2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkBlurMask.h"
10 #include "SkBlurMaskFilter.h"
14 #include "GrContext.h"
17 // Create a black&white checked texture with 2 1-pixel rings
18 // around the outside edge. The inner ring is red and the outer ring is blue.
19 static void make_ringed_bitmap(SkBitmap* result, int width, int height) {
20 SkASSERT(0 == width % 2 && 0 == height % 2);
22 static const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED);
23 static const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE);
24 static const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK);
25 static const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE);
27 result->allocN32Pixels(width, height, true);
29 SkPMColor* scanline = result->getAddr32(0, 0);
30 for (int x = 0; x < width; ++x) {
33 scanline = result->getAddr32(0, 1);
35 for (int x = 1; x < width - 1; ++x) {
38 scanline[width-1] = kBlue;
40 for (int y = 2; y < height/2; ++y) {
41 scanline = result->getAddr32(0, y);
44 for (int x = 2; x < width/2; ++x) {
47 for (int x = width/2; x < width-2; ++x) {
50 scanline[width-2] = kRed;
51 scanline[width-1] = kBlue;
54 for (int y = height/2; y < height-2; ++y) {
55 scanline = result->getAddr32(0, y);
58 for (int x = 2; x < width/2; ++x) {
61 for (int x = width/2; x < width-2; ++x) {
64 scanline[width-2] = kRed;
65 scanline[width-1] = kBlue;
68 scanline = result->getAddr32(0, height-2);
70 for (int x = 1; x < width - 1; ++x) {
73 scanline[width-1] = kBlue;
75 scanline = result->getAddr32(0, height-1);
76 for (int x = 0; x < width; ++x) {
79 result->setImmutable();
82 // This GM exercises the drawBitmapRectToRect "bleed" flag
83 class BleedGM : public skiagm::GM {
89 SkString onShortName() SK_OVERRIDE {
90 return SkString("bleed");
93 SkISize onISize() SK_OVERRIDE {
94 return SkISize::Make(kWidth, 780);
97 void onOnceBeforeDraw() SK_OVERRIDE {
98 make_ringed_bitmap(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize);
100 // To exercise the GPU's tiling path we need a texture
101 // too big for the GPU to handle in one go
102 make_ringed_bitmap(&fBitmapBig, 2*kMaxTextureSize, 2*kMaxTextureSize);
105 // Draw only the center of the small bitmap
106 void drawCase1(SkCanvas* canvas, int transX, int transY,
107 SkCanvas::DrawBitmapRectFlags flags, SkFilterQuality filter) {
108 SkRect src = SkRect::MakeXYWH(2, 2,
109 SkIntToScalar(kSmallTextureSize-4),
110 SkIntToScalar(kSmallTextureSize-4));
111 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
114 paint.setFilterQuality(filter);
117 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
118 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
122 // Draw almost all of the large bitmap
123 void drawCase2(SkCanvas* canvas, int transX, int transY,
124 SkCanvas::DrawBitmapRectFlags flags, SkFilterQuality filter) {
125 SkRect src = SkRect::MakeXYWH(2, 2,
126 SkIntToScalar(fBitmapBig.width()-4),
127 SkIntToScalar(fBitmapBig.height()-4));
128 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
131 paint.setFilterQuality(filter);
134 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
135 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
139 // Draw ~1/4 of the large bitmap
140 void drawCase3(SkCanvas* canvas, int transX, int transY,
141 SkCanvas::DrawBitmapRectFlags flags, SkFilterQuality filter) {
142 SkRect src = SkRect::MakeXYWH(2, 2,
143 SkIntToScalar(fBitmapBig.width()/2-2),
144 SkIntToScalar(fBitmapBig.height()/2-2));
145 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
148 paint.setFilterQuality(filter);
151 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
152 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
156 // Draw the center of the small bitmap with a mask filter
157 void drawCase4(SkCanvas* canvas, int transX, int transY,
158 SkCanvas::DrawBitmapRectFlags flags, SkFilterQuality filter) {
159 SkRect src = SkRect::MakeXYWH(2, 2,
160 SkIntToScalar(kSmallTextureSize-4),
161 SkIntToScalar(kSmallTextureSize-4));
162 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
165 paint.setFilterQuality(filter);
166 SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
167 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)));
168 paint.setMaskFilter(mf)->unref();
171 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
172 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
176 void onDraw(SkCanvas* canvas) SK_OVERRIDE {
178 canvas->clear(SK_ColorGRAY);
180 for (int m = 0; m < 2; ++m) {
183 static const SkScalar kBottom = SkIntToScalar(kRow3Y + kBlockSize + kBlockSpacing);
184 canvas->translate(0, kBottom);
186 rotate.setRotate(15.f, 0, kBottom + kBlockSpacing);
187 canvas->concat(rotate);
188 canvas->scale(0.71f, 1.22f);
191 // First draw a column with no bleeding, tiling, or filtering
192 this->drawCase1(canvas, kCol0X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, kNone_SkFilterQuality);
193 this->drawCase2(canvas, kCol0X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, kNone_SkFilterQuality);
194 this->drawCase3(canvas, kCol0X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, kNone_SkFilterQuality);
195 this->drawCase4(canvas, kCol0X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, kNone_SkFilterQuality);
197 // Then draw a column with no bleeding or tiling but with low filtering
198 this->drawCase1(canvas, kCol1X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
199 this->drawCase2(canvas, kCol1X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
200 this->drawCase3(canvas, kCol1X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
201 this->drawCase4(canvas, kCol1X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
203 // Then draw a column with no bleeding or tiling but with high filtering
204 this->drawCase1(canvas, kCol2X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
205 this->drawCase2(canvas, kCol2X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
206 this->drawCase3(canvas, kCol2X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
207 this->drawCase4(canvas, kCol2X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
210 GrContext* ctx = canvas->getGrContext();
211 int oldMaxTextureSize = 0;
213 // shrink the max texture size so all our textures can be reasonably sized
214 oldMaxTextureSize = ctx->getMaxTextureSize();
215 ctx->setMaxTextureSizeOverride(kMaxTextureSize);
219 // Then draw a column with no bleeding but with tiling and low filtering
220 this->drawCase1(canvas, kCol3X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
221 this->drawCase2(canvas, kCol3X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
222 this->drawCase3(canvas, kCol3X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
223 this->drawCase4(canvas, kCol3X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, kLow_SkFilterQuality);
225 // Then draw a column with no bleeding but with tiling and high filtering
226 this->drawCase1(canvas, kCol4X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
227 this->drawCase2(canvas, kCol4X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
228 this->drawCase3(canvas, kCol4X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
229 this->drawCase4(canvas, kCol4X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, kHigh_SkFilterQuality);
231 // Then draw a column with bleeding, tiling, and low filtering
232 this->drawCase1(canvas, kCol5X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, kLow_SkFilterQuality);
233 this->drawCase2(canvas, kCol5X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, kLow_SkFilterQuality);
234 this->drawCase3(canvas, kCol5X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, kLow_SkFilterQuality);
235 this->drawCase4(canvas, kCol5X, kRow3Y, SkCanvas::kBleed_DrawBitmapRectFlag, kLow_SkFilterQuality);
237 // Finally draw a column with bleeding, tiling, and high filtering
238 this->drawCase1(canvas, kCol6X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, kHigh_SkFilterQuality);
239 this->drawCase2(canvas, kCol6X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, kHigh_SkFilterQuality);
240 this->drawCase3(canvas, kCol6X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, kHigh_SkFilterQuality);
241 this->drawCase4(canvas, kCol6X, kRow3Y, SkCanvas::kBleed_DrawBitmapRectFlag, kHigh_SkFilterQuality);
245 ctx->setMaxTextureSizeOverride(oldMaxTextureSize);
253 static const int kBlockSize = 70;
254 static const int kBlockSpacing = 5;
256 static const int kCol0X = kBlockSpacing;
257 static const int kCol1X = 2*kBlockSpacing + kBlockSize;
258 static const int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
259 static const int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
260 static const int kCol4X = 5*kBlockSpacing + 4*kBlockSize;
261 static const int kCol5X = 6*kBlockSpacing + 5*kBlockSize;
262 static const int kCol6X = 7*kBlockSpacing + 6*kBlockSize;
263 static const int kWidth = 8*kBlockSpacing + 7*kBlockSize;
265 static const int kRow0Y = kBlockSpacing;
266 static const int kRow1Y = 2*kBlockSpacing + kBlockSize;
267 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize;
268 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize;
270 static const int kSmallTextureSize = 6;
271 static const int kMaxTextureSize = 32;
273 SkBitmap fBitmapSmall;
276 typedef GM INHERITED;
279 DEF_GM( return new BleedGM(); )