blob: a38215653d7b90a422f58ad894dea06458e81d21 [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"
9
10#include "SkCanvas.h"
11#include "SkPoint.h"
12#include "SkTextBlob.h"
13#include "SkTDArray.h"
14
15namespace {
16
17enum Pos {
18 kDefault_Pos = 0,
19 kScalar_Pos = 1,
20 kPoint_Pos = 2,
21};
22
23const struct BlobCfg {
24 unsigned count;
25 Pos pos;
26 SkScalar scale;
27} blobConfigs[][3][3] = {
28 {
29 { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
30 { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } },
31 { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } },
32 },
33 {
fmalita37ecbaf2014-08-22 09:01:19 -070034 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 } },
35 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 } },
36 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 } },
fmalita00d5c2c2014-08-21 08:53:26 -070037 },
38
39 {
fmalita37ecbaf2014-08-22 09:01:19 -070040 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
41 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
42 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
fmalita00d5c2c2014-08-21 08:53:26 -070043 },
44
45 {
fmalita37ecbaf2014-08-22 09:01:19 -070046 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
47 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
48 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
49 },
50
51 {
52 { { 4, kDefault_Pos, .75f }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1.25f } },
53 { { 4, kScalar_Pos, .75f }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1.25f } },
54 { { 4, kPoint_Pos, .75f }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1.25f } },
55 },
56
57 {
58 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, .75f }, { 4, kPoint_Pos, 1.25f } },
59 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, .75f }, { 4, kDefault_Pos, 1.25f } },
60 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, .75f }, { 4, kScalar_Pos, 1.25f } },
fmalita00d5c2c2014-08-21 08:53:26 -070061 },
62};
63
64const SkScalar kFontSize = 16;
65}
66
67class TextBlobGM : public skiagm::GM {
68public:
fmalitaacb882c2014-09-16 17:58:34 -070069 TextBlobGM(const char* txt)
kkinnunenb4a797f2015-05-21 06:15:28 -070070 : fText(txt) {
fmalita00d5c2c2014-08-21 08:53:26 -070071 }
72
73protected:
kkinnunenb4a797f2015-05-21 06:15:28 -070074 void onOnceBeforeDraw() override {
caryclark1818acb2015-07-24 12:09:25 -070075 fTypeface.reset(sk_tool_utils::create_portable_typeface("serif", SkTypeface::kNormal));
kkinnunenb4a797f2015-05-21 06:15:28 -070076 SkPaint p;
77 p.setTypeface(fTypeface);
78 size_t txtLen = strlen(fText);
halcanary96fcdcc2015-08-27 07:41:13 -070079 int glyphCount = p.textToGlyphs(fText, txtLen, nullptr);
kkinnunenb4a797f2015-05-21 06:15:28 -070080
81 fGlyphs.append(glyphCount);
82 p.textToGlyphs(fText, txtLen, fGlyphs.begin());
83 }
84
mtklein36352bf2015-03-25 18:17:31 -070085 SkString onShortName() override {
fmalita00d5c2c2014-08-21 08:53:26 -070086 return SkString("textblob");
87 }
88
mtklein36352bf2015-03-25 18:17:31 -070089 SkISize onISize() override {
fmalita00d5c2c2014-08-21 08:53:26 -070090 return SkISize::Make(640, 480);
91 }
92
mtklein36352bf2015-03-25 18:17:31 -070093 void onDraw(SkCanvas* canvas) override {
fmalita00d5c2c2014-08-21 08:53:26 -070094 for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
fmalita37ecbaf2014-08-22 09:01:19 -070095 SkAutoTUnref<const SkTextBlob> blob(this->makeBlob(b));
fmalita00d5c2c2014-08-21 08:53:26 -070096
97 SkPaint p;
fmalita00d5c2c2014-08-21 08:53:26 -070098 SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
99 SkIntToScalar(20 + 150 * (b / 2)));
100
101 canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
102
103 p.setColor(SK_ColorBLUE);
104 p.setStyle(SkPaint::kStroke_Style);
105 SkRect box = blob->bounds();
106 box.offset(offset);
107 canvas->drawRect(box, p);
108
109 }
110 }
111
112private:
113 const SkTextBlob* makeBlob(unsigned blobIndex) {
114 SkTextBlobBuilder builder;
115
116 SkPaint font;
117 font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
fmalita37ecbaf2014-08-22 09:01:19 -0700118 font.setAntiAlias(true);
119 font.setSubpixelText(true);
fmalitaacb882c2014-09-16 17:58:34 -0700120 font.setTypeface(fTypeface);
fmalita00d5c2c2014-08-21 08:53:26 -0700121
122 for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
123 unsigned currentGlyph = 0;
124
125 for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
126 const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
127 unsigned count = cfg->count;
128
129 if (count > fGlyphs.count() - currentGlyph) {
130 count = fGlyphs.count() - currentGlyph;
131 }
132 if (0 == count) {
133 break;
134 }
135
136 font.setTextSize(kFontSize * cfg->scale);
137 const SkScalar advanceX = font.getTextSize() * 0.85f;
138 const SkScalar advanceY = font.getTextSize() * 1.5f;
139
140 SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
141 advanceY * l);
142 switch (cfg->pos) {
143 case kDefault_Pos: {
144 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
145 offset.x(),
146 offset.y());
147 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
148 } break;
149 case kScalar_Pos: {
150 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
151 offset.y());
152 SkTDArray<SkScalar> pos;
153 for (unsigned i = 0; i < count; ++i) {
154 *pos.append() = offset.x() + i * advanceX;
155 }
156
157 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
158 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
159 } break;
160 case kPoint_Pos: {
161 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
162
163 SkTDArray<SkScalar> pos;
164 for (unsigned i = 0; i < count; ++i) {
165 *pos.append() = offset.x() + i * advanceX;
166 *pos.append() = offset.y() + i * (advanceY / count);
167 }
168
169 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
170 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
171 } break;
172 default:
173 SkFAIL("unhandled pos value");
174 }
175
176 currentGlyph += count;
177 }
178 }
179
180 return builder.build();
181 }
182
fmalitaacb882c2014-09-16 17:58:34 -0700183 SkTDArray<uint16_t> fGlyphs;
184 SkAutoTUnref<SkTypeface> fTypeface;
kkinnunenb4a797f2015-05-21 06:15:28 -0700185 const char* fText;
fmalita00d5c2c2014-08-21 08:53:26 -0700186 typedef skiagm::GM INHERITED;
187};
188
halcanary385fe4d2015-08-26 13:07:48 -0700189DEF_GM(return new TextBlobGM("hamburgefons");)