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/SkAlign.h"
31 #include "include/private/base/SkFixed.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:
generateMetrics(const SkGlyph & glyph,SkArenaAlloc *)256 GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
257 GlyphMetrics mx(glyph.maskFormat());
258
259 const SkUserTypeface* tf = this->userTF();
260 mx.advance = fMatrix.mapXY(tf->fGlyphRecs[glyph.getGlyphID()].fAdvance, 0);
261
262 const auto& rec = tf->fGlyphRecs[glyph.getGlyphID()];
263 if (rec.isDrawable()) {
264 mx.maskFormat = SkMask::kARGB32_Format;
265
266 SkRect bounds = fMatrix.mapRect(rec.fBounds);
267 bounds.offset(SkFixedToScalar(glyph.getSubXFixed()),
268 SkFixedToScalar(glyph.getSubYFixed()));
269 bounds.roundOut(&mx.bounds);
270
271 // These do not have an outline path.
272 mx.neverRequestPath = true;
273 }
274 return mx;
275 }
276
generateImage(const SkGlyph & glyph,void * imageBuffer)277 void generateImage(const SkGlyph& glyph, void* imageBuffer) override {
278 const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
279 SkASSERTF(rec.isDrawable(), "Only drawable-backed glyphs should reach generateImage.");
280
281 auto canvas = SkCanvas::MakeRasterDirectN32(glyph.width(), glyph.height(),
282 static_cast<SkPMColor*>(imageBuffer),
283 glyph.rowBytes());
284 if constexpr (kSkShowTextBlitCoverage) {
285 canvas->clear(0x33FF0000);
286 } else {
287 canvas->clear(SK_ColorTRANSPARENT);
288 }
289
290 canvas->translate(-glyph.left(), -glyph.top());
291 canvas->translate(SkFixedToScalar(glyph.getSubXFixed()),
292 SkFixedToScalar(glyph.getSubYFixed()));
293 canvas->drawDrawable(rec.fDrawable.get(), &fMatrix);
294 }
295
generatePath(const SkGlyph & glyph,SkPath * path)296 bool generatePath(const SkGlyph& glyph, SkPath* path) override {
297 const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
298
299 SkASSERT(!rec.isDrawable());
300
301 rec.fPath.transform(fMatrix, path);
302
303 return true;
304 }
305
generateDrawable(const SkGlyph & glyph)306 sk_sp<SkDrawable> generateDrawable(const SkGlyph& glyph) override {
307 class DrawableMatrixWrapper final : public SkDrawable {
308 public:
309 DrawableMatrixWrapper(sk_sp<SkDrawable> drawable, const SkMatrix& m)
310 : fDrawable(std::move(drawable))
311 , fMatrix(m)
312 {}
313
314 SkRect onGetBounds() override {
315 return fMatrix.mapRect(fDrawable->getBounds());
316 }
317
318 size_t onApproximateBytesUsed() override {
319 return fDrawable->approximateBytesUsed() + sizeof(DrawableMatrixWrapper);
320 }
321
322 void onDraw(SkCanvas* canvas) override {
323 if constexpr (kSkShowTextBlitCoverage) {
324 SkPaint paint;
325 paint.setColor(0x3300FF00);
326 paint.setStyle(SkPaint::kFill_Style);
327 canvas->drawRect(this->onGetBounds(), paint);
328 }
329 canvas->drawDrawable(fDrawable.get(), &fMatrix);
330 }
331 private:
332 const sk_sp<SkDrawable> fDrawable;
333 const SkMatrix fMatrix;
334 };
335
336 const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
337
338 return rec.fDrawable
339 ? sk_make_sp<DrawableMatrixWrapper>(rec.fDrawable, fMatrix)
340 : nullptr;
341 }
342
generateFontMetrics(SkFontMetrics * metrics)343 void generateFontMetrics(SkFontMetrics* metrics) override {
344 auto [sx, sy] = fMatrix.mapXY(1, 1);
345 *metrics = scale_fontmetrics(this->userTF()->fMetrics, sx, sy);
346 }
347
348 private:
349 SkMatrix fMatrix;
350 };
351
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const352 std::unique_ptr<SkScalerContext> SkUserTypeface::onCreateScalerContext(
353 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
354 {
355 return std::make_unique<SkUserScalerContext>(
356 sk_ref_sp(const_cast<SkUserTypeface*>(this)), effects, desc);
357 }
358
359 ///////////////////////////////////////////////////////////////////////////////////////////////////
360
361 static constexpr int kMaxGlyphCount = 65536;
362 static constexpr size_t kHeaderSize = 16;
363 static const char gHeaderString[] = "SkUserTypeface01";
364 static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes");
365
366 enum GlyphType : uint32_t { kPath, kDrawable };
367
onOpenStream(int * ttcIndex) const368 std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const {
369 SkDynamicMemoryWStream wstream;
370
371 wstream.write(gHeaderString, kHeaderSize);
372
373 wstream.write(&fMetrics, sizeof(fMetrics));
374
375 SkFontStyle style = this->fontStyle();
376 wstream.write(&style, sizeof(style));
377
378 wstream.write32(this->glyphCount());
379
380 for (const auto& rec : fGlyphRecs) {
381 wstream.write32(rec.isDrawable() ? GlyphType::kDrawable : GlyphType::kPath);
382
383 wstream.writeScalar(rec.fAdvance);
384
385 wstream.write(&rec.fBounds, sizeof(rec.fBounds));
386
387 auto data = rec.isDrawable()
388 ? rec.fDrawable->serialize()
389 : rec.fPath.serialize();
390
391 const size_t sz = data->size();
392 SkASSERT(SkIsAlign4(sz));
393 wstream.write(&sz, sizeof(sz));
394 wstream.write(data->data(), sz);
395 }
396
397 *ttcIndex = 0;
398 return wstream.detachAsStream();
399 }
400
401 class AutoRestorePosition {
402 SkStream* fStream;
403 size_t fPosition;
404 public:
AutoRestorePosition(SkStream * stream)405 AutoRestorePosition(SkStream* stream) : fStream(stream) {
406 fPosition = stream->getPosition();
407 }
408
~AutoRestorePosition()409 ~AutoRestorePosition() {
410 if (fStream) {
411 fStream->seek(fPosition);
412 }
413 }
414
415 // So we don't restore the position
markDone()416 void markDone() { fStream = nullptr; }
417 };
418
Deserialize(SkStream * stream)419 sk_sp<SkTypeface> SkCustomTypefaceBuilder::Deserialize(SkStream* stream) {
420 AutoRestorePosition arp(stream);
421
422 char header[kHeaderSize];
423 if (stream->read(header, kHeaderSize) != kHeaderSize ||
424 0 != memcmp(header, gHeaderString, kHeaderSize))
425 {
426 return nullptr;
427 }
428
429 SkFontMetrics metrics;
430 if (stream->read(&metrics, sizeof(metrics)) != sizeof(metrics)) {
431 return nullptr;
432 }
433
434 SkFontStyle style;
435 if (stream->read(&style, sizeof(style)) != sizeof(style)) {
436 return nullptr;
437 }
438
439 int glyphCount;
440 if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) {
441 return nullptr;
442 }
443
444 SkCustomTypefaceBuilder builder;
445
446 builder.setMetrics(metrics);
447 builder.setFontStyle(style);
448
449 for (int i = 0; i < glyphCount; ++i) {
450 uint32_t gtype;
451 if (!stream->readU32(>ype) ||
452 (gtype != GlyphType::kDrawable && gtype != GlyphType::kPath)) {
453 return nullptr;
454 }
455
456 float advance;
457 if (!stream->readScalar(&advance)) {
458 return nullptr;
459 }
460
461 SkRect bounds;
462 if (stream->read(&bounds, sizeof(bounds)) != sizeof(bounds) || !bounds.isFinite()) {
463 return nullptr;
464 }
465
466 // SkPath and SkDrawable cannot read from a stream, so we have to page them into ram
467 size_t sz;
468 if (stream->read(&sz, sizeof(sz)) != sizeof(sz)) {
469 return nullptr;
470 }
471
472 // The amount of bytes in the stream must be at least as big as sz, otherwise
473 // sz is invalid.
474 if (StreamRemainingLengthIsBelow(stream, sz)) {
475 return nullptr;
476 }
477
478 auto data = SkData::MakeUninitialized(sz);
479 if (stream->read(data->writable_data(), sz) != sz) {
480 return nullptr;
481 }
482
483 switch (gtype) {
484 case GlyphType::kDrawable: {
485 auto drawable = SkDrawable::Deserialize(data->data(), data->size());
486 if (!drawable) {
487 return nullptr;
488 }
489 builder.setGlyph(i, advance, std::move(drawable), bounds);
490 } break;
491 case GlyphType::kPath: {
492 SkPath path;
493 if (path.readFromMemory(data->data(), data->size()) != data->size()) {
494 return nullptr;
495 }
496
497 builder.setGlyph(i, advance, path);
498 } break;
499 default:
500 return nullptr;
501 }
502 }
503
504 arp.markDone();
505 return builder.detach();
506 }
507
MakeFromStream(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments &)508 sk_sp<SkTypeface> SkCustomTypefaceBuilder::MakeFromStream(std::unique_ptr<SkStreamAsset> stream,
509 const SkFontArguments&) {
510 return Deserialize(stream.get());
511 }
512