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