blob: dc7e96fbb122716c76d397de1cf5d59eda399354 [file] [log] [blame]
robertphillips@google.comaaa9b292013-07-25 21:34:00 +00001/*
2 * Copyright 2013 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"
robertphillips@google.comb7061172013-09-06 14:16:12 +00009#include "SkBlurMask.h"
robertphillips@google.com2cc0b472013-08-20 16:51:20 +000010#include "SkBlurMaskFilter.h"
robertphillips@google.comb7061172013-09-06 14:16:12 +000011#include "SkCanvas.h"
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000012
13#if SK_SUPPORT_GPU
14#include "GrContext.h"
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000015#endif
16
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000017// Create a black&white checked texture with a 1-pixel red ring
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000018// around the outside edge
19static void make_red_ringed_bitmap(SkBitmap* result, int width, int height) {
20 SkASSERT(0 == width % 2 && 0 == width % 2);
21
22 result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
23 result->allocPixels();
24 SkAutoLockPixels lock(*result);
25
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000026 SkPMColor* scanline = result->getAddr32(0, 0);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000027 for (int x = 0; x < width; ++x) {
28 scanline[x] = SK_ColorRED;
29 }
30
31 for (int y = 1; y < height/2; ++y) {
32 scanline = result->getAddr32(0, y);
33 scanline[0] = SK_ColorRED;
34 for (int x = 1; x < width/2; ++x) {
35 scanline[x] = SK_ColorBLACK;
36 }
37 for (int x = width/2; x < width-1; ++x) {
38 scanline[x] = SK_ColorWHITE;
39 }
40 scanline[width-1] = SK_ColorRED;
41 }
42
43 for (int y = height/2; y < height-1; ++y) {
44 scanline = result->getAddr32(0, y);
45 scanline[0] = SK_ColorRED;
46 for (int x = 1; x < width/2; ++x) {
47 scanline[x] = SK_ColorWHITE;
48 }
49 for (int x = width/2; x < width-1; ++x) {
50 scanline[x] = SK_ColorBLACK;
51 }
52 scanline[width-1] = SK_ColorRED;
53 }
54
55 scanline = result->getAddr32(0, height-1);
56 for (int x = 0; x < width; ++x) {
57 scanline[x] = SK_ColorRED;
58 }
59 result->setIsOpaque(true);
60 result->setImmutable();
61}
62
63// This GM exercises the drawBitmapRectToRect "bleed" flag
64class BleedGM : public skiagm::GM {
65public:
66 BleedGM() {}
67
68protected:
69 virtual SkString onShortName() SK_OVERRIDE {
70 return SkString("bleed");
71 }
72
73 virtual SkISize onISize() SK_OVERRIDE {
74 return SkISize::Make(kWidth, kHeight);
75 }
76
77 virtual void onOnceBeforeDraw() SK_OVERRIDE {
78 make_red_ringed_bitmap(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize);
79
80 // To exercise the GPU's tiling path we need a texture
81 // too big for the GPU to handle in one go
82 make_red_ringed_bitmap(&fBitmapBig, 2*kMaxTextureSize, 2*kMaxTextureSize);
83 }
84
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000085 // Draw only the center of the small bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +000086 void drawCase1(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000087 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
88 SkRect src = SkRect::MakeXYWH(1, 1,
89 kSmallTextureSize-2,
90 kSmallTextureSize-2);
91 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
92
93 SkPaint paint;
94 paint.setFilterBitmap(filter);
95
96 canvas->save();
97 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
98 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
99 canvas->restore();
100 }
101
102 // Draw almost all of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000103 void drawCase2(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000104 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
105 SkRect src = SkRect::MakeXYWH(1, 1,
106 SkIntToScalar(fBitmapBig.width()-2),
107 SkIntToScalar(fBitmapBig.height()-2));
108 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
109
110 SkPaint paint;
111 paint.setFilterBitmap(filter);
112
113 canvas->save();
114 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
115 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
116 canvas->restore();
117 }
118
119 // Draw ~1/4 of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000120 void drawCase3(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000121 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
122 SkRect src = SkRect::MakeXYWH(1, 1,
123 SkIntToScalar(fBitmapBig.width()/2-1),
124 SkIntToScalar(fBitmapBig.height()/2-1));
125 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
126
127 SkPaint paint;
128 paint.setFilterBitmap(filter);
129
130 canvas->save();
131 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
132 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
133 canvas->restore();
134 }
135
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000136 // Draw the center of the small bitmap with a mask filter
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000137 void drawCase4(SkCanvas* canvas, int transX, int transY,
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000138 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
139 SkRect src = SkRect::MakeXYWH(1, 1,
140 kSmallTextureSize-2,
141 kSmallTextureSize-2);
142 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
143
144 SkPaint paint;
145 paint.setFilterBitmap(filter);
robertphillips@google.comb7061172013-09-06 14:16:12 +0000146 SkMaskFilter* mf = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
147 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)));
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000148 paint.setMaskFilter(mf)->unref();
149
150 canvas->save();
151 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
152 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
153 canvas->restore();
154 }
155
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000156 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000157
158 canvas->clear(SK_ColorGRAY);
159
160 // First draw a column with no bleeding, tiling, or filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000161 this->drawCase1(canvas, kCol0X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
162 this->drawCase2(canvas, kCol0X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
163 this->drawCase3(canvas, kCol0X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000164 this->drawCase4(canvas, kCol0X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000165
166 // Then draw a column with no bleeding or tiling but with filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000167 this->drawCase1(canvas, kCol1X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
168 this->drawCase2(canvas, kCol1X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
169 this->drawCase3(canvas, kCol1X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000170 this->drawCase4(canvas, kCol1X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000171
172
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000173#if SK_SUPPORT_GPU
mtklein@google.com62b50b72013-09-16 20:42:15 +0000174 GrContext* ctx = GM::GetGr(canvas);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000175 int oldMaxTextureSize = 0;
176 if (NULL != ctx) {
177 // shrink the max texture size so all our textures can be reasonably sized
178 oldMaxTextureSize = ctx->getMaxTextureSize();
179 ctx->setMaxTextureSizeOverride(kMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000180 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000181#endif
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000182
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000183 // Then draw a column with no bleeding but with tiling and filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000184 this->drawCase1(canvas, kCol2X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
185 this->drawCase2(canvas, kCol2X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
186 this->drawCase3(canvas, kCol2X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000187 this->drawCase4(canvas, kCol2X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000188
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000189 // Finally draw a column with all three (bleeding, tiling, and filtering)
190 this->drawCase1(canvas, kCol3X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
191 this->drawCase2(canvas, kCol3X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
192 this->drawCase3(canvas, kCol3X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000193 this->drawCase4(canvas, kCol3X, kRow3Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000194
195#if SK_SUPPORT_GPU
196 if (NULL != ctx) {
197 ctx->setMaxTextureSizeOverride(oldMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000198 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000199#endif
200 }
201
202private:
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000203 static const int kBlockSize = 90;
204 static const int kBlockSpacing = 10;
205
206 static const int kCol0X = kBlockSpacing;
207 static const int kCol1X = 2*kBlockSpacing + kBlockSize;
208 static const int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
209 static const int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
210 static const int kWidth = 5*kBlockSpacing + 4*kBlockSize;
211
212 static const int kRow0Y = kBlockSpacing;
213 static const int kRow1Y = 2*kBlockSpacing + kBlockSize;
214 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize;
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000215 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize;
216 static const int kHeight = 5*kBlockSpacing + 4*kBlockSize;
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000217
218 static const int kSmallTextureSize = 4;
219 static const int kMaxTextureSize = 32;
220
221 SkBitmap fBitmapSmall;
222 SkBitmap fBitmapBig;
223
224 typedef GM INHERITED;
225};
226
227DEF_GM( return new BleedGM(); )