| OLD | NEW |
| 1 | |
| 2 /* | 1 /* |
| 3 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 4 * | 3 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 7 */ | 6 */ |
| 8 | 7 |
| 9 | |
| 10 #include "SkFontHost.h" | 8 #include "SkFontHost.h" |
| 11 #include "SkFontHost_FreeType_common.h" | 9 #include "SkFontHost_FreeType_common.h" |
| 12 #include "SkFontDescriptor.h" | 10 #include "SkFontDescriptor.h" |
| 11 #include "SkFontMgr.h" |
| 13 #include "SkDescriptor.h" | 12 #include "SkDescriptor.h" |
| 14 #include "SkOSFile.h" | 13 #include "SkOSFile.h" |
| 15 #include "SkPaint.h" | 14 #include "SkPaint.h" |
| 16 #include "SkString.h" | 15 #include "SkString.h" |
| 17 #include "SkStream.h" | 16 #include "SkStream.h" |
| 18 #include "SkThread.h" | 17 #include "SkThread.h" |
| 19 #include "SkTSearch.h" | 18 #include "SkTSearch.h" |
| 19 #include "SkTypefaceCache.h" |
| 20 #include "SkTArray.h" |
| 21 |
| 22 #include <limits> |
| 20 | 23 |
| 21 #ifndef SK_FONT_FILE_PREFIX | 24 #ifndef SK_FONT_FILE_PREFIX |
| 22 #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" | 25 # define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" |
| 23 #endif | 26 #endif |
| 24 #ifndef SK_FONT_FILE_DIR_SEPERATOR | 27 #ifndef SK_FONT_FILE_DIR_SEPERATOR |
| 25 #define SK_FONT_FILE_DIR_SEPERATOR "/" | 28 # define SK_FONT_FILE_DIR_SEPERATOR "/" |
| 26 #endif | 29 #endif |
| 27 | 30 |
| 28 bool find_name_and_attributes(SkStream* stream, SkString* name, | 31 bool find_name_and_attributes(SkStream* stream, SkString* name, |
| 29 SkTypeface::Style* style, bool* isFixedPitch); | 32 SkTypeface::Style* style, bool* isFixedPitch); |
| 30 | 33 |
| 31 /////////////////////////////////////////////////////////////////////////////// | 34 /////////////////////////////////////////////////////////////////////////////// |
| 32 | 35 |
| 33 struct FamilyRec; | 36 /** The base SkTypeface implementation for the custom font manager. */ |
| 34 | 37 class SkTypeface_Custom : public SkTypeface_FreeType { |
| 35 /* This guy holds a mapping of a name -> family, used for looking up fonts. | |
| 36 Since it is stored in a stretchy array that doesn't preserve object | |
| 37 semantics, we don't use constructor/destructors, but just have explicit | |
| 38 helpers to manage our internal bookkeeping. | |
| 39 */ | |
| 40 struct NameFamilyPair { | |
| 41 const char* fName; // we own this | |
| 42 FamilyRec* fFamily; // we don't own this, we just reference it | |
| 43 | |
| 44 void construct(const char name[], FamilyRec* family) | |
| 45 { | |
| 46 fName = strdup(name); | |
| 47 fFamily = family; // we don't own this, so just record the referene | |
| 48 } | |
| 49 void destruct() | |
| 50 { | |
| 51 free((char*)fName); | |
| 52 // we don't own family, so just ignore our reference | |
| 53 } | |
| 54 }; | |
| 55 | |
| 56 // we use atomic_inc to grow this for each typeface we create | |
| 57 static int32_t gUniqueFontID; | |
| 58 | |
| 59 // this is the mutex that protects these globals | |
| 60 SK_DECLARE_STATIC_MUTEX(gFamilyMutex); | |
| 61 static FamilyRec* gFamilyHead; | |
| 62 static SkTDArray<NameFamilyPair> gNameList; | |
| 63 | |
| 64 struct FamilyRec { | |
| 65 FamilyRec* fNext; | |
| 66 SkTypeface* fFaces[4]; | |
| 67 | |
| 68 FamilyRec() | |
| 69 { | |
| 70 fNext = gFamilyHead; | |
| 71 memset(fFaces, 0, sizeof(fFaces)); | |
| 72 gFamilyHead = this; | |
| 73 } | |
| 74 }; | |
| 75 | |
| 76 static SkTypeface* find_best_face(const FamilyRec* family, | |
| 77 SkTypeface::Style style) { | |
| 78 SkTypeface* const* faces = family->fFaces; | |
| 79 | |
| 80 if (faces[style] != NULL) { // exact match | |
| 81 return faces[style]; | |
| 82 } | |
| 83 // look for a matching bold | |
| 84 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); | |
| 85 if (faces[style] != NULL) { | |
| 86 return faces[style]; | |
| 87 } | |
| 88 // look for the plain | |
| 89 if (faces[SkTypeface::kNormal] != NULL) { | |
| 90 return faces[SkTypeface::kNormal]; | |
| 91 } | |
| 92 // look for anything | |
| 93 for (int i = 0; i < 4; i++) { | |
| 94 if (faces[i] != NULL) { | |
| 95 return faces[i]; | |
| 96 } | |
| 97 } | |
| 98 // should never get here, since the faces list should not be empty | |
| 99 SkDEBUGFAIL("faces list is empty"); | |
| 100 return NULL; | |
| 101 } | |
| 102 | |
| 103 static FamilyRec* find_family(const SkTypeface* member) { | |
| 104 FamilyRec* curr = gFamilyHead; | |
| 105 while (curr != NULL) { | |
| 106 for (int i = 0; i < 4; i++) { | |
| 107 if (curr->fFaces[i] == member) { | |
| 108 return curr; | |
| 109 } | |
| 110 } | |
| 111 curr = curr->fNext; | |
| 112 } | |
| 113 return NULL; | |
| 114 } | |
| 115 | |
| 116 /* Remove reference to this face from its family. If the resulting family | |
| 117 is empty (has no faces), return that family, otherwise return NULL | |
| 118 */ | |
| 119 static FamilyRec* remove_from_family(const SkTypeface* face) { | |
| 120 FamilyRec* family = find_family(face); | |
| 121 SkASSERT(family->fFaces[face->style()] == face); | |
| 122 family->fFaces[face->style()] = NULL; | |
| 123 | |
| 124 for (int i = 0; i < 4; i++) { | |
| 125 if (family->fFaces[i] != NULL) { // family is non-empty | |
| 126 return NULL; | |
| 127 } | |
| 128 } | |
| 129 return family; // return the empty family | |
| 130 } | |
| 131 | |
| 132 // maybe we should make FamilyRec be doubly-linked | |
| 133 static void detach_and_delete_family(FamilyRec* family) { | |
| 134 FamilyRec* curr = gFamilyHead; | |
| 135 FamilyRec* prev = NULL; | |
| 136 | |
| 137 while (curr != NULL) { | |
| 138 FamilyRec* next = curr->fNext; | |
| 139 if (curr == family) { | |
| 140 if (prev == NULL) { | |
| 141 gFamilyHead = next; | |
| 142 } else { | |
| 143 prev->fNext = next; | |
| 144 } | |
| 145 SkDELETE(family); | |
| 146 return; | |
| 147 } | |
| 148 prev = curr; | |
| 149 curr = next; | |
| 150 } | |
| 151 SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); | |
| 152 } | |
| 153 | |
| 154 static const char* find_family_name(const SkTypeface* familyMember) { | |
| 155 const FamilyRec* familyRec = find_family(familyMember); | |
| 156 for (int i = 0; i < gNameList.count(); i++) { | |
| 157 if (gNameList[i].fFamily == familyRec) { | |
| 158 return gNameList[i].fName; | |
| 159 } | |
| 160 } | |
| 161 return NULL; | |
| 162 } | |
| 163 | |
| 164 static FamilyRec* find_familyrec(const char name[]) { | |
| 165 const NameFamilyPair* list = gNameList.begin(); | |
| 166 int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, | |
| 167 sizeof(list[0])); | |
| 168 return index >= 0 ? list[index].fFamily : NULL; | |
| 169 } | |
| 170 | |
| 171 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { | |
| 172 FamilyRec* rec = find_familyrec(name); | |
| 173 return rec ? find_best_face(rec, style) : NULL; | |
| 174 } | |
| 175 | |
| 176 static SkTypeface* find_typeface(const SkTypeface* familyMember, | |
| 177 SkTypeface::Style style) { | |
| 178 const FamilyRec* family = find_family(familyMember); | |
| 179 return family ? find_best_face(family, style) : NULL; | |
| 180 } | |
| 181 | |
| 182 static void add_name(const char name[], FamilyRec* family) { | |
| 183 SkAutoAsciiToLC tolc(name); | |
| 184 name = tolc.lc(); | |
| 185 | |
| 186 NameFamilyPair* list = gNameList.begin(); | |
| 187 int count = gNameList.count(); | |
| 188 | |
| 189 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); | |
| 190 | |
| 191 if (index < 0) { | |
| 192 list = gNameList.insert(~index); | |
| 193 list->construct(name, family); | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 static void remove_from_names(FamilyRec* emptyFamily) { | |
| 198 #ifdef SK_DEBUG | |
| 199 for (int i = 0; i < 4; i++) { | |
| 200 SkASSERT(emptyFamily->fFaces[i] == NULL); | |
| 201 } | |
| 202 #endif | |
| 203 | |
| 204 SkTDArray<NameFamilyPair>& list = gNameList; | |
| 205 | |
| 206 // must go backwards when removing | |
| 207 for (int i = list.count() - 1; i >= 0; --i) { | |
| 208 NameFamilyPair* pair = &list[i]; | |
| 209 if (pair->fFamily == emptyFamily) { | |
| 210 pair->destruct(); | |
| 211 list.remove(i); | |
| 212 } | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 /////////////////////////////////////////////////////////////////////////////// | |
| 217 | |
| 218 class FamilyTypeface : public SkTypeface_FreeType { | |
| 219 public: | 38 public: |
| 220 FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedPit
ch) | 39 SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkStri
ng familyName) |
| 221 : INHERITED(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedPitch) { | 40 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) |
| 222 fIsSysFont = sysFont; | 41 , fIsSysFont(sysFont), fFamilyName(familyName) |
| 223 | 42 { } |
| 224 SkAutoMutexAcquire ac(gFamilyMutex); | |
| 225 | |
| 226 if (NULL == family) { | |
| 227 family = SkNEW(FamilyRec); | |
| 228 } | |
| 229 family->fFaces[style] = this; | |
| 230 fFamilyRec = family; // just record it so we can return it if asked | |
| 231 } | |
| 232 | |
| 233 virtual ~FamilyTypeface() { | |
| 234 SkAutoMutexAcquire ac(gFamilyMutex); | |
| 235 | |
| 236 // remove us from our family. If the family is now empty, we return | |
| 237 // that and then remove that family from the name list | |
| 238 FamilyRec* family = remove_from_family(this); | |
| 239 if (NULL != family) { | |
| 240 remove_from_names(family); | |
| 241 detach_and_delete_family(family); | |
| 242 } | |
| 243 } | |
| 244 | 43 |
| 245 bool isSysFont() const { return fIsSysFont; } | 44 bool isSysFont() const { return fIsSysFont; } |
| 246 FamilyRec* getFamily() const { return fFamilyRec; } | |
| 247 | 45 |
| 248 virtual const char* getUniqueString() const = 0; | 46 virtual const char* getUniqueString() const = 0; |
| 249 | 47 |
| 250 protected: | 48 protected: |
| 251 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; | 49 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) cons
t SK_OVERRIDE { |
| 252 virtual SkTypeface* onRefMatchingStyle(Style styleBits) const SK_OVERRIDE; | 50 desc->setFamilyName(fFamilyName.c_str()); |
| 51 desc->setFontFileName(this->getUniqueString()); |
| 52 *isLocal = !this->isSysFont(); |
| 53 } |
| 253 | 54 |
| 254 private: | 55 private: |
| 255 FamilyRec* fFamilyRec; // we don't own this, just point to it | 56 bool fIsSysFont; |
| 256 bool fIsSysFont; | 57 SkString fFamilyName; |
| 257 | 58 |
| 258 typedef SkTypeface_FreeType INHERITED; | 59 typedef SkTypeface_FreeType INHERITED; |
| 259 }; | 60 }; |
| 260 | 61 |
| 261 /////////////////////////////////////////////////////////////////////////////// | 62 /** The empty SkTypeface implementation for the custom font manager. |
| 63 * Used as the last resort fallback typeface. |
| 64 */ |
| 65 class SkTypeface_Empty : public SkTypeface_Custom { |
| 66 public: |
| 67 SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, true, false, SkString())
{} |
| 262 | 68 |
| 263 /* This subclass is just a place holder for when we have no fonts available. | 69 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } |
| 264 It exists so that our globals (e.g. gFamilyHead) that expect *something* | |
| 265 will not be null. | |
| 266 */ | |
| 267 class EmptyTypeface : public FamilyTypeface { | |
| 268 public: | |
| 269 EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {} | |
| 270 | |
| 271 virtual const char* getUniqueString() SK_OVERRIDE const { return NULL; } | |
| 272 | 70 |
| 273 protected: | 71 protected: |
| 274 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } | 72 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } |
| 275 | 73 |
| 276 private: | 74 private: |
| 277 typedef FamilyTypeface INHERITED; | 75 typedef SkTypeface_Custom INHERITED; |
| 278 }; | 76 }; |
| 279 | 77 |
| 280 class StreamTypeface : public FamilyTypeface { | 78 /** The stream SkTypeface implementation for the custom font manager. */ |
| 79 class SkTypeface_Stream : public SkTypeface_Custom { |
| 281 public: | 80 public: |
| 282 StreamTypeface(Style style, bool sysFont, FamilyRec* family, | 81 SkTypeface_Stream(Style style, bool sysFont, SkStream* stream, |
| 283 SkStream* stream, bool isFixedPitch) | 82 bool isFixedPitch, const SkString familyName) |
| 284 : INHERITED(style, sysFont, family, isFixedPitch) { | 83 : INHERITED(style, sysFont, isFixedPitch, familyName) |
| 285 stream->ref(); | 84 , fStream(SkRef(stream)) |
| 286 fStream = stream; | 85 { } |
| 287 } | |
| 288 virtual ~StreamTypeface() { | |
| 289 fStream->unref(); | |
| 290 } | |
| 291 | 86 |
| 292 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } | 87 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } |
| 293 | 88 |
| 294 protected: | 89 protected: |
| 295 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | 90 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { |
| 296 *ttcIndex = 0; | 91 *ttcIndex = 0; |
| 297 fStream->ref(); | 92 return SkRef(fStream.get()); |
| 298 return fStream; | |
| 299 } | 93 } |
| 300 | 94 |
| 301 private: | 95 private: |
| 302 SkStream* fStream; | 96 SkAutoTUnref<SkStream> fStream; |
| 303 | 97 |
| 304 typedef FamilyTypeface INHERITED; | 98 typedef SkTypeface_Custom INHERITED; |
| 305 }; | 99 }; |
| 306 | 100 |
| 307 class FileTypeface : public FamilyTypeface { | 101 /** The file SkTypeface implementation for the custom font manager. */ |
| 102 class SkTypeface_File : public SkTypeface_Custom { |
| 308 public: | 103 public: |
| 309 FileTypeface(Style style, bool sysFont, FamilyRec* family, | 104 SkTypeface_File(Style style, bool sysFont, const char path[], |
| 310 const char path[], bool isFixedPitch) | 105 bool isFixedPitch, const SkString familyName) |
| 311 : INHERITED(style, sysFont, family, isFixedPitch) { | 106 : INHERITED(style, sysFont, isFixedPitch, familyName) |
| 312 fPath.set(path); | 107 , fPath(path) |
| 313 } | 108 { } |
| 314 | 109 |
| 315 virtual const char* getUniqueString() const SK_OVERRIDE { | 110 virtual const char* getUniqueString() const SK_OVERRIDE { |
| 316 const char* str = strrchr(fPath.c_str(), '/'); | 111 const char* str = strrchr(fPath.c_str(), '/'); |
| 317 if (str) { | 112 if (str) { |
| 318 str += 1; // skip the '/' | 113 str += 1; // skip the '/' |
| 319 } | 114 } |
| 320 return str; | 115 return str; |
| 321 } | 116 } |
| 322 | 117 |
| 323 protected: | 118 protected: |
| 324 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | 119 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { |
| 325 *ttcIndex = 0; | 120 *ttcIndex = 0; |
| 326 return SkStream::NewFromFile(fPath.c_str()); | 121 return SkStream::NewFromFile(fPath.c_str()); |
| 327 } | 122 } |
| 328 | 123 |
| 329 private: | 124 private: |
| 330 SkString fPath; | 125 SkString fPath; |
| 331 | 126 |
| 332 typedef FamilyTypeface INHERITED; | 127 typedef SkTypeface_Custom INHERITED; |
| 333 }; | 128 }; |
| 334 | 129 |
| 335 /////////////////////////////////////////////////////////////////////////////// | 130 /////////////////////////////////////////////////////////////////////////////// |
| 336 /////////////////////////////////////////////////////////////////////////////// | 131 |
| 337 | 132 /** |
| 338 static bool get_name_and_style(const char path[], SkString* name, | 133 * SkFontStyleSet_Custom |
| 339 SkTypeface::Style* style, bool* isFixedPitch) { | 134 * |
| 340 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | 135 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. |
| 341 if (stream.get()) { | 136 */ |
| 342 return find_name_and_attributes(stream, name, style, isFixedPitch); | 137 class SkFontStyleSet_Custom : public SkFontStyleSet { |
| 343 } else { | 138 public: |
| 344 SkDebugf("---- failed to open <%s> as a font\n", path); | 139 SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) {
} |
| 345 return false; | 140 |
| 346 } | 141 virtual int count() SK_OVERRIDE { |
| 347 } | 142 return fStyles.count(); |
| 348 | 143 } |
| 349 // these globals are assigned (once) by load_system_fonts() | 144 |
| 350 static SkTypeface* gFallBackTypeface; | 145 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER
RIDE { |
| 351 static FamilyRec* gDefaultFamily; | 146 SkASSERT(index < fStyles.count()); |
| 352 static SkTypeface* gDefaultNormal; | 147 bool bold = fStyles[index]->isBold(); |
| 353 | 148 bool italic = fStyles[index]->isItalic(); |
| 354 static void load_directory_fonts(const SkString& directory, unsigned int* count)
{ | 149 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNo
rmal_Weight, |
| 355 SkOSFile::Iter iter(directory.c_str(), ".ttf"); | 150 SkFontStyle::kNormal_Width, |
| 356 SkString name; | 151 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::
kUpright_Slant); |
| 357 | 152 name->reset(); |
| 358 while (iter.next(&name, false)) { | 153 } |
| 359 SkString filename(directory); | 154 |
| 360 filename.append(name); | 155 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { |
| 156 SkASSERT(index < fStyles.count()); |
| 157 return SkRef(fStyles[index].get()); |
| 158 } |
| 159 |
| 160 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid
ate) { |
| 161 int score = 0; |
| 162 score += (pattern.width() - candidate.width()) * 100; |
| 163 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; |
| 164 score += pattern.weight() - candidate.weight(); |
| 165 return score; |
| 166 } |
| 167 |
| 168 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { |
| 169 if (0 == fStyles.count()) { |
| 170 return NULL; |
| 171 } |
| 172 |
| 173 SkTypeface_Custom* closest = fStyles[0]; |
| 174 int minScore = std::numeric_limits<int>::max(); |
| 175 for (int i = 0; i < fStyles.count(); ++i) { |
| 176 bool bold = fStyles[i]->isBold(); |
| 177 bool italic = fStyles[i]->isItalic(); |
| 178 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight |
| 179 : SkFontStyle::kNormal_Weight, |
| 180 SkFontStyle::kNormal_Width, |
| 181 italic ? SkFontStyle::kItalic_Slant |
| 182 : SkFontStyle::kUpright_Slant
); |
| 183 |
| 184 int score = match_score(pattern, style); |
| 185 if (score < minScore) { |
| 186 closest = fStyles[i]; |
| 187 minScore = score; |
| 188 } |
| 189 } |
| 190 return SkRef(closest); |
| 191 } |
| 192 |
| 193 private: |
| 194 SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles; |
| 195 SkString fFamilyName; |
| 196 |
| 197 void appendTypeface(SkTypeface_Custom* typeface) { |
| 198 fStyles.push_back().reset(typeface); |
| 199 } |
| 200 |
| 201 friend class SkFontMgr_Custom; |
| 202 }; |
| 203 |
| 204 /** |
| 205 * SkFontMgr_Custom |
| 206 * |
| 207 * This class is essentially a collection of SkFontStyleSet_Custom, |
| 208 * one SkFontStyleSet_Custom for each family. This class may be modified |
| 209 * to load fonts from any source by changing the initialization. |
| 210 */ |
| 211 class SkFontMgr_Custom : public SkFontMgr { |
| 212 public: |
| 213 SkFontMgr_Custom(const char* dir) { |
| 214 this->load_system_fonts(dir); |
| 215 } |
| 216 |
| 217 protected: |
| 218 virtual int onCountFamilies() SK_OVERRIDE { |
| 219 return fFamilies.count(); |
| 220 } |
| 221 |
| 222 virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE { |
| 223 SkASSERT(index < fFamilies.count()); |
| 224 familyName->set(fFamilies[index]->fFamilyName); |
| 225 } |
| 226 |
| 227 virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) SK_OVERRIDE { |
| 228 SkASSERT(index < fFamilies.count()); |
| 229 return SkRef(fFamilies[index].get()); |
| 230 } |
| 231 |
| 232 virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) SK_OVE
RRIDE { |
| 233 for (int i = 0; i < fFamilies.count(); ++i) { |
| 234 if (fFamilies[i]->fFamilyName.equals(familyName)) { |
| 235 return SkRef(fFamilies[i].get()); |
| 236 } |
| 237 } |
| 238 return NULL; |
| 239 } |
| 240 |
| 241 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
| 242 const SkFontStyle& fontStyle) SK_OVER
RIDE |
| 243 { |
| 244 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); |
| 245 return sset->matchStyle(fontStyle); |
| 246 } |
| 247 |
| 248 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, |
| 249 const SkFontStyle& fontStyle) SK_OVERRI
DE |
| 250 { |
| 251 for (int i = 0; i < fFamilies.count(); ++i) { |
| 252 for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { |
| 253 if (fFamilies[i]->fStyles[j] == familyMember) { |
| 254 return fFamilies[i]->matchStyle(fontStyle); |
| 255 } |
| 256 } |
| 257 } |
| 258 return NULL; |
| 259 } |
| 260 |
| 261 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE
{ |
| 262 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); |
| 263 return this->createFromStream(stream, ttcIndex); |
| 264 } |
| 265 |
| 266 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OV
ERRIDE { |
| 267 if (NULL == stream || stream->getLength() <= 0) { |
| 268 SkDELETE(stream); |
| 269 return NULL; |
| 270 } |
| 361 | 271 |
| 362 bool isFixedPitch; | 272 bool isFixedPitch; |
| 363 SkString realname; | 273 SkTypeface::Style style; |
| 364 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized wa
rning | 274 SkString name; |
| 365 | 275 if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) { |
| 366 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPit
ch)) { | 276 return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedP
itch, name)); |
| 367 SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); | 277 } else { |
| 368 continue; | 278 return NULL; |
| 369 } | 279 } |
| 370 | 280 } |
| 371 FamilyRec* family = find_familyrec(realname.c_str()); | 281 |
| 372 if (family && family->fFaces[style]) { | 282 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVE
RRIDE { |
| 373 continue; | 283 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
| 374 } | 284 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; |
| 375 | 285 } |
| 376 // this constructor puts us into the global gFamilyHead llist | 286 |
| 377 FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, | 287 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
| 378 (style, | 288 unsigned styleBits) SK_OVERRIDE |
| 379 true, // system-font (cannot delete) | 289 { |
| 380 family, // what family to join | 290 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; |
| 381 filename.c_str(), | 291 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold |
| 382 isFixedPitch) // filename | 292 ? SkFontStyle::kBold_Weight |
| 383 ); | 293 : SkFontStyle::kNormal_Weight, |
| 384 | 294 SkFontStyle::kNormal_Width, |
| 385 if (NULL == family) { | 295 oldStyle & SkTypeface::kItalic |
| 386 add_name(realname.c_str(), tf->getFamily()); | 296 ? SkFontStyle::kItalic_Slant |
| 387 } | 297 : SkFontStyle::kUpright_Slant); |
| 388 *count += 1; | 298 SkTypeface* tf = NULL; |
| 389 } | 299 |
| 390 | 300 if (NULL != familyName) { |
| 391 SkOSFile::Iter dirIter(directory.c_str()); | 301 tf = this->onMatchFamilyStyle(familyName, style); |
| 392 while (dirIter.next(&name, true)) { | 302 } |
| 393 if (name.startsWith(".")) { | 303 |
| 394 continue; | 304 if (NULL == tf) { |
| 395 } | 305 tf = gDefaultFamily->matchStyle(style); |
| 396 SkString dirname(directory); | 306 } |
| 397 dirname.append(name); | 307 |
| 398 dirname.append(SK_FONT_FILE_DIR_SEPERATOR); | 308 return SkSafeRef(tf); |
| 399 load_directory_fonts(dirname, count); | 309 } |
| 400 } | 310 |
| 401 } | 311 private: |
| 402 | 312 |
| 403 static void load_system_fonts() { | 313 static bool get_name_and_style(const char path[], SkString* name, |
| 404 // check if we've already be called | 314 SkTypeface::Style* style, bool* isFixedPitch)
{ |
| 405 if (NULL != gDefaultNormal) { | 315 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
| 406 return; | 316 if (stream.get()) { |
| 407 } | 317 return find_name_and_attributes(stream, name, style, isFixedPitch); |
| 408 | 318 } else { |
| 409 SkString baseDirectory(SK_FONT_FILE_PREFIX); | 319 SkDebugf("---- failed to open <%s> as a font\n", path); |
| 410 unsigned int count = 0; | 320 return false; |
| 411 load_directory_fonts(baseDirectory, &count); | 321 } |
| 412 | 322 } |
| 413 if (0 == count) { | 323 |
| 414 SkNEW(EmptyTypeface); | 324 void load_directory_fonts(const SkString& directory) { |
| 415 } | 325 SkOSFile::Iter iter(directory.c_str(), ".ttf"); |
| 416 | 326 SkString name; |
| 417 // do this after all fonts are loaded. This is our default font, and it | 327 |
| 418 // acts as a sentinel so we only execute load_system_fonts() once | 328 while (iter.next(&name, false)) { |
| 419 static const char* gDefaultNames[] = { | 329 SkString filename(directory); |
| 420 "Arial", "Verdana", "Times New Roman", NULL | 330 filename.append(name); |
| 421 }; | 331 |
| 422 const char** names = gDefaultNames; | 332 bool isFixedPitch; |
| 423 while (*names) { | 333 SkString realname; |
| 424 SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); | 334 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialize
d warning |
| 425 if (tf) { | 335 |
| 336 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixe
dPitch)) { |
| 337 SkDebugf("------ can't load <%s> as a font\n", filename.c_str())
; |
| 338 continue; |
| 339 } |
| 340 |
| 341 SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( |
| 342 style, |
| 343 true, // system-font (cannot de
lete) |
| 344 filename.c_str(), |
| 345 isFixedPitch, |
| 346 realname)); |
| 347 |
| 348 SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str())
; |
| 349 if (NULL == addTo) { |
| 350 addTo = new SkFontStyleSet_Custom(realname); |
| 351 fFamilies.push_back().reset(addTo); |
| 352 } |
| 353 addTo->appendTypeface(tf); |
| 354 } |
| 355 |
| 356 SkOSFile::Iter dirIter(directory.c_str()); |
| 357 while (dirIter.next(&name, true)) { |
| 358 if (name.startsWith(".")) { |
| 359 continue; |
| 360 } |
| 361 SkString dirname(directory); |
| 362 dirname.append(name); |
| 363 dirname.append(SK_FONT_FILE_DIR_SEPERATOR); |
| 364 load_directory_fonts(dirname); |
| 365 } |
| 366 } |
| 367 |
| 368 void load_system_fonts(const char* dir) { |
| 369 SkString baseDirectory(dir); |
| 370 load_directory_fonts(baseDirectory); |
| 371 |
| 372 if (fFamilies.empty()) { |
| 373 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()
); |
| 374 fFamilies.push_back().reset(family); |
| 375 family->appendTypeface(SkNEW(SkTypeface_Empty)); |
| 376 } |
| 377 |
| 378 // Try to pick a default font. |
| 379 static const char* gDefaultNames[] = { |
| 380 "Arial", "Verdana", "Times New Roman", NULL |
| 381 }; |
| 382 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { |
| 383 SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]); |
| 384 if (NULL == set) { |
| 385 continue; |
| 386 } |
| 387 |
| 388 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_We
ight, |
| 389 SkFontStyle::kNormal_Wi
dth, |
| 390 SkFontStyle::kUpright_S
lant)); |
| 391 if (NULL == tf) { |
| 392 continue; |
| 393 } |
| 394 |
| 395 gDefaultFamily = set; |
| 426 gDefaultNormal = tf; | 396 gDefaultNormal = tf; |
| 427 break; | 397 break; |
| 428 } | 398 } |
| 429 } | 399 if (NULL == gDefaultNormal) { |
| 430 // check if we found *something* | 400 gDefaultFamily = fFamilies[0]; |
| 431 if (NULL == gDefaultNormal) { | 401 gDefaultNormal = gDefaultFamily->fStyles[0]; |
| 432 if (NULL == gFamilyHead) { | 402 } |
| 433 sk_throw(); | 403 } |
| 434 } | 404 |
| 435 for (int i = 0; i < 4; i++) { | 405 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies; |
| 436 if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { | 406 SkFontStyleSet_Custom* gDefaultFamily; |
| 437 break; | 407 SkTypeface* gDefaultNormal; |
| 438 } | 408 }; |
| 439 } | 409 |
| 440 } | 410 SkFontMgr* SkFontMgr::Factory() { |
| 441 if (NULL == gDefaultNormal) { | 411 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX); |
| 442 sk_throw(); | |
| 443 } | |
| 444 gFallBackTypeface = gDefaultNormal; | |
| 445 gDefaultFamily = find_family(gDefaultNormal); | |
| 446 } | 412 } |
| 447 | |
| 448 /////////////////////////////////////////////////////////////////////////////// | |
| 449 | |
| 450 void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | |
| 451 bool* isLocalStream) const { | |
| 452 desc->setFamilyName(find_family_name(this)); | |
| 453 desc->setFontFileName(this->getUniqueString()); | |
| 454 *isLocalStream = !this->isSysFont(); | |
| 455 } | |
| 456 | |
| 457 static SkTypeface* create_typeface(const SkTypeface* familyFace, | |
| 458 const char familyName[], | |
| 459 SkTypeface::Style style) { | |
| 460 load_system_fonts(); | |
| 461 | |
| 462 SkAutoMutexAcquire ac(gFamilyMutex); | |
| 463 | |
| 464 // clip to legal style bits | |
| 465 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); | |
| 466 | |
| 467 SkTypeface* tf = NULL; | |
| 468 | |
| 469 if (NULL != familyFace) { | |
| 470 tf = find_typeface(familyFace, style); | |
| 471 } else if (NULL != familyName) { | |
| 472 // SkDebugf("======= familyName <%s>\n", familyName); | |
| 473 tf = find_typeface(familyName, style); | |
| 474 } | |
| 475 | |
| 476 if (NULL == tf) { | |
| 477 tf = find_best_face(gDefaultFamily, style); | |
| 478 } | |
| 479 | |
| 480 SkSafeRef(tf); | |
| 481 return tf; | |
| 482 } | |
| 483 | |
| 484 SkTypeface* FamilyTypeface::onRefMatchingStyle(Style style) const { | |
| 485 return create_typeface(this, NULL, style); | |
| 486 } | |
| 487 | |
| 488 /////////////////////////////////////////////////////////////////////////////// | |
| 489 | |
| 490 #ifndef SK_FONTHOST_USES_FONTMGR | |
| 491 | |
| 492 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, | |
| 493 const char familyName[], | |
| 494 SkTypeface::Style style) { | |
| 495 return create_typeface(familyFace, NULL, style); | |
| 496 } | |
| 497 | |
| 498 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { | |
| 499 if (NULL == stream || stream->getLength() <= 0) { | |
| 500 SkDELETE(stream); | |
| 501 return NULL; | |
| 502 } | |
| 503 | |
| 504 bool isFixedPitch; | |
| 505 SkTypeface::Style style; | |
| 506 if (find_name_and_attributes(stream, NULL, &style, &isFixedPitch)) { | |
| 507 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedPi
tch)); | |
| 508 } else { | |
| 509 return NULL; | |
| 510 } | |
| 511 } | |
| 512 | |
| 513 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { | |
| 514 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | |
| 515 return stream.get() ? CreateTypefaceFromStream(stream) : NULL; | |
| 516 } | |
| 517 | |
| 518 #endif | |
| 519 | |
| 520 /////////////////////////////////////////////////////////////////////////////// | |
| 521 | |
| 522 #include "SkFontMgr.h" | |
| 523 | |
| 524 SkFontMgr* SkFontMgr::Factory() { | |
| 525 // todo | |
| 526 return NULL; | |
| 527 } | |
| OLD | NEW |