2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SampleCode.h"
16 #include "SkSurface.h"
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
23 static SkScalar apply_grid(SkScalar x) {
24 const SkScalar grid = 2;
25 return SkScalarRoundToScalar(x * grid) / grid;
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));
34 static void erase(SkSurface* surface) {
35 surface->getCanvas()->clear(SK_ColorTRANSPARENT);
38 static SkShader* createChecker(const SkMatrix& localMatrix) {
39 // SkColor colors[] = { 0xFFFDFDFD, 0xFFF4F4F4 };
40 SkColor colors[] = { 0xFFFFFFFF, 0xFFFFFFFF };
42 bm.allocN32Pixels(2, 2);
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);
62 fClipRect.set(2, 2, 11, 8 );
65 int getZoom() const { return fZoom; }
67 bool getAA() const { return fAA; }
68 void setAA(bool aa) { fAA = aa; }
70 bool getGrid() const { return fGrid; }
71 void setGrid(bool g) { fGrid = g; }
73 bool getShowSkeleton() const { return fShowSkeleton; }
74 void setShowSkeleton(bool ss) { fShowSkeleton = ss; }
76 bool getUseGPU() const { return fUseGPU; }
77 void setUseGPU(bool ug) { fUseGPU = ug; }
79 bool getTriangle() const { return fUseTriangle; }
80 void setTriangle(bool ut) { fUseTriangle = ut; }
82 void toggleRectAsOval() { fRectAsOval = !fRectAsOval; }
84 bool getUseClip() const { return fUseClip; }
85 void setUseClip(bool uc) { fUseClip = uc; }
91 Style getStyle() const { return fStyle; }
92 void setStyle(Style s) { fStyle = s; }
94 void setWHZ(int width, int height, int 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));
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));
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]);
116 bool fAA, fGrid, fShowSkeleton, fUseGPU, fUseClip, fRectAsOval, fUseTriangle;
119 SkMatrix fMatrix, fInverse;
120 SkRect fBounds, fClipRect;
121 SkAutoTUnref<SkShader> fShader;
122 SkAutoTUnref<SkSurface> fMinSurface;
123 SkAutoTUnref<SkSurface> fMaxSurface;
125 void setupPaint(SkPaint* paint) {
126 bool aa = this->getAA();
129 paint->setStrokeWidth(0);
132 paint->setStrokeWidth(SK_Scalar1);
135 paint->setAntiAlias(aa);
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);
145 void drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]);
146 void drawLineSkeleton(SkCanvas* max, const SkPoint pts[]);
147 void drawRectSkeleton(SkCanvas* max, const SkRect& r) {
149 this->setupSkeletonPaint(&paint);
152 if (fUseGPU && fAA) {
154 rr.inset(SkIntToScalar(fZoom)/2, SkIntToScalar(fZoom)/2);
156 path.moveTo(rr.fLeft, rr.fTop);
157 path.lineTo(rr.fRight, rr.fBottom);
159 rr.inset(-SkIntToScalar(fZoom)/2, -SkIntToScalar(fZoom)/2);
162 fRectAsOval ? path.addOval(r) : path.addRect(r);
164 path.moveTo(r.fLeft, r.fTop);
165 path.lineTo(r.fRight, r.fBottom);
168 max->drawPath(path, paint);
171 void copyMinToMax() {
173 SkCanvas* canvas = fMaxSurface->getCanvas();
175 canvas->concat(fMatrix);
176 fMinSurface->draw(canvas, 0, 0, NULL);
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);
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);
192 void FatBits::drawBG(SkCanvas* canvas) {
195 paint.setShader(fShader);
196 canvas->drawRect(fBounds, paint);
197 paint.setShader(NULL);
200 void FatBits::drawFG(SkCanvas* canvas) {
201 SkPaint inner, outer;
203 inner.setAntiAlias(true);
204 inner.setColor(SK_ColorBLACK);
205 inner.setStrokeWidth(PIXEL_CENTER_SIZE);
207 outer.setAntiAlias(true);
208 outer.setColor(SK_ColorWHITE);
209 outer.setStrokeWidth(PIXEL_CENTER_SIZE + 2);
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;
217 canvas->drawPoint(x, y, outer);
218 canvas->drawPoint(x, y, inner);
224 p.setStyle(SkPaint::kStroke_Style);
225 p.setColor(SK_ColorLTGRAY);
227 fClipRect.fLeft * fZoom,
228 fClipRect.fTop * fZoom,
229 fClipRect.fRight * fZoom,
230 fClipRect.fBottom * fZoom
232 canvas->drawRect(r, p);
236 void FatBits::drawLineSkeleton(SkCanvas* max, const SkPoint pts[]) {
238 this->setupSkeletonPaint(&paint);
248 p.setStyle(SkPaint::kStroke_Style);
249 p.setStrokeWidth(SK_Scalar1 * fZoom);
251 p.getFillPath(path, &dst);
255 case kStroke_Style: {
257 p.setStyle(SkPaint::kStroke_Style);
258 p.setStrokeWidth(SK_Scalar1 * fZoom);
260 p.getFillPath(path, &dst);
264 path.moveTo(dst.getPoint(0));
265 path.lineTo(dst.getPoint(2));
269 max->drawPath(path, paint);
272 void FatBits::drawLine(SkCanvas* canvas, SkPoint pts[]) {
275 fInverse.mapPoints(pts, 2);
282 this->setupPaint(&paint);
283 paint.setColor(FAT_PIXEL_COLOR);
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);
290 fMinSurface->getCanvas()->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
292 fMinSurface->getCanvas()->restore();
294 this->copyMinToMax();
296 SkCanvas* max = fMaxSurface->getCanvas();
298 fMatrix.mapPoints(pts, 2);
299 this->drawLineSkeleton(max, pts);
301 fMaxSurface->draw(canvas, 0, 0, NULL);
304 void FatBits::drawRect(SkCanvas* canvas, SkPoint pts[2]) {
307 fInverse.mapPoints(pts, 2);
317 this->setupPaint(&paint);
318 paint.setColor(FAT_PIXEL_COLOR);
320 SkCanvas* c = fMinSurface->getCanvas();
321 fRectAsOval ? c->drawOval(r, paint) : c->drawRect(r, paint);
323 this->copyMinToMax();
325 SkCanvas* max = fMaxSurface->getCanvas();
327 fMatrix.mapPoints(pts, 2);
329 this->drawRectSkeleton(max, r);
331 fMaxSurface->draw(canvas, 0, 0, NULL);
334 void FatBits::drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]) {
336 this->setupSkeletonPaint(&paint);
344 max->drawPath(path, paint);
347 void FatBits::drawTriangle(SkCanvas* canvas, SkPoint pts[3]) {
350 fInverse.mapPoints(pts, 3);
363 this->setupPaint(&paint);
364 paint.setColor(FAT_PIXEL_COLOR);
365 fMinSurface->getCanvas()->drawPath(path, paint);
366 this->copyMinToMax();
368 SkCanvas* max = fMaxSurface->getCanvas();
370 fMatrix.mapPoints(pts, 3);
371 this->drawTriangleSkeleton(max, pts);
373 fMaxSurface->draw(canvas, 0, 0, NULL);
376 ///////////////////////////////////////////////////////////////////////////////////////////////////
378 class IndexClick : public SkView::Click {
381 IndexClick(SkView* v, int index) : SkView::Click(v), fIndex(index) {}
383 static int GetIndex(SkView::Click* click) {
384 return ((IndexClick*)click)->fIndex;
388 class DrawLineView : public SampleView {
394 fFB.setWHZ(24, 16, 48);
396 fPts[1].set(48 * 5, 48 * 4);
397 fPts[2].set(48 * 2, 48 * 6);
401 void setStyle(FatBits::Style s) {
407 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
408 if (SampleCode::TitleQ(*evt)) {
409 SampleCode::TitleR(evt, "FatBits");
413 if (SampleCode::CharQ(*evt, &uni)) {
416 fFB.setUseClip(!fFB.getUseClip());
424 fFB.toggleRectAsOval();
428 fFB.setGrid(!fFB.getGrid());
432 if (FatBits::kStroke_Style == fFB.getStyle()) {
433 this->setStyle(FatBits::kHair_Style);
435 this->setStyle(FatBits::kStroke_Style);
439 fFB.setAA(!fFB.getAA());
443 fFB.setShowSkeleton(!fFB.getShowSkeleton());
447 fFB.setUseGPU(!fFB.getUseGPU());
451 fFB.setTriangle(!fFB.getTriangle());
456 return this->INHERITED::onQuery(evt);
459 virtual void onDrawContent(SkCanvas* canvas) {
461 if (fFB.getTriangle()) {
462 fFB.drawTriangle(canvas, fPts);
465 fFB.drawRect(canvas, fPts);
467 fFB.drawLine(canvas, fPts);
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");
479 paint.setAntiAlias(true);
480 paint.setTextSize(16);
481 paint.setColor(SK_ColorBLUE);
482 canvas->drawText(str.c_str(), str.size(), 10, 16, paint);
486 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
487 unsigned modi) SK_OVERRIDE {
488 SkPoint pt = { x, y };
490 int count = fFB.getTriangle() ? 3 : 2;
493 for (int i = 0; i < count; ++i) {
494 if (fPts[i].equalsWithinTolerance(pt, tol)) {
499 return new IndexClick(this, index);
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;
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);
519 typedef SampleView INHERITED;
522 //////////////////////////////////////////////////////////////////////////////
524 static SkView* MyFactory() { return new DrawLineView; }
525 static SkViewRegister reg(MyFactory);