1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPictureRecorder.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTableColorFilter.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorFilterImageFilter.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPictureImageFilter.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int kTestRectSize = 50; 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int kDetectorGreenValue = 50; 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Below are few functions to install "detector" color filters. The filter is there to assert that 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// the color value it sees is the expected. It will trigger only with kDetectorGreenValue, and 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// turn that value into full green. The idea is that if an optimization incorrectly changes 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// kDetectorGreenValue and then the incorrect value is observable by some part of the drawing 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// pipeline, that pixel will remain empty. 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkColorFilter> make_detector_color_filter() { 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t tableA[256] = { 0, }; 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t tableR[256] = { 0, }; 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t tableG[256] = { 0, }; 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t tableB[256] = { 0, }; 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tableA[255] = 255; 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tableG[kDetectorGreenValue] = 255; 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB); 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This detector detects that color filter phase of the pixel pipeline receives the correct value. 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void install_detector_color_filter(SkPaint* drawPaint) { 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawPaint->setColorFilter(make_detector_color_filter()); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This detector detects that image filter phase of the pixel pipeline receives the correct value. 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void install_detector_image_filter(SkPaint* drawPaint) { 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawPaint->setImageFilter(SkColorFilterImageFilter::Make(make_detector_color_filter(), 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawPaint->refImageFilter())); 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void no_detector_install(SkPaint*) { 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottypedef void(*InstallDetectorFunc)(SkPaint*); 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// inner draw. Since we know that folding will happen to the inner draw, install a detector 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// to make sure that optimization does not change anything observable. 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_save_layer_draw_rect_restore_sequence(SkCanvas* canvas, SkColor shapeColor, 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot InstallDetectorFunc installDetector) { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar(kTestRectSize))); 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint layerPaint; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot layerPaint.setColor(SkColorSetARGB(128, 0, 0, 0)); 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->saveLayer(&targetRect, &layerPaint); 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint drawPaint; 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawPaint.setColor(shapeColor); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot installDetector(&drawPaint); 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawRect(targetRect, drawPaint); 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// inner draw. A variant where the draw is not uniform color. 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_save_layer_draw_bitmap_restore_sequence(SkCanvas* canvas, SkColor shapeColor, 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot InstallDetectorFunc installDetector) { 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bitmap; 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap.allocN32Pixels(kTestRectSize, kTestRectSize); 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap.eraseColor(shapeColor); 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Make the bitmap non-uniform color, so that it can not be optimized as uniform drawRect. 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas canvas(bitmap); 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint p; 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p.setColor(SK_ColorWHITE); 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(shapeColor != SK_ColorWHITE); 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.drawRect(SkRect::MakeWH(SkIntToScalar(7), SkIntToScalar(7)), p); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas.flush(); 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar(kTestRectSize))); 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint layerPaint; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot layerPaint.setColor(SkColorSetARGB(129, 0, 0, 0)); 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->saveLayer(&targetRect, &layerPaint); 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint drawPaint; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot installDetector(&drawPaint); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &drawPaint); 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// inner savelayer. We know that alpha folding happens to inner savelayer, so add detector there. 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_svg_opacity_and_filter_layer_sequence(SkCanvas* canvas, SkColor shapeColor, 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot InstallDetectorFunc installDetector) { 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar(kTestRectSize))); 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkPicture> shape; 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPictureRecorder recorder; 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kTestRectSize + 2), 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(kTestRectSize + 2)); 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint shapePaint; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shapePaint.setColor(shapeColor); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->drawRect(targetRect, shapePaint); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shape = recorder.finishRecordingAsPicture(); 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint layerPaint; 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot layerPaint.setColor(SkColorSetARGB(130, 0, 0, 0)); 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->saveLayer(&targetRect, &layerPaint); 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->clipRect(targetRect); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint drawPaint; 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawPaint.setImageFilter(SkPictureImageFilter::Make(shape)); 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot installDetector(&drawPaint); 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->saveLayer(&targetRect, &drawPaint); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Draws two columns of rectangles. The test is correct when: 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - Left and right columns always identical 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - First 3 rows are green, with a white dent in the middle row 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - Next 6 rows are green, with a grey dent in the middle row 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// (the grey dent is from the color filter removing everything but the "good" green, see below) 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - Last 6 rows are grey 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) { 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->clear(SK_ColorTRANSPARENT); 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef void (*TestVariantSequence)(SkCanvas*, SkColor, InstallDetectorFunc); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TestVariantSequence funcs[] = { 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_save_layer_draw_rect_restore_sequence, 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_save_layer_draw_bitmap_restore_sequence, 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_svg_opacity_and_filter_layer_sequence, 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Draw layer-related sequences that can be optimized by folding the opacity layer alpha to 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the inner draw operation. This tries to trigger the optimization, and relies on gm diffs 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // to keep the color value correct over time. 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Draws two green rects side by side: one is without the optimization, the other is with 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the optimization applied. 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor shapeColor = SkColorSetARGB(255, 0, 255, 0); 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t k = 0; k < SK_ARRAY_COUNT(funcs); ++k) { 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TestVariantSequence drawTestSequence = funcs[k]; 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawTestSequence(canvas, shapeColor, no_detector_install); 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->flush(); 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1), SkIntToScalar(0)); 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPictureRecorder recorder; 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawTestSequence(recorder.beginRecording(SkIntToScalar(kTestRectSize), 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(kTestRectSize)), 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shapeColor, no_detector_install); 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot recorder.finishRecordingAsPicture()->playback(canvas); 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->flush(); 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(SkIntToScalar(0), SkIntToScalar(kTestRectSize) + SkIntToScalar(1)); 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Draw the same layer related sequences, but manipulate the sequences so that the result is 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // incorrect if the alpha is folded or folded incorrectly. These test the observable state 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // throughout the pixel pipeline, and thus may turn off the optimizations (this is why we 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // trigger the optimizations above). 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Draws two green rects side by side: one is without the optimization, the other is with 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the possibility that optimization is applied. 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // At the end, draws the same patterns in translucent black. This tests that the detectors 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // work, eg. that if the value the detector sees is wrong, the resulting image shows this. 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor shapeColors[] = { 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSetARGB(255, 0, kDetectorGreenValue, 0), 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColorSetARGB(255, 0, (kDetectorGreenValue + 1), 0) // This tests that detectors work. 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot InstallDetectorFunc detectorInstallFuncs[] = { 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot install_detector_image_filter, 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot install_detector_color_filter 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < SK_ARRAY_COUNT(shapeColors); ++i) { 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shapeColor = shapeColors[i]; 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t j = 0; j < SK_ARRAY_COUNT(detectorInstallFuncs); ++j) { 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot InstallDetectorFunc detectorInstallFunc = detectorInstallFuncs[j]; 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t k = 0; k < SK_ARRAY_COUNT(funcs); ++k) { 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TestVariantSequence drawTestSequence = funcs[k]; 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->save(); 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawTestSequence(canvas, shapeColor, detectorInstallFunc); 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->flush(); 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1), SkIntToScalar(0)); 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPictureRecorder recorder; 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawTestSequence(recorder.beginRecording(SkIntToScalar(kTestRectSize), 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(kTestRectSize)), 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shapeColor, detectorInstallFunc); 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot recorder.finishRecordingAsPicture()->playback(canvas); 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->flush(); 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->restore(); 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot canvas->translate(SkIntToScalar(0), SkIntToScalar(kTestRectSize) + SkIntToScalar(1)); 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 214