Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
textblob.cpp
Go to the documentation of this file.
1/*
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/gm.h"
11#include "include/core/SkFont.h"
16#include "include/core/SkRect.h"
19#include "include/core/SkSize.h"
25#include "tools/ToolUtils.h"
27
28#include <cstring>
29
30namespace {
31
32enum Pos {
33 kDefault_Pos = 0,
34 kScalar_Pos = 1,
35 kPoint_Pos = 2,
36};
37
38const struct BlobCfg {
39 unsigned count;
40 Pos pos;
42} blobConfigs[][3][3] = {
43 {
44 { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
45 { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } },
46 { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } },
47 },
48 {
49 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 } },
50 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 } },
51 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 } },
52 },
53
54 {
55 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
56 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
57 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
58 },
59
60 {
61 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
62 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
63 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
64 },
65
66 {
67 { { 4, kDefault_Pos, .75f }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1.25f } },
68 { { 4, kScalar_Pos, .75f }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1.25f } },
69 { { 4, kPoint_Pos, .75f }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1.25f } },
70 },
71
72 {
73 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, .75f }, { 4, kPoint_Pos, 1.25f } },
74 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, .75f }, { 4, kDefault_Pos, 1.25f } },
75 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, .75f }, { 4, kScalar_Pos, 1.25f } },
76 },
77};
78
79const SkScalar kFontSize = 16;
80} // namespace
81
82class TextBlobGM : public skiagm::GM {
83public:
84 TextBlobGM(const char* txt)
85 : fText(txt) {
86 }
87
88protected:
89 void onOnceBeforeDraw() override {
90 fTypeface = ToolUtils::CreatePortableTypeface("serif", SkFontStyle());
91 SkFont font(fTypeface);
92 size_t txtLen = strlen(fText);
93 int glyphCount = font.countText(fText, txtLen, SkTextEncoding::kUTF8);
94
95 fGlyphs.append(glyphCount);
96 font.textToGlyphs(fText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), glyphCount);
97 }
98
99 SkString getName() const override { return SkString("textblob"); }
100
101 SkISize getISize() override { return SkISize::Make(640, 480); }
102
103 void onDraw(SkCanvas* canvas) override {
104 for (unsigned b = 0; b < std::size(blobConfigs); ++b) {
105 sk_sp<SkTextBlob> blob(this->makeBlob(b));
106
107 SkPaint p;
108 p.setAntiAlias(true);
109 SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
110 SkIntToScalar(20 + 150 * (b / 2)));
111
112 canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
113
114 p.setColor(SK_ColorBLUE);
115 p.setStyle(SkPaint::kStroke_Style);
116 SkRect box = blob->bounds();
117 box.offset(offset);
118 p.setAntiAlias(false);
119 canvas->drawRect(box, p);
120
121 }
122 }
123
124private:
125 sk_sp<SkTextBlob> makeBlob(unsigned blobIndex) {
126 SkTextBlobBuilder builder;
127
128 SkFont font;
129 font.setSubpixel(true);
130 font.setEdging(SkFont::Edging::kAntiAlias);
131 font.setTypeface(fTypeface);
132
133 for (unsigned l = 0; l < std::size(blobConfigs[blobIndex]); ++l) {
134 unsigned currentGlyph = 0;
135
136 for (unsigned c = 0; c < std::size(blobConfigs[blobIndex][l]); ++c) {
137 const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
138 unsigned count = cfg->count;
139
140 if (count > fGlyphs.size() - currentGlyph) {
141 count = fGlyphs.size() - currentGlyph;
142 }
143 if (0 == count) {
144 break;
145 }
146
147 font.setSize(kFontSize * cfg->scale);
148 const SkScalar advanceX = font.getSize() * 0.85f;
149 const SkScalar advanceY = font.getSize() * 1.5f;
150
151 SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
152 advanceY * l);
153 switch (cfg->pos) {
154 case kDefault_Pos: {
155 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
156 offset.x(),
157 offset.y());
158 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
159 } break;
160 case kScalar_Pos: {
161 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
162 offset.y());
164 for (unsigned i = 0; i < count; ++i) {
165 *pos.append() = offset.x() + i * advanceX;
166 }
167
168 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
169 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
170 } break;
171 case kPoint_Pos: {
172 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
173
175 for (unsigned i = 0; i < count; ++i) {
176 *pos.append() = offset.x() + i * advanceX;
177 *pos.append() = offset.y() + i * (advanceY / count);
178 }
179
180 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
181 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
182 } break;
183 default:
184 SK_ABORT("unhandled pos value");
185 }
186
187 currentGlyph += count;
188 }
189 }
190
191 return builder.make();
192 }
193
194 SkTDArray<uint16_t> fGlyphs;
195 sk_sp<SkTypeface> fTypeface;
196 const char* fText;
197 using INHERITED = skiagm::GM;
198};
199
200DEF_GM(return new TextBlobGM("hamburgefons");)
int count
SkPoint pos
#define SK_ABORT(message,...)
Definition SkAssert.h:70
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
@ kUTF8
uses bytes to represent UTF-8 or ASCII
#define SkIntToScalar(x)
Definition SkScalar.h:57
void drawRect(const SkRect &rect, const SkPaint &paint)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
@ kAntiAlias
may have transparent pixels on glyph edges
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
int size() const
Definition SkTDArray.h:138
T * begin()
Definition SkTDArray.h:150
T * append()
Definition SkTDArray.h:191
TextBlobGM(const char *txt)
Definition textblob.cpp:84
void onOnceBeforeDraw() override
Definition textblob.cpp:89
void onDraw(SkCanvas *canvas) override
Definition textblob.cpp:103
SkISize getISize() override
Definition textblob.cpp:101
SkString getName() const override
Definition textblob.cpp:99
float SkScalar
Definition extension.cpp:12
static bool b
#define DEF_GM(CODE)
Definition gm.h:40
sk_sp< SkTypeface > CreatePortableTypeface(const char *name, SkFontStyle style)
font
Font Metadata and Metrics.
const Scalar scale
Point offset
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
static constexpr SkPoint Make(float x, float y)
constexpr float y() const
constexpr float x() const
void offset(float dx, float dy)
Definition SkRect.h:1016
SkScalar * pos
storage for glyph positions in run
Definition SkTextBlob.h:330
SkGlyphID * glyphs
storage for glyph indexes in run
Definition SkTextBlob.h:329