1 2 /* 3 * Copyright 2013 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "Test.h" 10 #include "SkCanvas.h" 11 #include "SkCanvasStateUtils.h" 12 #include "SkDevice.h" 13 #include "SkDrawFilter.h" 14 #include "SkPaint.h" 15 #include "SkRect.h" 16 #include "SkRRect.h" 17 18 static void test_complex_layers(skiatest::Reporter* reporter) { 19 const int WIDTH = 400; 20 const int HEIGHT = 400; 21 const int SPACER = 10; 22 23 SkRect rect = SkRect::MakeXYWH(SPACER, SPACER, WIDTH-(2*SPACER), (HEIGHT-(2*SPACER)) / 7); 24 25 const SkBitmap::Config configs[] = { SkBitmap::kRGB_565_Config, 26 SkBitmap::kARGB_8888_Config 27 }; 28 const int configCount = sizeof(configs) / sizeof(SkBitmap::Config); 29 30 const int layerAlpha[] = { 255, 255, 0 }; 31 const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag, 32 SkCanvas::kARGB_ClipLayer_SaveFlag, 33 SkCanvas::kARGB_NoClipLayer_SaveFlag 34 }; 35 REPORTER_ASSERT(reporter, sizeof(layerAlpha) == sizeof(flags)); 36 const int layerCombinations = sizeof(layerAlpha) / sizeof(int); 37 38 for (int i = 0; i < configCount; ++i) { 39 SkBitmap bitmaps[2]; 40 for (int j = 0; j < 2; ++j) { 41 bitmaps[j].setConfig(configs[i], WIDTH, HEIGHT); 42 bitmaps[j].allocPixels(); 43 44 SkCanvas canvas(bitmaps[j]); 45 46 canvas.drawColor(SK_ColorRED); 47 48 for (int k = 0; k < layerCombinations; ++k) { 49 // draw a rect within the layer's bounds and again outside the layer's bounds 50 canvas.saveLayerAlpha(&rect, layerAlpha[k], flags[k]); 51 52 SkCanvasState* state = NULL; 53 SkCanvas* tmpCanvas = NULL; 54 if (j) { 55 state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 56 REPORTER_ASSERT(reporter, state); 57 tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state); 58 REPORTER_ASSERT(reporter, tmpCanvas); 59 } else { 60 tmpCanvas = SkRef(&canvas); 61 } 62 63 SkPaint bluePaint; 64 bluePaint.setColor(SK_ColorBLUE); 65 bluePaint.setStyle(SkPaint::kFill_Style); 66 67 tmpCanvas->drawRect(rect, bluePaint); 68 tmpCanvas->translate(0, rect.height() + SPACER); 69 tmpCanvas->drawRect(rect, bluePaint); 70 71 tmpCanvas->unref(); 72 SkCanvasStateUtils::ReleaseCanvasState(state); 73 74 canvas.restore(); 75 76 // translate the canvas for the next iteration 77 canvas.translate(0, 2*(rect.height() + SPACER)); 78 } 79 } 80 81 // now we memcmp the two bitmaps 82 REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize()); 83 REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(), 84 bitmaps[1].getPixels(), 85 bitmaps[0].getSize())); 86 } 87 } 88 89 //////////////////////////////////////////////////////////////////////////////// 90 91 static void test_complex_clips(skiatest::Reporter* reporter) { 92 93 const int WIDTH = 400; 94 const int HEIGHT = 400; 95 const SkScalar SPACER = SkIntToScalar(10); 96 97 SkRect layerRect = SkRect::MakeWH(SkIntToScalar(WIDTH), SkIntToScalar(HEIGHT / 4)); 98 layerRect.inset(2*SPACER, 2*SPACER); 99 100 SkRect clipRect = layerRect; 101 clipRect.fRight = clipRect.fLeft + (clipRect.width() / 2) - (2*SPACER); 102 clipRect.outset(SPACER, SPACER); 103 104 SkIRect regionBounds; 105 clipRect.roundIn(®ionBounds); 106 regionBounds.offset(clipRect.width() + (2*SPACER), 0); 107 108 SkIRect regionInterior = regionBounds; 109 regionInterior.inset(SPACER*3, SPACER*3); 110 111 SkRegion clipRegion; 112 clipRegion.setRect(regionBounds); 113 clipRegion.op(regionInterior, SkRegion::kDifference_Op); 114 115 116 const SkRegion::Op clipOps[] = { SkRegion::kIntersect_Op, 117 SkRegion::kIntersect_Op, 118 SkRegion::kReplace_Op, 119 }; 120 const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag, 121 SkCanvas::kARGB_ClipLayer_SaveFlag, 122 SkCanvas::kARGB_NoClipLayer_SaveFlag, 123 }; 124 REPORTER_ASSERT(reporter, sizeof(clipOps) == sizeof(flags)); 125 const int layerCombinations = sizeof(flags) / sizeof(SkCanvas::SaveFlags); 126 127 SkBitmap bitmaps[2]; 128 for (int i = 0; i < 2; ++i) { 129 bitmaps[i].setConfig(SkBitmap::kARGB_8888_Config, WIDTH, HEIGHT); 130 bitmaps[i].allocPixels(); 131 132 SkCanvas canvas(bitmaps[i]); 133 134 canvas.drawColor(SK_ColorRED); 135 136 SkRegion localRegion = clipRegion; 137 138 for (int j = 0; j < layerCombinations; ++j) { 139 canvas.saveLayerAlpha(&layerRect, 128, flags[j]); 140 141 SkCanvasState* state = NULL; 142 SkCanvas* tmpCanvas = NULL; 143 if (i) { 144 state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 145 REPORTER_ASSERT(reporter, state); 146 tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state); 147 REPORTER_ASSERT(reporter, tmpCanvas); 148 } else { 149 tmpCanvas = SkRef(&canvas); 150 } 151 152 tmpCanvas->save(); 153 tmpCanvas->clipRect(clipRect, clipOps[j]); 154 tmpCanvas->drawColor(SK_ColorBLUE); 155 tmpCanvas->restore(); 156 157 tmpCanvas->clipRegion(localRegion, clipOps[j]); 158 tmpCanvas->drawColor(SK_ColorBLUE); 159 160 tmpCanvas->unref(); 161 SkCanvasStateUtils::ReleaseCanvasState(state); 162 163 canvas.restore(); 164 165 // translate the canvas and region for the next iteration 166 canvas.translate(0, 2*(layerRect.height() + SPACER)); 167 localRegion.translate(0, 2*(layerRect.height() + SPACER)); 168 } 169 } 170 171 // now we memcmp the two bitmaps 172 REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize()); 173 REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(), 174 bitmaps[1].getPixels(), 175 bitmaps[0].getSize())); 176 } 177 178 //////////////////////////////////////////////////////////////////////////////// 179 180 class TestDrawFilter : public SkDrawFilter { 181 public: 182 virtual bool filter(SkPaint*, Type) SK_OVERRIDE { return true; } 183 }; 184 185 static void test_draw_filters(skiatest::Reporter* reporter) { 186 TestDrawFilter drawFilter; 187 SkDevice device(SkBitmap::kARGB_8888_Config, 10, 10); 188 SkCanvas canvas(&device); 189 190 canvas.setDrawFilter(&drawFilter); 191 192 SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 193 REPORTER_ASSERT(reporter, state); 194 SkCanvas* tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state); 195 REPORTER_ASSERT(reporter, tmpCanvas); 196 197 REPORTER_ASSERT(reporter, NULL != canvas.getDrawFilter()); 198 REPORTER_ASSERT(reporter, NULL == tmpCanvas->getDrawFilter()); 199 200 tmpCanvas->unref(); 201 SkCanvasStateUtils::ReleaseCanvasState(state); 202 } 203 204 //////////////////////////////////////////////////////////////////////////////// 205 206 static void test_soft_clips(skiatest::Reporter* reporter) { 207 SkDevice device(SkBitmap::kARGB_8888_Config, 10, 10); 208 SkCanvas canvas(&device); 209 210 SkRRect roundRect; 211 roundRect.setOval(SkRect::MakeWH(5, 5)); 212 213 canvas.clipRRect(roundRect, SkRegion::kIntersect_Op, true); 214 215 SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 216 REPORTER_ASSERT(reporter, !state); 217 } 218 219 //////////////////////////////////////////////////////////////////////////////// 220 221 static void test_canvas_state_utils(skiatest::Reporter* reporter) { 222 test_complex_layers(reporter); 223 test_complex_clips(reporter); 224 test_draw_filters(reporter); 225 test_soft_clips(reporter); 226 } 227 228 #include "TestClassDef.h" 229 DEFINE_TESTCLASS("CanvasState", TestCanvasStateClass, test_canvas_state_utils) 230