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