MatrixClipCollapseTest.cpp revision 1cb6d1a1fd11b23aca42dcb8453e6816836b7b6f
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
55105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#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
1321cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    kLast_DrawOpType = kRect_DrawOpType
1331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
1341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1351cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.orgstatic const int kDrawOpTypeCount = kLast_DrawOpType + 1;
1361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1375e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitMC)(SkCanvas* canvas, MatType mat, ClipType clip,
1385e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                         DrawOpType draw, SkTDArray<DrawType>* expected,
1391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         int accumulatedClips);
1405e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitBody)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
1415e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                           ClipType clip, DrawOpType draw,
1421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                           SkTDArray<DrawType>* expected, int accumulatedClips);
1435e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitStruct)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
1445e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                             ClipType clip, PFEmitBody emitBody, DrawOpType draw,
1451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                             SkTDArray<DrawType>* expected);
1461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
1481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// TODO: expand the testing to include the different ops & AA types!
1501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_clip(SkCanvas* canvas, ClipType clip) {
1511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (clip) {
1521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_ClipType:
1531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_ClipType: {
1551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
1561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRect(r, SkRegion::kIntersect_Op, true);
1571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_ClipType: {
1601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
1611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRRect rr;
1621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            rr.setRectXY(r, 10, 10);
1631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRRect(rr, SkRegion::kIntersect_Op, true);
1641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kPath_ClipType: {
1671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPath p;
1681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.moveTo(5.0f, 5.0f);
1691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.lineTo(50.0f, 50.0f);
1701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.lineTo(100.0f, 5.0f);
1711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.close();
1721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipPath(p, SkRegion::kIntersect_Op, true);
1731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRegion_ClipType: {
1761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkIRect rects[2] = {
1771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                { 1, 1, 55, 55 },
1781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                { 45, 45, 99, 99 },
1791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            };
1801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRegion r;
1811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            r.setRects(rects, 2);
1821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRegion(r, SkRegion::kIntersect_Op);
1831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
1861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
1871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
1881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
1891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void add_clip(ClipType clip, MatType mat, SkTDArray<DrawType>* expected) {
1911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (NULL == expected) {
1921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // expected is NULL if this clip will be fused into later clips
1931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
1941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
1951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (clip) {
1971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_ClipType:
1981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_ClipType:
2001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_RECT;
2021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_ClipType:
2041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_RRECT;
2061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kPath_ClipType:
2081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_PATH;
2101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRegion_ClipType:
2121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_REGION;
2141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
2161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
2171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
2191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_mat(SkCanvas* canvas, MatType mat) {
2211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (mat) {
2221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kNone_MatType:
2231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kTranslate_MatType:
2251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->translate(5.0f, 5.0f);
2261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kScale_MatType:
2281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->scale(1.1f, 1.1f);
2291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSkew_MatType:
2311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->skew(1.1f, 1.1f);
2321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kRotate_MatType:
2341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->rotate(1.0f);
2351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kConcat_MatType: {
2371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkMatrix m;
2381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        m.setTranslate(1.0f, 1.0f);
2391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->concat(m);
2401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSetMatrix_MatType: {
2431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkMatrix m;
2441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        m.setTranslate(1.0f, 1.0f);
2451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->setMatrix(m);
2461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    default:
2491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkASSERT(0);
2501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
2521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void add_mat(MatType mat, SkTDArray<DrawType>* expected) {
2541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (NULL == expected) {
2551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // expected is NULL if this matrix call will be fused into later ones
2561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
2571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (mat) {
2601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kNone_MatType:
2611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kTranslate_MatType:    // fall thru
2631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kScale_MatType:        // fall thru
2641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSkew_MatType:         // fall thru
2651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kRotate_MatType:       // fall thru
2661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kConcat_MatType:       // fall thru
2675e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    case kSetMatrix_MatType:
2681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // TODO: this system currently converts a setMatrix to concat. If we wanted to
2691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // really preserve the setMatrix semantics we should keep it a setMatrix. I'm
2701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // not sure if this is a good idea though since this would keep things like pinch
2711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // zoom from working.
2721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = CONCAT;
2731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    default:
2751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkASSERT(0);
2761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2775e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org}
2781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* expected) {
2801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (draw) {
2811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_DrawOpType:
2821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kClear_DrawOpType:
2841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clear(SK_ColorRED);
2851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_CLEAR;
2861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kOval_DrawOpType: {
2881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
2891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
2901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawOval(r, p);
2911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_OVAL;
2921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
2941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_DrawOpType: {
2951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
2961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
2971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawRect(r, p);
2981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_RECT;
2991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
3001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
3011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_DrawOpType: {
3021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10.0f, 10.0f, 90.0f, 90.0f);
3031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRRect rr;
3041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            rr.setRectXY(r, 5.0f, 5.0f);
3051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
3061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawRRect(rr, p);
3071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_RRECT;
3081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
3091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
3101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
3111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
3121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
3161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Simple case - the clip isn't effect by the matrix
3215e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip,
3225e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                              DrawOpType draw, SkTDArray<DrawType>* expected,
3231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                              int accumulatedClips) {
3241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3281cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_clip(canvas, clip);
3291cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_mat(canvas, mat);
3301cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org
3311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emitting the matrix first is more challenging since the matrix has to be
3411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// pushed across (i.e., applied to) the clip.
3425e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3435e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                              DrawOpType draw, SkTDArray<DrawType>* expected,
3441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                              int accumulatedClips) {
3451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3491cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_mat(canvas, mat);
3501cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    emit_clip(canvas, clip);
3511cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org
3521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // the matrix & clip order will be reversed once collapsed!
3531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This tests that the matrices and clips coalesce when collapsed
3655e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3665e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                     DrawOpType draw, SkTDArray<DrawType>* expected,
3671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                     int accumulatedClips) {
3681cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    if (kNone_DrawOpType == draw) {
3691cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        return;
3701cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    }
3711cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org
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
3771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This tests accumulation of clips in same transform state. It also tests pushing
3891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// of the matrix across both the clips.
3901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_mat_clip_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                               DrawOpType draw, SkTDArray<DrawType>* expected,
3921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                               int accumulatedClips) {
393f7d08ed626a4825317405c3708cf2896509209d6robertphillips@google.com    if (kNone_DrawOpType == draw) {
394f7d08ed626a4825317405c3708cf2896509209d6robertphillips@google.com        return;
395f7d08ed626a4825317405c3708cf2896509209d6robertphillips@google.com    }
396f7d08ed626a4825317405c3708cf2896509209d6robertphillips@google.com
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
4011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
4021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
4031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
4041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
4061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
4091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4135e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body0(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4165e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1);
4231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4345e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body1(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4375e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1);
4441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2);
4501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  SaveLayer
4591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
4601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      draw op
4611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
4625e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body2(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4655e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4681cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    if (needsSaveRestore) {
4691cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        *expected->append() = SAVE_LAYER;
4701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4711cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
4721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // TODO: widen testing to exercise saveLayer's parameters
4731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->saveLayer(NULL, NULL);
4741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
4751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = SAVE;
4761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
4771cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2);
4781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        emit_draw(canvas, draw, expected);
4791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
4801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = RESTORE;
4811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
4821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
4831cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    if (needsSaveRestore) {
4841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  SaveLayer
4911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
4921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      SaveLayer
4931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          matrix & clip calls
4941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          draw op
4951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
4961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
4971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
4985e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body3(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
5001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
5015e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
5021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
5031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5041cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    // This saveLayer will always be forced b.c. we currently can't tell
5051cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    // ahead of time if it will be empty (see comment in SkMatrixClipStateMgr::save)
5061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    *expected->append() = SAVE_LAYER;
5071cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org
5081cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
5091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // TODO: widen testing to exercise saveLayer's parameters
5101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->saveLayer(NULL, NULL);
5111cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
5121cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        if (needsSaveRestore) {
5131cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org            *expected->append() = SAVE_LAYER;
5141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
5151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // TODO: widen testing to exercise saveLayer's parameters
5161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->saveLayer(NULL, NULL);
5171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            if (needsSaveRestore) {
5181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                *expected->append() = SAVE;
5191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
5201cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org            (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+3);
5211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            emit_draw(canvas, draw, expected);
5221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            if (needsSaveRestore) {
5231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                *expected->append() = RESTORE;
5241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
5251cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        canvas->restore();
5261cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org        if (needsSaveRestore) {
5271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = RESTORE;
5281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
5291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5301cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org
5311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // required to match forced SAVE_LAYER
5321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    *expected->append() = RESTORE;
5331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
5361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      some body
5401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5425e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct0(SkCanvas* canvas,
5431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 0);
5471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5585e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct1(SkCanvas* canvas,
5591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
5631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get removed
5671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5815e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct2(SkCanvas* canvas,
5821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get fused into later ops
5861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get removed
5931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
6001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
6011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
6021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          matrix & clip calls
6031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          Save
6041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//              some body
6051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          Restore
6061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
6071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
6081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
6091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
6105e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct3(SkCanvas* canvas,
6111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
6121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
6131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
6141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get fused into later ops
6151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
6171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get fused into later ops
6201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->save();
6211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 2);
6221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->restore();
6231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get removed
6251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
6281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
629105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
6301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void print(const SkTDArray<DrawType>& expected, const SkTDArray<DrawType>& actual) {
6311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugf("\n\nexpected %d --- actual %d\n", expected.count(), actual.count());
6321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    int max = SkMax32(expected.count(), actual.count());
6331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < max; ++i) {
6351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (i < expected.count()) {
6361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%16s,    ", SkDrawCommand::GetCommandString(expected[i]));
6371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        } else {
6381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%16s,    ", " ");
6391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
6401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (i < actual.count()) {
6421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%s\n", SkDrawCommand::GetCommandString(actual[i]));
6431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        } else {
6441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("\n");
6451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
6461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
6471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugf("\n\n");
6481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkASSERT(0);
6491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void test_collapse(skiatest::Reporter* reporter) {
6531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    PFEmitStruct gStructure[] = { emit_struct0, emit_struct1, emit_struct2, emit_struct3 };
6541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    PFEmitBody gBody[] = { emit_body0, emit_body1, emit_body2, emit_body3 };
6555e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    PFEmitMC gMCs[] = { emit_clip_and_mat, emit_mat_and_clip,
6561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        emit_double_mat_and_clip, emit_mat_clip_clip };
6571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gStructure); ++i) {
6591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        for (size_t j = 0; j < SK_ARRAY_COUNT(gBody); ++j) {
6601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) {
6611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                for (int l = 0; l < kMatTypeCount; ++l) {
6621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                    for (int m = 0; m < kClipTypeCount; ++m) {
6631cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org                        for (int n = 0; n < kDrawOpTypeCount; ++n) {
664105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
6651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            static int testID = -1;
6661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            ++testID;
6671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            if (testID < -1) {
6681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                continue;
6691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
6701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkTDArray<DrawType> expected, actual;
6731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkPicture picture;
6751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            // Note: beginRecording/endRecording add a save/restore pair
6771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkCanvas* canvas = picture.beginRecording(100, 100);
6785e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                            (*gStructure[i])(canvas,
6795e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             gMCs[k],
6801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             (MatType) l,
6811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             (ClipType) m,
6825e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             gBody[j],
6835e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             (DrawOpType) n,
6841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             &expected);
6851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            picture.endRecording();
6861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            gets_ops(picture, &actual);
6881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            REPORTER_ASSERT(reporter, expected.count() == actual.count());
6901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            if (expected.count() != actual.count()) {
692105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
6931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                print(expected, actual);
6941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                continue;
6961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
6971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            for (int i = 0; i < expected.count(); ++i) {
6991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                REPORTER_ASSERT(reporter, expected[i] == actual[i]);
700105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
7011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                if (expected[i] != actual[i]) {
7021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                    print(expected, actual);
7031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                }
7041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
7051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                break;
7061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
7071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        }
7081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                    }
7091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                }
7101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
7111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
7121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
7131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
7141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
7151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comDEF_TEST(MatrixClipCollapse, reporter) {
7161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    test_collapse(reporter);
7171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
7181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
719940e3bac13291d95ffa811b233329196335fb3f4robertphillips@google.com#endif
720