1/* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "gm.h" 9#include "sk_tool_utils.h" 10#include "SkAAClip.h" 11#include "SkCanvas.h" 12#include "SkPath.h" 13 14namespace skiagm { 15 16static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip, 17 const SkPaint& paint) { 18 SkMask mask; 19 SkBitmap bm; 20 21 clip.copyToMask(&mask); 22 23 SkAutoMaskFreeImage amfi(mask.fImage); 24 25 bm.installMaskPixels(mask); 26 27 // need to copy for deferred drawing test to work 28 SkBitmap bm2; 29 30 sk_tool_utils::copy_to(&bm2, bm.colorType(), bm); 31 32 canvas->drawBitmap(bm2, 33 SK_Scalar1 * mask.fBounds.fLeft, 34 SK_Scalar1 * mask.fBounds.fTop, 35 &paint); 36} 37 38////////////////////////////////////////////////////////////////////////////// 39/* 40 * This GM tests anti aliased single operation booleans with SkAAClips, 41 * SkRect and SkPaths. 42 */ 43class SimpleClipGM : public GM { 44public: 45 enum SkGeomTypes { 46 kRect_GeomType, 47 kPath_GeomType, 48 kAAClip_GeomType 49 }; 50 51 SimpleClipGM(SkGeomTypes geomType) 52 : fGeomType(geomType) { 53 } 54 55protected: 56 void onOnceBeforeDraw() override { 57 // offset the rects a bit so we get anti-aliasing in the rect case 58 fBase.set(100.65f, 59 100.65f, 60 150.65f, 61 150.65f); 62 fRect = fBase; 63 fRect.inset(5, 5); 64 fRect.offset(25, 25); 65 66 fBasePath.addRoundRect(fBase, SkIntToScalar(5), SkIntToScalar(5)); 67 fRectPath.addRoundRect(fRect, SkIntToScalar(5), SkIntToScalar(5)); 68 INHERITED::setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); 69 } 70 71 void buildRgn(SkAAClip* clip, SkClipOp op) { 72 clip->setPath(fBasePath, nullptr, true); 73 74 SkAAClip clip2; 75 clip2.setPath(fRectPath, nullptr, true); 76 clip->op(clip2, (SkRegion::Op)op); 77 } 78 79 void drawOrig(SkCanvas* canvas) { 80 SkPaint paint; 81 82 paint.setStyle(SkPaint::kStroke_Style); 83 paint.setColor(SK_ColorBLACK); 84 85 canvas->drawRect(fBase, paint); 86 canvas->drawRect(fRect, paint); 87 } 88 89 void drawRgnOped(SkCanvas* canvas, SkClipOp op, SkColor color) { 90 91 SkAAClip clip; 92 93 this->buildRgn(&clip, op); 94 this->drawOrig(canvas); 95 96 SkPaint paint; 97 paint.setColor(color); 98 paint_rgn(canvas, clip, paint); 99 } 100 101 void drawPathsOped(SkCanvas* canvas, SkClipOp op, SkColor color) { 102 103 this->drawOrig(canvas); 104 105 canvas->save(); 106 107 // create the clip mask with the supplied boolean op 108 if (kPath_GeomType == fGeomType) { 109 // path-based case 110 canvas->clipPath(fBasePath, true); 111 canvas->clipPath(fRectPath, op, true); 112 } else { 113 // rect-based case 114 canvas->clipRect(fBase, true); 115 canvas->clipRect(fRect, op, true); 116 } 117 118 // draw a rect that will entirely cover the clip mask area 119 SkPaint paint; 120 paint.setColor(color); 121 122 SkRect r = SkRect::MakeLTRB(SkIntToScalar(90), SkIntToScalar(90), 123 SkIntToScalar(180), SkIntToScalar(180)); 124 125 canvas->drawRect(r, paint); 126 127 canvas->restore(); 128 } 129 130 SkString onShortName() override { 131 SkString str; 132 str.printf("simpleaaclip_%s", 133 kRect_GeomType == fGeomType ? "rect" : 134 (kPath_GeomType == fGeomType ? "path" : 135 "aaclip")); 136 return str; 137 } 138 139 SkISize onISize() override { 140 return SkISize::Make(640, 480); 141 } 142 143 void onDraw(SkCanvas* canvas) override { 144 145 const struct { 146 SkColor fColor; 147 const char* fName; 148 SkClipOp fOp; 149 } gOps[] = { 150 { SK_ColorBLACK, "Difference", kDifference_SkClipOp }, 151 { SK_ColorRED, "Intersect", kIntersect_SkClipOp }, 152 { sk_tool_utils::color_to_565(0xFF008800), "Union", kUnion_SkClipOp }, 153 { SK_ColorGREEN, "Rev Diff", kReverseDifference_SkClipOp }, 154 { SK_ColorYELLOW, "Replace", kReplace_SkClipOp }, 155 { SK_ColorBLUE, "XOR", kXOR_SkClipOp }, 156 }; 157 158 SkPaint textPaint; 159 textPaint.setAntiAlias(true); 160 sk_tool_utils::set_portable_typeface(&textPaint); 161 textPaint.setTextSize(SK_Scalar1*24); 162 int xOff = 0; 163 164 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) { 165 canvas->drawString(gOps[op].fName, 166 SkIntToScalar(75), SkIntToScalar(50), 167 textPaint); 168 169 if (kAAClip_GeomType == fGeomType) { 170 this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor); 171 } else { 172 this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor); 173 } 174 175 if (xOff >= 400) { 176 canvas->translate(SkIntToScalar(-400), SkIntToScalar(250)); 177 xOff = 0; 178 } else { 179 canvas->translate(SkIntToScalar(200), 0); 180 xOff += 200; 181 } 182 } 183 } 184private: 185 186 SkGeomTypes fGeomType; 187 188 SkRect fBase; 189 SkRect fRect; 190 191 SkPath fBasePath; // fBase as a round rect 192 SkPath fRectPath; // fRect as a round rect 193 194 typedef GM INHERITED; 195}; 196 197////////////////////////////////////////////////////////////////////////////// 198 199// rects 200DEF_GM( return new SimpleClipGM(SimpleClipGM::kRect_GeomType); ) 201DEF_GM( return new SimpleClipGM(SimpleClipGM::kPath_GeomType); ) 202DEF_GM( return new SimpleClipGM(SimpleClipGM::kAAClip_GeomType); ) 203 204} 205