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