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/SkFontScanner.h"
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkStream.h"
11 #include "include/ports/SkFontMgr_data.h"
12 #include "src/core/SkFontDescriptor.h"
13 #include "src/ports/SkFontMgr_custom.h"
14
15 struct SkEmbeddedResource { const uint8_t* data; size_t size; };
16 struct SkEmbeddedResourceHeader { const SkEmbeddedResource* entries; int count; };
17
18 static void load_font_from_data(const SkFontScanner* scanner,
19 std::unique_ptr<SkMemoryStream> stream, int index,
20 SkFontMgr_Custom::Families* families);
21
22 class EmbeddedSystemFontLoader : public SkFontMgr_Custom::SystemFontLoader {
23 public:
EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader * header)24 EmbeddedSystemFontLoader(const SkEmbeddedResourceHeader* header) : fHeader(header) { }
25
loadSystemFonts(const SkFontScanner * scanner,SkFontMgr_Custom::Families * families) const26 void loadSystemFonts(const SkFontScanner* scanner,
27 SkFontMgr_Custom::Families* families) const override
28 {
29 for (int i = 0; i < fHeader->count; ++i) {
30 const SkEmbeddedResource& fontEntry = fHeader->entries[i];
31 auto stream = std::make_unique<SkMemoryStream>(fontEntry.data, fontEntry.size, false);
32 load_font_from_data(scanner, std::move(stream), i, families);
33 }
34
35 if (families->empty()) {
36 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
37 families->push_back().reset(family);
38 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
39 }
40 }
41
42 const SkEmbeddedResourceHeader* fHeader;
43 };
44
45 class DataFontLoader : public SkFontMgr_Custom::SystemFontLoader {
46 public:
DataFontLoader(sk_sp<SkData> * datas,int n)47 DataFontLoader(sk_sp<SkData>* datas, int n) : fDatas(datas), fNum(n) { }
48
loadSystemFonts(const SkFontScanner * scanner,SkFontMgr_Custom::Families * families) const49 void loadSystemFonts(const SkFontScanner* scanner,
50 SkFontMgr_Custom::Families* families) const override
51 {
52 for (int i = 0; i < fNum; ++i) {
53 auto stream = std::make_unique<SkMemoryStream>(fDatas[i]);
54 load_font_from_data(scanner, std::move(stream), i, families);
55 }
56
57 if (families->empty()) {
58 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
59 families->push_back().reset(family);
60 family->appendTypeface(sk_make_sp<SkTypeface_Empty>());
61 }
62 }
63
64 const sk_sp<SkData>* fDatas;
65 const int fNum;
66 };
67
find_family(SkFontMgr_Custom::Families & families,const char familyName[])68 static SkFontStyleSet_Custom* find_family(SkFontMgr_Custom::Families& families,
69 const char familyName[])
70 {
71 for (int i = 0; i < families.size(); ++i) {
72 if (families[i]->getFamilyName().equals(familyName)) {
73 return families[i].get();
74 }
75 }
76 return nullptr;
77 }
78
load_font_from_data(const SkFontScanner * scanner,std::unique_ptr<SkMemoryStream> stream,int index,SkFontMgr_Custom::Families * families)79 static void load_font_from_data(const SkFontScanner* scanner,
80 std::unique_ptr<SkMemoryStream> stream,
81 int index,
82 SkFontMgr_Custom::Families* families) {
83 int numFaces;
84 if (!scanner->scanFile(stream.get(), &numFaces)) {
85 SkDebugf("---- failed to open <%d> as a font\n", index);
86 return;
87 }
88 for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) {
89 int numInstances;
90 if (!scanner->scanFace(stream.get(), faceIndex, &numInstances)) {
91 SkDebugf("---- failed to open <%d> <%d> as a face\n", index, faceIndex);
92 continue;
93 }
94
95 for (int instanceIndex = 0; instanceIndex <= numInstances; ++instanceIndex) {
96 bool isFixedPitch;
97 SkString realname;
98 SkFontStyle style = SkFontStyle(); // avoid uninitialized warning
99 if (!scanner->scanInstance(stream.get(),
100 faceIndex,
101 instanceIndex,
102 &realname,
103 &style,
104 &isFixedPitch,
105 nullptr)) {
106 SkDebugf("---- failed to open <%d> <%d> <%d> as an instance\n",
107 index,
108 faceIndex,
109 instanceIndex);
110 return;
111 }
112
113 SkFontStyleSet_Custom* addTo = find_family(*families, realname.c_str());
114 if (nullptr == addTo) {
115 addTo = new SkFontStyleSet_Custom(realname);
116 families->push_back().reset(addTo);
117 }
118 auto data = std::make_unique<SkFontData>(
119 stream->duplicate(), faceIndex, 0, nullptr, 0, nullptr, 0);
120 addTo->appendTypeface(sk_make_sp<SkTypeface_FreeTypeStream>(
121 std::move(data), realname, style, isFixedPitch));
122 }
123 }
124 }
125
SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader * header)126 sk_sp<SkFontMgr> SkFontMgr_New_Custom_Embedded(const SkEmbeddedResourceHeader* header) {
127 return sk_make_sp<SkFontMgr_Custom>(EmbeddedSystemFontLoader(header));
128 }
129
SkFontMgr_New_Custom_Data(SkSpan<sk_sp<SkData>> datas)130 sk_sp<SkFontMgr> SkFontMgr_New_Custom_Data(SkSpan<sk_sp<SkData>> datas) {
131 SkASSERT(!datas.empty());
132 return sk_make_sp<SkFontMgr_Custom>(DataFontLoader(datas.data(), datas.size()));
133 }
134