1/* 2 * Copyright 2006 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 8#include "SkFontArguments.h" 9#include "SkFontDescriptor.h" 10#include "SkFontHost_FreeType_common.h" 11#include "SkFontMgr.h" 12#include "SkFontMgr_custom.h" 13#include "SkFontStyle.h" 14#include "SkMakeUnique.h" 15#include "SkRefCnt.h" 16#include "SkStream.h" 17#include "SkString.h" 18#include "SkTArray.h" 19#include "SkTemplates.h" 20#include "SkTypeface.h" 21#include "SkTypes.h" 22 23#include <limits> 24#include <memory> 25 26class SkData; 27 28SkTypeface_Custom::SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, 29 bool sysFont, const SkString familyName, int index) 30 : INHERITED(style, isFixedPitch) 31 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index) 32{ } 33 34bool SkTypeface_Custom::isSysFont() const { return fIsSysFont; } 35 36void SkTypeface_Custom::onGetFamilyName(SkString* familyName) const { 37 *familyName = fFamilyName; 38} 39 40void SkTypeface_Custom::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { 41 desc->setFamilyName(fFamilyName.c_str()); 42 desc->setStyle(this->fontStyle()); 43 *isLocal = !this->isSysFont(); 44} 45 46int SkTypeface_Custom::getIndex() const { return fIndex; } 47 48 49SkTypeface_Empty::SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {} 50 51SkStreamAsset* SkTypeface_Empty::onOpenStream(int*) const { return nullptr; } 52 53 54SkTypeface_Stream::SkTypeface_Stream(std::unique_ptr<SkFontData> fontData, 55 const SkFontStyle& style, bool isFixedPitch, bool sysFont, 56 const SkString familyName) 57 : INHERITED(style, isFixedPitch, sysFont, familyName, fontData->getIndex()) 58 , fData(std::move(fontData)) 59{ } 60 61SkStreamAsset* SkTypeface_Stream::onOpenStream(int* ttcIndex) const { 62 *ttcIndex = fData->getIndex(); 63 return fData->getStream()->duplicate(); 64} 65 66std::unique_ptr<SkFontData> SkTypeface_Stream::onMakeFontData() const { 67 return skstd::make_unique<SkFontData>(*fData); 68} 69 70 71SkTypeface_File::SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont, 72 const SkString familyName, const char path[], int index) 73 : INHERITED(style, isFixedPitch, sysFont, familyName, index) 74 , fPath(path) 75{ } 76 77SkStreamAsset* SkTypeface_File::onOpenStream(int* ttcIndex) const { 78 *ttcIndex = this->getIndex(); 79 return SkStream::MakeFromFile(fPath.c_str()).release(); 80} 81 82/////////////////////////////////////////////////////////////////////////////// 83 84SkFontStyleSet_Custom::SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) {} 85 86void SkFontStyleSet_Custom::appendTypeface(sk_sp<SkTypeface_Custom> typeface) { 87 fStyles.emplace_back(std::move(typeface)); 88} 89 90int SkFontStyleSet_Custom::count() { 91 return fStyles.count(); 92} 93 94void SkFontStyleSet_Custom::getStyle(int index, SkFontStyle* style, SkString* name) { 95 SkASSERT(index < fStyles.count()); 96 if (style) { 97 *style = fStyles[index]->fontStyle(); 98 } 99 if (name) { 100 name->reset(); 101 } 102} 103 104SkTypeface* SkFontStyleSet_Custom::createTypeface(int index) { 105 SkASSERT(index < fStyles.count()); 106 return SkRef(fStyles[index].get()); 107} 108 109SkTypeface* SkFontStyleSet_Custom::matchStyle(const SkFontStyle& pattern) { 110 return this->matchStyleCSS3(pattern); 111} 112 113SkString SkFontStyleSet_Custom::getFamilyName() { return fFamilyName; } 114 115 116SkFontMgr_Custom::SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) { 117 loader.loadSystemFonts(fScanner, &fFamilies); 118 119 // Try to pick a default font. 120 static const char* defaultNames[] = { 121 "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr 122 }; 123 for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) { 124 sk_sp<SkFontStyleSet_Custom> set(this->onMatchFamily(defaultNames[i])); 125 if (nullptr == set) { 126 continue; 127 } 128 129 sk_sp<SkTypeface> tf(set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, 130 SkFontStyle::kNormal_Width, 131 SkFontStyle::kUpright_Slant))); 132 if (nullptr == tf) { 133 continue; 134 } 135 136 fDefaultFamily = set.get(); 137 break; 138 } 139 if (nullptr == fDefaultFamily) { 140 fDefaultFamily = fFamilies[0].get(); 141 } 142} 143 144int SkFontMgr_Custom::onCountFamilies() const { 145 return fFamilies.count(); 146} 147 148void SkFontMgr_Custom::onGetFamilyName(int index, SkString* familyName) const { 149 SkASSERT(index < fFamilies.count()); 150 familyName->set(fFamilies[index]->getFamilyName()); 151} 152 153SkFontStyleSet_Custom* SkFontMgr_Custom::onCreateStyleSet(int index) const { 154 SkASSERT(index < fFamilies.count()); 155 return SkRef(fFamilies[index].get()); 156} 157 158SkFontStyleSet_Custom* SkFontMgr_Custom::onMatchFamily(const char familyName[]) const { 159 for (int i = 0; i < fFamilies.count(); ++i) { 160 if (fFamilies[i]->getFamilyName().equals(familyName)) { 161 return SkRef(fFamilies[i].get()); 162 } 163 } 164 return nullptr; 165} 166 167SkTypeface* SkFontMgr_Custom::onMatchFamilyStyle(const char familyName[], 168 const SkFontStyle& fontStyle) const 169{ 170 sk_sp<SkFontStyleSet> sset(this->matchFamily(familyName)); 171 return sset->matchStyle(fontStyle); 172} 173 174SkTypeface* SkFontMgr_Custom::onMatchFamilyStyleCharacter(const char familyName[], 175 const SkFontStyle&, 176 const char* bcp47[], int bcp47Count, 177 SkUnichar character) const 178{ 179 return nullptr; 180} 181 182SkTypeface* SkFontMgr_Custom::onMatchFaceStyle(const SkTypeface* familyMember, 183 const SkFontStyle& fontStyle) const 184{ 185 for (int i = 0; i < fFamilies.count(); ++i) { 186 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { 187 if (fFamilies[i]->fStyles[j].get() == familyMember) { 188 return fFamilies[i]->matchStyle(fontStyle); 189 } 190 } 191 } 192 return nullptr; 193} 194 195SkTypeface* SkFontMgr_Custom::onCreateFromData(SkData* data, int ttcIndex) const { 196 return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex); 197} 198 199SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const { 200 return this->createFromStream(bareStream, FontParameters().setCollectionIndex(ttcIndex)); 201} 202 203SkTypeface* SkFontMgr_Custom::onCreateFromStream(SkStreamAsset* s, 204 const SkFontArguments& args) const 205{ 206 using Scanner = SkTypeface_FreeType::Scanner; 207 std::unique_ptr<SkStreamAsset> stream(s); 208 bool isFixedPitch; 209 SkFontStyle style; 210 SkString name; 211 Scanner::AxisDefinitions axisDefinitions; 212 if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(), 213 &name, &style, &isFixedPitch, &axisDefinitions)) 214 { 215 return nullptr; 216 } 217 218 const SkFontArguments::VariationPosition position = args.getVariationDesignPosition(); 219 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); 220 Scanner::computeAxisValues(axisDefinitions, position, axisValues, name); 221 222 auto data = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(), 223 axisValues.get(), axisDefinitions.count()); 224 return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name); 225} 226 227SkTypeface* SkFontMgr_Custom::onCreateFromFontData(std::unique_ptr<SkFontData> data) const { 228 bool isFixedPitch; 229 SkFontStyle style; 230 SkString name; 231 if (!fScanner.scanFont(data->getStream(), data->getIndex(), 232 &name, &style, &isFixedPitch, nullptr)) 233 { 234 return nullptr; 235 } 236 return new SkTypeface_Stream(std::move(data), style, isFixedPitch, false, name); 237} 238 239SkTypeface* SkFontMgr_Custom::onCreateFromFile(const char path[], int ttcIndex) const { 240 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path); 241 return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr; 242} 243 244SkTypeface* SkFontMgr_Custom::onLegacyCreateTypeface(const char familyName[], 245 SkFontStyle style) const 246{ 247 SkTypeface* tf = nullptr; 248 249 if (familyName) { 250 tf = this->onMatchFamilyStyle(familyName, style); 251 } 252 253 if (nullptr == tf) { 254 tf = fDefaultFamily->matchStyle(style); 255 } 256 257 return tf; 258} 259