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