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
8 #include "include/core/SkStream.h"
9 #include "src/core/SkFontDescriptor.h"
10 #include "src/core/SkMakeUnique.h"
11 #include "src/ports/SkFontMgr_custom.h"
12
13 struct SkEmbeddedResource { const uint8_t* data; size_t size; };
14 struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
15
16 static void load_font_from_data(const SkTypeface_FreeType::Scanner& scanner,
17 const uint8_t* data, size_t size, int index,
18 SkFontMgr_Custom::Families* families);
19
20 class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
21 public:
EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader * header)22 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
23
loadSystemFonts(const SkTypeface_FreeType::Scanner & scanner,SkFontMgr_Custom::Families * families) const24 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
25 SkFontMgr_Custom::Families* families) const override
26 {
27 for (int i = 0; i < fHeader->count; ++i) {
28 const SkEmbeddedResource& fontEntry = fHeader->entries[i];
29 load_font_from_data(scanner, fontEntry.data, fontEntry.size, i, families);
30 }
31
32 if (families->empty()) {
33 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
34 families->push_back().reset(family);
35 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
36 }
37 }
38
39 const SkEmbeddedResourceHeader* fHeader;
40 };
41
42 class DataFontLoader : public SkFontMgr_Custom::SystemFontLoader {
43 public:
DataFontLoader(const uint8_t ** datas,const size_t * sizes,int n)44 DataFontLoader(const uint8_t** datas, const size_t* sizes, int n) : fDatas(datas), fSizes(sizes), fNum(n) { }
45
loadSystemFonts(const SkTypeface_FreeType::Scanner & scanner,SkFontMgr_Custom::Families * families) const46 void loadSystemFonts(const SkTypeface_FreeType::Scanner& scanner,
47 SkFontMgr_Custom::Families* families) const override
48 {
49 for (int i = 0; i < fNum; ++i) {
50 load_font_from_data(scanner, fDatas[i], fSizes[i], i, families);
51 }
52
53 if (families->empty()) {
54 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
55 families->push_back().reset(family);
56 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
57 }
58 }
59
60 const uint8_t** fDatas;
61 const size_t* fSizes;
62 const int fNum;
63 };
64
find_family(SkFontMgr_Custom::Families & families,const char familyName[])65 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
66 const char familyName[])
67 {
68 for (int i = 0; i < families.count(); ++i) {
69 if (families[i]->getFamilyName().equals(familyName)) {
70 return families[i].get();
71 }
72 }
73 return nullptr;
74 }
75
load_font_from_data(const SkTypeface_FreeType::Scanner & scanner,const uint8_t * data,size_t size,int index,SkFontMgr_Custom::Families * families)76 static void load_font_from_data(const SkTypeface_FreeType::Scanner& scanner,
77 const uint8_t* data, size_t size, int index,
78 SkFontMgr_Custom::Families* families)
79 {
80 auto stream = skstd::make_unique<SkMemoryStream>(data, size, false);
81
82 int numFaces;
83 if (!scanner.recognizedFont(stream.get(), &numFaces)) {
84 SkDebugf("---- failed to open <%d> as a font\n", index);
85 return;
86 }
87
88 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
89 bool isFixedPitch;
90 SkString realname;
91 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
92 if (!scanner.scanFont(stream.get(), faceIndex,
93 &realname, &style, &isFixedPitch, nullptr))
94 {
95 SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex);
96 return;
97 }
98
99 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
100 if (nullptr == addTo) {
101 addTo = new SkFontStyleSet_Custom(realname);
102 families->push_back().reset(addTo);
103 }
104 auto data = skstd::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0);
105 addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
106 style, isFixedPitch,
107 true, realname));
108 }
109 }
110
SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader * header)111 sk_sp<SkFontMgr> SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) {
112 return sk_make_sp<SkFontMgr_Custom>(EmbeddedSystemFontLoader(header));
113 }
114
115 // SkFontMgr_New_Custom_Data expects to be called with the data for n font files. datas and sizes
116 // are parallel arrays of bytes and byte lengths.
SkFontMgr_New_Custom_Data(const uint8_t ** datas,const size_t * sizes,int n)117 sk_sp<SkFontMgr> SkFontMgr_New_Custom_Data(const uint8_t** datas, const size_t* sizes, int n) {
118 SkASSERT(datas != nullptr);
119 SkASSERT(sizes != nullptr);
120 SkASSERT(n > 0);
121 return sk_make_sp<SkFontMgr_Custom>(DataFontLoader(datas, sizes, n));
122 }
123