blob: d30f92f3bf12453297b5b225242faa6bfbe85fd8 [file] [log] [blame]
fmalita00d5c2c2014-08-21 08:53:26 -07001/*
2 * Copyright 2014 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.h"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
fmalita00d5c2c2014-08-21 08:53:26 -070010
11#include "SkCanvas.h"
12#include "SkPoint.h"
13#include "SkTextBlob.h"
14#include "SkTDArray.h"
15
16namespace {
17
18enum Pos {
19 kDefault_Pos = 0,
20 kScalar_Pos = 1,
21 kPoint_Pos = 2,
22};
23
24const struct BlobCfg {
25 unsigned count;
26 Pos pos;
27 SkScalar scale;
28} blobConfigs[][3][3] = {
29 {
30 { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
31 { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } },
32 { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } },
33 },
34 {
fmalita37ecbaf2014-08-22 09:01:19 -070035 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 } },
36 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 } },
37 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 } },
fmalita00d5c2c2014-08-21 08:53:26 -070038 },
39
40 {
fmalita37ecbaf2014-08-22 09:01:19 -070041 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
42 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
43 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
fmalita00d5c2c2014-08-21 08:53:26 -070044 },
45
46 {
fmalita37ecbaf2014-08-22 09:01:19 -070047 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
48 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
49 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
50 },
51
52 {
53 { { 4, kDefault_Pos, .75f }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1.25f } },
54 { { 4, kScalar_Pos, .75f }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1.25f } },
55 { { 4, kPoint_Pos, .75f }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1.25f } },
56 },
57
58 {
59 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, .75f }, { 4, kPoint_Pos, 1.25f } },
60 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, .75f }, { 4, kDefault_Pos, 1.25f } },
61 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, .75f }, { 4, kScalar_Pos, 1.25f } },
fmalita00d5c2c2014-08-21 08:53:26 -070062 },
63};
64
65const SkScalar kFontSize = 16;
66}
67
68class TextBlobGM : public skiagm::GM {
69public:
fmalitaacb882c2014-09-16 17:58:34 -070070 TextBlobGM(const char* txt)
kkinnunenb4a797f2015-05-21 06:15:28 -070071 : fText(txt) {
fmalita00d5c2c2014-08-21 08:53:26 -070072 }
73
74protected:
kkinnunenb4a797f2015-05-21 06:15:28 -070075 void onOnceBeforeDraw() override {
mbocee6a9912016-05-31 11:42:36 -070076 fTypeface = sk_tool_utils::create_portable_typeface("serif", SkFontStyle());
kkinnunenb4a797f2015-05-21 06:15:28 -070077 SkPaint p;
78 p.setTypeface(fTypeface);
79 size_t txtLen = strlen(fText);
halcanary96fcdcc2015-08-27 07:41:13 -070080 int glyphCount = p.textToGlyphs(fText, txtLen, nullptr);
kkinnunenb4a797f2015-05-21 06:15:28 -070081
82 fGlyphs.append(glyphCount);
83 p.textToGlyphs(fText, txtLen, fGlyphs.begin());
84 }
85
mtklein36352bf2015-03-25 18:17:31 -070086 SkString onShortName() override {
fmalita00d5c2c2014-08-21 08:53:26 -070087 return SkString("textblob");
88 }
89
mtklein36352bf2015-03-25 18:17:31 -070090 SkISize onISize() override {
fmalita00d5c2c2014-08-21 08:53:26 -070091 return SkISize::Make(640, 480);
92 }
93
mtklein36352bf2015-03-25 18:17:31 -070094 void onDraw(SkCanvas* canvas) override {
fmalita00d5c2c2014-08-21 08:53:26 -070095 for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
fmalita37283c22016-09-13 10:00:23 -070096 sk_sp<SkTextBlob> blob(this->makeBlob(b));
fmalita00d5c2c2014-08-21 08:53:26 -070097
98 SkPaint p;
fmalita00d5c2c2014-08-21 08:53:26 -070099 SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
100 SkIntToScalar(20 + 150 * (b / 2)));
101
102 canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
103
104 p.setColor(SK_ColorBLUE);
105 p.setStyle(SkPaint::kStroke_Style);
106 SkRect box = blob->bounds();
107 box.offset(offset);
108 canvas->drawRect(box, p);
109
110 }
111 }
112
113private:
fmalita37283c22016-09-13 10:00:23 -0700114 sk_sp<SkTextBlob> makeBlob(unsigned blobIndex) {
fmalita00d5c2c2014-08-21 08:53:26 -0700115 SkTextBlobBuilder builder;
116
117 SkPaint font;
118 font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
fmalita37ecbaf2014-08-22 09:01:19 -0700119 font.setAntiAlias(true);
120 font.setSubpixelText(true);
fmalitaacb882c2014-09-16 17:58:34 -0700121 font.setTypeface(fTypeface);
fmalita00d5c2c2014-08-21 08:53:26 -0700122
123 for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
124 unsigned currentGlyph = 0;
125
126 for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
127 const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
128 unsigned count = cfg->count;
129
130 if (count > fGlyphs.count() - currentGlyph) {
131 count = fGlyphs.count() - currentGlyph;
132 }
133 if (0 == count) {
134 break;
135 }
136
137 font.setTextSize(kFontSize * cfg->scale);
138 const SkScalar advanceX = font.getTextSize() * 0.85f;
139 const SkScalar advanceY = font.getTextSize() * 1.5f;
140
141 SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
142 advanceY * l);
143 switch (cfg->pos) {
144 case kDefault_Pos: {
145 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
146 offset.x(),
147 offset.y());
148 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
149 } break;
150 case kScalar_Pos: {
151 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
152 offset.y());
153 SkTDArray<SkScalar> pos;
154 for (unsigned i = 0; i < count; ++i) {
155 *pos.append() = offset.x() + i * advanceX;
156 }
157
158 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
159 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
160 } break;
161 case kPoint_Pos: {
162 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
163
164 SkTDArray<SkScalar> pos;
165 for (unsigned i = 0; i < count; ++i) {
166 *pos.append() = offset.x() + i * advanceX;
167 *pos.append() = offset.y() + i * (advanceY / count);
168 }
169
170 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
171 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
172 } break;
173 default:
djsollenf2b340f2016-01-29 08:51:04 -0800174 SK_ABORT("unhandled pos value");
fmalita00d5c2c2014-08-21 08:53:26 -0700175 }
176
177 currentGlyph += count;
178 }
179 }
180
fmalita37283c22016-09-13 10:00:23 -0700181 return builder.make();
fmalita00d5c2c2014-08-21 08:53:26 -0700182 }
183
bungeman13b9c952016-05-12 10:09:30 -0700184 SkTDArray<uint16_t> fGlyphs;
185 sk_sp<SkTypeface> fTypeface;
186 const char* fText;
fmalita00d5c2c2014-08-21 08:53:26 -0700187 typedef skiagm::GM INHERITED;
188};
189
halcanary385fe4d2015-08-26 13:07:48 -0700190DEF_GM(return new TextBlobGM("hamburgefons");)