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