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