Home | History | Annotate | Download | only in hwuicompare
      1 /*
      2  * Copyright (C) 2012 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 com.android.test.hwuicompare;
     18 
     19 import java.util.LinkedHashMap;
     20 import java.util.Map.Entry;
     21 
     22 import android.graphics.Canvas;
     23 import android.graphics.Paint;
     24 import android.graphics.RectF;
     25 import android.util.Log;
     26 
     27 public abstract class DisplayModifier {
     28 
     29     // automated tests ignore any combination of operations that don't together return TOTAL_MASK
     30     protected final static int TOTAL_MASK = 0x1F;
     31 
     32     // if we're filling, ensure we're not also sweeping over stroke parameters
     33     protected final static int SWEEP_STROKE_WIDTH_BIT = 0x1 << 0;
     34     protected final static int SWEEP_STROKE_CAP_BIT = 0x1 << 1;
     35     protected final static int SWEEP_STROKE_JOIN_BIT = 0x1 << 2;
     36 
     37     protected final static int SWEEP_SHADER_BIT = 0x1 << 3; // only allow non-simple shaders to use rectangle drawing
     38     protected final static int SWEEP_TRANSFORM_BIT = 0x1 << 4; // only sweep over specified transforms
     39 
     40     abstract public void modifyDrawing(Paint paint, Canvas canvas);
     41     protected int mask() { return 0x0; };
     42 
     43     private static final RectF gRect = new RectF(0, 0, 200, 175);
     44     private static final float[] gPts = new float[] {
     45             0, 100, 100, 0, 100, 200, 200, 100
     46     };
     47 
     48     private static final int NUM_PARALLEL_LINES = 24;
     49     private static final float[] gTriPts = new float[] {
     50         75, 0, 130, 130, 130, 130, 0, 130, 0, 130, 75, 0
     51     };
     52     private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
     53     static {
     54         int index;
     55         for (index = 0; index < gTriPts.length; index++) {
     56             gLinePts[index] = gTriPts[index];
     57         }
     58         float val = 0;
     59         for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
     60             gLinePts[index + 0] = 150;
     61             gLinePts[index + 1] = val;
     62             gLinePts[index + 2] = 300;
     63             gLinePts[index + 3] = val;
     64             index += 4;
     65             val += 8 + (2.0f/NUM_PARALLEL_LINES);
     66         }
     67         val = 0;
     68         for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
     69             gLinePts[index + 0] = val;
     70             gLinePts[index + 1] = 150;
     71             gLinePts[index + 2] = val;
     72             gLinePts[index + 3] = 300;
     73             index += 4;
     74             val += 8 + (2.0f/NUM_PARALLEL_LINES);
     75         }
     76     };
     77 
     78     @SuppressWarnings("serial")
     79     private static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> gMaps = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>() {
     80         {
     81             put("aa", new LinkedHashMap<String, DisplayModifier>() {
     82                 {
     83                     put("true", new DisplayModifier() {
     84                         @Override
     85                         public void modifyDrawing(Paint paint, Canvas canvas) {
     86                             paint.setAntiAlias(true);
     87                         }
     88                     });
     89                     put("false", new DisplayModifier() {
     90                         @Override
     91                         public void modifyDrawing(Paint paint, Canvas canvas) {
     92                             paint.setAntiAlias(false);
     93                         }
     94                     });
     95                 }
     96             });
     97             put("style", new LinkedHashMap<String, DisplayModifier>() {
     98                 {
     99                     put("fill", new DisplayModifier() {
    100                         @Override
    101                         public void modifyDrawing(Paint paint, Canvas canvas) {
    102                             paint.setStyle(Paint.Style.FILL);
    103                         }
    104                     });
    105                     put("stroke", new DisplayModifier() {
    106                         @Override
    107                         public void modifyDrawing(Paint paint, Canvas canvas) {
    108                             paint.setStyle(Paint.Style.STROKE);
    109                         }
    110                         @Override
    111                         protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
    112                     });
    113                     put("fillAndStroke", new DisplayModifier() {
    114                         @Override
    115                         public void modifyDrawing(Paint paint, Canvas canvas) {
    116                             paint.setStyle(Paint.Style.FILL_AND_STROKE);
    117                         }
    118 
    119                         @Override
    120                         protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
    121                     });
    122                 }
    123             });
    124             put("strokeWidth", new LinkedHashMap<String, DisplayModifier>() {
    125                 {
    126                     put("hair", new DisplayModifier() {
    127                         @Override
    128                         public void modifyDrawing(Paint paint, Canvas canvas) {
    129                             paint.setStrokeWidth(0);
    130                         }
    131                         @Override
    132                         protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
    133                     });
    134                     put("0.3", new DisplayModifier() {
    135                         @Override
    136                         public void modifyDrawing(Paint paint, Canvas canvas) {
    137                             paint.setStrokeWidth(0.3f);
    138                         }
    139                     });
    140                     put("1", new DisplayModifier() {
    141                         @Override
    142                         public void modifyDrawing(Paint paint, Canvas canvas) {
    143                             paint.setStrokeWidth(1);
    144                         }
    145                     });
    146                     put("5", new DisplayModifier() {
    147                         @Override
    148                         public void modifyDrawing(Paint paint, Canvas canvas) {
    149                             paint.setStrokeWidth(5);
    150                         }
    151                     });
    152                     put("30", new DisplayModifier() {
    153                         @Override
    154                         public void modifyDrawing(Paint paint, Canvas canvas) {
    155                             paint.setStrokeWidth(30);
    156                         }
    157                     });
    158                 }
    159             });
    160             put("strokeCap", new LinkedHashMap<String, DisplayModifier>() {
    161                 {
    162                     put("butt", new DisplayModifier() {
    163                         @Override
    164                         public void modifyDrawing(Paint paint, Canvas canvas) {
    165                             paint.setStrokeCap(Paint.Cap.BUTT);
    166                         }
    167                         @Override
    168                         protected int mask() { return SWEEP_STROKE_CAP_BIT; }
    169                     });
    170                     put("round", new DisplayModifier() {
    171                         @Override
    172                         public void modifyDrawing(Paint paint, Canvas canvas) {
    173                             paint.setStrokeCap(Paint.Cap.ROUND);
    174                         }
    175                     });
    176                     put("square", new DisplayModifier() {
    177                         @Override
    178                         public void modifyDrawing(Paint paint, Canvas canvas) {
    179                             paint.setStrokeCap(Paint.Cap.SQUARE);
    180                         }
    181                     });
    182                 }
    183             });
    184             put("strokeJoin", new LinkedHashMap<String, DisplayModifier>() {
    185                 {
    186                     put("bevel", new DisplayModifier() {
    187                         @Override
    188                         public void modifyDrawing(Paint paint, Canvas canvas) {
    189                             paint.setStrokeJoin(Paint.Join.BEVEL);
    190                         }
    191                         @Override
    192                         protected int mask() { return SWEEP_STROKE_JOIN_BIT; }
    193                     });
    194                     put("round", new DisplayModifier() {
    195                         @Override
    196                         public void modifyDrawing(Paint paint, Canvas canvas) {
    197                             paint.setStrokeJoin(Paint.Join.ROUND);
    198                         }
    199                     });
    200                     put("miter", new DisplayModifier() {
    201                         @Override
    202                         public void modifyDrawing(Paint paint, Canvas canvas) {
    203                             paint.setStrokeJoin(Paint.Join.MITER);
    204                         }
    205                     });
    206                     // TODO: add miter0, miter1 etc to test miter distances
    207                 }
    208             });
    209 
    210             put("transform", new LinkedHashMap<String, DisplayModifier>() {
    211                 {
    212                     put("noTransform", new DisplayModifier() {
    213                         @Override
    214                         public void modifyDrawing(Paint paint, Canvas canvas) {}
    215                         @Override
    216                         protected int mask() { return SWEEP_TRANSFORM_BIT; };
    217                     });
    218                     put("rotate5", new DisplayModifier() {
    219                         @Override
    220                         public void modifyDrawing(Paint paint, Canvas canvas) {
    221                             canvas.rotate(5);
    222                         }
    223                     });
    224                     put("rotate45", new DisplayModifier() {
    225                         @Override
    226                         public void modifyDrawing(Paint paint, Canvas canvas) {
    227                             canvas.rotate(45);
    228                         }
    229                     });
    230                     put("rotate90", new DisplayModifier() {
    231                         @Override
    232                         public void modifyDrawing(Paint paint, Canvas canvas) {
    233                             canvas.rotate(90);
    234                             canvas.translate(0, -200);
    235                         }
    236                     });
    237                     put("scale2x2", new DisplayModifier() {
    238                         @Override
    239                         public void modifyDrawing(Paint paint, Canvas canvas) {
    240                             canvas.scale(2, 2);
    241                         }
    242                         @Override
    243                         protected int mask() { return SWEEP_TRANSFORM_BIT; };
    244                     });
    245                     put("rot20scl1x4", new DisplayModifier() {
    246                         @Override
    247                         public void modifyDrawing(Paint paint, Canvas canvas) {
    248                             canvas.rotate(20);
    249                             canvas.scale(1, 4);
    250                         }
    251                         @Override
    252                         protected int mask() { return SWEEP_TRANSFORM_BIT; };
    253                     });
    254                 }
    255             });
    256 
    257             put("shader", new LinkedHashMap<String, DisplayModifier>() {
    258                 {
    259                     put("noShader", new DisplayModifier() {
    260                         @Override
    261                         public void modifyDrawing(Paint paint, Canvas canvas) {}
    262                         @Override
    263                         protected int mask() { return SWEEP_SHADER_BIT; };
    264                     });
    265                     put("repeatShader", new DisplayModifier() {
    266                         @Override
    267                         public void modifyDrawing(Paint paint, Canvas canvas) {
    268                             paint.setShader(ResourceModifiers.instance().mRepeatShader);
    269                         }
    270                         @Override
    271                         protected int mask() { return SWEEP_SHADER_BIT; };
    272                     });
    273                     put("translatedShader", new DisplayModifier() {
    274                         @Override
    275                         public void modifyDrawing(Paint paint, Canvas canvas) {
    276                             paint.setShader(ResourceModifiers.instance().mTranslatedShader);
    277                         }
    278                     });
    279                     put("scaledShader", new DisplayModifier() {
    280                         @Override
    281                         public void modifyDrawing(Paint paint, Canvas canvas) {
    282                             paint.setShader(ResourceModifiers.instance().mScaledShader);
    283                         }
    284                     });
    285                     put("horGradient", new DisplayModifier() {
    286                         @Override
    287                         public void modifyDrawing(Paint paint, Canvas canvas) {
    288                             paint.setShader(ResourceModifiers.instance().mHorGradient);
    289                         }
    290                     });
    291                     put("diagGradient", new DisplayModifier() {
    292                         @Override
    293                         public void modifyDrawing(Paint paint, Canvas canvas) {
    294                             paint.setShader(ResourceModifiers.instance().mDiagGradient);
    295                         }
    296                         @Override
    297                         protected int mask() { return SWEEP_SHADER_BIT; };
    298                     });
    299                     put("vertGradient", new DisplayModifier() {
    300                         @Override
    301                         public void modifyDrawing(Paint paint, Canvas canvas) {
    302                             paint.setShader(ResourceModifiers.instance().mVertGradient);
    303                         }
    304                     });
    305                     put("radGradient", new DisplayModifier() {
    306                         @Override
    307                         public void modifyDrawing(Paint paint, Canvas canvas) {
    308                             paint.setShader(ResourceModifiers.instance().mRadGradient);
    309                         }
    310                     });
    311                     put("sweepGradient", new DisplayModifier() {
    312                         @Override
    313                         public void modifyDrawing(Paint paint, Canvas canvas) {
    314                             paint.setShader(ResourceModifiers.instance().mSweepGradient);
    315                         }
    316                     });
    317                     put("composeShader", new DisplayModifier() {
    318                         @Override
    319                         public void modifyDrawing(Paint paint, Canvas canvas) {
    320                             paint.setShader(ResourceModifiers.instance().mComposeShader);
    321                         }
    322                     });
    323                     put("bad composeShader", new DisplayModifier() {
    324                         @Override
    325                         public void modifyDrawing(Paint paint, Canvas canvas) {
    326                             paint.setShader(ResourceModifiers.instance().mBadComposeShader);
    327                         }
    328                     });
    329                     put("bad composeShader 2", new DisplayModifier() {
    330                         @Override
    331                         public void modifyDrawing(Paint paint, Canvas canvas) {
    332                             paint.setShader(ResourceModifiers.instance().mAnotherBadComposeShader);
    333                         }
    334                     });
    335                 }
    336             });
    337 
    338             // FINAL MAP: DOES ACTUAL DRAWING
    339             put("drawing", new LinkedHashMap<String, DisplayModifier>() {
    340                 {
    341                     put("roundRect", new DisplayModifier() {
    342                         @Override
    343                         public void modifyDrawing(Paint paint, Canvas canvas) {
    344                             canvas.drawRoundRect(gRect, 20, 20, paint);
    345                         }
    346                     });
    347                     put("rect", new DisplayModifier() {
    348                         @Override
    349                         public void modifyDrawing(Paint paint, Canvas canvas) {
    350                             canvas.drawRect(gRect, paint);
    351                         }
    352                         @Override
    353                         protected int mask() { return SWEEP_SHADER_BIT | SWEEP_STROKE_CAP_BIT; };
    354                     });
    355                     put("circle", new DisplayModifier() {
    356                         @Override
    357                         public void modifyDrawing(Paint paint, Canvas canvas) {
    358                             canvas.drawCircle(100, 100, 75, paint);
    359                         }
    360                     });
    361                     put("oval", new DisplayModifier() {
    362                         @Override
    363                         public void modifyDrawing(Paint paint, Canvas canvas) {
    364                             canvas.drawOval(gRect, paint);
    365                         }
    366                     });
    367                     put("lines", new DisplayModifier() {
    368                         @Override
    369                         public void modifyDrawing(Paint paint, Canvas canvas) {
    370                             canvas.drawLines(gLinePts, paint);
    371                         }
    372                         @Override
    373                         protected int mask() { return SWEEP_STROKE_CAP_BIT; };
    374                     });
    375                     put("plusPoints", new DisplayModifier() {
    376                         @Override
    377                         public void modifyDrawing(Paint paint, Canvas canvas) {
    378                             canvas.drawPoints(gPts, paint);
    379                         }
    380                     });
    381                     put("text", new DisplayModifier() {
    382                         @Override
    383                         public void modifyDrawing(Paint paint, Canvas canvas) {
    384                             paint.setTextSize(36);
    385                             canvas.drawText("TEXTTEST", 0, 50, paint);
    386                         }
    387                     });
    388                     put("shadowtext", new DisplayModifier() {
    389                         @Override
    390                         public void modifyDrawing(Paint paint, Canvas canvas) {
    391                             paint.setTextSize(36);
    392                             paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
    393                             canvas.drawText("TEXTTEST", 0, 50, paint);
    394                         }
    395                     });
    396                     put("bitmapMesh", new DisplayModifier() {
    397                         @Override
    398                         public void modifyDrawing(Paint paint, Canvas canvas) {
    399                             canvas.drawBitmapMesh(ResourceModifiers.instance().mBitmap, 3, 3,
    400                                     ResourceModifiers.instance().mBitmapVertices, 0, null, 0, null);
    401                         }
    402                     });
    403                     put("arc", new DisplayModifier() {
    404                         @Override
    405                         public void modifyDrawing(Paint paint, Canvas canvas) {
    406                             canvas.drawArc(gRect, 260, 285, false, paint);
    407                         }
    408                         @Override
    409                         protected int mask() { return SWEEP_STROKE_CAP_BIT; };
    410                     });
    411                     put("arcFromCenter", new DisplayModifier() {
    412                         @Override
    413                         public void modifyDrawing(Paint paint, Canvas canvas) {
    414                             canvas.drawArc(gRect, 260, 285, true, paint);
    415                         }
    416                         @Override
    417                         protected int mask() { return SWEEP_STROKE_JOIN_BIT; };
    418                     });
    419                 }
    420             });
    421             // WARNING: DON'T PUT MORE MAPS BELOW THIS
    422         }
    423     };
    424 
    425     private static LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
    426         for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
    427             if (index == 0) {
    428                 return map;
    429             }
    430             index--;
    431         }
    432         return null;
    433     }
    434 
    435     // indices instead of iterators for easier bidirectional traversal
    436     private static final int mIndices[] = new int[gMaps.size()];
    437     private static final String[] mLastAppliedModifications = new String[gMaps.size()];
    438 
    439     private static boolean stepInternal(boolean forward) {
    440         int modifierMapIndex = gMaps.size() - 1;
    441         while (modifierMapIndex >= 0) {
    442             LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
    443             mIndices[modifierMapIndex] += (forward ? 1 : -1);
    444 
    445             if (mIndices[modifierMapIndex] >= 0 && mIndices[modifierMapIndex] < map.size()) {
    446                 break;
    447             }
    448 
    449             mIndices[modifierMapIndex] = (forward ? 0 : map.size() - 1);
    450             modifierMapIndex--;
    451         }
    452         return modifierMapIndex < 0; // true if resetting
    453     }
    454 
    455     public static boolean step() {
    456         boolean ret = false;
    457         do {
    458             ret |= stepInternal(true);
    459         } while (!checkModificationStateMask());
    460         return ret;
    461     }
    462 
    463     public static boolean stepBack() {
    464         boolean ret = false;
    465         do {
    466             ret |= stepInternal(false);
    467         } while (!checkModificationStateMask());
    468         return ret;
    469     }
    470 
    471     private static boolean checkModificationStateMask() {
    472         int operatorMask = 0x0;
    473         int mapIndex = 0;
    474         for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
    475             int displayModifierIndex = mIndices[mapIndex];
    476             for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
    477                 if (displayModifierIndex == 0) {
    478                     mLastAppliedModifications[mapIndex] = modifierEntry.getKey();
    479                     operatorMask |= modifierEntry.getValue().mask();
    480                     break;
    481                 }
    482                 displayModifierIndex--;
    483             }
    484             mapIndex++;
    485         }
    486         return operatorMask == TOTAL_MASK;
    487     }
    488 
    489     public static void apply(Paint paint, Canvas canvas) {
    490         int mapIndex = 0;
    491         for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
    492             int displayModifierIndex = mIndices[mapIndex];
    493             for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
    494                 if (displayModifierIndex == 0) {
    495                     mLastAppliedModifications[mapIndex] = modifierEntry.getKey();
    496                     modifierEntry.getValue().modifyDrawing(paint, canvas);
    497                     break;
    498                 }
    499                 displayModifierIndex--;
    500             }
    501             mapIndex++;
    502         }
    503     }
    504 
    505     public static String[] getLastAppliedModifications() {
    506         return mLastAppliedModifications.clone();
    507     }
    508 
    509     public static String[][] getStrings() {
    510         String[][] keys = new String[gMaps.size()][];
    511 
    512         int i = 0;
    513         for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
    514             keys[i] = new String[map.size()];
    515             int j = 0;
    516             for (String key : map.keySet()) {
    517                 keys[i][j++] = key;
    518             }
    519             i++;
    520         }
    521 
    522         return keys;
    523     }
    524 
    525     public static void setIndex(int mapIndex, int newIndexValue) {
    526         mIndices[mapIndex] = newIndexValue;
    527     }
    528 
    529     public static int[] getIndices() {
    530         return mIndices;
    531     }
    532 }
    533