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