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 "SkFontDescriptor.h" 9#include "SkFontHost_FreeType_common.h" 10#include "SkFontMgr.h" 11#include "SkFontMgr_custom.h" 12#include "SkFontStyle.h" 13#include "SkOSFile.h" 14#include "SkRefCnt.h" 15#include "SkStream.h" 16#include "SkString.h" 17#include "SkTArray.h" 18#include "SkTemplates.h" 19#include "SkTypeface.h" 20#include "SkTypefaceCache.h" 21#include "SkTypes.h" 22 23#include <limits> 24 25class SkData; 26 27/** The base SkTypeface implementation for the custom font manager. */ 28class SkTypeface_Custom : public SkTypeface_FreeType { 29public: 30 SkTypeface_Custom(const SkFontStyle& style, bool isFixedPitch, 31 bool sysFont, const SkString familyName, int index) 32 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) 33 , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index) 34 { } 35 36 bool isSysFont() const { return fIsSysFont; } 37 38protected: 39 void onGetFamilyName(SkString* familyName) const override { 40 *familyName = fFamilyName; 41 } 42 43 void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override { 44 desc->setFamilyName(fFamilyName.c_str()); 45 *isLocal = !this->isSysFont(); 46 } 47 48 int getIndex() const { return fIndex; } 49 50private: 51 const bool fIsSysFont; 52 const SkString fFamilyName; 53 const int fIndex; 54 55 typedef SkTypeface_FreeType INHERITED; 56}; 57 58/** The empty SkTypeface implementation for the custom font manager. 59 * Used as the last resort fallback typeface. 60 */ 61class SkTypeface_Empty : public SkTypeface_Custom { 62public: 63 SkTypeface_Empty() : INHERITED(SkFontStyle(), false, true, SkString(), 0) {} 64 65protected: 66 SkStreamAsset* onOpenStream(int*) const override { return nullptr; } 67 68private: 69 typedef SkTypeface_Custom INHERITED; 70}; 71 72/** The stream SkTypeface implementation for the custom font manager. */ 73class SkTypeface_Stream : public SkTypeface_Custom { 74public: 75 SkTypeface_Stream(const SkFontStyle& style, bool isFixedPitch, bool sysFont, 76 const SkString familyName, SkStreamAsset* stream, int index) 77 : INHERITED(style, isFixedPitch, sysFont, familyName, index) 78 , fStream(stream) 79 { } 80 81protected: 82 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 83 *ttcIndex = this->getIndex(); 84 return fStream->duplicate(); 85 } 86 87private: 88 const SkAutoTDelete<const SkStreamAsset> fStream; 89 90 typedef SkTypeface_Custom INHERITED; 91}; 92 93/** The file SkTypeface implementation for the custom font manager. */ 94class SkTypeface_File : public SkTypeface_Custom { 95public: 96 SkTypeface_File(const SkFontStyle& style, bool isFixedPitch, bool sysFont, 97 const SkString familyName, const char path[], int index) 98 : INHERITED(style, isFixedPitch, sysFont, familyName, index) 99 , fPath(path) 100 { } 101 102protected: 103 SkStreamAsset* onOpenStream(int* ttcIndex) const override { 104 *ttcIndex = this->getIndex(); 105 return SkStream::NewFromFile(fPath.c_str()); 106 } 107 108private: 109 SkString fPath; 110 111 typedef SkTypeface_Custom INHERITED; 112}; 113 114/////////////////////////////////////////////////////////////////////////////// 115 116/** 117 * SkFontStyleSet_Custom 118 * 119 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. 120 */ 121class SkFontStyleSet_Custom : public SkFontStyleSet { 122public: 123 explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } 124 125 /** Should only be called during the inital build phase. */ 126 void appendTypeface(SkTypeface_Custom* typeface) { 127 fStyles.push_back().reset(typeface); 128 } 129 130 int count() override { 131 return fStyles.count(); 132 } 133 134 void getStyle(int index, SkFontStyle* style, SkString* name) override { 135 SkASSERT(index < fStyles.count()); 136 bool bold = fStyles[index]->isBold(); 137 bool italic = fStyles[index]->isItalic(); 138 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, 139 SkFontStyle::kNormal_Width, 140 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); 141 name->reset(); 142 } 143 144 SkTypeface* createTypeface(int index) override { 145 SkASSERT(index < fStyles.count()); 146 return SkRef(fStyles[index].get()); 147 } 148 149 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) { 150 int score = 0; 151 score += (pattern.width() - candidate.width()) * 100; 152 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; 153 score += pattern.weight() - candidate.weight(); 154 return score; 155 } 156 157 SkTypeface* matchStyle(const SkFontStyle& pattern) override { 158 if (0 == fStyles.count()) { 159 return nullptr; 160 } 161 162 SkTypeface_Custom* closest = fStyles[0]; 163 int minScore = std::numeric_limits<int>::max(); 164 for (int i = 0; i < fStyles.count(); ++i) { 165 bool bold = fStyles[i]->isBold(); 166 bool italic = fStyles[i]->isItalic(); 167 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight 168 : SkFontStyle::kNormal_Weight, 169 SkFontStyle::kNormal_Width, 170 italic ? SkFontStyle::kItalic_Slant 171 : SkFontStyle::kUpright_Slant); 172 173 int score = match_score(pattern, style); 174 if (score < minScore) { 175 closest = fStyles[i]; 176 minScore = score; 177 } 178 } 179 return SkRef(closest); 180 } 181 182 SkString getFamilyName() { return fFamilyName; } 183 184private: 185 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles; 186 SkString fFamilyName; 187 188 friend class SkFontMgr_Custom; 189}; 190 191/** 192 * SkFontMgr_Custom 193 * 194 * This class is essentially a collection of SkFontStyleSet_Custom, 195 * one SkFontStyleSet_Custom for each family. This class may be modified 196 * to load fonts from any source by changing the initialization. 197 */ 198class SkFontMgr_Custom : public SkFontMgr { 199public: 200 typedef SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> Families; 201 class SystemFontLoader { 202 public: 203 virtual ~SystemFontLoader() { } 204 virtual void loadSystemFonts(const SkTypeface_FreeType::Scanner&, Families*) const = 0; 205 }; 206 explicit SkFontMgr_Custom(const SystemFontLoader& loader) : fDefaultFamily(nullptr) { 207 loader.loadSystemFonts(fScanner, &fFamilies); 208 209 // Try to pick a default font. 210 static const char* defaultNames[] = { 211 "Arial", "Verdana", "Times New Roman", "Droid Sans", nullptr 212 }; 213 for (size_t i = 0; i < SK_ARRAY_COUNT(defaultNames); ++i) { 214 SkFontStyleSet_Custom* set = this->onMatchFamily(defaultNames[i]); 215 if (nullptr == set) { 216 continue; 217 } 218 219 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, 220 SkFontStyle::kNormal_Width, 221 SkFontStyle::kUpright_Slant)); 222 if (nullptr == tf) { 223 continue; 224 } 225 226 fDefaultFamily = set; 227 break; 228 } 229 if (nullptr == fDefaultFamily) { 230 fDefaultFamily = fFamilies[0]; 231 } 232 } 233 234protected: 235 int onCountFamilies() const override { 236 return fFamilies.count(); 237 } 238 239 void onGetFamilyName(int index, SkString* familyName) const override { 240 SkASSERT(index < fFamilies.count()); 241 familyName->set(fFamilies[index]->getFamilyName()); 242 } 243 244 SkFontStyleSet_Custom* onCreateStyleSet(int index) const override { 245 SkASSERT(index < fFamilies.count()); 246 return SkRef(fFamilies[index].get()); 247 } 248 249 SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const override { 250 for (int i = 0; i < fFamilies.count(); ++i) { 251 if (fFamilies[i]->getFamilyName().equals(familyName)) { 252 return SkRef(fFamilies[i].get()); 253 } 254 } 255 return nullptr; 256 } 257 258 SkTypeface* onMatchFamilyStyle(const char familyName[], 259 const SkFontStyle& fontStyle) const override 260 { 261 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 262 return sset->matchStyle(fontStyle); 263 } 264 265 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, 266 const char* bcp47[], int bcp47Count, 267 SkUnichar character) const override 268 { 269 return nullptr; 270 } 271 272 SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 273 const SkFontStyle& fontStyle) const override 274 { 275 for (int i = 0; i < fFamilies.count(); ++i) { 276 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { 277 if (fFamilies[i]->fStyles[j] == familyMember) { 278 return fFamilies[i]->matchStyle(fontStyle); 279 } 280 } 281 } 282 return nullptr; 283 } 284 285 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { 286 return this->createFromStream(new SkMemoryStream(data), ttcIndex); 287 } 288 289 SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override { 290 SkAutoTDelete<SkStreamAsset> stream(bareStream); 291 if (nullptr == stream || stream->getLength() <= 0) { 292 return nullptr; 293 } 294 295 bool isFixedPitch; 296 SkFontStyle style; 297 SkString name; 298 if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, nullptr)) { 299 return new SkTypeface_Stream(style, isFixedPitch, false, name, stream.detach(), 300 ttcIndex); 301 } else { 302 return nullptr; 303 } 304 } 305 306 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 307 SkAutoTDelete<SkStreamAsset> stream(SkStream::NewFromFile(path)); 308 return stream.get() ? this->createFromStream(stream.detach(), ttcIndex) : nullptr; 309 } 310 311 SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const override { 312 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; 313 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold 314 ? SkFontStyle::kBold_Weight 315 : SkFontStyle::kNormal_Weight, 316 SkFontStyle::kNormal_Width, 317 oldStyle & SkTypeface::kItalic 318 ? SkFontStyle::kItalic_Slant 319 : SkFontStyle::kUpright_Slant); 320 SkTypeface* tf = nullptr; 321 322 if (familyName) { 323 tf = this->onMatchFamilyStyle(familyName, style); 324 } 325 326 if (nullptr == tf) { 327 tf = fDefaultFamily->matchStyle(style); 328 } 329 330 return SkSafeRef(tf); 331 } 332 333private: 334 Families fFamilies; 335 SkFontStyleSet_Custom* fDefaultFamily; 336 SkTypeface_FreeType::Scanner fScanner; 337}; 338 339/////////////////////////////////////////////////////////////////////////////// 340 341class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { 342public: 343 DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { } 344 345 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, 346 SkFontMgr_Custom::Families* families) const override 347 { 348 load_directory_fonts(scanner, fBaseDirectory, ".ttf", families); 349 load_directory_fonts(scanner, fBaseDirectory, ".ttc", families); 350 load_directory_fonts(scanner, fBaseDirectory, ".otf", families); 351 load_directory_fonts(scanner, fBaseDirectory, ".pfb", families); 352 353 if (families->empty()) { 354 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 355 families->push_back().reset(family); 356 family->appendTypeface(new SkTypeface_Empty); 357 } 358 } 359 360private: 361 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, 362 const char familyName[]) 363 { 364 for (int i = 0; i < families.count(); ++i) { 365 if (families[i]->getFamilyName().equals(familyName)) { 366 return families[i].get(); 367 } 368 } 369 return nullptr; 370 } 371 372 static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner, 373 const SkString& directory, const char* suffix, 374 SkFontMgr_Custom::Families* families) 375 { 376 SkOSFile::Iter iter(directory.c_str(), suffix); 377 SkString name; 378 379 while (iter.next(&name, false)) { 380 SkString filename(SkOSPath::Join(directory.c_str(), name.c_str())); 381 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(filename.c_str())); 382 if (!stream.get()) { 383 SkDebugf("---- failed to open <%s>\n", filename.c_str()); 384 continue; 385 } 386 387 int numFaces; 388 if (!scanner.recognizedFont(stream, &numFaces)) { 389 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); 390 continue; 391 } 392 393 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { 394 bool isFixedPitch; 395 SkString realname; 396 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning 397 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) { 398 SkDebugf("---- failed to open <%s> <%d> as a font\n", 399 filename.c_str(), faceIndex); 400 continue; 401 } 402 403 SkTypeface_Custom* tf = new SkTypeface_File(style, isFixedPitch, 404 true, // system-font (cannot delete) 405 realname, filename.c_str(), faceIndex); 406 407 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); 408 if (nullptr == addTo) { 409 addTo = new SkFontStyleSet_Custom(realname); 410 families->push_back().reset(addTo); 411 } 412 addTo->appendTypeface(tf); 413 } 414 } 415 416 SkOSFile::Iter dirIter(directory.c_str()); 417 while (dirIter.next(&name, true)) { 418 if (name.startsWith(".")) { 419 continue; 420 } 421 SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str())); 422 load_directory_fonts(scanner, dirname, suffix, families); 423 } 424 } 425 426 SkString fBaseDirectory; 427}; 428 429SK_API SkFontMgr* SkFontMgr_New_Custom_Directory(const char* dir) { 430 return new SkFontMgr_Custom(DirectorySystemFontLoader(dir)); 431} 432 433/////////////////////////////////////////////////////////////////////////////// 434 435struct SkEmbeddedResource { const uint8_t* data; size_t size; }; 436struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; }; 437 438class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader { 439public: 440 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { } 441 442 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner, 443 SkFontMgr_Custom::Families* families) const override 444 { 445 for (int i = 0; i < fHeader->count; ++i) { 446 const SkEmbeddedResource& fontEntry = fHeader->entries[i]; 447 load_embedded_font(scanner, fontEntry.data, fontEntry.size, i, families); 448 } 449 450 if (families->empty()) { 451 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 452 families->push_back().reset(family); 453 family->appendTypeface(new SkTypeface_Empty); 454 } 455 } 456 457private: 458 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families, 459 const char familyName[]) 460 { 461 for (int i = 0; i < families.count(); ++i) { 462 if (families[i]->getFamilyName().equals(familyName)) { 463 return families[i].get(); 464 } 465 } 466 return nullptr; 467 } 468 469 static void load_embedded_font(const SkTypeface_FreeType::Scanner& scanner, 470 const uint8_t* data, size_t size, int index, 471 SkFontMgr_Custom::Families* families) 472 { 473 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(data, size, false)); 474 475 int numFaces; 476 if (!scanner.recognizedFont(stream, &numFaces)) { 477 SkDebugf("---- failed to open <%d> as a font\n", index); 478 return; 479 } 480 481 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { 482 bool isFixedPitch; 483 SkString realname; 484 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning 485 if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, nullptr)) { 486 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); 487 return; 488 } 489 490 SkTypeface_Custom* tf = 491 new SkTypeface_Stream(style, isFixedPitch, true, // system-font (cannot delete) 492 realname, stream.detach(), faceIndex); 493 494 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str()); 495 if (nullptr == addTo) { 496 addTo = new SkFontStyleSet_Custom(realname); 497 families->push_back().reset(addTo); 498 } 499 addTo->appendTypeface(tf); 500 } 501 } 502 503 const SkEmbeddedResourceHeader* fHeader; 504}; 505 506SkFontMgr* SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) { 507 return new SkFontMgr_Custom(EmbeddedSystemFontLoader(header)); 508} 509