summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/gm/gradients.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/gm/gradients.cpp')
-rw-r--r--chromium/third_party/skia/gm/gradients.cpp467
1 files changed, 467 insertions, 0 deletions
diff --git a/chromium/third_party/skia/gm/gradients.cpp b/chromium/third_party/skia/gm/gradients.cpp
new file mode 100644
index 00000000000..277033b5dd1
--- /dev/null
+++ b/chromium/third_party/skia/gm/gradients.cpp
@@ -0,0 +1,467 @@
+
+/*
+ * 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 {
+
+struct GradData {
+ int fCount;
+ const SkColor* fColors;
+ const SkScalar* fPos;
+};
+
+static const SkColor gColors[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
+};
+static const SkScalar gPos0[] = { 0, SK_Scalar1 };
+static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
+static const SkScalar gPos2[] = {
+ 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
+};
+
+static const SkScalar gPosClamp[] = {0.0f, 0.0f, 1.0f, 1.0f};
+static const SkColor gColorClamp[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLUE
+};
+
+static const GradData gGradData[] = {
+ { 2, gColors, NULL },
+ { 2, gColors, gPos0 },
+ { 2, gColors, gPos1 },
+ { 5, gColors, NULL },
+ { 5, gColors, gPos2 },
+ { 4, gColorClamp, gPosClamp }
+};
+
+static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, const SkMatrix& localMatrix) {
+ return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
+ data.fCount, tm, 0, &localMatrix);
+}
+
+static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, const SkMatrix& localMatrix) {
+ SkPoint center;
+ center.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
+ data.fPos, data.fCount, tm, 0, &localMatrix);
+}
+
+static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode, const SkMatrix& localMatrix) {
+ SkPoint center;
+ center.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
+ data.fPos, data.fCount, 0, &localMatrix);
+}
+
+static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, const SkMatrix& localMatrix) {
+ SkPoint center0, center1;
+ center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
+ SkScalarAve(pts[0].fY, pts[1].fY));
+ center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
+ SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
+ return SkGradientShader::CreateTwoPointRadial(
+ center1, (pts[1].fX - pts[0].fX) / 7,
+ center0, (pts[1].fX - pts[0].fX) / 2,
+ data.fColors, data.fPos, data.fCount, tm,
+ 0, &localMatrix);
+}
+
+static SkShader* Make2Conical(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, const SkMatrix& localMatrix) {
+ SkPoint center0, center1;
+ SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
+ SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
+ center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
+ center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
+ return SkGradientShader::CreateTwoPointConical(center1, radius1,
+ center0, radius0,
+ data.fColors, data.fPos,
+ data.fCount, tm, 0, &localMatrix);
+}
+
+typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
+ SkShader::TileMode tm, const SkMatrix& localMatrix);
+static const GradMaker gGradMakers[] = {
+ MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GradientsGM : public GM {
+public:
+ GradientsGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
+
+protected:
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ return kSkipTiled_Flag;
+ }
+
+ SkString onShortName() {
+ return SkString("gradients");
+ }
+
+ virtual SkISize onISize() { return SkISize::Make(840, 815); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+
+ SkPoint pts[2] = {
+ { 0, 0 },
+ { SkIntToScalar(100), SkIntToScalar(100) }
+ };
+ SkShader::TileMode tm = SkShader::kClamp_TileMode;
+ SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
+ canvas->save();
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
+ SkMatrix scale = SkMatrix::I();
+
+ if (i == 5) { // if the clamp case
+ scale.setScale(0.5f, 0.5f);
+ scale.postTranslate(25.f, 25.f);
+ }
+
+ SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, scale);
+
+ paint.setShader(shader);
+ canvas->drawRect(r, paint);
+ shader->unref();
+ canvas->translate(0, SkIntToScalar(120));
+ }
+ canvas->restore();
+ canvas->translate(SkIntToScalar(120), 0);
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+// Based on the original gradient slide, but with perspective applied to the
+// gradient shaders' local matrices
+class GradientsLocalPerspectiveGM : public GM {
+public:
+ GradientsLocalPerspectiveGM() {
+ this->setBGColor(0xFFDDDDDD);
+ }
+
+protected:
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ return kSkipTiled_Flag;
+ }
+
+ SkString onShortName() {
+ return SkString("gradients_local_perspective");
+ }
+
+ virtual SkISize onISize() { return SkISize::Make(840, 815); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+
+ SkPoint pts[2] = {
+ { 0, 0 },
+ { SkIntToScalar(100), SkIntToScalar(100) }
+ };
+ SkShader::TileMode tm = SkShader::kClamp_TileMode;
+ SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
+ canvas->save();
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
+ // apply an increasing y perspective as we move to the right
+ SkMatrix perspective;
+ perspective.setIdentity();
+ perspective.setPerspY(SkScalarDiv(SkIntToScalar((unsigned) i+1),
+ SkIntToScalar(500)));
+ perspective.setSkewX(SkScalarDiv(SkIntToScalar((unsigned) i+1),
+ SkIntToScalar(10)));
+
+ SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, perspective);
+
+ paint.setShader(shader);
+ canvas->drawRect(r, paint);
+ shader->unref();
+ canvas->translate(0, SkIntToScalar(120));
+ }
+ canvas->restore();
+ canvas->translate(SkIntToScalar(120), 0);
+ }
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+// Based on the original gradient slide, but with perspective applied to
+// the view matrix
+class GradientsViewPerspectiveGM : public GradientsGM {
+protected:
+ SkString onShortName() {
+ return SkString("gradients_view_perspective");
+ }
+
+ virtual SkISize onISize() { return SkISize::Make(840, 500); }
+
+ virtual void onDraw(SkCanvas* canvas) {
+ SkMatrix perspective;
+ perspective.setIdentity();
+ perspective.setPerspY(SkScalarDiv(SK_Scalar1, SkIntToScalar(1000)));
+ perspective.setSkewX(SkScalarDiv(SkIntToScalar(8), SkIntToScalar(25)));
+ canvas->concat(perspective);
+ INHERITED::onDraw(canvas);
+ }
+
+private:
+ typedef GradientsGM 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 SkISize::Make(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, 0.01f, 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:
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ return kSkipTiled_Flag;
+ }
+
+ SkString onShortName() { return SkString("clamped_gradients"); }
+
+ virtual SkISize onISize() { return SkISize::Make(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);
+ paint.setShader(shader);
+ canvas->drawRect(r, paint);
+ shader->unref();
+ }
+
+private:
+ typedef GM INHERITED;
+};
+
+/// Checks quality of large radial gradients, which may display
+/// some banding.
+
+class RadialGradientGM : public GM {
+public:
+ RadialGradientGM() {}
+
+protected:
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ return kSkipTiled_Flag;
+ }
+
+ SkString onShortName() { return SkString("radial_gradient"); }
+ virtual SkISize onISize() { return SkISize::Make(1280, 1280); }
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFF000000);
+ }
+ virtual void onDraw(SkCanvas* canvas) {
+ const SkISize dim = this->getISize();
+
+ this->drawBG(canvas);
+
+ SkPaint paint;
+ paint.setDither(true);
+ SkPoint center;
+ center.set(SkIntToScalar(dim.width())/2, SkIntToScalar(dim.height())/2);
+ SkScalar radius = SkIntToScalar(dim.width())/2;
+ const SkColor colors[] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
+ const SkScalar pos[] = { 0.0f,
+ 0.35f,
+ 1.0f };
+ SkShader* shader =
+ SkGradientShader::CreateRadial(center, radius, colors,
+ pos, SK_ARRAY_COUNT(pos),
+ SkShader::kClamp_TileMode);
+ paint.setShader(shader)->unref();
+ SkRect r = {
+ 0, 0, SkIntToScalar(dim.width()), SkIntToScalar(dim.height())
+ };
+ canvas->drawRect(r, paint);
+ }
+private:
+ typedef GM INHERITED;
+};
+
+
+class RadialGradient2GM : public GM {
+public:
+ RadialGradient2GM() {}
+
+protected:
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ return kSkipTiled_Flag;
+ }
+
+ SkString onShortName() { return SkString("radial_gradient2"); }
+ virtual SkISize onISize() { return SkISize::Make(800, 400); }
+ void drawBG(SkCanvas* canvas) {
+ canvas->drawColor(0xFF000000);
+ }
+
+ // Reproduces the example given in bug 7671058.
+ virtual void onDraw(SkCanvas* canvas) {
+ SkPaint paint1, paint2, paint3;
+ paint1.setStyle(SkPaint::kFill_Style);
+ paint2.setStyle(SkPaint::kFill_Style);
+ paint3.setStyle(SkPaint::kFill_Style);
+
+ const SkColor sweep_colors[] =
+ { 0xFFFF0000, 0xFFFFFF00, 0xFF00FF00, 0xFF00FFFF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF0000 };
+ const SkColor colors1[] = { 0xFFFFFFFF, 0x00000000 };
+ const SkColor colors2[] = { 0xFF000000, 0x00000000 };
+
+ const SkScalar cx = 200, cy = 200, radius = 150;
+ SkPoint center;
+ center.set(cx, cy);
+
+ // We can either interpolate endpoints and premultiply each point (default, more precision),
+ // or premultiply the endpoints first, avoiding the need to premultiply each point (cheap).
+ const uint32_t flags[] = { 0, SkGradientShader::kInterpolateColorsInPremul_Flag };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(flags); i++) {
+ SkAutoTUnref<SkShader> sweep(
+ SkGradientShader::CreateSweep(cx, cy, sweep_colors,
+ NULL, SK_ARRAY_COUNT(sweep_colors),
+ flags[i], NULL));
+ SkAutoTUnref<SkShader> radial1(
+ SkGradientShader::CreateRadial(center, radius, colors1,
+ NULL, SK_ARRAY_COUNT(colors1),
+ SkShader::kClamp_TileMode,
+ flags[i], NULL));
+ SkAutoTUnref<SkShader> radial2(
+ SkGradientShader::CreateRadial(center, radius, colors2,
+ NULL, SK_ARRAY_COUNT(colors2),
+ SkShader::kClamp_TileMode,
+ flags[i], NULL));
+ paint1.setShader(sweep);
+ paint2.setShader(radial1);
+ paint3.setShader(radial2);
+
+ canvas->drawCircle(cx, cy, radius, paint1);
+ canvas->drawCircle(cx, cy, radius, paint3);
+ canvas->drawCircle(cx, cy, radius, paint2);
+
+ canvas->translate(400, 0);
+ }
+ }
+
+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);
+
+static GM* MyFactory4(void*) { return new RadialGradientGM; }
+static GMRegistry reg4(MyFactory4);
+
+static GM* MyFactory5(void*) { return new GradientsLocalPerspectiveGM; }
+static GMRegistry reg5(MyFactory5);
+
+static GM* MyFactory6(void*) { return new GradientsViewPerspectiveGM; }
+static GMRegistry reg6(MyFactory6);
+
+static GM* MyFactory7(void*) { return new RadialGradient2GM; }
+static GMRegistry reg7(MyFactory7);
+}