blob: 2d3743a5a25e976439795817fd3eb38cb27fe213 [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"
9#include "SkCanvas.h"
robertphillips@google.com2cc0b472013-08-20 16:51:20 +000010#include "SkBlurMaskFilter.h"
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000011
12#if SK_SUPPORT_GPU
13#include "GrContext.h"
14
15namespace skiagm {
16extern GrContext* GetGr();
17};
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000018#endif
19
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000020// Create a black&white checked texture with a 1-pixel red ring
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000021// around the outside edge
22static void make_red_ringed_bitmap(SkBitmap* result, int width, int height) {
23 SkASSERT(0 == width % 2 && 0 == width % 2);
24
25 result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
26 result->allocPixels();
27 SkAutoLockPixels lock(*result);
28
skia.committer@gmail.com956b3102013-07-26 07:00:58 +000029 SkPMColor* scanline = result->getAddr32(0, 0);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +000030 for (int x = 0; x < width; ++x) {
31 scanline[x] = SK_ColorRED;
32 }
33
34 for (int y = 1; y < height/2; ++y) {
35 scanline = result->getAddr32(0, y);
36 scanline[0] = SK_ColorRED;
37 for (int x = 1; x < width/2; ++x) {
38 scanline[x] = SK_ColorBLACK;
39 }
40 for (int x = width/2; x < width-1; ++x) {
41 scanline[x] = SK_ColorWHITE;
42 }
43 scanline[width-1] = SK_ColorRED;
44 }
45
46 for (int y = height/2; y < height-1; ++y) {
47 scanline = result->getAddr32(0, y);
48 scanline[0] = SK_ColorRED;
49 for (int x = 1; x < width/2; ++x) {
50 scanline[x] = SK_ColorWHITE;
51 }
52 for (int x = width/2; x < width-1; ++x) {
53 scanline[x] = SK_ColorBLACK;
54 }
55 scanline[width-1] = SK_ColorRED;
56 }
57
58 scanline = result->getAddr32(0, height-1);
59 for (int x = 0; x < width; ++x) {
60 scanline[x] = SK_ColorRED;
61 }
62 result->setIsOpaque(true);
63 result->setImmutable();
64}
65
66// This GM exercises the drawBitmapRectToRect "bleed" flag
67class BleedGM : public skiagm::GM {
68public:
69 BleedGM() {}
70
71protected:
72 virtual SkString onShortName() SK_OVERRIDE {
73 return SkString("bleed");
74 }
75
76 virtual SkISize onISize() SK_OVERRIDE {
77 return SkISize::Make(kWidth, kHeight);
78 }
79
80 virtual void onOnceBeforeDraw() SK_OVERRIDE {
81 make_red_ringed_bitmap(&fBitmapSmall, kSmallTextureSize, kSmallTextureSize);
82
83 // To exercise the GPU's tiling path we need a texture
84 // too big for the GPU to handle in one go
85 make_red_ringed_bitmap(&fBitmapBig, 2*kMaxTextureSize, 2*kMaxTextureSize);
86 }
87
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000088 // Draw only the center of the small bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +000089 void drawCase1(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +000090 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
91 SkRect src = SkRect::MakeXYWH(1, 1,
92 kSmallTextureSize-2,
93 kSmallTextureSize-2);
94 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
95
96 SkPaint paint;
97 paint.setFilterBitmap(filter);
98
99 canvas->save();
100 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
101 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
102 canvas->restore();
103 }
104
105 // Draw almost all of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000106 void drawCase2(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000107 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
108 SkRect src = SkRect::MakeXYWH(1, 1,
109 SkIntToScalar(fBitmapBig.width()-2),
110 SkIntToScalar(fBitmapBig.height()-2));
111 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
112
113 SkPaint paint;
114 paint.setFilterBitmap(filter);
115
116 canvas->save();
117 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
118 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
119 canvas->restore();
120 }
121
122 // Draw ~1/4 of the large bitmap
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000123 void drawCase3(SkCanvas* canvas, int transX, int transY,
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000124 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
125 SkRect src = SkRect::MakeXYWH(1, 1,
126 SkIntToScalar(fBitmapBig.width()/2-1),
127 SkIntToScalar(fBitmapBig.height()/2-1));
128 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
129
130 SkPaint paint;
131 paint.setFilterBitmap(filter);
132
133 canvas->save();
134 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
135 canvas->drawBitmapRectToRect(fBitmapBig, &src, dst, &paint, flags);
136 canvas->restore();
137 }
138
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000139 // Draw the center of the small bitmap with a mask filter
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000140 void drawCase4(SkCanvas* canvas, int transX, int transY,
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000141 SkCanvas::DrawBitmapRectFlags flags, bool filter) {
142 SkRect src = SkRect::MakeXYWH(1, 1,
143 kSmallTextureSize-2,
144 kSmallTextureSize-2);
145 SkRect dst = SkRect::MakeXYWH(0, 0, SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
146
147 SkPaint paint;
148 paint.setFilterBitmap(filter);
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +0000149 SkMaskFilter* mf = SkBlurMaskFilter::Create(SkIntToScalar(3),
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000150 SkBlurMaskFilter::kNormal_BlurStyle);
151 paint.setMaskFilter(mf)->unref();
152
153 canvas->save();
154 canvas->translate(SkIntToScalar(transX), SkIntToScalar(transY));
155 canvas->drawBitmapRectToRect(fBitmapSmall, &src, dst, &paint, flags);
156 canvas->restore();
157 }
158
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000159 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000160
161 canvas->clear(SK_ColorGRAY);
162
163 // First draw a column with no bleeding, tiling, or filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000164 this->drawCase1(canvas, kCol0X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
165 this->drawCase2(canvas, kCol0X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
166 this->drawCase3(canvas, kCol0X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000167 this->drawCase4(canvas, kCol0X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, false);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000168
169 // Then draw a column with no bleeding or tiling but with filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000170 this->drawCase1(canvas, kCol1X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
171 this->drawCase2(canvas, kCol1X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
172 this->drawCase3(canvas, kCol1X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000173 this->drawCase4(canvas, kCol1X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000174
175
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000176#if SK_SUPPORT_GPU
177 GrContext* ctx = skiagm::GetGr();
178 int oldMaxTextureSize = 0;
179 if (NULL != ctx) {
180 // shrink the max texture size so all our textures can be reasonably sized
181 oldMaxTextureSize = ctx->getMaxTextureSize();
182 ctx->setMaxTextureSizeOverride(kMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000183 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000184#endif
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000185
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000186 // Then draw a column with no bleeding but with tiling and filtering
robertphillips@google.com41464132013-08-20 12:28:23 +0000187 this->drawCase1(canvas, kCol2X, kRow0Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
188 this->drawCase2(canvas, kCol2X, kRow1Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
189 this->drawCase3(canvas, kCol2X, kRow2Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000190 this->drawCase4(canvas, kCol2X, kRow3Y, SkCanvas::kNone_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000191
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000192 // Finally draw a column with all three (bleeding, tiling, and filtering)
193 this->drawCase1(canvas, kCol3X, kRow0Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
194 this->drawCase2(canvas, kCol3X, kRow1Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
195 this->drawCase3(canvas, kCol3X, kRow2Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000196 this->drawCase4(canvas, kCol3X, kRow3Y, SkCanvas::kBleed_DrawBitmapRectFlag, true);
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000197
198#if SK_SUPPORT_GPU
199 if (NULL != ctx) {
200 ctx->setMaxTextureSizeOverride(oldMaxTextureSize);
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000201 }
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000202#endif
203 }
204
205private:
robertphillips@google.comd7ca6612013-08-20 12:09:32 +0000206 static const int kBlockSize = 90;
207 static const int kBlockSpacing = 10;
208
209 static const int kCol0X = kBlockSpacing;
210 static const int kCol1X = 2*kBlockSpacing + kBlockSize;
211 static const int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
212 static const int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
213 static const int kWidth = 5*kBlockSpacing + 4*kBlockSize;
214
215 static const int kRow0Y = kBlockSpacing;
216 static const int kRow1Y = 2*kBlockSpacing + kBlockSize;
217 static const int kRow2Y = 3*kBlockSpacing + 2*kBlockSize;
robertphillips@google.com2cc0b472013-08-20 16:51:20 +0000218 static const int kRow3Y = 4*kBlockSpacing + 3*kBlockSize;
219 static const int kHeight = 5*kBlockSpacing + 4*kBlockSize;
robertphillips@google.comaaa9b292013-07-25 21:34:00 +0000220
221 static const int kSmallTextureSize = 4;
222 static const int kMaxTextureSize = 32;
223
224 SkBitmap fBitmapSmall;
225 SkBitmap fBitmapBig;
226
227 typedef GM INHERITED;
228};
229
230DEF_GM( return new BleedGM(); )