1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
783f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org
80fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com#include "gm.h"
90fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com#include "SkCanvas.h"
100fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com#include "SkGradientShader.h"
112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkPath.h"
120fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
130fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comnamespace skiagm {
140fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
15dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.orgstatic void makebm(SkBitmap* bm, int w, int h) {
16dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    bm->allocN32Pixels(w, h);
17dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com    bm->eraseColor(SK_ColorTRANSPARENT);
180fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
190fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkCanvas    canvas(*bm);
20b28b5e4e26183b6e14846fb00501cc445a4fdd7eepoger@google.com    SkScalar    s = SkIntToScalar(SkMin32(w, h));
21386900790bbb2c07a6cc39bd46feb2e6526dbe01reed@google.com    SkPoint     pts[] = { { 0, 0 }, { s, s } };
220fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkColor     colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
230fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkScalar    pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
240fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkPaint     paint;
250fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
260fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    paint.setDither(true);
270fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
2883f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode))->unref();
290fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    canvas.drawPaint(paint);
300fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com}
310fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
320fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com///////////////////////////////////////////////////////////////////////////////
330fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
340fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comstruct GradData {
350fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    int             fCount;
360fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    const SkColor*  fColors;
370fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    const SkScalar* fPos;
380fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com};
390fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
400fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comstatic const SkColor gColors[] = {
410fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
420fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com};
430fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
440fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comstatic const GradData gGradData[] = {
452880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    { 2, gColors, nullptr },
462880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    { 5, gColors, nullptr },
470fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com};
480fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
4983f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.orgstatic SkShader* MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
5083f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, data.fCount, tm);
510fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com}
520fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
5383f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.orgstatic SkShader* MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
540fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkPoint center;
550fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
560fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com               SkScalarAve(pts[0].fY, pts[1].fY));
570fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
5883f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                                          data.fPos, data.fCount, tm);
590fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com}
600fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
6183f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.orgstatic SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode) {
620fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkPoint center;
630fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
640fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com               SkScalarAve(pts[0].fY, pts[1].fY));
6583f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
660fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com}
670fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
6871a6cbfc585959738dc0b375603696ca7f60605freedstatic SkShader* Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
690fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    SkPoint center0, center1;
700fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
710fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                SkScalarAve(pts[0].fY, pts[1].fY));
720fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
730fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
7471a6cbfc585959738dc0b375603696ca7f60605freed    return SkGradientShader::CreateTwoPointConical(
750fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                            center1, (pts[1].fX - pts[0].fX) / 7,
760fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                            center0, (pts[1].fX - pts[0].fX) / 2,
7783f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                            data.fColors, data.fPos, data.fCount, tm);
780fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com}
790fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
8083f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.orgtypedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm);
817693dbf46e9bf0159cc9032059738d418469a7adskia.committer@gmail.com
820fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comstatic const GradMaker gGradMakers[] = {
8371a6cbfc585959738dc0b375603696ca7f60605freed    MakeLinear, MakeRadial, MakeSweep, Make2Conical
840fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com};
850fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
860fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com///////////////////////////////////////////////////////////////////////////////
870fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
880fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comclass ShaderTextGM : public GM {
890fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.compublic:
90ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com    ShaderTextGM() {
9165cdba6ba78aaec0c0a4596bb5941020c789482bcaryclark        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
9248dd1a26ec07c5baa04856202e4e7e2a53e4d7e5bsalomon@google.com    }
930fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
940fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comprotected:
950fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
9636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override {
970fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        return SkString("shadertext");
980fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    }
990fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
10036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(1450, 500); }
1010fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
10236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
1030fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        const char text[] = "Shaded Text";
1040fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        const int textLen = SK_ARRAY_COUNT(text) - 1;
1053914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com        const int pointSize = 36;
1060fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
107da8cf5accb67d26a7f2e77d15cc918910e594e64reed        const int w = pointSize * textLen;
108da8cf5accb67d26a7f2e77d15cc918910e594e64reed        const int h = pointSize;
1090fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1100fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        SkPoint pts[2] = {
1110fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            { 0, 0 },
1120fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            { SkIntToScalar(w), SkIntToScalar(h) }
1130fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        };
1140fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        SkScalar textBase = SkIntToScalar(h/2);
1150fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1160fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        SkShader::TileMode tileModes[] = {
1170fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            SkShader::kClamp_TileMode,
1180fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            SkShader::kRepeat_TileMode,
1190fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            SkShader::kMirror_TileMode
1200fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        };
1210fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1220fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        static const int gradCount = SK_ARRAY_COUNT(gGradData) *
1230fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                                     SK_ARRAY_COUNT(gGradMakers);
1240fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        static const int bmpCount = SK_ARRAY_COUNT(tileModes) *
1250fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                                    SK_ARRAY_COUNT(tileModes);
1260fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        SkShader* shaders[gradCount + bmpCount];
1270fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1280fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        int shdIdx = 0;
1290fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        for (size_t d = 0; d < SK_ARRAY_COUNT(gGradData); ++d) {
1300fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            for (size_t m = 0; m < SK_ARRAY_COUNT(gGradMakers); ++m) {
1310fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                shaders[shdIdx++] = gGradMakers[m](pts,
1320fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com                                                   gGradData[d],
13383f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                                                   SkShader::kClamp_TileMode);
1340fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            }
1350fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        }
136da8cf5accb67d26a7f2e77d15cc918910e594e64reed
137da8cf5accb67d26a7f2e77d15cc918910e594e64reed        SkBitmap bm;
138da8cf5accb67d26a7f2e77d15cc918910e594e64reed        makebm(&bm, w/16, h/4);
1390fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        for (size_t tx = 0; tx < SK_ARRAY_COUNT(tileModes); ++tx) {
1400fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            for (size_t ty = 0; ty < SK_ARRAY_COUNT(tileModes); ++ty) {
141da8cf5accb67d26a7f2e77d15cc918910e594e64reed                shaders[shdIdx++] = SkShader::CreateBitmapShader(bm, tileModes[tx], tileModes[ty]);
1420fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            }
1430fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        }
1440fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1450fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        SkPaint paint;
1460fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        paint.setDither(true);
1470fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        paint.setAntiAlias(true);
1482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        sk_tool_utils::set_portable_typeface(&paint);
1490fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        paint.setTextSize(SkIntToScalar(pointSize));
1500fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1510fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        canvas->save();
1520fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        canvas->translate(SkIntToScalar(20), SkIntToScalar(10));
1530fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1543914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com        SkPath path;
155137c428290ac7a4804edf564c552711ffb9dfa58bsalomon@google.com        path.arcTo(SkRect::MakeXYWH(SkIntToScalar(-40), SkIntToScalar(15),
156ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com                                    SkIntToScalar(300), SkIntToScalar(90)),
157ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com                                    SkIntToScalar(225), SkIntToScalar(90),
158137c428290ac7a4804edf564c552711ffb9dfa58bsalomon@google.com                                    false);
1593914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com        path.close();
1603914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com
1610fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        static const int testsPerCol = 8;
1620fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        static const int rowHeight = 60;
1630fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        static const int colWidth = 300;
1640fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        canvas->save();
165e9cd27d4a3c92393cc6c79d4d6f93d266411d95erobertphillips@google.com        for (int s = 0; s < static_cast<int>(SK_ARRAY_COUNT(shaders)); s++) {
1660fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            canvas->save();
1673914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            int i = 2*s;
1683914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth),
1693914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com                              SkIntToScalar((i % testsPerCol) * rowHeight));
1703914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            paint.setShader(shaders[s])->unref();
1710fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            canvas->drawText(text, textLen, 0, textBase, paint);
1720fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com            canvas->restore();
1733914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            canvas->save();
1743914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            ++i;
1753914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth),
1763914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com                              SkIntToScalar((i % testsPerCol) * rowHeight));
1772880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            canvas->drawTextOnPath(text, textLen, path, nullptr, paint);
1783914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com            canvas->restore();
1790fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        }
1800fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com        canvas->restore();
1813914958a49ee089ddeb04acc16373aae8bc2eaf7bsalomon@google.com
1820fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    }
1830fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1840fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comprivate:
1850fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com    typedef GM INHERITED;
1860fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com};
1870fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1880fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com///////////////////////////////////////////////////////////////////////////////
1890fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com
1900fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comstatic GM* MyFactory(void*) { return new ShaderTextGM; }
1910fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.comstatic GMRegistry reg(MyFactory);
1920fdaa22dea3b139d7afa1daec4248aca1793460absalomon@google.com}
193