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