aboutsummaryrefslogtreecommitdiffstats
path: root/gm
diff options
context:
space:
mode:
authorDerek Sollenberger <djsollen@google.com>2012-01-18 08:56:56 -0500
committerDerek Sollenberger <derek@android.com>2012-02-06 14:14:40 -0500
commit1cab2921ab279367f8206cdadc9259d12e603548 (patch)
tree2852f9dc2481f639122e18fc7831ae6ca43d6d5a /gm
parentd7176fd5571bc9878d3cdac8696eaa35ec170d9d (diff)
downloadexternal_skia-1cab2921ab279367f8206cdadc9259d12e603548.zip
external_skia-1cab2921ab279367f8206cdadc9259d12e603548.tar.gz
external_skia-1cab2921ab279367f8206cdadc9259d12e603548.tar.bz2
Skia merge (revision 3022)
This CL has companion changes to account for API updates in... (1) frameworks/base (2) external/webkit Change-Id: Ibb989e76e8bd24313849f9631dbef42cdef9eb7d
Diffstat (limited to 'gm')
-rw-r--r--gm/Android.mk26
-rw-r--r--gm/aaclip.cpp115
-rw-r--r--gm/aarectmodes.cpp203
-rw-r--r--gm/arithmode.cpp140
-rw-r--r--gm/bitmapcopy.cpp121
-rw-r--r--gm/bitmapfilters.cpp9
-rw-r--r--gm/bitmapscroll.cpp147
-rw-r--r--gm/blurs.cpp17
-rw-r--r--gm/colormatrix.cpp118
-rw-r--r--gm/complexclip.cpp119
-rw-r--r--gm/complexclip2.cpp135
-rw-r--r--gm/cubicpaths.cpp309
-rw-r--r--gm/degeneratesegments.cpp400
-rw-r--r--gm/drawbitmaprect.cpp155
-rw-r--r--gm/emptypath.cpp133
-rw-r--r--gm/filltypes.cpp10
-rw-r--r--gm/filltypespersp.cpp128
-rw-r--r--gm/fontscaler.cpp93
-rw-r--r--gm/gm.cpp54
-rw-r--r--gm/gm.h38
-rw-r--r--gm/gm_files.mk17
-rw-r--r--gm/gmmain.cpp560
-rw-r--r--gm/gradients.cpp119
-rw-r--r--gm/gradtext.cpp97
-rw-r--r--gm/hairmodes.cpp152
-rw-r--r--gm/imageblur.cpp57
-rw-r--r--gm/lcdtext.cpp70
-rw-r--r--gm/linepaths.cpp305
-rw-r--r--gm/ninepatchstretch.cpp113
-rwxr-xr-xgm/nocolorbleed.cpp17
-rw-r--r--gm/pathfill.cpp13
-rw-r--r--gm/pathreverse.cpp118
-rw-r--r--gm/points.cpp23
-rw-r--r--gm/poly2poly.cpp17
-rw-r--r--gm/quadpaths.cpp307
-rw-r--r--gm/shadertext.cpp42
-rw-r--r--gm/shadows.cpp14
-rw-r--r--gm/shapes.cpp23
-rw-r--r--gm/strokefill.cpp81
-rw-r--r--gm/strokerects.cpp25
-rw-r--r--gm/strokes.cpp149
-rw-r--r--gm/tablecolorfilter.cpp139
-rw-r--r--gm/testimagefilters.cpp143
-rw-r--r--gm/texdata.cpp146
-rw-r--r--gm/tilemodes.cpp12
-rw-r--r--gm/tinybitmap.cpp68
-rw-r--r--gm/verttext.cpp90
-rw-r--r--gm/verttext2.cpp92
-rw-r--r--gm/xfermodes.cpp45
49 files changed, 5171 insertions, 353 deletions
diff --git a/gm/Android.mk b/gm/Android.mk
index acfb4a5..14f4d62 100644
--- a/gm/Android.mk
+++ b/gm/Android.mk
@@ -3,11 +3,21 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
+ aarectmodes.cpp \
bitmapfilters.cpp \
+ bitmapscroll.cpp \
blurs.cpp \
complexclip.cpp \
+ complexclip2.cpp \
+ emptypath.cpp \
filltypes.cpp \
+ filltypespersp.cpp \
+ gm.cpp \
+ gmmain.cpp \
gradients.cpp \
+ hairmodes.cpp \
+ lcdtext.cpp \
+ ninepatchstretch.cpp \
nocolorbleed.cpp \
pathfill.cpp \
points.cpp \
@@ -16,13 +26,11 @@ LOCAL_SRC_FILES := \
shadows.cpp \
shapes.cpp \
strokerects.cpp \
+ strokes.cpp \
+ texdata.cpp \
tilemodes.cpp \
- xfermodes.cpp \
- gmmain.cpp
-
-# additional optional class for this tool
-LOCAL_SRC_FILES += \
- ../src/utils/SkEGLContext_none.cpp
+ tinybitmap.cpp \
+ xfermodes.cpp
LOCAL_STATIC_LIBRARIES := libskiagpu
LOCAL_SHARED_LIBRARIES := \
@@ -35,11 +43,11 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_C_INCLUDES := \
external/skia/include/config \
external/skia/include/core \
+ external/skia/include/effects \
+ external/skia/include/gpu \
external/skia/include/images \
external/skia/include/utils \
- external/skia/include/effects \
- external/skia/gpu/include \
- external/skia/include/gpu
+ external/skia/gm
#LOCAL_CFLAGS :=
diff --git a/gm/aaclip.cpp b/gm/aaclip.cpp
new file mode 100644
index 0000000..2976560
--- /dev/null
+++ b/gm/aaclip.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPath.h"
+
+namespace skiagm {
+
+/** Draw a 2px border around the target, then red behind the target;
+ set the clip to match the target, then draw >> the target in blue.
+*/
+
+void draw (SkCanvas* canvas, SkRect& target, int x, int y) {
+ SkPaint borderPaint;
+ borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0));
+ borderPaint.setAntiAlias(true);
+ SkPaint backgroundPaint;
+ backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0));
+ backgroundPaint.setAntiAlias(true);
+ SkPaint foregroundPaint;
+ foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD));
+ foregroundPaint.setAntiAlias(true);
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ target.inset(SkIntToScalar(-2), SkIntToScalar(-2));
+ canvas->drawRect(target, borderPaint);
+ target.inset(SkIntToScalar(2), SkIntToScalar(2));
+ canvas->drawRect(target, backgroundPaint);
+ canvas->clipRect(target, SkRegion::kIntersect_Op, true);
+ target.inset(SkIntToScalar(-4), SkIntToScalar(-4));
+ canvas->drawRect(target, foregroundPaint);
+ canvas->restore();
+}
+
+void draw_square (SkCanvas* canvas, int x, int y) {
+ SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1));
+ draw(canvas, target, x, y);
+}
+
+void draw_column (SkCanvas* canvas, int x, int y) {
+ SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1));
+ draw(canvas, target, x, y);
+}
+
+void draw_bar (SkCanvas* canvas, int x, int y) {
+ SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1));
+ draw(canvas, target, x, y);
+}
+
+void draw_rect_tests (SkCanvas* canvas) {
+ draw_square(canvas, 10, 10);
+ draw_column(canvas, 30, 10);
+ draw_bar(canvas, 10, 30);
+}
+
+/**
+ Test a set of clipping problems discovered while writing blitAntiRect,
+ and test all the code paths through the clipping blitters.
+ Each region should show as a blue center surrounded by a 2px green
+ border, with no red.
+*/
+
+class AAClipGM : public GM {
+public:
+ AAClipGM() {
+
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("aaclip");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(640, 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ // Initial pixel-boundary-aligned draw
+ draw_rect_tests(canvas);
+
+ // Repeat 4x with .2, .4, .6, .8 px offsets
+ canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
+ canvas->translate(SkIntToScalar(50), 0);
+ draw_rect_tests(canvas);
+
+ canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
+ canvas->translate(SkIntToScalar(50), 0);
+ draw_rect_tests(canvas);
+
+ canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
+ canvas->translate(SkIntToScalar(50), 0);
+ draw_rect_tests(canvas);
+
+ canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
+ canvas->translate(SkIntToScalar(50), 0);
+ draw_rect_tests(canvas);
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new AAClipGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/aarectmodes.cpp b/gm/aarectmodes.cpp
new file mode 100644
index 0000000..f518cae
--- /dev/null
+++ b/gm/aarectmodes.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+
+static void test4(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkPoint pts[] = {
+ {10, 160}, {610, 160},
+ {610, 160}, {10, 160},
+
+ {610, 160}, {610, 160},
+ {610, 199}, {610, 199},
+
+ {10, 198}, {610, 198},
+ {610, 199}, {10, 199},
+
+ {10, 160}, {10, 160},
+ {10, 199}, {10, 199}
+ };
+ char verbs[] = {
+ 0, 1, 1, 1, 4,
+ 0, 1, 1, 1, 4,
+ 0, 1, 1, 1, 4,
+ 0, 1, 1, 1, 4
+ };
+ SkPath path;
+ SkPoint* ptPtr = pts;
+ for (size_t i = 0; i < sizeof(verbs); ++i) {
+ switch ((SkPath::Verb) verbs[i]) {
+ case SkPath::kMove_Verb:
+ path.moveTo(ptPtr->fX, ptPtr->fY);
+ ++ptPtr;
+ break;
+ case SkPath::kLine_Verb:
+ path.lineTo(ptPtr->fX, ptPtr->fY);
+ ++ptPtr;
+ break;
+ case SkPath::kClose_Verb:
+ path.close();
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
+ }
+ SkRect clip = {0, 130, 772, 531};
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+}
+
+static SkCanvas* create_canvas(int w, int h) {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ bm.allocPixels();
+ bm.eraseColor(0);
+ return new SkCanvas(bm);
+}
+
+static const SkBitmap& extract_bitmap(SkCanvas* canvas) {
+ return canvas->getDevice()->accessBitmap(false);
+}
+
+static const struct {
+ SkXfermode::Mode fMode;
+ const char* fLabel;
+} gModes[] = {
+ { SkXfermode::kClear_Mode, "Clear" },
+ { SkXfermode::kSrc_Mode, "Src" },
+ { SkXfermode::kDst_Mode, "Dst" },
+ { SkXfermode::kSrcOver_Mode, "SrcOver" },
+ { SkXfermode::kDstOver_Mode, "DstOver" },
+ { SkXfermode::kSrcIn_Mode, "SrcIn" },
+ { SkXfermode::kDstIn_Mode, "DstIn" },
+ { SkXfermode::kSrcOut_Mode, "SrcOut" },
+ { SkXfermode::kDstOut_Mode, "DstOut" },
+ { SkXfermode::kSrcATop_Mode, "SrcATop" },
+ { SkXfermode::kDstATop_Mode, "DstATop" },
+ { SkXfermode::kXor_Mode, "Xor" },
+};
+
+const int gWidth = 64;
+const int gHeight = 64;
+const SkScalar W = SkIntToScalar(gWidth);
+const SkScalar H = SkIntToScalar(gHeight);
+
+static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode,
+ SkAlpha a0, SkAlpha a1) {
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ SkRect r = SkRect::MakeWH(W, H);
+ r.inset(W/10, H/10);
+
+ paint.setColor(SK_ColorBLUE);
+ paint.setAlpha(a0);
+ canvas->drawOval(r, paint);
+
+ paint.setColor(SK_ColorRED);
+ paint.setAlpha(a1);
+ paint.setXfermode(mode);
+
+ SkScalar offset = SK_Scalar1 / 3;
+ SkRect rect = SkRect::MakeXYWH(W / 4 + offset,
+ H / 4 + offset,
+ W / 2, H / 2);
+ canvas->drawRect(rect, paint);
+
+ return H;
+}
+
+static SkShader* make_bg_shader() {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+ bm.allocPixels();
+ *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
+ *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC,
+ 0xCC, 0xCC);
+
+ SkShader* s = SkShader::CreateBitmapShader(bm,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+
+ SkMatrix m;
+ m.setScale(SkIntToScalar(6), SkIntToScalar(6));
+ s->setLocalMatrix(m);
+ return s;
+}
+
+namespace skiagm {
+
+ class AARectModesGM : public GM {
+ SkPaint fBGPaint;
+ public:
+ AARectModesGM () {
+ fBGPaint.setShader(make_bg_shader())->unref();
+ }
+
+ protected:
+
+ virtual SkString onShortName() {
+ return SkString("aarectmodes");
+ }
+
+ virtual SkISize onISize() { return make_isize(640, 480); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+// test4(canvas);
+ const SkRect bounds = SkRect::MakeWH(W, H);
+ static const SkAlpha gAlphaValue[] = { 0xFF, 0x88, 0x88 };
+
+ canvas->translate(SkIntToScalar(4), SkIntToScalar(4));
+
+ for (int alpha = 0; alpha < 4; ++alpha) {
+ canvas->save();
+ canvas->save();
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); ++i) {
+ if (6 == i) {
+ canvas->restore();
+ canvas->translate(W * 5, 0);
+ canvas->save();
+ }
+ SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
+
+ canvas->drawRect(bounds, fBGPaint);
+ canvas->saveLayer(&bounds, NULL);
+ SkScalar dy = drawCell(canvas, mode,
+ gAlphaValue[alpha & 1],
+ gAlphaValue[alpha & 2]);
+ canvas->restore();
+
+ canvas->translate(0, dy * 5 / 4);
+ SkSafeUnref(mode);
+ }
+ canvas->restore();
+ canvas->restore();
+ canvas->translate(W * 5 / 4, 0);
+ }
+ }
+
+ // disable pdf for now, since it crashes on mac
+ virtual uint32_t onGetFlags() const { return kSkipPDF_Flag; }
+
+ private:
+ typedef GM INHERITED;
+ };
+
+//////////////////////////////////////////////////////////////////////////////
+
+ static GM* MyFactory(void*) { return new AARectModesGM; }
+ static GMRegistry reg(MyFactory);
+
+}
+
diff --git a/gm/arithmode.cpp b/gm/arithmode.cpp
new file mode 100644
index 0000000..ea015c6
--- /dev/null
+++ b/gm/arithmode.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+
+#include "SkArithmeticMode.h"
+#include "SkGradientShader.h"
+#define WW 100
+#define HH 32
+
+static SkBitmap make_bm() {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, WW, HH);
+ bm.allocPixels();
+ bm.eraseColor(0);
+ return bm;
+}
+
+static SkBitmap make_src() {
+ SkBitmap bm = make_bm();
+ SkCanvas canvas(bm);
+ SkPaint paint;
+ SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
+ SkColor colors[] = {
+ SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
+ SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE
+ };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ canvas.drawPaint(paint);
+ return bm;
+}
+
+static SkBitmap make_dst() {
+ SkBitmap bm = make_bm();
+ SkCanvas canvas(bm);
+ SkPaint paint;
+ SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
+ SkColor colors[] = {
+ SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN, SK_ColorGRAY
+ };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ canvas.drawPaint(paint);
+ return bm;
+}
+
+static SkBitmap make_arith(const SkBitmap& src, const SkBitmap& dst,
+ const SkScalar k[]) {
+ SkBitmap bm = make_bm();
+ SkCanvas canvas(bm);
+ SkPaint paint;
+ canvas.drawBitmap(dst, 0, 0, NULL);
+ SkXfermode* xfer = SkArithmeticMode::Create(k[0], k[1], k[2], k[3]);
+ paint.setXfermode(xfer)->unref();
+ canvas.drawBitmap(src, 0, 0, &paint);
+ return bm;
+}
+
+static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
+ SkPaint paint;
+ paint.setTextSize(SkIntToScalar(24));
+ paint.setAntiAlias(true);
+ for (int i = 0; i < 4; ++i) {
+ SkString str;
+ str.appendScalar(k[i]);
+ SkScalar width = paint.measureText(str.c_str(), str.size());
+ canvas->drawText(str.c_str(), str.size(), x, y + paint.getTextSize(), paint);
+ x += width + SkIntToScalar(10);
+ }
+}
+
+class ArithmodeGM : public skiagm::GM {
+public:
+ ArithmodeGM () {}
+
+protected:
+
+ virtual SkString onShortName() {
+ return SkString("arithmode");
+ }
+
+ virtual SkISize onISize() { return SkISize::Make(640, 480); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkBitmap src = make_src();
+ SkBitmap dst = make_dst();
+
+ const SkScalar one = SK_Scalar1;
+ static const SkScalar K[] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, one,
+ 0, one, 0, 0,
+ 0, 0, one, 0,
+ 0, one, one, 0,
+ 0, one, -one, 0,
+ 0, one/2, one/2, 0,
+ 0, one/2, one/2, one/4,
+ 0, one/2, one/2, -one/4,
+ one/4, one/2, one/2, 0,
+ -one/4, one/2, one/2, 0,
+ };
+
+ const SkScalar* k = K;
+ const SkScalar* stop = k + SK_ARRAY_COUNT(K);
+ SkScalar y = 0;
+ SkScalar x = 0;
+ SkScalar gap = SkIntToScalar(src.width() + 20);
+ while (k < stop) {
+ SkScalar x = 0;
+ SkBitmap res = make_arith(src, dst, k);
+ canvas->drawBitmap(src, x, y, NULL);
+ x += gap;
+ canvas->drawBitmap(dst, x, y, NULL);
+ x += gap;
+ canvas->drawBitmap(res, x, y, NULL);
+ x += gap;
+ show_k_text(canvas, x, y, k);
+ k += 4;
+ y += SkIntToScalar(src.height() + 12);
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static skiagm::GM* MyFactory(void*) { return new ArithmodeGM; }
+static skiagm::GMRegistry reg(MyFactory);
diff --git a/gm/bitmapcopy.cpp b/gm/bitmapcopy.cpp
new file mode 100644
index 0000000..249ec43
--- /dev/null
+++ b/gm/bitmapcopy.cpp
@@ -0,0 +1,121 @@
+
+/*
+ * Copyright 2011 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"
+
+namespace skiagm {
+
+static const char* gConfigNames[] = {
+ "unknown config",
+ "A1",
+ "A8",
+ "Index8",
+ "565",
+ "4444",
+ "8888"
+};
+
+SkBitmap::Config gConfigs[] = {
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kARGB_4444_Config,
+ SkBitmap::kARGB_8888_Config,
+};
+
+#define NUM_CONFIGS (sizeof(gConfigs) / sizeof(SkBitmap::Config))
+
+static void draw_checks(SkCanvas* canvas, int width, int height) {
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ canvas->drawRectCoords(0, 0, width / 2, height / 2, paint);
+ paint.setColor(SK_ColorGREEN);
+ canvas->drawRectCoords(width / 2, 0, width, height / 2, paint);
+ paint.setColor(SK_ColorBLUE);
+ canvas->drawRectCoords(0, height / 2, width / 2, height, paint);
+ paint.setColor(SK_ColorYELLOW);
+ canvas->drawRectCoords(width / 2, height / 2, width, height, paint);
+}
+
+class BitmapCopyGM : public GM {
+public:
+ SkBitmap fDst[NUM_CONFIGS];
+
+ BitmapCopyGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("bitmapcopy");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(540, 330);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkScalar horizMargin(SkIntToScalar(10));
+ SkScalar vertMargin(SkIntToScalar(10));
+
+ draw_checks(canvas, 40, 40);
+ SkBitmap src = canvas->getDevice()->accessBitmap(false);
+
+ for (unsigned i = 0; i < NUM_CONFIGS; ++i) {
+ if (!src.deepCopyTo(&fDst[i], gConfigs[i])) {
+ src.copyTo(&fDst[i], gConfigs[i]);
+ }
+ }
+
+ canvas->clear(0xFFDDDDDD);
+ paint.setAntiAlias(true);
+ SkScalar width = SkIntToScalar(40);
+ SkScalar height = SkIntToScalar(40);
+ if (paint.getFontSpacing() > height) {
+ height = paint.getFontSpacing();
+ }
+ for (unsigned i = 0; i < NUM_CONFIGS; i++) {
+ const char* name = gConfigNames[src.config()];
+ SkScalar textWidth = paint.measureText(name, strlen(name));
+ if (textWidth > width) {
+ width = textWidth;
+ }
+ }
+ SkScalar horizOffset = width + horizMargin;
+ SkScalar vertOffset = height + vertMargin;
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+
+ for (unsigned i = 0; i < NUM_CONFIGS; i++) {
+ canvas->save();
+ // Draw destination config name
+ const char* name = gConfigNames[fDst[i].config()];
+ SkScalar textWidth = paint.measureText(name, strlen(name));
+ SkScalar x = (width - textWidth) / SkScalar(2);
+ SkScalar y = paint.getFontSpacing() / SkScalar(2);
+ canvas->drawText(name, strlen(name), x, y, paint);
+
+ // Draw destination bitmap
+ canvas->translate(0, vertOffset);
+ x = (width - 40) / SkScalar(2);
+ canvas->drawBitmap(fDst[i], x, 0, &paint);
+ canvas->restore();
+
+ canvas->translate(horizOffset, 0);
+ }
+ }
+
+ virtual uint32_t onGetFlags() const { return kSkipPicture_Flag; }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new BitmapCopyGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/bitmapfilters.cpp b/gm/bitmapfilters.cpp
index 3903913..cf98dcd 100644
--- a/gm/bitmapfilters.cpp
+++ b/gm/bitmapfilters.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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"
namespace skiagm {
@@ -79,6 +86,7 @@ public:
fBM8.copyTo(&fBM4444, SkBitmap::kARGB_4444_Config);
fBM8.copyTo(&fBM16, SkBitmap::kRGB_565_Config);
fBM8.copyTo(&fBM32, SkBitmap::kARGB_8888_Config);
+ this->setBGColor(0xFFDDDDDD);
}
protected:
@@ -91,7 +99,6 @@ protected:
}
virtual void onDraw(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
SkScalar x = SkIntToScalar(10);
SkScalar y = SkIntToScalar(10);
diff --git a/gm/bitmapscroll.cpp b/gm/bitmapscroll.cpp
new file mode 100644
index 0000000..70d1052
--- /dev/null
+++ b/gm/bitmapscroll.cpp
@@ -0,0 +1,147 @@
+
+/*
+ * Copyright 2011 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"
+
+namespace skiagm {
+
+/** Create a bitmap image suitable for testing SkBitmap::scrollRect().
+ *
+ * @param quarterWidth bitmap will be 4x this many pixels wide
+ * @param quarterHeight bitmap will be 4x this many pixels tall
+ * @param bitmap the bitmap data is written into this object
+ */
+static void make_bitmap(int quarterWidth, int quarterHeight, SkBitmap *bitmap) {
+ SkPaint pRed, pWhite, pGreen, pBlue, pLine, pAlphaGray;
+ pRed.setColor(0xFFFF9999);
+ pWhite.setColor(0xFFFFFFFF);
+ pGreen.setColor(0xFF99FF99);
+ pBlue.setColor(0xFF9999FF);
+ pLine.setColor(0xFF000000);
+ pLine.setStyle(SkPaint::kStroke_Style);
+ pAlphaGray.setColor(0x66888888);
+
+ // Prepare bitmap, and a canvas that draws into it.
+ bitmap->reset();
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config,
+ quarterWidth*4, quarterHeight*4);
+ bitmap->allocPixels();
+ SkCanvas canvas(*bitmap);
+
+ SkScalar w = SkIntToScalar(quarterWidth);
+ SkScalar h = SkIntToScalar(quarterHeight);
+ canvas.drawRectCoords( 0, 0, w*2, h*2, pRed);
+ canvas.drawRectCoords(w*2, 0, w*4, h*2, pGreen);
+ canvas.drawRectCoords( 0, h*2, w*2, h*4, pBlue);
+ canvas.drawRectCoords(w*2, h*2, w*4, h*4, pWhite);
+ canvas.drawRectCoords(w, h, w*3, h*3, pAlphaGray);
+ canvas.drawLine(w*2, 0, w*2, h*4, pLine);
+ canvas.drawLine( 0, h*2, w*4, h*2, pLine);
+ canvas.drawRectCoords(w, h, w*3, h*3, pLine);
+}
+
+class BitmapScrollGM : public GM {
+public:
+ BitmapScrollGM() {
+ // Create the original bitmap.
+ make_bitmap(quarterWidth, quarterHeight, &origBitmap);
+ this->setBGColor(0xFFDDDDDD);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("bitmapscroll");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(800, 600);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkIRect scrollCenterRegion = SkIRect::MakeXYWH(
+ quarterWidth, quarterHeight, quarterWidth*2+1, quarterHeight*2+1);
+ int x = quarterWidth;
+ int y = quarterHeight;
+ int xSpacing = quarterWidth * 20;
+ int ySpacing = quarterHeight * 16;
+
+ // Draw left-hand text labels.
+ drawLabel(canvas, "scroll entire bitmap",
+ x, y, x, y + ySpacing);
+ drawLabel(canvas, "scroll part of bitmap",
+ x, y + ySpacing, x, y + ySpacing*2);
+ x += 30;
+
+ // Draw various permutations of scrolled bitmaps, scrolling a bit
+ // further each time.
+ draw9(canvas, x, y, NULL, quarterWidth*1/2, quarterHeight*1/2);
+ draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
+ quarterWidth*1/2, quarterHeight*1/2);
+ x += xSpacing;
+ draw9(canvas, x, y, NULL, quarterWidth*3/2, quarterHeight*3/2);
+ draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
+ quarterWidth*3/2, quarterHeight*3/2);
+ x += xSpacing;
+ draw9(canvas, x, y, NULL, quarterWidth*5/2, quarterHeight*5/2);
+ draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
+ quarterWidth*5/2, quarterHeight*5/2);
+ x += xSpacing;
+ draw9(canvas, x, y, NULL, quarterWidth*9/2, quarterHeight*9/2);
+ draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
+ quarterWidth*9/2, quarterHeight*9/2);
+ }
+
+ void drawLabel(SkCanvas* canvas, const char *text, int startX, int startY,
+ int endX, int endY) {
+ SkPaint paint;
+ paint.setColor(0xFF000000);
+ SkPath path;
+ path.moveTo(SkIntToScalar(startX), SkIntToScalar(startY));
+ path.lineTo(SkIntToScalar(endX), SkIntToScalar(endY));
+ canvas->drawTextOnPath(text, strlen(text), path, NULL, paint);
+ }
+
+ /** Stamp out 9 copies of origBitmap, scrolled in each direction (and
+ * not scrolled at all).
+ */
+ void draw9(SkCanvas* canvas, int x, int y, SkIRect* subset,
+ int scrollX, int scrollY) {
+ for (int yMult=-1; yMult<=1; yMult++) {
+ for (int xMult=-1; xMult<=1; xMult++) {
+ // Figure out the (x,y) to draw this copy at
+ SkScalar bitmapX = SkIntToScalar(
+ x + quarterWidth * 5 * (xMult+1));
+ SkScalar bitmapY = SkIntToScalar(
+ y + quarterHeight * 5 * (yMult+1));
+
+ // Scroll a new copy of the bitmap, and then draw it.
+ // scrollRect() should always return true, even if it's a no-op
+ SkBitmap scrolledBitmap;
+ bool copyToReturnValue = origBitmap.copyTo(
+ &scrolledBitmap, origBitmap.config());
+ SkASSERT(copyToReturnValue);
+ bool scrollRectReturnValue = scrolledBitmap.scrollRect(
+ subset, scrollX * xMult, scrollY * yMult);
+ SkASSERT(scrollRectReturnValue);
+ canvas->drawBitmap(scrolledBitmap, bitmapX, bitmapY);
+ }
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+ static const int quarterWidth = 10;
+ static const int quarterHeight = 14;
+ SkBitmap origBitmap;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new BitmapScrollGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/blurs.cpp b/gm/blurs.cpp
index c934178..69504f7 100644
--- a/gm/blurs.cpp
+++ b/gm/blurs.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkBlurMaskFilter.h"
@@ -5,7 +12,9 @@ namespace skiagm {
class BlursGM : public GM {
public:
- BlursGM() {}
+ BlursGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
protected:
virtual SkString onShortName() {
@@ -16,13 +25,7 @@ protected:
return make_isize(700, 500);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- drawBG(canvas);
-
SkBlurMaskFilter::BlurStyle NONE = SkBlurMaskFilter::BlurStyle(-999);
static const struct {
SkBlurMaskFilter::BlurStyle fStyle;
diff --git a/gm/colormatrix.cpp b/gm/colormatrix.cpp
new file mode 100644
index 0000000..0a4acfd
--- /dev/null
+++ b/gm/colormatrix.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 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 "SkColorMatrixFilter.h"
+
+#define WIDTH 500
+#define HEIGHT 500
+
+namespace skiagm {
+
+class ColorMatrixGM : public GM {
+public:
+ ColorMatrixGM() {
+ this->setBGColor(0xFF808080);
+ fBitmap = createBitmap(64, 64);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("colormatrix");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(WIDTH, HEIGHT);
+ }
+
+ SkBitmap createBitmap(int width, int height) {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bm.allocPixels();
+ SkCanvas canvas(bm);
+ canvas.clear(0x0);
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ SkPaint paint;
+ paint.setColor(SkColorSetARGB(255, x * 255 / width, y * 255 / height, 0));
+ canvas.drawRect(SkRect::MakeXYWH(x, y, 1, 1), paint);
+ }
+ }
+ return bm;
+ }
+ virtual void onDraw(SkCanvas* canvas) {
+
+ SkPaint paint;
+ SkColorMatrix matrix;
+ SkColorMatrixFilter* filter = new SkColorMatrixFilter();
+ paint.setColorFilter(filter)->unref();
+
+ matrix.setIdentity();
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 0, 0, &paint);
+
+ matrix.setRotate(SkColorMatrix::kR_Axis, 90);
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 80, 0, &paint);
+
+ matrix.setRotate(SkColorMatrix::kG_Axis, 90);
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 160, 0, &paint);
+
+ matrix.setRotate(SkColorMatrix::kB_Axis, 90);
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 240, 0, &paint);
+
+ matrix.setSaturation(SkFloatToScalar(0.0f));
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 0, 80, &paint);
+
+ matrix.setSaturation(SkFloatToScalar(0.5f));
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 80, 80, &paint);
+
+ matrix.setSaturation(SkFloatToScalar(1.0f));
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 160, 80, &paint);
+
+ matrix.setSaturation(SkFloatToScalar(2.0f));
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 240, 80, &paint);
+
+ matrix.setRGB2YUV();
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 0, 160, &paint);
+
+ matrix.setYUV2RGB();
+ filter->setMatrix(matrix);
+ canvas->drawBitmap(fBitmap, 80, 160, &paint);
+
+ SkScalar s1 = SK_Scalar1;
+ SkScalar s255 = SkIntToScalar(255);
+ // Move red into alpha, set color to white
+ SkScalar data[20] = {
+ 0, 0, 0, 0, s255,
+ 0, 0, 0, 0, s255,
+ 0, 0, 0, 0, s255,
+ s1, 0, 0, 0, 0,
+ };
+
+ filter->setArray(data);
+ canvas->drawBitmap(fBitmap, 160, 160, &paint);
+ }
+
+private:
+ SkBitmap fBitmap;
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new ColorMatrixGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/complexclip.cpp b/gm/complexclip.cpp
index 867d230..30bb50b 100644
--- a/gm/complexclip.cpp
+++ b/gm/complexclip.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkCanvas.h"
//#include "SkParsePath.h"
@@ -6,22 +13,27 @@
namespace skiagm {
+static const SkColor gPathColor = SK_ColorBLACK;
+static const SkColor gClipAColor = SK_ColorBLUE;
+static const SkColor gClipBColor = SK_ColorRED;
+
class ComplexClipGM : public GM {
+ bool fDoAAClip;
public:
- ComplexClipGM() {
+ ComplexClipGM(bool aaclip) : fDoAAClip(aaclip) {
+ this->setBGColor(0xFFDDDDDD);
+// this->setBGColor(SkColorSetRGB(0xB0,0xDD,0xB0));
}
protected:
SkString onShortName() {
- return SkString("complexclip");
+ SkString str;
+ str.printf("complexclip_%s", fDoAAClip ? "aa" : "bw");
+ return str;
}
- SkISize onISize() { return make_isize(550, 1000); }
-
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(SkColorSetRGB(0xA0,0xDD,0xA0));
- }
+ SkISize onISize() { return make_isize(970, 780); }
virtual void onDraw(SkCanvas* canvas) {
SkPath path;
@@ -40,10 +52,9 @@ protected:
path.lineTo(SkIntToScalar(50), SkIntToScalar(150));
path.close();
path.setFillType(SkPath::kEvenOdd_FillType);
- SkColor pathColor = SK_ColorBLACK;
SkPaint pathPaint;
pathPaint.setAntiAlias(true);
- pathPaint.setColor(pathColor);
+ pathPaint.setColor(gPathColor);
SkPath clipA;
clipA.moveTo(SkIntToScalar(10), SkIntToScalar(20));
@@ -52,7 +63,6 @@ protected:
clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
clipA.lineTo(SkIntToScalar(-5), SkIntToScalar(180));
clipA.close();
- SkColor colorA = SK_ColorCYAN;
SkPath clipB;
clipB.moveTo(SkIntToScalar(40), SkIntToScalar(10));
@@ -61,21 +71,10 @@ protected:
clipB.lineTo(SkIntToScalar(40), SkIntToScalar(185));
clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
clipB.close();
- SkColor colorB = SK_ColorRED;
- drawBG(canvas);
SkPaint paint;
paint.setAntiAlias(true);
-
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(0);
-
- canvas->translate(SkIntToScalar(10),SkIntToScalar(10));
- canvas->drawPath(path, pathPaint);
- paint.setColor(colorA);
- canvas->drawPath(clipA, paint);
- paint.setColor(colorB);
- canvas->drawPath(clipB, paint);
+ paint.setTextSize(SkIntToScalar(20));
static const struct {
SkRegion::Op fOp;
@@ -88,65 +87,77 @@ protected:
{SkRegion::kReverseDifference_Op, "RDiff "}
};
- canvas->translate(0, SkIntToScalar(40));
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
- canvas->save();
- for (int invA = 0; invA < 2; ++invA) {
+ for (int invBits = 0; invBits < 4; ++invBits) {
+ canvas->save();
for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
- int idx = invA * SK_ARRAY_COUNT(gOps) + op;
- if (!(idx % 3)) {
- canvas->restore();
- canvas->translate(0, SkIntToScalar(250));
- canvas->save();
- }
+ this->drawHairlines(canvas, path, clipA, clipB);
+
+ bool doInvA = SkToBool(invBits & 1);
+ bool doInvB = SkToBool(invBits & 2);
canvas->save();
// set clip
- clipA.setFillType(invA ? SkPath::kInverseEvenOdd_FillType :
- SkPath::kEvenOdd_FillType);
- canvas->clipPath(clipA);
- canvas->clipPath(clipB, gOps[op].fOp);
+ clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
+ SkPath::kEvenOdd_FillType);
+ clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
+ SkPath::kEvenOdd_FillType);
+ canvas->clipPath(clipA, SkRegion::kIntersect_Op, fDoAAClip);
+ canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
// draw path clipped
canvas->drawPath(path, pathPaint);
canvas->restore();
- // draw path in hairline
- paint.setColor(pathColor);
- canvas->drawPath(path, paint);
- // draw clips in hair line
- paint.setColor(colorA);
- canvas->drawPath(clipA, paint);
- paint.setColor(colorB);
- canvas->drawPath(clipB, paint);
-
- paint.setTextSize(SkIntToScalar(20));
-
- SkScalar txtX = SkIntToScalar(55);
- paint.setColor(colorA);
- const char* aTxt = invA ? "InverseA " : "A ";
+ SkScalar txtX = SkIntToScalar(45);
+ paint.setColor(gClipAColor);
+ const char* aTxt = doInvA ? "InvA " : "A ";
canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
txtX += paint.measureText(aTxt, strlen(aTxt));
paint.setColor(SK_ColorBLACK);
canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
txtX, SkIntToScalar(220), paint);
txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
- paint.setColor(colorB);
- canvas->drawText("B", 1, txtX, SkIntToScalar(220), paint);
+ paint.setColor(gClipBColor);
+ const char* bTxt = doInvB ? "InvB " : "B ";
+ canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint);
canvas->translate(SkIntToScalar(250),0);
}
+ canvas->restore();
+ canvas->translate(0, SkIntToScalar(250));
}
- canvas->restore();
}
private:
+ void drawHairlines(SkCanvas* canvas, const SkPath& path,
+ const SkPath& clipA, const SkPath& clipB) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ const SkAlpha fade = 0x33;
+
+ // draw path in hairline
+ paint.setColor(gPathColor); paint.setAlpha(fade);
+ canvas->drawPath(path, paint);
+
+ // draw clips in hair line
+ paint.setColor(gClipAColor); paint.setAlpha(fade);
+ canvas->drawPath(clipA, paint);
+ paint.setColor(gClipBColor); paint.setAlpha(fade);
+ canvas->drawPath(clipB, paint);
+ }
+
typedef GM INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
-static GM* MyFactory(void*) { return new ComplexClipGM; }
-static GMRegistry reg(MyFactory);
+static GM* gFact0(void*) { return new ComplexClipGM(false); }
+static GM* gFact1(void*) { return new ComplexClipGM(true); }
+
+static GMRegistry gReg0(gFact0);
+static GMRegistry gReg1(gFact1);
}
diff --git a/gm/complexclip2.cpp b/gm/complexclip2.cpp
new file mode 100644
index 0000000..d6b653e
--- /dev/null
+++ b/gm/complexclip2.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPath.h"
+#include "SkRandom.h"
+
+namespace skiagm {
+
+class ComplexClip2GM : public GM {
+public:
+ ComplexClip2GM() {
+ this->setBGColor(SkColorSetRGB(0xDD,0xA0,0xDD));
+
+ SkScalar xA = 0 * SK_Scalar1;
+ SkScalar xB = 10 * SK_Scalar1;
+ SkScalar xC = 20 * SK_Scalar1;
+ SkScalar xD = 30 * SK_Scalar1;
+ SkScalar xE = 40 * SK_Scalar1;
+ SkScalar xF = 50 * SK_Scalar1;
+
+ SkScalar yA = 0 * SK_Scalar1;
+ SkScalar yB = 10 * SK_Scalar1;
+ SkScalar yC = 20 * SK_Scalar1;
+ SkScalar yD = 30 * SK_Scalar1;
+ SkScalar yE = 40 * SK_Scalar1;
+ SkScalar yF = 50 * SK_Scalar1;
+
+ fWidth = xF - xA;
+ fHeight = yF - yA;
+
+ fRects[0].set(xB, yB, xE, yE);
+ fRectColors[0] = SK_ColorRED;
+
+ fRects[1].set(xA, yA, xD, yD);
+ fRectColors[1] = SK_ColorGREEN;
+
+ fRects[2].set(xC, yA, xF, yD);
+ fRectColors[2] = SK_ColorBLUE;
+
+ fRects[3].set(xA, yC, xD, yF);
+ fRectColors[3] = SK_ColorYELLOW;
+
+ fRects[4].set(xC, yC, xF, yF);
+ fRectColors[4] = SK_ColorCYAN;
+
+ fTotalWidth = kCols * fWidth + SK_Scalar1 * (kCols + 1) * kPadX;
+ fTotalHeight = kRows * fHeight + SK_Scalar1 * (kRows + 1) * kPadY;
+
+ SkRegion::Op ops[] = {
+ SkRegion::kDifference_Op,
+ SkRegion::kIntersect_Op,
+ SkRegion::kUnion_Op,
+ SkRegion::kXOR_Op,
+ SkRegion::kReverseDifference_Op,
+ SkRegion::kReplace_Op,
+ };
+
+ SkRandom r;
+ for (int i = 0; i < kRows; ++i) {
+ for (int j = 0; j < kCols; ++j) {
+ for (int k = 0; k < 5; ++k) {
+ fOps[j*kRows+i][k] = ops[r.nextU() % SK_ARRAY_COUNT(ops)];
+ }
+ }
+ }
+ }
+
+protected:
+
+ static const int kRows = 5;
+ static const int kCols = 5;
+ static const int kPadX = 20;
+ static const int kPadY = 20;
+
+ virtual SkString onShortName() {
+ return SkString("complexclip2");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(SkScalarRoundToInt(fTotalWidth),
+ SkScalarRoundToInt(fTotalHeight));
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint rectPaint;
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+
+ SkPaint fillPaint;
+ fillPaint.setColor(SkColorSetRGB(0xA0,0xDD,0xA0));
+
+ for (int i = 0; i < kRows; ++i) {
+ for (int j = 0; j < kCols; ++j) {
+ canvas->save();
+ canvas->translate(kPadX * SK_Scalar1 + (fWidth + kPadX * SK_Scalar1)*j,
+ kPadY * SK_Scalar1 + (fHeight + kPadY * SK_Scalar1)*i);
+ canvas->save();
+ for (int k = 0; k < 5; ++k) {
+ canvas->clipRect(fRects[k], fOps[j*kRows+i][k]);
+ }
+ canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
+ canvas->restore();
+ for (int k = 0; k < 5; ++k) {
+ rectPaint.setColor(fRectColors[k]);
+ canvas->drawRect(fRects[k], rectPaint);
+ }
+ canvas->restore();
+ }
+ }
+ }
+private:
+ SkRect fRects[5];
+ SkColor fRectColors[5];
+ SkRegion::Op fOps[kRows * kCols][5];
+ SkScalar fWidth;
+ SkScalar fHeight;
+ SkScalar fTotalWidth;
+ SkScalar fTotalHeight;
+
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new ComplexClip2GM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/cubicpaths.cpp b/gm/cubicpaths.cpp
new file mode 100644
index 0000000..7cd3df1
--- /dev/null
+++ b/gm/cubicpaths.cpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+namespace skiagm {
+
+class CubicPathGM : public GM {
+public:
+ CubicPathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("cubicpath");
+ }
+
+ SkISize onISize() { return make_isize(1240, 390); }
+
+ void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
+ const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName;
+ };
+ PathAndName path;
+ path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
+ path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
+ 60*SK_Scalar1, 20*SK_Scalar1,
+ 75*SK_Scalar1, 10*SK_Scalar1);
+ path.fName = "moveTo-cubic";
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Cubic Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, with stroke width 10";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
+ canvas->save();
+ for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
+ if (0 < cap) {
+ canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
+ }
+ canvas->save();
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 < fill) {
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (0 < style) {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ this->drawPath(path.fPath, canvas, color, rect,
+ gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
+ gFills[fill].fFill, SK_Scalar1*10);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gCaps[cap].fName,
+ strlen(gCaps[cap].fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+class CubicClosePathGM : public GM {
+public:
+ CubicClosePathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("cubicclosepath");
+ }
+
+ SkISize onISize() { return make_isize(1240, 390); }
+
+ void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
+ const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName;
+ };
+ PathAndName path;
+ path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
+ path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
+ 60*SK_Scalar1, 20*SK_Scalar1,
+ 75*SK_Scalar1, 10*SK_Scalar1);
+ path.fPath.close();
+ path.fName = "moveTo-cubic-close";
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Cubic Closed Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, with stroke width 10";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
+ canvas->save();
+ for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
+ if (0 < cap) {
+ canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
+ }
+ canvas->save();
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 < fill) {
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (0 < style) {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ this->drawPath(path.fPath, canvas, color, rect,
+ gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
+ gFills[fill].fFill, SK_Scalar1*10);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gCaps[cap].fName,
+ strlen(gCaps[cap].fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* CubicPathFactory(void*) { return new CubicPathGM; }
+static GMRegistry regCubicPath(CubicPathFactory);
+
+static GM* CubicClosePathFactory(void*) { return new CubicClosePathGM; }
+static GMRegistry regCubicClosePath(CubicClosePathFactory);
+
+}
diff --git a/gm/degeneratesegments.cpp b/gm/degeneratesegments.cpp
new file mode 100644
index 0000000..63d9dba
--- /dev/null
+++ b/gm/degeneratesegments.cpp
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+namespace skiagm {
+
+class DegenerateSegmentsGM : public GM {
+public:
+ DegenerateSegmentsGM() {}
+
+protected:
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName1;
+ const char* fName2;
+ };
+
+ SkString onShortName() {
+ return SkString("degeneratesegments");
+ }
+
+ SkISize onISize() { return make_isize(896, 930); }
+
+ typedef SkPoint (*AddSegmentFunc)(SkPath&, SkPoint&);
+
+ // We need to use explicit commands here, instead of addPath, because we
+ // do not want the moveTo that is added at the beginning of a path to
+ // appear in the appended path.
+ static SkPoint AddMove(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ return moveToPt;
+ }
+
+ static SkPoint AddMoveClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.close();
+ return moveToPt;
+ }
+
+ static SkPoint AddDegenLine(SkPath& path, SkPoint& startPt) {
+ path.lineTo(startPt);
+ return startPt;
+ }
+
+ static SkPoint AddMoveDegenLine(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.lineTo(moveToPt);
+ return moveToPt;
+ }
+
+ static SkPoint AddMoveDegenLineClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.lineTo(moveToPt);
+ path.close();
+ return moveToPt;
+ }
+
+ static SkPoint AddDegenQuad(SkPath& path, SkPoint& startPt) {
+ path.quadTo(startPt, startPt);
+ return startPt;
+ }
+
+ static SkPoint AddMoveDegenQuad(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.quadTo(moveToPt, moveToPt);
+ return moveToPt;
+ }
+
+ static SkPoint AddMoveDegenQuadClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.quadTo(moveToPt, moveToPt);
+ path.close();
+ return moveToPt;
+ }
+
+ static SkPoint AddDegenCubic(SkPath& path, SkPoint& startPt) {
+ path.cubicTo(startPt, startPt, startPt);
+ return startPt;
+ }
+
+ static SkPoint AddMoveDegenCubic(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.cubicTo(moveToPt, moveToPt, moveToPt);
+ return moveToPt;
+ }
+
+ static SkPoint AddMoveDegenCubicClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ path.moveTo(moveToPt);
+ path.cubicTo(moveToPt, moveToPt, moveToPt);
+ path.close();
+ return moveToPt;
+ }
+
+ static SkPoint AddClose(SkPath& path, SkPoint& startPt) {
+ path.close();
+ return startPt;
+ }
+
+ static SkPoint AddLine(SkPath& path, SkPoint& startPt) {
+ SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.lineTo(endPt);
+ return endPt;
+ }
+
+ static SkPoint AddMoveLine(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.moveTo(moveToPt);
+ path.lineTo(endPt);
+ return endPt;
+ }
+
+ static SkPoint AddMoveLineClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.moveTo(moveToPt);
+ path.lineTo(endPt);
+ path.close();
+ return endPt;
+ }
+
+ static SkPoint AddQuad(SkPath& path, SkPoint& startPt) {
+ SkPoint midPt = startPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.quadTo(midPt, endPt);
+ return endPt;
+ }
+
+ static SkPoint AddMoveQuad(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.moveTo(moveToPt);
+ path.quadTo(midPt, endPt);
+ return endPt;
+ }
+
+ static SkPoint AddMoveQuadClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.moveTo(moveToPt);
+ path.quadTo(midPt, endPt);
+ path.close();
+ return endPt;
+ }
+
+ static SkPoint AddCubic(SkPath& path, SkPoint& startPt) {
+ SkPoint t1Pt = startPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint t2Pt = startPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint endPt = startPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.cubicTo(t1Pt, t2Pt, endPt);
+ return endPt;
+ }
+
+ static SkPoint AddMoveCubic(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.moveTo(moveToPt);
+ path.cubicTo(t1Pt, t2Pt, endPt);
+ return endPt;
+ }
+
+ static SkPoint AddMoveCubicClose(SkPath& path, SkPoint& startPt) {
+ SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1);
+ SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1);
+ SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0);
+ path.moveTo(moveToPt);
+ path.cubicTo(t1Pt, t2Pt, endPt);
+ path.close();
+ return endPt;
+ }
+
+ void drawPath(SkPath& path, SkCanvas* canvas, SkColor color,
+ const SkRect& clip, SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ static const AddSegmentFunc gSegmentFunctions[] = {
+ AddMove,
+ AddMoveClose,
+ AddDegenLine,
+ AddMoveDegenLine,
+ AddMoveDegenLineClose,
+ AddDegenQuad,
+ AddMoveDegenQuad,
+ AddMoveDegenQuadClose,
+ AddDegenCubic,
+ AddMoveDegenCubic,
+ AddMoveDegenCubicClose,
+ AddClose,
+ AddLine,
+ AddMoveLine,
+ AddMoveLineClose,
+ AddQuad,
+ AddMoveQuad,
+ AddMoveQuadClose,
+ AddCubic,
+ AddMoveCubic,
+ AddMoveCubicClose
+ };
+ static const char* gSegmentNames[] = {
+ "Move",
+ "MoveClose",
+ "DegenLine",
+ "MoveDegenLine",
+ "MoveDegenLineClose",
+ "DegenQuad",
+ "MoveDegenQuad",
+ "MoveDegenQuadClose",
+ "DegenCubic",
+ "MoveDegenCubic",
+ "MoveDegenCubicClose",
+ "Close",
+ "Line",
+ "MoveLine",
+ "MoveLineClose",
+ "Quad",
+ "MoveQuad",
+ "MoveQuadClose",
+ "Cubic",
+ "MoveCubic",
+ "MoveCubicClose"
+ };
+
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke 10"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke 10 And Fill"}
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Random Paths Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, "
+ "with Stroke width 6";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(220*SK_Scalar1, 50*SK_Scalar1);
+ canvas->save();
+ canvas->translate(2*SK_Scalar1, 30 * SK_Scalar1); // The title
+ canvas->save();
+ unsigned numSegments = SK_ARRAY_COUNT(gSegmentFunctions);
+ unsigned numCaps = SK_ARRAY_COUNT(gCaps);
+ unsigned numStyles = SK_ARRAY_COUNT(gStyles);
+ unsigned numFills = SK_ARRAY_COUNT(gFills);
+ for (size_t row = 0; row < 6; ++row) {
+ if (0 < row) {
+ canvas->translate(0, rect.height() + 100*SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t column = 0; column < 4; ++column) {
+ if (0 < column) {
+ canvas->translate(rect.width() + 4*SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ StyleAndName style = gStyles[(rand.nextU() >> 16) % numStyles];
+ CapAndName cap = gCaps[(rand.nextU() >> 16) % numCaps];
+ FillAndName fill = gFills[(rand.nextU() >> 16) % numFills];
+ SkPath path;
+ unsigned s1 = (rand.nextU() >> 16) % numSegments;
+ unsigned s2 = (rand.nextU() >> 16) % numSegments;
+ unsigned s3 = (rand.nextU() >> 16) % numSegments;
+ unsigned s4 = (rand.nextU() >> 16) % numSegments;
+ unsigned s5 = (rand.nextU() >> 16) % numSegments;
+ SkPoint pt = SkPoint::Make(10*SK_Scalar1, 0);
+ pt = gSegmentFunctions[s1](path, pt);
+ pt = gSegmentFunctions[s2](path, pt);
+ pt = gSegmentFunctions[s3](path, pt);
+ pt = gSegmentFunctions[s4](path, pt);
+ pt = gSegmentFunctions[s5](path, pt);
+
+ this->drawPath(path, canvas, color, rect,
+ cap.fCap, cap.fJoin, style.fStyle,
+ fill.fFill, SK_Scalar1*6);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(style.fName,
+ strlen(style.fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(fill.fName,
+ strlen(fill.fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(cap.fName,
+ strlen(cap.fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gSegmentNames[s1],
+ strlen(gSegmentNames[s1]),
+ 0, rect.height() + 48 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gSegmentNames[s2],
+ strlen(gSegmentNames[s2]),
+ 0, rect.height() + 60 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gSegmentNames[s3],
+ strlen(gSegmentNames[s3]),
+ 0, rect.height() + 72 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gSegmentNames[s4],
+ strlen(gSegmentNames[s4]),
+ 0, rect.height() + 84 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gSegmentNames[s5],
+ strlen(gSegmentNames[s5]),
+ 0, rect.height() + 96 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new DegenerateSegmentsGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/drawbitmaprect.cpp b/gm/drawbitmaprect.cpp
new file mode 100644
index 0000000..5832a9c
--- /dev/null
+++ b/gm/drawbitmaprect.cpp
@@ -0,0 +1,155 @@
+
+/*
+ * Copyright 2011 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 "SkShader.h"
+#include "SkColorPriv.h"
+
+// effects
+#include "SkGradientShader.h"
+
+
+namespace skiagm {
+
+static void makebm(SkBitmap* bm, SkBitmap::Config config, int w, int h) {
+ bm->setConfig(config, w, h);
+ bm->allocPixels();
+ bm->eraseColor(0);
+
+ SkCanvas canvas(*bm);
+
+ SkScalar wScalar = SkIntToScalar(w);
+ SkScalar hScalar = SkIntToScalar(h);
+
+ SkPoint pt = { wScalar / 2, hScalar / 2 };
+
+ SkScalar radius = 4 * SkMaxScalar(wScalar, hScalar);
+
+ SkColor colors[] = { SK_ColorRED, SK_ColorYELLOW,
+ SK_ColorGREEN, SK_ColorMAGENTA,
+ SK_ColorBLUE, SK_ColorCYAN,
+ SK_ColorRED};
+
+ SkScalar pos[] = {0,
+ SK_Scalar1 / 6,
+ 2 * SK_Scalar1 / 6,
+ 3 * SK_Scalar1 / 6,
+ 4 * SK_Scalar1 / 6,
+ 5 * SK_Scalar1 / 6,
+ SK_Scalar1};
+
+ SkPaint paint;
+ paint.setShader(SkGradientShader::CreateRadial(
+ pt, radius,
+ colors, pos,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kRepeat_TileMode))->unref();
+ SkRect rect = SkRect::MakeWH(wScalar, hScalar);
+ SkMatrix mat = SkMatrix::I();
+ for (int i = 0; i < 4; ++i) {
+ paint.getShader()->setLocalMatrix(mat);
+ canvas.drawRect(rect, paint);
+ rect.inset(wScalar / 8, hScalar / 8);
+ mat.postScale(SK_Scalar1 / 4, SK_Scalar1 / 4);
+ }
+}
+
+static const int gSize = 1024;
+
+class DrawBitmapRectGM : public GM {
+public:
+ DrawBitmapRectGM() {
+ }
+
+ SkBitmap fLargeBitmap;
+
+protected:
+ SkString onShortName() {
+ return SkString("drawbitmaprect");
+ }
+
+ SkISize onISize() { return make_isize(gSize, gSize); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ static const int kBmpSize = 2048;
+ if (fLargeBitmap.isNull()) {
+ makebm(&fLargeBitmap,
+ SkBitmap::kARGB_8888_Config,
+ kBmpSize, kBmpSize);
+ }
+ SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)};
+ static const int kMaxSrcRectSize = 1 << (SkNextLog2(kBmpSize) + 2);
+
+ static const int kPadX = 30;
+ static const int kPadY = 40;
+ SkPaint paint;
+ paint.setAlpha(0x20);
+ canvas->drawBitmapRect(fLargeBitmap, NULL,
+ SkRect::MakeWH(gSize * SK_Scalar1,
+ gSize * SK_Scalar1),
+ &paint);
+ canvas->translate(SK_Scalar1 * kPadX / 2,
+ SK_Scalar1 * kPadY / 2);
+ SkPaint blackPaint;
+ SkScalar titleHeight = SK_Scalar1 * 24;
+ blackPaint.setColor(SK_ColorBLACK);
+ blackPaint.setTextSize(titleHeight);
+ blackPaint.setAntiAlias(true);
+ SkString title;
+ title.printf("Bitmap size: %d x %d", kBmpSize, kBmpSize);
+ canvas->drawText(title.c_str(), title.size(), 0,
+ titleHeight, blackPaint);
+
+ canvas->translate(0, SK_Scalar1 * kPadY / 2 + titleHeight);
+ int rowCount = 0;
+ canvas->save();
+ for (int w = 1; w <= kMaxSrcRectSize; w *= 4) {
+ for (int h = 1; h <= kMaxSrcRectSize; h *= 4) {
+
+ SkIRect srcRect = SkIRect::MakeXYWH((kBmpSize - w) / 2,
+ (kBmpSize - h) / 2,
+ w, h);
+ canvas->drawBitmapRect(fLargeBitmap, &srcRect, dstRect);
+
+ SkString label;
+ label.appendf("%d x %d", w, h);
+ blackPaint.setAntiAlias(true);
+ blackPaint.setStyle(SkPaint::kFill_Style);
+ blackPaint.setTextSize(SK_Scalar1 * 10);
+ SkScalar baseline = dstRect.height() +
+ blackPaint.getTextSize() + SK_Scalar1 * 3;
+ canvas->drawText(label.c_str(), label.size(),
+ 0, baseline,
+ blackPaint);
+ blackPaint.setStyle(SkPaint::kStroke_Style);
+ blackPaint.setStrokeWidth(SK_Scalar1);
+ blackPaint.setAntiAlias(false);
+ canvas->drawRect(dstRect, blackPaint);
+
+ canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0);
+ ++rowCount;
+ if ((dstRect.width() + kPadX) * rowCount > gSize) {
+ canvas->restore();
+ canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY);
+ canvas->save();
+ rowCount = 0;
+ }
+ }
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new DrawBitmapRectGM; }
+static GMRegistry reg(MyFactory);
+
+}
+
diff --git a/gm/emptypath.cpp b/gm/emptypath.cpp
new file mode 100644
index 0000000..c52932e
--- /dev/null
+++ b/gm/emptypath.cpp
@@ -0,0 +1,133 @@
+
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+namespace skiagm {
+
+class EmptyPathGM : public GM {
+public:
+ EmptyPathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("emptypath");
+ }
+
+ SkISize onISize() { return make_isize(600, 280); }
+
+ void drawEmpty(SkCanvas* canvas,
+ SkColor color,
+ const SkRect& clip,
+ SkPaint::Style style,
+ SkPath::FillType fill) {
+ SkPath path;
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Empty Paths Drawn Into Rectangle Clips With "
+ "Indicated Style and Fill";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ int i = 0;
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 0);
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 == i % 4) {
+ canvas->restore();
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ canvas->save();
+ } else {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+ ++i;
+
+
+ SkColor color = rand.nextU();
+ color = 0xff000000| color; // force solid
+ this->drawEmpty(canvas, color, rect,
+ gStyles[style].fStyle, gFills[fill].fFill);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(12 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 15 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 28 * SK_Scalar1,
+ labelPaint);
+ }
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new EmptyPathGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/filltypes.cpp b/gm/filltypes.cpp
index e723f16..73c718e 100644
--- a/gm/filltypes.cpp
+++ b/gm/filltypes.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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"
namespace skiagm {
@@ -6,6 +13,7 @@ class FillTypeGM : public GM {
SkPath fPath;
public:
FillTypeGM() {
+ this->setBGColor(0xFFDDDDDD);
const SkScalar radius = SkIntToScalar(45);
fPath.addCircle(SkIntToScalar(50), SkIntToScalar(50), radius);
fPath.addCircle(SkIntToScalar(100), SkIntToScalar(100), radius);
@@ -49,8 +57,6 @@ protected:
}
virtual void onDraw(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
-
canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
SkPaint paint;
diff --git a/gm/filltypespersp.cpp b/gm/filltypespersp.cpp
new file mode 100644
index 0000000..33f3242
--- /dev/null
+++ b/gm/filltypespersp.cpp
@@ -0,0 +1,128 @@
+
+/*
+ * Copyright 2011 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 "SkGradientShader.h"
+
+namespace skiagm {
+
+class FillTypePerspGM : public GM {
+ SkPath fPath;
+public:
+ FillTypePerspGM() {
+ const SkScalar radius = SkIntToScalar(45);
+ fPath.addCircle(SkIntToScalar(50), SkIntToScalar(50), radius);
+ fPath.addCircle(SkIntToScalar(100), SkIntToScalar(100), radius);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("filltypespersp");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(835, 840);
+ }
+
+ void showPath(SkCanvas* canvas, int x, int y, SkPath::FillType ft,
+ SkScalar scale, const SkPaint& paint) {
+
+ const SkRect r = { 0, 0, SkIntToScalar(150), SkIntToScalar(150) };
+
+ canvas->save();
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas->clipRect(r);
+ canvas->drawColor(SK_ColorWHITE);
+ fPath.setFillType(ft);
+ canvas->translate(r.centerX(), r.centerY());
+ canvas->scale(scale, scale);
+ canvas->translate(-r.centerX(), -r.centerY());
+ canvas->drawPath(fPath, paint);
+ canvas->restore();
+ }
+
+ void showFour(SkCanvas* canvas, SkScalar scale, bool aa) {
+
+ SkPaint paint;
+ SkPoint center = SkPoint::Make(SkIntToScalar(100), SkIntToScalar(100));
+ SkColor colors[] = {SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN};
+ SkScalar pos[] = {0, SK_ScalarHalf, SK_Scalar1};
+ SkShader* s = SkGradientShader::CreateRadial(center,
+ SkIntToScalar(100),
+ colors,
+ pos,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ paint.setAntiAlias(aa);
+
+ showPath(canvas, 0, 0, SkPath::kWinding_FillType,
+ scale, paint);
+ showPath(canvas, 200, 0, SkPath::kEvenOdd_FillType,
+ scale, paint);
+ showPath(canvas, 00, 200, SkPath::kInverseWinding_FillType,
+ scale, paint);
+ showPath(canvas, 200, 200, SkPath::kInverseEvenOdd_FillType,
+ scale, paint);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ // do perspective drawPaint as the background;
+ SkPaint bkgnrd;
+ SkPoint center = SkPoint::Make(SkIntToScalar(100),
+ SkIntToScalar(100));
+ SkColor colors[] = {SK_ColorBLACK, SK_ColorCYAN,
+ SK_ColorYELLOW, SK_ColorWHITE};
+ SkScalar pos[] = {0, SK_ScalarHalf / 2,
+ 3 * SK_ScalarHalf / 2, SK_Scalar1};
+ SkShader* s = SkGradientShader::CreateRadial(center,
+ SkIntToScalar(1000),
+ colors,
+ pos,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ bkgnrd.setShader(s)->unref();
+ canvas->save();
+ canvas->translate(SkIntToScalar(100), SkIntToScalar(100));
+ SkMatrix mat;
+ mat.reset();
+ mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 1000));
+ canvas->concat(mat);
+ canvas->drawPaint(bkgnrd);
+ canvas->restore();
+
+ // draw the paths in perspective
+ SkMatrix persp;
+ persp.reset();
+ persp.setPerspX(SkScalarToPersp(-SK_Scalar1 / 1800));
+ persp.setPerspY(SkScalarToPersp(SK_Scalar1 / 500));
+ canvas->concat(persp);
+
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+ const SkScalar scale = SkIntToScalar(5)/4;
+
+ showFour(canvas, SK_Scalar1, false);
+ canvas->translate(SkIntToScalar(450), 0);
+ showFour(canvas, scale, false);
+
+ canvas->translate(SkIntToScalar(-450), SkIntToScalar(450));
+ showFour(canvas, SK_Scalar1, true);
+ canvas->translate(SkIntToScalar(450), 0);
+ showFour(canvas, scale, true);
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new FillTypePerspGM; }
+static GMRegistry reg(MyFactory);
+
+}
+
diff --git a/gm/fontscaler.cpp b/gm/fontscaler.cpp
new file mode 100644
index 0000000..b331bde
--- /dev/null
+++ b/gm/fontscaler.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 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 "SkTypeface.h"
+
+namespace skiagm {
+
+class FontScalerGM : public GM {
+public:
+ FontScalerGM() {
+ this->setBGColor(0xFFFFFFFF);
+ }
+
+ virtual ~FontScalerGM() {
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("fontscaler");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(1450, 750);
+ }
+
+ static void rotate_about(SkCanvas* canvas,
+ SkScalar degrees,
+ SkScalar px, SkScalar py) {
+ canvas->translate(px, py);
+ canvas->rotate(degrees);
+ canvas->translate(-px, -py);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setLCDRenderText(true);
+ //With freetype the default (normal hinting) can be really ugly.
+ //Most distros now set slight (vertical hinting only) in any event.
+ paint.setHinting(SkPaint::kSlight_Hinting);
+ SkSafeUnref(paint.setTypeface(SkTypeface::CreateFromName("Times Roman", SkTypeface::kNormal)));
+
+ const char* text = "Hamburgefons ooo mmm";
+ const size_t textLen = strlen(text);
+
+ for (int j = 0; j < 2; ++j) {
+ for (int i = 0; i < 6; ++i) {
+ SkScalar x = SkIntToScalar(10);
+ SkScalar y = SkIntToScalar(20);
+
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(SkIntToScalar(50 + i * 230),
+ SkIntToScalar(20));
+ rotate_about(canvas, SkIntToScalar(i * 5), x, y * 10);
+
+ {
+ SkPaint p;
+ p.setAntiAlias(true);
+ SkRect r;
+ r.set(x - SkIntToScalar(3), SkIntToScalar(15),
+ x - SkIntToScalar(1), SkIntToScalar(280));
+ canvas->drawRect(r, p);
+ }
+
+ int index = 0;
+ for (int ps = 6; ps <= 22; ps++) {
+ paint.setTextSize(SkIntToScalar(ps));
+ canvas->drawText(text, textLen, x, y, paint);
+ y += paint.getFontMetrics(NULL);
+ index += 1;
+ }
+ }
+ canvas->translate(0, SkIntToScalar(360));
+ paint.setSubpixelText(true);
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new FontScalerGM; }
+static GMRegistry reg(MyFactory);
+
+}
+
diff --git a/gm/gm.cpp b/gm/gm.cpp
new file mode 100644
index 0000000..f9c0e66
--- /dev/null
+++ b/gm/gm.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 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"
+using namespace skiagm;
+
+GM::GM() {
+ fBGColor = SK_ColorWHITE;
+}
+GM::~GM() {}
+
+void GM::draw(SkCanvas* canvas) {
+ this->drawBackground(canvas);
+ this->drawContent(canvas);
+}
+
+void GM::drawContent(SkCanvas* canvas) {
+ this->onDraw(canvas);
+}
+
+void GM::drawBackground(SkCanvas* canvas) {
+ this->onDrawBackground(canvas);
+}
+
+const char* GM::shortName() {
+ if (fShortName.size() == 0) {
+ fShortName = this->onShortName();
+ }
+ return fShortName.c_str();
+}
+
+void GM::setBGColor(SkColor color) {
+ fBGColor = color;
+}
+
+void GM::onDrawBackground(SkCanvas* canvas) {
+ canvas->drawColor(fBGColor);
+}
+
+void GM::drawSizeBounds(SkCanvas* canvas, SkColor color) {
+ SkISize size = this->getISize();
+ SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()));
+ SkPaint paint;
+ paint.setColor(color);
+ canvas->drawRect(r, paint);
+}
+
+// need to explicitly declare this, or we get some weird infinite loop llist
+template GMRegistry* SkTRegistry<GM*, void*>::gHead;
diff --git a/gm/gm.h b/gm/gm.h
index ab92ff6..b0de922 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -1,7 +1,16 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#ifndef skiagm_DEFINED
#define skiagm_DEFINED
+#include "SkBitmap.h"
#include "SkCanvas.h"
+#include "SkDevice.h"
#include "SkPaint.h"
#include "SkRefCnt.h"
#include "SkSize.h"
@@ -21,22 +30,39 @@ namespace skiagm {
GM();
virtual ~GM();
- void draw(SkCanvas*);
+ enum Flags {
+ kSkipPDF_Flag = 1 << 0,
+ kSkipPicture_Flag = 1 << 1
+ };
+
+ void draw(SkCanvas*);
+ void drawBackground(SkCanvas*);
+ void drawContent(SkCanvas*);
+
SkISize getISize() { return this->onISize(); }
- const char* shortName() {
- if (fShortName.size() == 0) {
- fShortName = this->onShortName();
- }
- return fShortName.c_str();
+ const char* shortName();
+
+ uint32_t getFlags() const {
+ return this->onGetFlags();
}
+
+ SkColor getBGColor() const { return fBGColor; }
+ void setBGColor(SkColor);
+
+ // helper: fill a rect in the specified color based on the
+ // GM's getISize bounds.
+ void drawSizeBounds(SkCanvas*, SkColor);
protected:
virtual void onDraw(SkCanvas*) = 0;
+ virtual void onDrawBackground(SkCanvas*);
virtual SkISize onISize() = 0;
virtual SkString onShortName() = 0;
+ virtual uint32_t onGetFlags() const { return 0; }
private:
SkString fShortName;
+ SkColor fBGColor;
};
typedef SkTRegistry<GM*, void*> GMRegistry;
diff --git a/gm/gm_files.mk b/gm/gm_files.mk
deleted file mode 100644
index fec20b6..0000000
--- a/gm/gm_files.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-SOURCE := \
- bitmapfilters.cpp \
- blurs.cpp \
- filltypes.cpp \
- gradients.cpp \
- nocolorbleed.cpp \
- pathfill.cpp \
- points.cpp \
- poly2poly.cpp \
- shadows.cpp \
- shapes.cpp \
- strokerects.cpp \
- tilemodes.cpp \
- xfermodes.cpp \
- shadertext.cpp \
- complexclip.cpp \
- gmmain.cpp
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 37c3ee3..0af2933 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -1,31 +1,65 @@
+/*
+ * Copyright 2011 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 "GrContext.h"
+#include "GrRenderTarget.h"
+
#include "SkColorPriv.h"
+#include "SkData.h"
+#include "SkDevice.h"
+#include "SkGpuCanvas.h"
+#include "SkGpuDevice.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
+#include "SkNativeGLContext.h"
+#include "SkMesaGLContext.h"
#include "SkPicture.h"
#include "SkStream.h"
#include "SkRefCnt.h"
-#include "GrContext.h"
-#include "SkGpuCanvas.h"
-#include "SkGpuDevice.h"
-#include "SkEGLContext.h"
-#include "SkDevice.h"
+static bool gForceBWtext;
+
+extern bool gSkSuppressFontCachePurgeSpew;
#ifdef SK_SUPPORT_PDF
#include "SkPDFDevice.h"
#include "SkPDFDocument.h"
#endif
-using namespace skiagm;
+#ifdef SK_SUPPORT_XPS
+ #include "SkXPSDevice.h"
+#endif
+
+#ifdef SK_BUILD_FOR_MAC
+ #include "SkCGUtils.h"
+ #define CAN_IMAGE_PDF 1
+#else
+ #define CAN_IMAGE_PDF 0
+#endif
+
+typedef int ErrorBitfield;
+const static ErrorBitfield ERROR_NONE = 0x00;
+const static ErrorBitfield ERROR_NO_GPU_CONTEXT = 0x01;
+const static ErrorBitfield ERROR_PIXEL_MISMATCH = 0x02;
+const static ErrorBitfield ERROR_DIMENSION_MISMATCH = 0x04;
+const static ErrorBitfield ERROR_READING_REFERENCE_IMAGE = 0x08;
+const static ErrorBitfield ERROR_WRITING_REFERENCE_IMAGE = 0x10;
-// need to explicitly declare this, or we get some weird infinite loop llist
-template GMRegistry* GMRegistry::gHead;
+using namespace skiagm;
class Iter {
public:
Iter() {
+ this->reset();
+ }
+
+ void reset() {
fReg = GMRegistry::Head();
}
@@ -119,34 +153,42 @@ static void compute_diff(const SkBitmap& target, const SkBitmap& base,
}
}
-static bool compare(const SkBitmap& target, const SkBitmap& base,
- const SkString& name, const char* renderModeDescriptor,
- SkBitmap* diff) {
+static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
+ const SkString& name,
+ const char* renderModeDescriptor,
+ SkBitmap* diff) {
SkBitmap copy;
const SkBitmap* bm = &target;
if (target.config() != SkBitmap::kARGB_8888_Config) {
target.copyTo(&copy, SkBitmap::kARGB_8888_Config);
bm = &copy;
}
+ SkBitmap baseCopy;
+ const SkBitmap* bp = &base;
+ if (base.config() != SkBitmap::kARGB_8888_Config) {
+ base.copyTo(&baseCopy, SkBitmap::kARGB_8888_Config);
+ bp = &baseCopy;
+ }
force_all_opaque(*bm);
+ force_all_opaque(*bp);
const int w = bm->width();
const int h = bm->height();
- if (w != base.width() || h != base.height()) {
+ if (w != bp->width() || h != bp->height()) {
SkDebugf(
"---- %s dimensions mismatch for %s base [%d %d] current [%d %d]\n",
renderModeDescriptor, name.c_str(),
- base.width(), base.height(), w, h);
- return false;
+ bp->width(), bp->height(), w, h);
+ return ERROR_DIMENSION_MISMATCH;
}
SkAutoLockPixels bmLock(*bm);
- SkAutoLockPixels baseLock(base);
+ SkAutoLockPixels baseLock(*bp);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
- SkPMColor c0 = *base.getAddr32(x, y);
+ SkPMColor c0 = *bp->getAddr32(x, y);
SkPMColor c1 = *bm->getAddr32(x, y);
if (c0 != c1) {
SkDebugf(
@@ -156,26 +198,29 @@ static bool compare(const SkBitmap& target, const SkBitmap& base,
if (diff) {
diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
diff->allocPixels();
- compute_diff(*bm, base, diff);
+ compute_diff(*bm, *bp, diff);
}
- return false;
+ return ERROR_PIXEL_MISMATCH;
}
}
}
// they're equal
- return true;
+ return ERROR_NONE;
}
-static bool write_pdf(const SkString& path, const SkDynamicMemoryWStream& pdf) {
+static bool write_document(const SkString& path,
+ const SkDynamicMemoryWStream& document) {
SkFILEWStream stream(path.c_str());
- return stream.write(pdf.getStream(), pdf.getOffset());
+ SkAutoDataUnref data(document.copyToData());
+ return stream.writeData(data.get());
}
enum Backend {
kRaster_Backend,
kGPU_Backend,
kPDF_Backend,
+ kXPS_Backend,
};
struct ConfigData {
@@ -197,32 +242,54 @@ static void setup_bitmap(const ConfigData& gRec, SkISize& size,
bitmap->eraseColor(0);
}
-// Returns true if the test should continue, false if the test should
-// halt.
-static bool generate_image(GM* gm, const ConfigData& gRec,
- GrContext* context,
- SkBitmap& bitmap) {
+#include "SkDrawFilter.h"
+class BWTextDrawFilter : public SkDrawFilter {
+public:
+ virtual void filter(SkPaint*, Type) SK_OVERRIDE;
+};
+void BWTextDrawFilter::filter(SkPaint* p, Type t) {
+ if (kText_Type == t) {
+ p->setAntiAlias(false);
+ }
+}
+
+static void installFilter(SkCanvas* canvas) {
+ if (gForceBWtext) {
+ canvas->setDrawFilter(new BWTextDrawFilter)->unref();
+ }
+}
+
+static void invokeGM(GM* gm, SkCanvas* canvas) {
+ installFilter(canvas);
+ gm->draw(canvas);
+ canvas->setDrawFilter(NULL);
+}
+
+static ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
+ GrContext* context,
+ GrRenderTarget* rt,
+ SkBitmap* bitmap) {
SkISize size (gm->getISize());
- setup_bitmap(gRec, size, &bitmap);
- SkCanvas canvas(bitmap);
+ setup_bitmap(gRec, size, bitmap);
+ SkCanvas canvas(*bitmap);
if (gRec.fBackend == kRaster_Backend) {
- gm->draw(&canvas);
+ invokeGM(gm, &canvas);
} else { // GPU
if (NULL == context) {
- return false;
+ return ERROR_NO_GPU_CONTEXT;
}
- SkGpuCanvas gc(context,
- SkGpuDevice::Current3DApiRenderTarget());
- gc.setDevice(gc.createDevice(bitmap.config(),
- bitmap.width(),
- bitmap.height(),
- bitmap.isOpaque(),
- false))->unref();
- gm->draw(&gc);
- gc.readPixels(&bitmap); // overwrite our previous allocation
+ SkGpuCanvas gc(context, rt);
+ gc.setDevice(new SkGpuDevice(context, rt))->unref();
+ invokeGM(gm, &gc);
+ // the device is as large as the current rendertarget, so we explicitly
+ // only readback the amount we expect (in size)
+ // overwrite our previous allocation
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
+ size.fHeight);
+ gc.readPixels(bitmap, 0, 0);
}
- return true;
+ return ERROR_NONE;
}
static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
@@ -230,6 +297,7 @@ static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
SkISize size = gm->getISize();
setup_bitmap(gRec, size, bitmap);
SkCanvas canvas(*bitmap);
+ installFilter(&canvas);
canvas.drawPicture(*pict);
}
@@ -242,7 +310,7 @@ static void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
SkAutoUnref aur(dev);
SkCanvas c(dev);
- gm->draw(&c);
+ invokeGM(gm, &c);
SkPDFDocument doc;
doc.appendPage(dev);
@@ -250,78 +318,133 @@ static void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
#endif
}
-static bool write_reference_image(const ConfigData& gRec,
- const char writePath [],
- const char renderModeDescriptor [],
- const SkString& name,
- SkBitmap& bitmap,
- SkDynamicMemoryWStream* pdf) {
+static void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
+#ifdef SK_SUPPORT_XPS
+ SkISize size = gm->getISize();
+
+ SkSize trimSize = SkSize::Make(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()));
+ static const SkScalar inchesPerMeter = SkScalarDiv(10000, 254);
+ static const SkScalar upm = 72 * inchesPerMeter;
+ SkVector unitsPerMeter = SkPoint::Make(upm, upm);
+ static const SkScalar ppm = 200 * inchesPerMeter;
+ SkVector pixelsPerMeter = SkPoint::Make(ppm, ppm);
+
+ SkXPSDevice* dev = new SkXPSDevice();
+ SkAutoUnref aur(dev);
+
+ SkCanvas c(dev);
+ dev->beginPortfolio(&xps);
+ dev->beginSheet(unitsPerMeter, pixelsPerMeter, trimSize);
+ invokeGM(gm, &c);
+ dev->endSheet();
+ dev->endPortfolio();
+
+#endif
+}
+
+static ErrorBitfield write_reference_image(const ConfigData& gRec,
+ const char writePath [],
+ const char renderModeDescriptor [],
+ const SkString& name,
+ SkBitmap& bitmap,
+ SkDynamicMemoryWStream* document) {
SkString path;
bool success = false;
- if (gRec.fBackend != kPDF_Backend) {
+ if (gRec.fBackend == kRaster_Backend ||
+ gRec.fBackend == kGPU_Backend ||
+ (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF)) {
+
path = make_filename(writePath, renderModeDescriptor, name, "png");
success = write_bitmap(path, bitmap);
- } else if (pdf) {
+ }
+ if (kPDF_Backend == gRec.fBackend) {
path = make_filename(writePath, renderModeDescriptor, name, "pdf");
- success = write_pdf(path, *pdf);
+ success = write_document(path, *document);
}
- if (!success) {
+ if (kXPS_Backend == gRec.fBackend) {
+ path = make_filename(writePath, renderModeDescriptor, name, "xps");
+ success = write_document(path, *document);
+ }
+ if (success) {
+ return ERROR_NONE;
+ } else {
fprintf(stderr, "FAILED to write %s\n", path.c_str());
+ return ERROR_WRITING_REFERENCE_IMAGE;
}
- return success;
}
-static bool compare_to_reference_image(const char readPath [],
- const SkString& name,
- SkBitmap &bitmap,
- const char diffPath [],
- const char renderModeDescriptor []) {
+static ErrorBitfield compare_to_reference_image(const SkString& name,
+ SkBitmap &bitmap,
+ const SkBitmap& comparisonBitmap,
+ const char diffPath [],
+ const char renderModeDescriptor []) {
+ ErrorBitfield errors;
+ SkBitmap diffBitmap;
+ errors = compare(bitmap, comparisonBitmap, name, renderModeDescriptor,
+ diffPath ? &diffBitmap : NULL);
+ if ((ERROR_NONE == errors) && diffPath) {
+ SkString diffName = make_filename(diffPath, "", name, ".diff.png");
+ if (!write_bitmap(diffName, diffBitmap)) {
+ errors |= ERROR_WRITING_REFERENCE_IMAGE;
+ }
+ }
+ return errors;
+}
+
+static ErrorBitfield compare_to_reference_image(const char readPath [],
+ const SkString& name,
+ SkBitmap &bitmap,
+ const char diffPath [],
+ const char renderModeDescriptor []) {
SkString path = make_filename(readPath, "", name, "png");
SkBitmap orig;
- bool success = SkImageDecoder::DecodeFile(path.c_str(), &orig,
- SkBitmap::kARGB_8888_Config,
- SkImageDecoder::kDecodePixels_Mode, NULL);
- if (success) {
- SkBitmap diffBitmap;
- success = compare(bitmap, orig, name, renderModeDescriptor,
- diffPath ? &diffBitmap : NULL);
- if (!success && diffPath) {
- SkString diffName = make_filename(diffPath, "", name, ".diff.png");
- fprintf(stderr, "Writing %s\n", diffName.c_str());
- write_bitmap(diffName, diffBitmap);
- }
+ if (SkImageDecoder::DecodeFile(path.c_str(), &orig,
+ SkBitmap::kARGB_8888_Config,
+ SkImageDecoder::kDecodePixels_Mode, NULL)) {
+ return compare_to_reference_image(name, bitmap,
+ orig, diffPath,
+ renderModeDescriptor);
} else {
fprintf(stderr, "FAILED to read %s\n", path.c_str());
+ return ERROR_READING_REFERENCE_IMAGE;
}
- return success;
}
-static bool handle_test_results(GM* gm,
- const ConfigData& gRec,
- const char writePath [],
- const char readPath [],
- const char diffPath [],
- const char renderModeDescriptor [],
- SkBitmap& bitmap,
- SkDynamicMemoryWStream* pdf) {
+static ErrorBitfield handle_test_results(GM* gm,
+ const ConfigData& gRec,
+ const char writePath [],
+ const char readPath [],
+ const char diffPath [],
+ const char renderModeDescriptor [],
+ SkBitmap& bitmap,
+ SkDynamicMemoryWStream* pdf,
+ const SkBitmap* comparisonBitmap) {
SkString name = make_name(gm->shortName(), gRec.fName);
if (writePath) {
- write_reference_image(gRec, writePath, renderModeDescriptor,
- name, bitmap, pdf);
- // TODO: Figure out a way to compare PDFs.
- } else if (readPath && gRec.fBackend != kPDF_Backend) {
+ return write_reference_image(gRec, writePath, renderModeDescriptor,
+ name, bitmap, pdf);
+ } else if (readPath && (
+ gRec.fBackend == kRaster_Backend ||
+ gRec.fBackend == kGPU_Backend ||
+ (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF))) {
return compare_to_reference_image(readPath, name, bitmap,
diffPath, renderModeDescriptor);
+ } else if (comparisonBitmap) {
+ return compare_to_reference_image(name, bitmap,
+ *comparisonBitmap, diffPath,
+ renderModeDescriptor);
+ } else {
+ return ERROR_NONE;
}
- return true;
}
static SkPicture* generate_new_picture(GM* gm) {
// Pictures are refcounted so must be on heap
SkPicture* pict = new SkPicture;
SkCanvas* cv = pict->beginRecording(1000, 1000);
- gm->draw(cv);
+ invokeGM(gm, cv);
pict->endRecording();
return pict;
@@ -352,51 +475,60 @@ static SkPicture* stream_to_new_picture(const SkPicture& src) {
// Test: draw into a bitmap or pdf.
// Depending on flags, possibly compare to an expected image
// and possibly output a diff image if it fails to match.
-static bool test_drawing(GM* gm,
- const ConfigData& gRec,
- const char writePath [],
- const char readPath [],
- const char diffPath [],
- GrContext* context) {
- SkBitmap bitmap;
- SkDynamicMemoryWStream pdf;
+static ErrorBitfield test_drawing(GM* gm,
+ const ConfigData& gRec,
+ const char writePath [],
+ const char readPath [],
+ const char diffPath [],
+ GrContext* context,
+ GrRenderTarget* rt,
+ SkBitmap* bitmap) {
+ SkDynamicMemoryWStream document;
if (gRec.fBackend == kRaster_Backend ||
- gRec.fBackend == kGPU_Backend) {
- // Early exit if we can't generate the image, but this is
- // expected in some cases, so don't report a test failure.
- if (!generate_image(gm, gRec, context, bitmap)) {
- return true;
+ gRec.fBackend == kGPU_Backend) {
+ // Early exit if we can't generate the image.
+ ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap);
+ if (ERROR_NONE != errors) {
+ return errors;
}
- }
- // TODO: Figure out a way to compare PDFs.
- if (gRec.fBackend == kPDF_Backend && writePath) {
- generate_pdf(gm, pdf);
+ } else if (gRec.fBackend == kPDF_Backend) {
+ generate_pdf(gm, document);
+#if CAN_IMAGE_PDF
+ SkAutoDataUnref data(document.copyToData());
+ SkMemoryStream stream(data.data(), data.size());
+ SkPDFDocumentToBitmap(&stream, bitmap);
+#endif
+ } else if (gRec.fBackend == kXPS_Backend) {
+ generate_xps(gm, document);
}
return handle_test_results(gm, gRec, writePath, readPath, diffPath,
- "", bitmap, &pdf);
+ "", *bitmap, &document, NULL);
}
-static bool test_picture_playback(GM* gm,
- const ConfigData& gRec,
- const char readPath [],
- const char diffPath []) {
+static ErrorBitfield test_picture_playback(GM* gm,
+ const ConfigData& gRec,
+ const SkBitmap& comparisonBitmap,
+ const char readPath [],
+ const char diffPath []) {
SkPicture* pict = generate_new_picture(gm);
SkAutoUnref aur(pict);
if (kRaster_Backend == gRec.fBackend) {
SkBitmap bitmap;
generate_image_from_picture(gm, gRec, pict, &bitmap);
- return handle_test_results(gm, gRec, NULL, readPath, diffPath,
- "-replay", bitmap, NULL);
+ return handle_test_results(gm, gRec, NULL, NULL, diffPath,
+ "-replay", bitmap, NULL, &comparisonBitmap);
+ } else {
+ return ERROR_NONE;
}
- return true;
}
-static bool test_picture_serialization(GM* gm,
- const ConfigData& gRec,
- const char readPath [],
- const char diffPath []) {
+static ErrorBitfield test_picture_serialization(GM* gm,
+ const ConfigData& gRec,
+ const SkBitmap& comparisonBitmap,
+ const char readPath [],
+ const char diffPath []) {
SkPicture* pict = generate_new_picture(gm);
SkAutoUnref aurp(pict);
SkPicture* repict = stream_to_new_picture(*pict);
@@ -405,10 +537,11 @@ static bool test_picture_serialization(GM* gm,
if (kRaster_Backend == gRec.fBackend) {
SkBitmap bitmap;
generate_image_from_picture(gm, gRec, repict, &bitmap);
- return handle_test_results(gm, gRec, NULL, readPath, diffPath,
- "-serialize", bitmap, NULL);
+ return handle_test_results(gm, gRec, NULL, NULL, diffPath,
+ "-serialize", bitmap, NULL, &comparisonBitmap);
+ } else {
+ return ERROR_NONE;
}
- return true;
}
static void usage(const char * argv0) {
@@ -422,27 +555,64 @@ static void usage(const char * argv0) {
SkDebugf(" --replay: exercise SkPicture replay.\n");
SkDebugf(
" --serialize: exercise SkPicture serialization & deserialization.\n");
+ SkDebugf(" --match foo will only run tests that substring match foo.\n");
+#if SK_MESA
+ SkDebugf(" --mesagl will run using the osmesa sw gl rasterizer.\n");
+#endif
}
static const ConfigData gRec[] = {
{ SkBitmap::kARGB_8888_Config, kRaster_Backend, "8888" },
{ SkBitmap::kARGB_4444_Config, kRaster_Backend, "4444" },
{ SkBitmap::kRGB_565_Config, kRaster_Backend, "565" },
+#ifdef SK_SCALAR_IS_FLOAT
{ SkBitmap::kARGB_8888_Config, kGPU_Backend, "gpu" },
+#endif
#ifdef SK_SUPPORT_PDF
{ SkBitmap::kARGB_8888_Config, kPDF_Backend, "pdf" },
#endif
+#ifdef SK_SUPPORT_XPS
+ { SkBitmap::kARGB_8888_Config, kXPS_Backend, "xps" },
+#endif
};
+static bool skip_name(const SkTDArray<const char*> array, const char name[]) {
+ if (0 == array.count()) {
+ // no names, so don't skip anything
+ return false;
+ }
+ for (int i = 0; i < array.count(); ++i) {
+ if (strstr(name, array[i])) {
+ // found the name, so don't skip
+ return false;
+ }
+ }
+ return true;
+}
+
+namespace skiagm {
+static GrContext* gGrContext;
+GrContext* GetGr() {
+ return gGrContext;
+}
+}
+
int main(int argc, char * const argv[]) {
SkAutoGraphics ag;
+ // we don't need to see this during a run
+ gSkSuppressFontCachePurgeSpew = true;
const char* writePath = NULL; // if non-null, where we write the originals
const char* readPath = NULL; // if non-null, were we read from to compare
const char* diffPath = NULL; // if non-null, where we write our diffs (from compare)
+ SkTDArray<const char*> fMatches;
+
+ bool doPDF = true;
bool doReplay = true;
bool doSerialize = false;
+ bool useMesa = false;
+
const char* const commandName = argv[0];
char* const* stop = argv + argc;
for (++argv; argv < stop; ++argv) {
@@ -461,10 +631,24 @@ int main(int argc, char * const argv[]) {
if (argv < stop && **argv) {
diffPath = *argv;
}
+ } else if (strcmp(*argv, "--forceBWtext") == 0) {
+ gForceBWtext = true;
} else if (strcmp(*argv, "--noreplay") == 0) {
doReplay = false;
+ } else if (strcmp(*argv, "--nopdf") == 0) {
+ doPDF = false;
} else if (strcmp(*argv, "--serialize") == 0) {
doSerialize = true;
+ } else if (strcmp(*argv, "--match") == 0) {
+ ++argv;
+ if (argv < stop && **argv) {
+ // just record the ptr, no need for a deep copy
+ *fMatches.append() = *argv;
+ }
+#if SK_MESA
+ } else if (strcmp(*argv, "--mesagl") == 0) {
+ useMesa = true;
+#endif
} else {
usage(commandName);
return -1;
@@ -475,15 +659,39 @@ int main(int argc, char * const argv[]) {
return -1;
}
+ int maxW = -1;
+ int maxH = -1;
+ Iter iter;
+ GM* gm;
+ while ((gm = iter.next()) != NULL) {
+ SkISize size = gm->getISize();
+ maxW = SkMax32(size.width(), maxW);
+ maxH = SkMax32(size.height(), maxH);
+ }
// setup a GL context for drawing offscreen
- GrContext* context = NULL;
- SkEGLContext eglContext;
- if (eglContext.init(1024, 1024)) {
- context = GrContext::CreateGLShaderContext();
+ SkAutoTUnref<SkGLContext> glContext;
+#if SK_MESA
+ if (useMesa) {
+ glContext.reset(new SkMesaGLContext());
+ } else
+#endif
+ {
+ glContext.reset(new SkNativeGLContext());
}
- Iter iter;
- GM* gm;
+ GrPlatformRenderTargetDesc rtDesc;
+ if (glContext.get()->init(maxW, maxH)) {
+ GrPlatform3DContext ctx =
+ reinterpret_cast<GrPlatform3DContext>(glContext.get()->gl());
+ gGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, ctx);
+ if (NULL != gGrContext) {
+ rtDesc.fConfig = kSkia8888_PM_GrPixelConfig;
+ rtDesc.fStencilBits = 8;
+ rtDesc.fRenderTargetHandle = glContext.get()->getFBOID();
+ }
+ } else {
+ fprintf(stderr, "could not create GL context.\n");
+ }
if (readPath) {
fprintf(stderr, "reading from %s\n", readPath);
@@ -491,45 +699,95 @@ int main(int argc, char * const argv[]) {
fprintf(stderr, "writing to %s\n", writePath);
}
- // Accumulate success of all tests so we can flag error in any
- // one with the return value.
- bool overallSuccess = true;
+ // Accumulate success of all tests.
+ int testsRun = 0;
+ int testsPassed = 0;
+ int testsFailed = 0;
+ int testsMissingReferenceImages = 0;
+
+ iter.reset();
while ((gm = iter.next()) != NULL) {
+ const char* shortName = gm->shortName();
+ if (skip_name(fMatches, shortName)) {
+ SkDELETE(gm);
+ continue;
+ }
+
SkISize size = gm->getISize();
- SkDebugf("drawing... %s [%d %d]\n", gm->shortName(),
+ SkDebugf("drawing... %s [%d %d]\n", shortName,
size.width(), size.height());
+ SkBitmap forwardRenderedBitmap;
+
+ // Above we created an fbo for the context at maxW x maxH size.
+ // Here we lie about the size of the rt. We claim it is the size
+ // desired by the test. The reason is that rasterization may change
+ // slightly when the viewport dimensions change. Previously, whenever
+ // a new test was checked in that bumped maxW or maxH several images
+ // would slightly change.
+ rtDesc.fWidth = size.width();
+ rtDesc.fHeight = size.height();
+ SkAutoTUnref<GrRenderTarget> rt;
+ if (gGrContext) {
+ rt.reset(gGrContext->createPlatformRenderTarget(rtDesc));
+ }
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
- bool testSuccess = test_drawing(gm, gRec[i],
- writePath, readPath, diffPath, context);
- overallSuccess &= testSuccess;
-
- if (doReplay && testSuccess) {
- testSuccess = test_picture_playback(gm, gRec[i],
- readPath, diffPath);
- overallSuccess &= testSuccess;
+ // Skip any tests that we don't even need to try.
+ uint32_t gmFlags = gm->getFlags();
+ if ((kPDF_Backend == gRec[i].fBackend) &&
+ (!doPDF || (gmFlags & GM::kSkipPDF_Flag)))
+ {
+ continue;
}
- if (doSerialize && testSuccess) {
- overallSuccess &= test_picture_serialization(gm, gRec[i],
- readPath, diffPath);
+ // Now we know that we want to run this test and record its
+ // success or failure.
+ ErrorBitfield testErrors = ERROR_NONE;
+
+ if ((ERROR_NONE == testErrors) &&
+ (kGPU_Backend == gRec[i].fBackend) &&
+ (NULL == rt.get())) {
+ fprintf(stderr, "Could not create render target for gpu.\n");
+ testErrors |= ERROR_NO_GPU_CONTEXT;
}
- }
- SkDELETE(gm);
- }
- if (false == overallSuccess) {
- return -1;
- }
- return 0;
-}
-///////////////////////////////////////////////////////////////////////////////
+ if (ERROR_NONE == testErrors) {
+ testErrors |= test_drawing(gm, gRec[i],
+ writePath, readPath, diffPath,
+ gGrContext,
+ rt.get(), &forwardRenderedBitmap);
+ }
-using namespace skiagm;
+ if ((ERROR_NONE == testErrors) && doReplay &&
+ !(gmFlags & GM::kSkipPicture_Flag)) {
+ testErrors |= test_picture_playback(gm, gRec[i],
+ forwardRenderedBitmap,
+ readPath, diffPath);
+ }
-GM::GM() {}
-GM::~GM() {}
+ if ((ERROR_NONE == testErrors) && doSerialize) {
+ testErrors |= test_picture_serialization(gm, gRec[i],
+ forwardRenderedBitmap,
+ readPath, diffPath);
+ }
-void GM::draw(SkCanvas* canvas) {
- this->onDraw(canvas);
+ // Update overall results.
+ // We only tabulate the particular error types that we currently
+ // care about (e.g., missing reference images). Later on, if we
+ // want to also tabulate pixel mismatches vs dimension mistmatches
+ // (or whatever else), we can do so.
+ testsRun++;
+ if (ERROR_NONE == testErrors) {
+ testsPassed++;
+ } else if (ERROR_READING_REFERENCE_IMAGE & testErrors) {
+ testsMissingReferenceImages++;
+ } else {
+ testsFailed++;
+ }
+ }
+ SkDELETE(gm);
+ }
+ printf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
+ testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
+ return (0 == testsFailed) ? 0 : -1;
}
diff --git a/gm/gradients.cpp b/gm/gradients.cpp
index 26eee9d..aac8a96 100644
--- a/gm/gradients.cpp
+++ b/gm/gradients.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkGradientShader.h"
@@ -73,21 +80,18 @@ static const GradMaker gGradMakers[] = {
class GradientsGM : public GM {
public:
- GradientsGM() {}
+ GradientsGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
protected:
SkString onShortName() {
return SkString("gradients");
}
- SkISize onISize() { return make_isize(640, 510); }
-
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
-
+ virtual SkISize onISize() { return make_isize(640, 510); }
+
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
SkPoint pts[2] = {
{ 0, 0 },
@@ -117,10 +121,109 @@ private:
typedef GM INHERITED;
};
+/*
+ Inspired by this <canvas> javascript, where we need to detect that we are not
+ solving a quadratic equation, but must instead solve a linear (since our X^2
+ coefficient is 0)
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0.01, '#0f0');
+ g.addColorStop(0.99, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ */
+class GradientsDegenrate2PointGM : public GM {
+public:
+ GradientsDegenrate2PointGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("gradients_degenerate_2pt");
+ }
+
+ virtual SkISize onISize() { return make_isize(320, 320); }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorBLUE);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
+ SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
+ SkPoint c0;
+ c0.iset(-80, 25);
+ SkScalar r0 = SkIntToScalar(70);
+ SkPoint c1;
+ c1.iset(0, 25);
+ SkScalar r1 = SkIntToScalar(150);
+ SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
+ pos, SK_ARRAY_COUNT(pos),
+ SkShader::kClamp_TileMode);
+ SkPaint paint;
+ paint.setShader(s)->unref();
+ canvas->drawPaint(paint);
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+/// Tests correctness of *optimized* codepaths in gradients.
+
+class ClampedGradientsGM : public GM {
+public:
+ ClampedGradientsGM() {}
+
+protected:
+ SkString onShortName() { return SkString("clamped_gradients"); }
+
+ virtual SkISize onISize() { return make_isize(640, 510); }
+
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ this->drawBG(canvas);
+
+ SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ SkPoint center;
+ center.iset(0, 300);
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+ SkShader* shader = SkGradientShader::CreateRadial(
+ SkPoint(center),
+ SkIntToScalar(200), gColors, NULL, 5,
+ SkShader::kClamp_TileMode, NULL);
+ paint.setShader(shader);
+ canvas->drawRect(r, paint);
+ shader->unref();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+
///////////////////////////////////////////////////////////////////////////////
static GM* MyFactory(void*) { return new GradientsGM; }
static GMRegistry reg(MyFactory);
+static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
+static GMRegistry reg2(MyFactory2);
+
+static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
+static GMRegistry reg3(MyFactory3);
+
}
diff --git a/gm/gradtext.cpp b/gm/gradtext.cpp
new file mode 100644
index 0000000..a3769d2
--- /dev/null
+++ b/gm/gradtext.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkGradientShader.h"
+
+// test shader w/ transparency
+static SkShader* make_grad(SkScalar width) {
+ SkColor colors[] = { SK_ColorRED, 0x0000FF00, SK_ColorBLUE };
+ SkPoint pts[] = { { 0, 0 }, { width, 0 } };
+ return SkGradientShader::CreateLinear(pts, colors, NULL,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kMirror_TileMode);
+}
+
+// test opaque shader
+static SkShader* make_grad2(SkScalar width) {
+ SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
+ SkPoint pts[] = { { 0, 0 }, { width, 0 } };
+ return SkGradientShader::CreateLinear(pts, colors, NULL,
+ SK_ARRAY_COUNT(colors),
+ SkShader::kMirror_TileMode);
+}
+
+namespace skiagm {
+
+class GradTextGM : public GM {
+public:
+ GradTextGM () {}
+
+protected:
+
+ virtual SkString onShortName() {
+ return SkString("gradtext");
+ }
+
+ virtual SkISize onISize() { return make_isize(500, 480); }
+
+ static void draw_text(SkCanvas* canvas, const SkPaint& paint) {
+ const char* text = "When in the course of human events";
+ size_t len = strlen(text);
+ canvas->drawText(text, len, 0, 0, paint);
+ }
+
+ static void draw_text3(SkCanvas* canvas, const SkPaint& paint) {
+ SkPaint p(paint);
+
+ p.setAntiAlias(false);
+ draw_text(canvas, p);
+ p.setAntiAlias(true);
+ canvas->translate(0, paint.getTextSize() * 4/3);
+ draw_text(canvas, p);
+ p.setLCDRenderText(true);
+ canvas->translate(0, paint.getTextSize() * 4/3);
+ draw_text(canvas, p);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setTextSize(SkIntToScalar(26));
+
+ const SkISize& size = this->getISize();
+ SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()) / 2);
+ canvas->drawRect(r, paint);
+
+ canvas->translate(SkIntToScalar(20), paint.getTextSize());
+
+ for (int i = 0; i < 2; ++i) {
+ paint.setShader(make_grad(SkIntToScalar(80)))->unref();
+ draw_text3(canvas, paint);
+
+ canvas->translate(0, paint.getTextSize() * 2);
+
+ paint.setShader(make_grad2(SkIntToScalar(80)))->unref();
+ draw_text3(canvas, paint);
+
+ canvas->translate(0, paint.getTextSize() * 2);
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new GradTextGM; }
+static GMRegistry reg(MyFactory);
+
+}
+
diff --git a/gm/hairmodes.cpp b/gm/hairmodes.cpp
new file mode 100644
index 0000000..8bfa186
--- /dev/null
+++ b/gm/hairmodes.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+
+static SkCanvas* create_canvas(int w, int h) {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ bm.allocPixels();
+ bm.eraseColor(0);
+ return new SkCanvas(bm);
+}
+
+static const SkBitmap& extract_bitmap(SkCanvas* canvas) {
+ return canvas->getDevice()->accessBitmap(false);
+}
+
+static const struct {
+ SkXfermode::Mode fMode;
+ const char* fLabel;
+} gModes[] = {
+ { SkXfermode::kClear_Mode, "Clear" },
+ { SkXfermode::kSrc_Mode, "Src" },
+ { SkXfermode::kDst_Mode, "Dst" },
+ { SkXfermode::kSrcOver_Mode, "SrcOver" },
+ { SkXfermode::kDstOver_Mode, "DstOver" },
+ { SkXfermode::kSrcIn_Mode, "SrcIn" },
+ { SkXfermode::kDstIn_Mode, "DstIn" },
+ { SkXfermode::kSrcOut_Mode, "SrcOut" },
+ { SkXfermode::kDstOut_Mode, "DstOut" },
+ { SkXfermode::kSrcATop_Mode, "SrcATop" },
+ { SkXfermode::kDstATop_Mode, "DstATop" },
+ { SkXfermode::kXor_Mode, "Xor" },
+};
+
+const int gWidth = 64;
+const int gHeight = 64;
+const SkScalar W = SkIntToScalar(gWidth);
+const SkScalar H = SkIntToScalar(gHeight);
+
+static SkScalar drawCell(SkCanvas* canvas, SkXfermode* mode, SkAlpha a0, SkAlpha a1) {
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ SkRect r = SkRect::MakeWH(W, H);
+ r.inset(W/10, H/10);
+
+ paint.setColor(SK_ColorBLUE);
+ paint.setAlpha(a0);
+ canvas->drawOval(r, paint);
+
+ paint.setColor(SK_ColorRED);
+ paint.setAlpha(a1);
+ paint.setXfermode(mode);
+ for (int angle = 0; angle < 24; ++angle) {
+ SkScalar x = SkScalarCos(SkIntToScalar(angle) * (SK_ScalarPI * 2) / 24) * gWidth;
+ SkScalar y = SkScalarSin(SkIntToScalar(angle) * (SK_ScalarPI * 2) / 24) * gHeight;
+ paint.setStrokeWidth(SK_Scalar1 * angle * 2 / 24);
+ canvas->drawLine(W/2, H/2, W/2 + x, H/2 + y, paint);
+ }
+
+ return H;
+}
+
+static SkShader* make_bg_shader() {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+ bm.allocPixels();
+ *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
+ *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC, 0xCC, 0xCC);
+
+ SkShader* s = SkShader::CreateBitmapShader(bm,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+
+ SkMatrix m;
+ m.setScale(SkIntToScalar(6), SkIntToScalar(6));
+ s->setLocalMatrix(m);
+ return s;
+}
+
+namespace skiagm {
+
+ class HairModesGM : public GM {
+ SkPaint fBGPaint;
+ public:
+ HairModesGM() {
+ fBGPaint.setShader(make_bg_shader())->unref();
+ }
+
+ protected:
+
+ virtual SkString onShortName() {
+ return SkString("hairmodes");
+ }
+
+ virtual SkISize onISize() { return make_isize(640, 480); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ const SkRect bounds = SkRect::MakeWH(W, H);
+ static const SkAlpha gAlphaValue[] = { 0xFF, 0x88, 0x88 };
+
+ canvas->translate(SkIntToScalar(4), SkIntToScalar(4));
+
+ for (int alpha = 0; alpha < 4; ++alpha) {
+ canvas->save();
+ canvas->save();
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); ++i) {
+ if (6 == i) {
+ canvas->restore();
+ canvas->translate(W * 5, 0);
+ canvas->save();
+ }
+ SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
+
+ canvas->drawRect(bounds, fBGPaint);
+ canvas->saveLayer(&bounds, NULL);
+ SkScalar dy = drawCell(canvas, mode,
+ gAlphaValue[alpha & 1],
+ gAlphaValue[alpha & 2]);
+ canvas->restore();
+
+ canvas->translate(0, dy * 5 / 4);
+ SkSafeUnref(mode);
+ }
+ canvas->restore();
+ canvas->restore();
+ canvas->translate(W * 5 / 4, 0);
+ }
+ }
+
+ // disable pdf for now, since it crashes on mac
+ virtual uint32_t onGetFlags() const { return kSkipPDF_Flag; }
+
+ private:
+ typedef GM INHERITED;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ static GM* MyFactory(void*) { return new HairModesGM; }
+ static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/imageblur.cpp b/gm/imageblur.cpp
new file mode 100644
index 0000000..841441e
--- /dev/null
+++ b/gm/imageblur.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011 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 "SkBlurImageFilter.h"
+
+#define WIDTH 500
+#define HEIGHT 500
+
+namespace skiagm {
+
+class ImageBlurGM : public GM {
+public:
+ ImageBlurGM() {
+ this->setBGColor(0xFF000000);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("imageblur");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(WIDTH, HEIGHT);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setImageFilter(new SkBlurImageFilter(24.0f, 0.0f))->unref();
+ canvas->saveLayer(NULL, &paint);
+ paint.setAntiAlias(true);
+ const char* str = "The quick brown fox jumped over the lazy dog.";
+ srand(1234);
+ for (int i = 0; i < 25; ++i) {
+ int x = rand() % WIDTH;
+ int y = rand() % HEIGHT;
+ paint.setColor(rand() % 0x1000000 | 0xFF000000);
+ paint.setTextSize(rand() % 300);
+ canvas->drawText(str, strlen(str), x, y, paint);
+ }
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new ImageBlurGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/lcdtext.cpp b/gm/lcdtext.cpp
new file mode 100644
index 0000000..ab8b8e4
--- /dev/null
+++ b/gm/lcdtext.cpp
@@ -0,0 +1,70 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+/* Tests text rendering with LCD and subpixel rendering turned on and off.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+
+namespace skiagm {
+
+class LcdTextGM : public GM {
+public:
+ LcdTextGM() {
+ const int pointSize = 36;
+ textHeight = SkIntToScalar(pointSize);
+ }
+
+protected:
+
+ SkString onShortName() {
+ return SkString("lcdtext");
+ }
+
+ SkISize onISize() { return make_isize(640, 480); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+
+ y = textHeight;
+ drawText(canvas, SkString("TEXT: SubpixelTrue LCDRenderTrue"),
+ true, true);
+ drawText(canvas, SkString("TEXT: SubpixelTrue LCDRenderFalse"),
+ true, false);
+ drawText(canvas, SkString("TEXT: SubpixelFalse LCDRenderTrue"),
+ false, true);
+ drawText(canvas, SkString("TEXT: SubpixelFalse LCDRenderFalse"),
+ false, false);
+ }
+
+ void drawText(SkCanvas* canvas, const SkString& string,
+ bool subpixelTextEnabled, bool lcdRenderTextEnabled) {
+ SkPaint paint;
+ paint.setColor(SK_ColorBLACK);
+ paint.setDither(true);
+ paint.setAntiAlias(true);
+ paint.setSubpixelText(subpixelTextEnabled);
+ paint.setLCDRenderText(lcdRenderTextEnabled);
+ paint.setTextSize(textHeight);
+
+ canvas->drawText(string.c_str(), string.size(), 0, y, paint);
+ y += textHeight;
+ }
+
+private:
+ typedef GM INHERITED;
+ SkScalar y, textHeight;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new LcdTextGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/linepaths.cpp b/gm/linepaths.cpp
new file mode 100644
index 0000000..3d84c37
--- /dev/null
+++ b/gm/linepaths.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+namespace skiagm {
+
+class LinePathGM : public GM {
+public:
+ LinePathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("linepath");
+ }
+
+ SkISize onISize() { return make_isize(1240, 390); }
+
+ void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
+ const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName;
+ };
+ PathAndName path;
+ path.fPath.moveTo(25*SK_Scalar1, 15*SK_Scalar1);
+ path.fPath.lineTo(75*SK_Scalar1, 15*SK_Scalar1);
+ path.fName = "moveTo-line";
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Line Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, with stroke width 10";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
+ canvas->save();
+ for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
+ if (0 < cap) {
+ canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
+ }
+ canvas->save();
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 < fill) {
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (0 < style) {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ this->drawPath(path.fPath, canvas, color, rect,
+ gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
+ gFills[fill].fFill, SK_Scalar1*10);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gCaps[cap].fName,
+ strlen(gCaps[cap].fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+class LineClosePathGM : public GM {
+public:
+ LineClosePathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("lineclosepath");
+ }
+
+ SkISize onISize() { return make_isize(1240, 390); }
+
+ void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
+ const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName;
+ };
+ PathAndName path;
+ path.fPath.moveTo(25*SK_Scalar1, 15*SK_Scalar1);
+ path.fPath.lineTo(75*SK_Scalar1, 15*SK_Scalar1);
+ path.fPath.close();
+ path.fName = "moveTo-line-close";
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Line Closed Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, with stroke width 10";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
+ canvas->save();
+ for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
+ if (0 < cap) {
+ canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
+ }
+ canvas->save();
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 < fill) {
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (0 < style) {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ this->drawPath(path.fPath, canvas, color, rect,
+ gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
+ gFills[fill].fFill, SK_Scalar1*10);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gCaps[cap].fName,
+ strlen(gCaps[cap].fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* LinePathFactory(void*) { return new LinePathGM; }
+static GMRegistry regLinePath(LinePathFactory);
+
+static GM* LineClosePathFactory(void*) { return new LineClosePathGM; }
+static GMRegistry regLineClosePath(LineClosePathFactory);
+
+}
diff --git a/gm/ninepatchstretch.cpp b/gm/ninepatchstretch.cpp
new file mode 100644
index 0000000..d1d4dda
--- /dev/null
+++ b/gm/ninepatchstretch.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 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 "SkGpuDevice.h"
+
+static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) {
+ SkDevice* dev;
+ SkCanvas canvas;
+
+ const int kFixed = 28;
+ const int kStretchy = 8;
+ const int kSize = 2*kFixed + kStretchy;
+
+ if (ctx) {
+ dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize);
+ *bitmap = dev->accessBitmap(false);
+ } else {
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize);
+ bitmap->allocPixels();
+ dev = new SkDevice(*bitmap);
+ }
+
+ canvas.setDevice(dev)->unref();
+ canvas.clear(0);
+
+ SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
+ const SkScalar strokeWidth = SkIntToScalar(6);
+ const SkScalar radius = SkIntToScalar(kFixed) - strokeWidth/2;
+
+ center->setXYWH(kFixed, kFixed, kStretchy, kStretchy);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ paint.setColor(0xFFFF0000);
+ canvas.drawRoundRect(r, radius, radius, paint);
+ r.setXYWH(SkIntToScalar(kFixed), 0, SkIntToScalar(kStretchy), SkIntToScalar(kSize));
+ paint.setColor(0x8800FF00);
+ canvas.drawRect(r, paint);
+ r.setXYWH(0, SkIntToScalar(kFixed), SkIntToScalar(kSize), SkIntToScalar(kStretchy));
+ paint.setColor(0x880000FF);
+ canvas.drawRect(r, paint);
+}
+
+namespace skiagm {
+
+class NinePatchStretchGM : public GM {
+public:
+ SkBitmap fBM;
+
+ NinePatchStretchGM() {}
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("ninepatch-stretch");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(400, 400);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkBitmap bm;
+ SkIRect center;
+ make_bitmap(&bm, NULL /*SampleCode::GetGr()*/, &center);
+
+ // amount of bm that should not be stretched (unless we have to)
+ const SkScalar fixed = SkIntToScalar(bm.width() - center.width());
+
+ const SkTSize<SkScalar> size[] = {
+ { fixed * 4 / 5, fixed * 4 / 5 }, // shrink in both axes
+ { fixed * 4 / 5, fixed * 4 }, // shrink in X
+ { fixed * 4, fixed * 4 / 5 }, // shrink in Y
+ { fixed * 4, fixed * 4 }
+ };
+
+ canvas->drawBitmap(bm, SkIntToScalar(10), SkIntToScalar(10), NULL);
+
+ SkScalar x = SkIntToScalar(100);
+ SkScalar y = SkIntToScalar(100);
+
+ SkPaint paint;
+ paint.setFilterBitmap(true);
+
+ for (int iy = 0; iy < 2; ++iy) {
+ for (int ix = 0; ix < 2; ++ix) {
+ int i = ix * 2 + iy;
+ SkRect r = SkRect::MakeXYWH(x + ix * fixed, y + iy * fixed,
+ size[i].width(), size[i].height());
+ canvas->drawBitmapNine(bm, center, r, &paint);
+ }
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new NinePatchStretchGM; }
+static GMRegistry reg(MyFactory);
+
+}
+
+
+
diff --git a/gm/nocolorbleed.cpp b/gm/nocolorbleed.cpp
index 3dec7cc..26b8184 100755
--- a/gm/nocolorbleed.cpp
+++ b/gm/nocolorbleed.cpp
@@ -1,10 +1,19 @@
+
+/*
+ * Copyright 2011 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"
namespace skiagm {
class NoColorBleedGM : public GM {
public:
- NoColorBleedGM() {}
+ NoColorBleedGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
protected:
virtual SkString onShortName() {
@@ -15,13 +24,7 @@ protected:
return make_isize(200, 200);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- drawBG(canvas);
-
SkBitmap sprite;
sprite.setConfig(SkBitmap::kARGB_8888_Config, 4, 4, 4*sizeof(SkColor));
const SkColor spriteData[16] = {
diff --git a/gm/pathfill.cpp b/gm/pathfill.cpp
index 713847f..9d4b3c8 100644
--- a/gm/pathfill.cpp
+++ b/gm/pathfill.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkPicture.h"
#include "SkRectShape.h"
@@ -118,13 +125,7 @@ protected:
return make_isize(640, 480);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(SK_ColorWHITE);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
SkPaint paint;
paint.setAntiAlias(true);
diff --git a/gm/pathreverse.cpp b/gm/pathreverse.cpp
new file mode 100644
index 0000000..fc8028e
--- /dev/null
+++ b/gm/pathreverse.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPath.h"
+#include "SkTypeface.h"
+
+static void test_path(SkCanvas* canvas, const SkPath& path) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ canvas->drawPath(path, paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(SK_ColorRED);
+ canvas->drawPath(path, paint);
+}
+
+static void test_rev(SkCanvas* canvas, const SkPath& path) {
+ test_path(canvas, path);
+
+ SkPath rev;
+ rev.reverseAddPath(path);
+ canvas->save();
+ canvas->translate(150, 0);
+ test_path(canvas, rev);
+ canvas->restore();
+}
+
+static void test_rev(SkCanvas* canvas) {
+ SkRect r = { 10, 10, 100, 60 };
+
+ SkPath path;
+
+ path.addRect(r); test_rev(canvas, path);
+
+ canvas->translate(0, 100);
+ path.offset(20, 20);
+ path.addRect(r); test_rev(canvas, path);
+
+ canvas->translate(0, 100);
+ path.reset();
+ path.moveTo(10, 10); path.lineTo(30, 30);
+ path.addOval(r);
+ r.offset(50, 20);
+ path.addOval(r);
+ test_rev(canvas, path);
+
+ SkPaint paint;
+ paint.setTextSize(SkIntToScalar(100));
+ SkTypeface* hira = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro", SkTypeface::kNormal);
+ SkSafeUnref(paint.setTypeface(hira));
+ path.reset();
+ paint.getTextPath("e", 1, 50, 50, &path);
+ canvas->translate(0, 100);
+ test_rev(canvas, path);
+}
+
+namespace skiagm {
+
+class PathReverseGM : public GM {
+public:
+ PathReverseGM() {
+
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("path-reverse");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(640, 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkRect r = { 10, 10, 100, 60 };
+
+ SkPath path;
+
+ path.addRect(r); test_rev(canvas, path);
+
+ canvas->translate(0, 100);
+ path.offset(20, 20);
+ path.addRect(r); test_rev(canvas, path);
+
+ canvas->translate(0, 100);
+ path.reset();
+ path.moveTo(10, 10); path.lineTo(30, 30);
+ path.addOval(r);
+ r.offset(50, 20);
+ path.addOval(r);
+ test_rev(canvas, path);
+
+ SkPaint paint;
+ paint.setTextSize(SkIntToScalar(100));
+ SkTypeface* hira = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro", SkTypeface::kNormal);
+ SkSafeUnref(paint.setTypeface(hira));
+ path.reset();
+ paint.getTextPath("e", 1, 50, 50, &path);
+ canvas->translate(0, 100);
+ test_rev(canvas, path);
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new PathReverseGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/points.cpp b/gm/points.cpp
index 48d8fec..e4f3c2e 100644
--- a/gm/points.cpp
+++ b/gm/points.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkRandom.h"
@@ -16,18 +23,18 @@ protected:
return make_isize(640, 490);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(SK_ColorWHITE);
- }
-
static void fill_pts(SkPoint pts[], size_t n, SkRandom* rand) {
- for (size_t i = 0; i < n; i++)
- pts[i].set(rand->nextUScalar1() * 640, rand->nextUScalar1() * 480);
+ for (size_t i = 0; i < n; i++) {
+ // Compute these independently and store in variables, rather
+ // than in the parameter-passing expression, to get consistent
+ // evaluation order across compilers.
+ SkScalar y = rand->nextUScalar1() * 480;
+ SkScalar x = rand->nextUScalar1() * 640;
+ pts[i].set(x, y);
+ }
}
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
canvas->translate(SK_Scalar1, SK_Scalar1);
SkRandom rand;
diff --git a/gm/poly2poly.cpp b/gm/poly2poly.cpp
index 193ede7..df824b5 100644
--- a/gm/poly2poly.cpp
+++ b/gm/poly2poly.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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"
namespace skiagm {
@@ -14,10 +21,6 @@ protected:
virtual SkISize onISize() {
return make_isize(835, 840);
}
-
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(SK_ColorWHITE);
- }
static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[],
const int idst[], int count) {
@@ -45,7 +48,7 @@ protected:
paint->setColor(SK_ColorRED);
paint->setStyle(SkPaint::kFill_Style);
SkScalar x = D/2;
- float y = D/2 - (fm.fAscent + fm.fDescent)/2;
+ SkScalar y = D/2 - (fm.fAscent + fm.fDescent)/2;
SkString str;
str.appendS32(count);
canvas->drawText(str.c_str(), str.size(), x, y, *paint);
@@ -53,9 +56,7 @@ protected:
canvas->restore();
}
- virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
+ virtual void onDraw(SkCanvas* canvas) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setStrokeWidth(SkIntToScalar(4));
diff --git a/gm/quadpaths.cpp b/gm/quadpaths.cpp
new file mode 100644
index 0000000..f8b172b
--- /dev/null
+++ b/gm/quadpaths.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+
+namespace skiagm {
+
+class QuadPathGM : public GM {
+public:
+ QuadPathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("quadpath");
+ }
+
+ SkISize onISize() { return make_isize(1240, 390); }
+
+ void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
+ const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName;
+ };
+ PathAndName path;
+ path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
+ path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1,
+ 75*SK_Scalar1, 10*SK_Scalar1);
+ path.fName = "moveTo-quad";
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Quad Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, with stroke width 10";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
+ canvas->save();
+ for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
+ if (0 < cap) {
+ canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
+ }
+ canvas->save();
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 < fill) {
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (0 < style) {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ this->drawPath(path.fPath, canvas, color, rect,
+ gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
+ gFills[fill].fFill, SK_Scalar1*10);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gCaps[cap].fName,
+ strlen(gCaps[cap].fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+class QuadClosePathGM : public GM {
+public:
+ QuadClosePathGM() {}
+
+protected:
+ SkString onShortName() {
+ return SkString("quadclosepath");
+ }
+
+ SkISize onISize() { return make_isize(1240, 390); }
+
+ void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
+ const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
+ SkPaint::Style style, SkPath::FillType fill,
+ SkScalar strokeWidth) {
+ path.setFillType(fill);
+ SkPaint paint;
+ paint.setStrokeCap(cap);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setStrokeJoin(join);
+ paint.setColor(color);
+ paint.setStyle(style);
+ canvas->save();
+ canvas->clipRect(clip);
+ canvas->drawPath(path, paint);
+ canvas->restore();
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ struct FillAndName {
+ SkPath::FillType fFill;
+ const char* fName;
+ };
+ static const FillAndName gFills[] = {
+ {SkPath::kWinding_FillType, "Winding"},
+ {SkPath::kEvenOdd_FillType, "Even / Odd"},
+ {SkPath::kInverseWinding_FillType, "Inverse Winding"},
+ {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
+ };
+ struct StyleAndName {
+ SkPaint::Style fStyle;
+ const char* fName;
+ };
+ static const StyleAndName gStyles[] = {
+ {SkPaint::kFill_Style, "Fill"},
+ {SkPaint::kStroke_Style, "Stroke"},
+ {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
+ };
+ struct CapAndName {
+ SkPaint::Cap fCap;
+ SkPaint::Join fJoin;
+ const char* fName;
+ };
+ static const CapAndName gCaps[] = {
+ {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
+ {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
+ {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
+ };
+ struct PathAndName {
+ SkPath fPath;
+ const char* fName;
+ };
+ PathAndName path;
+ path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
+ path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1,
+ 75*SK_Scalar1, 10*SK_Scalar1);
+ path.fPath.close();
+ path.fName = "moveTo-quad-close";
+
+ SkPaint titlePaint;
+ titlePaint.setColor(SK_ColorBLACK);
+ titlePaint.setAntiAlias(true);
+ titlePaint.setLCDRenderText(true);
+ titlePaint.setTextSize(15 * SK_Scalar1);
+ const char title[] = "Quad Closed Drawn Into Rectangle Clips With "
+ "Indicated Style, Fill and Linecaps, with stroke width 10";
+ canvas->drawText(title, strlen(title),
+ 20 * SK_Scalar1,
+ 20 * SK_Scalar1,
+ titlePaint);
+
+ SkRandom rand;
+ SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
+ canvas->save();
+ canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
+ canvas->save();
+ for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
+ if (0 < cap) {
+ canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
+ }
+ canvas->save();
+ for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
+ if (0 < fill) {
+ canvas->translate(0, rect.height() + 40 * SK_Scalar1);
+ }
+ canvas->save();
+ for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (0 < style) {
+ canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
+ }
+
+ SkColor color = 0xff007000;
+ this->drawPath(path.fPath, canvas, color, rect,
+ gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
+ gFills[fill].fFill, SK_Scalar1*10);
+
+ SkPaint rectPaint;
+ rectPaint.setColor(SK_ColorBLACK);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ rectPaint.setStrokeWidth(-1);
+ rectPaint.setAntiAlias(true);
+ canvas->drawRect(rect, rectPaint);
+
+ SkPaint labelPaint;
+ labelPaint.setColor(color);
+ labelPaint.setAntiAlias(true);
+ labelPaint.setLCDRenderText(true);
+ labelPaint.setTextSize(10 * SK_Scalar1);
+ canvas->drawText(gStyles[style].fName,
+ strlen(gStyles[style].fName),
+ 0, rect.height() + 12 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gFills[fill].fName,
+ strlen(gFills[fill].fName),
+ 0, rect.height() + 24 * SK_Scalar1,
+ labelPaint);
+ canvas->drawText(gCaps[cap].fName,
+ strlen(gCaps[cap].fName),
+ 0, rect.height() + 36 * SK_Scalar1,
+ labelPaint);
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ }
+ canvas->restore();
+ canvas->restore();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* QuadPathFactory(void*) { return new QuadPathGM; }
+static GMRegistry regQuadPath(QuadPathFactory);
+
+static GM* QuadClosePathFactory(void*) { return new QuadClosePathGM; }
+static GMRegistry regQuadClosePath(QuadClosePathFactory);
+
+}
diff --git a/gm/shadertext.cpp b/gm/shadertext.cpp
index ea87823..b574ab6 100644
--- a/gm/shadertext.cpp
+++ b/gm/shadertext.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkCanvas.h"
#include "SkGradientShader.h"
@@ -102,7 +109,9 @@ static const GradMaker gGradMakers[] = {
class ShaderTextGM : public GM {
public:
- ShaderTextGM() {}
+ ShaderTextGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
protected:
@@ -110,18 +119,12 @@ protected:
return SkString("shadertext");
}
- SkISize onISize() { return make_isize(950, 500); }
-
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
+ SkISize onISize() { return make_isize(1450, 500); }
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
const char text[] = "Shaded Text";
const int textLen = SK_ARRAY_COUNT(text) - 1;
- const int pointSize = 48;
+ const int pointSize = 36;
int w = pointSize * textLen;
int h = pointSize;
@@ -169,19 +172,34 @@ protected:
canvas->save();
canvas->translate(SkIntToScalar(20), SkIntToScalar(10));
+ SkPath path;
+ path.arcTo(SkRect::MakeXYWH(SkIntToScalar(-40), SkIntToScalar(15),
+ SkIntToScalar(300), SkIntToScalar(90)),
+ SkIntToScalar(225), SkIntToScalar(90),
+ false);
+ path.close();
+
static const int testsPerCol = 8;
static const int rowHeight = 60;
static const int colWidth = 300;
canvas->save();
for (size_t s = 0; s < SK_ARRAY_COUNT(shaders); s++) {
canvas->save();
- canvas->translate(SkIntToScalar((s / testsPerCol) * colWidth),
- SkIntToScalar((s % testsPerCol) * rowHeight));
- paint.setShader(shaders[s])->ref();
+ int i = 2*s;
+ canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth),
+ SkIntToScalar((i % testsPerCol) * rowHeight));
+ paint.setShader(shaders[s])->unref();
canvas->drawText(text, textLen, 0, textBase, paint);
canvas->restore();
+ canvas->save();
+ ++i;
+ canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth),
+ SkIntToScalar((i % testsPerCol) * rowHeight));
+ canvas->drawTextOnPath(text, textLen, path, NULL, paint);
+ canvas->restore();
}
canvas->restore();
+
}
private:
diff --git a/gm/shadows.cpp b/gm/shadows.cpp
index bba997f..d4dd72f 100644
--- a/gm/shadows.cpp
+++ b/gm/shadows.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkBlurDrawLooper.h"
@@ -21,6 +28,7 @@ public:
SkRect fRect;
ShadowsGM() {
+ this->setBGColor(0xFFDDDDDD);
fCirclePath.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(10) );
fRect.set(SkIntToScalar(10), SkIntToScalar(10),
SkIntToScalar(30), SkIntToScalar(30));
@@ -35,13 +43,7 @@ protected:
return make_isize(200, 80);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
SkBlurDrawLooper* shadowLoopers[5];
shadowLoopers[0] =
new SkBlurDrawLooper (SkIntToScalar(10), SkIntToScalar(5),
diff --git a/gm/shapes.cpp b/gm/shapes.cpp
index 5daea0a..0f46355 100644
--- a/gm/shapes.cpp
+++ b/gm/shapes.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkPicture.h"
#include "SkRectShape.h"
@@ -43,6 +50,8 @@ class ShapesGM : public GM {
SkMatrixRef* fMatrixRefs[4];
public:
ShapesGM() {
+ this->setBGColor(0xFFDDDDDD);
+
SkMatrix m;
fGroup.appendShape(make_shape0(false))->unref();
m.setRotate(SkIntToScalar(30), SkIntToScalar(50), SkIntToScalar(50));
@@ -76,13 +85,7 @@ protected:
return make_isize(380, 480);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
SkMatrix matrix;
SkGroupShape* gs = new SkGroupShape;
@@ -95,16 +98,14 @@ protected:
matrix.preScale(SK_Scalar1*2, SK_Scalar1*2);
gs->appendShape(&fGroup, matrix);
-#if 0
- canvas->drawShape(gs);
-#else
+#if 1
SkPicture* pict = new SkPicture;
SkCanvas* cv = pict->beginRecording(1000, 1000);
cv->scale(SK_ScalarHalf, SK_ScalarHalf);
- cv->drawShape(gs);
+ gs->draw(cv);
cv->translate(SkIntToScalar(680), SkIntToScalar(480));
cv->scale(-SK_Scalar1, SK_Scalar1);
- cv->drawShape(gs);
+ gs->draw(cv);
pict->endRecording();
canvas->drawPicture(*pict);
pict->unref();
diff --git a/gm/strokefill.cpp b/gm/strokefill.cpp
new file mode 100644
index 0000000..a37af80
--- /dev/null
+++ b/gm/strokefill.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkPath.h"
+#include "SkTypeface.h"
+
+namespace skiagm {
+
+class StrokeFillGM : public GM {
+public:
+ StrokeFillGM() {
+
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("stroke-fill");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(640, 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint;
+ const char text[] = "Hello"; // "Hello";
+ const size_t len = sizeof(text) - 1;
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(100));
+// SkTypeface* hira = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro", SkTypeface::kNormal);
+ SkTypeface* hira = SkTypeface::CreateFromName("Papyrus", SkTypeface::kNormal);
+ paint.setTypeface(hira);
+ SkScalar x = SkIntToScalar(180);
+ SkScalar y = SkIntToScalar(88);
+
+ canvas->drawText(text, len, x, y, paint);
+ paint.setFakeBoldText(true);
+ canvas->drawText(text, len, x, y + SkIntToScalar(100), paint);
+ paint.setStyle(SkPaint::kStrokeAndFill_Style);
+ paint.setStrokeWidth(SkIntToScalar(5));
+
+ SkPath path;
+ path.setFillType(SkPath::kWinding_FillType);
+ path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCW_Direction);
+ path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(40), SkPath::kCCW_Direction);
+ canvas->drawPath(path, paint);
+
+ SkPath path2;
+ path2.setFillType(SkPath::kWinding_FillType);
+ path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCCW_Direction);
+ path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(40), SkPath::kCW_Direction);
+ canvas->drawPath(path2, paint);
+
+ path2.reset();
+ path2.addCircle(x + SkIntToScalar(240), y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCCW_Direction);
+ canvas->drawPath(path2, paint);
+ SkASSERT(path2.cheapIsDirection(SkPath::kCCW_Direction));
+
+ path2.reset();
+ SkASSERT(!path2.cheapComputeDirection(NULL));
+ path2.addCircle(x + SkIntToScalar(360), y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCW_Direction);
+ SkASSERT(path2.cheapIsDirection(SkPath::kCW_Direction));
+ canvas->drawPath(path2, paint);
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new StrokeFillGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/strokerects.cpp b/gm/strokerects.cpp
index 891b95a..92f2a18 100644
--- a/gm/strokerects.cpp
+++ b/gm/strokerects.cpp
@@ -1,20 +1,13 @@
-/*
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+/*
+ * Copyright 2011 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 "SkRandom.h"
@@ -45,14 +38,14 @@ protected:
SkScalar y = rand.nextUScalar1() * H;
SkScalar w = rand.nextUScalar1() * (W >> 2);
SkScalar h = rand.nextUScalar1() * (H >> 2);
+ SkScalar hoffset = rand.nextSScalar1();
+ SkScalar woffset = rand.nextSScalar1();
r->set(x, y, x + w, y + h);
- r->offset(-w/2 + rand.nextSScalar1(), -h/2 + + rand.nextSScalar1());
+ r->offset(-w/2 + woffset, -h/2 + hoffset);
}
virtual void onDraw(SkCanvas* canvas) {
- canvas->drawColor(SK_ColorWHITE);
-
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
diff --git a/gm/strokes.cpp b/gm/strokes.cpp
new file mode 100644
index 0000000..ec265ad
--- /dev/null
+++ b/gm/strokes.cpp
@@ -0,0 +1,149 @@
+
+/*
+ * Copyright 2011 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 "SkRandom.h"
+
+namespace skiagm {
+
+#define W 400
+#define H 400
+#define N 50
+
+static const SkScalar SW = SkIntToScalar(W);
+static const SkScalar SH = SkIntToScalar(H);
+
+static void rnd_rect(SkRect* r, SkPaint* paint, SkRandom& rand) {
+ SkScalar x = rand.nextUScalar1() * W;
+ SkScalar y = rand.nextUScalar1() * H;
+ SkScalar w = rand.nextUScalar1() * (W >> 2);
+ SkScalar h = rand.nextUScalar1() * (H >> 2);
+ SkScalar hoffset = rand.nextSScalar1();
+ SkScalar woffset = rand.nextSScalar1();
+
+ r->set(x, y, x + w, y + h);
+ r->offset(-w/2 + woffset, -h/2 + hoffset);
+
+ paint->setColor(rand.nextU());
+ paint->setAlpha(0xFF);
+}
+
+
+class StrokesGM : public GM {
+public:
+ StrokesGM() {}
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("strokes_round");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(W, H*2);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(9)/2);
+
+ for (int y = 0; y < 2; y++) {
+ paint.setAntiAlias(!!y);
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(0, SH * y);
+ canvas->clipRect(SkRect::MakeLTRB(
+ SkIntToScalar(2), SkIntToScalar(2)
+ , SW - SkIntToScalar(2), SH - SkIntToScalar(2)
+ ));
+
+ SkRandom rand;
+ for (int i = 0; i < N; i++) {
+ SkRect r;
+ rnd_rect(&r, &paint, rand);
+ canvas->drawOval(r, paint);
+ rnd_rect(&r, &paint, rand);
+ canvas->drawRoundRect(r, r.width()/4, r.height()/4, paint);
+ rnd_rect(&r, &paint, rand);
+ }
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+class Strokes2GM : public GM {
+ SkPath fPath;
+public:
+ Strokes2GM() {
+ SkRandom rand;
+ fPath.moveTo(0, 0);
+ for (int i = 0; i < 13; i++) {
+ SkScalar x = rand.nextUScalar1() * (W >> 1);
+ SkScalar y = rand.nextUScalar1() * (H >> 1);
+ fPath.lineTo(x, y);
+ }
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("strokes_poly");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(W, H*2);
+ }
+
+ static void rotate(SkScalar angle, SkScalar px, SkScalar py, SkCanvas* canvas) {
+ SkMatrix matrix;
+ matrix.setRotate(angle, px, py);
+ canvas->concat(matrix);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ canvas->drawColor(SK_ColorWHITE);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(9)/2);
+
+ for (int y = 0; y < 2; y++) {
+ paint.setAntiAlias(!!y);
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(0, SH * y);
+ canvas->clipRect(SkRect::MakeLTRB(SkIntToScalar(2),
+ SkIntToScalar(2),
+ SW - SkIntToScalar(2),
+ SH - SkIntToScalar(2)));
+
+ SkRandom rand;
+ for (int i = 0; i < N/2; i++) {
+ SkRect r;
+ rnd_rect(&r, &paint, rand);
+ rotate(SkIntToScalar(15), SW/2, SH/2, canvas);
+ canvas->drawPath(fPath, paint);
+ }
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new StrokesGM; }
+static GMRegistry reg(MyFactory);
+
+static GM* MyFactory2(void*) { return new Strokes2GM; }
+static GMRegistry reg2(MyFactory2);
+
+}
+
diff --git a/gm/tablecolorfilter.cpp b/gm/tablecolorfilter.cpp
new file mode 100644
index 0000000..df33337
--- /dev/null
+++ b/gm/tablecolorfilter.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkTableColorFilter.h"
+
+static void make_bm0(SkBitmap* bm) {
+ int W = 120;
+ int H = 120;
+ bm->setConfig(SkBitmap::kARGB_8888_Config, W, H);
+ bm->allocPixels();
+ bm->eraseColor(0);
+
+ SkCanvas canvas(*bm);
+ SkPaint paint;
+ SkPoint pts[] = { {0, 0}, {SkIntToScalar(W), SkIntToScalar(H)} };
+ SkColor colors[] = {
+ SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
+ SK_ColorRED, 0, SK_ColorBLUE, SK_ColorWHITE
+ };
+ SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ canvas.drawPaint(paint);
+}
+static void make_bm1(SkBitmap* bm) {
+ int W = 120;
+ int H = 120;
+ bm->setConfig(SkBitmap::kARGB_8888_Config, W, H);
+ bm->allocPixels();
+ bm->eraseColor(0);
+
+ SkCanvas canvas(*bm);
+ SkPaint paint;
+ SkScalar cx = SkIntToScalar(W)/2;
+ SkScalar cy = SkIntToScalar(H)/2;
+ SkColor colors[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
+ };
+ SkShader* s = SkGradientShader::CreateRadial(SkPoint::Make(SkIntToScalar(W)/2,
+ SkIntToScalar(H)/2),
+ SkIntToScalar(W)/2, colors, NULL, SK_ARRAY_COUNT(colors),
+ SkShader::kClamp_TileMode);
+ paint.setShader(s)->unref();
+ paint.setAntiAlias(true);
+ canvas.drawCircle(cx, cy, cx, paint);
+}
+
+static void make_table0(uint8_t table[]) {
+ for (int i = 0; i < 256; ++i) {
+ int n = i >> 5;
+ table[i] = (n << 5) | (n << 2) | (n >> 1);
+ }
+}
+static void make_table1(uint8_t table[]) {
+ for (int i = 0; i < 256; ++i) {
+ table[i] = i * i / 255;
+ }
+}
+static void make_table2(uint8_t table[]) {
+ for (int i = 0; i < 256; ++i) {
+ float fi = i / 255.0f;
+ table[i] = sqrtf(fi) * 255;
+ }
+}
+
+static SkColorFilter* make_cf0() {
+ uint8_t table[256]; make_table0(table);
+ return SkTableColorFilter::Create(table);
+}
+static SkColorFilter* make_cf1() {
+ uint8_t table[256]; make_table1(table);
+ return SkTableColorFilter::Create(table);
+}
+static SkColorFilter* make_cf2() {
+ uint8_t table[256]; make_table2(table);
+ return SkTableColorFilter::Create(table);
+}
+static SkColorFilter* make_cf3() {
+ uint8_t table0[256]; make_table0(table0);
+ uint8_t table1[256]; make_table1(table1);
+ uint8_t table2[256]; make_table2(table2);
+ return SkTableColorFilter::CreateARGB(NULL, table0, table1, table2);
+}
+
+class TableColorFilterGM : public skiagm::GM {
+public:
+ TableColorFilterGM() {}
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("tablecolorfilter");
+ }
+
+ virtual SkISize onISize() {
+ return SkISize::Make(640, 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ canvas->drawColor(0xFFDDDDDD);
+ canvas->translate(20, 20);
+
+ SkScalar x = 0, y = 0;
+
+ static void (*gMakers[])(SkBitmap*) = { make_bm0, make_bm1 };
+ for (size_t maker = 0; maker < SK_ARRAY_COUNT(gMakers); ++maker) {
+ SkBitmap bm;
+ gMakers[maker](&bm);
+
+ SkPaint paint;
+ x = 0;
+ canvas->drawBitmap(bm, x, y, &paint);
+ paint.setColorFilter(make_cf0())->unref(); x += bm.width() * 9 / 8;
+ canvas->drawBitmap(bm, x, y, &paint);
+ paint.setColorFilter(make_cf1())->unref(); x += bm.width() * 9 / 8;
+ canvas->drawBitmap(bm, x, y, &paint);
+ paint.setColorFilter(make_cf2())->unref(); x += bm.width() * 9 / 8;
+ canvas->drawBitmap(bm, x, y, &paint);
+ paint.setColorFilter(make_cf3())->unref(); x += bm.width() * 9 / 8;
+ canvas->drawBitmap(bm, x, y, &paint);
+
+ y += bm.height() * 9 / 8;
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static skiagm::GM* MyFactory(void*) { return new TableColorFilterGM; }
+static skiagm::GMRegistry reg(MyFactory);
diff --git a/gm/testimagefilters.cpp b/gm/testimagefilters.cpp
new file mode 100644
index 0000000..fc71d30
--- /dev/null
+++ b/gm/testimagefilters.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+#include "SkColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+
+#include "SkBlurImageFilter.h"
+#include "SkTestImageFilters.h"
+
+#define FILTER_WIDTH SkIntToScalar(150)
+#define FILTER_HEIGHT SkIntToScalar(200)
+
+static SkImageFilter* make0() { return new SkDownSampleImageFilter(SK_Scalar1 / 5); }
+static SkImageFilter* make1() { return new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16)); }
+static SkImageFilter* make2() {
+ SkColorFilter* cf = SkColorFilter::CreateModeFilter(SK_ColorBLUE,
+ SkXfermode::kSrcIn_Mode);
+ SkAutoUnref aur(cf);
+ return new SkColorFilterImageFilter(cf);
+}
+static SkImageFilter* make3() {
+ return new SkBlurImageFilter(8, 0);
+}
+
+static SkImageFilter* make4() {
+ SkImageFilter* outer = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
+ SkImageFilter* inner = new SkDownSampleImageFilter(SK_Scalar1 / 5);
+ SkAutoUnref aur0(outer);
+ SkAutoUnref aur1(inner);
+ return new SkComposeImageFilter(outer, inner);
+}
+static SkImageFilter* make5() {
+ SkImageFilter* first = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
+ SkImageFilter* second = new SkDownSampleImageFilter(SK_Scalar1 / 5);
+ SkAutoUnref aur0(first);
+ SkAutoUnref aur1(second);
+ return new SkMergeImageFilter(first, second);
+}
+
+static SkImageFilter* make6() {
+ SkImageFilter* outer = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
+ SkImageFilter* inner = new SkDownSampleImageFilter(SK_Scalar1 / 5);
+ SkAutoUnref aur0(outer);
+ SkAutoUnref aur1(inner);
+ SkImageFilter* compose = new SkComposeImageFilter(outer, inner);
+ SkAutoUnref aur2(compose);
+
+ SkColorFilter* cf = SkColorFilter::CreateModeFilter(0x880000FF,
+ SkXfermode::kSrcIn_Mode);
+ SkAutoUnref aur3(cf);
+ SkImageFilter* blue = new SkColorFilterImageFilter(cf);
+ SkAutoUnref aur4(blue);
+
+ return new SkMergeImageFilter(compose, blue);
+}
+
+static SkImageFilter* make7() {
+ SkImageFilter* outer = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
+ SkImageFilter* inner = make3();
+ SkAutoUnref aur0(outer);
+ SkAutoUnref aur1(inner);
+ SkImageFilter* compose = new SkComposeImageFilter(outer, inner);
+ SkAutoUnref aur2(compose);
+
+ SkColorFilter* cf = SkColorFilter::CreateModeFilter(0x880000FF,
+ SkXfermode::kSrcIn_Mode);
+ SkAutoUnref aur3(cf);
+ SkImageFilter* blue = new SkColorFilterImageFilter(cf);
+ SkAutoUnref aur4(blue);
+
+ return new SkMergeImageFilter(compose, blue);
+}
+
+static void draw0(SkCanvas* canvas) {
+ SkPaint p;
+ p.setAntiAlias(true);
+ SkRect r = SkRect::MakeWH(FILTER_WIDTH, FILTER_HEIGHT);
+ r.inset(SK_Scalar1 * 12, SK_Scalar1 * 12);
+ p.setColor(SK_ColorRED);
+ canvas->drawOval(r, p);
+}
+
+class TestImageFiltersGM : public skiagm::GM {
+public:
+ TestImageFiltersGM () {}
+
+protected:
+
+ virtual SkString onShortName() {
+ return SkString("testimagefilters");
+ }
+
+ virtual SkISize onISize() { return SkISize::Make(700, 460); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+// this->drawSizeBounds(canvas, 0xFFCCCCCC);
+
+ static SkImageFilter* (*gFilterProc[])() = {
+ make0, make1, make2, make3, make4, make5, make6, make7
+ };
+
+ const SkRect bounds = SkRect::MakeWH(FILTER_WIDTH, FILTER_HEIGHT);
+
+ const SkScalar dx = bounds.width() * 8 / 7;
+ const SkScalar dy = bounds.height() * 8 / 7;
+
+ canvas->translate(SkIntToScalar(8), SkIntToScalar(8));
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gFilterProc); ++i) {
+ int ix = i % 4;
+ int iy = i / 4;
+
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(ix * dx, iy * dy);
+
+ SkPaint p;
+ p.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(bounds, p);
+
+ SkPaint paint;
+ paint.setImageFilter(gFilterProc[i]())->unref();
+ canvas->saveLayer(&bounds, &paint);
+ draw0(canvas);
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static skiagm::GM* MyFactory(void*) { return new TestImageFiltersGM; }
+static skiagm::GMRegistry reg(MyFactory);
+
+
diff --git a/gm/texdata.cpp b/gm/texdata.cpp
new file mode 100644
index 0000000..c68a16a
--- /dev/null
+++ b/gm/texdata.cpp
@@ -0,0 +1,146 @@
+
+/*
+ * Copyright 2011 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 "GrContext.h"
+#include "SkColorPriv.h"
+#include "SkDevice.h"
+
+namespace skiagm {
+
+extern GrContext* GetGr();
+
+static const int S = 200;
+
+class TexDataGM : public GM {
+public:
+ TexDataGM() {
+ this->setBGColor(0xff000000);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("texdata");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(2*S, 2*S);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkDevice* device = canvas->getDevice();
+ GrRenderTarget* target = (GrRenderTarget*) device->accessRenderTarget();
+ GrContext* ctx = GetGr();
+ if (ctx && target) {
+ SkPMColor gTextureData[(2 * S) * (2 * S)];
+ static const int stride = 2 * S;
+ static const SkPMColor gray = SkPackARGB32(0x40, 0x40, 0x40, 0x40);
+ static const SkPMColor white = SkPackARGB32(0xff, 0xff, 0xff, 0xff);
+ static const SkPMColor red = SkPackARGB32(0x80, 0x80, 0x00, 0x00);
+ static const SkPMColor blue = SkPackARGB32(0x80, 0x00, 0x00, 0x80);
+ static const SkPMColor green = SkPackARGB32(0x80, 0x00, 0x80, 0x00);
+ static const SkPMColor black = SkPackARGB32(0x00, 0x00, 0x00, 0x00);
+ for (int i = 0; i < 2; ++i) {
+ int offset = 0;
+ // fill upper-left
+ for (int y = 0; y < S; ++y) {
+ for (int x = 0; x < S; ++x) {
+ gTextureData[offset + y * stride + x] = gray;
+ }
+ }
+ // fill upper-right
+ offset = S;
+ for (int y = 0; y < S; ++y) {
+ for (int x = 0; x < S; ++x) {
+ gTextureData[offset + y * stride + x] = white;
+ }
+ }
+ // fill lower left
+ offset = S * stride;
+ for (int y = 0; y < S; ++y) {
+ for (int x = 0; x < S; ++x) {
+ gTextureData[offset + y * stride + x] = black;
+ }
+ }
+ // fill lower right
+ offset = S * stride + S;
+ for (int y = 0; y < S; ++y) {
+ for (int x = 0; x < S; ++x) {
+ gTextureData[offset + y * stride + x] = gray;
+ }
+ }
+
+ GrTextureDesc desc;
+ desc.fAALevel = kNone_GrAALevel;
+ // use RT flag bit because in GL it makes the texture be bottom-up
+ desc.fFlags = i ? kRenderTarget_GrTextureFlagBit :
+ kNone_GrTextureFlags;
+ desc.fConfig = kSkia8888_PM_GrPixelConfig;
+ desc.fWidth = 2 * S;
+ desc.fHeight = 2 * S;
+ GrTexture* texture =
+ ctx->createUncachedTexture(desc, gTextureData, 0);
+
+ if (!texture) {
+ return;
+ }
+ GrAutoUnref au(texture);
+
+ ctx->setClip(GrRect::MakeWH(2*S, 2*S));
+ ctx->setRenderTarget(target);
+
+ GrPaint paint;
+ paint.reset();
+ paint.fColor = 0xffffffff;
+ paint.fSrcBlendCoeff = kOne_BlendCoeff;
+ paint.fDstBlendCoeff = kISA_BlendCoeff;
+ GrMatrix vm;
+ if (i) {
+ vm.setRotate(90 * SK_Scalar1,
+ S * SK_Scalar1,
+ S * SK_Scalar1);
+ } else {
+ vm.reset();
+ }
+ ctx->setMatrix(vm);
+ GrMatrix tm;
+ tm = vm;
+ GrMatrix* sampleMat = paint.textureSampler(0)->matrix();
+ *sampleMat = vm;
+ sampleMat->postIDiv(2*S, 2*S);
+ paint.setTexture(0, texture);
+
+ ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));
+
+ // now update the lower right of the texture in first pass
+ // or upper right in second pass
+ offset = 0;
+ for (int y = 0; y < S; ++y) {
+ for (int x = 0; x < S; ++x) {
+ gTextureData[offset + y * stride + x] =
+ ((x + y) % 2) ? (i ? green : red) : blue;
+ }
+ }
+ texture->writePixels(S, (i ? 0 : S), S, S,
+ texture->config(), gTextureData,
+ 4 * stride);
+ ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));
+ }
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new TexDataGM; }
+static GMRegistry reg(MyFactory);
+
+}
+
diff --git a/gm/tilemodes.cpp b/gm/tilemodes.cpp
index d836ea5..289caae 100644
--- a/gm/tilemodes.cpp
+++ b/gm/tilemodes.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkPath.h"
#include "SkRegion.h"
@@ -73,12 +80,7 @@ protected:
SkISize onISize() { return make_isize(880, 560); }
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(SK_ColorWHITE);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
SkRect r = { 0, 0, SkIntToScalar(gWidth*2), SkIntToScalar(gHeight*2) };
diff --git a/gm/tinybitmap.cpp b/gm/tinybitmap.cpp
new file mode 100644
index 0000000..d532b5b
--- /dev/null
+++ b/gm/tinybitmap.cpp
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright 2011 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 "SkShader.h"
+#include "SkCanvas.h"
+#include "SkUtils.h"
+
+namespace skiagm {
+
+static SkBitmap make_bitmap() {
+ SkBitmap bm;
+
+ SkColorTable* ctable = new SkColorTable(1);
+ SkPMColor* c = ctable->lockColors();
+ c[0] = SkPackARGB32(0x80, 0x80, 0, 0);
+ ctable->unlockColors(true);
+
+ bm.setConfig(SkBitmap::kIndex8_Config, 1, 1);
+ bm.allocPixels(ctable);
+ ctable->unref();
+
+ bm.lockPixels();
+ *bm.getAddr8(0, 0) = 0;
+ bm.unlockPixels();
+ return bm;
+}
+
+class TinyBitmapGM : public GM {
+ SkBitmap fBM;
+public:
+ TinyBitmapGM() {
+ this->setBGColor(0xFFDDDDDD);
+ fBM = make_bitmap();
+ }
+
+protected:
+ SkString onShortName() {
+ return SkString("tinybitmap");
+ }
+
+ virtual SkISize onISize() { return make_isize(100, 100); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkShader* s =
+ SkShader::CreateBitmapShader(fBM, SkShader::kRepeat_TileMode,
+ SkShader::kMirror_TileMode);
+ SkPaint paint;
+ paint.setAlpha(0x80);
+ paint.setShader(s)->unref();
+ canvas->drawPaint(paint);
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new TinyBitmapGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/verttext.cpp b/gm/verttext.cpp
new file mode 100644
index 0000000..0f3cb3b
--- /dev/null
+++ b/gm/verttext.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011 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 "SkCanvas.h"
+
+namespace skiagm {
+
+#define TEXT_SIZE 48
+static const char gText[] = "Hello";
+static const size_t gLen = sizeof(gText) - 1;
+
+class VertTextGM : public GM {
+public:
+ VertTextGM() {}
+
+protected:
+
+ SkString onShortName() {
+ return SkString("verttext");
+ }
+
+ SkISize onISize() { return make_isize(640, 480); }
+
+ static void drawBaseline(SkCanvas* canvas, const SkPaint& paint,
+ SkScalar x, SkScalar y) {
+ SkScalar total = paint.measureText(gText, gLen);
+
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setColor(0x80FF0000);
+ canvas->drawLine(x, y,
+ paint.isVerticalText() ? x : x + total,
+ paint.isVerticalText() ? y + total : y,
+ p);
+
+ p.setColor(0xFF0000FF);
+ SkScalar adv[gLen];
+ paint.getTextWidths(gText, gLen, adv, NULL);
+ for (size_t i = 0; i < gLen; ++i) {
+ canvas->drawCircle(x, y, SK_Scalar1 * 3 / 2, p);
+ if (paint.isVerticalText()) {
+ y += adv[i];
+ } else {
+ x += adv[i];
+ }
+ }
+ canvas->drawCircle(x, y, SK_Scalar1 * 3 / 2, p);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkScalar x = SkIntToScalar(100);
+ SkScalar y = SkIntToScalar(50);
+
+ for (int i = 0; i < 4; ++i) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(SkIntToScalar(TEXT_SIZE));
+
+
+ paint.setVerticalText(false);
+ drawBaseline(canvas, paint, x, y);
+ canvas->drawText(gText, gLen, x, y, paint);
+
+ paint.setVerticalText(true);
+ drawBaseline(canvas, paint, x, y);
+ canvas->drawText(gText, gLen, x, y, paint);
+
+ x += SkIntToScalar(40);
+ y += SkIntToScalar(120);
+
+ canvas->rotate(SkIntToScalar(-15));
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new VertTextGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/verttext2.cpp b/gm/verttext2.cpp
new file mode 100644
index 0000000..3bfb471
--- /dev/null
+++ b/gm/verttext2.cpp
@@ -0,0 +1,92 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+/* Tests text vertical text rendering with different fonts and centering.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkTypeface.h"
+
+namespace skiagm {
+
+class VertText2GM : public GM {
+public:
+ VertText2GM() {
+ const int pointSize = 24;
+ textHeight = SkIntToScalar(pointSize);
+ prop = SkTypeface::CreateFromName("Helvetica", SkTypeface::kNormal);
+ mono = SkTypeface::CreateFromName("Courier New", SkTypeface::kNormal);
+ }
+
+protected:
+
+ SkString onShortName() {
+ return SkString("verttext2");
+ }
+
+ SkISize onISize() { return make_isize(640, 480); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+
+ for (int i = 0; i < 3; ++i) {
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ paint.setAntiAlias(true);
+ y = textHeight;
+ canvas->drawLine(0, SkIntToScalar(10),
+ SkIntToScalar(110), SkIntToScalar(10), paint);
+ canvas->drawLine(0, SkIntToScalar(240),
+ SkIntToScalar(110), SkIntToScalar(240), paint);
+ canvas->drawLine(0, SkIntToScalar(470),
+ SkIntToScalar(110), SkIntToScalar(470), paint);
+ drawText(canvas, SkString("Proportional / Top Aligned"),
+ prop, SkPaint::kLeft_Align);
+ drawText(canvas, SkString("< Proportional / Centered >"),
+ prop, SkPaint::kCenter_Align);
+ drawText(canvas, SkString("Monospaced / Top Aligned"),
+ mono, SkPaint::kLeft_Align);
+ drawText(canvas, SkString("< Monospaced / Centered >"),
+ mono, SkPaint::kCenter_Align);
+ canvas->rotate(SkIntToScalar(-15));
+ canvas->translate(textHeight * 4, SkIntToScalar(50));
+ if (i > 0) {
+ canvas->translate(0, SkIntToScalar(50));
+ }
+ }
+ }
+
+ void drawText(SkCanvas* canvas, const SkString& string,
+ SkTypeface* family, SkPaint::Align alignment) {
+ SkPaint paint;
+ paint.setColor(SK_ColorBLACK);
+ paint.setAntiAlias(true);
+ paint.setVerticalText(true);
+ paint.setTextAlign(alignment);
+ paint.setTypeface(family);
+ paint.setTextSize(textHeight);
+
+ canvas->drawText(string.c_str(), string.size(), y,
+ alignment == SkPaint::kLeft_Align ? 10 : 240, paint);
+ y += textHeight;
+ }
+
+private:
+ typedef GM INHERITED;
+ SkScalar y, textHeight;
+ SkTypeface* prop;
+ SkTypeface* mono;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new VertText2GM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp
index b8565a3..42b8a6a 100644
--- a/gm/xfermodes.cpp
+++ b/gm/xfermodes.cpp
@@ -1,3 +1,10 @@
+
+/*
+ * Copyright 2011 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 "SkBitmap.h"
#include "SkShader.h"
@@ -31,11 +38,10 @@ static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
c.drawRect(r, p);
}
-static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
-
class XfermodesGM : public GM {
SkBitmap fBG;
SkBitmap fSrcB, fDstB;
+ bool fOnce;
void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
SkScalar x, SkScalar y) {
@@ -47,20 +53,25 @@ class XfermodesGM : public GM {
canvas->drawBitmap(fDstB, x, y, &p);
}
+ void init() {
+ if (!fOnce) {
+ // Do all this work in a temporary so we get a deep copy
+ uint16_t localData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
+ SkBitmap scratchBitmap;
+ scratchBitmap.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
+ scratchBitmap.setPixels(localData);
+ scratchBitmap.setIsOpaque(true);
+ scratchBitmap.copyTo(&fBG, SkBitmap::kARGB_4444_Config);
+
+ make_bitmaps(W, H, &fSrcB, &fDstB);
+ fOnce = true;
+ }
+ }
+
public:
const static int W = 64;
const static int H = 64;
- XfermodesGM() {
- // Do all this work in a temporary so we get a deep copy,
- // especially of gBG.
- SkBitmap scratchBitmap;
- scratchBitmap.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
- scratchBitmap.setPixels(gBG);
- scratchBitmap.setIsOpaque(true);
- scratchBitmap.copyTo(&fBG, SkBitmap::kARGB_4444_Config);
-
- make_bitmaps(W, H, &fSrcB, &fDstB);
- }
+ XfermodesGM() : fOnce(false) {}
protected:
virtual SkString onShortName() {
@@ -71,14 +82,10 @@ protected:
return make_isize(790, 640);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(SK_ColorWHITE);
- }
-
virtual void onDraw(SkCanvas* canvas) {
- canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
+ this->init();
- this->drawBG(canvas);
+ canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
const struct {
SkXfermode::Mode fMode;