blob: 9939c0826b82571370cfab60837dca0cc1b9ec1e [file] [log] [blame]
Chris Craikc3683b52012-10-01 18:22:38 -07001/*
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
17package com.android.test.hwuicompare;
18
19import java.util.LinkedHashMap;
20import java.util.Map.Entry;
21
22import android.graphics.Canvas;
23import android.graphics.Paint;
24import android.graphics.RectF;
25import android.util.Log;
26
27public 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);
Chris Craikc3683b52012-10-01 18:22:38 -070044 private static final float[] gPts = new float[] {
45 0, 100, 100, 0, 100, 200, 200, 100
46 };
47
Chris Craik62a42c12013-02-15 11:58:14 -080048 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
Chris Craikc3683b52012-10-01 18:22:38 -070078 @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 });
Chris Craik65cd6122012-12-10 17:56:27 -0800152 put("30", new DisplayModifier() {
153 @Override
154 public void modifyDrawing(Paint paint, Canvas canvas) {
155 paint.setStrokeWidth(30);
156 }
157 });
Chris Craikc3683b52012-10-01 18:22:38 -0700158 }
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(5);
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 }
306 });
307
308 // FINAL MAP: DOES ACTUAL DRAWING
309 put("drawing", new LinkedHashMap<String, DisplayModifier>() {
310 {
311 put("roundRect", new DisplayModifier() {
312 @Override
313 public void modifyDrawing(Paint paint, Canvas canvas) {
314 canvas.drawRoundRect(gRect, 20, 20, paint);
315 }
316 });
317 put("rect", new DisplayModifier() {
318 @Override
319 public void modifyDrawing(Paint paint, Canvas canvas) {
320 canvas.drawRect(gRect, paint);
321 }
322 @Override
323 protected int mask() { return SWEEP_SHADER_BIT | SWEEP_STROKE_CAP_BIT; };
324 });
325 put("circle", new DisplayModifier() {
326 @Override
327 public void modifyDrawing(Paint paint, Canvas canvas) {
328 canvas.drawCircle(100, 100, 75, paint);
329 }
330 });
331 put("oval", new DisplayModifier() {
332 @Override
333 public void modifyDrawing(Paint paint, Canvas canvas) {
334 canvas.drawOval(gRect, paint);
335 }
336 });
Chris Craik62a42c12013-02-15 11:58:14 -0800337 put("lines", new DisplayModifier() {
Chris Craikc3683b52012-10-01 18:22:38 -0700338 @Override
339 public void modifyDrawing(Paint paint, Canvas canvas) {
340 canvas.drawLines(gLinePts, paint);
341 }
342 @Override
343 protected int mask() { return SWEEP_STROKE_CAP_BIT; };
344 });
345 put("plusPoints", new DisplayModifier() {
346 @Override
347 public void modifyDrawing(Paint paint, Canvas canvas) {
348 canvas.drawPoints(gPts, paint);
349 }
350 });
351 put("text", new DisplayModifier() {
352 @Override
353 public void modifyDrawing(Paint paint, Canvas canvas) {
354 paint.setTextSize(36);
355 canvas.drawText("TEXTTEST", 0, 50, paint);
356 }
357 });
358 put("shadowtext", new DisplayModifier() {
359 @Override
360 public void modifyDrawing(Paint paint, Canvas canvas) {
361 paint.setTextSize(36);
362 paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
363 canvas.drawText("TEXTTEST", 0, 50, paint);
364 }
365 });
366 put("bitmapMesh", new DisplayModifier() {
367 @Override
368 public void modifyDrawing(Paint paint, Canvas canvas) {
369 canvas.drawBitmapMesh(ResourceModifiers.instance().mBitmap, 3, 3,
370 ResourceModifiers.instance().mBitmapVertices, 0, null, 0, null);
371 }
372 });
373 put("arc", new DisplayModifier() {
374 @Override
375 public void modifyDrawing(Paint paint, Canvas canvas) {
376 canvas.drawArc(gRect, 260, 285, false, paint);
377 }
378 @Override
379 protected int mask() { return SWEEP_STROKE_CAP_BIT; };
380 });
381 put("arcFromCenter", new DisplayModifier() {
382 @Override
383 public void modifyDrawing(Paint paint, Canvas canvas) {
384 canvas.drawArc(gRect, 260, 285, true, paint);
385 }
386 @Override
387 protected int mask() { return SWEEP_STROKE_JOIN_BIT; };
388 });
389 }
390 });
391 // WARNING: DON'T PUT MORE MAPS BELOW THIS
392 }
393 };
394
395 private static LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
396 for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
397 if (index == 0) {
398 return map;
399 }
400 index--;
401 }
402 return null;
403 }
404
405 // indices instead of iterators for easier bidirectional traversal
406 private static final int mIndices[] = new int[gMaps.size()];
407 private static final String[] mLastAppliedModifications = new String[gMaps.size()];
408
409 private static boolean stepInternal(boolean forward) {
410 int modifierMapIndex = gMaps.size() - 1;
411 while (modifierMapIndex >= 0) {
412 LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
413 mIndices[modifierMapIndex] += (forward ? 1 : -1);
414
415 if (mIndices[modifierMapIndex] >= 0 && mIndices[modifierMapIndex] < map.size()) {
416 break;
417 }
418
419 mIndices[modifierMapIndex] = (forward ? 0 : map.size() - 1);
420 modifierMapIndex--;
421 }
422 return modifierMapIndex < 0; // true if resetting
423 }
424
425 public static boolean step() {
426 boolean ret = false;
427 do {
428 ret |= stepInternal(true);
429 } while (!checkModificationStateMask());
430 return ret;
431 }
432
433 public static boolean stepBack() {
434 boolean ret = false;
435 do {
436 ret |= stepInternal(false);
437 } while (!checkModificationStateMask());
438 return ret;
439 }
440
441 private static boolean checkModificationStateMask() {
442 int operatorMask = 0x0;
443 int mapIndex = 0;
444 for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
445 int displayModifierIndex = mIndices[mapIndex];
446 for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
447 if (displayModifierIndex == 0) {
448 mLastAppliedModifications[mapIndex] = modifierEntry.getKey();
449 operatorMask |= modifierEntry.getValue().mask();
450 break;
451 }
452 displayModifierIndex--;
453 }
454 mapIndex++;
455 }
456 return operatorMask == TOTAL_MASK;
457 }
458
459 public static void apply(Paint paint, Canvas canvas) {
460 int mapIndex = 0;
461 for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
462 int displayModifierIndex = mIndices[mapIndex];
463 for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
464 if (displayModifierIndex == 0) {
465 mLastAppliedModifications[mapIndex] = modifierEntry.getKey();
466 modifierEntry.getValue().modifyDrawing(paint, canvas);
467 break;
468 }
469 displayModifierIndex--;
470 }
471 mapIndex++;
472 }
473 }
474
475 public static String[] getLastAppliedModifications() {
476 return mLastAppliedModifications.clone();
477 }
478
479 public static String[][] getStrings() {
480 String[][] keys = new String[gMaps.size()][];
481
482 int i = 0;
483 for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
484 keys[i] = new String[map.size()];
485 int j = 0;
486 for (String key : map.keySet()) {
487 keys[i][j++] = key;
488 }
489 i++;
490 }
491
492 return keys;
493 }
494
495 public static void setIndex(int mapIndex, int newIndexValue) {
496 mIndices[mapIndex] = newIndexValue;
497 }
498
499 public static int[] getIndices() {
500 return mIndices;
501 }
502}