1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkFontHost.h"
11 #include "SkDescriptor.h"
12 #include "SkString.h"
13 #include "SkStream.h"
14 #include <stdio.h>
15
16 /* define this if we can use mmap() to access fonts from the filesystem */
17 #define SK_CAN_USE_MMAP
18
19 #ifndef SK_FONTPATH
20 #define SK_FONTPATH "the complete path for a font file"
21 #endif
22
23 struct FontFaceRec {
24 const char* fFileName;
25 uint8_t fFamilyIndex;
26 SkBool8 fBold;
27 SkBool8 fItalic;
28
29 static const FontFaceRec& FindFace(const FontFaceRec rec[], int count,
30 int isBold, int isItalic);
31 };
32
33 struct FontFamilyRec {
34 const FontFaceRec* fFaces;
35 int fFaceCount;
36 };
37
FindFace(const FontFaceRec rec[],int count,int isBold,int isItalic)38 const FontFaceRec& FontFaceRec::FindFace(const FontFaceRec rec[], int count,
39 int isBold, int isItalic)
40 {
41 SkASSERT(count > 0);
42
43 int i;
44
45 // look for an exact match
46 for (i = 0; i < count; i++) {
47 if (rec[i].fBold == isBold && rec[i].fItalic == isItalic)
48 return rec[i];
49 }
50 // look for a match in the bold field
51 for (i = 0; i < count; i++) {
52 if (rec[i].fBold == isBold)
53 return rec[i];
54 }
55 // look for a normal/regular face
56 for (i = 0; i < count; i++) {
57 if (!rec[i].fBold && !rec[i].fItalic)
58 return rec[i];
59 }
60 // give up
61 return rec[0];
62 }
63
64 enum {
65 DEFAULT_FAMILY_INDEX,
66
67 FAMILY_INDEX_COUNT
68 };
69
70 static const FontFaceRec gDefaultFaces[] = {
71 { SK_FONTPATH, DEFAULT_FAMILY_INDEX, 0, 0 }
72 };
73
74 // This table must be in the same order as the ..._FAMILY_INDEX enum specifies
75 static const FontFamilyRec gFamilies[] = {
76 { gDefaultFaces, SK_ARRAY_COUNT(gDefaultFaces) }
77 };
78
79 #define DEFAULT_FAMILY_INDEX DEFAULT_FAMILY_INDEX
80 #define DEFAULT_FAMILY_FACE_INDEX 0
81
82 ///////////////////////////////////////////////////////////////////////////////
83
84 /* map common "web" font names to our font list */
85
86 struct FontFamilyMatchRec {
87 const char* fLCName;
88 int fFamilyIndex;
89 };
90
91 /* This is a table of synonyms for collapsing font names
92 down to their pseudo-equivalents (i.e. in terms of fonts
93 we actually have.)
94 Keep this sorted by the first field so we can do a binary search.
95 If this gets big, we could switch to a hash...
96 */
97 static const FontFamilyMatchRec gMatches[] = {
98 #if 0
99 { "Ahem", Ahem_FAMILY_INDEX },
100 { "arial", SANS_FAMILY_INDEX },
101 { "courier", MONO_FAMILY_INDEX },
102 { "courier new", MONO_FAMILY_INDEX },
103 { "cursive", SERIF_FAMILY_INDEX },
104 { "fantasy", SERIF_FAMILY_INDEX },
105 { "georgia", SERIF_FAMILY_INDEX },
106 { "goudy", SERIF_FAMILY_INDEX },
107 { "helvetica", SANS_FAMILY_INDEX },
108 { "palatino", SERIF_FAMILY_INDEX },
109 { "tahoma", SANS_FAMILY_INDEX },
110 { "sans-serif", SANS_FAMILY_INDEX },
111 { "serif", SERIF_FAMILY_INDEX },
112 { "times", SERIF_FAMILY_INDEX },
113 { "times new roman", SERIF_FAMILY_INDEX },
114 { "verdana", SANS_FAMILY_INDEX }
115 #endif
116 };
117
118 ///////////////////////////////////////////////////////////////////////////////
119
120 #include "SkTSearch.h"
121
contains_only_ascii(const char s[])122 static bool contains_only_ascii(const char s[])
123 {
124 for (;;)
125 {
126 int c = *s++;
127 if (c == 0)
128 break;
129 if ((c >> 7) != 0)
130 return false;
131 }
132 return true;
133 }
134
135 #define TRACE_FONT_NAME(code)
136 //#define TRACE_FONT_NAME(code) code
137
find_family_rec(const char target[])138 const FontFamilyRec* find_family_rec(const char target[])
139 {
140 int index;
141
142 // If we're asked for a font name that contains non-ascii,
143 // 1) SkStrLCSearch can't handle it
144 // 2) All of our fonts are have ascii names, so...
145
146 TRACE_FONT_NAME(printf("----------------- font request <%s>", target);)
147
148 if (contains_only_ascii(target))
149 {
150 // Search for the font by matching the entire name
151 index = SkStrLCSearch(&gMatches[0].fLCName, SK_ARRAY_COUNT(gMatches),
152 target, sizeof(gMatches[0]));
153 if (index >= 0)
154 {
155 TRACE_FONT_NAME(printf(" found %d\n", index);)
156 return &gFamilies[gMatches[index].fFamilyIndex];
157 }
158 }
159
160 // Sniff for key words...
161
162 #if 0
163 if (strstr(target, "sans") || strstr(target, "Sans"))
164 {
165 TRACE_FONT_NAME(printf(" found sans\n");)
166 return &gFamilies[SANS_FAMILY_INDEX];
167 }
168 if (strstr(target, "serif") || strstr(target, "Serif"))
169 {
170 TRACE_FONT_NAME(printf(" found serif\n");)
171 return &gFamilies[SERIF_FAMILY_INDEX];
172 }
173 if (strstr(target, "mono") || strstr(target, "Mono"))
174 {
175 TRACE_FONT_NAME(printf(" found mono\n");)
176 return &gFamilies[MONO_FAMILY_INDEX];
177 }
178 #endif
179
180 TRACE_FONT_NAME(printf(" use default\n");)
181 // we give up, just give them the default font
182 return &gFamilies[DEFAULT_FAMILY_INDEX];
183 }
184
185 ///////////////////////////////////////////////////////////////////////////////
186
get_default_face()187 static const FontFaceRec* get_default_face()
188 {
189 return &gFamilies[DEFAULT_FAMILY_INDEX].fFaces[DEFAULT_FAMILY_FACE_INDEX];
190 }
191
get_style(const FontFaceRec & face)192 static SkTypeface::Style get_style(const FontFaceRec& face) {
193 int style = 0;
194 if (face.fBold) {
195 style |= SkTypeface::kBold;
196 }
197 if (face.fItalic) {
198 style |= SkTypeface::kItalic;
199 }
200 return static_cast<SkTypeface::Style>(style);
201 }
202
203 // This global const reference completely identifies the face
get_id(const FontFaceRec & face)204 static uint32_t get_id(const FontFaceRec& face) {
205 uintptr_t id = reinterpret_cast<uintptr_t>(&face);
206 return static_cast<uint32_t>(id);
207 }
208
209 class FontFaceRec_Typeface : public SkTypeface {
210 public:
FontFaceRec_Typeface(const FontFaceRec & face)211 FontFaceRec_Typeface(const FontFaceRec& face) :
212 SkTypeface(get_style(face), get_id(face)),
213 fFace(face)
214 {
215 }
216
217 // This global const reference completely identifies the face
218 const FontFaceRec& fFace;
219 };
220
get_typeface_rec(const SkTypeface * face)221 static const FontFaceRec* get_typeface_rec(const SkTypeface* face)
222 {
223 const FontFaceRec_Typeface* f = (FontFaceRec_Typeface*)face;
224 return f ? &f->fFace : get_default_face();
225 }
226
ptr2uint32(const void * p)227 static uint32_t ptr2uint32(const void* p)
228 {
229 // cast so we avoid warnings on 64bit machines that a ptr difference
230 // which might be 64bits is being trucated from 64 to 32
231 return (uint32_t)((char*)p - (char*)0);
232 }
233
CreateTypeface(const SkTypeface * familyFace,const char familyName[],const void * data,size_t bytelength,SkTypeface::Style style)234 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
235 const char familyName[],
236 const void* data, size_t bytelength,
237 SkTypeface::Style style)
238 {
239 const FontFamilyRec* family;
240
241 if (familyFace)
242 family = &gFamilies[
243 ((FontFaceRec_Typeface*)familyFace)->fFace.fFamilyIndex];
244 else if (familyName)
245 family = find_family_rec(familyName);
246 else
247 family = &gFamilies[DEFAULT_FAMILY_INDEX];
248
249 const FontFaceRec& face = FontFaceRec::FindFace(family->fFaces,
250 family->fFaceCount,
251 (style & SkTypeface::kBold) != 0,
252 (style & SkTypeface::kItalic) != 0);
253
254 // if we're returning our input parameter, no need to create a new instance
255 if (familyFace != NULL &&
256 &((FontFaceRec_Typeface*)familyFace)->fFace == &face)
257 {
258 familyFace->ref();
259 return (SkTypeface*)familyFace;
260 }
261 return SkNEW_ARGS(FontFaceRec_Typeface, (face));
262 }
263
264 // static
GetAdvancedTypefaceMetrics(uint32_t fontID,SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo)265 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
266 uint32_t fontID,
267 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
268 sk_throw(); // not implemented
269 return NULL;
270 }
271
CreateTypefaceFromStream(SkStream * stream)272 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
273 sk_throw(); // not implemented
274 return NULL;
275 }
276
CreateTypefaceFromFile(const char path[])277 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
278 sk_throw(); // not implemented
279 return NULL;
280 }
281
OpenStream(uint32_t fontID)282 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
283 sk_throw(); // not implemented
284 return NULL;
285 }
286
GetFileName(SkFontID fontID,char path[],size_t length,int32_t * index)287 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
288 int32_t* index) {
289 SkDebugf("SkFontHost::GetFileName unimplemented\n");
290 return 0;
291 }
292
Serialize(const SkTypeface * tface,SkWStream * stream)293 void SkFontHost::Serialize(const SkTypeface* tface, SkWStream* stream) {
294 const FontFaceRec* face = &((const FontFaceRec_Typeface*)tface)->fFace;
295 stream->write(face, sizeof(face));
296 }
297
Deserialize(SkStream * stream)298 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
299 const FontFaceRec* face;
300 stream->read(&face, sizeof(face));
301 return new FontFaceRec_Typeface(*face);
302 }
303
CreateFallbackScalerContext(const SkScalerContext::Rec & rec)304 SkScalerContext* SkFontHost::CreateFallbackScalerContext(
305 const SkScalerContext::Rec& rec)
306 {
307 const FontFaceRec* face = get_default_face();
308
309 SkAutoDescriptor ad(sizeof(rec) + sizeof(face) +
310 SkDescriptor::ComputeOverhead(2));
311 SkDescriptor* desc = ad.getDesc();
312 SkScalerContext::Rec* newRec;
313
314 desc->init();
315 newRec = reinterpret_cast<SkScalerContext::Rec*>(
316 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec));
317 newRec->fFontID = get_id(*face);
318 desc->computeChecksum();
319
320 return SkFontHost::CreateScalerContext(desc);
321 }
322
323