Home | History | Annotate | Download | only in ports
      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 
     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 
    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 
    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 
    187 static const FontFaceRec* get_default_face()
    188 {
    189     return &gFamilies[DEFAULT_FAMILY_INDEX].fFaces[DEFAULT_FAMILY_FACE_INDEX];
    190 }
    191 
    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
    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:
    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 
    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 
    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 
    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
    265 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
    266         uint32_t fontID,
    267         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
    268     sk_throw();  // not implemented
    269     return NULL;
    270 }
    271 
    272 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
    273     sk_throw();  // not implemented
    274     return NULL;
    275 }
    276 
    277 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
    278     sk_throw();  // not implemented
    279     return NULL;
    280 }
    281 
    282 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
    283     sk_throw();  // not implemented
    284     return NULL;
    285 }
    286 
    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 
    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 
    298 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
    299     const FontFaceRec* face;
    300     stream->read(&face, sizeof(face));
    301     return new FontFaceRec_Typeface(*face);
    302 }
    303 
    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