• 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(
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 
unicharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const357 void SkTypeface::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
358     if (count > 0 && glyphs && uni) {
359         this->onCharsToGlyphs(uni, count, glyphs);
360     }
361 }
362 
unicharToGlyph(SkUnichar uni) const363 SkGlyphID SkTypeface::unicharToGlyph(SkUnichar uni) const {
364     SkGlyphID glyphs[1] = { 0 };
365     this->onCharsToGlyphs(&uni, 1, glyphs);
366     return glyphs[0];
367 }
368 
369 namespace {
370 class SkConvertToUTF32 {
371 public:
SkConvertToUTF32()372     SkConvertToUTF32() {}
373 
convert(const void * text,size_t byteLength,SkTextEncoding encoding)374     const SkUnichar* convert(const void* text, size_t byteLength, SkTextEncoding encoding) {
375         const SkUnichar* uni;
376         switch (encoding) {
377             case SkTextEncoding::kUTF8: {
378                 uni = fStorage.reset(byteLength);
379                 const char* ptr = (const char*)text;
380                 const char* end = ptr + byteLength;
381                 for (int i = 0; ptr < end; ++i) {
382                     fStorage[i] = SkUTF::NextUTF8(&ptr, end);
383                 }
384             } break;
385             case SkTextEncoding::kUTF16: {
386                 uni = fStorage.reset(byteLength);
387                 const uint16_t* ptr = (const uint16_t*)text;
388                 const uint16_t* end = ptr + (byteLength >> 1);
389                 for (int i = 0; ptr < end; ++i) {
390                     fStorage[i] = SkUTF::NextUTF16(&ptr, end);
391                 }
392             } break;
393             case SkTextEncoding::kUTF32:
394                 uni = (const SkUnichar*)text;
395                 break;
396             default:
397                 SK_ABORT("unexpected enum");
398         }
399         return uni;
400     }
401 
402 private:
403     AutoSTMalloc<256, SkUnichar> fStorage;
404 };
405 }
406 
textToGlyphs(const void * text,size_t byteLength,SkTextEncoding encoding,SkGlyphID glyphs[],int maxGlyphCount) const407 int SkTypeface::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
408                              SkGlyphID glyphs[], int maxGlyphCount) const {
409     if (0 == byteLength) {
410         return 0;
411     }
412 
413     SkASSERT(text);
414 
415     int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
416     if (!glyphs || count > maxGlyphCount) {
417         return count;
418     }
419 
420     if (encoding == SkTextEncoding::kGlyphID) {
421         memcpy(glyphs, text, count << 1);
422         return count;
423     }
424 
425     SkConvertToUTF32 storage;
426     const SkUnichar* uni = storage.convert(text, byteLength, encoding);
427 
428     this->unicharsToGlyphs(uni, count, glyphs);
429     return count;
430 }
431 
countGlyphs() const432 int SkTypeface::countGlyphs() const {
433     return this->onCountGlyphs();
434 }
435 
getUnitsPerEm() const436 int SkTypeface::getUnitsPerEm() const {
437     // should we try to cache this in the base-class?
438     return this->onGetUPEM();
439 }
440 
getKerningPairAdjustments(const uint16_t glyphs[],int count,int32_t adjustments[]) const441 bool SkTypeface::getKerningPairAdjustments(const uint16_t glyphs[], int count,
442                                            int32_t adjustments[]) const {
443     SkASSERT(count >= 0);
444     // check for the only legal way to pass a nullptr.. everything is 0
445     // in which case they just want to know if this face can possibly support
446     // kerning (true) or never (false).
447     if (nullptr == glyphs || nullptr == adjustments) {
448         SkASSERT(nullptr == glyphs);
449         SkASSERT(0 == count);
450         SkASSERT(nullptr == adjustments);
451     }
452     return this->onGetKerningPairAdjustments(glyphs, count, adjustments);
453 }
454 
createFamilyNameIterator() const455 SkTypeface::LocalizedStrings* SkTypeface::createFamilyNameIterator() const {
456     return this->onCreateFamilyNameIterator();
457 }
458 
getFamilyName(SkString * name) const459 void SkTypeface::getFamilyName(SkString* name) const {
460     SkASSERT(name);
461     this->onGetFamilyName(name);
462 }
463 
getPostScriptName(SkString * name) const464 bool SkTypeface::getPostScriptName(SkString* name) const {
465     return this->onGetPostScriptName(name);
466 }
467 
getGlyphToUnicodeMap(SkUnichar * dst) const468 void SkTypeface::getGlyphToUnicodeMap(SkUnichar* dst) const {
469     sk_bzero(dst, sizeof(SkUnichar) * this->countGlyphs());
470 }
471 
getAdvancedMetrics() const472 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface::getAdvancedMetrics() const {
473     std::unique_ptr<SkAdvancedTypefaceMetrics> result = this->onGetAdvancedMetrics();
474     if (result && result->fPostScriptName.isEmpty()) {
475         if (!this->getPostScriptName(&result->fPostScriptName)) {
476             this->getFamilyName(&result->fPostScriptName);
477         }
478     }
479     if (result && (result->fType == SkAdvancedTypefaceMetrics::kTrueType_Font ||
480                    result->fType == SkAdvancedTypefaceMetrics::kCFF_Font)) {
481         SkOTTableOS2::Version::V2::Type::Field fsType;
482         constexpr SkFontTableTag os2Tag = SkTEndian_SwapBE32(SkOTTableOS2::TAG);
483         constexpr size_t fsTypeOffset = offsetof(SkOTTableOS2::Version::V2, fsType);
484         if (this->getTableData(os2Tag, fsTypeOffset, sizeof(fsType), &fsType) == sizeof(fsType)) {
485             if (fsType.Bitmap || (fsType.Restricted && !(fsType.PreviewPrint || fsType.Editable))) {
486                 result->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag;
487             }
488             if (fsType.NoSubsetting) {
489                 result->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag;
490             }
491         }
492     }
493     return result;
494 }
495 
onGetKerningPairAdjustments(const uint16_t glyphs[],int count,int32_t adjustments[]) const496 bool SkTypeface::onGetKerningPairAdjustments(const uint16_t glyphs[], int count,
497                                              int32_t adjustments[]) const {
498     return false;
499 }
500 
onOpenExistingStream(int * ttcIndex) const501 std::unique_ptr<SkStreamAsset> SkTypeface::onOpenExistingStream(int* ttcIndex) const {
502     return this->onOpenStream(ttcIndex);
503 }
504 
505 ///////////////////////////////////////////////////////////////////////////////
506 
getBounds() const507 SkRect SkTypeface::getBounds() const {
508     fBoundsOnce([this] {
509         if (!this->onComputeBounds(&fBounds)) {
510             fBounds.setEmpty();
511         }
512     });
513     return fBounds;
514 }
515 
onComputeBounds(SkRect * bounds) const516 bool SkTypeface::onComputeBounds(SkRect* bounds) const {
517     // we use a big size to ensure lots of significant bits from the scalercontext.
518     // then we scale back down to return our final answer (at 1-pt)
519     const SkScalar textSize = 2048;
520     const SkScalar invTextSize = 1 / textSize;
521 
522     SkFont font;
523     font.setTypeface(sk_ref_sp(const_cast<SkTypeface*>(this)));
524     font.setSize(textSize);
525     font.setLinearMetrics(true);
526 
527     SkScalerContextRec rec;
528     SkScalerContextEffects effects;
529 
530     SkScalerContext::MakeRecAndEffectsFromFont(font, &rec, &effects);
531 
532     SkAutoDescriptor ad;
533     SkScalerContextEffects noeffects;
534     SkScalerContext::AutoDescriptorGivenRecAndEffects(rec, noeffects, &ad);
535 
536     std::unique_ptr<SkScalerContext> ctx = this->createScalerContext(noeffects, ad.getDesc());
537 
538     SkFontMetrics fm;
539     ctx->getFontMetrics(&fm);
540     if (!fm.hasBounds()) {
541         return false;
542     }
543     bounds->setLTRB(fm.fXMin * invTextSize, fm.fTop * invTextSize,
544                     fm.fXMax * invTextSize, fm.fBottom * invTextSize);
545     return true;
546 }
547