|
1 #import <UIKit/UIKit.h> |
|
2 |
|
3 #include "SkStream_NSData.h" |
|
4 #include "SkTypeface.h" |
|
5 #include "SkFontHost.h" |
|
6 #include "SkThread.h" |
|
7 #include "SkTemplates.h" |
|
8 |
|
9 enum FontDesign { |
|
10 kUnknown_Design, |
|
11 kSans_FontDesign, |
|
12 kSerif_FontDesign, |
|
13 |
|
14 kIllegal_FontDesign, // never use with a real font |
|
15 }; |
|
16 |
|
17 // returns kIllegal_FontDesign if not found |
|
18 static FontDesign find_design_from_name(const char name[]) { |
|
19 static const struct { |
|
20 const char* fName; |
|
21 FontDesign fDesign; |
|
22 } gRec[] = { |
|
23 { "sans-serif", kSans_FontDesign }, |
|
24 { "serif", kSerif_FontDesign }, |
|
25 }; |
|
26 |
|
27 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { |
|
28 if (!strcasecmp(name, gRec[i].fName)) { |
|
29 return gRec[i].fDesign; |
|
30 } |
|
31 } |
|
32 return kIllegal_FontDesign; |
|
33 } |
|
34 |
|
35 struct FontRes { |
|
36 const char* fName; |
|
37 SkTypeface::Style fStyle; |
|
38 FontDesign fDesign; |
|
39 }; |
|
40 |
|
41 static const FontRes gFontRes[] = { |
|
42 { "DroidSans", SkTypeface::kNormal, kSans_FontDesign }, |
|
43 { "DroidSans", SkTypeface::kBold, kSans_FontDesign }, |
|
44 { "DroidSerif-Regular", SkTypeface::kNormal, kSerif_FontDesign }, |
|
45 { "DroidSerif-Bold", SkTypeface::kBold, kSerif_FontDesign }, |
|
46 // { "PescaderoPro", SkTypeface::kNormal, kSerif_FontDesign }, |
|
47 // { "PescaderoPro-Bold", SkTypeface::kBold, kSerif_FontDesign }, |
|
48 }; |
|
49 #define FONTRES_COUNT SK_ARRAY_COUNT(gFontRes) |
|
50 |
|
51 #define DEFAULT_INDEX_REGULAR 1 |
|
52 #define DEFAULT_INDEX_BOLD 2 |
|
53 |
|
54 /////////////////////////////////////////////////////////////////////////////// |
|
55 |
|
56 class SkTypeface_Stream : public SkTypeface { |
|
57 public: |
|
58 SkTypeface_Stream(SkStream* stream, Style style); |
|
59 virtual ~SkTypeface_Stream(); |
|
60 |
|
61 SkStream* refStream() { |
|
62 fStream->ref(); |
|
63 return fStream; |
|
64 } |
|
65 |
|
66 private: |
|
67 SkStream* fStream; |
|
68 }; |
|
69 |
|
70 static int32_t gUniqueFontID; |
|
71 |
|
72 SkTypeface_Stream::SkTypeface_Stream(SkStream* stream, Style style) |
|
73 : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) { |
|
74 fStream = stream; |
|
75 fStream->ref(); |
|
76 } |
|
77 |
|
78 SkTypeface_Stream::~SkTypeface_Stream() { |
|
79 fStream->unref(); |
|
80 } |
|
81 |
|
82 static SkTypeface_Stream* create_from_fontres(const FontRes& res) { |
|
83 SkStream* stream = SkStream_NSData::CreateFromResource(res.fName, "ttf"); |
|
84 SkAutoUnref aur(stream); |
|
85 |
|
86 return SkNEW_ARGS(SkTypeface_Stream, (stream, res.fStyle)); |
|
87 } |
|
88 |
|
89 /////////////////////////////////////////////////////////////////////////////// |
|
90 |
|
91 static int compute_style_distance(SkTypeface::Style a, SkTypeface::Style b) { |
|
92 int dist = 0; |
|
93 int diff = a ^ b; |
|
94 if (diff & SkTypeface::kBold) { |
|
95 dist += 2; |
|
96 } |
|
97 if (diff & SkTypeface::kItalic) { |
|
98 dist += 1; |
|
99 } |
|
100 return dist; |
|
101 } |
|
102 |
|
103 static SkTypeface_Stream* gFonts[FONTRES_COUNT]; |
|
104 |
|
105 static void assure_init_fonts() { |
|
106 static bool gOnce; |
|
107 if (!gOnce) { |
|
108 for (size_t i = 0; i < FONTRES_COUNT; i++) { |
|
109 gFonts[i] = create_from_fontres(gFontRes[i]); |
|
110 gOnce = true; |
|
111 } |
|
112 } |
|
113 } |
|
114 |
|
115 static SkTypeface_Stream* get_default_font(SkTypeface::Style style) { |
|
116 assure_init_fonts(); |
|
117 |
|
118 if (style & SkTypeface::kBold) { |
|
119 return gFonts[DEFAULT_INDEX_BOLD]; |
|
120 } else { |
|
121 return gFonts[DEFAULT_INDEX_REGULAR]; |
|
122 } |
|
123 } |
|
124 |
|
125 static SkTypeface_Stream* find_by_id(SkFontID fontID) { |
|
126 assure_init_fonts(); |
|
127 |
|
128 for (size_t i = 0; i < FONTRES_COUNT; i++) { |
|
129 if (gFonts[i]->uniqueID() == fontID) { |
|
130 return gFonts[i]; |
|
131 } |
|
132 } |
|
133 return NULL; |
|
134 } |
|
135 |
|
136 /////////////////////////////////////////////////////////////////////////////// |
|
137 |
|
138 template <typename T> T* ref_and_return(T* obj) { |
|
139 obj->ref(); |
|
140 return obj; |
|
141 } |
|
142 |
|
143 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, |
|
144 const char familyName[], |
|
145 const void* data, size_t bytelength, |
|
146 SkTypeface::Style style) { |
|
147 assure_init_fonts(); |
|
148 |
|
149 if (familyName) { |
|
150 FontDesign design = find_design_from_name(familyName); |
|
151 if (kIllegal_FontDesign != design) { |
|
152 familyName = "$#@*&%*#$@ never match any name"; |
|
153 } |
|
154 |
|
155 int bestDistance = 999; |
|
156 int bestIndex = -1; |
|
157 for (size_t i = 0; i < FONTRES_COUNT; i++) { |
|
158 if (design == gFontRes[i].fDesign || !strcmp(gFontRes[i].fName, familyName)) { |
|
159 int dist = compute_style_distance(style, gFontRes[i].fStyle); |
|
160 if (dist < bestDistance) { |
|
161 bestDistance = dist; |
|
162 bestIndex = i; |
|
163 } |
|
164 } |
|
165 } |
|
166 if (bestIndex >= 0) { |
|
167 return ref_and_return(gFonts[bestIndex]); |
|
168 } |
|
169 } |
|
170 |
|
171 return ref_and_return(get_default_font(style)); |
|
172 } |
|
173 |
|
174 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { |
|
175 SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented"); |
|
176 return NULL; |
|
177 } |
|
178 |
|
179 SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { |
|
180 // SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented"); |
|
181 return NULL; |
|
182 } |
|
183 |
|
184 /////////////////////////////////////////////////////////////////////////////// |
|
185 |
|
186 SkStream* SkFontHost::OpenStream(uint32_t uniqueID) { |
|
187 SkTypeface_Stream* tf = find_by_id(uniqueID); |
|
188 SkASSERT(tf); |
|
189 return tf->refStream(); |
|
190 } |
|
191 |
|
192 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, |
|
193 int32_t* index) { |
|
194 SkDebugf("SkFontHost::GetFileName unimplemented\n"); |
|
195 return 0; |
|
196 } |
|
197 |
|
198 /////////////////////////////////////////////////////////////////////////////// |
|
199 |
|
200 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { |
|
201 SkDEBUGFAIL("SkFontHost::Serialize unimplemented"); |
|
202 } |
|
203 |
|
204 SkTypeface* SkFontHost::Deserialize(SkStream* stream) { |
|
205 int style = stream->readU8(); |
|
206 int len = stream->readPackedUInt(); |
|
207 const char* name = NULL; |
|
208 if (len > 0) { |
|
209 SkString str; |
|
210 str.resize(len); |
|
211 stream->read(str.writable_str(), len); |
|
212 |
|
213 if (str.startsWith("DroidSans")) { |
|
214 name = "sans-serif"; |
|
215 } else if (str.startsWith("DroidSerif")) { |
|
216 name = "serif"; |
|
217 } |
|
218 SkDebugf("---- deserialize typeface <%s> %d %s\n", str.c_str(), style, name); |
|
219 } |
|
220 // name = NULL; style = 0; |
|
221 return SkFontHost::CreateTypeface(NULL, name, NULL, NULL, |
|
222 (SkTypeface::Style)style); |
|
223 } |
|
224 |
|
225 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { |
|
226 return 0; |
|
227 } |
|
228 |
|
229 #define FONT_CACHE_MEMORY_BUDGET 1 * 1024 * 1024 |
|
230 |
|
231 size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) { |
|
232 if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET) |
|
233 return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET; |
|
234 else |
|
235 return 0; // nothing to do |
|
236 } |
|
237 |
|
238 /////////////////////////////////////////////////////////////////////////////// |
|
239 int SkFontHost::ComputeGammaFlag(const SkPaint& paint) { |
|
240 return 0; |
|
241 } |
|
242 |
|
243 void SkFontHost::GetGammaTables(const uint8_t* tables[2]) { |
|
244 tables[0] = NULL; // black gamma (e.g. exp=1.4) |
|
245 tables[1] = NULL; // white gamma (e.g. exp= 1/1.4) |
|
246 } |
|
247 |
|
248 // static |
|
249 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( |
|
250 uint32_t fontID, |
|
251 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { |
|
252 SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); |
|
253 return NULL; |
|
254 } |
|
255 |
|
256 void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { |
|
257 } |
|
258 |
|
259 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { |
|
260 SkDEBUGFAIL("SkFontHost::CreateScalarContext unimplemented"); |
|
261 return NULL; |
|
262 } |