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 
25 namespace skiagm {
26 class TextBlobTransforms : public GM {
27 public:
28     // This gm tests that textblobs can be translated, rotated, and scaled
TextBlobTransforms()29     TextBlobTransforms() {}
30 
31 protected:
onOnceBeforeDraw()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 
onShortName()62     SkString onShortName() override {
63         return SkString("textblobtransforms");
64     }
65 
onISize()66     SkISize onISize() override {
67         return SkISize::Make(kWidth, kHeight);
68     }
69 
onDraw(SkCanvas * canvas)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 
167 private:
168     sk_sp<SkTextBlob> fBlob;
169 
170     static constexpr int kWidth = 1000;
171     static constexpr int kHeight = 1200;
172 
173     using INHERITED = GM;
174 };
175 
176 //////////////////////////////////////////////////////////////////////////////
177 
178 DEF_GM(return new TextBlobTransforms;)
179 }  // namespace skiagm
180