• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&gtype) ||
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