Home | History | Annotate | Download | only in testinfrastructure
      1 /*
      2      * Copyright (C) 2014 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/LICENSE2.0
      9      *
     10      * Unless required by applicable law or agreed to in riting, 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 package android.uirendering.cts.testinfrastructure;
     17 
     18 import android.graphics.Canvas;
     19 import android.graphics.ColorFilter;
     20 import android.graphics.Paint;
     21 import android.graphics.PorterDuff;
     22 import android.graphics.PorterDuffColorFilter;
     23 import android.graphics.PorterDuffXfermode;
     24 import android.graphics.RectF;
     25 import android.graphics.Xfermode;
     26 
     27 import java.util.ArrayList;
     28 import java.util.LinkedHashMap;
     29 import java.util.Map;
     30 
     31 /**
     32  * Modifies the canvas and paint objects when called.
     33  */
     34 public abstract class DisplayModifier {
     35     private static final RectF gRect = new RectF(0, 0, 100, 100);
     36     private static final float[] gPts = new float[]{
     37             0, 100, 100, 0, 100, 200, 200, 100
     38     };
     39     private static final float[] gTriPts = new float[]{
     40             75, 0, 130, 130, 130, 130, 0, 130, 0, 130, 75, 0
     41     };
     42     private static final int NUM_PARALLEL_LINES = 24;
     43     private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
     44     protected static final int MODIFIER_WIDTH = 180;
     45     protected static final int MODIFIER_HEIGHT = 180;
     46 
     47     public static final PorterDuff.Mode[] PORTERDUFF_MODES = new PorterDuff.Mode[] {
     48         PorterDuff.Mode.SRC, PorterDuff.Mode.DST, PorterDuff.Mode.SRC_OVER,
     49         PorterDuff.Mode.DST_OVER, PorterDuff.Mode.SRC_IN, PorterDuff.Mode.DST_IN,
     50         PorterDuff.Mode.SRC_OUT, PorterDuff.Mode.DST_OUT, PorterDuff.Mode.SRC_ATOP,
     51         PorterDuff.Mode.DST_ATOP, PorterDuff.Mode.XOR, PorterDuff.Mode.MULTIPLY,
     52         PorterDuff.Mode.SCREEN
     53     };
     54 
     55     static {
     56         int index;
     57         for (index = 0; index < gTriPts.length; index++) {
     58             gLinePts[index] = gTriPts[index];
     59         }
     60         float val = 0;
     61         for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
     62             gLinePts[index + 0] = 150;
     63             gLinePts[index + 1] = val;
     64             gLinePts[index + 2] = 300;
     65             gLinePts[index + 3] = val;
     66             index += 4;
     67             val += 8 + (2.0f / NUM_PARALLEL_LINES);
     68         }
     69         val = 0;
     70         for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
     71             gLinePts[index + 0] = val;
     72             gLinePts[index + 1] = 150;
     73             gLinePts[index + 2] = val;
     74             gLinePts[index + 3] = 300;
     75             index += 4;
     76             val += 8 + (2.0f / NUM_PARALLEL_LINES);
     77         }
     78     }
     79 
     80     // This linked hash map contains each of the different things that can be done to a canvas and
     81     // paint object, like anti-aliasing or drawing. Within those LinkedHashMaps are the various
     82     // options for that specific topic, which contains a displaymodifier which will affect the
     83     // given canvas and paint objects.
     84     public static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> sMaps =
     85             new LinkedHashMap<String, LinkedHashMap<String,DisplayModifier>>() {
     86                 {
     87                     put("aa", new LinkedHashMap<String, DisplayModifier>() {
     88                         {
     89                             put("true", new DisplayModifier() {
     90                                 @Override
     91                                 public void modifyDrawing(Paint paint, Canvas canvas) {
     92                                     paint.setAntiAlias(true);
     93                                 }
     94                             });
     95                             put("false", new DisplayModifier() {
     96                                 @Override
     97                                 public void modifyDrawing(Paint paint, Canvas canvas) {
     98                                     paint.setAntiAlias(false);
     99                                 }
    100                             });
    101                         }
    102                     });
    103                     put("style", new LinkedHashMap<String, DisplayModifier>() {
    104                         {
    105                             put("fill", new DisplayModifier() {
    106                                 @Override
    107                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    108                                     paint.setStyle(Paint.Style.FILL);
    109                                 }
    110                             });
    111                             put("stroke", new DisplayModifier() {
    112                                 @Override
    113                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    114                                     paint.setStyle(Paint.Style.STROKE);
    115                                 }
    116                             });
    117                             put("fillAndStroke", new DisplayModifier() {
    118                                 @Override
    119                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    120                                     paint.setStyle(Paint.Style.FILL_AND_STROKE);
    121                                 }
    122                             });
    123                         }
    124                     });
    125                     put("strokeWidth", new LinkedHashMap<String, DisplayModifier>() {
    126                         {
    127                             put("hair", new DisplayModifier() {
    128                                 @Override
    129                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    130                                     paint.setStrokeWidth(0);
    131                                 }
    132                             });
    133                             put("0.3", new DisplayModifier() {
    134                                 @Override
    135                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    136                                     paint.setStrokeWidth(0.3f);
    137                                 }
    138                             });
    139                             put("1", new DisplayModifier() {
    140                                 @Override
    141                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    142                                     paint.setStrokeWidth(1);
    143                                 }
    144                             });
    145                             put("5", new DisplayModifier() {
    146                                 @Override
    147                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    148                                     paint.setStrokeWidth(5);
    149                                 }
    150                             });
    151                             put("30", new DisplayModifier() {
    152                                 @Override
    153                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    154                                     paint.setStrokeWidth(30);
    155                                 }
    156                             });
    157                         }
    158                     });
    159                     put("strokeCap", new LinkedHashMap<String, DisplayModifier>() {
    160                         {
    161                             put("butt", new DisplayModifier() {
    162                                 @Override
    163                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    164                                     paint.setStrokeCap(Paint.Cap.BUTT);
    165                                 }
    166                             });
    167                             put("round", new DisplayModifier() {
    168                                 @Override
    169                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    170                                     paint.setStrokeCap(Paint.Cap.ROUND);
    171                                 }
    172                             });
    173                             put("square", new DisplayModifier() {
    174                                 @Override
    175                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    176                                     paint.setStrokeCap(Paint.Cap.SQUARE);
    177                                 }
    178                             });
    179                         }
    180                     });
    181                     put("strokeJoin", new LinkedHashMap<String, DisplayModifier>() {
    182                         {
    183                             put("bevel", new DisplayModifier() {
    184                                 @Override
    185                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    186                                     paint.setStrokeJoin(Paint.Join.BEVEL);
    187                                 }
    188                             });
    189                             put("round", new DisplayModifier() {
    190                                 @Override
    191                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    192                                     paint.setStrokeJoin(Paint.Join.ROUND);
    193                                 }
    194                             });
    195                             put("miter", new DisplayModifier() {
    196                                 @Override
    197                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    198                                     paint.setStrokeJoin(Paint.Join.MITER);
    199                                 }
    200                             });
    201                             // TODO: add miter0, miter1 etc to test miter distances
    202                         }
    203                     });
    204 
    205                     put("transform", new LinkedHashMap<String, DisplayModifier>() {
    206                         {
    207                             put("noTransform", new DisplayModifier() {
    208                                 @Override
    209                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    210                                 }
    211                             });
    212                             put("rotate5", new DisplayModifier() {
    213                                 @Override
    214                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    215                                     canvas.rotate(5);
    216                                 }
    217                             });
    218                             put("rotate45", new DisplayModifier() {
    219                                 @Override
    220                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    221                                     canvas.rotate(45);
    222                                 }
    223                             });
    224                             put("rotate90", new DisplayModifier() {
    225                                 @Override
    226                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    227                                     canvas.rotate(90);
    228                                     canvas.translate(0, -200);
    229                                 }
    230                             });
    231                             put("scale2x2", new DisplayModifier() {
    232                                 @Override
    233                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    234                                     canvas.scale(2, 2);
    235                                 }
    236                             });
    237                             put("rot20scl1x4", new DisplayModifier() {
    238                                 @Override
    239                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    240                                     canvas.rotate(20);
    241                                     canvas.scale(1, 4);
    242                                 }
    243                             });
    244                         }
    245                     });
    246 
    247                     put("shader", new LinkedHashMap<String, DisplayModifier>() {
    248                         {
    249                             put("noShader", new DisplayModifier() {
    250                                 @Override
    251                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    252                                 }
    253                             });
    254                             put("repeatShader", new DisplayModifier() {
    255                                 @Override
    256                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    257                                     paint.setShader(ResourceModifier.instance().repeatShader);
    258                                 }
    259                             });
    260                             put("translatedShader", new DisplayModifier() {
    261                                 @Override
    262                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    263                                     paint.setShader(ResourceModifier.instance().translatedShader);
    264                                 }
    265                             });
    266                             put("scaledShader", new DisplayModifier() {
    267                                 @Override
    268                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    269                                     paint.setShader(ResourceModifier.instance().scaledShader);
    270                                 }
    271                             });
    272                             put("composeShader", new DisplayModifier() {
    273                                 @Override
    274                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    275                                     paint.setShader(ResourceModifier.instance().composeShader);
    276                                 }
    277                             });
    278                             /*
    279                             put("bad composeShader", new DisplayModifier() {
    280                                 @Override
    281                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    282                                     paint.setShader(ResourceModifier.instance().nestedComposeShader);
    283                                 }
    284                             });
    285                             put("bad composeShader 2", new DisplayModifier() {
    286                                 @Override
    287                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    288                                     paint.setShader(
    289                                             ResourceModifier.instance().doubleGradientComposeShader);
    290                                 }
    291                             });
    292                             */
    293                             put("horGradient", new DisplayModifier() {
    294                                 @Override
    295                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    296                                     paint.setShader(ResourceModifier.instance().horGradient);
    297                                 }
    298                             });
    299                             put("diagGradient", new DisplayModifier() {
    300                                 @Override
    301                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    302                                     paint.setShader(ResourceModifier.instance().diagGradient);
    303                                 }
    304                             });
    305                             put("vertGradient", new DisplayModifier() {
    306                                 @Override
    307                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    308                                     paint.setShader(ResourceModifier.instance().vertGradient);
    309                                 }
    310                             });
    311                             put("radGradient", new DisplayModifier() {
    312                                 @Override
    313                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    314                                     paint.setShader(ResourceModifier.instance().radGradient);
    315                                 }
    316                             });
    317                             put("sweepGradient", new DisplayModifier() {
    318                                 @Override
    319                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    320                                     paint.setShader(ResourceModifier.instance().sweepGradient);
    321                                 }
    322                             });
    323                         }
    324                     });
    325 
    326                     put("xfermodes", new LinkedHashMap<String, DisplayModifier>() {
    327                         {
    328                             for (int i = 0 ; i < PORTERDUFF_MODES.length ; i++) {
    329                                 put(PORTERDUFF_MODES[i].toString(),
    330                                         new XfermodeModifier(PORTERDUFF_MODES[i]));
    331                             }
    332                         }
    333                     });
    334 
    335                     put("colorfilters", new LinkedHashMap<String, DisplayModifier>() {
    336                         {
    337                             for (int i = 0 ; i < PORTERDUFF_MODES.length ; i++) {
    338                                 put(PORTERDUFF_MODES[i].toString(),
    339                                         new ColorFilterModifier(PORTERDUFF_MODES[i]));
    340                             }
    341                         }
    342                     });
    343 
    344                     // FINAL MAP: DOES ACTUAL DRAWING
    345                     put("drawing", new LinkedHashMap<String, DisplayModifier>() {
    346                         {
    347                             put("roundRect", new DisplayModifier() {
    348                                 @Override
    349                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    350                                     canvas.drawRoundRect(gRect, 20, 20, paint);
    351                                 }
    352                             });
    353                             put("rect", new DisplayModifier() {
    354                                 @Override
    355                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    356                                     canvas.drawRect(gRect, paint);
    357                                 }
    358                             });
    359                             put("circle", new DisplayModifier() {
    360                                 @Override
    361                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    362                                     canvas.drawCircle(100, 100, 75, paint);
    363                                 }
    364                             });
    365                             put("oval", new DisplayModifier() {
    366                                 @Override
    367                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    368                                     canvas.drawOval(gRect, paint);
    369                                 }
    370                             });
    371                             put("lines", new DisplayModifier() {
    372                                 @Override
    373                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    374                                     canvas.drawLines(gLinePts, paint);
    375                                 }
    376                             });
    377                             /* drawPoints does not work with zero stroke width,
    378                              * but it isn't a regression
    379                              * TODO: fix hardware canvas so that drawPoints works
    380                             put("plusPoints", new DisplayModifier() {
    381                                 @Override
    382                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    383                                     canvas.drawPoints(gPts, paint);
    384                                 }
    385                             });
    386                              */
    387                             put("text", new DisplayModifier() {
    388                                 @Override
    389                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    390                                     paint.setTextSize(36);
    391                                     canvas.drawText("TEXTTEST", 0, 50, paint);
    392                                 }
    393                             });
    394                             put("shadowtext", new DisplayModifier() {
    395                                 @Override
    396                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    397                                     paint.setTextSize(36);
    398                                     paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
    399                                     canvas.drawText("TEXTTEST", 0, 50, paint);
    400                                 }
    401                             });
    402                             put("bitmapMesh", new DisplayModifier() {
    403                                 @Override
    404                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    405                                     canvas.drawBitmapMesh(ResourceModifier.instance().bitmap, 3, 3,
    406                                             ResourceModifier.instance().bitmapVertices, 0, null, 0,
    407                                             null);
    408                                 }
    409                             });
    410                             put("arc", new DisplayModifier() {
    411                                 @Override
    412                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    413                                     canvas.drawArc(gRect, 260, 285, false, paint);
    414                                 }
    415                             });
    416                             put("arcFromCenter", new DisplayModifier() {
    417                                 @Override
    418                                 public void modifyDrawing(Paint paint, Canvas canvas) {
    419                                     canvas.drawArc(gRect, 260, 285, true, paint);
    420                                 }
    421                             });
    422                         }
    423                     });
    424                     // WARNING: DON'T PUT MORE MAPS BELOW THIS
    425                 }
    426             };
    427 
    428     abstract public void modifyDrawing(Paint paint, Canvas canvas);
    429 
    430     public static class Accessor {
    431         public final static int AA_MASK =               0x1 << 0;
    432         public final static int STYLE_MASK =            0x1 << 1;
    433         public final static int STROKE_WIDTH_MASK =     0x1 << 2;
    434         public final static int STROKE_CAP_MASK =       0x1 << 3;
    435         public final static int STROKE_JOIN_MASK =      0x1 << 4;
    436         public final static int TRANSFORM_MASK =        0x1 << 5;
    437         public final static int SHADER_MASK =           0x1 << 6;
    438         public final static int XFERMODE_MASK =         0x1 << 7;
    439         public final static int COLOR_FILTER_MASK =     0x1 << 8;
    440         public final static int SHAPES_MASK =           0x1 << 9;
    441         public final static int ALL_OPTIONS_MASK =      (0x1 << 10) - 1;
    442         public final static int SHAPES_INDEX = 9;
    443         public final static int XFERMODE_INDEX = 7;
    444         private final int mMask;
    445 
    446         private String mDebugString;
    447         private int[] mIndices;
    448         private LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> mDisplayMap;
    449 
    450         public Accessor(int mask) {
    451             int totalModifiers = Integer.bitCount(mask);
    452             mIndices = new int[totalModifiers];
    453             mMask = mask;
    454             // Create a Display Map of the valid indices
    455             mDisplayMap = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>();
    456             int index = 0;
    457             for (String key : DisplayModifier.sMaps.keySet()) {
    458                 if (validIndex(index)) {
    459                     mDisplayMap.put(key, DisplayModifier.sMaps.get(key));
    460                 }
    461                 index++;
    462             }
    463             mDebugString = "";
    464         }
    465 
    466         private LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
    467             int i = 0;
    468             for (LinkedHashMap<String, DisplayModifier> map : mDisplayMap.values()) {
    469                 if (i == index) {
    470                     return map;
    471                 }
    472                 i++;
    473             }
    474             return null;
    475         }
    476 
    477         /**
    478          * This will create the next combination of drawing commands. If we have done every combination,
    479          * then we will return false.
    480          * @return true if there is more combinations to do
    481          */
    482         public boolean step() {
    483             int modifierMapIndex = mIndices.length - 1;
    484             // Start from the last map, and loop until it is at the front
    485             while (modifierMapIndex >= 0) {
    486                 LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
    487                 mIndices[modifierMapIndex]++;
    488 
    489                 // If we are still at a valid index, then we don't need to update any others
    490                 if (mIndices[modifierMapIndex] < map.size()) {
    491                     break;
    492                 }
    493 
    494                 // If we updated and it was outside the boundary, and it was the last index then
    495                 // we are done
    496                 if (modifierMapIndex == 0) {
    497                     return false;
    498                 }
    499                 // If we ran off the end of the map, we need to update one more down the list
    500                 mIndices[modifierMapIndex] = 0;
    501 
    502                 modifierMapIndex--;
    503             }
    504             return true;
    505         }
    506 
    507         /**
    508          * Modifies the canvas and paint given for the particular combination currently
    509          */
    510         public void modifyDrawing(Canvas canvas, Paint paint) {
    511             final ArrayList<DisplayModifier> modifierArrayList = getModifierList();
    512             for (DisplayModifier modifier : modifierArrayList) {
    513                 modifier.modifyDrawing(paint, canvas);
    514             }
    515         }
    516 
    517         /**
    518          * Gets a list of all the current modifications to be used.
    519          */
    520         private ArrayList<DisplayModifier> getModifierList() {
    521             ArrayList<DisplayModifier> modifierArrayList = new ArrayList<DisplayModifier>();
    522             int mapIndex = 0;
    523             mDebugString = "";
    524 
    525             // Through each possible category of modification
    526             for (Map.Entry<String, LinkedHashMap<String, DisplayModifier>> entry :
    527                     mDisplayMap.entrySet()) {
    528                 int displayModifierIndex = mIndices[mapIndex];
    529                 mDebugString += "Modification : " + entry.getKey();
    530                 // Loop until we find the modification we are going to use
    531                 for (Map.Entry<String, DisplayModifier> modifierEntry :
    532                         entry.getValue().entrySet()) {
    533                     // Once we find the modification we want, then we will add it to the list,
    534                     // and the last applied modifications
    535                     if (displayModifierIndex == 0) {
    536                         mDebugString += " value : " + modifierEntry.getKey() + " ";
    537                         modifierArrayList.add(modifierEntry.getValue());
    538                         break;
    539                     }
    540                     displayModifierIndex--;
    541                 }
    542                 mapIndex++;
    543             }
    544             return modifierArrayList;
    545         }
    546 
    547         public String getDebugString() {
    548             return mDebugString;
    549         }
    550 
    551         /**
    552          * Using the given masks, it tells if the map at the given index should be used, or not.
    553          */
    554         private boolean validIndex(int index) {
    555             return (mMask & (0x1 << index)) != 0;
    556         }
    557     }
    558 
    559     private static class XfermodeModifier extends DisplayModifier {
    560         private Xfermode mXfermode;
    561 
    562         public XfermodeModifier(PorterDuff.Mode mode) {
    563             mXfermode = new PorterDuffXfermode(mode);
    564         }
    565 
    566         @Override
    567         public void modifyDrawing(Paint paint, Canvas canvas) {
    568             paint.setXfermode(mXfermode);
    569         }
    570     }
    571 
    572     private static class ColorFilterModifier extends DisplayModifier {
    573         private static final int FILTER_COLOR = 0xFFBB0000;
    574         private ColorFilter mColorFilter;
    575 
    576         public ColorFilterModifier(PorterDuff.Mode mode) {
    577             mColorFilter = new PorterDuffColorFilter(FILTER_COLOR, mode);
    578         }
    579 
    580         @Override
    581         public void modifyDrawing(Paint paint, Canvas canvas) {
    582             paint.setColorFilter(mColorFilter);
    583         }
    584     }
    585 }
    586