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