Flutter Engine
The Flutter Engine
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) {
127
128 SkFont font;
129 font.setSubpixel(true);
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
Definition: FontMgrTest.cpp:50
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)
Definition: SkCanvas.cpp:1673
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
Definition: SkCanvas.cpp:2484
Definition: SkFont.h:35
@ 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
const SkRect & bounds() const
Definition: SkTextBlob.h:53
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
Definition: gm.h:110
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)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
const Scalar scale
SeparatedVector2 offset
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
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