SkFontMgr_custom_directory.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright 2017 Google Inc.
  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. #include "include/core/SkStream.h"
  8. #include "include/ports/SkFontMgr_directory.h"
  9. #include "src/core/SkOSFile.h"
  10. #include "src/ports/SkFontMgr_custom.h"
  11. #include "src/utils/SkOSPath.h"
  12. class DirectorySystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
  13. public:
  14. DirectorySystemFontLoader(const char* dir) : fBaseDirectory(dir) { }
  15. void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
  16. SkFontMgr_Custom::Families* families) const override
  17. {
  18. load_directory_fonts(scanner, fBaseDirectory, ".ttf", families);
  19. load_directory_fonts(scanner, fBaseDirectory, ".ttc", families);
  20. load_directory_fonts(scanner, fBaseDirectory, ".otf", families);
  21. load_directory_fonts(scanner, fBaseDirectory, ".pfb", families);
  22. if (families->empty()) {
  23. SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
  24. families->push_back().reset(family);
  25. family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
  26. }
  27. }
  28. private:
  29. static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
  30. const char familyName[])
  31. {
  32. for (int i = 0; i < families.count(); ++i) {
  33. if (families[i]->getFamilyName().equals(familyName)) {
  34. return families[i].get();
  35. }
  36. }
  37. return nullptr;
  38. }
  39. static void load_directory_fonts(const SkTypeface_FreeType::Scanner& scanner,
  40. const SkString& directory, const char* suffix,
  41. SkFontMgr_Custom::Families* families)
  42. {
  43. SkOSFile::Iter iter(directory.c_str(), suffix);
  44. SkString name;
  45. while (iter.next(&name, false)) {
  46. SkString filename(SkOSPath::Join(directory.c_str(), name.c_str()));
  47. std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(filename.c_str());
  48. if (!stream) {
  49. // SkDebugf("---- failed to open <%s>\n", filename.c_str());
  50. continue;
  51. }
  52. int numFaces;
  53. if (!scanner.recognizedFont(stream.get(), &numFaces)) {
  54. // SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
  55. continue;
  56. }
  57. for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
  58. bool isFixedPitch;
  59. SkString realname;
  60. SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
  61. if (!scanner.scanFont(stream.get(), faceIndex,
  62. &realname, &style, &isFixedPitch, nullptr))
  63. {
  64. // SkDebugf("---- failed to open <%s> <%d> as a font\n",
  65. // filename.c_str(), faceIndex);
  66. continue;
  67. }
  68. SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
  69. if (nullptr == addTo) {
  70. addTo = new SkFontStyleSet_Custom(realname);
  71. families->push_back().reset(addTo);
  72. }
  73. addTo->appendTypeface(sk_make_sp<SkTypeface_File>(style, isFixedPitch, true,
  74. realname, filename.c_str(),
  75. faceIndex));
  76. }
  77. }
  78. SkOSFile::Iter dirIter(directory.c_str());
  79. while (dirIter.next(&name, true)) {
  80. if (name.startsWith(".")) {
  81. continue;
  82. }
  83. SkString dirname(SkOSPath::Join(directory.c_str(), name.c_str()));
  84. load_directory_fonts(scanner, dirname, suffix, families);
  85. }
  86. }
  87. SkString fBaseDirectory;
  88. };
  89. SK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir) {
  90. return sk_make_sp<SkFontMgr_Custom>(DirectorySystemFontLoader(dir));
  91. }