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
23struct 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
33struct FontFamilyRec {
34    const FontFaceRec*  fFaces;
35    int                 fFaceCount;
36};
37
38const 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
64enum {
65    DEFAULT_FAMILY_INDEX,
66
67    FAMILY_INDEX_COUNT
68};
69
70static 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
75static 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
86struct 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*/
97static 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
122static 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
138const 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
146TRACE_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
187static const FontFaceRec* get_default_face()
188{
189    return &gFamilies[DEFAULT_FAMILY_INDEX].fFaces[DEFAULT_FAMILY_FACE_INDEX];
190}
191
192static 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
204static 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
209class FontFaceRec_Typeface : public SkTypeface {
210public:
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
221static 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
227static 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
234SkTypeface* 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
265SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
266        uint32_t fontID,
267        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
268    sk_throw();  // not implemented
269    return NULL;
270}
271
272SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
273    sk_throw();  // not implemented
274    return NULL;
275}
276
277SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
278    sk_throw();  // not implemented
279    return NULL;
280}
281
282SkStream* SkFontHost::OpenStream(uint32_t fontID) {
283    sk_throw();  // not implemented
284    return NULL;
285}
286
287size_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
293void SkFontHost::Serialize(const SkTypeface* tface, SkWStream* stream) {
294    const FontFaceRec* face = &((const FontFaceRec_Typeface*)tface)->fFace;
295    stream->write(face, sizeof(face));
296}
297
298SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
299    const FontFaceRec* face;
300    stream->read(&face, sizeof(face));
301    return new FontFaceRec_Typeface(*face);
302}
303
304SkScalerContext* 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