• 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/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
onOpenExistingStream(int *) const71     std::unique_ptr<SkStreamAsset> onOpenExistingStream(int*) const override { return nullptr; }
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 {}
onGlyphMaskNeedsCurrentColor() const85     bool onGlyphMaskNeedsCurrentColor() const override { return false; }
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],int) const86     int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],
87                                      int) const override { return 0; }
onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],int) const88     int onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],
89                                        int) const override { return 0; }
onGetTableTags(SkFontTableTag tags[]) const90     int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
onGetTableData(SkFontTableTag,size_t,size_t,void *) const91     size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
92 
glyphCount() const93     int glyphCount() const {
94         SkASSERT(fPaths.size() == fAdvances.size());
95         return SkToInt(fPaths.size());
96     }
97 };
98 
SkCustomTypefaceBuilder()99 SkCustomTypefaceBuilder::SkCustomTypefaceBuilder() {
100     sk_bzero(&fMetrics, sizeof(fMetrics));
101 }
102 
setMetrics(const SkFontMetrics & fm,float scale)103 void SkCustomTypefaceBuilder::setMetrics(const SkFontMetrics& fm, float scale) {
104     fMetrics = scale_fontmetrics(fm, scale, scale);
105 }
106 
setFontStyle(SkFontStyle style)107 void SkCustomTypefaceBuilder::setFontStyle(SkFontStyle style) {
108     fStyle = style;
109 }
110 
setGlyph(SkGlyphID index,float advance,const SkPath & path)111 void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) {
112     SkASSERT(fPaths.size() == fAdvances.size());
113     if (index >= fPaths.size()) {
114            fPaths.resize(SkToSizeT(index) + 1);
115         fAdvances.resize(SkToSizeT(index) + 1);
116     }
117     fAdvances[index] = advance;
118     fPaths[index]    = path;
119 }
120 
detach()121 sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
122     SkASSERT(fPaths.size() == fAdvances.size());
123     if (fPaths.empty()) return nullptr;
124 
125     sk_sp<SkUserTypeface> tf(new SkUserTypeface(fStyle));
126     tf->fAdvances = std::move(fAdvances);
127     tf->fPaths    = std::move(fPaths);
128     tf->fMetrics  = fMetrics;
129 
130     // initially inverted, so that any "union" will overwrite the first time
131     SkRect bounds = {SK_ScalarMax, SK_ScalarMax, -SK_ScalarMax, -SK_ScalarMax};
132 
133     for (const auto& path : tf->fPaths) {
134         if (!path.isEmpty()) {
135             bounds.join(path.getBounds());
136         }
137     }
138     tf->fMetrics.fTop    = bounds.top();
139     tf->fMetrics.fBottom = bounds.bottom();
140     tf->fMetrics.fXMin   = bounds.left();
141     tf->fMetrics.fXMax   = bounds.right();
142 
143     return std::move(tf);
144 }
145 
146 /////////////
147 
148 #include "src/core/SkScalerContext.h"
149 
onFilterRec(SkScalerContextRec * rec) const150 void SkUserTypeface::onFilterRec(SkScalerContextRec* rec) const {
151     rec->setHinting(SkFontHinting::kNone);
152 }
153 
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const154 void SkUserTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
155     for (int gid = 0; gid < this->glyphCount(); ++gid) {
156         glyphToUnicode[gid] = SkTo<SkUnichar>(gid);
157     }
158 }
159 
onGetAdvancedMetrics() const160 std::unique_ptr<SkAdvancedTypefaceMetrics> SkUserTypeface::onGetAdvancedMetrics() const {
161     return nullptr;
162 }
163 
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const164 void SkUserTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
165     *isLocal = true;
166 }
167 
onCharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const168 void SkUserTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
169     for (int i = 0; i < count; ++i) {
170         glyphs[i] = uni[i] < this->glyphCount() ? SkTo<SkGlyphID>(uni[i]) : 0;
171     }
172 }
173 
onGetFamilyName(SkString * familyName) const174 void SkUserTypeface::onGetFamilyName(SkString* familyName) const {
175     *familyName = "";
176 }
177 
onGetPostScriptName(SkString *) const178 bool SkUserTypeface::onGetPostScriptName(SkString*) const {
179     return false;
180 }
181 
onCreateFamilyNameIterator() const182 SkTypeface::LocalizedStrings* SkUserTypeface::onCreateFamilyNameIterator() const {
183     return nullptr;
184 }
185 
186 //////////////
187 
188 #include "src/core/SkScalerContext.h"
189 
190 class SkUserScalerContext : public SkScalerContext {
191 public:
SkUserScalerContext(sk_sp<SkUserTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)192     SkUserScalerContext(sk_sp<SkUserTypeface>           face,
193                         const SkScalerContextEffects& effects,
194                         const SkDescriptor*           desc)
195             : SkScalerContext(std::move(face), effects, desc) {
196         fRec.getSingleMatrix(&fMatrix);
197         this->forceGenerateImageFromPath();
198     }
199 
userTF() const200     const SkUserTypeface* userTF() const {
201         return static_cast<SkUserTypeface*>(this->getTypeface());
202     }
203 
204 protected:
generateAdvance(SkGlyph * glyph)205     bool generateAdvance(SkGlyph* glyph) override {
206         const SkUserTypeface* tf = this->userTF();
207         auto advance = fMatrix.mapXY(tf->fAdvances[glyph->getGlyphID()], 0);
208 
209         glyph->fAdvanceX = advance.fX;
210         glyph->fAdvanceY = advance.fY;
211         return true;
212     }
213 
generateMetrics(SkGlyph * glyph)214     void generateMetrics(SkGlyph* glyph) override {
215         glyph->zeroMetrics();
216         this->generateAdvance(glyph);
217         // Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
218     }
219 
generateImage(const SkGlyph &)220     void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }
221 
generatePath(SkGlyphID glyph,SkPath * path)222     bool generatePath(SkGlyphID glyph, SkPath* path) override {
223         this->userTF()->fPaths[glyph].transform(fMatrix, path);
224         return true;
225     }
226 
generateFontMetrics(SkFontMetrics * metrics)227     void generateFontMetrics(SkFontMetrics* metrics) override {
228         auto [sx, sy] = fMatrix.mapXY(1, 1);
229         *metrics = scale_fontmetrics(this->userTF()->fMetrics, sx, sy);
230     }
231 
232 private:
233     SkMatrix fMatrix;
234 };
235 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const236 std::unique_ptr<SkScalerContext> SkUserTypeface::onCreateScalerContext(
237     const SkScalerContextEffects& effects, const SkDescriptor* desc) const
238 {
239     return std::make_unique<SkUserScalerContext>(
240             sk_ref_sp(const_cast<SkUserTypeface*>(this)), effects, desc);
241 }
242 
243 ///////////////////////////////////////////////////////////////////////////////////////////////////
244 
245 #include "include/private/SkFloatingPoint.h"
246 #include "src/core/SkAutoMalloc.h"
247 #include "src/core/SkPathPriv.h"
248 
write_scaled_float_to_16(SkWStream * stream,float x,float scale)249 static void write_scaled_float_to_16(SkWStream* stream, float x, float scale) {
250     stream->write16(SkToS16(sk_float_round2int(x * scale)) & 0xFFFF);
251 }
252 
253 enum PVerb {
254     kMove,
255     kLine,
256     kCurve,
257     kClose,
258 };
259 
compress_write(SkWStream * stream,const SkPath & path,int upem)260 static void compress_write(SkWStream* stream, const SkPath& path, int upem) {
261     int pCount = 0;
262     std::vector<PVerb> verbs;
263     for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
264         switch (v) {
265             default: break;
266             case SkPathVerb::kMove: verbs.push_back(kMove); pCount += 1; break;
267             case SkPathVerb::kQuad: verbs.push_back(kCurve); pCount += 2; break;
268             case SkPathVerb::kLine: verbs.push_back(kLine); pCount += 1; break;
269             case SkPathVerb::kClose: verbs.push_back(kClose); break;
270         }
271     }
272 
273     int vCount = verbs.size();
274 
275     stream->write16(upem);      // share w/ other paths?
276     stream->write16(vCount);
277     stream->write16(pCount);
278     for (int i = 0; i < (vCount & ~3); i += 4) {
279         stream->write8((verbs[i+0]<<6) | (verbs[i+1]<<4) | (verbs[i+2]<<2) | verbs[i+3]);
280     }
281     if (vCount & 3) {
282         uint8_t b = 0;
283         int shift = 6;
284         for (int i = vCount & ~3; i < vCount; ++i) {
285             b |= verbs[i] << shift;
286             shift >>= 2;
287         }
288         stream->write8(b);
289     }
290     if (vCount & 1) {
291         stream->write8(0);
292     }
293 
294     const float scale = (float)upem;
295     auto write_pts = [&](const SkPoint pts[], int count) {
296         for (int i = 0; i < count; ++i) {
297             write_scaled_float_to_16(stream, pts[i].fX, scale);
298             write_scaled_float_to_16(stream, pts[i].fY, scale);
299         }
300     };
301 
302     for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
303         switch (v) {
304             default: break;
305             case SkPathVerb::kMove: write_pts(&p[0], 1); break;
306             case SkPathVerb::kQuad: write_pts(&p[1], 2); break;
307             case SkPathVerb::kLine: write_pts(&p[1], 1); break;
308             case SkPathVerb::kClose:                     break;
309         }
310     }
311 }
312 
313 static constexpr int kMaxGlyphCount = 65536;
314 static constexpr size_t kHeaderSize = 16;
315 static const char gHeaderString[] = "SkUserTypeface01";
316 static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes");
317 
onOpenStream(int * ttcIndex) const318 std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const {
319     SkDynamicMemoryWStream wstream;
320 
321     wstream.write(gHeaderString, kHeaderSize);
322 
323     wstream.write(&fMetrics, sizeof(fMetrics));
324 
325     SkFontStyle style = this->fontStyle();
326     wstream.write(&style, sizeof(style));
327 
328     // just hacking around -- this makes the serialized font 1/2 size
329     const bool use_compression = false;
330 
331     wstream.write32(this->glyphCount());
332 
333     if (use_compression) {
334         for (float a : fAdvances) {
335             write_scaled_float_to_16(&wstream, a, 2048);
336         }
337     } else {
338         wstream.write(fAdvances.data(), this->glyphCount() * sizeof(float));
339     }
340 
341     for (const auto& p : fPaths) {
342         if (use_compression) {
343             compress_write(&wstream, p, 2048);
344         } else {
345             auto data = p.serialize();
346             SkASSERT(SkIsAlign4(data->size()));
347             wstream.write(data->data(), data->size());
348         }
349     }
350 //    SkDebugf("%d glyphs, %d bytes\n", fGlyphCount, wstream.bytesWritten());
351     *ttcIndex = 0;
352     return wstream.detachAsStream();
353 }
354 
355 class AutoRestorePosition {
356     SkStream* fStream;
357     size_t fPosition;
358 public:
AutoRestorePosition(SkStream * stream)359     AutoRestorePosition(SkStream* stream) : fStream(stream) {
360         fPosition = stream->getPosition();
361     }
362 
~AutoRestorePosition()363     ~AutoRestorePosition() {
364         if (fStream) {
365             fStream->seek(fPosition);
366         }
367     }
368 
369     // So we don't restore the position
markDone()370     void markDone() { fStream = nullptr; }
371 };
372 
Deserialize(SkStream * stream)373 sk_sp<SkTypeface> SkCustomTypefaceBuilder::Deserialize(SkStream* stream) {
374     AutoRestorePosition arp(stream);
375 
376     char header[kHeaderSize];
377     if (stream->read(header, kHeaderSize) != kHeaderSize ||
378         0 != memcmp(header, gHeaderString, kHeaderSize))
379     {
380         return nullptr;
381     }
382 
383     SkFontMetrics metrics;
384     if (stream->read(&metrics, sizeof(metrics)) != sizeof(metrics)) {
385         return nullptr;
386     }
387 
388     SkFontStyle style;
389     if (stream->read(&style, sizeof(style)) != sizeof(style)) {
390         return nullptr;
391     }
392 
393     int glyphCount;
394     if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) {
395         return nullptr;
396     }
397 
398     SkCustomTypefaceBuilder builder;
399 
400     builder.setMetrics(metrics);
401     builder.setFontStyle(style);
402 
403     std::vector<float> advances(glyphCount);
404     if (stream->read(advances.data(), glyphCount * sizeof(float)) != glyphCount * sizeof(float)) {
405         return nullptr;
406     }
407 
408     // SkPath can read from a stream, so we have to page the rest into ram
409     const size_t offset = stream->getPosition();
410     const size_t length = stream->getLength() - offset;
411     SkAutoMalloc ram(length);
412     char* buffer = (char*)ram.get();
413 
414     if (stream->read(buffer, length) != length) {
415         return nullptr;
416     }
417 
418     size_t totalUsed = 0;
419     for (int i = 0; i < glyphCount; ++i) {
420         SkPath path;
421         size_t used = path.readFromMemory(buffer + totalUsed, length - totalUsed);
422         if (used == 0) {
423             return nullptr;
424         }
425         builder.setGlyph(i, advances[i], path);
426         totalUsed += used;
427         SkASSERT(length >= totalUsed);
428     }
429 
430     // all done, update the stream to only reflect the bytes we needed
431     stream->seek(offset + totalUsed);
432 
433     arp.markDone();
434     return builder.detach();
435 }
436