1 /*
2 * Copyright 2020 Google LLC
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 "include/core/SkCanvas.h"
9 #include "include/core/SkData.h"
10 #include "include/core/SkFontMetrics.h"
11 #include "include/utils/SkCustomTypeface.h"
12 #include "src/core/SkAdvancedTypefaceMetrics.h"
13
scale_fontmetrics(const SkFontMetrics & src,float sx,float sy)14 static SkFontMetrics scale_fontmetrics(const SkFontMetrics& src, float sx, float sy) {
15 SkFontMetrics dst = src;
16
17 #define SCALE_X(field) dst.field *= sx
18 #define SCALE_Y(field) dst.field *= sy
19
20 SCALE_X(fAvgCharWidth);
21 SCALE_X(fMaxCharWidth);
22 SCALE_X(fXMin);
23 SCALE_X(fXMax);
24
25 SCALE_Y(fTop);
26 SCALE_Y(fAscent);
27 SCALE_Y(fDescent);
28 SCALE_Y(fBottom);
29 SCALE_Y(fLeading);
30 SCALE_Y(fXHeight);
31 SCALE_Y(fCapHeight);
32 SCALE_Y(fUnderlineThickness);
33 SCALE_Y(fUnderlinePosition);
34 SCALE_Y(fStrikeoutThickness);
35 SCALE_Y(fStrikeoutPosition);
36
37 #undef SCALE_X
38 #undef SCALE_Y
39
40 return dst;
41 }
42
43 class SkUserTypeface final : public SkTypeface {
44 private:
45 friend class SkCustomTypefaceBuilder;
46 friend class SkUserScalerContext;
47
SkUserTypeface(SkFontStyle style)48 explicit SkUserTypeface(SkFontStyle style) : SkTypeface(style) {}
49
50 std::vector<SkPath> fPaths;
51 std::vector<float> fAdvances;
52 SkFontMetrics fMetrics;
53
54 std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects&,
55 const SkDescriptor* desc) const override;
56 void onFilterRec(SkScalerContextRec* rec) const override;
57 void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override;
58 std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
59
60 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
61
62 void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
63
64 void onGetFamilyName(SkString* familyName) const override;
65 bool onGetPostScriptName(SkString*) const override;
66 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
67
68 std::unique_ptr<SkStreamAsset> onOpenStream(int*) const override;
69
70 // trivial
71
onMakeClone(const SkFontArguments & args) const72 sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
73 return sk_ref_sp(this);
74 }
onCountGlyphs() const75 int onCountGlyphs() const override { return this->glyphCount(); }
onGetUPEM() const76 int onGetUPEM() const override { return 2048; /* ?? */ }
onComputeBounds(SkRect * bounds) const77 bool onComputeBounds(SkRect* bounds) const override {
78 bounds->setLTRB(fMetrics.fXMin, fMetrics.fTop, fMetrics.fXMax, fMetrics.fBottom);
79 return true;
80 }
81
82 // noops
83
getPostScriptGlyphNames(SkString *) const84 void getPostScriptGlyphNames(SkString*) const override {}
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],int) const85 int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],
86 int) const override { return 0; }
onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],int) const87 int onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],
88 int) const override { return 0; }
onGetTableTags(SkFontTableTag tags[]) const89 int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
onGetTableData(SkFontTableTag,size_t,size_t,void *) const90 size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
91
glyphCount() const92 int glyphCount() const {
93 SkASSERT(fPaths.size() == fAdvances.size());
94 return SkToInt(fPaths.size());
95 }
96 };
97
SkCustomTypefaceBuilder()98 SkCustomTypefaceBuilder::SkCustomTypefaceBuilder() {
99 sk_bzero(&fMetrics, sizeof(fMetrics));
100 }
101
setMetrics(const SkFontMetrics & fm,float scale)102 void SkCustomTypefaceBuilder::setMetrics(const SkFontMetrics& fm, float scale) {
103 fMetrics = scale_fontmetrics(fm, scale, scale);
104 }
105
setFontStyle(SkFontStyle style)106 void SkCustomTypefaceBuilder::setFontStyle(SkFontStyle style) {
107 fStyle = style;
108 }
109
setGlyph(SkGlyphID index,float advance,const SkPath & path)110 void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) {
111 SkASSERT(fPaths.size() == fAdvances.size());
112 if (index >= fPaths.size()) {
113 fPaths.resize(SkToSizeT(index) + 1);
114 fAdvances.resize(SkToSizeT(index) + 1);
115 }
116 fAdvances[index] = advance;
117 fPaths[index] = path;
118 }
119
detach()120 sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
121 SkASSERT(fPaths.size() == fAdvances.size());
122 if (fPaths.empty()) return nullptr;
123
124 sk_sp<SkUserTypeface> tf(new SkUserTypeface(fStyle));
125 tf->fAdvances = std::move(fAdvances);
126 tf->fPaths = std::move(fPaths);
127 tf->fMetrics = fMetrics;
128
129 // initially inverted, so that any "union" will overwrite the first time
130 SkRect bounds = {SK_ScalarMax, SK_ScalarMax, -SK_ScalarMax, -SK_ScalarMax};
131
132 for (const auto& path : tf->fPaths) {
133 if (!path.isEmpty()) {
134 bounds.join(path.getBounds());
135 }
136 }
137 tf->fMetrics.fTop = bounds.top();
138 tf->fMetrics.fBottom = bounds.bottom();
139 tf->fMetrics.fXMin = bounds.left();
140 tf->fMetrics.fXMax = bounds.right();
141
142 return std::move(tf);
143 }
144
145 /////////////
146
147 #include "src/core/SkScalerContext.h"
148
onFilterRec(SkScalerContextRec * rec) const149 void SkUserTypeface::onFilterRec(SkScalerContextRec* rec) const {
150 rec->setHinting(SkFontHinting::kNone);
151 }
152
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const153 void SkUserTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
154 for (int gid = 0; gid < this->glyphCount(); ++gid) {
155 glyphToUnicode[gid] = SkTo<SkUnichar>(gid);
156 }
157 }
158
onGetAdvancedMetrics() const159 std::unique_ptr<SkAdvancedTypefaceMetrics> SkUserTypeface::onGetAdvancedMetrics() const {
160 return nullptr;
161 }
162
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const163 void SkUserTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
164 *isLocal = true;
165 }
166
onCharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const167 void SkUserTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
168 for (int i = 0; i < count; ++i) {
169 glyphs[i] = uni[i] < this->glyphCount() ? SkTo<SkGlyphID>(uni[i]) : 0;
170 }
171 }
172
onGetFamilyName(SkString * familyName) const173 void SkUserTypeface::onGetFamilyName(SkString* familyName) const {
174 *familyName = "";
175 }
176
onGetPostScriptName(SkString *) const177 bool SkUserTypeface::onGetPostScriptName(SkString*) const {
178 return false;
179 }
180
onCreateFamilyNameIterator() const181 SkTypeface::LocalizedStrings* SkUserTypeface::onCreateFamilyNameIterator() const {
182 return nullptr;
183 }
184
185 //////////////
186
187 #include "src/core/SkScalerContext.h"
188
189 class SkUserScalerContext : public SkScalerContext {
190 public:
SkUserScalerContext(sk_sp<SkUserTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)191 SkUserScalerContext(sk_sp<SkUserTypeface> face,
192 const SkScalerContextEffects& effects,
193 const SkDescriptor* desc)
194 : SkScalerContext(std::move(face), effects, desc) {
195 fRec.getSingleMatrix(&fMatrix);
196 this->forceGenerateImageFromPath();
197 }
198
userTF() const199 const SkUserTypeface* userTF() const {
200 return static_cast<SkUserTypeface*>(this->getTypeface());
201 }
202
203 protected:
generateAdvance(SkGlyph * glyph)204 bool generateAdvance(SkGlyph* glyph) override {
205 const SkUserTypeface* tf = this->userTF();
206 auto advance = fMatrix.mapXY(tf->fAdvances[glyph->getGlyphID()], 0);
207
208 glyph->fAdvanceX = advance.fX;
209 glyph->fAdvanceY = advance.fY;
210 return true;
211 }
212
generateMetrics(SkGlyph * glyph)213 void generateMetrics(SkGlyph* glyph) override {
214 glyph->zeroMetrics();
215 this->generateAdvance(glyph);
216 // Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
217 }
218
generateImage(const SkGlyph &)219 void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }
220
generatePath(SkGlyphID glyph,SkPath * path)221 bool generatePath(SkGlyphID glyph, SkPath* path) override {
222 this->userTF()->fPaths[glyph].transform(fMatrix, path);
223 return true;
224 }
225
generateFontMetrics(SkFontMetrics * metrics)226 void generateFontMetrics(SkFontMetrics* metrics) override {
227 auto [sx, sy] = fMatrix.mapXY(1, 1);
228 *metrics = scale_fontmetrics(this->userTF()->fMetrics, sx, sy);
229 }
230
231 private:
232 SkMatrix fMatrix;
233 };
234
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const235 std::unique_ptr<SkScalerContext> SkUserTypeface::onCreateScalerContext(
236 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
237 {
238 return std::make_unique<SkUserScalerContext>(
239 sk_ref_sp(const_cast<SkUserTypeface*>(this)), effects, desc);
240 }
241
242 ///////////////////////////////////////////////////////////////////////////////////////////////////
243
244 #include "include/private/SkFloatingPoint.h"
245 #include "src/core/SkAutoMalloc.h"
246 #include "src/core/SkPathPriv.h"
247
write_scaled_float_to_16(SkWStream * stream,float x,float scale)248 static void write_scaled_float_to_16(SkWStream* stream, float x, float scale) {
249 stream->write16(SkToS16(sk_float_round2int(x * scale)) & 0xFFFF);
250 }
251
252 enum PVerb {
253 kMove,
254 kLine,
255 kCurve,
256 kClose,
257 };
258
compress_write(SkWStream * stream,const SkPath & path,int upem)259 static void compress_write(SkWStream* stream, const SkPath& path, int upem) {
260 int pCount = 0;
261 std::vector<PVerb> verbs;
262 for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
263 switch (v) {
264 default: break;
265 case SkPathVerb::kMove: verbs.push_back(kMove); pCount += 1; break;
266 case SkPathVerb::kQuad: verbs.push_back(kCurve); pCount += 2; break;
267 case SkPathVerb::kLine: verbs.push_back(kLine); pCount += 1; break;
268 case SkPathVerb::kClose: verbs.push_back(kClose); break;
269 }
270 }
271
272 int vCount = verbs.size();
273
274 stream->write16(upem); // share w/ other paths?
275 stream->write16(vCount);
276 stream->write16(pCount);
277 for (int i = 0; i < (vCount & ~3); i += 4) {
278 stream->write8((verbs[i+0]<<6) | (verbs[i+1]<<4) | (verbs[i+2]<<2) | verbs[i+3]);
279 }
280 if (vCount & 3) {
281 uint8_t b = 0;
282 int shift = 6;
283 for (int i = vCount & ~3; i < vCount; ++i) {
284 b |= verbs[i] << shift;
285 shift >>= 2;
286 }
287 stream->write8(b);
288 }
289 if (vCount & 1) {
290 stream->write8(0);
291 }
292
293 const float scale = (float)upem;
294 auto write_pts = [&](const SkPoint pts[], int count) {
295 for (int i = 0; i < count; ++i) {
296 write_scaled_float_to_16(stream, pts[i].fX, scale);
297 write_scaled_float_to_16(stream, pts[i].fY, scale);
298 }
299 };
300
301 for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
302 switch (v) {
303 default: break;
304 case SkPathVerb::kMove: write_pts(&p[0], 1); break;
305 case SkPathVerb::kQuad: write_pts(&p[1], 2); break;
306 case SkPathVerb::kLine: write_pts(&p[1], 1); break;
307 case SkPathVerb::kClose: break;
308 }
309 }
310 }
311
312 static constexpr int kMaxGlyphCount = 65536;
313 static constexpr size_t kHeaderSize = 16;
314 static const char gHeaderString[] = "SkUserTypeface01";
315 static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes");
316
onOpenStream(int * ttcIndex) const317 std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const {
318 SkDynamicMemoryWStream wstream;
319
320 wstream.write(gHeaderString, kHeaderSize);
321
322 wstream.write(&fMetrics, sizeof(fMetrics));
323
324 SkFontStyle style = this->fontStyle();
325 wstream.write(&style, sizeof(style));
326
327 // just hacking around -- this makes the serialized font 1/2 size
328 const bool use_compression = false;
329
330 wstream.write32(this->glyphCount());
331
332 if (use_compression) {
333 for (float a : fAdvances) {
334 write_scaled_float_to_16(&wstream, a, 2048);
335 }
336 } else {
337 wstream.write(fAdvances.data(), this->glyphCount() * sizeof(float));
338 }
339
340 for (const auto& p : fPaths) {
341 if (use_compression) {
342 compress_write(&wstream, p, 2048);
343 } else {
344 auto data = p.serialize();
345 SkASSERT(SkIsAlign4(data->size()));
346 wstream.write(data->data(), data->size());
347 }
348 }
349 // SkDebugf("%d glyphs, %d bytes\n", fGlyphCount, wstream.bytesWritten());
350 *ttcIndex = 0;
351 return wstream.detachAsStream();
352 }
353
354 class AutoRestorePosition {
355 SkStream* fStream;
356 size_t fPosition;
357 public:
AutoRestorePosition(SkStream * stream)358 AutoRestorePosition(SkStream* stream) : fStream(stream) {
359 fPosition = stream->getPosition();
360 }
361
~AutoRestorePosition()362 ~AutoRestorePosition() {
363 if (fStream) {
364 fStream->seek(fPosition);
365 }
366 }
367
368 // So we don't restore the position
markDone()369 void markDone() { fStream = nullptr; }
370 };
371
Deserialize(SkStream * stream)372 sk_sp<SkTypeface> SkCustomTypefaceBuilder::Deserialize(SkStream* stream) {
373 AutoRestorePosition arp(stream);
374
375 char header[kHeaderSize];
376 if (stream->read(header, kHeaderSize) != kHeaderSize ||
377 0 != memcmp(header, gHeaderString, kHeaderSize))
378 {
379 return nullptr;
380 }
381
382 SkFontMetrics metrics;
383 if (stream->read(&metrics, sizeof(metrics)) != sizeof(metrics)) {
384 return nullptr;
385 }
386
387 SkFontStyle style;
388 if (stream->read(&style, sizeof(style)) != sizeof(style)) {
389 return nullptr;
390 }
391
392 int glyphCount;
393 if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) {
394 return nullptr;
395 }
396
397 SkCustomTypefaceBuilder builder;
398
399 builder.setMetrics(metrics);
400 builder.setFontStyle(style);
401
402 std::vector<float> advances(glyphCount);
403 if (stream->read(advances.data(), glyphCount * sizeof(float)) != glyphCount * sizeof(float)) {
404 return nullptr;
405 }
406
407 // SkPath can read from a stream, so we have to page the rest into ram
408 const size_t offset = stream->getPosition();
409 const size_t length = stream->getLength() - offset;
410 SkAutoMalloc ram(length);
411 char* buffer = (char*)ram.get();
412
413 if (stream->read(buffer, length) != length) {
414 return nullptr;
415 }
416
417 size_t totalUsed = 0;
418 for (int i = 0; i < glyphCount; ++i) {
419 SkPath path;
420 size_t used = path.readFromMemory(buffer + totalUsed, length - totalUsed);
421 if (used == 0) {
422 return nullptr;
423 }
424 builder.setGlyph(i, advances[i], path);
425 totalUsed += used;
426 SkASSERT(length >= totalUsed);
427 }
428
429 // all done, update the stream to only reflect the bytes we needed
430 stream->seek(offset + totalUsed);
431
432 arp.markDone();
433 return builder.detach();
434 }
435