Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/ports/SkFontConfigInterface_android.cpp

Issue 15720006: Android specific changes that are upstreamed from the android framework. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: missing declaration Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/core/SkPaintOptionsAndroid.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2013 The Android Open Source Project 3 * Copyright 2013 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkFontConfigInterface.h" 9 #include "SkFontConfigInterface.h"
10 #include "SkTypeface_android.h" 10 #include "SkTypeface_android.h"
11 11
12 #include "SkFontConfigParser_android.h" 12 #include "SkFontConfigParser_android.h"
13 #include "SkFontConfigTypeface.h" 13 #include "SkFontConfigTypeface.h"
14 #include "SkFontMgr.h" 14 #include "SkFontMgr.h"
15 #include "SkGlyphCache.h" 15 #include "SkGlyphCache.h"
16 #include "SkPaint.h" 16 #include "SkPaint.h"
17 #include "SkPaintOptionsAndroid.h"
18 #include "SkString.h" 17 #include "SkString.h"
19 #include "SkStream.h" 18 #include "SkStream.h"
20 #include "SkThread.h" 19 #include "SkThread.h"
21 #include "SkTypefaceCache.h" 20 #include "SkTypefaceCache.h"
22 #include "SkTArray.h" 21 #include "SkTArray.h"
23 #include "SkTDict.h" 22 #include "SkTDict.h"
24 #include "SkTSearch.h" 23 #include "SkTSearch.h"
25 24
26 #include <stdio.h> 25 #include <stdio.h>
27 #include <string.h> 26 #include <string.h>
(...skipping 10 matching lines...) Expand all
38 37
39 /////////////////////////////////////////////////////////////////////////////// 38 ///////////////////////////////////////////////////////////////////////////////
40 39
41 // For test only. 40 // For test only.
42 static const char* gTestMainConfigFile = NULL; 41 static const char* gTestMainConfigFile = NULL;
43 static const char* gTestFallbackConfigFile = NULL; 42 static const char* gTestFallbackConfigFile = NULL;
44 static const char* gTestFontFilePrefix = NULL; 43 static const char* gTestFontFilePrefix = NULL;
45 44
46 /////////////////////////////////////////////////////////////////////////////// 45 ///////////////////////////////////////////////////////////////////////////////
47 46
47 typedef int32_t FontRecID;
48 #define INVALID_FONT_REC_ID -1
49
50 typedef int32_t FamilyRecID;
51 #define INVALID_FAMILY_REC_ID -1
52
48 // used to record our notion of the pre-existing fonts 53 // used to record our notion of the pre-existing fonts
49 struct FontRec { 54 struct FontRec {
50 SkRefPtr<SkTypeface> fTypeface; 55 SkRefPtr<SkTypeface> fTypeface;
51 SkString fFileName; 56 SkString fFileName;
52 SkTypeface::Style fStyle; 57 SkTypeface::Style fStyle;
53 SkPaintOptionsAndroid fPaintOptions; 58 SkPaintOptionsAndroid fPaintOptions;
54 bool fIsFallbackFont; 59 bool fIsFallbackFont;
55 bool fIsValid; 60 bool fIsValid;
61 FamilyRecID fFamilyRecID;
56 }; 62 };
57 63
58 typedef int32_t FontRecID;
59 #define INVALID_FONT_REC_ID -1
60
61 struct FamilyRec { 64 struct FamilyRec {
62 FamilyRec() { 65 FamilyRec() {
63 memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID)); 66 memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID));
64 } 67 }
65 68
66 static const int FONT_STYLE_COUNT = 4; 69 static const int FONT_STYLE_COUNT = 4;
67 FontRecID fFontRecID[FONT_STYLE_COUNT]; 70 FontRecID fFontRecID[FONT_STYLE_COUNT];
68 }; 71 };
69 72
70 typedef int32_t FamilyRecID;
71 #define INVALID_FAMILY_REC_ID -1
72 73
73 typedef SkTDArray<FontRecID> FallbackFontList; 74 typedef SkTDArray<FontRecID> FallbackFontList;
74 75
75 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface { 76 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
76 public: 77 public:
77 SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies); 78 SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies);
78 virtual ~SkFontConfigInterfaceAndroid(); 79 virtual ~SkFontConfigInterfaceAndroid();
79 80
80 virtual bool matchFamilyName(const char familyName[], 81 virtual bool matchFamilyName(const char familyName[],
81 SkTypeface::Style requested, 82 SkTypeface::Style requested,
(...skipping 16 matching lines...) Expand all
98 /** 99 /**
99 * 100 *
100 */ 101 */
101 SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style, 102 SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style,
102 SkPaintOptionsAndroid::FontVariant fontVarian t); 103 SkPaintOptionsAndroid::FontVariant fontVarian t);
103 SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, 104 SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
104 const SkPaintOptionsAndroid& options); 105 const SkPaintOptionsAndroid& options);
105 106
106 private: 107 private:
107 void addFallbackFont(FontRecID fontRecID); 108 void addFallbackFont(FontRecID fontRecID);
108 FallbackFontList* findFallbackFontList(const SkLanguage& lang); 109 SkTypeface* getTypefaceForFontRec(FontRecID fontRecID);
110 FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOrigin al = true);
109 111
110 SkTArray<FontRec> fFonts; 112 SkTArray<FontRec> fFonts;
111 SkTArray<FamilyRec> fFontFamilies; 113 SkTArray<FamilyRec> fFontFamilies;
112 SkTDict<FamilyRecID> fFamilyNameDict; 114 SkTDict<FamilyRecID> fFamilyNameDict;
113 FamilyRecID fDefaultFamilyRecID; 115 FamilyRecID fDefaultFamilyRecID;
114 116
115 // (SkLanguage)<->(fallback chain index) translation 117 // (SkLanguage)<->(fallback chain index) translation
116 SkTDict<FallbackFontList*> fFallbackFontDict; 118 SkTDict<FallbackFontList*> fFallbackFontDict;
119 SkTDict<FallbackFontList*> fFallbackFontAliasDict;
117 FallbackFontList fDefaultFallbackList; 120 FallbackFontList fDefaultFallbackList;
118 }; 121 };
119 122
120 /////////////////////////////////////////////////////////////////////////////// 123 ///////////////////////////////////////////////////////////////////////////////
121 124
122 static SkFontConfigInterfaceAndroid* getSingletonInterface() { 125 static SkFontConfigInterfaceAndroid* getSingletonInterface() {
123 SK_DECLARE_STATIC_MUTEX(gMutex); 126 SK_DECLARE_STATIC_MUTEX(gMutex);
124 static SkFontConfigInterfaceAndroid* gFontConfigInterface; 127 static SkFontConfigInterfaceAndroid* gFontConfigInterface;
125 128
126 SkAutoMutexAcquire ac(gMutex); 129 SkAutoMutexAcquire ac(gMutex);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 bool find_name_and_attributes(SkStream* stream, SkString* name, 185 bool find_name_and_attributes(SkStream* stream, SkString* name,
183 SkTypeface::Style* style, bool* isFixedWidth); 186 SkTypeface::Style* style, bool* isFixedWidth);
184 187
185 /////////////////////////////////////////////////////////////////////////////// 188 ///////////////////////////////////////////////////////////////////////////////
186 189
187 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily* >& fontFamilies) : 190 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily* >& fontFamilies) :
188 fFonts(fontFamilies.count()), 191 fFonts(fontFamilies.count()),
189 fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT), 192 fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT),
190 fFamilyNameDict(1024), 193 fFamilyNameDict(1024),
191 fDefaultFamilyRecID(INVALID_FAMILY_REC_ID), 194 fDefaultFamilyRecID(INVALID_FAMILY_REC_ID),
192 fFallbackFontDict(128) { 195 fFallbackFontDict(128),
196 fFallbackFontAliasDict(128) {
193 197
194 for (int i = 0; i < fontFamilies.count(); ++i) { 198 for (int i = 0; i < fontFamilies.count(); ++i) {
195 FontFamily* family = fontFamilies[i]; 199 FontFamily* family = fontFamilies[i];
196 200
197 // defer initializing the familyRec until we can be sure that at least 201 // defer initializing the familyRec until we can be sure that at least
198 // one of it's children contains a valid font file 202 // one of it's children contains a valid font file
199 FamilyRec* familyRec = NULL; 203 FamilyRec* familyRec = NULL;
200 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; 204 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
201 205
202 for (int j = 0; j < family->fFontFiles.count(); ++j) { 206 for (int j = 0; j < family->fFontFiles.count(); ++j) {
203 SkString filename; 207 SkString filename;
204 get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName); 208 get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName);
205 209
206 if (has_font(fFonts, filename)) { 210 if (has_font(fFonts, filename)) {
207 SkDebugf("---- system font and fallback font files specify a dup licate " 211 SkDebugf("---- system font and fallback font files specify a dup licate "
208 "font %s, skipping the second occurrence", filename.c_st r()); 212 "font %s, skipping the second occurrence", filename.c_st r());
209 continue; 213 continue;
210 } 214 }
211 215
212 FontRec& fontRec = fFonts.push_back(); 216 FontRec& fontRec = fFonts.push_back();
213 fontRec.fFileName = filename; 217 fontRec.fFileName = filename;
214 fontRec.fStyle = SkTypeface::kNormal; 218 fontRec.fStyle = SkTypeface::kNormal;
215 fontRec.fPaintOptions = family->fFontFiles[j]->fPaintOptions; 219 fontRec.fPaintOptions = family->fFontFiles[j]->fPaintOptions;
216 fontRec.fIsFallbackFont = family->fIsFallbackFont; 220 fontRec.fIsFallbackFont = family->fIsFallbackFont;
217 fontRec.fIsValid = false; 221 fontRec.fIsValid = false;
222 fontRec.fFamilyRecID = familyRecID;
218 223
219 const FontRecID fontRecID = fFonts.count() - 1; 224 const FontRecID fontRecID = fFonts.count() - 1;
220 225
221 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str() )); 226 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str() ));
222 if (stream.get() != NULL) { 227 if (stream.get() != NULL) {
223 bool isFixedWidth; 228 bool isFixedWidth;
224 SkString name; 229 SkString name;
225 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name, 230 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name,
226 &fontRec.fStyle, &is FixedWidth); 231 &fontRec.fStyle, &is FixedWidth);
227 } else { 232 } else {
228 if (!fontRec.fIsFallbackFont) { 233 if (!fontRec.fIsFallbackFont) {
229 SkDebugf("---- failed to open <%s> as a font\n", filename.c_ str()); 234 SkDebugf("---- failed to open <%s> as a font\n", filename.c_ str());
230 } 235 }
231 } 236 }
232 237
233 if (fontRec.fIsValid) { 238 if (fontRec.fIsValid) {
234 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s", 239 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s",
235 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen ame.c_str())); 240 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen ame.c_str()));
236 } else { 241 } else {
237 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVAL ID)", 242 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVAL ID)",
238 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen ame.c_str())); 243 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen ame.c_str()));
239 continue; 244 continue;
240 } 245 }
241 246
242 // create a familyRec now that we know that at least one font in 247 // create a familyRec now that we know that at least one font in
243 // the family is valid 248 // the family is valid
244 if (familyRec == NULL) { 249 if (familyRec == NULL) {
245 familyRec = &fFontFamilies.push_back(); 250 familyRec = &fFontFamilies.push_back();
246 familyRecID = fFontFamilies.count() - 1; 251 familyRecID = fFontFamilies.count() - 1;
252 fontRec.fFamilyRecID = familyRecID;
247 } 253 }
248 254
249 // add this font to the current familyRec 255 // add this font to the current familyRec
250 if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) { 256 if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) {
251 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d) ", 257 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d) ",
252 fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle ], 258 fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle ],
253 fontRecID)); 259 fontRecID));
254 } 260 }
255 familyRec->fFontRecID[fontRec.fStyle] = fontRecID; 261 familyRec->fFontRecID[fontRec.fStyle] = fontRecID;
256 262
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), 453 return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
448 sizes.begin(), names.count()); 454 sizes.begin(), names.count());
449 } 455 }
450 456
451 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[], 457 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[],
452 SkString* outFamilyName, 458 SkString* outFamilyName,
453 SkTArray<FontIdentity>*) { 459 SkTArray<FontIdentity>*) {
454 return false; 460 return false;
455 } 461 }
456 462
457 static SkTypeface* get_typeface_for_rec(FontRec& fontRec) { 463 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
464 const FontRecID* fontRecID = (const FontRecID*)ctx;
465 FontRecID currFontRecID = ((FontConfigTypeface*)face)->getIdentity().fID;
466 return currFontRecID == *fontRecID;
467 }
468
469 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRe cID) {
470 FontRec& fontRec = fFonts[fontRecID];
458 SkTypeface* face = fontRec.fTypeface.get(); 471 SkTypeface* face = fontRec.fTypeface.get();
459 if (!face) { 472 if (!face) {
460 // TODO look for it in the typeface cache 473 // look for it in the typeface cache
474 face = SkTypefaceCache::FindByProcAndRef(find_proc, &fontRecID);
461 475
462 // if it is not in the cache then create it 476 // if it is not in the cache then create it
463 face = SkTypeface::CreateFromFile(fontRec.fFileName.c_str()); 477 if (!face) {
478 const char* familyName = NULL;
479 SkAssertResult(fFamilyNameDict.findKey(fontRec.fFamilyRecID, &family Name));
480 SkASSERT(familyName);
481 face = SkTypeface::CreateFromName(familyName, fontRec.fStyle);
482 }
464 483
465 // store the result for subsequent lookups 484 // store the result for subsequent lookups
466 fontRec.fTypeface = face; 485 fontRec.fTypeface = face;
467 } 486 }
468 SkASSERT(face); 487 SkASSERT(face);
469 return face; 488 return face;
470 } 489 }
471 490
472 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, S kString* name) { 491 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, S kString* name) {
473 for (int i = 0; i < fDefaultFallbackList.count(); i++) { 492 for (int i = 0; i < fDefaultFallbackList.count(); i++) {
474 FontRecID fontRecID = fDefaultFallbackList[i]; 493 FontRecID fontRecID = fDefaultFallbackList[i];
475 SkTypeface* face = get_typeface_for_rec(fFonts[fontRecID]); 494 SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
476 495
477 SkPaint paint; 496 SkPaint paint;
478 paint.setTypeface(face); 497 paint.setTypeface(face);
479 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 498 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
480 499
481 uint16_t glyphID; 500 uint16_t glyphID;
482 paint.textToGlyphs(&uni, sizeof(uni), &glyphID); 501 paint.textToGlyphs(&uni, sizeof(uni), &glyphID);
483 if (glyphID != 0) { 502 if (glyphID != 0) {
484 name->set(fFonts[fontRecID].fFileName); 503 name->set(fFonts[fontRecID].fFileName);
485 return true; 504 return true;
486 } 505 }
487 } 506 }
488 return false; 507 return false;
489 } 508 }
490 509
491 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni, 510 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni,
492 SkTypeface::Style s tyle, 511 SkTypeface::Style s tyle,
493 SkPaintOptionsAndro id::FontVariant fontVariant) { 512 SkPaintOptionsAndro id::FontVariant fontVariant) {
494 FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], st yle); 513 FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], st yle);
495 SkTypeface* face = get_typeface_for_rec(fFonts[fontRecID]); 514 SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
496 515
497 SkPaintOptionsAndroid paintOptions; 516 SkPaintOptionsAndroid paintOptions;
498 paintOptions.setFontVariant(fontVariant); 517 paintOptions.setFontVariant(fontVariant);
499 paintOptions.setUseFontFallbacks(true); 518 paintOptions.setUseFontFallbacks(true);
500 519
501 SkPaint paint; 520 SkPaint paint;
502 paint.setTypeface(face); 521 paint.setTypeface(face);
503 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 522 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
504 paint.setPaintOptionsAndroid(paintOptions); 523 paint.setPaintOptionsAndroid(paintOptions);
505 524
506 SkAutoGlyphCache autoCache(paint, NULL, NULL); 525 SkAutoGlyphCache autoCache(paint, NULL, NULL);
507 SkGlyphCache* cache = autoCache.getCache(); 526 SkGlyphCache* cache = autoCache.getCache();
508 527
509 SkScalerContext* ctx = cache->getScalerContext(); 528 SkScalerContext* ctx = cache->getScalerContext();
510 if (ctx) { 529 if (ctx) {
511 SkFontID fontID = ctx->findTypefaceIdForChar(uni); 530 SkFontID fontID = ctx->findTypefaceIdForChar(uni);
512 return SkTypefaceCache::FindByID(fontID); 531 return SkTypefaceCache::FindByID(fontID);
513 } 532 }
514 return NULL; 533 return NULL;
515 } 534 }
516 535
517 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLan guage& lang) { 536 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLan guage& lang,
537 bool isOrig inal) {
518 const SkString& langTag = lang.getTag(); 538 const SkString& langTag = lang.getTag();
519 if (langTag.isEmpty()) { 539 if (langTag.isEmpty()) {
520 return &fDefaultFallbackList; 540 return &fDefaultFallbackList;
521 } 541 }
522 542
523 FallbackFontList* fallbackFontList; 543 FallbackFontList* fallbackFontList;
524 if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontLis t)) { 544 if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontLis t) ||
545 fFallbackFontAliasDict.find(langTag.c_str(), langTag.size(), &fallbackFo ntList)) {
525 return fallbackFontList; 546 return fallbackFontList;
526 } 547 }
527 548
528 // attempt a recursive fuzzy match 549 // attempt a recursive fuzzy match
529 // TODO we could cache the intermediate parent so that we don't have to do
530 // the recursion again.
531 SkLanguage parent = lang.getParent(); 550 SkLanguage parent = lang.getParent();
532 return findFallbackFontList(parent); 551 fallbackFontList = findFallbackFontList(parent, false);
552
553 // cache the original lang so we don't have to do the recursion again.
554 if (isOriginal) {
555 DEBUG_FONT(("---- Created fallback list alias for \"%s\"", langTag.c_st r()));
556 fFallbackFontAliasDict.set(langTag.c_str(), fallbackFontList);
557 }
558 return fallbackFontList;
533 } 559 }
534 560
535 SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI D, 561 SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI D,
536 SkFontID origFontI D, 562 SkFontID origFontI D,
537 const SkPaintOptio nsAndroid& opts) { 563 const SkPaintOptio nsAndroid& opts) {
538 // Skia does not support font fallback by default. This enables clients such 564 // Skia does not support font fallback by default. This enables clients such
539 // as WebKit to customize their font selection. In any case, clients can use 565 // as WebKit to customize their font selection. In any case, clients can use
540 // GetFallbackFamilyNameForChar() to get the fallback font for individual 566 // GetFallbackFamilyNameForChar() to get the fallback font for individual
541 // characters. 567 // characters.
542 if (!opts.isUsingFontFallbacks()) { 568 if (!opts.isUsingFontFallbacks()) {
543 return NULL; 569 return NULL;
544 } 570 }
545 571
546 const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID); 572 const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
573 SkASSERT(currTypeface != 0);
547 574
548 FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguag e()); 575 FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguag e());
549 SkASSERT(currentFallbackList); 576 SkASSERT(currentFallbackList);
550 577
551 SkASSERT(currTypeface != 0);
552
553 // we must convert currTypeface into a FontRecID 578 // we must convert currTypeface into a FontRecID
554 FontRecID currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity() .fID; 579 FontRecID currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity() .fID;
580 SkASSERT(INVALID_FONT_REC_ID != currFontRecID);
555 581
556 // TODO lookup the index next font in the chain 582 // TODO lookup the index next font in the chain
557 int currFallbackFontIndex = currentFallbackList->find(currFontRecID); 583 int currFallbackFontIndex = currentFallbackList->find(currFontRecID);
558 int nextFallbackFontIndex = currFallbackFontIndex + 1; 584 int nextFallbackFontIndex = currFallbackFontIndex + 1;
559 SkASSERT(-1 == nextFallbackFontIndex);
560 585
561 if(nextFallbackFontIndex >= currentFallbackList->count() && -1 == currFallba ckFontIndex) { 586 if(nextFallbackFontIndex >= currentFallbackList->count()) {
562 return NULL; 587 return NULL;
563 } 588 }
564 589
565 // If a rec object is set to prefer "kDefault_Variant" it means they have no preference 590 // If a rec object is set to prefer "kDefault_Variant" it means they have no preference
566 // In this case, we set the value to "kCompact_Variant" 591 // In this case, we set the value to "kCompact_Variant"
567 SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant(); 592 SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant();
568 if (variant == SkPaintOptionsAndroid::kDefault_Variant) { 593 if (variant == SkPaintOptionsAndroid::kDefault_Variant) {
569 variant = SkPaintOptionsAndroid::kCompact_Variant; 594 variant = SkPaintOptionsAndroid::kCompact_Variant;
570 } 595 }
571 596
572 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant ; 597 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant ;
573 598
574 SkTypeface* nextLogicalTypeface = 0; 599 SkTypeface* nextLogicalTypeface = 0;
575 while (nextFallbackFontIndex < currentFallbackList->count()) { 600 while (nextFallbackFontIndex < currentFallbackList->count()) {
576 FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex); 601 FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex);
577 if (fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants) { 602 if ((fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants ) != 0) {
578 nextLogicalTypeface = get_typeface_for_rec(fFonts[fontRecID]); 603 nextLogicalTypeface = this->getTypefaceForFontRec(fontRecID);
579 break; 604 break;
580 } 605 }
581 nextFallbackFontIndex++; 606 nextFallbackFontIndex++;
582 } 607 }
583 608
584 DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=% d, " 609 DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=% d, "
585 "lang=%s, variant=%d, nextFallbackIndex=%d => nextLogicalTypefac e=%d", 610 "lang=%s, variant=%d, nextFallbackIndex[%d,%d] => nextLogicalTyp eface=%d",
586 currFontID, origFontID, currFontRecID, opts.getLanguage().getTag ().c_str(), 611 currFontID, origFontID, currFontRecID, opts.getLanguage().getTag ().c_str(),
587 variant, nextFallbackFontIndex, 612 variant, nextFallbackFontIndex, currentFallbackList->getAt(nextF allbackFontIndex),
588 (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0)); 613 (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0));
589 return SkSafeRef(nextLogicalTypeface); 614 return SkSafeRef(nextLogicalTypeface);
590 } 615 }
591 616
592 /////////////////////////////////////////////////////////////////////////////// 617 ///////////////////////////////////////////////////////////////////////////////
593 618
594 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) { 619 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
595 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 620 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
596 return fontConfig->getFallbackFamilyNameForChar(uni, name); 621 return fontConfig->getFallbackFamilyNameForChar(uni, name);
597 } 622 }
(...skipping 12 matching lines...) Expand all
610 635
611 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontI D, 636 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontI D,
612 const SkPaintOptionsAndroid& options) { 637 const SkPaintOptionsAndroid& options) {
613 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 638 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
614 return fontConfig->nextLogicalTypeface(currFontID, origFontID, options); 639 return fontConfig->nextLogicalTypeface(currFontID, origFontID, options);
615 640
616 } 641 }
617 642
618 /////////////////////////////////////////////////////////////////////////////// 643 ///////////////////////////////////////////////////////////////////////////////
619 644
645 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
646
647 struct HB_UnicodeMapping {
648 // TODO: when the WebView no longer needs harfbuzz_old, remove
649 HB_Script script_old;
650 hb_script_t script;
651 const SkUnichar unicode;
652 };
653
654 /*
655 * The following scripts are not complex fonts and we do not expect them to be p arsed by this table
656 * HB_SCRIPT_COMMON,
657 * HB_SCRIPT_GREEK,
658 * HB_SCRIPT_CYRILLIC,
659 * HB_SCRIPT_HANGUL
660 * HB_SCRIPT_INHERITED
661 */
662
663 /* Harfbuzz (old) is missing a number of scripts in its table. For these,
664 * we include a value which can never happen. We won't get complex script
665 * shaping in these cases, but the library wouldn't know how to shape
666 * them anyway. */
667 #define HB_Script_Unknown HB_ScriptCount
668
669 static HB_UnicodeMapping HB_UnicodeMappingArray[] = {
670 {HB_Script_Armenian, HB_SCRIPT_ARMENIAN, 0x0531},
671 {HB_Script_Hebrew, HB_SCRIPT_HEBREW, 0x0591},
672 {HB_Script_Arabic, HB_SCRIPT_ARABIC, 0x0600},
673 {HB_Script_Syriac, HB_SCRIPT_SYRIAC, 0x0710},
674 {HB_Script_Thaana, HB_SCRIPT_THAANA, 0x0780},
675 {HB_Script_Nko, HB_SCRIPT_NKO, 0x07C0},
676 {HB_Script_Devanagari, HB_SCRIPT_DEVANAGARI, 0x0901},
677 {HB_Script_Bengali, HB_SCRIPT_BENGALI, 0x0981},
678 {HB_Script_Gurmukhi, HB_SCRIPT_GURMUKHI, 0x0A10},
679 {HB_Script_Gujarati, HB_SCRIPT_GUJARATI, 0x0A90},
680 {HB_Script_Oriya, HB_SCRIPT_ORIYA, 0x0B10},
681 {HB_Script_Tamil, HB_SCRIPT_TAMIL, 0x0B82},
682 {HB_Script_Telugu, HB_SCRIPT_TELUGU, 0x0C10},
683 {HB_Script_Kannada, HB_SCRIPT_KANNADA, 0x0C90},
684 {HB_Script_Malayalam, HB_SCRIPT_MALAYALAM, 0x0D10},
685 {HB_Script_Sinhala, HB_SCRIPT_SINHALA, 0x0D90},
686 {HB_Script_Thai, HB_SCRIPT_THAI, 0x0E01},
687 {HB_Script_Lao, HB_SCRIPT_LAO, 0x0E81},
688 {HB_Script_Tibetan, HB_SCRIPT_TIBETAN, 0x0F00},
689 {HB_Script_Myanmar, HB_SCRIPT_MYANMAR, 0x1000},
690 {HB_Script_Georgian, HB_SCRIPT_GEORGIAN, 0x10A0},
691 {HB_Script_Unknown, HB_SCRIPT_ETHIOPIC, 0x1200},
692 {HB_Script_Unknown, HB_SCRIPT_CHEROKEE, 0x13A0},
693 {HB_Script_Ogham, HB_SCRIPT_OGHAM, 0x1680},
694 {HB_Script_Runic, HB_SCRIPT_RUNIC, 0x16A0},
695 {HB_Script_Khmer, HB_SCRIPT_KHMER, 0x1780},
696 {HB_Script_Unknown, HB_SCRIPT_TAI_LE, 0x1950},
697 {HB_Script_Unknown, HB_SCRIPT_NEW_TAI_LUE, 0x1980},
698 {HB_Script_Unknown, HB_SCRIPT_TAI_THAM, 0x1A20},
699 {HB_Script_Unknown, HB_SCRIPT_CHAM, 0xAA00},
700 };
701
702 static hb_script_t getHBScriptFromHBScriptOld(HB_Script script_old) {
703 hb_script_t script = HB_SCRIPT_INVALID;
704 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMa pping);
705 for (int i = 0; i < numSupportedFonts; i++) {
706 if (script_old == HB_UnicodeMappingArray[i].script_old) {
707 script = HB_UnicodeMappingArray[i].script;
708 break;
709 }
710 }
711 return script;
712 }
713
714 // returns 0 for "Not Found"
715 static SkUnichar getUnicodeFromHBScript(hb_script_t script) {
716 SkUnichar unichar = 0;
717 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMa pping);
718 for (int i = 0; i < numSupportedFonts; i++) {
719 if (script == HB_UnicodeMappingArray[i].script) {
720 unichar = HB_UnicodeMappingArray[i].unicode;
721 break;
722 }
723 }
724 return unichar;
725 }
726
727 struct TypefaceLookupStruct {
728 hb_script_t script;
729 SkTypeface::Style style;
730 SkPaintOptionsAndroid::FontVariant fontVariant;
731 SkTypeface* typeface;
732 };
733
734 SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex); // This is the mutex for gTypefac eTable
735 static SkTDArray<TypefaceLookupStruct> gTypefaceTable; // This is protected by gTypefaceTableMutex
736
737 static int typefaceLookupCompare(const TypefaceLookupStruct& first,
738 const TypefaceLookupStruct& second) {
739 if (first.script != second.script) {
740 return (first.script > second.script) ? 1 : -1;
741 }
742 if (first.style != second.style) {
743 return (first.style > second.style) ? 1 : -1;
744 }
745 if (first.fontVariant != second.fontVariant) {
746 return (first.fontVariant > second.fontVariant) ? 1 : -1;
747 }
748 return 0;
749 }
750
751 SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style st yle,
752 SkPaintOptionsAndroid::FontVariant fontV ariant) {
753 SkAutoMutexAcquire ac(gTypefaceTableMutex);
754
755 TypefaceLookupStruct key;
756 key.script = script;
757 key.style = style;
758 key.fontVariant = fontVariant;
759
760 int index = SkTSearch<TypefaceLookupStruct>(
761 (const TypefaceLookupStruct*) gTypefaceTable.begin(),
762 gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct),
763 typefaceLookupCompare);
764
765 SkTypeface* retTypeface = NULL;
766 if (index >= 0) {
767 retTypeface = gTypefaceTable[index].typeface;
768 }
769 else {
770 SkUnichar unichar = getUnicodeFromHBScript(script);
771 if (!unichar) {
772 return NULL;
773 }
774
775 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
776 retTypeface = fontConfig->getTypefaceForChar(unichar, style, fontVariant );
777
778 // add to the lookup table
779 key.typeface = retTypeface;
780 *gTypefaceTable.insert(~index) = key;
781 }
782
783 // we ref(), the caller is expected to unref when they are done
784 return SkSafeRef(retTypeface);
785 }
786
787 SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
788 SkPaintOptionsAndroid::FontVariant fontVar iant) {
789 return SkCreateTypefaceForScriptNG(getHBScriptFromHBScriptOld(script), style , fontVariant);
790 }
791
792 #endif
793
794 ///////////////////////////////////////////////////////////////////////////////
795
620 SkFontMgr* SkFontMgr::Factory() { 796 SkFontMgr* SkFontMgr::Factory() {
621 return NULL; 797 return NULL;
622 } 798 }
OLDNEW
« no previous file with comments | « src/core/SkPaintOptionsAndroid.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698