diff options
-rw-r--r-- | gm/techtalk1.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/gm/techtalk1.cpp b/gm/techtalk1.cpp new file mode 100644 index 0000000000..1b6555520d --- /dev/null +++ b/gm/techtalk1.cpp @@ -0,0 +1,321 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "gm.h" + +#include "SkColorPriv.h" +#include "SkGeometry.h" +#include "SkShader.h" + +static void tesselate(const SkPath& src, SkPath* dst) { + SkPath::Iter iter(src, true); + SkPoint pts[4]; + SkPath::Verb verb; + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { + switch (verb) { + case SkPath::kMove_Verb: + dst->moveTo(pts[0]); + break; + case SkPath::kLine_Verb: + dst->lineTo(pts[1]); + break; + case SkPath::kQuad_Verb: { + SkPoint p; + for (int i = 1; i <= 8; ++i) { + SkEvalQuadAt(pts, i / 8.0f, &p, NULL); + dst->lineTo(p); + } + } break; + case SkPath::kCubic_Verb: { + SkPoint p; + for (int i = 1; i <= 8; ++i) { + SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL); + dst->lineTo(p); + } + } break; + } + } +} + +static void setFade(SkPaint* paint, bool showGL) { + paint->setAlpha(showGL ? 0x66 : 0xFF); +} + +static void setGLFrame(SkPaint* paint) { + paint->setColor(0xFFFF0000); + paint->setStyle(SkPaint::kStroke_Style); + paint->setAntiAlias(true); + paint->setStrokeWidth(1.1f); +} + +static void show_mesh(SkCanvas* canvas, const SkRect& r) { + SkPaint paint; + setGLFrame(&paint); + + canvas->drawRect(r, paint); + canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint); +} + +static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, + const SkPaint& paint) { + canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint); +} + +static void show_mesh(SkCanvas* canvas, const SkPoint pts[], + const uint16_t indices[], int count) { + SkPaint paint; + setGLFrame(&paint); + + for (int i = 0; i < count - 2; ++i) { + drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint); + drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint); + drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint); + } +} + +static void show_glframe(SkCanvas* canvas, const SkPath& path) { + SkPaint paint; + setGLFrame(&paint); + canvas->drawPath(path, paint); +} + +static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) { + SkPath d0, d1; + tesselate(p0, &d0); + tesselate(p1, &d1); + + SkPoint pts0[256*2], pts1[256]; + int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0)); + int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1)); + SkASSERT(count == count1); + memcpy(&pts0[count], pts1, count * sizeof(SkPoint)); + + uint16_t indices[256*6]; + uint16_t* ndx = indices; + for (int i = 0; i < count; ++i) { + *ndx++ = i; + *ndx++ = i + count; + } + *ndx++ = 0; + + show_mesh(canvas, pts0, indices, ndx - indices); +} + +static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) { + SkPaint paint; + setGLFrame(&paint); + + canvas->drawPath(path, paint); + + SkPoint pts[256]; + int count = path.getPoints(pts, SK_ARRAY_COUNT(pts)); + for (int i = 0; i < count; ++i) { + canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags); + +static void draw_line(SkCanvas* canvas, bool showGL, int flags) { + SkPaint paint; + paint.setAntiAlias(true); + + canvas->drawLine(50, 50, 400, 100, paint); + + canvas->rotate(40); + setFade(&paint, showGL); + paint.setStrokeWidth(40); + canvas->drawLine(100, 50, 450, 50, paint); + if (showGL) { + show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20)); + } +} + +static void draw_rect(SkCanvas* canvas, bool showGL, int flags) { + SkPaint paint; + paint.setAntiAlias(true); + + SkRect r = SkRect::MakeLTRB(50, 50, 250, 350); + + setFade(&paint, showGL); + canvas->drawRect(r, paint); + if (showGL) { + show_mesh(canvas, r); + } + + canvas->translate(320, 0); + + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(25); + canvas->drawRect(r, paint); + if (showGL) { + SkScalar rad = paint.getStrokeWidth() / 2; + SkPoint pts[8]; + r.outset(rad, rad); + r.toQuad(&pts[0]); + r.inset(rad*2, rad*2); + r.toQuad(&pts[4]); + + const uint16_t indices[] = { + 0, 4, 1, 5, 2, 6, 3, 7, 0, 4 + }; + show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices)); + } +} + +static void draw_oval(SkCanvas* canvas, bool showGL, int flags) { + SkPaint paint; + paint.setAntiAlias(true); + + SkRect r = SkRect::MakeLTRB(50, 50, 250, 350); + + setFade(&paint, showGL); + canvas->drawOval(r, paint); + if (showGL) { + switch (flags) { + case 0: { + SkPath path; + path.addOval(r); + show_glframe(canvas, path); + } break; + case 1: { + SkPath src, dst; + src.addOval(r); + tesselate(src, &dst); + show_fan(canvas, dst, r.centerX(), r.centerY()); + } break; + } + } + + canvas->translate(320, 0); + + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(25); + canvas->drawOval(r, paint); + if (showGL) { + switch (flags) { + case 0: { + SkPath path; + SkScalar rad = paint.getStrokeWidth() / 2; + r.outset(rad, rad); + path.addOval(r); + r.inset(rad*2, rad*2); + path.addOval(r); + show_glframe(canvas, path); + } break; + case 1: { + SkPath path0, path1; + SkScalar rad = paint.getStrokeWidth() / 2; + r.outset(rad, rad); + path0.addOval(r); + r.inset(rad*2, rad*2); + path1.addOval(r); + show_mesh_between(canvas, path0, path1); + } break; + } + } +} + +static void draw_image(SkCanvas* canvas, bool showGL, int flags) { + SkPaint paint; + paint.setAntiAlias(true); + + canvas->drawLine(10, 10, 400, 30, paint); + paint.setStrokeWidth(10); + canvas->drawLine(50, 50, 400, 400, paint); +} + +static void draw_text(SkCanvas* canvas, bool showGL, int flags) { + SkPaint paint; + paint.setAntiAlias(true); + + canvas->drawLine(10, 10, 400, 30, paint); + paint.setStrokeWidth(10); + canvas->drawLine(50, 50, 400, 400, paint); +} + +static const struct { + DrawProc fProc; + const char* fName; +} gRec[] = { + { draw_line, "Lines" }, + { draw_rect, "Rects" }, + { draw_oval, "Ovals" }, + { draw_image, "Images" }, + { draw_text, "Text" }, +}; + +class TalkGM : public skiagm::GM { + DrawProc fProc; + SkString fName; + bool fShowGL; + int fFlags; + +public: + TalkGM(int index, bool showGL, int flags = 0) { + fProc = gRec[index].fProc; + fName.set(gRec[index].fName); + if (showGL) { + fName.append("-gl"); + } + fShowGL = showGL; + fFlags = flags; + } + +protected: + virtual SkString onShortName() { + return fName; + } + + virtual SkISize onISize() { + return SkISize::Make(640, 480); + } + + virtual void onDraw(SkCanvas* canvas) { + SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height()); + SkRect src = SkRect::MakeWH(640, 480); + SkMatrix matrix; + matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit); + + canvas->concat(matrix); + fProc(canvas, fShowGL, fFlags); + } + +private: + typedef skiagm::GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y) +#define GM_CONCAT_IMPL(X,Y) X##Y + +#define FACTORY_NAME GM_CONCAT(Factory, __LINE__) +#define REGISTRY_NAME GM_CONCAT(gReg, __LINE__) + +#define ADD_GM(Class, args) \ + static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \ + static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME); + +ADD_GM(TalkGM, (0, false)) +ADD_GM(TalkGM, (0, true)) +ADD_GM(TalkGM, (1, false)) +ADD_GM(TalkGM, (1, true)) +ADD_GM(TalkGM, (2, false)) +ADD_GM(TalkGM, (2, true)) +ADD_GM(TalkGM, (2, true, 1)) +ADD_GM(TalkGM, (3, false)) +ADD_GM(TalkGM, (3, true)) +ADD_GM(TalkGM, (4, false)) +ADD_GM(TalkGM, (4, true)) + +//static GM* MyFactory(void*) { return new TalkGM(0, false); } +//static GMRegistry reg(MyFactory); + + |