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