Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / samplecode / SampleFatBits.cpp
1 /*
2  * Copyright 2012 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 "SampleCode.h"
9 #include "SkView.h"
10 #include "SkCanvas.h"
11 #include "SkPath.h"
12 #include "SkRegion.h"
13 #include "SkShader.h"
14 #include "SkUtils.h"
15 #include "SkImage.h"
16 #include "SkSurface.h"
17
18 #define FAT_PIXEL_COLOR     SK_ColorBLACK
19 #define PIXEL_CENTER_SIZE   3
20 #define WIRE_FRAME_COLOR    0xFFFF0000  /*0xFF00FFFF*/
21 #define WIRE_FRAME_SIZE     1.5f
22
23 static SkScalar apply_grid(SkScalar x) {
24     const SkScalar grid = 2;
25     return SkScalarRoundToScalar(x * grid) / grid;
26 }
27
28 static void apply_grid(SkPoint pts[], int count) {
29     for (int i = 0; i < count; ++i) {
30         pts[i].set(apply_grid(pts[i].fX), apply_grid(pts[i].fY));
31     }
32 }
33
34 static void erase(SkSurface* surface) {
35     surface->getCanvas()->clear(SK_ColorTRANSPARENT);
36 }
37
38 static SkShader* createChecker(const SkMatrix& localMatrix) {
39 //    SkColor colors[] = { 0xFFFDFDFD, 0xFFF4F4F4 };
40     SkColor colors[] = { 0xFFFFFFFF, 0xFFFFFFFF };
41     SkBitmap bm;
42     bm.allocN32Pixels(2, 2);
43     bm.lockPixels();
44     *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(colors[0]);
45     *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(colors[1]);
46     return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
47                                         SkShader::kRepeat_TileMode, &localMatrix);
48 }
49
50 class FatBits {
51 public:
52     FatBits() {
53         fAA = false;
54         fStyle = kHair_Style;
55         fGrid = true;
56         fShowSkeleton = true;
57         fUseGPU = false;
58         fUseClip = false;
59         fRectAsOval = false;
60         fUseTriangle = false;
61
62         fClipRect.set(2, 2, 11, 8 );
63     }
64
65     int getZoom() const { return fZoom; }
66
67     bool getAA() const { return fAA; }
68     void setAA(bool aa) { fAA = aa; }
69
70     bool getGrid() const { return fGrid; }
71     void setGrid(bool g) { fGrid = g; }
72
73     bool getShowSkeleton() const { return fShowSkeleton; }
74     void setShowSkeleton(bool ss) { fShowSkeleton = ss; }
75
76     bool getUseGPU() const { return fUseGPU; }
77     void setUseGPU(bool ug) { fUseGPU = ug; }
78
79     bool getTriangle() const { return fUseTriangle; }
80     void setTriangle(bool ut) { fUseTriangle = ut; }
81
82     void toggleRectAsOval() { fRectAsOval = !fRectAsOval; }
83
84     bool getUseClip() const { return fUseClip; }
85     void setUseClip(bool uc) { fUseClip = uc; }
86
87     enum Style {
88         kHair_Style,
89         kStroke_Style,
90     };
91     Style getStyle() const { return fStyle; }
92     void setStyle(Style s) { fStyle = s; }
93
94     void setWHZ(int width, int height, int zoom) {
95         fW = width;
96         fH = height;
97         fZoom = zoom;
98         fBounds.set(0, 0, SkIntToScalar(width * zoom), SkIntToScalar(height * zoom));
99         fMatrix.setScale(SkIntToScalar(zoom), SkIntToScalar(zoom));
100         fInverse.setScale(SK_Scalar1 / zoom, SK_Scalar1 / zoom);
101         fShader.reset(createChecker(fMatrix));
102
103         SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
104         fMinSurface.reset(SkSurface::NewRaster(info));
105         info = info.makeWH(width * zoom, height * zoom);
106         fMaxSurface.reset(SkSurface::NewRaster(info));
107     }
108
109     void drawBG(SkCanvas*);
110     void drawFG(SkCanvas*);
111     void drawLine(SkCanvas*, SkPoint pts[2]);
112     void drawRect(SkCanvas* canvas, SkPoint pts[2]);
113     void drawTriangle(SkCanvas* canvas, SkPoint pts[3]);
114
115 private:
116     bool fAA, fGrid, fShowSkeleton, fUseGPU, fUseClip, fRectAsOval, fUseTriangle;
117     Style fStyle;
118     int fW, fH, fZoom;
119     SkMatrix fMatrix, fInverse;
120     SkRect   fBounds, fClipRect;
121     SkAutoTUnref<SkShader> fShader;
122     SkAutoTUnref<SkSurface> fMinSurface;
123     SkAutoTUnref<SkSurface> fMaxSurface;
124
125     void setupPaint(SkPaint* paint) {
126         bool aa = this->getAA();
127         switch (fStyle) {
128             case kHair_Style:
129                 paint->setStrokeWidth(0);
130                 break;
131             case kStroke_Style:
132                 paint->setStrokeWidth(SK_Scalar1);
133                 break;
134         }
135         paint->setAntiAlias(aa);
136     }
137
138     void setupSkeletonPaint(SkPaint* paint) {
139         paint->setStyle(SkPaint::kStroke_Style);
140         paint->setStrokeWidth(WIRE_FRAME_SIZE);
141         paint->setColor(fShowSkeleton ? WIRE_FRAME_COLOR : 0);
142         paint->setAntiAlias(true);
143     }
144
145     void drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]);
146     void drawLineSkeleton(SkCanvas* max, const SkPoint pts[]);
147     void drawRectSkeleton(SkCanvas* max, const SkRect& r) {
148         SkPaint paint;
149         this->setupSkeletonPaint(&paint);
150         SkPath path;
151
152         if (fUseGPU && fAA) {
153             SkRect rr = r;
154             rr.inset(SkIntToScalar(fZoom)/2, SkIntToScalar(fZoom)/2);
155             path.addRect(rr);
156             path.moveTo(rr.fLeft, rr.fTop);
157             path.lineTo(rr.fRight, rr.fBottom);
158             rr = r;
159             rr.inset(-SkIntToScalar(fZoom)/2, -SkIntToScalar(fZoom)/2);
160             path.addRect(rr);
161         } else {
162             fRectAsOval ? path.addOval(r) : path.addRect(r);
163             if (fUseGPU) {
164                 path.moveTo(r.fLeft, r.fTop);
165                 path.lineTo(r.fRight, r.fBottom);
166             }
167         }
168         max->drawPath(path, paint);
169     }
170
171     void copyMinToMax() {
172         erase(fMaxSurface);
173         SkCanvas* canvas = fMaxSurface->getCanvas();
174         canvas->save();
175         canvas->concat(fMatrix);
176         fMinSurface->draw(canvas, 0, 0, NULL);
177         canvas->restore();
178
179         SkPaint paint;
180         paint.setXfermodeMode(SkXfermode::kClear_Mode);
181         for (int iy = 1; iy < fH; ++iy) {
182             SkScalar y = SkIntToScalar(iy * fZoom);
183             canvas->drawLine(0, y - SK_ScalarHalf, 999, y - SK_ScalarHalf, paint);
184         }
185         for (int ix = 1; ix < fW; ++ix) {
186             SkScalar x = SkIntToScalar(ix * fZoom);
187             canvas->drawLine(x - SK_ScalarHalf, 0, x - SK_ScalarHalf, 999, paint);
188         }
189     }
190 };
191
192 void FatBits::drawBG(SkCanvas* canvas) {
193     SkPaint paint;
194
195     paint.setShader(fShader);
196     canvas->drawRect(fBounds, paint);
197     paint.setShader(NULL);
198 }
199
200 void FatBits::drawFG(SkCanvas* canvas) {
201     SkPaint inner, outer;
202
203     inner.setAntiAlias(true);
204     inner.setColor(SK_ColorBLACK);
205     inner.setStrokeWidth(PIXEL_CENTER_SIZE);
206
207     outer.setAntiAlias(true);
208     outer.setColor(SK_ColorWHITE);
209     outer.setStrokeWidth(PIXEL_CENTER_SIZE + 2);
210
211     SkScalar half = SkIntToScalar(fZoom) / 2;
212     for (int iy = 0; iy < fH; ++iy) {
213         SkScalar y = SkIntToScalar(iy * fZoom) + half;
214         for (int ix = 0; ix < fW; ++ix) {
215             SkScalar x = SkIntToScalar(ix * fZoom) + half;
216
217             canvas->drawPoint(x, y, outer);
218             canvas->drawPoint(x, y, inner);
219         }
220     }
221
222     if (fUseClip) {
223         SkPaint p;
224         p.setStyle(SkPaint::kStroke_Style);
225         p.setColor(SK_ColorLTGRAY);
226         SkRect r = {
227             fClipRect.fLeft * fZoom,
228             fClipRect.fTop * fZoom,
229             fClipRect.fRight * fZoom,
230             fClipRect.fBottom * fZoom
231         };
232         canvas->drawRect(r, p);
233     }
234 }
235
236 void FatBits::drawLineSkeleton(SkCanvas* max, const SkPoint pts[]) {
237     SkPaint paint;
238     this->setupSkeletonPaint(&paint);
239
240     SkPath path;
241     path.moveTo(pts[0]);
242     path.lineTo(pts[1]);
243
244     switch (fStyle) {
245         case kHair_Style:
246             if (fUseGPU) {
247                 SkPaint p;
248                 p.setStyle(SkPaint::kStroke_Style);
249                 p.setStrokeWidth(SK_Scalar1 * fZoom);
250                 SkPath dst;
251                 p.getFillPath(path, &dst);
252                 path.addPath(dst);
253             }
254             break;
255         case kStroke_Style: {
256             SkPaint p;
257             p.setStyle(SkPaint::kStroke_Style);
258             p.setStrokeWidth(SK_Scalar1 * fZoom);
259             SkPath dst;
260             p.getFillPath(path, &dst);
261             path = dst;
262
263             if (fUseGPU) {
264                 path.moveTo(dst.getPoint(0));
265                 path.lineTo(dst.getPoint(2));
266             }
267         } break;
268     }
269     max->drawPath(path, paint);
270 }
271
272 void FatBits::drawLine(SkCanvas* canvas, SkPoint pts[]) {
273     SkPaint paint;
274
275     fInverse.mapPoints(pts, 2);
276
277     if (fGrid) {
278         apply_grid(pts, 2);
279     }
280
281     erase(fMinSurface);
282     this->setupPaint(&paint);
283     paint.setColor(FAT_PIXEL_COLOR);
284     if (fUseClip) {
285         fMinSurface->getCanvas()->save();
286         SkRect r = fClipRect;
287         r.inset(SK_Scalar1/3, SK_Scalar1/3);
288         fMinSurface->getCanvas()->clipRect(r, SkRegion::kIntersect_Op, true);
289     }
290     fMinSurface->getCanvas()->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
291     if (fUseClip) {
292         fMinSurface->getCanvas()->restore();
293     }
294     this->copyMinToMax();
295
296     SkCanvas* max = fMaxSurface->getCanvas();
297
298     fMatrix.mapPoints(pts, 2);
299     this->drawLineSkeleton(max, pts);
300
301     fMaxSurface->draw(canvas, 0, 0, NULL);
302 }
303
304 void FatBits::drawRect(SkCanvas* canvas, SkPoint pts[2]) {
305     SkPaint paint;
306
307     fInverse.mapPoints(pts, 2);
308
309     if (fGrid) {
310         apply_grid(pts, 2);
311     }
312
313     SkRect r;
314     r.set(pts, 2);
315
316     erase(fMinSurface);
317     this->setupPaint(&paint);
318     paint.setColor(FAT_PIXEL_COLOR);
319     {
320         SkCanvas* c = fMinSurface->getCanvas();
321         fRectAsOval ? c->drawOval(r, paint) : c->drawRect(r, paint);
322     }
323     this->copyMinToMax();
324
325     SkCanvas* max = fMaxSurface->getCanvas();
326
327     fMatrix.mapPoints(pts, 2);
328     r.set(pts, 2);
329     this->drawRectSkeleton(max, r);
330
331     fMaxSurface->draw(canvas, 0, 0, NULL);
332 }
333
334 void FatBits::drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]) {
335     SkPaint paint;
336     this->setupSkeletonPaint(&paint);
337
338     SkPath path;
339     path.moveTo(pts[0]);
340     path.lineTo(pts[1]);
341     path.lineTo(pts[2]);
342     path.close();
343
344     max->drawPath(path, paint);
345 }
346
347 void FatBits::drawTriangle(SkCanvas* canvas, SkPoint pts[3]) {
348     SkPaint paint;
349
350     fInverse.mapPoints(pts, 3);
351
352     if (fGrid) {
353         apply_grid(pts, 3);
354     }
355
356     SkPath path;
357     path.moveTo(pts[0]);
358     path.lineTo(pts[1]);
359     path.lineTo(pts[2]);
360     path.close();
361
362     erase(fMinSurface);
363     this->setupPaint(&paint);
364     paint.setColor(FAT_PIXEL_COLOR);
365     fMinSurface->getCanvas()->drawPath(path, paint);
366     this->copyMinToMax();
367
368     SkCanvas* max = fMaxSurface->getCanvas();
369
370     fMatrix.mapPoints(pts, 3);
371     this->drawTriangleSkeleton(max, pts);
372
373     fMaxSurface->draw(canvas, 0, 0, NULL);
374 }
375
376 ///////////////////////////////////////////////////////////////////////////////////////////////////
377
378 class IndexClick : public SkView::Click {
379     int fIndex;
380 public:
381     IndexClick(SkView* v, int index) : SkView::Click(v), fIndex(index) {}
382
383     static int GetIndex(SkView::Click* click) {
384         return ((IndexClick*)click)->fIndex;
385     }
386 };
387
388 class DrawLineView : public SampleView {
389     FatBits fFB;
390     SkPoint fPts[3];
391     bool    fIsRect;
392 public:
393     DrawLineView() {
394         fFB.setWHZ(24, 16, 48);
395         fPts[0].set(48, 48);
396         fPts[1].set(48 * 5, 48 * 4);
397         fPts[2].set(48 * 2, 48 * 6);
398         fIsRect = false;
399     }
400
401     void setStyle(FatBits::Style s) {
402         fFB.setStyle(s);
403         this->inval(NULL);
404     }
405
406 protected:
407     virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
408         if (SampleCode::TitleQ(*evt)) {
409             SampleCode::TitleR(evt, "FatBits");
410             return true;
411         }
412         SkUnichar uni;
413         if (SampleCode::CharQ(*evt, &uni)) {
414             switch (uni) {
415                 case 'c':
416                     fFB.setUseClip(!fFB.getUseClip());
417                     this->inval(NULL);
418                     return true;
419                 case 'r':
420                     fIsRect = !fIsRect;
421                     this->inval(NULL);
422                     return true;
423                 case 'o':
424                     fFB.toggleRectAsOval();
425                     this->inval(NULL);
426                     return true;
427                 case 'x':
428                     fFB.setGrid(!fFB.getGrid());
429                     this->inval(NULL);
430                     return true;
431                 case 's':
432                     if (FatBits::kStroke_Style == fFB.getStyle()) {
433                         this->setStyle(FatBits::kHair_Style);
434                     } else {
435                         this->setStyle(FatBits::kStroke_Style);
436                     }
437                     return true;
438                 case 'a':
439                     fFB.setAA(!fFB.getAA());
440                     this->inval(NULL);
441                     return true;
442                 case 'w':
443                     fFB.setShowSkeleton(!fFB.getShowSkeleton());
444                     this->inval(NULL);
445                     return true;
446                 case 'g':
447                     fFB.setUseGPU(!fFB.getUseGPU());
448                     this->inval(NULL);
449                     return true;
450                 case 't':
451                     fFB.setTriangle(!fFB.getTriangle());
452                     this->inval(NULL);
453                     return true;
454             }
455         }
456         return this->INHERITED::onQuery(evt);
457     }
458
459     virtual void onDrawContent(SkCanvas* canvas) {
460         fFB.drawBG(canvas);
461         if (fFB.getTriangle()) {
462             fFB.drawTriangle(canvas, fPts);
463         }
464         else if (fIsRect) {
465             fFB.drawRect(canvas, fPts);
466         } else {
467             fFB.drawLine(canvas, fPts);
468         }
469         fFB.drawFG(canvas);
470
471         {
472             SkString str;
473             str.printf("%s %s %s %s",
474                        fFB.getAA() ? "AA" : "BW",
475                        FatBits::kHair_Style == fFB.getStyle() ? "Hair" : "Stroke",
476                        fFB.getUseGPU() ? "GPU" : "CPU",
477                        fFB.getUseClip() ? "clip" : "noclip");
478             SkPaint paint;
479             paint.setAntiAlias(true);
480             paint.setTextSize(16);
481             paint.setColor(SK_ColorBLUE);
482             canvas->drawText(str.c_str(), str.size(), 10, 16, paint);
483         }
484     }
485
486     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
487                                               unsigned modi) SK_OVERRIDE {
488         SkPoint pt = { x, y };
489         int index = -1;
490         int count = fFB.getTriangle() ? 3 : 2;
491         SkScalar tol = 12;
492
493         for (int i = 0; i < count; ++i) {
494             if (fPts[i].equalsWithinTolerance(pt, tol)) {
495                 index = i;
496                 break;
497             }
498         }
499         return new IndexClick(this, index);
500     }
501
502     virtual bool onClick(Click* click) SK_OVERRIDE {
503         int index = IndexClick::GetIndex(click);
504         if (index >= 0 && index <= 2) {
505             fPts[index] = click->fCurr;
506         } else {
507             SkScalar dx = click->fCurr.fX - click->fPrev.fX;
508             SkScalar dy = click->fCurr.fY - click->fPrev.fY;
509             fPts[0].offset(dx, dy);
510             fPts[1].offset(dx, dy);
511             fPts[2].offset(dx, dy);
512         }
513         this->inval(NULL);
514         return true;
515     }
516
517 private:
518
519     typedef SampleView INHERITED;
520 };
521
522 //////////////////////////////////////////////////////////////////////////////
523
524 static SkView* MyFactory() { return new DrawLineView; }
525 static SkViewRegister reg(MyFactory);