• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SampleCode.h"
9 #include "SkView.h"
10 #include "SkCanvas.h"
11 #include "SkGradientShader.h"
12 #include "SkPath.h"
13 #include "SkRegion.h"
14 #include "SkShader.h"
15 #include "SkUtils.h"
16 #include "SkImageDecoder.h"
17 
18 #ifdef SK_BUILD_FOR_WIN
19 // windows doesn't have roundf
roundf(float x)20 inline float roundf(float x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
21 #endif
22 
23 #ifdef SK_DEBUG
make_rgn(SkRegion * rgn,int left,int top,int right,int bottom,size_t count,int32_t runs[])24 static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
25                      size_t count, int32_t runs[]) {
26     SkIRect r;
27     r.set(left, top, right, bottom);
28 
29     rgn->debugSetRuns(runs, count);
30     SkASSERT(rgn->getBounds() == r);
31 }
32 
test_union_bug_1505668(SkRegion * ra,SkRegion * rb,SkRegion * rc)33 static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
34     static int32_t dataA[] = {
35         0x00000001, 0x000001dd,
36         0x00000001, 0x0000000c, 0x0000000d, 0x00000025,
37         0x7fffffff, 0x000001de, 0x00000001, 0x00000025,
38         0x7fffffff, 0x000004b3, 0x00000001, 0x00000026,
39         0x7fffffff, 0x000004b4, 0x0000000c, 0x00000026,
40         0x7fffffff, 0x00000579, 0x00000000, 0x0000013a,
41         0x7fffffff, 0x000005d8, 0x00000000, 0x0000013b,
42         0x7fffffff, 0x7fffffff
43     };
44     make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);
45 
46     static int32_t dataB[] = {
47         0x000000b6, 0x000000c4,
48         0x000000a1, 0x000000f0, 0x7fffffff, 0x000000d6,
49         0x7fffffff, 0x000000e4, 0x00000070, 0x00000079,
50         0x000000a1, 0x000000b0, 0x7fffffff, 0x000000e6,
51         0x7fffffff, 0x000000f4, 0x00000070, 0x00000079,
52         0x000000a1, 0x000000b0, 0x7fffffff, 0x000000f6,
53         0x7fffffff, 0x00000104, 0x000000a1, 0x000000b0,
54         0x7fffffff, 0x7fffffff
55     };
56     make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);
57 
58     rc->op(*ra, *rb, SkRegion::kUnion_Op);
59 }
60 #endif
61 
scale_rect(SkIRect * dst,const SkIRect & src,float scale)62 static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
63     dst->fLeft = (int)::roundf(src.fLeft * scale);
64     dst->fTop = (int)::roundf(src.fTop * scale);
65     dst->fRight = (int)::roundf(src.fRight * scale);
66     dst->fBottom = (int)::roundf(src.fBottom * scale);
67 }
68 
scale_rgn(SkRegion * dst,const SkRegion & src,float scale)69 static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
70     SkRegion tmp;
71     SkRegion::Iterator iter(src);
72 
73     for (; !iter.done(); iter.next()) {
74         SkIRect r;
75         scale_rect(&r, iter.rect(), scale);
76         tmp.op(r, SkRegion::kUnion_Op);
77     }
78     dst->swap(tmp);
79 }
80 
paint_rgn(SkCanvas * canvas,const SkRegion & rgn,const SkPaint & paint)81 static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn,
82                       const SkPaint& paint) {
83     SkRegion scaled;
84     scale_rgn(&scaled, rgn, 0.5f);
85 
86     SkRegion::Iterator  iter(rgn);
87 
88     for (; !iter.done(); iter.next())
89     {
90         SkRect    r;
91         r.set(iter.rect());
92         canvas->drawRect(r, paint);
93     }
94 }
95 
96 class RegionView : public SampleView {
97 public:
RegionView()98 	RegionView() {
99         fBase.set(100, 100, 150, 150);
100         fRect = fBase;
101         fRect.inset(5, 5);
102         fRect.offset(25, 25);
103         this->setBGColor(0xFFDDDDDD);
104     }
105 
build_rgn(SkRegion * rgn,SkRegion::Op op)106     void build_rgn(SkRegion* rgn, SkRegion::Op op) {
107         rgn->setRect(fBase);
108         SkIRect r = fBase;
109         r.offset(75, 20);
110         rgn->op(r, SkRegion::kUnion_Op);
111         rgn->op(fRect, op);
112     }
113 
114 
115 protected:
116     // overrides from SkEventSink
onQuery(SkEvent * evt)117     virtual bool onQuery(SkEvent* evt) {
118         if (SampleCode::TitleQ(*evt)) {
119             SampleCode::TitleR(evt, "Regions");
120             return true;
121         }
122         return this->INHERITED::onQuery(evt);
123     }
124 
drawOrig(SkCanvas * canvas,bool bg)125     void drawOrig(SkCanvas* canvas, bool bg) {
126         SkRect      r;
127         SkPaint     paint;
128 
129         paint.setStyle(SkPaint::kStroke_Style);
130         if (bg)
131             paint.setColor(0xFFBBBBBB);
132 
133         r.set(fBase);
134         canvas->drawRect(r, paint);
135         r.set(fRect);
136         canvas->drawRect(r, paint);
137     }
138 
drawRgnOped(SkCanvas * canvas,SkRegion::Op op,SkColor color)139     void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
140         SkRegion    rgn;
141 
142         this->build_rgn(&rgn, op);
143 
144         {
145             SkRegion tmp, tmp2(rgn);
146 
147             tmp = tmp2;
148             tmp.translate(5, -3);
149 
150             {
151                 char    buffer[1000];
152                 size_t  size = tmp.flatten(NULL);
153                 SkASSERT(size <= sizeof(buffer));
154                 size_t  size2 = tmp.flatten(buffer);
155                 SkASSERT(size == size2);
156 
157                 SkRegion    tmp3;
158                 size2 = tmp3.unflatten(buffer);
159                 SkASSERT(size == size2);
160 
161                 SkASSERT(tmp3 == tmp);
162             }
163 
164             rgn.translate(20, 30, &tmp);
165             SkASSERT(rgn.isEmpty() || tmp != rgn);
166             tmp.translate(-20, -30);
167             SkASSERT(tmp == rgn);
168         }
169 
170         this->drawOrig(canvas, true);
171 
172         SkPaint paint;
173         paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
174         paint_rgn(canvas, rgn, paint);
175 
176         paint.setStyle(SkPaint::kStroke_Style);
177         paint.setColor(color);
178         paint_rgn(canvas, rgn, paint);
179     }
180 
drawPathOped(SkCanvas * canvas,SkRegion::Op op,SkColor color)181     void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
182         SkRegion    rgn;
183         SkPath      path;
184 
185         this->build_rgn(&rgn, op);
186         rgn.getBoundaryPath(&path);
187 
188         this->drawOrig(canvas, true);
189 
190         SkPaint paint;
191 
192         paint.setStyle(SkPaint::kFill_Style);
193         paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
194         canvas->drawPath(path, paint);
195         paint.setColor(color);
196         paint.setStyle(SkPaint::kStroke_Style);
197         canvas->drawPath(path, paint);
198     }
199 
onDrawContent(SkCanvas * canvas)200     virtual void onDrawContent(SkCanvas* canvas) {
201 #ifdef SK_DEBUG
202         if (true) {
203             SkRegion a, b, c;
204             test_union_bug_1505668(&a, &b, &c);
205 
206             if (false) {    // draw the result of the test
207                 SkPaint paint;
208 
209                 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
210                 paint.setColor(SK_ColorRED);
211                 paint_rgn(canvas, a, paint);
212                 paint.setColor(0x800000FF);
213                 paint_rgn(canvas, b, paint);
214                 paint.setColor(SK_ColorBLACK);
215                 paint.setStyle(SkPaint::kStroke_Style);
216              //   paint_rgn(canvas, c, paint);
217                 return;
218             }
219         }
220 #endif
221 
222         static const struct {
223             SkColor         fColor;
224             const char*     fName;
225             SkRegion::Op    fOp;
226         } gOps[] = {
227             { SK_ColorBLACK,    "Difference",   SkRegion::kDifference_Op    },
228             { SK_ColorRED,      "Intersect",    SkRegion::kIntersect_Op     },
229             { 0xFF008800,       "Union",        SkRegion::kUnion_Op         },
230             { SK_ColorBLUE,     "XOR",          SkRegion::kXOR_Op           }
231         };
232 
233         SkPaint textPaint;
234         textPaint.setAntiAlias(true);
235         textPaint.setTextSize(SK_Scalar1*24);
236 
237         this->drawOrig(canvas, false);
238         canvas->save();
239             canvas->translate(SkIntToScalar(200), 0);
240             this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
241         canvas->restore();
242 
243         canvas->translate(0, SkIntToScalar(200));
244 
245         for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
246             canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
247 
248             this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
249 
250             canvas->save();
251             canvas->translate(0, SkIntToScalar(200));
252             this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
253             canvas->restore();
254 
255             canvas->translate(SkIntToScalar(200), 0);
256         }
257     }
258 
onFindClickHandler(SkScalar x,SkScalar y)259     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
260         return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : NULL;
261     }
262 
onClick(Click * click)263     virtual bool onClick(Click* click) {
264         fRect.offset(click->fICurr.fX - click->fIPrev.fX,
265                      click->fICurr.fY - click->fIPrev.fY);
266         this->inval(NULL);
267         return true;
268     }
269 
270 private:
271     SkIRect    fBase, fRect;
272 
273     typedef SampleView INHERITED;
274 };
275 
276 //////////////////////////////////////////////////////////////////////////////
277 
MyFactory()278 static SkView* MyFactory() { return new RegionView; }
279 static SkViewRegister reg(MyFactory);
280 
281