OLD | NEW |
| (Empty) |
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, fami
lyName)) { | |
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, n
ame); | |
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 fontI
D, | |
251 SkAdvancedType
faceMetrics::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 } | |
OLD | NEW |