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