drawatlas.cpp revision 45561a0b15fe045ba272c328684c3f7ae290785a
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"
971c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkCanvas.h"
1071c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkRSXform.h"
1171c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkSurface.h"
1271c3c760a83123ee0b3127b8c65c6394ce541c50reed
1371c3c760a83123ee0b3127b8c65c6394ce541c50reedclass DrawAtlasGM : public skiagm::GM {
149ce9d6772df650ceb0511f275e1a83dffa78ff72reed    static sk_sp<SkImage> MakeAtlas(SkCanvas* caller, const SkRect& target) {
1571c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
16e8f3062a36d3682f4019309a32b5b84dc9eddf8creed        auto surface(caller->makeSurface(info));
1796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == surface) {
18e8f3062a36d3682f4019309a32b5b84dc9eddf8creed            surface = SkSurface::MakeRaster(info);
1971c3c760a83123ee0b3127b8c65c6394ce541c50reed        }
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;
2671c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setXfermodeMode(SkXfermode::kClear_Mode);
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);
3196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint.setXfermode(nullptr);
3271c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setColor(SK_ColorBLUE);
3371c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setAntiAlias(true);
3471c3c760a83123ee0b3127b8c65c6394ce541c50reed        canvas->drawOval(target, paint);
359ce9d6772df650ceb0511f275e1a83dffa78ff72reed        return surface->makeImageSnapshot();
3671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
3771c3c760a83123ee0b3127b8c65c6394ce541c50reed
389ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage> fAtlas;
3971c3c760a83123ee0b3127b8c65c6394ce541c50reed
4071c3c760a83123ee0b3127b8c65c6394ce541c50reedpublic:
4171c3c760a83123ee0b3127b8c65c6394ce541c50reed    DrawAtlasGM() {}
429d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
4371c3c760a83123ee0b3127b8c65c6394ce541c50reedprotected:
449d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
4571c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkString onShortName() override {
4671c3c760a83123ee0b3127b8c65c6394ce541c50reed        return SkString("draw-atlas");
4771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
489d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
4971c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkISize onISize() override {
5071c3c760a83123ee0b3127b8c65c6394ce541c50reed        return SkISize::Make(640, 480);
5171c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
529d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
5371c3c760a83123ee0b3127b8c65c6394ce541c50reed    void onDraw(SkCanvas* canvas) override {
5471c3c760a83123ee0b3127b8c65c6394ce541c50reed        const SkRect target = { 50, 50, 80, 90 };
5596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fAtlas) {
569ce9d6772df650ceb0511f275e1a83dffa78ff72reed            fAtlas = MakeAtlas(canvas, target);
5771c3c760a83123ee0b3127b8c65c6394ce541c50reed        }
5871c3c760a83123ee0b3127b8c65c6394ce541c50reed
5971c3c760a83123ee0b3127b8c65c6394ce541c50reed        const struct {
6071c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fScale;
6171c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fDegrees;
6271c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fTx;
6371c3c760a83123ee0b3127b8c65c6394ce541c50reed            SkScalar fTy;
649d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
6571c3c760a83123ee0b3127b8c65c6394ce541c50reed            void apply(SkRSXform* xform) const {
6671c3c760a83123ee0b3127b8c65c6394ce541c50reed                const SkScalar rad = SkDegreesToRadians(fDegrees);
6771c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fSCos = fScale * SkScalarCos(rad);
6871c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fSSin = fScale * SkScalarSin(rad);
6971c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fTx   = fTx;
7071c3c760a83123ee0b3127b8c65c6394ce541c50reed                xform->fTy   = fTy;
7171c3c760a83123ee0b3127b8c65c6394ce541c50reed            }
7271c3c760a83123ee0b3127b8c65c6394ce541c50reed        } rec[] = {
7371c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 1, 0, 10, 10 },       // just translate
7471c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 2, 0, 110, 10 },      // scale + translate
7571c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 1, 30, 210, 10 },     // rotate + translate
7671c3c760a83123ee0b3127b8c65c6394ce541c50reed            { 2, -30, 310, 30 },    // scale + rotate + translate
7771c3c760a83123ee0b3127b8c65c6394ce541c50reed        };
7871c3c760a83123ee0b3127b8c65c6394ce541c50reed
7971c3c760a83123ee0b3127b8c65c6394ce541c50reed        const int N = SK_ARRAY_COUNT(rec);
8071c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkRSXform xform[N];
8171c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkRect tex[N];
8271c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkColor colors[N];
8371c3c760a83123ee0b3127b8c65c6394ce541c50reed
8471c3c760a83123ee0b3127b8c65c6394ce541c50reed        for (int i = 0; i < N; ++i) {
8571c3c760a83123ee0b3127b8c65c6394ce541c50reed            rec[i].apply(&xform[i]);
8671c3c760a83123ee0b3127b8c65c6394ce541c50reed            tex[i] = target;
8771c3c760a83123ee0b3127b8c65c6394ce541c50reed            colors[i] = 0x80FF0000 + (i * 40 * 256);
8871c3c760a83123ee0b3127b8c65c6394ce541c50reed        }
8971c3c760a83123ee0b3127b8c65c6394ce541c50reed
9071c3c760a83123ee0b3127b8c65c6394ce541c50reed        SkPaint paint;
9171c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setFilterQuality(kLow_SkFilterQuality);
9271c3c760a83123ee0b3127b8c65c6394ce541c50reed        paint.setAntiAlias(true);
9371c3c760a83123ee0b3127b8c65c6394ce541c50reed
949ce9d6772df650ceb0511f275e1a83dffa78ff72reed        canvas->drawAtlas(fAtlas.get(), xform, tex, N, nullptr, &paint);
9571c3c760a83123ee0b3127b8c65c6394ce541c50reed        canvas->translate(0, 100);
969ce9d6772df650ceb0511f275e1a83dffa78ff72reed        canvas->drawAtlas(fAtlas.get(), xform, tex, colors, N, SkXfermode::kSrcIn_Mode, nullptr, &paint);
9771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
989d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
9971c3c760a83123ee0b3127b8c65c6394ce541c50reedprivate:
10071c3c760a83123ee0b3127b8c65c6394ce541c50reed    typedef GM INHERITED;
10171c3c760a83123ee0b3127b8c65c6394ce541c50reed};
10271c3c760a83123ee0b3127b8c65c6394ce541c50reedDEF_GM( return new DrawAtlasGM; )
10345561a0b15fe045ba272c328684c3f7ae290785areed
10445561a0b15fe045ba272c328684c3f7ae290785areed///////////////////////////////////////////////////////////////////////////////////////////////////
10545561a0b15fe045ba272c328684c3f7ae290785areed#include "SkPath.h"
10645561a0b15fe045ba272c328684c3f7ae290785areed#include "SkPathMeasure.h"
10745561a0b15fe045ba272c328684c3f7ae290785areed
10845561a0b15fe045ba272c328684c3f7ae290785areedstatic void draw_text_on_path_rigid(SkCanvas* canvas, const void* text, size_t length,
10945561a0b15fe045ba272c328684c3f7ae290785areed                                    const SkPoint xy[], const SkPath& path, const SkPaint& paint) {
11045561a0b15fe045ba272c328684c3f7ae290785areed    SkPathMeasure meas(path, false);
11145561a0b15fe045ba272c328684c3f7ae290785areed
11245561a0b15fe045ba272c328684c3f7ae290785areed    int count = paint.countText(text, length);
11345561a0b15fe045ba272c328684c3f7ae290785areed    SkAutoSTArray<100, SkRSXform> xform(count);
11445561a0b15fe045ba272c328684c3f7ae290785areed
11545561a0b15fe045ba272c328684c3f7ae290785areed    for (int i = 0; i < count; ++i) {
11645561a0b15fe045ba272c328684c3f7ae290785areed        SkPoint pos;
11745561a0b15fe045ba272c328684c3f7ae290785areed        SkVector tan;
11845561a0b15fe045ba272c328684c3f7ae290785areed        if (!meas.getPosTan(xy[i].x(), &pos, &tan)) {
11945561a0b15fe045ba272c328684c3f7ae290785areed            pos = xy[i];
12045561a0b15fe045ba272c328684c3f7ae290785areed            tan.set(1, 0);
12145561a0b15fe045ba272c328684c3f7ae290785areed        }
12245561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fSCos = tan.x();
12345561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fSSin = tan.y();
12445561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fTx   = pos.x();
12545561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fTy   = pos.y();
12645561a0b15fe045ba272c328684c3f7ae290785areed    }
12745561a0b15fe045ba272c328684c3f7ae290785areed
12845561a0b15fe045ba272c328684c3f7ae290785areed    canvas->drawTextRSXform(text, length, &xform[0], nullptr, paint);
12945561a0b15fe045ba272c328684c3f7ae290785areed}
13045561a0b15fe045ba272c328684c3f7ae290785areed
13145561a0b15fe045ba272c328684c3f7ae290785areedDEF_SIMPLE_GM(drawTextRSXform, canvas, 510, 310) {
13245561a0b15fe045ba272c328684c3f7ae290785areed    const char text[] = "ABCDFGHJKLMNOPQRSTUVWXYZ";
13345561a0b15fe045ba272c328684c3f7ae290785areed    const int N = sizeof(text) - 1;
13445561a0b15fe045ba272c328684c3f7ae290785areed    SkPoint pos[N];
13545561a0b15fe045ba272c328684c3f7ae290785areed    SkRSXform xform[N];
13645561a0b15fe045ba272c328684c3f7ae290785areed
13745561a0b15fe045ba272c328684c3f7ae290785areed    canvas->translate(0, 30);
13845561a0b15fe045ba272c328684c3f7ae290785areed
13945561a0b15fe045ba272c328684c3f7ae290785areed    SkScalar x = 20;
14045561a0b15fe045ba272c328684c3f7ae290785areed    SkScalar dx = 20;
14145561a0b15fe045ba272c328684c3f7ae290785areed    SkScalar rad = 0;
14245561a0b15fe045ba272c328684c3f7ae290785areed    SkScalar drad = 2 * SK_ScalarPI / (N - 1);
14345561a0b15fe045ba272c328684c3f7ae290785areed    for (int i = 0; i < N; ++i) {
14445561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fSCos = SkScalarCos(rad);
14545561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fSSin = SkScalarSin(rad);
14645561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fTx = x;
14745561a0b15fe045ba272c328684c3f7ae290785areed        xform[i].fTy = 0;
14845561a0b15fe045ba272c328684c3f7ae290785areed        pos[i].set(x, 0);
14945561a0b15fe045ba272c328684c3f7ae290785areed        x += dx;
15045561a0b15fe045ba272c328684c3f7ae290785areed        rad += drad;
15145561a0b15fe045ba272c328684c3f7ae290785areed    }
15245561a0b15fe045ba272c328684c3f7ae290785areed
15345561a0b15fe045ba272c328684c3f7ae290785areed    SkPaint paint;
15445561a0b15fe045ba272c328684c3f7ae290785areed    paint.setAntiAlias(true);
15545561a0b15fe045ba272c328684c3f7ae290785areed    paint.setTextSize(20);
15645561a0b15fe045ba272c328684c3f7ae290785areed    canvas->drawTextRSXform(text, N, xform, nullptr, paint);
15745561a0b15fe045ba272c328684c3f7ae290785areed
15845561a0b15fe045ba272c328684c3f7ae290785areed    SkPath path;
15945561a0b15fe045ba272c328684c3f7ae290785areed    path.addOval(SkRect::MakeXYWH(150, 50, 200, 200));
16045561a0b15fe045ba272c328684c3f7ae290785areed
16145561a0b15fe045ba272c328684c3f7ae290785areed    draw_text_on_path_rigid(canvas, text, N, pos, path, paint);
16245561a0b15fe045ba272c328684c3f7ae290785areed
16345561a0b15fe045ba272c328684c3f7ae290785areed    paint.setStyle(SkPaint::kStroke_Style);
16445561a0b15fe045ba272c328684c3f7ae290785areed    canvas->drawPath(path, paint);
16545561a0b15fe045ba272c328684c3f7ae290785areed}
16645561a0b15fe045ba272c328684c3f7ae290785areed
16745561a0b15fe045ba272c328684c3f7ae290785areed
168