• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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