blob: 8958c82d88774725068f85956db6273e1bb1d63b [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGradientShader.h"
5#include "SkPath.h"
6#include "SkRegion.h"
7#include "SkShader.h"
8#include "SkUtils.h"
9#include "SkImageDecoder.h"
10
11#ifdef SK_DEBUG
12static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
13 size_t count, int32_t runs[]) {
14 SkIRect r;
15 r.set(left, top, right, bottom);
16
17 rgn->debugSetRuns(runs, count);
18 SkASSERT(rgn->getBounds() == r);
19}
20
21static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
22 static int32_t dataA[] = {
23 0x00000001, 0x000001dd,
24 0x00000001, 0x0000000c, 0x0000000d, 0x00000025,
25 0x7fffffff, 0x000001de, 0x00000001, 0x00000025,
26 0x7fffffff, 0x000004b3, 0x00000001, 0x00000026,
27 0x7fffffff, 0x000004b4, 0x0000000c, 0x00000026,
28 0x7fffffff, 0x00000579, 0x00000000, 0x0000013a,
29 0x7fffffff, 0x000005d8, 0x00000000, 0x0000013b,
30 0x7fffffff, 0x7fffffff
31 };
32 make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);
33
34 static int32_t dataB[] = {
35 0x000000b6, 0x000000c4,
36 0x000000a1, 0x000000f0, 0x7fffffff, 0x000000d6,
37 0x7fffffff, 0x000000e4, 0x00000070, 0x00000079,
38 0x000000a1, 0x000000b0, 0x7fffffff, 0x000000e6,
39 0x7fffffff, 0x000000f4, 0x00000070, 0x00000079,
40 0x000000a1, 0x000000b0, 0x7fffffff, 0x000000f6,
41 0x7fffffff, 0x00000104, 0x000000a1, 0x000000b0,
42 0x7fffffff, 0x7fffffff
43 };
44 make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);
45
46 rc->op(*ra, *rb, SkRegion::kUnion_Op);
47}
48#endif
49
50static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn, const SkPaint& paint)
51{
52 SkRegion::Iterator iter(rgn);
53
54 for (; !iter.done(); iter.next())
55 {
56 SkRect r;
57 r.set(iter.rect());
58 canvas->drawRect(r, paint);
59 }
60}
61
62class RegionView : public SkView {
63public:
64 RegionView()
65 {
66 fBase.set(100, 100, 150, 150);
67 fRect = fBase;
68 fRect.inset(5, 5);
69 fRect.offset(25, 25);
70 }
71
72 void build_rgn(SkRegion* rgn, SkRegion::Op op)
73 {
74 rgn->setRect(fBase);
75 SkIRect r = fBase;
76 r.offset(75, 20);
77 rgn->op(r, SkRegion::kUnion_Op);
78 rgn->op(fRect, op);
79 }
80
81
82protected:
83 // overrides from SkEventSink
84 virtual bool onQuery(SkEvent* evt)
85 {
86 if (SampleCode::TitleQ(*evt))
87 {
88 SampleCode::TitleR(evt, "Regions");
89 return true;
90 }
91 return this->INHERITED::onQuery(evt);
92 }
93
94 void drawOrig(SkCanvas* canvas, bool bg)
95 {
96 SkRect r;
97 SkPaint paint;
98
99 paint.setStyle(SkPaint::kStroke_Style);
100 if (bg)
101 paint.setColor(0xFFBBBBBB);
102
103 r.set(fBase);
104 canvas->drawRect(r, paint);
105 r.set(fRect);
106 canvas->drawRect(r, paint);
107 }
108
109 void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
110 {
111 SkRegion rgn;
112
113 this->build_rgn(&rgn, op);
114
115 {
116 SkRegion tmp, tmp2(rgn);
117
118 tmp = tmp2;
119 tmp.translate(5, -3);
120
121 {
122 char buffer[1000];
123 size_t size = tmp.flatten(NULL);
124 SkASSERT(size <= sizeof(buffer));
125 size_t size2 = tmp.flatten(buffer);
126 SkASSERT(size == size2);
127
128 SkRegion tmp3;
129 size2 = tmp3.unflatten(buffer);
130 SkASSERT(size == size2);
131
132 SkASSERT(tmp3 == tmp);
133 }
134
135 rgn.translate(20, 30, &tmp);
136 SkASSERT(rgn.isEmpty() || tmp != rgn);
137 tmp.translate(-20, -30);
138 SkASSERT(tmp == rgn);
139 }
140
141 this->drawOrig(canvas, true);
142
143 SkPaint paint;
144 paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
145 paint_rgn(canvas, rgn, paint);
146
147 paint.setStyle(SkPaint::kStroke_Style);
148 paint.setColor(color);
149 paint_rgn(canvas, rgn, paint);
150 }
151
152 void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
153 {
154 SkRegion rgn;
155 SkPath path;
156
157 this->build_rgn(&rgn, op);
158 rgn.getBoundaryPath(&path);
159
160 this->drawOrig(canvas, true);
161
162 SkPaint paint;
163
164 paint.setStyle(SkPaint::kFill_Style);
165 paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
166 canvas->drawPath(path, paint);
167 paint.setColor(color);
168 paint.setStyle(SkPaint::kStroke_Style);
169 canvas->drawPath(path, paint);
170 }
171
172 void drawBG(SkCanvas* canvas)
173 {
174 canvas->drawColor(0xFFDDDDDD);
175 return;
176
177#if 0
178 SkColorTable ct;
179 SkPMColor colors[] = { SK_ColorRED, SK_ColorBLUE };
180 ct.setColors(colors, 2);
181 ct.setFlags(ct.getFlags() | SkColorTable::kColorsAreOpaque_Flag);
182
183 SkBitmap bm;
184 bm.setConfig(SkBitmap::kIndex8_Config, 20, 20, 21);
185 bm.setColorTable(&ct);
186 bm.allocPixels();
187 sk_memset16((uint16_t*)bm.getAddr8(0, 0), 0x0001, bm.rowBytes() * bm.height() / 2);
188#endif
189#if 0
190 SkBitmap bm;
191 bm.setConfig(SkBitmap::kRGB_565_Config, 20, 20, 42);
192 bm.allocPixels();
193 sk_memset32((uint32_t*)bm.getAddr16(0, 0), 0x0000FFFF, bm.rowBytes() * bm.height() / 4);
194#endif
195#if 1
196 SkBitmap bm;
197 bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
198 bm.allocPixels();
199 sk_memset32((uint32_t*)bm.getAddr32(0, 0), 0xFFDDDDDD, bm.rowBytes() * bm.height() / 4);
200#endif
201
202 SkPaint paint;
203
204// SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kBilinear_FilterType, SkShader::kRepeat_TileMode);
205 SkPoint pts[] = { 0, 0, SkIntToScalar(100), SkIntToScalar(0) };
206 SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
207 SkShader* shader = SkGradientShader::CreateLinear(pts, colors, nil, 2, SkShader::kMirror_TileMode);
208 paint.setShader(shader)->unref();
209
210 canvas->drawPaint(paint);
211 }
212
213 virtual void onDraw(SkCanvas* canvas)
214 {
215 if (true) {
216 SkRect r = { 0, 0, 1 << 30, 1 << 30 };
217 bool open = canvas->clipRect(r);
218 SkDebugf("---- giant clip is %d\n", open);
219 }
220 this->drawBG(canvas);
221
222#ifdef SK_DEBUG
223 if (true) {
224 SkRegion a, b, c;
225 test_union_bug_1505668(&a, &b, &c);
226
227 if (false) { // draw the result of the test
228 SkPaint paint;
229
230 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
231 paint.setColor(SK_ColorRED);
232 paint_rgn(canvas, a, paint);
233 paint.setColor(0x800000FF);
234 paint_rgn(canvas, b, paint);
235 paint.setColor(SK_ColorBLACK);
236 paint.setStyle(SkPaint::kStroke_Style);
237 // paint_rgn(canvas, c, paint);
238 return;
239 }
240 }
241#endif
242
243 static const struct {
244 SkColor fColor;
245 const char* fName;
246 SkRegion::Op fOp;
247 } gOps[] = {
248 { SK_ColorBLACK, "Difference", SkRegion::kDifference_Op },
249 { SK_ColorRED, "Intersect", SkRegion::kIntersect_Op },
250 { 0xFF008800, "Union", SkRegion::kUnion_Op },
251 { SK_ColorBLUE, "XOR", SkRegion::kXOR_Op }
252 };
253
254 SkPaint textPaint;
255 textPaint.setAntiAlias(true);
256 textPaint.setTextSize(SK_Scalar1*24);
257
258 this->drawOrig(canvas, false);
259 canvas->save();
260 canvas->translate(SkIntToScalar(200), 0);
261 this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
262 canvas->restore();
263
264 canvas->translate(0, SkIntToScalar(200));
265
266 for (int op = 0; op < SK_ARRAY_COUNT(gOps); op++)
267 {
268 canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
269
270 this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
271
272 if (true)
273 {
274 canvas->save();
275 canvas->translate(0, SkIntToScalar(200));
276 this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
277 canvas->restore();
278 }
279
280 canvas->translate(SkIntToScalar(200), 0);
281 }
282
283 if (false)
284 {
285 SkBitmap bitmap;
286
287 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
288 bitmap.allocPixels();
289 bitmap.eraseColor(0);
290
291 SkCanvas canvas(bitmap);
292 SkPaint paint;
293 SkRect r;
294
295 paint.setAntiAlias(true);
296 paint.setARGB(0xFF, 0xFF, 0, 0xFF);
297 r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
298 canvas.drawOval(r, paint);
299
300 SkImageEncoder* en = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
301 en->encodeFile("testfile.png", bitmap);
302 delete en;
303 }
304 }
305
306 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
307 {
308 return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : nil;
309 }
310
311 virtual bool onClick(Click* click)
312 {
313 fRect.offset(click->fICurr.fX - click->fIPrev.fX,
314 click->fICurr.fY - click->fIPrev.fY);
315 this->inval(nil);
316 return true;
317 }
318
319private:
320 SkIRect fBase, fRect;
321
322 typedef SkView INHERITED;
323};
324
325//////////////////////////////////////////////////////////////////////////////
326
327static SkView* MyFactory() { return new RegionView; }
328static SkViewRegister reg(MyFactory);
329