11f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com/*
21f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com * Copyright 2014 Google Inc.
31f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com *
41f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
51f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com * found in the LICENSE file.
61f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com */
71f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
81f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#include "Test.h"
91f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#include "SkCanvas.h"
101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#include "SkDebugCanvas.h"
111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#include "SkPicture.h"
121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#include "SkPictureFlat.h"
131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#include "SkPictureRecord.h"
141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This test exercises the Matrix/Clip State collapsing system. It generates
161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// example skps and the compares the actual stored operations to the expected
171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// operations. The test works by emitting canvas operations at three levels:
181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// overall structure, bodies that draw something and model/clip state changes.
191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//
201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Structure methods only directly emit save and restores but call the
211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// ModelClip and Body helper methods to fill in the structure. Since they only
221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// emit saves and restores the operations emitted by the structure methods will
235e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org// be completely removed by the matrix/clip collapse. Note: every save in
241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// a structure method is followed by a call to a ModelClip helper.
251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//
261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Body methods only directly emit draw ops and saveLayer/restore pairs but call
271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// the ModelClip helper methods. Since the body methods emit the ops that cannot
281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// be collapsed (i.e., draw ops, saveLayer/restore) they also generate the
291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// expected result information. Note: every saveLayer in a body method is
301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// followed by a call to a ModelClip helper.
311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//
321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// The ModelClip methods output matrix and clip ops in various orders and
335e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org// combinations. They contribute to the expected result by outputting the
341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// expected matrix & clip ops. Note that, currently, the entire clip stack
351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// is output for each MC state so the clip operations accumulate down the
361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// save/restore stack.
371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// TODOs:
391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//   check on clip offsets
401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      - not sure if this is possible. The desire is to verify that the clip
411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        operations' offsets point to the correct follow-on operations. This
421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        could be difficult since there is no good way to communicate the
431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        offset stored in the SkPicture to the debugger's clip objects
445e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org//   add comparison of rendered before & after images?
451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      - not sure if this would be useful since it somewhat duplicates the
461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        correctness test of running render_pictures in record mode and
471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        rendering before and after images. Additionally the matrix/clip collapse
481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        is sure to cause some small differences so an automated test might
491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        yield too many false positives.
501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//   run the matrix/clip collapse system on the 10K skp set
511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      - this should give us warm fuzzies that the matrix clip collapse
521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//        system is ready for prime time
531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//   bench the recording times with/without matrix/clip collapsing
541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
552de59391157850b62ab5891aae349b64eb1d8a17robertphillips#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
56105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
57105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com// Enable/disable debugging helper code
58105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com//#define TEST_COLLAPSE_MATRIX_CLIP_STATE 1
591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Extract the command ops from the input SkPicture
611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void gets_ops(SkPicture& input, SkTDArray<DrawType>* ops) {
621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugCanvas debugCanvas(input.width(), input.height());
631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    debugCanvas.setBounds(input.width(), input.height());
641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    input.draw(&debugCanvas);
651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    ops->setCount(debugCanvas.getSize());
671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < debugCanvas.getSize(); ++i) {
681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*ops)[i] = debugCanvas.getDrawCommandAt(i)->getType();
691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comenum ClipType {
731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kNone_ClipType,
741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRect_ClipType,
751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRRect_ClipType,
761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPath_ClipType,
771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRegion_ClipType,
781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kLast_ClipType = kRRect_ClipType
801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic const int kClipTypeCount = kLast_ClipType + 1;
831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comenum MatType {
851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kNone_MatType,
861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kTranslate_MatType,
871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kScale_MatType,
881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kSkew_MatType,
891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRotate_MatType,
901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kConcat_MatType,
911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kSetMatrix_MatType,
921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kLast_MatType = kScale_MatType
941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic const int kMatTypeCount = kLast_MatType + 1;
971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// TODO: implement the rest of the draw ops
991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comenum DrawOpType {
1001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kNone_DrawOpType,
1011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmap_DrawOpType,
1031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmapMatrix_DrawOpType,
1041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmapNone_DrawOpType,
1051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmapRectToRect_DrawOpType,
1061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kClear_DrawOpType,
1081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kData_DrawOpType,
1101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kOval_DrawOpType,
1121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPaint_DrawOpType,
1141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPath_DrawOpType,
1151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPicture_DrawOpType,
1161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPoints_DrawOpType,
1171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosText_DrawOpType,
1181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosTextTopBottom_DrawOpType,
1191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosTextH_DrawOpType,
1201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosTextHTopBottom_DrawOpType,
1211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRect_DrawOpType,
1231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRRect_DrawOpType,
1241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kSprite_DrawOpType,
1261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kText_DrawOpType,
1271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kTextOnPath_DrawOpType,
1281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kTextTopBottom_DrawOpType,
1291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kDrawVertices_DrawOpType,
1301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
13292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    kLastNonSaveLayer_DrawOpType = kRect_DrawOpType,
13392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
13492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // saveLayer's have to handled apart from the other draw operations
13592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // since they also alter the save/restore structure.
13692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    kSaveLayer_DrawOpType,
1371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
1381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
13992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.orgstatic const int kNonSaveLayerDrawOpTypeCount = kLastNonSaveLayer_DrawOpType + 1;
1401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1415e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitMC)(SkCanvas* canvas, MatType mat, ClipType clip,
1425e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                         DrawOpType draw, SkTDArray<DrawType>* expected,
1431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         int accumulatedClips);
1445e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitBody)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
1455e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                           ClipType clip, DrawOpType draw,
1461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                           SkTDArray<DrawType>* expected, int accumulatedClips);
1475e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitStruct)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
1485e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                             ClipType clip, PFEmitBody emitBody, DrawOpType draw,
1491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                             SkTDArray<DrawType>* expected);
1501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
1521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// TODO: expand the testing to include the different ops & AA types!
1541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_clip(SkCanvas* canvas, ClipType clip) {
1551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (clip) {
1561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_ClipType:
1571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_ClipType: {
1591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
1601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRect(r, SkRegion::kIntersect_Op, true);
1611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_ClipType: {
1641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
1651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRRect rr;
1661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            rr.setRectXY(r, 10, 10);
1671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRRect(rr, SkRegion::kIntersect_Op, true);
1681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kPath_ClipType: {
1711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPath p;
1721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.moveTo(5.0f, 5.0f);
1731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.lineTo(50.0f, 50.0f);
1741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.lineTo(100.0f, 5.0f);
1751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.close();
1761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipPath(p, SkRegion::kIntersect_Op, true);
1771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRegion_ClipType: {
1801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkIRect rects[2] = {
1811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                { 1, 1, 55, 55 },
1821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                { 45, 45, 99, 99 },
1831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            };
1841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRegion r;
1851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            r.setRects(rects, 2);
1861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRegion(r, SkRegion::kIntersect_Op);
1871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
1901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
1911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
1921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
1931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void add_clip(ClipType clip, MatType mat, SkTDArray<DrawType>* expected) {
1952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (nullptr == expected) {
1962880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        // expected is nullptr if this clip will be fused into later clips
1971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
1981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
1991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (clip) {
2011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_ClipType:
2021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_ClipType:
2041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_RECT;
2061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_ClipType:
2081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_RRECT;
2101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kPath_ClipType:
2121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_PATH;
2141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRegion_ClipType:
2161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_REGION;
2181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
2201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
2211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
2231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_mat(SkCanvas* canvas, MatType mat) {
2251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (mat) {
2261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kNone_MatType:
2271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kTranslate_MatType:
2291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->translate(5.0f, 5.0f);
2301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kScale_MatType:
2321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->scale(1.1f, 1.1f);
2331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSkew_MatType:
2351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->skew(1.1f, 1.1f);
2361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kRotate_MatType:
2381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->rotate(1.0f);
2391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kConcat_MatType: {
2411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkMatrix m;
2421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        m.setTranslate(1.0f, 1.0f);
2431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->concat(m);
2441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSetMatrix_MatType: {
2471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkMatrix m;
2481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        m.setTranslate(1.0f, 1.0f);
2491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->setMatrix(m);
2501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    default:
2531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkASSERT(0);
2541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
2561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void add_mat(MatType mat, SkTDArray<DrawType>* expected) {
2582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (nullptr == expected) {
2592880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        // expected is nullptr if this matrix call will be fused into later ones
2601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
2611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (mat) {
2641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kNone_MatType:
2651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kTranslate_MatType:    // fall thru
2671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kScale_MatType:        // fall thru
2681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSkew_MatType:         // fall thru
2691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kRotate_MatType:       // fall thru
2701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kConcat_MatType:       // fall thru
2715e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    case kSetMatrix_MatType:
2721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // TODO: this system currently converts a setMatrix to concat. If we wanted to
2731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // really preserve the setMatrix semantics we should keep it a setMatrix. I'm
2741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // not sure if this is a good idea though since this would keep things like pinch
2751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // zoom from working.
2761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = CONCAT;
2771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    default:
2791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkASSERT(0);
2801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2815e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org}
2821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* expected) {
2841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (draw) {
2851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_DrawOpType:
2861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kClear_DrawOpType:
2881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clear(SK_ColorRED);
2891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_CLEAR;
2901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kOval_DrawOpType: {
2921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
2931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
2941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawOval(r, p);
2951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_OVAL;
2961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
2981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_DrawOpType: {
2991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
3001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
3011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawRect(r, p);
3021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_RECT;
3031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
3041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
3051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_DrawOpType: {
3061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10.0f, 10.0f, 90.0f, 90.0f);
3071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRRect rr;
3081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            rr.setRectXY(r, 5.0f, 5.0f);
3091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
3101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawRRect(rr, p);
3111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_RRECT;
3121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
3131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
3141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
3151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
3161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
3201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Simple case - the clip isn't effect by the matrix
3255e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip,
3265e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                              DrawOpType draw, SkTDArray<DrawType>* expected,
3271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                              int accumulatedClips) {
32892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    emit_clip(canvas, clip);
32992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    emit_mat(canvas, mat);
33092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
3311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emitting the matrix first is more challenging since the matrix has to be
3451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// pushed across (i.e., applied to) the clip.
3465e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3475e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                              DrawOpType draw, SkTDArray<DrawType>* expected,
3481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                              int accumulatedClips) {
34992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    emit_mat(canvas, mat);
35092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    emit_clip(canvas, clip);
35192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
3521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // the matrix & clip order will be reversed once collapsed!
3571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This tests that the matrices and clips coalesce when collapsed
3695e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3705e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                     DrawOpType draw, SkTDArray<DrawType>* expected,
3711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                     int accumulatedClips) {
3721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
37792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (kNone_DrawOpType == draw) {
37892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        return;
37992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
38092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
3811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This tests accumulation of clips in same transform state. It also tests pushing
3931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// of the matrix across both the clips.
3941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_mat_clip_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                               DrawOpType draw, SkTDArray<DrawType>* expected,
3961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                               int accumulatedClips) {
3971cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_mat(canvas, mat);
3981cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_clip(canvas, clip);
3991cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_clip(canvas, clip);
4001cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org
40192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (kNone_DrawOpType == draw) {
40292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        return;
40392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
40492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
4051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
4061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
4071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
4081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
4101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
4131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4175e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body0(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4205e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1);
4271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4385e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body1(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4415e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1);
4481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2);
4541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  SaveLayer
4631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
4641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      draw op
4651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
4665e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body2(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4695e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
47292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (kNone_MatType != mat || kNone_ClipType != clip) {
47392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        *expected->append() = SAVE;
4741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
47592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, accumulatedClips+1);
47692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    *expected->append() = SAVE_LAYER;
4771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // TODO: widen testing to exercise saveLayer's parameters
4782880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    canvas->saveLayer(nullptr, nullptr);
4791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
4801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = SAVE;
4811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
48292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        (*emitMC)(canvas, mat, clip, draw, expected, 1);
4831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        emit_draw(canvas, draw, expected);
4841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
4851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = RESTORE;
4861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
4871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
48892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    *expected->append() = RESTORE;
48992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (kNone_MatType != mat || kNone_ClipType != clip) {
4901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  SaveLayer
4971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
4981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      SaveLayer
4991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          matrix & clip calls
5001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          draw op
5011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5045e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body3(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
5051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
5061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
5075e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
5081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
5091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
51092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (kNone_MatType != mat || kNone_ClipType != clip) {
51192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        *expected->append() = SAVE;
51292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
513c05d2859e10f4e1fb0c6486eebfbe88801202648skia.committer@gmail.com    (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, accumulatedClips+1);
5141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    *expected->append() = SAVE_LAYER;
5151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // TODO: widen testing to exercise saveLayer's parameters
5162880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    canvas->saveLayer(nullptr, nullptr);
51792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, 1);
51892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        if (kNone_MatType != mat || kNone_ClipType != clip) {
51992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            *expected->append() = SAVE;
5201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
52192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        *expected->append() = SAVE_LAYER;
5221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // TODO: widen testing to exercise saveLayer's parameters
5232880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        canvas->saveLayer(nullptr, nullptr);
5241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            if (needsSaveRestore) {
5251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                *expected->append() = SAVE;
5261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
52792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            (*emitMC)(canvas, mat, clip, draw, expected, 1);
5281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            emit_draw(canvas, draw, expected);
5291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            if (needsSaveRestore) {
5301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                *expected->append() = RESTORE;
5311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
53292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        canvas->restore();             // for saveLayer
53392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        *expected->append() = RESTORE; // for saveLayer
53492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        if (kNone_MatType != mat || kNone_ClipType != clip) {
5351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = RESTORE;
5361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
5371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // required to match forced SAVE_LAYER
5391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    *expected->append() = RESTORE;
54092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (kNone_MatType != mat || kNone_ClipType != clip) {
54192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        *expected->append() = RESTORE;
54292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
5431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
5461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      some body
5501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5525e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct0(SkCanvas* canvas,
5531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 0);
5571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5685e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct1(SkCanvas* canvas,
5691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5722880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these get fused into later ops
5731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5762880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these will get removed
5771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5915e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct2(SkCanvas* canvas,
5921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    (*emitMC)(canvas, mat, clip, draw, nullptr, 1); // these will get fused into later ops
5961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
6011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6022880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    (*emitMC)(canvas, mat, clip, draw, nullptr, 1); // these will get removed
6031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
6061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
6071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
6081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
6091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
6101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
6111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
6121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          matrix & clip calls
6131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          Save
6141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//              some body
6151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          Restore
6161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
6171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
6181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
6191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
6205e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct3(SkCanvas* canvas,
6211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
6221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
6231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
6242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these will get fused into later ops
6251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
6271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6292880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        (*emitMC)(canvas, mat, clip, draw, nullptr, 1); // these will get fused into later ops
6301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->save();
6311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 2);
6321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->restore();
6331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6342880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these will get removed
6351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
6381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
639105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
6401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void print(const SkTDArray<DrawType>& expected, const SkTDArray<DrawType>& actual) {
6411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugf("\n\nexpected %d --- actual %d\n", expected.count(), actual.count());
6421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    int max = SkMax32(expected.count(), actual.count());
6431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < max; ++i) {
6451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (i < expected.count()) {
6461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%16s,    ", SkDrawCommand::GetCommandString(expected[i]));
6471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        } else {
6481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%16s,    ", " ");
6491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
6501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (i < actual.count()) {
6521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%s\n", SkDrawCommand::GetCommandString(actual[i]));
6531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        } else {
6541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("\n");
6551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
6561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
6571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugf("\n\n");
6581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkASSERT(0);
6591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void test_collapse(skiatest::Reporter* reporter) {
6631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    PFEmitStruct gStructure[] = { emit_struct0, emit_struct1, emit_struct2, emit_struct3 };
6641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    PFEmitBody gBody[] = { emit_body0, emit_body1, emit_body2, emit_body3 };
6655e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    PFEmitMC gMCs[] = { emit_clip_and_mat, emit_mat_and_clip,
6661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        emit_double_mat_and_clip, emit_mat_clip_clip };
6671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gStructure); ++i) {
6691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        for (size_t j = 0; j < SK_ARRAY_COUNT(gBody); ++j) {
6701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) {
6711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                for (int l = 0; l < kMatTypeCount; ++l) {
6721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                    for (int m = 0; m < kClipTypeCount; ++m) {
67392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org                        for (int n = 0; n < kNonSaveLayerDrawOpTypeCount; ++n) {
674105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
6751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            static int testID = -1;
6761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            ++testID;
6771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            if (testID < -1) {
6781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                continue;
6791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
68092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org                            SkDebugf("test: %d\n", testID);
6811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkTDArray<DrawType> expected, actual;
6841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkPicture picture;
6861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            // Note: beginRecording/endRecording add a save/restore pair
6881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkCanvas* canvas = picture.beginRecording(100, 100);
6895e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                            (*gStructure[i])(canvas,
6905e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             gMCs[k],
6911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             (MatType) l,
6921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             (ClipType) m,
6935e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             gBody[j],
6945e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             (DrawOpType) n,
6951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             &expected);
6961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            picture.endRecording();
6971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            gets_ops(picture, &actual);
6991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
7001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            REPORTER_ASSERT(reporter, expected.count() == actual.count());
7011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
7021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            if (expected.count() != actual.count()) {
703105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
7041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                print(expected, actual);
7051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
7061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                continue;
7071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
7081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
7091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            for (int i = 0; i < expected.count(); ++i) {
7101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                REPORTER_ASSERT(reporter, expected[i] == actual[i]);
711105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
7121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                if (expected[i] != actual[i]) {
7131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                    print(expected, actual);
7141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                }
7151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
7161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                break;
7171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
7181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        }
7191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                    }
7201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                }
7211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
7221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
7231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
7241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
7251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
7261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comDEF_TEST(MatrixClipCollapse, reporter) {
7271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    test_collapse(reporter);
7281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
7291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
730940e3bac13291d95ffa811b233329196335fb3f4robertphillips@google.com#endif
731