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