MatrixClipCollapseTest.cpp revision 5e0995e4b36178e1e4465a9f50114ed39f038c27
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
551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#ifdef COLLAPSE_MATRIX_CLIP_STATE
561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Extract the command ops from the input SkPicture
581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void gets_ops(SkPicture& input, SkTDArray<DrawType>* ops) {
591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugCanvas debugCanvas(input.width(), input.height());
601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    debugCanvas.setBounds(input.width(), input.height());
611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    input.draw(&debugCanvas);
621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    ops->setCount(debugCanvas.getSize());
641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < debugCanvas.getSize(); ++i) {
651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*ops)[i] = debugCanvas.getDrawCommandAt(i)->getType();
661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comenum ClipType {
701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kNone_ClipType,
711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRect_ClipType,
721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRRect_ClipType,
731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPath_ClipType,
741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRegion_ClipType,
751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kLast_ClipType = kRRect_ClipType
771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic const int kClipTypeCount = kLast_ClipType + 1;
801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comenum MatType {
821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kNone_MatType,
831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kTranslate_MatType,
841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kScale_MatType,
851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kSkew_MatType,
861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRotate_MatType,
871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kConcat_MatType,
881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kSetMatrix_MatType,
891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kLast_MatType = kScale_MatType
911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic const int kMatTypeCount = kLast_MatType + 1;
941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// TODO: implement the rest of the draw ops
961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comenum DrawOpType {
971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kNone_DrawOpType,
981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmap_DrawOpType,
1001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmapMatrix_DrawOpType,
1011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmapNone_DrawOpType,
1021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kBitmapRectToRect_DrawOpType,
1031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kClear_DrawOpType,
1051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kData_DrawOpType,
1071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kOval_DrawOpType,
1091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPaint_DrawOpType,
1111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPath_DrawOpType,
1121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPicture_DrawOpType,
1131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPoints_DrawOpType,
1141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosText_DrawOpType,
1151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosTextTopBottom_DrawOpType,
1161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosTextH_DrawOpType,
1171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kPosTextHTopBottom_DrawOpType,
1181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRect_DrawOpType,
1201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kRRect_DrawOpType,
1211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#if 0
1221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kSprite_DrawOpType,
1231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kText_DrawOpType,
1241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kTextOnPath_DrawOpType,
1251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kTextTopBottom_DrawOpType,
1261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kDrawVertices_DrawOpType,
1271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
1281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    kLast_DrawOpType = kRect_DrawOpType
1301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com};
1311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic const int kDrawOpTypeCount = kLast_DrawOpType + 1;
1331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1345e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitMC)(SkCanvas* canvas, MatType mat, ClipType clip,
1355e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                         DrawOpType draw, SkTDArray<DrawType>* expected,
1361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         int accumulatedClips);
1375e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitBody)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
1385e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                           ClipType clip, DrawOpType draw,
1391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                           SkTDArray<DrawType>* expected, int accumulatedClips);
1405e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgtypedef void (*PFEmitStruct)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
1415e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                             ClipType clip, PFEmitBody emitBody, DrawOpType draw,
1421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                             SkTDArray<DrawType>* expected);
1431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
1451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// TODO: expand the testing to include the different ops & AA types!
1471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_clip(SkCanvas* canvas, ClipType clip) {
1481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (clip) {
1491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_ClipType:
1501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_ClipType: {
1521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
1531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRect(r, SkRegion::kIntersect_Op, true);
1541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_ClipType: {
1571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
1581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRRect rr;
1591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            rr.setRectXY(r, 10, 10);
1601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRRect(rr, SkRegion::kIntersect_Op, true);
1611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kPath_ClipType: {
1641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPath p;
1651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.moveTo(5.0f, 5.0f);
1661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.lineTo(50.0f, 50.0f);
1671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.lineTo(100.0f, 5.0f);
1681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            p.close();
1691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipPath(p, SkRegion::kIntersect_Op, true);
1701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRegion_ClipType: {
1731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkIRect rects[2] = {
1741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                { 1, 1, 55, 55 },
1751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                { 45, 45, 99, 99 },
1761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            };
1771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRegion r;
1781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            r.setRects(rects, 2);
1791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clipRegion(r, SkRegion::kIntersect_Op);
1801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
1821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
1831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
1841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
1851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
1861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void add_clip(ClipType clip, MatType mat, SkTDArray<DrawType>* expected) {
1881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (NULL == expected) {
1891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // expected is NULL if this clip will be fused into later clips
1901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
1911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
1921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
1931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (clip) {
1941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_ClipType:
1951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
1961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_ClipType:
1971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
1981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_RECT;
1991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_ClipType:
2011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_RRECT;
2031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kPath_ClipType:
2051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_PATH;
2071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRegion_ClipType:
2091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CONCAT;
2101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = CLIP_REGION;
2111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
2131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
2141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
2161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_mat(SkCanvas* canvas, MatType mat) {
2181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (mat) {
2191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kNone_MatType:
2201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kTranslate_MatType:
2221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->translate(5.0f, 5.0f);
2231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kScale_MatType:
2251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->scale(1.1f, 1.1f);
2261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSkew_MatType:
2281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->skew(1.1f, 1.1f);
2291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kRotate_MatType:
2311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->rotate(1.0f);
2321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kConcat_MatType: {
2341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkMatrix m;
2351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        m.setTranslate(1.0f, 1.0f);
2361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->concat(m);
2371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSetMatrix_MatType: {
2401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkMatrix m;
2411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        m.setTranslate(1.0f, 1.0f);
2421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->setMatrix(m);
2431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    default:
2461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkASSERT(0);
2471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
2491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void add_mat(MatType mat, SkTDArray<DrawType>* expected) {
2511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (NULL == expected) {
2521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // expected is NULL if this matrix call will be fused into later ones
2531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
2541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (mat) {
2571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kNone_MatType:
2581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kTranslate_MatType:    // fall thru
2601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kScale_MatType:        // fall thru
2611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kSkew_MatType:         // fall thru
2621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kRotate_MatType:       // fall thru
2631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    case kConcat_MatType:       // fall thru
2645e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    case kSetMatrix_MatType:
2651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // TODO: this system currently converts a setMatrix to concat. If we wanted to
2661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // really preserve the setMatrix semantics we should keep it a setMatrix. I'm
2671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // not sure if this is a good idea though since this would keep things like pinch
2681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // zoom from working.
2691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = CONCAT;
2701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        break;
2711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    default:
2721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        SkASSERT(0);
2731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
2745e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org}
2751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
2761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* expected) {
2771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    switch (draw) {
2781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kNone_DrawOpType:
2791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kClear_DrawOpType:
2811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->clear(SK_ColorRED);
2821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_CLEAR;
2831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kOval_DrawOpType: {
2851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
2861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
2871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawOval(r, p);
2881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_OVAL;
2891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
2911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRect_DrawOpType: {
2921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10, 10, 90, 90);
2931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
2941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawRect(r, p);
2951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_RECT;
2961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
2971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
2981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        case kRRect_DrawOpType: {
2991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRect r = SkRect::MakeLTRB(10.0f, 10.0f, 90.0f, 90.0f);
3001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkRRect rr;
3011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            rr.setRectXY(r, 5.0f, 5.0f);
3021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkPaint p;
3031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            canvas->drawRRect(rr, p);
3041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = DRAW_RRECT;
3051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            break;
3061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
3071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        default:
3081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkASSERT(0);
3091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
3131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Simple case - the clip isn't effect by the matrix
3185e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip,
3195e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                              DrawOpType draw, SkTDArray<DrawType>* expected,
3201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                              int accumulatedClips) {
3211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emitting the matrix first is more challenging since the matrix has to be
3381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// pushed across (i.e., applied to) the clip.
3395e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3405e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                              DrawOpType draw, SkTDArray<DrawType>* expected,
3411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                              int accumulatedClips) {
3421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // the matrix & clip order will be reversed once collapsed!
3501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This tests that the matrices and clips coalesce when collapsed
3625e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3635e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                     DrawOpType draw, SkTDArray<DrawType>* expected,
3641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                     int accumulatedClips) {
3651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
3771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
3791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
3801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
3821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix
3831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  clip
3851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// This tests accumulation of clips in same transform state. It also tests pushing
3861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// of the matrix across both the clips.
3871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void emit_mat_clip_clip(SkCanvas* canvas, MatType mat, ClipType clip,
3881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                               DrawOpType draw, SkTDArray<DrawType>* expected,
3891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                               int accumulatedClips) {
3901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (kNone_DrawOpType == draw) {
3911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        return;
3921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
3935e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org
3941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_mat(canvas, mat);
3951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_clip(canvas, clip);
3971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
3981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < accumulatedClips; ++i) {
3991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
4001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        add_clip(clip, mat, expected);
4011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    add_mat(mat, expected);
4031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
4061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4105e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body0(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4135e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1);
4201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  draw op
4315e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body1(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4345e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1);
4411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE;
4451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2);
4471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    emit_draw(canvas, draw, expected);
4481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  SaveLayer
4561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
4571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      draw op
4581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
4595e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body2(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4625e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
4641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = SAVE_LAYER;
4671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
4691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // TODO: widen testing to exercise saveLayer's parameters
4701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->saveLayer(NULL, NULL);
4711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
4721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = SAVE;
4731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
4741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2);
4751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        emit_draw(canvas, draw, expected);
4761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
4771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = RESTORE;
4781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
4791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
4801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    if (needsSaveRestore) {
4811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        *expected->append() = RESTORE;
4821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
4831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
4841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
4851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
4861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  matrix & clip calls
4871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  SaveLayer
4881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
4891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      SaveLayer
4901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          matrix & clip calls
4911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          draw op
4921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
4931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
4941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
4955e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_body3(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
4961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       ClipType clip, DrawOpType draw,
4971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                       SkTDArray<DrawType>* expected, int accumulatedClips) {
4985e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    bool needsSaveRestore = kNone_DrawOpType != draw &&
4991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            (kNone_MatType != mat || kNone_ClipType != clip);
5001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5015e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    // This saveLayer will always be forced b.c. we currently can't tell
5021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // ahead of time if it will be empty (see comment in SkMatrixClipStateMgr::save)
5031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    *expected->append() = SAVE_LAYER;
5041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
5061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // TODO: widen testing to exercise saveLayer's parameters
5071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->saveLayer(NULL, NULL);
5081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
5091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
5101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = SAVE_LAYER;
5111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
5121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        // TODO: widen testing to exercise saveLayer's parameters
5131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->saveLayer(NULL, NULL);
5141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            if (needsSaveRestore) {
5151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                *expected->append() = SAVE;
5161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
5171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+3);
5181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            emit_draw(canvas, draw, expected);
5191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            if (needsSaveRestore) {
5201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                *expected->append() = RESTORE;
5211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
5221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->restore();
5231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (needsSaveRestore) {
5241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            *expected->append() = RESTORE;
5251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
5261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    // required to match forced SAVE_LAYER
5291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    *expected->append() = RESTORE;
5301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
5331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      some body
5371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5395e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct0(SkCanvas* canvas,
5401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 0);
5441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5521f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5555e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct1(SkCanvas* canvas,
5561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
5601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get removed
5641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5751f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
5761f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
5771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
5785e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct2(SkCanvas* canvas,
5791f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
5801f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
5811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
5821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get fused into later ops
5831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
5871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
5881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
5891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get removed
5901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
5911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
5921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Emit:
5931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Save
5941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls
5951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          some body
5971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
5981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Save
5991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          matrix & clip calls
6001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          Save
6011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//              some body
6021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//          Restore
6031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      Restore
6041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//      matrix & clip calls (will be ignored)
6051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//  Restore
6061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com// Note: the outer save/restore are provided by beginRecording/endRecording
6075e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.orgstatic void emit_struct3(SkCanvas* canvas,
6081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitMC emitMC, MatType mat, ClipType clip,
6091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         PFEmitBody emitBody, DrawOpType draw,
6101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                         SkTDArray<DrawType>* expected) {
6111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get fused into later ops
6121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1);
6141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->save();
6161f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get fused into later ops
6171f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->save();
6181f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 2);
6191f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        canvas->restore();
6201f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    canvas->restore();
6211f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get removed
6221f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6231f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6241f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com//////////////////////////////////////////////////////////////////////////////
6251f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6261f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#ifdef COLLAPSE_MATRIX_CLIP_STATE
6271f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void print(const SkTDArray<DrawType>& expected, const SkTDArray<DrawType>& actual) {
6281f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugf("\n\nexpected %d --- actual %d\n", expected.count(), actual.count());
6291f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    int max = SkMax32(expected.count(), actual.count());
6301f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6311f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (int i = 0; i < max; ++i) {
6321f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (i < expected.count()) {
6331f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%16s,    ", SkDrawCommand::GetCommandString(expected[i]));
6341f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        } else {
6351f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%16s,    ", " ");
6361f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
6371f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6381f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        if (i < actual.count()) {
6391f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("%s\n", SkDrawCommand::GetCommandString(actual[i]));
6401f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        } else {
6411f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            SkDebugf("\n");
6421f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
6431f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
6441f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkDebugf("\n\n");
6451f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    SkASSERT(0);
6461f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
6471f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6481f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6491f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comstatic void test_collapse(skiatest::Reporter* reporter) {
6501f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    PFEmitStruct gStructure[] = { emit_struct0, emit_struct1, emit_struct2, emit_struct3 };
6511f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    PFEmitBody gBody[] = { emit_body0, emit_body1, emit_body2, emit_body3 };
6525e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org    PFEmitMC gMCs[] = { emit_clip_and_mat, emit_mat_and_clip,
6531f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        emit_double_mat_and_clip, emit_mat_clip_clip };
6541f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6551f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gStructure); ++i) {
6561f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        for (size_t j = 0; j < SK_ARRAY_COUNT(gBody); ++j) {
6571f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) {
6581f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                for (int l = 0; l < kMatTypeCount; ++l) {
6591f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                    for (int m = 0; m < kClipTypeCount; ++m) {
6601f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        for (int n = 0; n < kDrawOpTypeCount; ++n) {
6611f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#ifdef COLLAPSE_MATRIX_CLIP_STATE
6621f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            static int testID = -1;
6631f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            ++testID;
6641f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            if (testID < -1) {
6651f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                continue;
6661f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
6671f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6681f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6691f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkTDArray<DrawType> expected, actual;
6701f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6711f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkPicture picture;
6721f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6731f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            // Note: beginRecording/endRecording add a save/restore pair
6741f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            SkCanvas* canvas = picture.beginRecording(100, 100);
6755e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                            (*gStructure[i])(canvas,
6765e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             gMCs[k],
6771f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             (MatType) l,
6781f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             (ClipType) m,
6795e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             gBody[j],
6805e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org                                             (DrawOpType) n,
6811f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                             &expected);
6821f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            picture.endRecording();
6831f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6841f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            gets_ops(picture, &actual);
6851f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6861f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            REPORTER_ASSERT(reporter, expected.count() == actual.count());
6871f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6881f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            if (expected.count() != actual.count()) {
6891f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#ifdef COLLAPSE_MATRIX_CLIP_STATE
6901f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                print(expected, actual);
6911f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
6921f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                continue;
6931f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
6941f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
6951f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            for (int i = 0; i < expected.count(); ++i) {
6961f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                REPORTER_ASSERT(reporter, expected[i] == actual[i]);
6971f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#ifdef COLLAPSE_MATRIX_CLIP_STATE
6981f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                if (expected[i] != actual[i]) {
6991f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                    print(expected, actual);
7001f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                }
7011f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com#endif
7021f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                                break;
7031f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                            }
7041f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                        }
7051f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                    }
7061f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com                }
7071f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com            }
7081f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com        }
7091f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    }
7101f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
7111f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
7121f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.comDEF_TEST(MatrixClipCollapse, reporter) {
7131f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com    test_collapse(reporter);
7141f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com}
7151f71846e5c0ee85bb4e4c2b42044eefdebbcf2dfrobertphillips@google.com
716940e3bac13291d95ffa811b233329196335fb3f4robertphillips@google.com#endif
717