xref: /aosp_15_r20/external/skia/src/core/SkTypeface.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2011 The Android Open Source Project
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 #include "include/core/SkTypeface.h"
8 
9 #include "include/core/SkData.h"
10 #include "include/core/SkFont.h"
11 #include "include/core/SkFontMetrics.h"
12 #include "include/core/SkFontMgr.h"
13 #include "include/core/SkFontTypes.h"
14 #include "include/core/SkScalar.h"
15 #include "include/core/SkStream.h"
16 #include "include/private/base/SkDebug.h"
17 #include "include/private/base/SkMalloc.h"
18 #include "include/private/base/SkOnce.h"
19 #include "include/private/base/SkTemplates.h"
20 #include "include/utils/SkCustomTypeface.h"
21 #include "src/base/SkBitmaskEnum.h"
22 #include "src/base/SkEndian.h"
23 #include "src/base/SkNoDestructor.h"
24 #include "src/base/SkUTF.h"
25 #include "src/core/SkAdvancedTypefaceMetrics.h"
26 #include "src/core/SkDescriptor.h"
27 #include "src/core/SkFontDescriptor.h"
28 #include "src/core/SkFontPriv.h"
29 #include "src/core/SkScalerContext.h"
30 #include "src/core/SkTypefaceCache.h"
31 #include "src/sfnt/SkOTTable_OS_2.h"
32 
33 #ifdef SK_TYPEFACE_FACTORY_FREETYPE
34 #include "src/ports/SkTypeface_FreeType.h"
35 #endif
36 
37 #ifdef SK_TYPEFACE_FACTORY_CORETEXT
38 #include "src/ports/SkTypeface_mac_ct.h"
39 #endif
40 
41 #ifdef SK_TYPEFACE_FACTORY_DIRECTWRITE
42 #include "src/ports/SkTypeface_win_dw.h"
43 #endif
44 
45 // TODO(https://crbug.com/skia/14338): This needs to be set by Bazel rules.
46 #ifdef SK_TYPEFACE_FACTORY_FONTATIONS
47 #include "src/ports/SkTypeface_fontations_priv.h"
48 #endif
49 
50 #include <cstddef>
51 #include <cstring>
52 #include <vector>
53 
54 using namespace skia_private;
55 
SkTypeface(const SkFontStyle & style,bool isFixedPitch)56 SkTypeface::SkTypeface(const SkFontStyle& style, bool isFixedPitch)
57     : fUniqueID(SkTypefaceCache::NewTypefaceID()), fStyle(style), fIsFixedPitch(isFixedPitch) { }
58 
~SkTypeface()59 SkTypeface::~SkTypeface() { }
60 
61 ///////////////////////////////////////////////////////////////////////////////
62 
63 namespace {
64 
65 class SkEmptyTypeface : public SkTypeface {
66 public:
Make()67     static sk_sp<SkTypeface> Make() {
68         static SkNoDestructor<SkEmptyTypeface> instance;
69         return sk_ref_sp(instance.get());
70     }
71 
72     static constexpr SkTypeface::FactoryId FactoryId = SkSetFourByteTag('e','m','t','y');
MakeFromStream(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments &)73     static sk_sp<SkTypeface> MakeFromStream(std::unique_ptr<SkStreamAsset> stream,
74                                             const SkFontArguments&) {
75         if (stream->getLength() == 0) {
76             return SkEmptyTypeface::Make();
77         }
78         return nullptr;
79     }
80 protected:
81     friend SkNoDestructor<SkEmptyTypeface>;
SkEmptyTypeface()82     SkEmptyTypeface() : SkTypeface(SkFontStyle(), true) { }
83 
onOpenStream(int * ttcIndex) const84     std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override { return nullptr; }
onMakeClone(const SkFontArguments & args) const85     sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
86         return sk_ref_sp(this);
87     }
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const88     std::unique_ptr<SkScalerContext> onCreateScalerContext(
89         const SkScalerContextEffects& effects, const SkDescriptor* desc) const override
90     {
91         return SkScalerContext::MakeEmpty(
92                 sk_ref_sp(const_cast<SkEmptyTypeface*>(this)), effects, desc);
93     }
onFilterRec(SkScalerContextRec *) const94     void onFilterRec(SkScalerContextRec*) const override { }
onGetAdvancedMetrics() const95     std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
96         return nullptr;
97     }
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const98     void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
99         desc->setFactoryId(FactoryId);
100         *serialize = false;
101     }
onCharsToGlyphs(const SkUnichar * chars,int count,SkGlyphID glyphs[]) const102     void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override {
103         sk_bzero(glyphs, count * sizeof(glyphs[0]));
104     }
onCountGlyphs() const105     int onCountGlyphs() const override { return 0; }
getPostScriptGlyphNames(SkString *) const106     void getPostScriptGlyphNames(SkString*) const override {}
getGlyphToUnicodeMap(SkUnichar *) const107     void getGlyphToUnicodeMap(SkUnichar*) const override {}
onGetUPEM() const108     int onGetUPEM() const override { return 0; }
onComputeBounds(SkRect * bounds) const109     bool onComputeBounds(SkRect* bounds) const override { return false; }
110 
111     class EmptyLocalizedStrings : public SkTypeface::LocalizedStrings {
112     public:
next(SkTypeface::LocalizedString *)113         bool next(SkTypeface::LocalizedString*) override { return false; }
114     };
onGetFamilyName(SkString * familyName) const115     void onGetFamilyName(SkString* familyName) const override {
116         familyName->reset();
117     }
onGetPostScriptName(SkString *) const118     bool onGetPostScriptName(SkString*) const override {
119         return false;
120     }
onCreateFamilyNameIterator() const121     SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override {
122         return new EmptyLocalizedStrings;
123     }
onGlyphMaskNeedsCurrentColor() const124     bool onGlyphMaskNeedsCurrentColor() const override {
125         return false;
126     }
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const127     int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
128                                      int coordinateCount) const override
129     {
130         return 0;
131     }
onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const132     int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
133                                        int parameterCount) const override
134     {
135         return 0;
136     }
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 {
139         return 0;
140     }
141 };
142 
143 }  // namespace
144 
MakeEmpty()145 sk_sp<SkTypeface> SkTypeface::MakeEmpty() {
146     return SkEmptyTypeface::Make();
147 }
148 
Equal(const SkTypeface * facea,const SkTypeface * faceb)149 bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) {
150     if (facea == faceb) {
151         return true;
152     }
153     if (!facea || !faceb) {
154         return false;
155     }
156     return facea->uniqueID() == faceb->uniqueID();
157 }
158 
159 ///////////////////////////////////////////////////////////////////////////////
160 
161 namespace {
162 
163     struct DecoderProc {
164         SkFourByteTag id;
165         sk_sp<SkTypeface> (*makeFromStream)(std::unique_ptr<SkStreamAsset>, const SkFontArguments&);
166     };
167 
decoders()168     std::vector<DecoderProc>* decoders() {
169         static SkNoDestructor<std::vector<DecoderProc>> decoders{{
170             { SkEmptyTypeface::FactoryId, SkEmptyTypeface::MakeFromStream },
171             { SkCustomTypefaceBuilder::FactoryId, SkCustomTypefaceBuilder::MakeFromStream },
172 #ifdef SK_TYPEFACE_FACTORY_CORETEXT
173             { SkTypeface_Mac::FactoryId, SkTypeface_Mac::MakeFromStream },
174 #endif
175 #ifdef SK_TYPEFACE_FACTORY_DIRECTWRITE
176             { DWriteFontTypeface::FactoryId, DWriteFontTypeface::MakeFromStream },
177 #endif
178 #ifdef SK_TYPEFACE_FACTORY_FREETYPE
179             { SkTypeface_FreeType::FactoryId, SkTypeface_FreeType::MakeFromStream },
180 #endif
181 #ifdef SK_TYPEFACE_FACTORY_FONTATIONS
182             { SkTypeface_Fontations::FactoryId, SkTypeface_Fontations::MakeFromStream },
183 #endif
184         }};
185         return decoders.get();
186     }
187 
188 }  // namespace
189 
makeClone(const SkFontArguments & args) const190 sk_sp<SkTypeface> SkTypeface::makeClone(const SkFontArguments& args) const {
191     return this->onMakeClone(args);
192 }
193 
194 ///////////////////////////////////////////////////////////////////////////////
195 
Register(FactoryId id,sk_sp<SkTypeface> (* make)(std::unique_ptr<SkStreamAsset>,const SkFontArguments &))196 void SkTypeface::Register(
197             FactoryId id,
198             sk_sp<SkTypeface> (*make)(std::unique_ptr<SkStreamAsset>, const SkFontArguments&)) {
199     decoders()->push_back(DecoderProc{id, make});
200 }
201 
serialize(SkWStream * wstream,SerializeBehavior behavior) const202 void SkTypeface::serialize(SkWStream* wstream, SerializeBehavior behavior) const {
203     bool isLocalData = false;
204     SkFontDescriptor desc;
205     this->onGetFontDescriptor(&desc, &isLocalData);
206     if (desc.getFactoryId() == 0) {
207         SkDEBUGF("Factory was not set for %s.\n", desc.getFamilyName());
208     }
209 
210     bool shouldSerializeData = false;
211     switch (behavior) {
212         case SerializeBehavior::kDoIncludeData:      shouldSerializeData = true;        break;
213         case SerializeBehavior::kDontIncludeData:    shouldSerializeData = false;       break;
214         case SerializeBehavior::kIncludeDataIfLocal: shouldSerializeData = isLocalData; break;
215     }
216 
217     if (shouldSerializeData) {
218         int index;
219         desc.setStream(this->openStream(&index));
220         if (desc.hasStream()) {
221             desc.setCollectionIndex(index);
222         }
223 
224         int numAxes = this->getVariationDesignPosition(nullptr, 0);
225         if (0 < numAxes) {
226             numAxes = this->getVariationDesignPosition(desc.setVariationCoordinates(numAxes), numAxes);
227             if (numAxes <= 0) {
228                 desc.setVariationCoordinates(0);
229             }
230         }
231     }
232     desc.serialize(wstream);
233 }
234 
serialize(SerializeBehavior behavior) const235 sk_sp<SkData> SkTypeface::serialize(SerializeBehavior behavior) const {
236     SkDynamicMemoryWStream stream;
237     this->serialize(&stream, behavior);
238     return stream.detachAsData();
239 }
240 
MakeDeserialize(SkStream * stream,sk_sp<SkFontMgr> lastResortMgr)241 sk_sp<SkTypeface> SkTypeface::MakeDeserialize(SkStream* stream, sk_sp<SkFontMgr> lastResortMgr) {
242     SkFontDescriptor desc;
243     if (!SkFontDescriptor::Deserialize(stream, &desc)) {
244         return nullptr;
245     }
246 
247     if (desc.hasStream()) {
248         for (const DecoderProc& proc : *decoders()) {
249             if (proc.id == desc.getFactoryId()) {
250                 return proc.makeFromStream(desc.detachStream(), desc.getFontArguments());
251             }
252         }
253 
254         [[maybe_unused]] FactoryId id = desc.getFactoryId();
255         SkDEBUGF("Could not find factory %c%c%c%c for %s.\n",
256                  (char)((id >> 24) & 0xFF),
257                  (char)((id >> 16) & 0xFF),
258                  (char)((id >> 8) & 0xFF),
259                  (char)((id >> 0) & 0xFF),
260                  desc.getFamilyName());
261 
262         if (lastResortMgr) {
263             // If we've gotten to here, we will try desperately to find something that might match
264             // as a kind of last ditch effort to make something work (and maybe this SkFontMgr knows
265             // something about the serialization and can look up the right thing by name anyway if
266             // the user provides it).
267             // Any time it is used the user will probably get the wrong glyphs drawn (and if they're
268             // right it is totally by accident). But sometimes drawing something or getting lucky
269             // while debugging is better than drawing nothing at all.
270             sk_sp<SkTypeface> typeface = lastResortMgr->makeFromStream(desc.detachStream(),
271                                                                        desc.getFontArguments());
272             if (typeface) {
273                 return typeface;
274             }
275         }
276     }
277     if (lastResortMgr) {
278         return lastResortMgr->legacyMakeTypeface(desc.getFamilyName(), desc.getStyle());
279     }
280     return SkEmptyTypeface::Make();
281 }
282 
283 ///////////////////////////////////////////////////////////////////////////////
284 
glyphMaskNeedsCurrentColor() const285 bool SkTypeface::glyphMaskNeedsCurrentColor() const {
286     return this->onGlyphMaskNeedsCurrentColor();
287 }
288 
getVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const289 int SkTypeface::getVariationDesignPosition(
290         SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
291 {
292     return this->onGetVariationDesignPosition(coordinates, coordinateCount);
293 }
294 
getVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const295 int SkTypeface::getVariationDesignParameters(
296         SkFontParameters::Variation::Axis parameters[], int parameterCount) const
297 {
298     return this->onGetVariationDesignParameters(parameters, parameterCount);
299 }
300 
countTables() const301 int SkTypeface::countTables() const {
302     return this->onGetTableTags(nullptr);
303 }
304 
getTableTags(SkFontTableTag tags[]) const305 int SkTypeface::getTableTags(SkFontTableTag tags[]) const {
306     return this->onGetTableTags(tags);
307 }
308 
getTableSize(SkFontTableTag tag) const309 size_t SkTypeface::getTableSize(SkFontTableTag tag) const {
310     return this->onGetTableData(tag, 0, ~0U, nullptr);
311 }
312 
getTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const313 size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length,
314                                 void* data) const {
315     return this->onGetTableData(tag, offset, length, data);
316 }
317 
copyTableData(SkFontTableTag tag) const318 sk_sp<SkData> SkTypeface::copyTableData(SkFontTableTag tag) const {
319     return this->onCopyTableData(tag);
320 }
321 
onCopyTableData(SkFontTableTag tag) const322 sk_sp<SkData> SkTypeface::onCopyTableData(SkFontTableTag tag) const {
323     size_t size = this->getTableSize(tag);
324     if (size) {
325         sk_sp<SkData> data = SkData::MakeUninitialized(size);
326         (void)this->getTableData(tag, 0, size, data->writable_data());
327         return data;
328     }
329     return nullptr;
330 }
331 
openStream(int * ttcIndex) const332 std::unique_ptr<SkStreamAsset> SkTypeface::openStream(int* ttcIndex) const {
333     int ttcIndexStorage;
334     if (nullptr == ttcIndex) {
335         // So our subclasses don't need to check for null param
336         ttcIndex = &ttcIndexStorage;
337     }
338     return this->onOpenStream(ttcIndex);
339 }
340 
openExistingStream(int * ttcIndex) const341 std::unique_ptr<SkStreamAsset> SkTypeface::openExistingStream(int* ttcIndex) const {
342     int ttcIndexStorage;
343     if (nullptr == ttcIndex) {
344         // So our subclasses don't need to check for null param
345         ttcIndex = &ttcIndexStorage;
346     }
347     return this->onOpenExistingStream(ttcIndex);
348 }
349 
createScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const350 std::unique_ptr<SkScalerContext> SkTypeface::createScalerContext(
351         const SkScalerContextEffects& effects, const SkDescriptor* desc) const {
352     std::unique_ptr<SkScalerContext> scalerContext = this->onCreateScalerContext(effects, desc);
353     SkASSERT(scalerContext);
354     return scalerContext;
355 }
356 
onCreateScalerContextAsProxyTypeface(const SkScalerContextEffects &,const SkDescriptor *,sk_sp<SkTypeface>) const357 std::unique_ptr<SkScalerContext> SkTypeface::onCreateScalerContextAsProxyTypeface
358         (const SkScalerContextEffects&,
359          const SkDescriptor*,
360          sk_sp<SkTypeface>) const {
361     SK_ABORT("Not implemented.");
362 }
363 
unicharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const364 void SkTypeface::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
365     if (count > 0 && glyphs && uni) {
366         this->onCharsToGlyphs(uni, count, glyphs);
367     }
368 }
369 
unicharToGlyph(SkUnichar uni) const370 SkGlyphID SkTypeface::unicharToGlyph(SkUnichar uni) const {
371     SkGlyphID glyphs[1] = { 0 };
372     this->onCharsToGlyphs(&uni, 1, glyphs);
373     return glyphs[0];
374 }
375 
376 namespace {
377 class SkConvertToUTF32 {
378 public:
SkConvertToUTF32()379     SkConvertToUTF32() {}
380 
convert(const void * text,size_t byteLength,SkTextEncoding encoding)381     const SkUnichar* convert(const void* text, size_t byteLength, SkTextEncoding encoding) {
382         const SkUnichar* uni;
383         switch (encoding) {
384             case SkTextEncoding::kUTF8: {
385                 uni = fStorage.reset(byteLength);
386                 const char* ptr = (const char*)text;
387                 const char* end = ptr + byteLength;
388                 for (int i = 0; ptr < end; ++i) {
389                     fStorage[i] = SkUTF::NextUTF8(&ptr, end);
390                 }
391             } break;
392             case SkTextEncoding::kUTF16: {
393                 uni = fStorage.reset(byteLength);
394                 const uint16_t* ptr = (const uint16_t*)text;
395                 const uint16_t* end = ptr + (byteLength >> 1);
396                 for (int i = 0; ptr < end; ++i) {
397                     fStorage[i] = SkUTF::NextUTF16(&ptr, end);
398                 }
399             } break;
400             case SkTextEncoding::kUTF32:
401                 uni = (const SkUnichar*)text;
402                 break;
403             default:
404                 SK_ABORT("unexpected enum");
405         }
406         return uni;
407     }
408 
409 private:
410     AutoSTMalloc<256, SkUnichar> fStorage;
411 };
412 }
413 
textToGlyphs(const void * text,size_t byteLength,SkTextEncoding encoding,SkGlyphID glyphs[],int maxGlyphCount) const414 int SkTypeface::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
415                              SkGlyphID glyphs[], int maxGlyphCount) const {
416     if (0 == byteLength) {
417         return 0;
418     }
419 
420     SkASSERT(text);
421 
422     int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
423     if (!glyphs || count > maxGlyphCount) {
424         return count;
425     }
426 
427     if (encoding == SkTextEncoding::kGlyphID) {
428         memcpy(glyphs, text, count << 1);
429         return count;
430     }
431 
432     SkConvertToUTF32 storage;
433     const SkUnichar* uni = storage.convert(text, byteLength, encoding);
434 
435     this->unicharsToGlyphs(uni, count, glyphs);
436     return count;
437 }
438 
countGlyphs() const439 int SkTypeface::countGlyphs() const {
440     return this->onCountGlyphs();
441 }
442 
getUnitsPerEm() const443 int SkTypeface::getUnitsPerEm() const {
444     // should we try to cache this in the base-class?
445     return this->onGetUPEM();
446 }
447 
getKerningPairAdjustments(const uint16_t glyphs[],int count,int32_t adjustments[]) const448 bool SkTypeface::getKerningPairAdjustments(const uint16_t glyphs[], int count,
449                                            int32_t adjustments[]) const {
450     SkASSERT(count >= 0);
451     // check for the only legal way to pass a nullptr.. everything is 0
452     // in which case they just want to know if this face can possibly support
453     // kerning (true) or never (false).
454     if (nullptr == glyphs || nullptr == adjustments) {
455         SkASSERT(nullptr == glyphs);
456         SkASSERT(0 == count);
457         SkASSERT(nullptr == adjustments);
458     }
459     return this->onGetKerningPairAdjustments(glyphs, count, adjustments);
460 }
461 
createFamilyNameIterator() const462 SkTypeface::LocalizedStrings* SkTypeface::createFamilyNameIterator() const {
463     return this->onCreateFamilyNameIterator();
464 }
465 
getFamilyName(SkString * name) const466 void SkTypeface::getFamilyName(SkString* name) const {
467     SkASSERT(name);
468     this->onGetFamilyName(name);
469 }
470 
getPostScriptName(SkString * name) const471 bool SkTypeface::getPostScriptName(SkString* name) const {
472     return this->onGetPostScriptName(name);
473 }
474 
getResourceName(SkString * resourceName) const475 int SkTypeface::getResourceName(SkString* resourceName) const {
476     return this->onGetResourceName(resourceName);
477 }
478 
onGetResourceName(SkString * resourceName) const479 int SkTypeface::onGetResourceName(SkString* resourceName) const {
480     return 0;
481 }
482 
fontStyle() const483 SkFontStyle SkTypeface::fontStyle() const {
484     return this->onGetFontStyle();
485 }
486 
onGetFontStyle() const487 SkFontStyle SkTypeface::onGetFontStyle() const {
488     return fStyle;
489 }
490 
isBold() const491 bool SkTypeface::isBold() const {
492     return this->onGetFontStyle().weight() >= SkFontStyle::kSemiBold_Weight;
493 }
494 
isItalic() const495 bool SkTypeface::isItalic() const {
496     return this->onGetFontStyle().slant() != SkFontStyle::kUpright_Slant;
497 }
498 
isFixedPitch() const499 bool SkTypeface::isFixedPitch() const {
500     return this->onGetFixedPitch();
501 }
502 
onGetFixedPitch() const503 bool SkTypeface::onGetFixedPitch() const {
504     return fIsFixedPitch;
505 }
506 
getGlyphToUnicodeMap(SkUnichar * dst) const507 void SkTypeface::getGlyphToUnicodeMap(SkUnichar* dst) const {
508     sk_bzero(dst, sizeof(SkUnichar) * this->countGlyphs());
509 }
510 
getAdvancedMetrics() const511 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface::getAdvancedMetrics() const {
512     std::unique_ptr<SkAdvancedTypefaceMetrics> result = this->onGetAdvancedMetrics();
513     if (result && result->fPostScriptName.isEmpty()) {
514         if (!this->getPostScriptName(&result->fPostScriptName)) {
515             this->getFamilyName(&result->fPostScriptName);
516         }
517     }
518     if (result && (result->fType == SkAdvancedTypefaceMetrics::kTrueType_Font ||
519                    result->fType == SkAdvancedTypefaceMetrics::kCFF_Font)) {
520         SkOTTableOS2::Version::V2::Type::Field fsType;
521         constexpr SkFontTableTag os2Tag = SkTEndian_SwapBE32(SkOTTableOS2::TAG);
522         constexpr size_t fsTypeOffset = offsetof(SkOTTableOS2::Version::V2, fsType);
523         if (this->getTableData(os2Tag, fsTypeOffset, sizeof(fsType), &fsType) == sizeof(fsType)) {
524             if (fsType.Bitmap || (fsType.Restricted && !(fsType.PreviewPrint || fsType.Editable))) {
525                 result->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag;
526             }
527             if (fsType.NoSubsetting) {
528                 result->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag;
529             }
530         }
531     }
532     return result;
533 }
534 
onGetKerningPairAdjustments(const uint16_t glyphs[],int count,int32_t adjustments[]) const535 bool SkTypeface::onGetKerningPairAdjustments(const uint16_t glyphs[], int count,
536                                              int32_t adjustments[]) const {
537     return false;
538 }
539 
onOpenExistingStream(int * ttcIndex) const540 std::unique_ptr<SkStreamAsset> SkTypeface::onOpenExistingStream(int* ttcIndex) const {
541     return this->onOpenStream(ttcIndex);
542 }
543 
544 ///////////////////////////////////////////////////////////////////////////////
545 
getBounds() const546 SkRect SkTypeface::getBounds() const {
547     fBoundsOnce([this] {
548         if (!this->onComputeBounds(&fBounds)) {
549             fBounds.setEmpty();
550         }
551     });
552     return fBounds;
553 }
554 
onComputeBounds(SkRect * bounds) const555 bool SkTypeface::onComputeBounds(SkRect* bounds) const {
556     // we use a big size to ensure lots of significant bits from the scalercontext.
557     // then we scale back down to return our final answer (at 1-pt)
558     const SkScalar textSize = 2048;
559     const SkScalar invTextSize = 1 / textSize;
560 
561     SkFont font;
562     font.setTypeface(sk_ref_sp(const_cast<SkTypeface*>(this)));
563     font.setSize(textSize);
564     font.setLinearMetrics(true);
565 
566     SkScalerContextRec rec;
567     SkScalerContextEffects effects;
568 
569     SkScalerContext::MakeRecAndEffectsFromFont(font, &rec, &effects);
570 
571     SkAutoDescriptor ad;
572     SkScalerContextEffects noeffects;
573     SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, noeffects, &ad);
574 
575     std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc());
576 
577     SkFontMetrics fm;
578     ctx->getFontMetrics(&fm);
579     if (!fm.hasBounds()) {
580         return false;
581     }
582     bounds->setLTRB(fm.fXMin * invTextSize, fm.fTop * invTextSize,
583                     fm.fXMax * invTextSize, fm.fBottom * invTextSize);
584     return true;
585 }
586