1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkPicture.h" 10cb93a386Sopenharmony_ci#include "src/core/SkPictureFlat.h" 11cb93a386Sopenharmony_ci#include "src/core/SkPictureRecord.h" 12cb93a386Sopenharmony_ci#include "tests/Test.h" 13cb93a386Sopenharmony_ci#include "tools/debugger/DebugCanvas.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci// This test exercises the Matrix/Clip State collapsing system. It generates 16cb93a386Sopenharmony_ci// example skps and the compares the actual stored operations to the expected 17cb93a386Sopenharmony_ci// operations. The test works by emitting canvas operations at three levels: 18cb93a386Sopenharmony_ci// overall structure, bodies that draw something and model/clip state changes. 19cb93a386Sopenharmony_ci// 20cb93a386Sopenharmony_ci// Structure methods only directly emit save and restores but call the 21cb93a386Sopenharmony_ci// ModelClip and Body helper methods to fill in the structure. Since they only 22cb93a386Sopenharmony_ci// emit saves and restores the operations emitted by the structure methods will 23cb93a386Sopenharmony_ci// be completely removed by the matrix/clip collapse. Note: every save in 24cb93a386Sopenharmony_ci// a structure method is followed by a call to a ModelClip helper. 25cb93a386Sopenharmony_ci// 26cb93a386Sopenharmony_ci// Body methods only directly emit draw ops and saveLayer/restore pairs but call 27cb93a386Sopenharmony_ci// the ModelClip helper methods. Since the body methods emit the ops that cannot 28cb93a386Sopenharmony_ci// be collapsed (i.e., draw ops, saveLayer/restore) they also generate the 29cb93a386Sopenharmony_ci// expected result information. Note: every saveLayer in a body method is 30cb93a386Sopenharmony_ci// followed by a call to a ModelClip helper. 31cb93a386Sopenharmony_ci// 32cb93a386Sopenharmony_ci// The ModelClip methods output matrix and clip ops in various orders and 33cb93a386Sopenharmony_ci// combinations. They contribute to the expected result by outputting the 34cb93a386Sopenharmony_ci// expected matrix & clip ops. Note that, currently, the entire clip stack 35cb93a386Sopenharmony_ci// is output for each MC state so the clip operations accumulate down the 36cb93a386Sopenharmony_ci// save/restore stack. 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci// TODOs: 39cb93a386Sopenharmony_ci// check on clip offsets 40cb93a386Sopenharmony_ci// - not sure if this is possible. The desire is to verify that the clip 41cb93a386Sopenharmony_ci// operations' offsets point to the correct follow-on operations. This 42cb93a386Sopenharmony_ci// could be difficult since there is no good way to communicate the 43cb93a386Sopenharmony_ci// offset stored in the SkPicture to the debugger's clip objects 44cb93a386Sopenharmony_ci// add comparison of rendered before & after images? 45cb93a386Sopenharmony_ci// - not sure if this would be useful since it somewhat duplicates the 46cb93a386Sopenharmony_ci// correctness test of running render_pictures in record mode and 47cb93a386Sopenharmony_ci// rendering before and after images. Additionally the matrix/clip collapse 48cb93a386Sopenharmony_ci// is sure to cause some small differences so an automated test might 49cb93a386Sopenharmony_ci// yield too many false positives. 50cb93a386Sopenharmony_ci// run the matrix/clip collapse system on the 10K skp set 51cb93a386Sopenharmony_ci// - this should give us warm fuzzies that the matrix clip collapse 52cb93a386Sopenharmony_ci// system is ready for prime time 53cb93a386Sopenharmony_ci// bench the recording times with/without matrix/clip collapsing 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci// Enable/disable debugging helper code 58cb93a386Sopenharmony_ci//#define TEST_COLLAPSE_MATRIX_CLIP_STATE 1 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci// Extract the command ops from the input SkPicture 61cb93a386Sopenharmony_cistatic void gets_ops(SkPicture& input, SkTDArray<DrawType>* ops) { 62cb93a386Sopenharmony_ci DebugCanvas debugCanvas(input.width(), input.height()); 63cb93a386Sopenharmony_ci debugCanvas.setBounds(input.width(), input.height()); 64cb93a386Sopenharmony_ci input.draw(&debugCanvas); 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci ops->setCount(debugCanvas.getSize()); 67cb93a386Sopenharmony_ci for (int i = 0; i < debugCanvas.getSize(); ++i) { 68cb93a386Sopenharmony_ci (*ops)[i] = debugCanvas.getDrawCommandAt(i)->getType(); 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_cienum ClipType { 73cb93a386Sopenharmony_ci kNone_ClipType, 74cb93a386Sopenharmony_ci kRect_ClipType, 75cb93a386Sopenharmony_ci kRRect_ClipType, 76cb93a386Sopenharmony_ci kPath_ClipType, 77cb93a386Sopenharmony_ci kRegion_ClipType, 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci kLast_ClipType = kRRect_ClipType 80cb93a386Sopenharmony_ci}; 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_cistatic const int kClipTypeCount = kLast_ClipType + 1; 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_cienum MatType { 85cb93a386Sopenharmony_ci kNone_MatType, 86cb93a386Sopenharmony_ci kTranslate_MatType, 87cb93a386Sopenharmony_ci kScale_MatType, 88cb93a386Sopenharmony_ci kSkew_MatType, 89cb93a386Sopenharmony_ci kRotate_MatType, 90cb93a386Sopenharmony_ci kConcat_MatType, 91cb93a386Sopenharmony_ci kSetMatrix_MatType, 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci kLast_MatType = kScale_MatType 94cb93a386Sopenharmony_ci}; 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_cistatic const int kMatTypeCount = kLast_MatType + 1; 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci// TODO: implement the rest of the draw ops 99cb93a386Sopenharmony_cienum DrawOpType { 100cb93a386Sopenharmony_ci kNone_DrawOpType, 101cb93a386Sopenharmony_ci#if 0 102cb93a386Sopenharmony_ci kBitmap_DrawOpType, 103cb93a386Sopenharmony_ci kBitmapMatrix_DrawOpType, 104cb93a386Sopenharmony_ci kBitmapNone_DrawOpType, 105cb93a386Sopenharmony_ci kBitmapRectToRect_DrawOpType, 106cb93a386Sopenharmony_ci#endif 107cb93a386Sopenharmony_ci kClear_DrawOpType, 108cb93a386Sopenharmony_ci#if 0 109cb93a386Sopenharmony_ci kData_DrawOpType, 110cb93a386Sopenharmony_ci#endif 111cb93a386Sopenharmony_ci kOval_DrawOpType, 112cb93a386Sopenharmony_ci#if 0 113cb93a386Sopenharmony_ci kPaint_DrawOpType, 114cb93a386Sopenharmony_ci kPath_DrawOpType, 115cb93a386Sopenharmony_ci kPicture_DrawOpType, 116cb93a386Sopenharmony_ci kPoints_DrawOpType, 117cb93a386Sopenharmony_ci kPosText_DrawOpType, 118cb93a386Sopenharmony_ci kPosTextTopBottom_DrawOpType, 119cb93a386Sopenharmony_ci kPosTextH_DrawOpType, 120cb93a386Sopenharmony_ci kPosTextHTopBottom_DrawOpType, 121cb93a386Sopenharmony_ci#endif 122cb93a386Sopenharmony_ci kRect_DrawOpType, 123cb93a386Sopenharmony_ci kRRect_DrawOpType, 124cb93a386Sopenharmony_ci#if 0 125cb93a386Sopenharmony_ci kSprite_DrawOpType, 126cb93a386Sopenharmony_ci kText_DrawOpType, 127cb93a386Sopenharmony_ci kTextOnPath_DrawOpType, 128cb93a386Sopenharmony_ci kTextTopBottom_DrawOpType, 129cb93a386Sopenharmony_ci kDrawVertices_DrawOpType, 130cb93a386Sopenharmony_ci#endif 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci kLastNonSaveLayer_DrawOpType = kRect_DrawOpType, 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci // saveLayer's have to handled apart from the other draw operations 135cb93a386Sopenharmony_ci // since they also alter the save/restore structure. 136cb93a386Sopenharmony_ci kSaveLayer_DrawOpType, 137cb93a386Sopenharmony_ci}; 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_cistatic const int kNonSaveLayerDrawOpTypeCount = kLastNonSaveLayer_DrawOpType + 1; 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_citypedef void (*PFEmitMC)(SkCanvas* canvas, MatType mat, ClipType clip, 142cb93a386Sopenharmony_ci DrawOpType draw, SkTDArray<DrawType>* expected, 143cb93a386Sopenharmony_ci int accumulatedClips); 144cb93a386Sopenharmony_citypedef void (*PFEmitBody)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, 145cb93a386Sopenharmony_ci ClipType clip, DrawOpType draw, 146cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected, int accumulatedClips); 147cb93a386Sopenharmony_citypedef void (*PFEmitStruct)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, 148cb93a386Sopenharmony_ci ClipType clip, PFEmitBody emitBody, DrawOpType draw, 149cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected); 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci// TODO: expand the testing to include the different ops & AA types! 154cb93a386Sopenharmony_cistatic void emit_clip(SkCanvas* canvas, ClipType clip) { 155cb93a386Sopenharmony_ci switch (clip) { 156cb93a386Sopenharmony_ci case kNone_ClipType: 157cb93a386Sopenharmony_ci break; 158cb93a386Sopenharmony_ci case kRect_ClipType: { 159cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); 160cb93a386Sopenharmony_ci canvas->clipRect(r, SkRegion::kIntersect_Op, true); 161cb93a386Sopenharmony_ci break; 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci case kRRect_ClipType: { 164cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); 165cb93a386Sopenharmony_ci SkRRect rr; 166cb93a386Sopenharmony_ci rr.setRectXY(r, 10, 10); 167cb93a386Sopenharmony_ci canvas->clipRRect(rr, SkRegion::kIntersect_Op, true); 168cb93a386Sopenharmony_ci break; 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci case kPath_ClipType: { 171cb93a386Sopenharmony_ci SkPath p; 172cb93a386Sopenharmony_ci p.moveTo(5.0f, 5.0f); 173cb93a386Sopenharmony_ci p.lineTo(50.0f, 50.0f); 174cb93a386Sopenharmony_ci p.lineTo(100.0f, 5.0f); 175cb93a386Sopenharmony_ci p.close(); 176cb93a386Sopenharmony_ci canvas->clipPath(p, SkRegion::kIntersect_Op, true); 177cb93a386Sopenharmony_ci break; 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci case kRegion_ClipType: { 180cb93a386Sopenharmony_ci SkIRect rects[2] = { 181cb93a386Sopenharmony_ci { 1, 1, 55, 55 }, 182cb93a386Sopenharmony_ci { 45, 45, 99, 99 }, 183cb93a386Sopenharmony_ci }; 184cb93a386Sopenharmony_ci SkRegion r; 185cb93a386Sopenharmony_ci r.setRects(rects, 2); 186cb93a386Sopenharmony_ci canvas->clipRegion(r, SkRegion::kIntersect_Op); 187cb93a386Sopenharmony_ci break; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci default: 190cb93a386Sopenharmony_ci SkASSERT(0); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci} 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_cistatic void add_clip(ClipType clip, MatType mat, SkTDArray<DrawType>* expected) { 195cb93a386Sopenharmony_ci if (nullptr == expected) { 196cb93a386Sopenharmony_ci // expected is nullptr if this clip will be fused into later clips 197cb93a386Sopenharmony_ci return; 198cb93a386Sopenharmony_ci } 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci switch (clip) { 201cb93a386Sopenharmony_ci case kNone_ClipType: 202cb93a386Sopenharmony_ci break; 203cb93a386Sopenharmony_ci case kRect_ClipType: 204cb93a386Sopenharmony_ci *expected->append() = CONCAT; 205cb93a386Sopenharmony_ci *expected->append() = CLIP_RECT; 206cb93a386Sopenharmony_ci break; 207cb93a386Sopenharmony_ci case kRRect_ClipType: 208cb93a386Sopenharmony_ci *expected->append() = CONCAT; 209cb93a386Sopenharmony_ci *expected->append() = CLIP_RRECT; 210cb93a386Sopenharmony_ci break; 211cb93a386Sopenharmony_ci case kPath_ClipType: 212cb93a386Sopenharmony_ci *expected->append() = CONCAT; 213cb93a386Sopenharmony_ci *expected->append() = CLIP_PATH; 214cb93a386Sopenharmony_ci break; 215cb93a386Sopenharmony_ci case kRegion_ClipType: 216cb93a386Sopenharmony_ci *expected->append() = CONCAT; 217cb93a386Sopenharmony_ci *expected->append() = CLIP_REGION; 218cb93a386Sopenharmony_ci break; 219cb93a386Sopenharmony_ci default: 220cb93a386Sopenharmony_ci SkASSERT(0); 221cb93a386Sopenharmony_ci } 222cb93a386Sopenharmony_ci} 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_cistatic void emit_mat(SkCanvas* canvas, MatType mat) { 225cb93a386Sopenharmony_ci switch (mat) { 226cb93a386Sopenharmony_ci case kNone_MatType: 227cb93a386Sopenharmony_ci break; 228cb93a386Sopenharmony_ci case kTranslate_MatType: 229cb93a386Sopenharmony_ci canvas->translate(5.0f, 5.0f); 230cb93a386Sopenharmony_ci break; 231cb93a386Sopenharmony_ci case kScale_MatType: 232cb93a386Sopenharmony_ci canvas->scale(1.1f, 1.1f); 233cb93a386Sopenharmony_ci break; 234cb93a386Sopenharmony_ci case kSkew_MatType: 235cb93a386Sopenharmony_ci canvas->skew(1.1f, 1.1f); 236cb93a386Sopenharmony_ci break; 237cb93a386Sopenharmony_ci case kRotate_MatType: 238cb93a386Sopenharmony_ci canvas->rotate(1.0f); 239cb93a386Sopenharmony_ci break; 240cb93a386Sopenharmony_ci case kConcat_MatType: { 241cb93a386Sopenharmony_ci SkMatrix m; 242cb93a386Sopenharmony_ci m.setTranslate(1.0f, 1.0f); 243cb93a386Sopenharmony_ci canvas->concat(m); 244cb93a386Sopenharmony_ci break; 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci case kSetMatrix_MatType: { 247cb93a386Sopenharmony_ci SkMatrix m; 248cb93a386Sopenharmony_ci m.setTranslate(1.0f, 1.0f); 249cb93a386Sopenharmony_ci canvas->setMatrix(m); 250cb93a386Sopenharmony_ci break; 251cb93a386Sopenharmony_ci } 252cb93a386Sopenharmony_ci default: 253cb93a386Sopenharmony_ci SkASSERT(0); 254cb93a386Sopenharmony_ci } 255cb93a386Sopenharmony_ci} 256cb93a386Sopenharmony_ci 257cb93a386Sopenharmony_cistatic void add_mat(MatType mat, SkTDArray<DrawType>* expected) { 258cb93a386Sopenharmony_ci if (nullptr == expected) { 259cb93a386Sopenharmony_ci // expected is nullptr if this matrix call will be fused into later ones 260cb93a386Sopenharmony_ci return; 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ci switch (mat) { 264cb93a386Sopenharmony_ci case kNone_MatType: 265cb93a386Sopenharmony_ci break; 266cb93a386Sopenharmony_ci case kTranslate_MatType: // fall thru 267cb93a386Sopenharmony_ci case kScale_MatType: // fall thru 268cb93a386Sopenharmony_ci case kSkew_MatType: // fall thru 269cb93a386Sopenharmony_ci case kRotate_MatType: // fall thru 270cb93a386Sopenharmony_ci case kConcat_MatType: // fall thru 271cb93a386Sopenharmony_ci case kSetMatrix_MatType: 272cb93a386Sopenharmony_ci // TODO: this system currently converts a setMatrix to concat. If we wanted to 273cb93a386Sopenharmony_ci // really preserve the setMatrix semantics we should keep it a setMatrix. I'm 274cb93a386Sopenharmony_ci // not sure if this is a good idea though since this would keep things like pinch 275cb93a386Sopenharmony_ci // zoom from working. 276cb93a386Sopenharmony_ci *expected->append() = CONCAT; 277cb93a386Sopenharmony_ci break; 278cb93a386Sopenharmony_ci default: 279cb93a386Sopenharmony_ci SkASSERT(0); 280cb93a386Sopenharmony_ci } 281cb93a386Sopenharmony_ci} 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_cistatic void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* expected) { 284cb93a386Sopenharmony_ci switch (draw) { 285cb93a386Sopenharmony_ci case kNone_DrawOpType: 286cb93a386Sopenharmony_ci break; 287cb93a386Sopenharmony_ci case kClear_DrawOpType: 288cb93a386Sopenharmony_ci canvas->clear(SK_ColorRED); 289cb93a386Sopenharmony_ci *expected->append() = DRAW_CLEAR; 290cb93a386Sopenharmony_ci break; 291cb93a386Sopenharmony_ci case kOval_DrawOpType: { 292cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); 293cb93a386Sopenharmony_ci SkPaint p; 294cb93a386Sopenharmony_ci canvas->drawOval(r, p); 295cb93a386Sopenharmony_ci *expected->append() = DRAW_OVAL; 296cb93a386Sopenharmony_ci break; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci case kRect_DrawOpType: { 299cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); 300cb93a386Sopenharmony_ci SkPaint p; 301cb93a386Sopenharmony_ci canvas->drawRect(r, p); 302cb93a386Sopenharmony_ci *expected->append() = DRAW_RECT; 303cb93a386Sopenharmony_ci break; 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci case kRRect_DrawOpType: { 306cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(10.0f, 10.0f, 90.0f, 90.0f); 307cb93a386Sopenharmony_ci SkRRect rr; 308cb93a386Sopenharmony_ci rr.setRectXY(r, 5.0f, 5.0f); 309cb93a386Sopenharmony_ci SkPaint p; 310cb93a386Sopenharmony_ci canvas->drawRRect(rr, p); 311cb93a386Sopenharmony_ci *expected->append() = DRAW_RRECT; 312cb93a386Sopenharmony_ci break; 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci default: 315cb93a386Sopenharmony_ci SkASSERT(0); 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci} 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci// Emit: 322cb93a386Sopenharmony_ci// clip 323cb93a386Sopenharmony_ci// matrix 324cb93a386Sopenharmony_ci// Simple case - the clip isn't effect by the matrix 325cb93a386Sopenharmony_cistatic void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip, 326cb93a386Sopenharmony_ci DrawOpType draw, SkTDArray<DrawType>* expected, 327cb93a386Sopenharmony_ci int accumulatedClips) { 328cb93a386Sopenharmony_ci emit_clip(canvas, clip); 329cb93a386Sopenharmony_ci emit_mat(canvas, mat); 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_ci if (kNone_DrawOpType == draw) { 332cb93a386Sopenharmony_ci return; 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci for (int i = 0; i < accumulatedClips; ++i) { 336cb93a386Sopenharmony_ci add_clip(clip, mat, expected); 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci add_mat(mat, expected); 339cb93a386Sopenharmony_ci} 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci// Emit: 342cb93a386Sopenharmony_ci// matrix 343cb93a386Sopenharmony_ci// clip 344cb93a386Sopenharmony_ci// Emitting the matrix first is more challenging since the matrix has to be 345cb93a386Sopenharmony_ci// pushed across (i.e., applied to) the clip. 346cb93a386Sopenharmony_cistatic void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip, 347cb93a386Sopenharmony_ci DrawOpType draw, SkTDArray<DrawType>* expected, 348cb93a386Sopenharmony_ci int accumulatedClips) { 349cb93a386Sopenharmony_ci emit_mat(canvas, mat); 350cb93a386Sopenharmony_ci emit_clip(canvas, clip); 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_ci if (kNone_DrawOpType == draw) { 353cb93a386Sopenharmony_ci return; 354cb93a386Sopenharmony_ci } 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci // the matrix & clip order will be reversed once collapsed! 357cb93a386Sopenharmony_ci for (int i = 0; i < accumulatedClips; ++i) { 358cb93a386Sopenharmony_ci add_clip(clip, mat, expected); 359cb93a386Sopenharmony_ci } 360cb93a386Sopenharmony_ci add_mat(mat, expected); 361cb93a386Sopenharmony_ci} 362cb93a386Sopenharmony_ci 363cb93a386Sopenharmony_ci// Emit: 364cb93a386Sopenharmony_ci// matrix 365cb93a386Sopenharmony_ci// clip 366cb93a386Sopenharmony_ci// matrix 367cb93a386Sopenharmony_ci// clip 368cb93a386Sopenharmony_ci// This tests that the matrices and clips coalesce when collapsed 369cb93a386Sopenharmony_cistatic void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip, 370cb93a386Sopenharmony_ci DrawOpType draw, SkTDArray<DrawType>* expected, 371cb93a386Sopenharmony_ci int accumulatedClips) { 372cb93a386Sopenharmony_ci emit_mat(canvas, mat); 373cb93a386Sopenharmony_ci emit_clip(canvas, clip); 374cb93a386Sopenharmony_ci emit_mat(canvas, mat); 375cb93a386Sopenharmony_ci emit_clip(canvas, clip); 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ci if (kNone_DrawOpType == draw) { 378cb93a386Sopenharmony_ci return; 379cb93a386Sopenharmony_ci } 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ci for (int i = 0; i < accumulatedClips; ++i) { 382cb93a386Sopenharmony_ci add_clip(clip, mat, expected); 383cb93a386Sopenharmony_ci add_clip(clip, mat, expected); 384cb93a386Sopenharmony_ci } 385cb93a386Sopenharmony_ci add_mat(mat, expected); 386cb93a386Sopenharmony_ci} 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci// Emit: 389cb93a386Sopenharmony_ci// matrix 390cb93a386Sopenharmony_ci// clip 391cb93a386Sopenharmony_ci// clip 392cb93a386Sopenharmony_ci// This tests accumulation of clips in same transform state. It also tests pushing 393cb93a386Sopenharmony_ci// of the matrix across both the clips. 394cb93a386Sopenharmony_cistatic void emit_mat_clip_clip(SkCanvas* canvas, MatType mat, ClipType clip, 395cb93a386Sopenharmony_ci DrawOpType draw, SkTDArray<DrawType>* expected, 396cb93a386Sopenharmony_ci int accumulatedClips) { 397cb93a386Sopenharmony_ci emit_mat(canvas, mat); 398cb93a386Sopenharmony_ci emit_clip(canvas, clip); 399cb93a386Sopenharmony_ci emit_clip(canvas, clip); 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci if (kNone_DrawOpType == draw) { 402cb93a386Sopenharmony_ci return; 403cb93a386Sopenharmony_ci } 404cb93a386Sopenharmony_ci 405cb93a386Sopenharmony_ci for (int i = 0; i < accumulatedClips; ++i) { 406cb93a386Sopenharmony_ci add_clip(clip, mat, expected); 407cb93a386Sopenharmony_ci add_clip(clip, mat, expected); 408cb93a386Sopenharmony_ci } 409cb93a386Sopenharmony_ci add_mat(mat, expected); 410cb93a386Sopenharmony_ci} 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 413cb93a386Sopenharmony_ci 414cb93a386Sopenharmony_ci// Emit: 415cb93a386Sopenharmony_ci// matrix & clip calls 416cb93a386Sopenharmony_ci// draw op 417cb93a386Sopenharmony_cistatic void emit_body0(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, 418cb93a386Sopenharmony_ci ClipType clip, DrawOpType draw, 419cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected, int accumulatedClips) { 420cb93a386Sopenharmony_ci bool needsSaveRestore = kNone_DrawOpType != draw && 421cb93a386Sopenharmony_ci (kNone_MatType != mat || kNone_ClipType != clip); 422cb93a386Sopenharmony_ci 423cb93a386Sopenharmony_ci if (needsSaveRestore) { 424cb93a386Sopenharmony_ci *expected->append() = SAVE; 425cb93a386Sopenharmony_ci } 426cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1); 427cb93a386Sopenharmony_ci emit_draw(canvas, draw, expected); 428cb93a386Sopenharmony_ci if (needsSaveRestore) { 429cb93a386Sopenharmony_ci *expected->append() = RESTORE; 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci} 432cb93a386Sopenharmony_ci 433cb93a386Sopenharmony_ci// Emit: 434cb93a386Sopenharmony_ci// matrix & clip calls 435cb93a386Sopenharmony_ci// draw op 436cb93a386Sopenharmony_ci// matrix & clip calls 437cb93a386Sopenharmony_ci// draw op 438cb93a386Sopenharmony_cistatic void emit_body1(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, 439cb93a386Sopenharmony_ci ClipType clip, DrawOpType draw, 440cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected, int accumulatedClips) { 441cb93a386Sopenharmony_ci bool needsSaveRestore = kNone_DrawOpType != draw && 442cb93a386Sopenharmony_ci (kNone_MatType != mat || kNone_ClipType != clip); 443cb93a386Sopenharmony_ci 444cb93a386Sopenharmony_ci if (needsSaveRestore) { 445cb93a386Sopenharmony_ci *expected->append() = SAVE; 446cb93a386Sopenharmony_ci } 447cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1); 448cb93a386Sopenharmony_ci emit_draw(canvas, draw, expected); 449cb93a386Sopenharmony_ci if (needsSaveRestore) { 450cb93a386Sopenharmony_ci *expected->append() = RESTORE; 451cb93a386Sopenharmony_ci *expected->append() = SAVE; 452cb93a386Sopenharmony_ci } 453cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2); 454cb93a386Sopenharmony_ci emit_draw(canvas, draw, expected); 455cb93a386Sopenharmony_ci if (needsSaveRestore) { 456cb93a386Sopenharmony_ci *expected->append() = RESTORE; 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci} 459cb93a386Sopenharmony_ci 460cb93a386Sopenharmony_ci// Emit: 461cb93a386Sopenharmony_ci// matrix & clip calls 462cb93a386Sopenharmony_ci// SaveLayer 463cb93a386Sopenharmony_ci// matrix & clip calls 464cb93a386Sopenharmony_ci// draw op 465cb93a386Sopenharmony_ci// Restore 466cb93a386Sopenharmony_cistatic void emit_body2(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, 467cb93a386Sopenharmony_ci ClipType clip, DrawOpType draw, 468cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected, int accumulatedClips) { 469cb93a386Sopenharmony_ci bool needsSaveRestore = kNone_DrawOpType != draw && 470cb93a386Sopenharmony_ci (kNone_MatType != mat || kNone_ClipType != clip); 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci if (kNone_MatType != mat || kNone_ClipType != clip) { 473cb93a386Sopenharmony_ci *expected->append() = SAVE; 474cb93a386Sopenharmony_ci } 475cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, accumulatedClips+1); 476cb93a386Sopenharmony_ci *expected->append() = SAVE_LAYER; 477cb93a386Sopenharmony_ci // TODO: widen testing to exercise saveLayer's parameters 478cb93a386Sopenharmony_ci canvas->saveLayer(nullptr, nullptr); 479cb93a386Sopenharmony_ci if (needsSaveRestore) { 480cb93a386Sopenharmony_ci *expected->append() = SAVE; 481cb93a386Sopenharmony_ci } 482cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, expected, 1); 483cb93a386Sopenharmony_ci emit_draw(canvas, draw, expected); 484cb93a386Sopenharmony_ci if (needsSaveRestore) { 485cb93a386Sopenharmony_ci *expected->append() = RESTORE; 486cb93a386Sopenharmony_ci } 487cb93a386Sopenharmony_ci canvas->restore(); 488cb93a386Sopenharmony_ci *expected->append() = RESTORE; 489cb93a386Sopenharmony_ci if (kNone_MatType != mat || kNone_ClipType != clip) { 490cb93a386Sopenharmony_ci *expected->append() = RESTORE; 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci} 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci// Emit: 495cb93a386Sopenharmony_ci// matrix & clip calls 496cb93a386Sopenharmony_ci// SaveLayer 497cb93a386Sopenharmony_ci// matrix & clip calls 498cb93a386Sopenharmony_ci// SaveLayer 499cb93a386Sopenharmony_ci// matrix & clip calls 500cb93a386Sopenharmony_ci// draw op 501cb93a386Sopenharmony_ci// Restore 502cb93a386Sopenharmony_ci// matrix & clip calls (will be ignored) 503cb93a386Sopenharmony_ci// Restore 504cb93a386Sopenharmony_cistatic void emit_body3(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, 505cb93a386Sopenharmony_ci ClipType clip, DrawOpType draw, 506cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected, int accumulatedClips) { 507cb93a386Sopenharmony_ci bool needsSaveRestore = kNone_DrawOpType != draw && 508cb93a386Sopenharmony_ci (kNone_MatType != mat || kNone_ClipType != clip); 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci if (kNone_MatType != mat || kNone_ClipType != clip) { 511cb93a386Sopenharmony_ci *expected->append() = SAVE; 512cb93a386Sopenharmony_ci } 513cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, accumulatedClips+1); 514cb93a386Sopenharmony_ci *expected->append() = SAVE_LAYER; 515cb93a386Sopenharmony_ci // TODO: widen testing to exercise saveLayer's parameters 516cb93a386Sopenharmony_ci canvas->saveLayer(nullptr, nullptr); 517cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, 1); 518cb93a386Sopenharmony_ci if (kNone_MatType != mat || kNone_ClipType != clip) { 519cb93a386Sopenharmony_ci *expected->append() = SAVE; 520cb93a386Sopenharmony_ci } 521cb93a386Sopenharmony_ci *expected->append() = SAVE_LAYER; 522cb93a386Sopenharmony_ci // TODO: widen testing to exercise saveLayer's parameters 523cb93a386Sopenharmony_ci canvas->saveLayer(nullptr, nullptr); 524cb93a386Sopenharmony_ci if (needsSaveRestore) { 525cb93a386Sopenharmony_ci *expected->append() = SAVE; 526cb93a386Sopenharmony_ci } 527cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, expected, 1); 528cb93a386Sopenharmony_ci emit_draw(canvas, draw, expected); 529cb93a386Sopenharmony_ci if (needsSaveRestore) { 530cb93a386Sopenharmony_ci *expected->append() = RESTORE; 531cb93a386Sopenharmony_ci } 532cb93a386Sopenharmony_ci canvas->restore(); // for saveLayer 533cb93a386Sopenharmony_ci *expected->append() = RESTORE; // for saveLayer 534cb93a386Sopenharmony_ci if (kNone_MatType != mat || kNone_ClipType != clip) { 535cb93a386Sopenharmony_ci *expected->append() = RESTORE; 536cb93a386Sopenharmony_ci } 537cb93a386Sopenharmony_ci canvas->restore(); 538cb93a386Sopenharmony_ci // required to match forced SAVE_LAYER 539cb93a386Sopenharmony_ci *expected->append() = RESTORE; 540cb93a386Sopenharmony_ci if (kNone_MatType != mat || kNone_ClipType != clip) { 541cb93a386Sopenharmony_ci *expected->append() = RESTORE; 542cb93a386Sopenharmony_ci } 543cb93a386Sopenharmony_ci} 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 546cb93a386Sopenharmony_ci 547cb93a386Sopenharmony_ci// Emit: 548cb93a386Sopenharmony_ci// Save 549cb93a386Sopenharmony_ci// some body 550cb93a386Sopenharmony_ci// Restore 551cb93a386Sopenharmony_ci// Note: the outer save/restore are provided by beginRecording/endRecording 552cb93a386Sopenharmony_cistatic void emit_struct0(SkCanvas* canvas, 553cb93a386Sopenharmony_ci PFEmitMC emitMC, MatType mat, ClipType clip, 554cb93a386Sopenharmony_ci PFEmitBody emitBody, DrawOpType draw, 555cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected) { 556cb93a386Sopenharmony_ci (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 0); 557cb93a386Sopenharmony_ci} 558cb93a386Sopenharmony_ci 559cb93a386Sopenharmony_ci// Emit: 560cb93a386Sopenharmony_ci// Save 561cb93a386Sopenharmony_ci// matrix & clip calls 562cb93a386Sopenharmony_ci// Save 563cb93a386Sopenharmony_ci// some body 564cb93a386Sopenharmony_ci// Restore 565cb93a386Sopenharmony_ci// matrix & clip calls (will be ignored) 566cb93a386Sopenharmony_ci// Restore 567cb93a386Sopenharmony_ci// Note: the outer save/restore are provided by beginRecording/endRecording 568cb93a386Sopenharmony_cistatic void emit_struct1(SkCanvas* canvas, 569cb93a386Sopenharmony_ci PFEmitMC emitMC, MatType mat, ClipType clip, 570cb93a386Sopenharmony_ci PFEmitBody emitBody, DrawOpType draw, 571cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected) { 572cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these get fused into later ops 573cb93a386Sopenharmony_ci canvas->save(); 574cb93a386Sopenharmony_ci (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); 575cb93a386Sopenharmony_ci canvas->restore(); 576cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these will get removed 577cb93a386Sopenharmony_ci} 578cb93a386Sopenharmony_ci 579cb93a386Sopenharmony_ci// Emit: 580cb93a386Sopenharmony_ci// Save 581cb93a386Sopenharmony_ci// matrix & clip calls 582cb93a386Sopenharmony_ci// Save 583cb93a386Sopenharmony_ci// some body 584cb93a386Sopenharmony_ci// Restore 585cb93a386Sopenharmony_ci// Save 586cb93a386Sopenharmony_ci// some body 587cb93a386Sopenharmony_ci// Restore 588cb93a386Sopenharmony_ci// matrix & clip calls (will be ignored) 589cb93a386Sopenharmony_ci// Restore 590cb93a386Sopenharmony_ci// Note: the outer save/restore are provided by beginRecording/endRecording 591cb93a386Sopenharmony_cistatic void emit_struct2(SkCanvas* canvas, 592cb93a386Sopenharmony_ci PFEmitMC emitMC, MatType mat, ClipType clip, 593cb93a386Sopenharmony_ci PFEmitBody emitBody, DrawOpType draw, 594cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected) { 595cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 1); // these will get fused into later ops 596cb93a386Sopenharmony_ci canvas->save(); 597cb93a386Sopenharmony_ci (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); 598cb93a386Sopenharmony_ci canvas->restore(); 599cb93a386Sopenharmony_ci canvas->save(); 600cb93a386Sopenharmony_ci (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); 601cb93a386Sopenharmony_ci canvas->restore(); 602cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 1); // these will get removed 603cb93a386Sopenharmony_ci} 604cb93a386Sopenharmony_ci 605cb93a386Sopenharmony_ci// Emit: 606cb93a386Sopenharmony_ci// Save 607cb93a386Sopenharmony_ci// matrix & clip calls 608cb93a386Sopenharmony_ci// Save 609cb93a386Sopenharmony_ci// some body 610cb93a386Sopenharmony_ci// Restore 611cb93a386Sopenharmony_ci// Save 612cb93a386Sopenharmony_ci// matrix & clip calls 613cb93a386Sopenharmony_ci// Save 614cb93a386Sopenharmony_ci// some body 615cb93a386Sopenharmony_ci// Restore 616cb93a386Sopenharmony_ci// Restore 617cb93a386Sopenharmony_ci// matrix & clip calls (will be ignored) 618cb93a386Sopenharmony_ci// Restore 619cb93a386Sopenharmony_ci// Note: the outer save/restore are provided by beginRecording/endRecording 620cb93a386Sopenharmony_cistatic void emit_struct3(SkCanvas* canvas, 621cb93a386Sopenharmony_ci PFEmitMC emitMC, MatType mat, ClipType clip, 622cb93a386Sopenharmony_ci PFEmitBody emitBody, DrawOpType draw, 623cb93a386Sopenharmony_ci SkTDArray<DrawType>* expected) { 624cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these will get fused into later ops 625cb93a386Sopenharmony_ci canvas->save(); 626cb93a386Sopenharmony_ci (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); 627cb93a386Sopenharmony_ci canvas->restore(); 628cb93a386Sopenharmony_ci canvas->save(); 629cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 1); // these will get fused into later ops 630cb93a386Sopenharmony_ci canvas->save(); 631cb93a386Sopenharmony_ci (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 2); 632cb93a386Sopenharmony_ci canvas->restore(); 633cb93a386Sopenharmony_ci canvas->restore(); 634cb93a386Sopenharmony_ci (*emitMC)(canvas, mat, clip, draw, nullptr, 0); // these will get removed 635cb93a386Sopenharmony_ci} 636cb93a386Sopenharmony_ci 637cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_ci#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE 640cb93a386Sopenharmony_cistatic void print(const SkTDArray<DrawType>& expected, const SkTDArray<DrawType>& actual) { 641cb93a386Sopenharmony_ci SkDebugf("\n\nexpected %d --- actual %d\n", expected.count(), actual.count()); 642cb93a386Sopenharmony_ci int max = std::max(expected.count(), actual.count()); 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_ci for (int i = 0; i < max; ++i) { 645cb93a386Sopenharmony_ci if (i < expected.count()) { 646cb93a386Sopenharmony_ci SkDebugf("%16s, ", DrawCommand::GetCommandString(expected[i])); 647cb93a386Sopenharmony_ci } else { 648cb93a386Sopenharmony_ci SkDebugf("%16s, ", " "); 649cb93a386Sopenharmony_ci } 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_ci if (i < actual.count()) { 652cb93a386Sopenharmony_ci SkDebugf("%s\n", DrawCommand::GetCommandString(actual[i])); 653cb93a386Sopenharmony_ci } else { 654cb93a386Sopenharmony_ci SkDebugf("\n"); 655cb93a386Sopenharmony_ci } 656cb93a386Sopenharmony_ci } 657cb93a386Sopenharmony_ci SkDebugf("\n\n"); 658cb93a386Sopenharmony_ci SkASSERT(0); 659cb93a386Sopenharmony_ci} 660cb93a386Sopenharmony_ci#endif 661cb93a386Sopenharmony_ci 662cb93a386Sopenharmony_cistatic void test_collapse(skiatest::Reporter* reporter) { 663cb93a386Sopenharmony_ci PFEmitStruct gStructure[] = { emit_struct0, emit_struct1, emit_struct2, emit_struct3 }; 664cb93a386Sopenharmony_ci PFEmitBody gBody[] = { emit_body0, emit_body1, emit_body2, emit_body3 }; 665cb93a386Sopenharmony_ci PFEmitMC gMCs[] = { emit_clip_and_mat, emit_mat_and_clip, 666cb93a386Sopenharmony_ci emit_double_mat_and_clip, emit_mat_clip_clip }; 667cb93a386Sopenharmony_ci 668cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gStructure); ++i) { 669cb93a386Sopenharmony_ci for (size_t j = 0; j < SK_ARRAY_COUNT(gBody); ++j) { 670cb93a386Sopenharmony_ci for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) { 671cb93a386Sopenharmony_ci for (int l = 0; l < kMatTypeCount; ++l) { 672cb93a386Sopenharmony_ci for (int m = 0; m < kClipTypeCount; ++m) { 673cb93a386Sopenharmony_ci for (int n = 0; n < kNonSaveLayerDrawOpTypeCount; ++n) { 674cb93a386Sopenharmony_ci#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE 675cb93a386Sopenharmony_ci static int testID = -1; 676cb93a386Sopenharmony_ci ++testID; 677cb93a386Sopenharmony_ci if (testID < -1) { 678cb93a386Sopenharmony_ci continue; 679cb93a386Sopenharmony_ci } 680cb93a386Sopenharmony_ci SkDebugf("test: %d\n", testID); 681cb93a386Sopenharmony_ci#endif 682cb93a386Sopenharmony_ci 683cb93a386Sopenharmony_ci SkTDArray<DrawType> expected, actual; 684cb93a386Sopenharmony_ci 685cb93a386Sopenharmony_ci SkPicture picture; 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_ci // Note: beginRecording/endRecording add a save/restore pair 688cb93a386Sopenharmony_ci SkCanvas* canvas = picture.beginRecording(100, 100); 689cb93a386Sopenharmony_ci (*gStructure[i])(canvas, 690cb93a386Sopenharmony_ci gMCs[k], 691cb93a386Sopenharmony_ci (MatType) l, 692cb93a386Sopenharmony_ci (ClipType) m, 693cb93a386Sopenharmony_ci gBody[j], 694cb93a386Sopenharmony_ci (DrawOpType) n, 695cb93a386Sopenharmony_ci &expected); 696cb93a386Sopenharmony_ci picture.endRecording(); 697cb93a386Sopenharmony_ci 698cb93a386Sopenharmony_ci gets_ops(picture, &actual); 699cb93a386Sopenharmony_ci 700cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expected.count() == actual.count()); 701cb93a386Sopenharmony_ci 702cb93a386Sopenharmony_ci if (expected.count() != actual.count()) { 703cb93a386Sopenharmony_ci#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE 704cb93a386Sopenharmony_ci print(expected, actual); 705cb93a386Sopenharmony_ci#endif 706cb93a386Sopenharmony_ci continue; 707cb93a386Sopenharmony_ci } 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci for (int i = 0; i < expected.count(); ++i) { 710cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expected[i] == actual[i]); 711cb93a386Sopenharmony_ci#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE 712cb93a386Sopenharmony_ci if (expected[i] != actual[i]) { 713cb93a386Sopenharmony_ci print(expected, actual); 714cb93a386Sopenharmony_ci } 715cb93a386Sopenharmony_ci#endif 716cb93a386Sopenharmony_ci break; 717cb93a386Sopenharmony_ci } 718cb93a386Sopenharmony_ci } 719cb93a386Sopenharmony_ci } 720cb93a386Sopenharmony_ci } 721cb93a386Sopenharmony_ci } 722cb93a386Sopenharmony_ci } 723cb93a386Sopenharmony_ci } 724cb93a386Sopenharmony_ci} 725cb93a386Sopenharmony_ci 726cb93a386Sopenharmony_ciDEF_TEST(MatrixClipCollapse, reporter) { 727cb93a386Sopenharmony_ci test_collapse(reporter); 728cb93a386Sopenharmony_ci} 729cb93a386Sopenharmony_ci 730cb93a386Sopenharmony_ci#endif 731