• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(*const_cast<SkEmptyTypeface*>(this), effects, desc);
92     }
onFilterRec(SkScalerContextRec *) const93     void onFilterRec(SkScalerContextRec*) const override { }
onGetAdvancedMetrics() const94     std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
95         return nullptr;
96     }
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const97     void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
98         desc->setFactoryId(FactoryId);
99         *serialize = false;
100     }
onCharsToGlyphs(const SkUnichar * chars,int count,SkGlyphID glyphs[]) const101     void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override {
102         sk_bzero(glyphs, count * sizeof(glyphs[0]));
103     }
onCountGlyphs() const104     int onCountGlyphs() const override { return 0; }
getPostScriptGlyphNames(SkString *) const105     void getPostScriptGlyphNames(SkString*) const override {}
getGlyphToUnicodeMap(SkUnichar *) const106     void getGlyphToUnicodeMap(SkUnichar*) const override {}
onGetUPEM() const107     int onGetUPEM() const override { return 0; }
onComputeBounds(SkRect * bounds) const108     bool onComputeBounds(SkRect* bounds) const override { return false; }
109 
110     class EmptyLocalizedStrings : public SkTypeface::LocalizedStrings {
111     public:
next(SkTypeface::LocalizedString *)112         bool next(SkTypeface::LocalizedString*) override { return false; }
113     };
onGetFamilyName(SkString * familyName) const114     void onGetFamilyName(SkString* familyName) const override {
115         familyName->reset();
116     }
onGetPostScriptName(SkString *) const117     bool onGetPostScriptName(SkString*) const override {
118         return false;
119     }
onCreateFamilyNameIterator() const120     SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override {
121         return new EmptyLocalizedStrings;
122     }
onGlyphMaskNeedsCurrentColor() const123     bool onGlyphMaskNeedsCurrentColor() const override {
124         return false;
125     }
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const126     int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
127                                      int coordinateCount) const override
128     {
129         return 0;
130     }
onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const131     int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
132                                        int parameterCount) const override
133     {
134         return 0;
135     }
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 {
138         return 0;
139     }
140 };
141 
142 }  // namespace
143 
MakeEmpty()144 sk_sp<SkTypeface> SkTypeface::MakeEmpty() {
145     return SkEmptyTypeface::Make();
146 }
147 
Equal(const SkTypeface * facea,const SkTypeface * faceb)148 bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) {
149     if (facea == faceb) {
150         return true;
151     }
152     if (!facea || !faceb) {
153         return false;
154     }
155     return facea->uniqueID() == faceb->uniqueID();
156 }
157 
158 ///////////////////////////////////////////////////////////////////////////////
159 
160 namespace {
161 
162     struct DecoderProc {
163         SkFourByteTag id;
164         sk_sp<SkTypeface> (*makeFromStream)(std::unique_ptr<SkStreamAsset>, const SkFontArguments&);
165     };
166 
decoders()167     std::vector<DecoderProc>* decoders() {
168         static SkNoDestructor<std::vector<DecoderProc>> decoders{{
169             { SkEmptyTypeface::FactoryId, SkEmptyTypeface::MakeFromStream },
170             { SkCustomTypefaceBuilder::FactoryId, SkCustomTypefaceBuilder::MakeFromStream },
171 #ifdef SK_TYPEFACE_FACTORY_CORETEXT
172             { SkTypeface_Mac::FactoryId, SkTypeface_Mac::MakeFromStream },
173 #endif
174 #ifdef SK_TYPEFACE_FACTORY_DIRECTWRITE
175             { DWriteFontTypeface::FactoryId, DWriteFontTypeface::MakeFromStream },
176 #endif
177 #ifdef SK_TYPEFACE_FACTORY_FREETYPE
178             { SkTypeface_FreeType::FactoryId, SkTypeface_FreeType::MakeFromStream },
179 #endif
180 #ifdef SK_TYPEFACE_FACTORY_FONTATIONS
181             { SkTypeface_Fontations::FactoryId, SkTypeface_Fontations::MakeFromStream },
182 #endif
183         }};
184         return decoders.get();
185     }
186 
187 }  // namespace
188 
makeClone(const SkFontArguments & args) const189 sk_sp<SkTypeface> SkTypeface::makeClone(const SkFontArguments& args) const {
190     return this->onMakeClone(args);
191 }
192 
193 ///////////////////////////////////////////////////////////////////////////////
194 
Register(FactoryId id,sk_sp<SkTypeface> (* make)(std::unique_ptr<SkStreamAsset>,const SkFontArguments &))195 void SkTypeface::Register(
196             FactoryId id,
197             sk_sp<SkTypeface> (*make)(std::unique_ptr<SkStreamAsset>, const SkFontArguments&)) {
198     decoders()->push_back(DecoderProc{id, make});
199 }
200 
serialize(SkWStream * wstream,SerializeBehavior behavior) const201 void SkTypeface::serialize(SkWStream* wstream, SerializeBehavior behavior) const {
202     bool isLocalData = false;
203     SkFontDescriptor desc;
204     this->onGetFontDescriptor(&desc, &isLocalData);
205     if (desc.getFactoryId() == 0) {
206         SkDEBUGF("Factory was not set for %s.\n", desc.getFamilyName());
207     }
208 
209     bool shouldSerializeData = false;
210     switch (behavior) {
211         case SerializeBehavior::kDoIncludeData:      shouldSerializeData = true;        break;
212         case SerializeBehavior::kDontIncludeData:    shouldSerializeData = false;       break;
213         case SerializeBehavior::kIncludeDataIfLocal: shouldSerializeData = isLocalData; break;
214     }
215 
216     if (shouldSerializeData) {
217         int index;
218         desc.setStream(this->openStream(&index));
219         if (desc.hasStream()) {
220             desc.setCollectionIndex(index);
221         }
222 
223         int numAxes = this->getVariationDesignPosition(nullptr, 0);
224         if (0 < numAxes) {
225             numAxes = this->getVariationDesignPosition(desc.setVariationCoordinates(numAxes), numAxes);
226             if (numAxes <= 0) {
227                 desc.setVariationCoordinates(0);
228             }
229         }
230     }
231     desc.serialize(wstream);
232 }
233 
serialize(SerializeBehavior behavior) const234 sk_sp<SkData> SkTypeface::serialize(SerializeBehavior behavior) const {
235     SkDynamicMemoryWStream stream;
236     this->serialize(&stream, behavior);
237     return stream.detachAsData();
238 }
239 
MakeDeserialize(SkStream * stream,sk_sp<SkFontMgr> lastResortMgr)240 sk_sp<SkTypeface> SkTypeface::MakeDeserialize(SkStream* stream, sk_sp<SkFontMgr> lastResortMgr) {
241     SkFontDescriptor desc;
242     if (!SkFontDescriptor::Deserialize(stream, &desc)) {
243         return nullptr;
244     }
245 
246     if (desc.hasStream()) {
247         for (const DecoderProc& proc : *decoders()) {
248             if (proc.id == desc.getFactoryId()) {
249                 return proc.makeFromStream(desc.detachStream(), desc.getFontArguments());
250             }
251         }
252 
253         [[maybe_unused]] FactoryId id = desc.getFactoryId();
254         SkDEBUGF("Could not find factory %c%c%c%c for %s.\n",
255                  (char)((id >> 24) & 0xFF),
256                  (char)((id >> 16) & 0xFF),
257                  (char)((id >> 8) & 0xFF),
258                  (char)((id >> 0) & 0xFF),
259                  desc.getFamilyName());
260 
261         if (lastResortMgr) {
262             // If we've gotten to here, we will try desperately to find something that might match
263             // as a kind of last ditch effort to make something work (and maybe this SkFontMgr knows
264             // something about the serialization and can look up the right thing by name anyway if
265             // the user provides it).
266             // Any time it is used the user will probably get the wrong glyphs drawn (and if they're
267             // right it is totally by accident). But sometimes drawing something or getting lucky
268             // while debugging is better than drawing nothing at all.
269             sk_sp<SkTypeface> typeface = lastResortMgr->makeFromStream(desc.detachStream(),
270                                                                        desc.getFontArguments());
271             if (typeface) {
272                 return typeface;
273             }
274         }
275     }
276     if (lastResortMgr) {
277         return lastResortMgr->legacyMakeTypeface(desc.getFamilyName(), desc.getStyle());
278     }
279     return SkEmptyTypeface::Make();
280 }
281 
282 ///////////////////////////////////////////////////////////////////////////////
283 
glyphMaskNeedsCurrentColor() const284 bool SkTypeface::glyphMaskNeedsCurrentColor() const {
285     return this->onGlyphMaskNeedsCurrentColor();
286 }
287 
getVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const288 int SkTypeface::getVariationDesignPosition(
289         SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
290 {
291     return this->onGetVariationDesignPosition(coordinates, coordinateCount);
292 }
293 
getVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const294 int SkTypeface::getVariationDesignParameters(
295         SkFontParameters::Variation::Axis parameters[], int parameterCount) const
296 {
297     return this->onGetVariationDesignParameters(parameters, parameterCount);
298 }
299 
countTables() const300 int SkTypeface::countTables() const {
301     return this->onGetTableTags(nullptr);
302 }
303 
getTableTags(SkFontTableTag tags[]) const304 int SkTypeface::getTableTags(SkFontTableTag tags[]) const {
305     return this->onGetTableTags(tags);
306 }
307 
getTableSize(SkFontTableTag tag) const308 size_t SkTypeface::getTableSize(SkFontTableTag tag) const {
309     return this->onGetTableData(tag, 0, ~0U, nullptr);
310 }
311 
getTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const312 size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length,
313                                 void* data) const {
314     return this->onGetTableData(tag, offset, length, data);
315 }
316 
copyTableData(SkFontTableTag tag) const317 sk_sp<SkData> SkTypeface::copyTableData(SkFontTableTag tag) const {
318     return this->onCopyTableData(tag);
319 }
320 
onCopyTableData(SkFontTableTag tag) const321 sk_sp<SkData> SkTypeface::onCopyTableData(SkFontTableTag tag) const {
322     size_t size = this->getTableSize(tag);
323     if (size) {
324         sk_sp<SkData> data = SkData::MakeUninitialized(size);
325         (void)this->getTableData(tag, 0, size, data->writable_data());
326         return data;
327     }
328     return nullptr;
329 }
330 
openStream(int * ttcIndex) const331 std::unique_ptr<SkStreamAsset> SkTypeface::openStream(int* ttcIndex) const {
332     int ttcIndexStorage;
333     if (nullptr == ttcIndex) {
334         // So our subclasses don't need to check for null param
335         ttcIndex = &ttcIndexStorage;
336     }
337     return this->onOpenStream(ttcIndex);
338 }
339 
openExistingStream(int * ttcIndex) const340 std::unique_ptr<SkStreamAsset> SkTypeface::openExistingStream(int* ttcIndex) const {
341     int ttcIndexStorage;
342     if (nullptr == ttcIndex) {
343         // So our subclasses don't need to check for null param
344         ttcIndex = &ttcIndexStorage;
345     }
346     return this->onOpenExistingStream(ttcIndex);
347 }
348 
createScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const349 std::unique_ptr<SkScalerContext> SkTypeface::createScalerContext(
350         const SkScalerContextEffects& effects, const SkDescriptor* desc) const {
351     std::unique_ptr<SkScalerContext> scalerContext = this->onCreateScalerContext(effects, desc);
352     SkASSERT(scalerContext);
353     return scalerContext;
354 }
355 
onCreateScalerContextAsProxyTypeface(const SkScalerContextEffects &,const SkDescriptor *,SkTypeface *) const356 std::unique_ptr<SkScalerContext> SkTypeface::onCreateScalerContextAsProxyTypeface
357         (const SkScalerContextEffects&,
358          const SkDescriptor*,
359          SkTypeface*) const {
360     SK_ABORT("Not implemented.");
361 }
362 
unicharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const363 void SkTypeface::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
364     if (count > 0 && glyphs && uni) {
365         this->onCharsToGlyphs(uni, count, glyphs);
366     }
367 }
368 
unicharToGlyph(SkUnichar uni) const369 SkGlyphID SkTypeface::unicharToGlyph(SkUnichar uni) const {
370     SkGlyphID glyphs[1] = { 0 };
371     this->onCharsToGlyphs(&uni, 1, glyphs);
372     return glyphs[0];
373 }
374 
375 namespace {
376 class SkConvertToUTF32 {
377 public:
SkConvertToUTF32()378     SkConvertToUTF32() {}
379 
convert(const void * text,size_t byteLength,SkTextEncoding encoding)380     const SkUnichar* convert(const void* text, size_t byteLength, SkTextEncoding encoding) {
381         const SkUnichar* uni;
382         switch (encoding) {
383             case SkTextEncoding::kUTF8: {
384                 uni = fStorage.reset(byteLength);
385                 const char* ptr = (const char*)text;
386                 const char* end = ptr + byteLength;
387                 for (int i = 0; ptr < end; ++i) {
388                     fStorage[i] = SkUTF::NextUTF8(&ptr, end);
389                 }
390             } break;
391             case SkTextEncoding::kUTF16: {
392                 uni = fStorage.reset(byteLength);
393                 const uint16_t* ptr = (const uint16_t*)text;
394                 const uint16_t* end = ptr + (byteLength >> 1);
395                 for (int i = 0; ptr < end; ++i) {
396                     fStorage[i] = SkUTF::NextUTF16(&ptr, end);
397                 }
398             } break;
399             case SkTextEncoding::kUTF32:
400                 uni = (const SkUnichar*)text;
401                 break;
402             default:
403                 SK_ABORT("unexpected enum");
404         }
405         return uni;
406     }
407 
408 private:
409     AutoSTMalloc<256, SkUnichar> fStorage;
410 };
411 }
412 
textToGlyphs(const void * text,size_t byteLength,SkTextEncoding encoding,SkGlyphID glyphs[],int maxGlyphCount) const413 int SkTypeface::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
414                              SkGlyphID glyphs[], int maxGlyphCount) const {
415     if (0 == byteLength) {
416         return 0;
417     }
418 
419     SkASSERT(text);
420 
421     int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
422     if (!glyphs || count > maxGlyphCount) {
423         return count;
424     }
425 
426     if (encoding == SkTextEncoding::kGlyphID) {
427         memcpy(glyphs, text, count << 1);
428         return count;
429     }
430 
431     SkConvertToUTF32 storage;
432     const SkUnichar* uni = storage.convert(text, byteLength, encoding);
433 
434     this->unicharsToGlyphs(uni, count, glyphs);
435     return count;
436 }
437 
countGlyphs() const438 int SkTypeface::countGlyphs() const {
439     return this->onCountGlyphs();
440 }
441 
getUnitsPerEm() const442 int SkTypeface::getUnitsPerEm() const {
443     // should we try to cache this in the base-class?
444     return this->onGetUPEM();
445 }
446 
getKerningPairAdjustments(const SkGlyphID glyphs[],int count,int32_t adjustments[]) const447 bool SkTypeface::getKerningPairAdjustments(const SkGlyphID glyphs[], int count,
448                                            int32_t adjustments[]) const {
449     SkASSERT(count >= 0);
450     // check for the only legal way to pass a nullptr.. everything is 0
451     // in which case they just want to know if this face can possibly support
452     // kerning (true) or never (false).
453     if (nullptr == glyphs || nullptr == adjustments) {
454         SkASSERT(nullptr == glyphs);
455         SkASSERT(0 == count);
456         SkASSERT(nullptr == adjustments);
457     }
458     return this->onGetKerningPairAdjustments(glyphs, count, adjustments);
459 }
460 
createFamilyNameIterator() const461 SkTypeface::LocalizedStrings* SkTypeface::createFamilyNameIterator() const {
462     return this->onCreateFamilyNameIterator();
463 }
464 
getFamilyName(SkString * name) const465 void SkTypeface::getFamilyName(SkString* name) const {
466     SkASSERT(name);
467     this->onGetFamilyName(name);
468 }
469 
getPostScriptName(SkString * name) const470 bool SkTypeface::getPostScriptName(SkString* name) const {
471     return this->onGetPostScriptName(name);
472 }
473 
getResourceName(SkString * resourceName) const474 int SkTypeface::getResourceName(SkString* resourceName) const {
475     return this->onGetResourceName(resourceName);
476 }
477 
onGetResourceName(SkString * resourceName) const478 int SkTypeface::onGetResourceName(SkString* resourceName) const {
479     return 0;
480 }
481 
fontStyle() const482 SkFontStyle SkTypeface::fontStyle() const {
483     return this->onGetFontStyle();
484 }
485 
onGetFontStyle() const486 SkFontStyle SkTypeface::onGetFontStyle() const {
487     return fStyle;
488 }
489 
isBold() const490 bool SkTypeface::isBold() const {
491     return this->onGetFontStyle().weight() >= SkFontStyle::kSemiBold_Weight;
492 }
493 
isItalic() const494 bool SkTypeface::isItalic() const {
495     return this->onGetFontStyle().slant() != SkFontStyle::kUpright_Slant;
496 }
497 
isFixedPitch() const498 bool SkTypeface::isFixedPitch() const {
499     return this->onGetFixedPitch();
500 }
501 
onGetFixedPitch() const502 bool SkTypeface::onGetFixedPitch() const {
503     return fIsFixedPitch;
504 }
505 
getGlyphToUnicodeMap(SkUnichar * dst) const506 void SkTypeface::getGlyphToUnicodeMap(SkUnichar* dst) const {
507     sk_bzero(dst, sizeof(SkUnichar) * this->countGlyphs());
508 }
509 
getAdvancedMetrics() const510 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface::getAdvancedMetrics() const {
511     std::unique_ptr<SkAdvancedTypefaceMetrics> result = this->onGetAdvancedMetrics();
512     if (result && result->fPostScriptName.isEmpty()) {
513         if (!this->getPostScriptName(&result->fPostScriptName)) {
514             this->getFamilyName(&result->fPostScriptName);
515         }
516     }
517     if (result && (result->fType == SkAdvancedTypefaceMetrics::kTrueType_Font ||
518                    result->fType == SkAdvancedTypefaceMetrics::kCFF_Font)) {
519         SkOTTableOS2::Version::V2::Type::Field fsType;
520         constexpr SkFontTableTag os2Tag = SkTEndian_SwapBE32(SkOTTableOS2::TAG);
521         constexpr size_t fsTypeOffset = offsetof(SkOTTableOS2::Version::V2, fsType);
522         if (this->getTableData(os2Tag, fsTypeOffset, sizeof(fsType), &fsType) == sizeof(fsType)) {
523             if (fsType.Bitmap || (fsType.Restricted && !(fsType.PreviewPrint || fsType.Editable))) {
524                 result->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag;
525             }
526             if (fsType.NoSubsetting) {
527                 result->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag;
528             }
529         }
530     }
531     return result;
532 }
533 
onGetKerningPairAdjustments(const SkGlyphID glyphs[],int count,int32_t adjustments[]) const534 bool SkTypeface::onGetKerningPairAdjustments(const SkGlyphID glyphs[], int count,
535                                              int32_t adjustments[]) const {
536     return false;
537 }
538 
onOpenExistingStream(int * ttcIndex) const539 std::unique_ptr<SkStreamAsset> SkTypeface::onOpenExistingStream(int* ttcIndex) const {
540     return this->onOpenStream(ttcIndex);
541 }
542 
543 ///////////////////////////////////////////////////////////////////////////////
544 
getBounds() const545 SkRect SkTypeface::getBounds() const {
546     fBoundsOnce([this] {
547         if (!this->onComputeBounds(&fBounds)) {
548             fBounds.setEmpty();
549         }
550     });
551     return fBounds;
552 }
553 
onComputeBounds(SkRect * bounds) const554 bool SkTypeface::onComputeBounds(SkRect* bounds) const {
555     // we use a big size to ensure lots of significant bits from the scalercontext.
556     // then we scale back down to return our final answer (at 1-pt)
557     const SkScalar textSize = 2048;
558     const SkScalar invTextSize = 1 / textSize;
559 
560     SkFont font;
561     font.setTypeface(sk_ref_sp(const_cast<SkTypeface*>(this)));
562     font.setSize(textSize);
563     font.setLinearMetrics(true);
564 
565     SkScalerContextRec rec;
566     SkScalerContextEffects effects;
567 
568     SkScalerContext::MakeRecAndEffectsFromFont(font, &rec, &effects);
569 
570     SkAutoDescriptor ad;
571     SkScalerContextEffects noeffects;
572     SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, noeffects, &ad);
573 
574     std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc());
575 
576     SkFontMetrics fm;
577     ctx->getFontMetrics(&fm);
578     if (!fm.hasBounds()) {
579         return false;
580     }
581     bounds->setLTRB(fm.fXMin * invTextSize, fm.fTop * invTextSize,
582                     fm.fXMax * invTextSize, fm.fBottom * invTextSize);
583     return true;
584 }
585