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