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