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/utils/SkCustomTypeface.h"
9
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkDrawable.h"
14 #include "include/core/SkFontArguments.h"
15 #include "include/core/SkFontMetrics.h"
16 #include "include/core/SkFontParameters.h"
17 #include "include/core/SkFontStyle.h"
18 #include "include/core/SkFontTypes.h"
19 #include "include/core/SkMatrix.h"
20 #include "include/core/SkPaint.h"
21 #include "include/core/SkPath.h"
22 #include "include/core/SkPoint.h"
23 #include "include/core/SkRect.h"
24 #include "include/core/SkRefCnt.h"
25 #include "include/core/SkScalar.h"
26 #include "include/core/SkStream.h"
27 #include "include/core/SkString.h"
28 #include "include/core/SkTypeface.h"
29 #include "include/core/SkTypes.h"
30 #include "include/private/base/SkFixed.h"
31 #include "include/private/base/SkAlign.h"
32 #include "include/private/base/SkMalloc.h"
33 #include "include/private/base/SkTo.h"
34 #include "src/core/SkAdvancedTypefaceMetrics.h" // IWYU pragma: keep
35 #include "src/core/SkFontDescriptor.h"
36 #include "src/core/SkGlyph.h"
37 #include "src/core/SkMask.h"
38 #include "src/core/SkScalerContext.h"
39 #include "src/core/SkStreamPriv.h"
40
41 #include <cstdint>
42 #include <cstring>
43 #include <memory>
44 #include <utility>
45 #include <vector>
46
47 class SkArenaAlloc;
48 class SkDescriptor;
49
50 namespace {
51 static inline const constexpr bool kSkShowTextBlitCoverage = false;
52 }
53
scale_fontmetrics(const SkFontMetrics & src,float sx,float sy)54 static SkFontMetrics scale_fontmetrics(const SkFontMetrics& src, float sx, float sy) {
55 SkFontMetrics dst = src;
56
57 #define SCALE_X(field) dst.field *= sx
58 #define SCALE_Y(field) dst.field *= sy
59
60 SCALE_X(fAvgCharWidth);
61 SCALE_X(fMaxCharWidth);
62 SCALE_X(fXMin);
63 SCALE_X(fXMax);
64
65 SCALE_Y(fTop);
66 SCALE_Y(fAscent);
67 SCALE_Y(fDescent);
68 SCALE_Y(fBottom);
69 SCALE_Y(fLeading);
70 SCALE_Y(fXHeight);
71 SCALE_Y(fCapHeight);
72 SCALE_Y(fUnderlineThickness);
73 SCALE_Y(fUnderlinePosition);
74 SCALE_Y(fStrikeoutThickness);
75 SCALE_Y(fStrikeoutPosition);
76
77 #undef SCALE_X
78 #undef SCALE_Y
79
80 return dst;
81 }
82
83 class SkUserTypeface final : public SkTypeface {
84 private:
85 friend class SkCustomTypefaceBuilder;
86 friend class SkUserScalerContext;
87
SkUserTypeface(SkFontStyle style,const SkFontMetrics & metrics,std::vector<SkCustomTypefaceBuilder::GlyphRec> && recs)88 explicit SkUserTypeface(SkFontStyle style, const SkFontMetrics& metrics,
89 std::vector<SkCustomTypefaceBuilder::GlyphRec>&& recs)
90 : SkTypeface(style)
91 , fGlyphRecs(std::move(recs))
92 , fMetrics(metrics)
93 {}
94
95 const std::vector<SkCustomTypefaceBuilder::GlyphRec> fGlyphRecs;
96 const SkFontMetrics fMetrics;
97
98 std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects&,
99 const SkDescriptor* desc) const override;
100 void onFilterRec(SkScalerContextRec* rec) const override;
101 void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override;
102 std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
103
104 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
105
106 void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
107
108 void onGetFamilyName(SkString* familyName) const override;
109 bool onGetPostScriptName(SkString*) const override;
110 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
111
112 std::unique_ptr<SkStreamAsset> onOpenStream(int*) const override;
113
114 // trivial
115
onOpenExistingStream(int *) const116 std::unique_ptr<SkStreamAsset> onOpenExistingStream(int*) const override { return nullptr; }
117
onMakeClone(const SkFontArguments & args) const118 sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
119 return sk_ref_sp(this);
120 }
onCountGlyphs() const121 int onCountGlyphs() const override { return this->glyphCount(); }
onGetUPEM() const122 int onGetUPEM() const override { return 2048; /* ?? */ }
onComputeBounds(SkRect * bounds) const123 bool onComputeBounds(SkRect* bounds) const override {
124 bounds->setLTRB(fMetrics.fXMin, fMetrics.fTop, fMetrics.fXMax, fMetrics.fBottom);
125 return true;
126 }
127
128 // noops
129
getPostScriptGlyphNames(SkString *) const130 void getPostScriptGlyphNames(SkString*) const override {}
onGlyphMaskNeedsCurrentColor() const131 bool onGlyphMaskNeedsCurrentColor() const override { return false; }
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],int) const132 int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],
133 int) const override { return 0; }
onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],int) const134 int onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],
135 int) const override { return 0; }
onGetTableTags(SkFontTableTag tags[]) const136 int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
onGetTableData(SkFontTableTag,size_t,size_t,void *) const137 size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
138
glyphCount() const139 int glyphCount() const {
140 return SkToInt(fGlyphRecs.size());
141 }
142 };
143
SkCustomTypefaceBuilder()144 SkCustomTypefaceBuilder::SkCustomTypefaceBuilder() {
145 sk_bzero(&fMetrics, sizeof(fMetrics));
146 }
147
setMetrics(const SkFontMetrics & fm,float scale)148 void SkCustomTypefaceBuilder::setMetrics(const SkFontMetrics& fm, float scale) {
149 fMetrics = scale_fontmetrics(fm, scale, scale);
150 }
151
setFontStyle(SkFontStyle style)152 void SkCustomTypefaceBuilder::setFontStyle(SkFontStyle style) {
153 fStyle = style;
154 }
155
ensureStorage(SkGlyphID index)156 SkCustomTypefaceBuilder::GlyphRec& SkCustomTypefaceBuilder::ensureStorage(SkGlyphID index) {
157 if (index >= fGlyphRecs.size()) {
158 fGlyphRecs.resize(SkToSizeT(index) + 1);
159 }
160
161 return fGlyphRecs[index];
162 }
163
setGlyph(SkGlyphID index,float advance,const SkPath & path)164 void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) {
165 auto& rec = this->ensureStorage(index);
166 rec.fAdvance = advance;
167 rec.fPath = path;
168 rec.fDrawable = nullptr;
169 }
170
setGlyph(SkGlyphID index,float advance,sk_sp<SkDrawable> drawable,const SkRect & bounds)171 void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance,
172 sk_sp<SkDrawable> drawable, const SkRect& bounds) {
173 auto& rec = this->ensureStorage(index);
174 rec.fAdvance = advance;
175 rec.fDrawable = std::move(drawable);
176 rec.fBounds = bounds;
177 rec.fPath.reset();
178 }
179
detach()180 sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
181 if (fGlyphRecs.empty()) return nullptr;
182
183 // initially inverted, so that any "union" will overwrite the first time
184 SkRect bounds = {SK_ScalarMax, SK_ScalarMax, -SK_ScalarMax, -SK_ScalarMax};
185
186 for (const auto& rec : fGlyphRecs) {
187 bounds.join(rec.isDrawable()
188 ? rec.fBounds
189 : rec.fPath.getBounds());
190 }
191
192 fMetrics.fTop = bounds.top();
193 fMetrics.fBottom = bounds.bottom();
194 fMetrics.fXMin = bounds.left();
195 fMetrics.fXMax = bounds.right();
196
197 return sk_sp<SkUserTypeface>(new SkUserTypeface(fStyle, fMetrics, std::move(fGlyphRecs)));
198 }
199
200 /////////////
201
onFilterRec(SkScalerContextRec * rec) const202 void SkUserTypeface::onFilterRec(SkScalerContextRec* rec) const {
203 rec->setHinting(SkFontHinting::kNone);
204 }
205
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const206 void SkUserTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
207 for (int gid = 0; gid < this->glyphCount(); ++gid) {
208 glyphToUnicode[gid] = SkTo<SkUnichar>(gid);
209 }
210 }
211
onGetAdvancedMetrics() const212 std::unique_ptr<SkAdvancedTypefaceMetrics> SkUserTypeface::onGetAdvancedMetrics() const {
213 return nullptr;
214 }
215
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const216 void SkUserTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
217 desc->setFactoryId(SkCustomTypefaceBuilder::FactoryId);
218 *isLocal = true;
219 }
220
onCharsToGlyphs(const SkUnichar * chars,int count,SkGlyphID glyphs[]) const221 void SkUserTypeface::onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const {
222 for (int i = 0; i < count; ++i) {
223 glyphs[i] = chars[i] < this->glyphCount() ? SkTo<SkGlyphID>(chars[i]) : 0;
224 }
225 }
226
onGetFamilyName(SkString * familyName) const227 void SkUserTypeface::onGetFamilyName(SkString* familyName) const {
228 *familyName = "";
229 }
230
onGetPostScriptName(SkString *) const231 bool SkUserTypeface::onGetPostScriptName(SkString*) const {
232 return false;
233 }
234
onCreateFamilyNameIterator() const235 SkTypeface::LocalizedStrings* SkUserTypeface::onCreateFamilyNameIterator() const {
236 return nullptr;
237 }
238
239 //////////////
240
241 class SkUserScalerContext : public SkScalerContext {
242 public:
SkUserScalerContext(sk_sp<SkUserTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)243 SkUserScalerContext(sk_sp<SkUserTypeface> face,
244 const SkScalerContextEffects& effects,
245 const SkDescriptor* desc)
246 : SkScalerContext(std::move(face), effects, desc) {
247 fRec.getSingleMatrix(&fMatrix);
248 this->forceGenerateImageFromPath();
249 }
250
userTF() const251 const SkUserTypeface* userTF() const {
252 return static_cast<SkUserTypeface*>(this->getTypeface());
253 }
254
255 protected:
generateAdvance(SkGlyph * glyph)256 bool generateAdvance(SkGlyph* glyph) override {
257 const SkUserTypeface* tf = this->userTF();
258 auto advance = fMatrix.mapXY(tf->fGlyphRecs[glyph->getGlyphID()].fAdvance, 0);
259
260 glyph->fAdvanceX = advance.fX;
261 glyph->fAdvanceY = advance.fY;
262 return true;
263 }
264
generateMetrics(SkGlyph * glyph,SkArenaAlloc * alloc)265 void generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) override {
266 glyph->zeroMetrics();
267 this->generateAdvance(glyph);
268
269 const auto& rec = this->userTF()->fGlyphRecs[glyph->getGlyphID()];
270 if (rec.isDrawable()) {
271 glyph->fMaskFormat = SkMask::kARGB32_Format;
272
273 SkRect bounds = fMatrix.mapRect(rec.fBounds);
274 bounds.offset(SkFixedToScalar(glyph->getSubXFixed()),
275 SkFixedToScalar(glyph->getSubYFixed()));
276
277 SkIRect ibounds;
278 bounds.roundOut(&ibounds);
279 glyph->fLeft = ibounds.fLeft;
280 glyph->fTop = ibounds.fTop;
281 glyph->fWidth = ibounds.width();
282 glyph->fHeight = ibounds.height();
283
284 // These do not have an outline path.
285 glyph->setPath(alloc, nullptr, false);
286 }
287 }
288
generateImage(const SkGlyph & glyph)289 void generateImage(const SkGlyph& glyph) override {
290 const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
291 SkASSERTF(rec.isDrawable(), "Only drawable-backed glyphs should reach generateImage.");
292
293 auto canvas = SkCanvas::MakeRasterDirectN32(glyph.fWidth, glyph.fHeight,
294 static_cast<SkPMColor*>(glyph.fImage),
295 glyph.rowBytes());
296 if constexpr (kSkShowTextBlitCoverage) {
297 canvas->clear(0x33FF0000);
298 } else {
299 canvas->clear(SK_ColorTRANSPARENT);
300 }
301
302 canvas->translate(-glyph.fLeft, -glyph.fTop);
303 canvas->translate(SkFixedToScalar(glyph.getSubXFixed()),
304 SkFixedToScalar(glyph.getSubYFixed()));
305 canvas->drawDrawable(rec.fDrawable.get(), &fMatrix);
306 }
307
generatePath(const SkGlyph & glyph,SkPath * path)308 bool generatePath(const SkGlyph& glyph, SkPath* path) override {
309 const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
310
311 SkASSERT(!rec.isDrawable());
312
313 rec.fPath.transform(fMatrix, path);
314
315 return true;
316 }
317
generateDrawable(const SkGlyph & glyph)318 sk_sp<SkDrawable> generateDrawable(const SkGlyph& glyph) override {
319 class DrawableMatrixWrapper final : public SkDrawable {
320 public:
321 DrawableMatrixWrapper(sk_sp<SkDrawable> drawable, const SkMatrix& m)
322 : fDrawable(std::move(drawable))
323 , fMatrix(m)
324 {}
325
326 SkRect onGetBounds() override {
327 return fMatrix.mapRect(fDrawable->getBounds());
328 }
329
330 size_t onApproximateBytesUsed() override {
331 return fDrawable->approximateBytesUsed() + sizeof(DrawableMatrixWrapper);
332 }
333
334 void onDraw(SkCanvas* canvas) override {
335 if constexpr (kSkShowTextBlitCoverage) {
336 SkPaint paint;
337 paint.setColor(0x3300FF00);
338 paint.setStyle(SkPaint::kFill_Style);
339 canvas->drawRect(this->onGetBounds(), paint);
340 }
341 canvas->drawDrawable(fDrawable.get(), &fMatrix);
342 }
343 private:
344 const sk_sp<SkDrawable> fDrawable;
345 const SkMatrix fMatrix;
346 };
347
348 const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
349
350 return rec.fDrawable
351 ? sk_make_sp<DrawableMatrixWrapper>(rec.fDrawable, fMatrix)
352 : nullptr;
353 }
354
generateFontMetrics(SkFontMetrics * metrics)355 void generateFontMetrics(SkFontMetrics* metrics) override {
356 auto [sx, sy] = fMatrix.mapXY(1, 1);
357 *metrics = scale_fontmetrics(this->userTF()->fMetrics, sx, sy);
358 }
359
360 private:
361 SkMatrix fMatrix;
362 };
363
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const364 std::unique_ptr<SkScalerContext> SkUserTypeface::onCreateScalerContext(
365 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
366 {
367 return std::make_unique<SkUserScalerContext>(
368 sk_ref_sp(const_cast<SkUserTypeface*>(this)), effects, desc);
369 }
370
371 ///////////////////////////////////////////////////////////////////////////////////////////////////
372
373 static constexpr int kMaxGlyphCount = 65536;
374 static constexpr size_t kHeaderSize = 16;
375 static const char gHeaderString[] = "SkUserTypeface01";
376 static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes");
377
378 enum GlyphType : uint32_t { kPath, kDrawable };
379
onOpenStream(int * ttcIndex) const380 std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const {
381 SkDynamicMemoryWStream wstream;
382
383 wstream.write(gHeaderString, kHeaderSize);
384
385 wstream.write(&fMetrics, sizeof(fMetrics));
386
387 SkFontStyle style = this->fontStyle();
388 wstream.write(&style, sizeof(style));
389
390 wstream.write32(this->glyphCount());
391
392 for (const auto& rec : fGlyphRecs) {
393 wstream.write32(rec.isDrawable() ? GlyphType::kDrawable : GlyphType::kPath);
394
395 wstream.writeScalar(rec.fAdvance);
396
397 wstream.write(&rec.fBounds, sizeof(rec.fBounds));
398
399 auto data = rec.isDrawable()
400 ? rec.fDrawable->serialize()
401 : rec.fPath.serialize();
402
403 const size_t sz = data->size();
404 SkASSERT(SkIsAlign4(sz));
405 wstream.write(&sz, sizeof(sz));
406 wstream.write(data->data(), sz);
407 }
408
409 *ttcIndex = 0;
410 return wstream.detachAsStream();
411 }
412
413 class AutoRestorePosition {
414 SkStream* fStream;
415 size_t fPosition;
416 public:
AutoRestorePosition(SkStream * stream)417 AutoRestorePosition(SkStream* stream) : fStream(stream) {
418 fPosition = stream->getPosition();
419 }
420
~AutoRestorePosition()421 ~AutoRestorePosition() {
422 if (fStream) {
423 fStream->seek(fPosition);
424 }
425 }
426
427 // So we don't restore the position
markDone()428 void markDone() { fStream = nullptr; }
429 };
430
Deserialize(SkStream * stream)431 sk_sp<SkTypeface> SkCustomTypefaceBuilder::Deserialize(SkStream* stream) {
432 AutoRestorePosition arp(stream);
433
434 char header[kHeaderSize];
435 if (stream->read(header, kHeaderSize) != kHeaderSize ||
436 0 != memcmp(header, gHeaderString, kHeaderSize))
437 {
438 return nullptr;
439 }
440
441 SkFontMetrics metrics;
442 if (stream->read(&metrics, sizeof(metrics)) != sizeof(metrics)) {
443 return nullptr;
444 }
445
446 SkFontStyle style;
447 if (stream->read(&style, sizeof(style)) != sizeof(style)) {
448 return nullptr;
449 }
450
451 int glyphCount;
452 if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) {
453 return nullptr;
454 }
455
456 SkCustomTypefaceBuilder builder;
457
458 builder.setMetrics(metrics);
459 builder.setFontStyle(style);
460
461 for (int i = 0; i < glyphCount; ++i) {
462 uint32_t gtype;
463 if (!stream->readU32(>ype) ||
464 (gtype != GlyphType::kDrawable && gtype != GlyphType::kPath)) {
465 return nullptr;
466 }
467
468 float advance;
469 if (!stream->readScalar(&advance)) {
470 return nullptr;
471 }
472
473 SkRect bounds;
474 if (stream->read(&bounds, sizeof(bounds)) != sizeof(bounds) || !bounds.isFinite()) {
475 return nullptr;
476 }
477
478 // SkPath and SkDrawable cannot read from a stream, so we have to page them into ram
479 size_t sz;
480 if (stream->read(&sz, sizeof(sz)) != sizeof(sz)) {
481 return nullptr;
482 }
483
484 // The amount of bytes in the stream must be at least as big as sz, otherwise
485 // sz is invalid.
486 if (StreamRemainingLengthIsBelow(stream, sz)) {
487 return nullptr;
488 }
489
490 auto data = SkData::MakeUninitialized(sz);
491 if (stream->read(data->writable_data(), sz) != sz) {
492 return nullptr;
493 }
494
495 switch (gtype) {
496 case GlyphType::kDrawable: {
497 auto drawable = SkDrawable::Deserialize(data->data(), data->size());
498 if (!drawable) {
499 return nullptr;
500 }
501 builder.setGlyph(i, advance, std::move(drawable), bounds);
502 } break;
503 case GlyphType::kPath: {
504 SkPath path;
505 if (path.readFromMemory(data->data(), data->size()) != data->size()) {
506 return nullptr;
507 }
508
509 builder.setGlyph(i, advance, path);
510 } break;
511 default:
512 return nullptr;
513 }
514 }
515
516 arp.markDone();
517 return builder.detach();
518 }
519
MakeFromStream(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments &)520 sk_sp<SkTypeface> SkCustomTypefaceBuilder::MakeFromStream(std::unique_ptr<SkStreamAsset> stream,
521 const SkFontArguments&) {
522 return Deserialize(stream.get());
523 }
524