1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkFont.h"
12#include "include/core/SkFontTypes.h"
13#include "include/core/SkPaint.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkRefCnt.h"
16#include "include/core/SkScalar.h"
17#include "include/core/SkSize.h"
18#include "include/core/SkString.h"
19#include "include/core/SkTextBlob.h"
20#include "include/core/SkTypeface.h"
21#include "tools/ToolUtils.h"
22
23#include <string.h>
24
25namespace skiagm {
26class TextBlobTransforms : public GM {
27public:
28    // This gm tests that textblobs can be translated, rotated, and scaled
29    TextBlobTransforms() {}
30
31protected:
32    void onOnceBeforeDraw() override {
33        SkTextBlobBuilder builder;
34
35        // make textblob.  To stress distance fields, we choose sizes appropriately
36        SkFont font(ToolUtils::create_portable_typeface(), 162);
37        font.setEdging(SkFont::Edging::kAlias);
38        const char* text = "A";
39
40        SkRect bounds;
41        font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
42        ToolUtils::add_to_text_blob(&builder, text, font, 0, 0);
43
44        // Medium
45        SkScalar xOffset = bounds.width() + 5;
46        font.setSize(72);
47        text = "B";
48        ToolUtils::add_to_text_blob(&builder, text, font, xOffset, 0);
49
50        font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
51        SkScalar yOffset = bounds.height();
52
53        // Small
54        font.setSize(32);
55        text = "C";
56        ToolUtils::add_to_text_blob(&builder, text, font, xOffset, -yOffset - 10);
57
58        // build
59        fBlob = builder.make();
60    }
61
62    SkString onShortName() override {
63        return SkString("textblobtransforms");
64    }
65
66    SkISize onISize() override {
67        return SkISize::Make(kWidth, kHeight);
68    }
69
70    void onDraw(SkCanvas* canvas) override {
71
72        canvas->drawColor(SK_ColorGRAY);
73
74        SkPaint paint;
75
76        SkRect bounds = fBlob->bounds();
77        canvas->translate(20, 20);
78
79        // Colors were chosen to map to pairs of canonical colors.  The GPU Backend will cache A8
80        // Texture Blobs based on the canonical color they map to.  Canonical colors are used to
81        // create masks.  For A8 there are 8 of them.
82        //SkColor colors[] = {SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorYELLOW, SK_ColorWHITE};
83
84        SkScalar xOffset = SkScalarCeilToScalar(bounds.width());
85        SkScalar yOffset = SkScalarCeilToScalar(bounds.height());
86        // first translate
87        canvas->translate(xOffset, 2 * yOffset);
88        canvas->drawTextBlob(fBlob, 0, 0, paint);
89        canvas->translate(-xOffset, 0);
90        canvas->drawTextBlob(fBlob, 0, 0, paint);
91        canvas->translate(2 * xOffset, 0);
92        canvas->drawTextBlob(fBlob, 0, 0, paint);
93        canvas->translate(-xOffset, -yOffset);
94        canvas->drawTextBlob(fBlob, 0, 0, paint);
95        canvas->translate(0, 2 * yOffset);
96        canvas->drawTextBlob(fBlob, 0, 0, paint);
97
98        // now rotate
99        canvas->translate(4 * xOffset, -yOffset);
100        canvas->rotate(180.f);
101        canvas->drawTextBlob(fBlob, 0, 0, paint);
102        canvas->rotate(-180.f);
103        canvas->translate(0, -yOffset);
104        canvas->rotate(-180.f);
105        canvas->drawTextBlob(fBlob, 0, 0, paint);
106        canvas->rotate(270.f);
107        canvas->drawTextBlob(fBlob, 0, 0, paint);
108        canvas->rotate(-90.f);
109        canvas->translate(-xOffset, yOffset);
110        canvas->rotate(-90.f);
111        canvas->drawTextBlob(fBlob, 0, 0, paint);
112        canvas->rotate(90.f);
113
114        // and scales
115        canvas->translate(- 3 * xOffset, 3 * yOffset);
116        canvas->scale(1.5f, 1.5f);
117        canvas->drawTextBlob(fBlob, 0, 0, paint);
118        canvas->translate(xOffset, 0);
119        canvas->scale(.25f, .25f);
120        canvas->drawTextBlob(fBlob, 0, 0, paint);
121        canvas->translate(xOffset, 0);
122        canvas->scale(3.f, 2.f);
123        canvas->drawTextBlob(fBlob, 0, 0, paint);
124
125        // finally rotates, scales, and translates together
126        canvas->translate(xOffset, 0);
127        canvas->rotate(23.f);
128        canvas->scale(.33f, .5f);
129        canvas->drawTextBlob(fBlob, 0, 0, paint);
130
131        canvas->rotate(-46.f);
132        canvas->translate(xOffset, 0);
133        canvas->scale(1.2f, 1.1f);
134        canvas->drawTextBlob(fBlob, 0, 0, paint);
135
136        canvas->rotate(46.f);
137        canvas->translate(xOffset, 0);
138        canvas->scale(1.1f, 1.2f);
139        canvas->drawTextBlob(fBlob, 0, 0, paint);
140
141        canvas->rotate(46.f);
142        canvas->translate(xOffset, 0);
143        canvas->scale(.95f, 1.1f);
144        canvas->drawTextBlob(fBlob, 0, 0, paint);
145
146        canvas->rotate(46.f);
147        canvas->translate(xOffset, 0);
148        canvas->scale(1.3f, .7f);
149        canvas->drawTextBlob(fBlob, 0, 0, paint);
150
151        canvas->rotate(46.f);
152        canvas->translate(xOffset, 0);
153        canvas->scale(.8f, 1.1f);
154        canvas->drawTextBlob(fBlob, 0, 0, paint);
155
156        canvas->rotate(10.f);
157        canvas->translate(xOffset, 0);
158        canvas->scale(1.f, 5.f);
159        canvas->drawTextBlob(fBlob, 0, 0, paint);
160
161        canvas->rotate(5.f);
162        canvas->translate(xOffset, 0);
163        canvas->scale(5.f, 1.f);
164        canvas->drawTextBlob(fBlob, 0, 0, paint);
165    }
166
167private:
168    sk_sp<SkTextBlob> fBlob;
169
170    inline static constexpr int kWidth = 1000;
171    inline static constexpr int kHeight = 1200;
172
173    using INHERITED = GM;
174};
175
176//////////////////////////////////////////////////////////////////////////////
177
178DEF_GM(return new TextBlobTransforms;)
179}  // namespace skiagm
180