Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.text.cts;
     18 
     19 import android.content.Context;
     20 import android.graphics.Bitmap;
     21 import android.graphics.Canvas;
     22 import android.graphics.Paint;
     23 import android.graphics.Picture;
     24 import android.test.ActivityInstrumentationTestCase2;
     25 import android.view.KeyEvent;
     26 import android.view.Menu;
     27 import android.view.View;
     28 import android.webkit.cts.WebViewOnUiThread;
     29 import android.widget.TextView;
     30 import android.widget.EditText;
     31 
     32 public class EmojiTest extends ActivityInstrumentationTestCase2<EmojiStubActivity> {
     33 
     34     public EmojiTest() {
     35         super("com.android.cts.stub", EmojiStubActivity.class);
     36     }
     37 
     38     protected void setUp() throws Exception {
     39         super.setUp();
     40     }
     41 
     42     protected void tearDown() throws Exception {
     43         super.tearDown();
     44     }
     45 
     46     /**
     47      * Tests all Emoji are defined in Character class
     48      */
     49     public void testEmojiCodePoints() {
     50         for (int i = 0; i < EmojiConstants.emojiCodePoints.length; i++) {
     51             assertTrue(Character.isDefined(EmojiConstants.emojiCodePoints[i]));
     52         }
     53     }
     54 
     55     /**
     56      * Tests Emoji has different glyph for different meaning characters.
     57      * Test on Canvas, TextView, EditText and WebView
     58      */
     59     public void testEmojiGlyph() {
     60         CaptureCanvas ccanvas = new CaptureCanvas(getInstrumentation().getContext());
     61         CaptureWebView cwebview = new CaptureWebView(getInstrumentation().getContext());
     62 
     63         Bitmap mBitmapA, mBitmapB;  // Emoji displayed Bitmaps to compare
     64 
     65         int comparedCodePoints[][] = {   // Emojis should have different characters
     66             {0x1F436, 0x1F435},      // Dog(U+1F436) and Monkey(U+1F435)
     67             {0x26BD, 0x26BE},        // Soccer ball(U+26BD) and Baseball(U+26BE)
     68             {0x1F47B, 0x1F381},      // Ghost(U+1F47B) and wrapped present(U+1F381)
     69             {0x2764, 0x1F494},       // Heavy black heart(U+2764) and broken heart(U+1F494)
     70             {0x1F603, 0x1F33B}       // Smiling face with open mouth(U+1F603) and sunflower(U+1F33B)
     71         };
     72 
     73         for (int i = 0; i < comparedCodePoints.length; i++) {
     74 
     75             mBitmapA = ccanvas.capture(Character.toChars(comparedCodePoints[i][0]));
     76             mBitmapB = ccanvas.capture(Character.toChars(comparedCodePoints[i][1]));
     77 
     78             assertFalse(mBitmapA.sameAs(mBitmapB));
     79 
     80             // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
     81             CaptureTextView cviewA = new CaptureTextView(getInstrumentation().getContext());
     82             mBitmapA = cviewA.capture(Character.toChars(comparedCodePoints[i][0]));
     83             CaptureTextView cviewB = new CaptureTextView(getInstrumentation().getContext());
     84             mBitmapB = cviewB.capture(Character.toChars(comparedCodePoints[i][1]));
     85 
     86             assertFalse(mBitmapA.sameAs(mBitmapB));
     87 
     88             CaptureEditText cedittextA = new CaptureEditText(getInstrumentation().getContext());
     89             mBitmapA = cedittextA.capture(Character.toChars(comparedCodePoints[i][0]));
     90             CaptureEditText cedittextB = new CaptureEditText(getInstrumentation().getContext());
     91             mBitmapB = cedittextB.capture(Character.toChars(comparedCodePoints[i][1]));
     92 
     93             assertFalse(mBitmapA.sameAs(mBitmapB));
     94 
     95             mBitmapA = cwebview.capture(Character.toChars(comparedCodePoints[i][0]));
     96             mBitmapB = cwebview.capture(Character.toChars(comparedCodePoints[i][1]));
     97 
     98             assertFalse(mBitmapA.sameAs(mBitmapB));
     99 
    100         }
    101     }
    102 
    103     /**
    104      * Tests EditText handles Emoji
    105      */
    106     public void testEmojiEditable() {
    107         int testedCodePoints[] = {
    108             0xAE,    // registered mark
    109             0x2764,    // heavy black heart
    110             0x1F353    // strawberry - surrogate pair sample. Count as two characters.
    111         };
    112 
    113         String origStr, newStr;
    114 
    115         // delete Emoji by sending KEYCODE_DEL
    116         for (int i = 0; i < testedCodePoints.length; i++) {
    117             origStr = "Test character  ";
    118             // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
    119             EditText editText = new EditText(getInstrumentation().getContext());
    120             editText.setText(origStr + String.valueOf(Character.toChars(testedCodePoints[i])));
    121 
    122             // confirm the emoji is added.
    123             newStr = editText.getText().toString();
    124             assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
    125 
    126             // Delete added character by sending KEYCODE_DEL event
    127             editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
    128 
    129             newStr = editText.getText().toString();
    130             assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
    131         }
    132     }
    133 
    134     private class CaptureCanvas extends View {
    135 
    136         String mTestStr;
    137         Paint paint = new Paint();
    138 
    139         CaptureCanvas(Context context) {
    140             super(context);
    141         }
    142 
    143         public void onDraw(Canvas canvas) {
    144             if (mTestStr != null) {
    145                 canvas.drawText(mTestStr, 50, 50, paint);
    146             }
    147             return;
    148         }
    149 
    150         Bitmap capture(char c[]) {
    151             mTestStr = String.valueOf(c);
    152             invalidate();
    153 
    154             setDrawingCacheEnabled(true);
    155             measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
    156                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    157             layout(0, 0, 200,200);
    158 
    159             Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
    160             setDrawingCacheEnabled(false);
    161             return bitmap;
    162         }
    163 
    164     }
    165 
    166     private class CaptureTextView extends TextView {
    167 
    168         CaptureTextView(Context context) {
    169             super(context);
    170         }
    171 
    172         Bitmap capture(char c[]) {
    173             setText(String.valueOf(c));
    174 
    175             invalidate();
    176 
    177             setDrawingCacheEnabled(true);
    178             measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
    179                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    180             layout(0, 0, 200,200);
    181 
    182             Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
    183             setDrawingCacheEnabled(false);
    184             return bitmap;
    185         }
    186 
    187     }
    188 
    189     private class CaptureEditText extends EditText {
    190 
    191         CaptureEditText(Context context) {
    192             super(context);
    193         }
    194 
    195         Bitmap capture(char c[]) {
    196             setText(String.valueOf(c));
    197 
    198             invalidate();
    199 
    200             setDrawingCacheEnabled(true);
    201             measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
    202                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    203             layout(0, 0, 200,200);
    204 
    205             Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
    206             setDrawingCacheEnabled(false);
    207             return bitmap;
    208         }
    209 
    210     }
    211 
    212 
    213     private class CaptureWebView {
    214 
    215         WebViewOnUiThread webViewOnUiThread;
    216         Bitmap bitmap;
    217         CaptureWebView(Context context) {
    218             webViewOnUiThread = new WebViewOnUiThread(EmojiTest.this, getActivity().getWebView());
    219         }
    220 
    221         Bitmap capture(char c[]) {
    222 
    223             webViewOnUiThread.loadDataAndWaitForCompletion("<html><body>" + String.valueOf(c) + "</body></html>",
    224                     "text/html; charset=utf-8", "utf-8");
    225             // The Chromium-powered WebView renders asynchronously and there's nothing reliable
    226             // we can easily wait for to be sure that capturePicture will return a fresh frame.
    227             // So, just sleep for a sufficient time.
    228             try {
    229                 Thread.sleep(250);
    230             } catch (InterruptedException e) {
    231                 return null;
    232             }
    233 
    234             Picture picture = webViewOnUiThread.capturePicture();
    235             if (picture == null || picture.getHeight() <= 0 || picture.getWidth() <= 0) {
    236                 return null;
    237             } else {
    238                 bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),
    239                         Bitmap.Config.ARGB_8888);
    240                 Canvas canvas = new Canvas(bitmap);
    241                 picture.draw(canvas);
    242             }
    243 
    244             return bitmap;
    245         }
    246 
    247     }
    248 
    249 }
    250 
    251