vandebo@chromium.org | 2a22e10 | 2011-01-25 21:01:34 +0000 | [diff] [blame] | 1 | /* |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 2 | * Copyright 2011 The Android Open Source Project |
vandebo@chromium.org | 2a22e10 | 2011-01-25 21:01:34 +0000 | [diff] [blame] | 3 | * |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
vandebo@chromium.org | 2a22e10 | 2011-01-25 21:01:34 +0000 | [diff] [blame] | 6 | */ |
| 7 | |
vandebo@chromium.org | 325cb9a | 2011-03-30 18:36:29 +0000 | [diff] [blame] | 8 | #include "SkAdvancedTypefaceMetrics.h" |
vandebo | 0f9bad0 | 2014-06-19 11:05:39 -0700 | [diff] [blame] | 9 | #include "SkEndian.h" |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 10 | #include "SkFontDescriptor.h" |
bungeman | f91c47d | 2014-09-10 15:49:48 -0700 | [diff] [blame] | 11 | #include "SkFontMgr.h" |
mtklein | 1b24933 | 2015-07-07 12:21:21 -0700 | [diff] [blame] | 12 | #include "SkMutex.h" |
vandebo | 0f9bad0 | 2014-06-19 11:05:39 -0700 | [diff] [blame] | 13 | #include "SkOTTable_OS_2.h" |
mtklein | ffa4a92 | 2016-05-05 16:05:56 -0700 | [diff] [blame] | 14 | #include "SkOnce.h" |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 15 | #include "SkStream.h" |
| 16 | #include "SkTypeface.h" |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 17 | |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 18 | SkTypeface::SkTypeface(const SkFontStyle& style, SkFontID fontID, bool isFixedPitch) |
| 19 | : fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) { } |
reed@google.com | 2f3dc9d | 2011-05-02 17:33:45 +0000 | [diff] [blame] | 20 | |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 21 | SkTypeface::~SkTypeface() { } |
reed@google.com | 2f3dc9d | 2011-05-02 17:33:45 +0000 | [diff] [blame] | 22 | |
caryclark | 5ef194c | 2015-08-31 09:22:38 -0700 | [diff] [blame] | 23 | #ifdef SK_WHITELIST_SERIALIZED_TYPEFACES |
| 24 | extern void WhitelistSerializeTypeface(const SkTypeface*, SkWStream* ); |
| 25 | #define SK_TYPEFACE_DELEGATE WhitelistSerializeTypeface |
| 26 | #else |
| 27 | #define SK_TYPEFACE_DELEGATE nullptr |
| 28 | #endif |
caryclark | 83ca628 | 2015-06-10 09:31:09 -0700 | [diff] [blame] | 29 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 30 | sk_sp<SkTypeface> (*gCreateTypefaceDelegate)(const char [], SkTypeface::Style ) = nullptr; |
caryclark | 5ef194c | 2015-08-31 09:22:38 -0700 | [diff] [blame] | 31 | void (*gSerializeTypefaceDelegate)(const SkTypeface*, SkWStream* ) = SK_TYPEFACE_DELEGATE; |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 32 | sk_sp<SkTypeface> (*gDeserializeTypefaceDelegate)(SkStream* ) = nullptr; |
caryclark | 83ca628 | 2015-06-10 09:31:09 -0700 | [diff] [blame] | 33 | |
reed@google.com | 2f3dc9d | 2011-05-02 17:33:45 +0000 | [diff] [blame] | 34 | /////////////////////////////////////////////////////////////////////////////// |
| 35 | |
bungeman | a821af83 | 2016-04-14 09:44:34 -0700 | [diff] [blame] | 36 | namespace { |
| 37 | |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 38 | class SkEmptyTypeface : public SkTypeface { |
| 39 | public: |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 40 | static SkEmptyTypeface* Create() { return new SkEmptyTypeface; } |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 41 | protected: |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 42 | SkEmptyTypeface() : SkTypeface(SkFontStyle(), 0, true) { } |
commit-bot@chromium.org | c4df655 | 2014-04-07 19:34:16 +0000 | [diff] [blame] | 43 | |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 44 | SkStreamAsset* onOpenStream(int* ttcIndex) const override { return nullptr; } |
reed | a9322c2 | 2016-04-12 06:47:05 -0700 | [diff] [blame] | 45 | SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, |
| 46 | const SkDescriptor*) const override { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 47 | return nullptr; |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 48 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 49 | void onFilterRec(SkScalerContextRec*) const override { } |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 50 | virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
reed | 39a9a50 | 2015-05-12 09:50:04 -0700 | [diff] [blame] | 51 | PerGlyphInfo, |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 52 | const uint32_t*, uint32_t) const override { return nullptr; } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 53 | void onGetFontDescriptor(SkFontDescriptor*, bool*) const override { } |
bungeman@google.com | 3c996f8 | 2013-10-24 21:39:35 +0000 | [diff] [blame] | 54 | virtual int onCharsToGlyphs(const void* chars, Encoding encoding, |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 55 | uint16_t glyphs[], int glyphCount) const override { |
bungeman@google.com | 3c996f8 | 2013-10-24 21:39:35 +0000 | [diff] [blame] | 56 | if (glyphs && glyphCount > 0) { |
| 57 | sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); |
| 58 | } |
| 59 | return 0; |
| 60 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 61 | int onCountGlyphs() const override { return 0; }; |
| 62 | int onGetUPEM() const override { return 0; }; |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 63 | class EmptyLocalizedStrings : public SkTypeface::LocalizedStrings { |
| 64 | public: |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 65 | bool next(SkTypeface::LocalizedString*) override { return false; } |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 66 | }; |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 67 | void onGetFamilyName(SkString* familyName) const override { |
bungeman | b374d6a | 2014-09-17 07:48:59 -0700 | [diff] [blame] | 68 | familyName->reset(); |
| 69 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 70 | SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override { |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 71 | return new EmptyLocalizedStrings; |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 72 | }; |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 73 | int onGetTableTags(SkFontTableTag tags[]) const override { return 0; } |
| 74 | size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 75 | return 0; |
| 76 | } |
bungeman@google.com | 5c1d88d | 2013-08-21 17:20:57 +0000 | [diff] [blame] | 77 | }; |
| 78 | |
bungeman | a821af83 | 2016-04-14 09:44:34 -0700 | [diff] [blame] | 79 | } |
| 80 | |
bungeman@google.com | 18b75e5 | 2014-01-09 17:13:32 +0000 | [diff] [blame] | 81 | SkTypeface* SkTypeface::GetDefaultTypeface(Style style) { |
mtklein | ffa4a92 | 2016-05-05 16:05:56 -0700 | [diff] [blame] | 82 | static SkOnce once[4]; |
| 83 | static SkTypeface* defaults[4]; |
| 84 | |
mtklein | 78358bf | 2014-06-02 08:44:27 -0700 | [diff] [blame] | 85 | SkASSERT((int)style < 4); |
mtklein | ffa4a92 | 2016-05-05 16:05:56 -0700 | [diff] [blame] | 86 | once[style]([style] { |
mtklein | 6c59d80 | 2015-09-09 09:09:53 -0700 | [diff] [blame] | 87 | SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); |
bungeman | 11a77c6 | 2016-04-12 13:45:06 -0700 | [diff] [blame] | 88 | SkTypeface* t = fm->legacyCreateTypeface(nullptr, SkFontStyle::FromOldStyle(style)); |
mtklein | ffa4a92 | 2016-05-05 16:05:56 -0700 | [diff] [blame] | 89 | defaults[style] = t ? t : SkEmptyTypeface::Create(); |
mtklein | 6c59d80 | 2015-09-09 09:09:53 -0700 | [diff] [blame] | 90 | }); |
mtklein | ffa4a92 | 2016-05-05 16:05:56 -0700 | [diff] [blame] | 91 | return defaults[style]; |
reed@google.com | 538f784 | 2011-12-16 17:56:23 +0000 | [diff] [blame] | 92 | } |
| 93 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 94 | sk_sp<SkTypeface> SkTypeface::MakeDefault(Style style) { |
| 95 | return sk_ref_sp(GetDefaultTypeface(style)); |
reed@google.com | fed86bd | 2013-03-14 15:04:57 +0000 | [diff] [blame] | 96 | } |
| 97 | |
reed@android.com | ef772dd | 2009-03-03 21:20:49 +0000 | [diff] [blame] | 98 | uint32_t SkTypeface::UniqueID(const SkTypeface* face) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 99 | if (nullptr == face) { |
bungeman@google.com | cb1bbb3 | 2012-10-12 18:48:35 +0000 | [diff] [blame] | 100 | face = GetDefaultTypeface(); |
reed@android.com | b1d9d2e | 2009-03-04 17:37:51 +0000 | [diff] [blame] | 101 | } |
reed@google.com | 538f784 | 2011-12-16 17:56:23 +0000 | [diff] [blame] | 102 | return face->uniqueID(); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 103 | } |
| 104 | |
reed@android.com | ef772dd | 2009-03-03 21:20:49 +0000 | [diff] [blame] | 105 | bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) { |
jin.a.yang | 48fc0ea | 2015-06-17 04:47:18 -0700 | [diff] [blame] | 106 | return facea == faceb || SkTypeface::UniqueID(facea) == SkTypeface::UniqueID(faceb); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | /////////////////////////////////////////////////////////////////////////////// |
| 110 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 111 | sk_sp<SkTypeface> SkTypeface::MakeFromName(const char name[], Style style) { |
caryclark | 83ca628 | 2015-06-10 09:31:09 -0700 | [diff] [blame] | 112 | if (gCreateTypefaceDelegate) { |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 113 | sk_sp<SkTypeface> result = (*gCreateTypefaceDelegate)(name, style); |
caryclark | 83ca628 | 2015-06-10 09:31:09 -0700 | [diff] [blame] | 114 | if (result) { |
| 115 | return result; |
| 116 | } |
| 117 | } |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 118 | if (nullptr == name) { |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 119 | return MakeDefault(style); |
djsollen@google.com | 4fa748d | 2013-06-05 14:20:25 +0000 | [diff] [blame] | 120 | } |
bungeman | f91c47d | 2014-09-10 15:49:48 -0700 | [diff] [blame] | 121 | SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 122 | return sk_sp<SkTypeface>(fm->legacyCreateTypeface(name, SkFontStyle::FromOldStyle(style))); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 123 | } |
| 124 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 125 | sk_sp<SkTypeface> SkTypeface::MakeFromTypeface(SkTypeface* family, Style s) { |
bungeman | b14e4a0 | 2014-09-18 13:57:20 -0700 | [diff] [blame] | 126 | if (!family) { |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 127 | return SkTypeface::MakeDefault(s); |
bungeman | b14e4a0 | 2014-09-18 13:57:20 -0700 | [diff] [blame] | 128 | } |
| 129 | |
| 130 | if (family->style() == s) { |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 131 | return sk_ref_sp(family); |
reed@google.com | 4969044 | 2013-03-04 14:39:47 +0000 | [diff] [blame] | 132 | } |
bungeman | b14e4a0 | 2014-09-18 13:57:20 -0700 | [diff] [blame] | 133 | |
bungeman | f91c47d | 2014-09-10 15:49:48 -0700 | [diff] [blame] | 134 | SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 135 | return sk_sp<SkTypeface>(fm->matchFaceStyle(family, SkFontStyle::FromOldStyle(s))); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 136 | } |
| 137 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 138 | sk_sp<SkTypeface> SkTypeface::MakeFromStream(SkStreamAsset* stream, int index) { |
bungeman | f91c47d | 2014-09-10 15:49:48 -0700 | [diff] [blame] | 139 | SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 140 | return sk_sp<SkTypeface>(fm->createFromStream(stream, index)); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 141 | } |
| 142 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 143 | sk_sp<SkTypeface> SkTypeface::MakeFromFontData(SkFontData* data) { |
bungeman | 41868fe | 2015-05-20 09:21:04 -0700 | [diff] [blame] | 144 | SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 145 | return sk_sp<SkTypeface>(fm->createFromFontData(data)); |
bungeman | 41868fe | 2015-05-20 09:21:04 -0700 | [diff] [blame] | 146 | } |
| 147 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 148 | sk_sp<SkTypeface> SkTypeface::MakeFromFile(const char path[], int index) { |
bungeman | f91c47d | 2014-09-10 15:49:48 -0700 | [diff] [blame] | 149 | SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 150 | return sk_sp<SkTypeface>(fm->createFromFile(path, index)); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | /////////////////////////////////////////////////////////////////////////////// |
| 154 | |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 155 | void SkTypeface::serialize(SkWStream* wstream) const { |
caryclark | 5ef194c | 2015-08-31 09:22:38 -0700 | [diff] [blame] | 156 | if (gSerializeTypefaceDelegate) { |
| 157 | (*gSerializeTypefaceDelegate)(this, wstream); |
| 158 | return; |
| 159 | } |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 160 | bool isLocal = false; |
| 161 | SkFontDescriptor desc(this->style()); |
| 162 | this->onGetFontDescriptor(&desc, &isLocal); |
| 163 | |
mtklein | 1a4900e | 2014-12-11 11:06:00 -0800 | [diff] [blame] | 164 | // Embed font data if it's a local font. |
bungeman | 5ae1312 | 2015-05-13 12:16:41 -0700 | [diff] [blame] | 165 | if (isLocal && !desc.hasFontData()) { |
bungeman | 41868fe | 2015-05-20 09:21:04 -0700 | [diff] [blame] | 166 | desc.setFontData(this->onCreateFontData()); |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 167 | } |
mtklein | 1a4900e | 2014-12-11 11:06:00 -0800 | [diff] [blame] | 168 | desc.serialize(wstream); |
| 169 | } |
bungeman | d71b757 | 2014-09-18 10:55:32 -0700 | [diff] [blame] | 170 | |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 171 | sk_sp<SkTypeface> SkTypeface::MakeDeserialize(SkStream* stream) { |
caryclark | 5ef194c | 2015-08-31 09:22:38 -0700 | [diff] [blame] | 172 | if (gDeserializeTypefaceDelegate) { |
| 173 | return (*gDeserializeTypefaceDelegate)(stream); |
| 174 | } |
robertphillips | 3552ba1 | 2016-02-25 10:58:49 -0800 | [diff] [blame] | 175 | |
| 176 | SkFontDescriptor desc; |
| 177 | if (!SkFontDescriptor::Deserialize(stream, &desc)) { |
| 178 | return nullptr; |
| 179 | } |
| 180 | |
bungeman | 41868fe | 2015-05-20 09:21:04 -0700 | [diff] [blame] | 181 | SkFontData* data = desc.detachFontData(); |
bungeman | d71b757 | 2014-09-18 10:55:32 -0700 | [diff] [blame] | 182 | if (data) { |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 183 | sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData(data)); |
bungeman | d71b757 | 2014-09-18 10:55:32 -0700 | [diff] [blame] | 184 | if (typeface) { |
| 185 | return typeface; |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 186 | } |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 187 | } |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 188 | return SkTypeface::MakeFromName(desc.getFamilyName(), desc.getStyle()); |
vandebo@chromium.org | 2a22e10 | 2011-01-25 21:01:34 +0000 | [diff] [blame] | 189 | } |
reed@google.com | f11508d | 2012-04-17 18:01:31 +0000 | [diff] [blame] | 190 | |
| 191 | /////////////////////////////////////////////////////////////////////////////// |
| 192 | |
| 193 | int SkTypeface::countTables() const { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 194 | return this->onGetTableTags(nullptr); |
reed@google.com | f11508d | 2012-04-17 18:01:31 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | int SkTypeface::getTableTags(SkFontTableTag tags[]) const { |
reed@google.com | 6c66d2f | 2013-03-21 20:34:27 +0000 | [diff] [blame] | 198 | return this->onGetTableTags(tags); |
reed@google.com | f11508d | 2012-04-17 18:01:31 +0000 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | size_t SkTypeface::getTableSize(SkFontTableTag tag) const { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 202 | return this->onGetTableData(tag, 0, ~0U, nullptr); |
reed@google.com | f11508d | 2012-04-17 18:01:31 +0000 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length, |
| 206 | void* data) const { |
reed@google.com | 6c66d2f | 2013-03-21 20:34:27 +0000 | [diff] [blame] | 207 | return this->onGetTableData(tag, offset, length, data); |
reed@google.com | f11508d | 2012-04-17 18:01:31 +0000 | [diff] [blame] | 208 | } |
| 209 | |
bungeman | 5f213d9 | 2015-01-27 05:39:10 -0800 | [diff] [blame] | 210 | SkStreamAsset* SkTypeface::openStream(int* ttcIndex) const { |
reed@google.com | 2cdc671 | 2013-03-21 18:22:00 +0000 | [diff] [blame] | 211 | int ttcIndexStorage; |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 212 | if (nullptr == ttcIndex) { |
reed@google.com | 2cdc671 | 2013-03-21 18:22:00 +0000 | [diff] [blame] | 213 | // So our subclasses don't need to check for null param |
| 214 | ttcIndex = &ttcIndexStorage; |
reed@google.com | fed86bd | 2013-03-14 15:04:57 +0000 | [diff] [blame] | 215 | } |
reed@google.com | 2cdc671 | 2013-03-21 18:22:00 +0000 | [diff] [blame] | 216 | return this->onOpenStream(ttcIndex); |
reed@google.com | fed86bd | 2013-03-14 15:04:57 +0000 | [diff] [blame] | 217 | } |
| 218 | |
bungeman | 41868fe | 2015-05-20 09:21:04 -0700 | [diff] [blame] | 219 | SkFontData* SkTypeface::createFontData() const { |
| 220 | return this->onCreateFontData(); |
| 221 | } |
| 222 | |
| 223 | // This implementation is temporary until this method can be made pure virtual. |
| 224 | SkFontData* SkTypeface::onCreateFontData() const { |
| 225 | int index; |
| 226 | SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index)); |
mtklein | 18300a3 | 2016-03-16 13:53:35 -0700 | [diff] [blame] | 227 | return new SkFontData(stream.release(), index, nullptr, 0); |
bungeman | 41868fe | 2015-05-20 09:21:04 -0700 | [diff] [blame] | 228 | }; |
| 229 | |
reed@google.com | bcb42ae | 2013-07-02 13:56:39 +0000 | [diff] [blame] | 230 | int SkTypeface::charsToGlyphs(const void* chars, Encoding encoding, |
| 231 | uint16_t glyphs[], int glyphCount) const { |
| 232 | if (glyphCount <= 0) { |
| 233 | return 0; |
| 234 | } |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 235 | if (nullptr == chars || (unsigned)encoding > kUTF32_Encoding) { |
reed@google.com | bcb42ae | 2013-07-02 13:56:39 +0000 | [diff] [blame] | 236 | if (glyphs) { |
| 237 | sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); |
| 238 | } |
| 239 | return 0; |
| 240 | } |
| 241 | return this->onCharsToGlyphs(chars, encoding, glyphs, glyphCount); |
| 242 | } |
| 243 | |
| 244 | int SkTypeface::countGlyphs() const { |
| 245 | return this->onCountGlyphs(); |
| 246 | } |
| 247 | |
reed@google.com | 4b2af9c | 2012-07-31 17:24:44 +0000 | [diff] [blame] | 248 | int SkTypeface::getUnitsPerEm() const { |
reed@google.com | 38c37dd | 2013-03-21 15:36:26 +0000 | [diff] [blame] | 249 | // should we try to cache this in the base-class? |
| 250 | return this->onGetUPEM(); |
reed@google.com | 4b2af9c | 2012-07-31 17:24:44 +0000 | [diff] [blame] | 251 | } |
mike@reedtribe.org | dc09f07 | 2013-03-03 01:15:48 +0000 | [diff] [blame] | 252 | |
reed@google.com | 35fe737 | 2013-10-30 15:07:03 +0000 | [diff] [blame] | 253 | bool SkTypeface::getKerningPairAdjustments(const uint16_t glyphs[], int count, |
| 254 | int32_t adjustments[]) const { |
| 255 | SkASSERT(count >= 0); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 256 | // check for the only legal way to pass a nullptr.. everything is 0 |
reed@google.com | 35fe737 | 2013-10-30 15:07:03 +0000 | [diff] [blame] | 257 | // in which case they just want to know if this face can possibly support |
| 258 | // kerning (true) or never (false). |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 259 | if (nullptr == glyphs || nullptr == adjustments) { |
| 260 | SkASSERT(nullptr == glyphs); |
reed@google.com | 35fe737 | 2013-10-30 15:07:03 +0000 | [diff] [blame] | 261 | SkASSERT(0 == count); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 262 | SkASSERT(nullptr == adjustments); |
reed@google.com | 35fe737 | 2013-10-30 15:07:03 +0000 | [diff] [blame] | 263 | } |
| 264 | return this->onGetKerningPairAdjustments(glyphs, count, adjustments); |
| 265 | } |
| 266 | |
bungeman@google.com | 839702b | 2013-08-07 17:09:22 +0000 | [diff] [blame] | 267 | SkTypeface::LocalizedStrings* SkTypeface::createFamilyNameIterator() const { |
| 268 | return this->onCreateFamilyNameIterator(); |
bungeman@google.com | a980269 | 2013-08-07 02:45:25 +0000 | [diff] [blame] | 269 | } |
| 270 | |
reed@google.com | 08df48d | 2013-07-29 18:54:08 +0000 | [diff] [blame] | 271 | void SkTypeface::getFamilyName(SkString* name) const { |
bungeman | b374d6a | 2014-09-17 07:48:59 -0700 | [diff] [blame] | 272 | SkASSERT(name); |
| 273 | this->onGetFamilyName(name); |
reed@google.com | 08df48d | 2013-07-29 18:54:08 +0000 | [diff] [blame] | 274 | } |
| 275 | |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 276 | SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics( |
reed | 39a9a50 | 2015-05-12 09:50:04 -0700 | [diff] [blame] | 277 | PerGlyphInfo info, |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 278 | const uint32_t* glyphIDs, |
| 279 | uint32_t glyphIDsCount) const { |
vandebo | 0f9bad0 | 2014-06-19 11:05:39 -0700 | [diff] [blame] | 280 | SkAdvancedTypefaceMetrics* result = |
| 281 | this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount); |
| 282 | if (result && result->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
| 283 | struct SkOTTableOS2 os2table; |
| 284 | if (this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG), 0, |
| 285 | sizeof(os2table), &os2table) > 0) { |
| 286 | if (os2table.version.v2.fsType.field.Bitmap || |
| 287 | (os2table.version.v2.fsType.field.Restricted && |
| 288 | !(os2table.version.v2.fsType.field.PreviewPrint || |
| 289 | os2table.version.v2.fsType.field.Editable))) { |
| 290 | result->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( |
| 291 | result->fFlags, |
| 292 | SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); |
| 293 | } |
| 294 | if (os2table.version.v2.fsType.field.NoSubsetting) { |
| 295 | result->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( |
| 296 | result->fFlags, |
| 297 | SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag); |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | return result; |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 302 | } |
mike@reedtribe.org | dc09f07 | 2013-03-03 01:15:48 +0000 | [diff] [blame] | 303 | |
reed@google.com | 35fe737 | 2013-10-30 15:07:03 +0000 | [diff] [blame] | 304 | bool SkTypeface::onGetKerningPairAdjustments(const uint16_t glyphs[], int count, |
| 305 | int32_t adjustments[]) const { |
| 306 | return false; |
| 307 | } |
reed | a0c814c | 2014-10-22 13:20:58 -0700 | [diff] [blame] | 308 | |
| 309 | /////////////////////////////////////////////////////////////////////////////// |
| 310 | |
| 311 | #include "SkDescriptor.h" |
| 312 | #include "SkPaint.h" |
| 313 | |
mtklein | 6c59d80 | 2015-09-09 09:09:53 -0700 | [diff] [blame] | 314 | SkRect SkTypeface::getBounds() const { |
mtklein | 59c12e3 | 2016-05-02 07:19:41 -0700 | [diff] [blame] | 315 | fBoundsOnce([this] { |
| 316 | if (!this->onComputeBounds(&fBounds)) { |
| 317 | fBounds.setEmpty(); |
reed | a0c814c | 2014-10-22 13:20:58 -0700 | [diff] [blame] | 318 | } |
mtklein | 6c59d80 | 2015-09-09 09:09:53 -0700 | [diff] [blame] | 319 | }); |
mtklein | 59c12e3 | 2016-05-02 07:19:41 -0700 | [diff] [blame] | 320 | return fBounds; |
reed | a0c814c | 2014-10-22 13:20:58 -0700 | [diff] [blame] | 321 | } |
| 322 | |
| 323 | bool SkTypeface::onComputeBounds(SkRect* bounds) const { |
| 324 | // we use a big size to ensure lots of significant bits from the scalercontext. |
| 325 | // then we scale back down to return our final answer (at 1-pt) |
| 326 | const SkScalar textSize = 2048; |
| 327 | const SkScalar invTextSize = 1 / textSize; |
| 328 | |
| 329 | SkPaint paint; |
bungeman | 13b9c95 | 2016-05-12 10:09:30 -0700 | [diff] [blame] | 330 | paint.setTypeface(sk_ref_sp(const_cast<SkTypeface*>(this))); |
reed | a0c814c | 2014-10-22 13:20:58 -0700 | [diff] [blame] | 331 | paint.setTextSize(textSize); |
| 332 | paint.setLinearText(true); |
| 333 | |
| 334 | SkScalerContext::Rec rec; |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 335 | SkScalerContext::MakeRec(paint, nullptr, nullptr, &rec); |
reed | a0c814c | 2014-10-22 13:20:58 -0700 | [diff] [blame] | 336 | |
| 337 | SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1)); |
| 338 | SkDescriptor* desc = ad.getDesc(); |
| 339 | desc->init(); |
| 340 | desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); |
| 341 | |
reed | a9322c2 | 2016-04-12 06:47:05 -0700 | [diff] [blame] | 342 | SkScalerContextEffects noeffects; |
| 343 | SkAutoTDelete<SkScalerContext> ctx(this->createScalerContext(noeffects, desc, true)); |
reed | a0c814c | 2014-10-22 13:20:58 -0700 | [diff] [blame] | 344 | if (ctx.get()) { |
| 345 | SkPaint::FontMetrics fm; |
| 346 | ctx->getFontMetrics(&fm); |
| 347 | bounds->set(fm.fXMin * invTextSize, fm.fTop * invTextSize, |
| 348 | fm.fXMax * invTextSize, fm.fBottom * invTextSize); |
| 349 | return true; |
| 350 | } |
| 351 | return false; |
| 352 | } |