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[],SkTypeface::Style style)234 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
235 const char familyName[],
236 SkTypeface::Style style)
237 {
238 const FontFamilyRec* family;
239
240 if (familyFace)
241 family = &gFamilies[
242 ((FontFaceRec_Typeface*)familyFace)->fFace.fFamilyIndex];
243 else if (familyName)
244 family = find_family_rec(familyName);
245 else
246 family = &gFamilies[DEFAULT_FAMILY_INDEX];
247
248 const FontFaceRec& face = FontFaceRec::FindFace(family->fFaces,
249 family->fFaceCount,
250 (style & SkTypeface::kBold) != 0,
251 (style & SkTypeface::kItalic) != 0);
252
253 // if we're returning our input parameter, no need to create a new instance
254 if (familyFace != NULL &&
255 &((FontFaceRec_Typeface*)familyFace)->fFace == &face)
256 {
257 familyFace->ref();
258 return (SkTypeface*)familyFace;
259 }
260 return SkNEW_ARGS(FontFaceRec_Typeface, (face));
261 }
262
263 // static
GetAdvancedTypefaceMetrics(uint32_t fontID,SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,const uint32_t * glyphIDs,uint32_t glyphIDsCount)264 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
265 uint32_t fontID,
266 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
267 const uint32_t* glyphIDs,
268 uint32_t glyphIDsCount) {
269 sk_throw(); // not implemented
270 return NULL;
271 }
272
CreateTypefaceFromStream(SkStream * stream)273 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
274 sk_throw(); // not implemented
275 return NULL;
276 }
277
CreateTypefaceFromFile(const char path[])278 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
279 sk_throw(); // not implemented
280 return NULL;
281 }
282
OpenStream(uint32_t fontID)283 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
284 sk_throw(); // not implemented
285 return NULL;
286 }
287
GetFileName(SkFontID fontID,char path[],size_t length,int32_t * index)288 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
289 int32_t* index) {
290 SkDebugf("SkFontHost::GetFileName unimplemented\n");
291 return 0;
292 }
293
Serialize(const SkTypeface * tface,SkWStream * stream)294 void SkFontHost::Serialize(const SkTypeface* tface, SkWStream* stream) {
295 const FontFaceRec* face = &((const FontFaceRec_Typeface*)tface)->fFace;
296 stream->write(face, sizeof(face));
297 }
298
Deserialize(SkStream * stream)299 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
300 const FontFaceRec* face;
301 stream->read(&face, sizeof(face));
302 return new FontFaceRec_Typeface(*face);
303 }
304
CreateFallbackScalerContext(const SkScalerContext::Rec & rec)305 SkScalerContext* SkFontHost::CreateFallbackScalerContext(
306 const SkScalerContext::Rec& rec)
307 {
308 const FontFaceRec* face = get_default_face();
309
310 SkAutoDescriptor ad(sizeof(rec) + sizeof(face) +
311 SkDescriptor::ComputeOverhead(2));
312 SkDescriptor* desc = ad.getDesc();
313 SkScalerContext::Rec* newRec;
314
315 desc->init();
316 newRec = reinterpret_cast<SkScalerContext::Rec*>(
317 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec));
318 newRec->fFontID = get_id(*face);
319 desc->computeChecksum();
320
321 return SkFontHost::CreateScalerContext(desc);
322 }
323