2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "effects/GrRRectEffect.h"
18 ///////////////////////////////////////////////////////////////////////////////
20 class RRectGM : public GM {
29 RRectGM(Type type) : fType(type) {
30 this->setBGColor(0xFFDDDDDD);
35 SkString onShortName() SK_OVERRIDE {
36 SkString name("rrect");
39 name.append("_draw_bw");
42 name.append("_draw_aa");
45 name.append("_clip_bw");
48 name.append("_clip_aa");
51 name.append("_effect");
57 virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(kImageWidth, kImageHeight); }
59 virtual uint32_t onGetFlags() const SK_OVERRIDE {
60 if (kEffect_Type == fType) {
61 return kGPUOnly_Flag | kSkipTiled_Flag;
63 return kSkipTiled_Flag;
67 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
69 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
70 GrContext* context = rt ? rt->getContext() : NULL;
71 if (kEffect_Type == fType && NULL == context) {
77 if (kAA_Draw_Type == fType) {
78 paint.setAntiAlias(true);
81 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX),
82 SkIntToScalar(kTileY));
84 static const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
85 SkIntToScalar(kImageHeight));
89 int lastEdgeType = (kEffect_Type == fType) ? kLast_GrEffectEdgeType: 0;
95 for (int et = 0; et <= lastEdgeType; ++et) {
97 for (int curRRect = 0; curRRect < kNumRRects; ++curRRect) {
100 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
101 SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
102 imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
103 SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
106 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
107 if (kEffect_Type == fType) {
110 context->getTestTarget(&tt);
111 if (NULL == tt.target()) {
112 SkDEBUGFAIL("Couldn't get Gr test target.");
115 GrDrawState* drawState = tt.target()->drawState();
117 SkRRect rrect = fRRects[curRRect];
118 rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
119 GrEffectEdgeType edgeType = (GrEffectEdgeType) et;
120 SkAutoTUnref<GrEffect> effect(GrRRectEffect::Create(edgeType, rrect));
122 drawState->addCoverageEffect(effect);
123 drawState->setIdentityViewMatrix();
124 drawState->setRenderTarget(rt);
125 drawState->setColor(0xff000000);
127 SkRect bounds = rrect.getBounds();
128 bounds.outset(2.f, 2.f);
130 tt.target()->drawSimpleRect(bounds);
135 } else if (kBW_Clip_Type == fType || kAA_Clip_Type == fType) {
136 bool aaClip = (kAA_Clip_Type == fType);
137 canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, aaClip);
138 canvas->drawRect(kMaxTileBound, paint);
140 canvas->drawRRect(fRRects[curRRect], paint);
145 if (x > kImageWidth) {
158 // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across
159 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
162 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
163 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
164 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
165 fRRects[3].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 5);
166 // small circular corners are an interesting test case for gpu clipping
167 fRRects[4].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 1, 1);
168 fRRects[5].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.5f, 0.5f);
169 fRRects[6].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 0.2f, 0.2f);
171 // The first complex case needs special handling since it is a square
172 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
173 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
174 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
181 static const int kImageWidth = 640;
182 static const int kImageHeight = 480;
184 static const int kTileX = 80;
185 static const int kTileY = 40;
187 static const int kNumSimpleCases = 7;
188 static const int kNumComplexCases = 35;
189 static const SkVector gRadii[kNumComplexCases][4];
191 static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
192 SkRRect fRRects[kNumRRects];
194 typedef GM INHERITED;
197 // Radii for the various test cases. Order is UL, UR, LR, LL
198 const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
200 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
203 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
204 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
205 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
208 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
209 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
210 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
213 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
214 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
215 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
218 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
219 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
220 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
223 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
224 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
225 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
228 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
229 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
230 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
232 // circular corner tabs
233 { { 0, 0 }, { 20, 20 }, { 20, 20 }, { 0, 0 } },
234 { { 20, 20 }, { 20, 20 }, { 0, 0 }, { 0, 0 } },
235 { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 20, 20 } },
236 { { 20, 20 }, { 0, 0 }, { 0, 0 }, { 20, 20 } },
238 // small radius circular corner tabs
239 { { 0, 0 }, { 0.2f, 0.2f }, { 0.2f, 0.2f }, { 0, 0 } },
240 { { 0.3f, 0.3f }, { 0.3f, .3f }, { 0, 0 }, { 0, 0 } },
242 // single circular corner cases
243 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 15 } },
244 { { 0, 0 }, { 0, 0 }, { 15, 15 }, { 0, 0 } },
245 { { 0, 0 }, { 15, 15 }, { 0, 0 }, { 0, 0 } },
246 { { 15, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
248 // nine patch elliptical
249 { { 5, 7 }, { 8, 7 }, { 8, 12 }, { 5, 12 } },
250 { { 0, 7 }, { 8, 7 }, { 8, 12 }, { 0, 12 } },
252 // nine patch elliptical, small radii
253 { { 0.4f, 7 }, { 8, 7 }, { 8, 12 }, { 0.4f, 12 } },
254 { { 0.4f, 0.4f }, { 8, 0.4f }, { 8, 12 }, { 0.4f, 12 } },
255 { { 20, 0.4f }, { 18, 0.4f }, { 18, 0.4f }, { 20, 0.4f } },
256 { { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f }, { 0.3f, 0.4f } },
260 ///////////////////////////////////////////////////////////////////////////////
262 DEF_GM( return new RRectGM(RRectGM::kAA_Draw_Type); )
263 DEF_GM( return new RRectGM(RRectGM::kBW_Draw_Type); )
264 DEF_GM( return new RRectGM(RRectGM::kAA_Clip_Type); )
265 DEF_GM( return new RRectGM(RRectGM::kBW_Clip_Type); )
267 DEF_GM( return new RRectGM(RRectGM::kEffect_Type); )