xref: /aosp_15_r20/external/skia/src/ports/SkFontMgr_custom_embedded.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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