171c3c760a83123ee0b3127b8c65c6394ce541c50reed/*
271c3c760a83123ee0b3127b8c65c6394ce541c50reed * Copyright 2015 Google Inc.
371c3c760a83123ee0b3127b8c65c6394ce541c50reed *
471c3c760a83123ee0b3127b8c65c6394ce541c50reed * Use of this source code is governed by a BSD-style license that can be
571c3c760a83123ee0b3127b8c65c6394ce541c50reed * found in the LICENSE file.
671c3c760a83123ee0b3127b8c65c6394ce541c50reed */
771c3c760a83123ee0b3127b8c65c6394ce541c50reed
871c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "gm.h"
995e3c058ef633782f7549e9e1c2727d60dbc8ee5Hal Canary
1095e3c058ef633782f7549e9e1c2727d60dbc8ee5Hal Canary#include "SkAutoMalloc.h"
1171c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkCanvas.h"
1271c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkRSXform.h"
1371c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkSurface.h"
1446596ae50559e89a0a2462573ac9448cf309cf56Mike Reed#include "sk_tool_utils.h"
1571c3c760a83123ee0b3127b8c65c6394ce541c50reed
1671c3c760a83123ee0b3127b8c65c6394ce541c50reedclass DrawAtlasGM : public skiagm::GM {
179ce9d6772df650ceb0511f275e1a83dffa78ff72reed    static sk_sp<SkImage> MakeAtlas(SkCanvas* caller, const SkRect& target) {
1871c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
1946596ae50559e89a0a2462573ac9448cf309cf56Mike Reed        auto surface(sk_tool_utils::makeSurface(caller, info));
2071c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkCanvas* canvas = surface->getCanvas();
2171c3c760a83123ee0b3127b8c65c6394ce541c50reed        // draw red everywhere, but we don't expect to see it in the draw, testing the notion
2271c3c760a83123ee0b3127b8c65c6394ce541c50reed        // that drawAtlas draws a subset-region of the atlas.
2371c3c760a83123ee0b3127b8c65c6394ce541c50reed        canvas->clear(SK_ColorRED);
2471c3c760a83123ee0b3127b8c65c6394ce541c50reed
2571c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkPaint paint;
26374772bd61951f01bf84fe17bf53d8867681c9aereed        paint.setBlendMode(SkBlendMode::kClear);
2771c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkRect r(target);
2871c3c760a83123ee0b3127b8c65c6394ce541c50reed        r.inset(-1, -1);
2971c3c760a83123ee0b3127b8c65c6394ce541c50reed        // zero out a place (with a 1-pixel border) to land our drawing.
3071c3c760a83123ee0b3127b8c65c6394ce541c50reed        canvas->drawRect(r, paint);
31374772bd61951f01bf84fe17bf53d8867681c9aereed        paint.setBlendMode(SkBlendMode::kSrcOver);
3271c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setColor(SK_ColorBLUE);
3371c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setAntiAlias(true);
3471c3c760a83123ee0b3127b8c65c6394ce541c50reed        canvas->drawOval(target, paint);
359ce9d6772df650ceb0511f275e1a83dffa78ff72reed        return surface->makeImageSnapshot();
3671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
3771c3c760a83123ee0b3127b8c65c6394ce541c50reed
3871c3c760a83123ee0b3127b8c65c6394ce541c50reedpublic:
3971c3c760a83123ee0b3127b8c65c6394ce541c50reed    DrawAtlasGM() {}
409d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
4171c3c760a83123ee0b3127b8c65c6394ce541c50reedprotected:
429d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
4371c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkString onShortName() override {
4471c3c760a83123ee0b3127b8c65c6394ce541c50reed        return SkString("draw-atlas");
4571c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
469d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
4771c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkISize onISize() override {
4871c3c760a83123ee0b3127b8c65c6394ce541c50reed        return SkISize::Make(640, 480);
4971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
509d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
5171c3c760a83123ee0b3127b8c65c6394ce541c50reed    void onDraw(SkCanvas* canvas) override {
5271c3c760a83123ee0b3127b8c65c6394ce541c50reed        const SkRect target = { 50, 50, 80, 90 };
5395e8d0a4ae3c755fd9ffbd0c276fc657999feceebrianosman        auto atlas = MakeAtlas(canvas, target);
5471c3c760a83123ee0b3127b8c65c6394ce541c50reed
5571c3c760a83123ee0b3127b8c65c6394ce541c50reed        const struct {
5671c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fScale;
5771c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fDegrees;
5871c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fTx;
5971c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fTy;
609d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
6171c3c760a83123ee0b3127b8c65c6394ce541c50reed            void apply(SkRSXform* xform) const {
6271c3c760a83123ee0b3127b8c65c6394ce541c50reed                const SkScalar rad = SkDegreesToRadians(fDegrees);
6371c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fSCos = fScale * SkScalarCos(rad);
6471c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fSSin = fScale * SkScalarSin(rad);
6571c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fTx   = fTx;
6671c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fTy   = fTy;
6771c3c760a83123ee0b3127b8c65c6394ce541c50reed            }
6871c3c760a83123ee0b3127b8c65c6394ce541c50reed        } rec[] = {
6971c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 1, 0, 10, 10 },       // just translate
7071c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 2, 0, 110, 10 },      // scale + translate
7171c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 1, 30, 210, 10 },     // rotate + translate
7271c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 2, -30, 310, 30 },    // scale + rotate + translate
7371c3c760a83123ee0b3127b8c65c6394ce541c50reed        };
7471c3c760a83123ee0b3127b8c65c6394ce541c50reed
7571c3c760a83123ee0b3127b8c65c6394ce541c50reed        const int N = SK_ARRAY_COUNT(rec);
7671c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkRSXform xform[N];
7771c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkRect tex[N];
7871c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkColor colors[N];
7971c3c760a83123ee0b3127b8c65c6394ce541c50reed
8071c3c760a83123ee0b3127b8c65c6394ce541c50reed        for (int i = 0; i < N; ++i) {
8171c3c760a83123ee0b3127b8c65c6394ce541c50reed            rec[i].apply(&xform[i]);
8271c3c760a83123ee0b3127b8c65c6394ce541c50reed            tex[i] = target;
8371c3c760a83123ee0b3127b8c65c6394ce541c50reed            colors[i] = 0x80FF0000 + (i * 40 * 256);
8471c3c760a83123ee0b3127b8c65c6394ce541c50reed        }
8571c3c760a83123ee0b3127b8c65c6394ce541c50reed
8671c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkPaint paint;
8771c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setFilterQuality(kLow_SkFilterQuality);
8871c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setAntiAlias(true);
8971c3c760a83123ee0b3127b8c65c6394ce541c50reed
9095e8d0a4ae3c755fd9ffbd0c276fc657999feceebrianosman        canvas->drawAtlas(atlas.get(), xform, tex, N, nullptr, &paint);
9171c3c760a83123ee0b3127b8c65c6394ce541c50reed        canvas->translate(0, 100);
927d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        canvas->drawAtlas(atlas.get(), xform, tex, colors, N, SkBlendMode::kSrcIn, nullptr, &paint);
9371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
949d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
9571c3c760a83123ee0b3127b8c65c6394ce541c50reedprivate:
9671c3c760a83123ee0b3127b8c65c6394ce541c50reed    typedef GM INHERITED;
9771c3c760a83123ee0b3127b8c65c6394ce541c50reed};
9871c3c760a83123ee0b3127b8c65c6394ce541c50reedDEF_GM( return new DrawAtlasGM; )
9945561a0b15fe045ba272c328684c3f7ae290785areed
10045561a0b15fe045ba272c328684c3f7ae290785areed///////////////////////////////////////////////////////////////////////////////////////////////////
10145561a0b15fe045ba272c328684c3f7ae290785areed#include "SkPath.h"
10245561a0b15fe045ba272c328684c3f7ae290785areed#include "SkPathMeasure.h"
10345561a0b15fe045ba272c328684c3f7ae290785areed
104488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reedstatic void draw_text_on_path(SkCanvas* canvas, const void* text, size_t length,
105488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed                              const SkPoint xy[], const SkPath& path, const SkPaint& paint,
106488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed                              float baseline_offset, bool useRSX) {
10745561a0b15fe045ba272c328684c3f7ae290785areed    SkPathMeasure meas(path, false);
10845561a0b15fe045ba272c328684c3f7ae290785areed
10945561a0b15fe045ba272c328684c3f7ae290785areed    int count = paint.countText(text, length);
1107c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    size_t size = count * (sizeof(SkRSXform) + sizeof(SkScalar));
1117c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    SkAutoSMalloc<512> storage(size);
1127c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    SkRSXform* xform = (SkRSXform*)storage.get();
1137c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    SkScalar* widths = (SkScalar*)(xform + count);
1147c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed
1157c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    // Compute a conservative bounds so we can cull the draw
1167c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    const SkRect font = paint.getFontBounds();
1177c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    const SkScalar max = SkTMax(SkTMax(SkScalarAbs(font.fLeft), SkScalarAbs(font.fRight)),
1187c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed                                SkTMax(SkScalarAbs(font.fTop), SkScalarAbs(font.fBottom)));
1197c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    const SkRect bounds = path.getBounds().makeOutset(max, max);
1207c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed
121488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    if (useRSX) {
122488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        paint.getTextWidths(text, length, widths);
123488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed
124488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        for (int i = 0; i < count; ++i) {
125488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            // we want to position each character on the center of its advance
126488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            const SkScalar offset = SkScalarHalf(widths[i]);
127488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            SkPoint pos;
128488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            SkVector tan;
129488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            if (!meas.getPosTan(xy[i].x() + offset, &pos, &tan)) {
130488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed                pos = xy[i];
131488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed                tan.set(1, 0);
132488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            }
133488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            pos += SkVector::Make(-tan.fY, tan.fX) * baseline_offset;
134488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed
135488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            xform[i].fSCos = tan.x();
136488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            xform[i].fSSin = tan.y();
137488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            xform[i].fTx   = pos.x() - tan.y() * xy[i].y() - tan.x() * offset;
138488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed            xform[i].fTy   = pos.y() + tan.x() * xy[i].y() - tan.y() * offset;
139488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        }
140488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed
141488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        canvas->drawTextRSXform(text, length, &xform[0], &bounds, paint);
142488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    } else {
143488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        canvas->drawTextOnPathHV(text, length, path, 0, baseline_offset, paint);
144488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    }
1457c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed
1467c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    if (true) {
1477c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed        SkPaint p;
1487c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed        p.setStyle(SkPaint::kStroke_Style);
1497c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed        canvas->drawRect(bounds, p);
1507c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    }
15145561a0b15fe045ba272c328684c3f7ae290785areed}
15245561a0b15fe045ba272c328684c3f7ae290785areed
1535734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed#include "SkGradientShader.h"
1545734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reedstatic sk_sp<SkShader> make_shader() {
1555734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed    SkPoint pts[2] = {{0, 0}, {220, 0}};
1565734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed    SkColor colors[2] = {SK_ColorRED, SK_ColorBLUE};
1575734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed    return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kMirror_TileMode);
1585734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed}
1595734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed
160caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reedstatic void drawTextPath(SkCanvas* canvas, bool useRSX, bool doStroke) {
161dde2b1f1a8b888d233120b8b8f66ec7cf546cac8reed    const char text0[] = "ABCDFGHJKLMNOPQRSTUVWXYZ";
162dde2b1f1a8b888d233120b8b8f66ec7cf546cac8reed    const int N = sizeof(text0) - 1;
16345561a0b15fe045ba272c328684c3f7ae290785areed    SkPoint pos[N];
16445561a0b15fe045ba272c328684c3f7ae290785areed
1657c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    SkPaint paint;
1665734c4b3d89bac522af3c76d8f711a73039a58c2Mike Reed    paint.setShader(make_shader());
1677c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    paint.setAntiAlias(true);
1687c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    paint.setTextSize(100);
169caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed    if (doStroke) {
170caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        paint.setStyle(SkPaint::kStroke_Style);
171caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        paint.setStrokeWidth(2.25f);
172caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        paint.setStrokeJoin(SkPaint::kRound_Join);
173caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed    }
17445561a0b15fe045ba272c328684c3f7ae290785areed
1757c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed    SkScalar x = 0;
17645561a0b15fe045ba272c328684c3f7ae290785areed    for (int i = 0; i < N; ++i) {
1777c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed        pos[i].set(x, 0);
1787c70d7cfa2be8bb6d36d8df76ba9f967cf019c26reed        x += paint.measureText(&text0[i], 1);
17945561a0b15fe045ba272c328684c3f7ae290785areed    }
18045561a0b15fe045ba272c328684c3f7ae290785areed
18145561a0b15fe045ba272c328684c3f7ae290785areed    SkPath path;
182488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    const float baseline_offset = -5;
183488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed
184488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    const SkPath::Direction dirs[] = {
185488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        SkPath::kCW_Direction, SkPath::kCCW_Direction,
186488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    };
187488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    for (auto d : dirs) {
188488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        path.reset();
189488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        path.addOval(SkRect::MakeXYWH(160, 160, 540, 540), d);
190488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed        draw_text_on_path(canvas, text0, N, pos, path, paint, baseline_offset, useRSX);
191488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    }
19245561a0b15fe045ba272c328684c3f7ae290785areed
193caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed    paint.reset();
19445561a0b15fe045ba272c328684c3f7ae290785areed    paint.setStyle(SkPaint::kStroke_Style);
19545561a0b15fe045ba272c328684c3f7ae290785areed    canvas->drawPath(path, paint);
19645561a0b15fe045ba272c328684c3f7ae290785areed}
19745561a0b15fe045ba272c328684c3f7ae290785areed
198caaf211e8dd094db6b7408cecdf531ce7d91382cMike ReedDEF_SIMPLE_GM(drawTextRSXform, canvas, 860, 860) {
199488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed    canvas->scale(0.5f, 0.5f);
200caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed    const bool doStroke[] = { false, true };
201caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed    for (auto st : doStroke) {
202caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        canvas->save();
203caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        drawTextPath(canvas, false, st);
204caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        canvas->translate(860, 0);
205caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        drawTextPath(canvas, true, st);
206caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        canvas->restore();
207caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed        canvas->translate(0, 860);
208caaf211e8dd094db6b7408cecdf531ce7d91382cMike Reed    }
209488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed}
210488fbd13a6a241f2b74f6fa770ae3497af33dbceMike Reed
21193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed#include "Resources.h"
21293cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed#include "SkColorFilter.h"
21393cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed#include "SkVertices.h"
21493cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed
21593cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reedstatic sk_sp<SkVertices> make_vertices(sk_sp<SkImage> image, const SkRect& r,
21693cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                                       SkColor color) {
21793cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    SkPoint pos[4];
21893cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    r.toQuad(pos);
21993cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    SkColor colors[4] = { color, color, color, color };
22093cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    return SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode, 4,
22193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                                pos, pos, colors);
22293cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed}
22345561a0b15fe045ba272c328684c3f7ae290785areed
22493cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed/*
22593cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *  drawAtlas and drawVertices have several things in common:
22693cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *  - can create compound "shaders", combining texture and colors
22793cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *      - these are combined via an explicit blendmode
22893cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *  - like drawImage, they only respect parts of the paint
22993cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *      - colorfilter, imagefilter, blendmode, alpha
23093cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *
23193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *  This GM produces a series of pairs of images (atlas | vertices).
23293cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *  Each pair should look the same, and each set shows a different combination
23393cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed *  of alpha | colorFilter | mode
23493cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed */
23593cb252c179c4c8a9aa0e51f76ae703e409306d5Mike ReedDEF_SIMPLE_GM(compare_atlas_vertices, canvas, 560, 585) {
23693cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    const SkRect tex = SkRect::MakeWH(128, 128);
23793cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    const SkRSXform xform = SkRSXform::Make(1, 0, 0, 0);
23893cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    const SkColor color = 0x884488CC;
23993cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed
240c465d13e6fca5e171bde45d35b2dd43117f4702eHal Canary    auto image = GetResourceAsImage("images/mandrill_128.png");
24193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    auto verts = make_vertices(image, tex, color);
24293cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    const sk_sp<SkColorFilter> filters[] = {
24393cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed        nullptr,
24493cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed        SkColorFilter::MakeModeFilter(0xFF00FF88, SkBlendMode::kModulate),
24593cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    };
24693cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    const SkBlendMode modes[] = {
24793cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed        SkBlendMode::kSrcOver,
24893cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed        SkBlendMode::kPlus,
24993cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    };
25093cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed
25193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    canvas->translate(10, 10);
25293cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    SkPaint paint;
25393cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    for (SkBlendMode mode : modes) {
25493cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed        for (int alpha : { 0xFF, 0x7F }) {
25593cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed            paint.setAlpha(alpha);
25693cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed            canvas->save();
25793cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed            for (auto cf : filters) {
25893cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                paint.setColorFilter(cf);
25993cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                canvas->drawAtlas(image, &xform, &tex, &color, 1,
26093cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                                  mode, &tex, &paint);
26193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                canvas->translate(128, 0);
2620acd7954a9e654d7e9c11a532eeeeb2f18a76152Mike Reed                paint.setShader(image->makeShader());
26393cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                canvas->drawVertices(verts, mode, paint);
26493cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                paint.setShader(nullptr);
26593cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed                canvas->translate(145, 0);
26693cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed            }
26793cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed            canvas->restore();
26893cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed            canvas->translate(0, 145);
26993cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed        }
27093cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed    }
27193cb252c179c4c8a9aa0e51f76ae703e409306d5Mike Reed}
272