Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / ports / SkFontMgr_android.cpp
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkFontConfigParser_android.h"
9 #include "SkFontDescriptor.h"
10 #include "SkFontHost_FreeType_common.h"
11 #include "SkFontMgr.h"
12 #include "SkFontStyle.h"
13 #include "SkStream.h"
14 #include "SkTDArray.h"
15 #include "SkTSearch.h"
16 #include "SkTypeface.h"
17 #include "SkTypeface_android.h"
18 #include "SkTypefaceCache.h"
19
20 #include <limits>
21 #include <stdlib.h>
22
23 #ifndef SK_FONT_FILE_PREFIX
24 #    define SK_FONT_FILE_PREFIX "/fonts/"
25 #endif
26
27 #ifndef SK_DEBUG_FONTS
28     #define SK_DEBUG_FONTS 0
29 #endif
30
31 #if SK_DEBUG_FONTS
32 #    define DEBUG_FONT(args) SkDebugf args
33 #else
34 #    define DEBUG_FONT(args)
35 #endif
36
37 // For test only.
38 static const char* gTestMainConfigFile = NULL;
39 static const char* gTestFallbackConfigFile = NULL;
40 static const char* gTestFontFilePrefix = NULL;
41
42 class SkTypeface_Android : public SkTypeface_FreeType {
43 public:
44     SkTypeface_Android(int index,
45                        const SkFontStyle& style,
46                        bool isFixedPitch,
47                        const SkString& familyName)
48         : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
49         , fIndex(index)
50         , fFamilyName(familyName) { }
51
52 protected:
53     virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
54         *familyName = fFamilyName;
55     }
56
57     int fIndex;
58     SkString fFamilyName;
59
60 private:
61     typedef SkTypeface_FreeType INHERITED;
62 };
63
64 class SkTypeface_AndroidSystem : public SkTypeface_Android {
65 public:
66     SkTypeface_AndroidSystem(const SkString& pathName,
67                              int index,
68                              const SkFontStyle& style,
69                              bool isFixedPitch,
70                              const SkString& familyName,
71                              const SkLanguage& lang,
72                              FontVariant variantStyle)
73         : INHERITED(index, style, isFixedPitch, familyName)
74         , fPathName(pathName)
75         , fLang(lang)
76         , fVariantStyle(variantStyle) { }
77
78     virtual void onGetFontDescriptor(SkFontDescriptor* desc,
79                                      bool* serialize) const SK_OVERRIDE {
80         SkASSERT(desc);
81         SkASSERT(serialize);
82         desc->setFamilyName(fFamilyName.c_str());
83         desc->setFontFileName(fPathName.c_str());
84         desc->setFontIndex(fIndex);
85         *serialize = false;
86     }
87     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
88         *ttcIndex = fIndex;
89         return SkStream::NewFromFile(fPathName.c_str());
90     }
91
92     const SkString fPathName;
93     const SkLanguage fLang;
94     const FontVariant fVariantStyle;
95
96     typedef SkTypeface_Android INHERITED;
97 };
98
99 class SkTypeface_AndroidStream : public SkTypeface_Android {
100 public:
101     SkTypeface_AndroidStream(SkStream* stream,
102                              int index,
103                              const SkFontStyle& style,
104                              bool isFixedPitch,
105                              const SkString& familyName)
106         : INHERITED(index, style, isFixedPitch, familyName)
107         , fStream(SkRef(stream)) { }
108
109     virtual void onGetFontDescriptor(SkFontDescriptor* desc,
110                                      bool* serialize) const SK_OVERRIDE {
111         SkASSERT(desc);
112         SkASSERT(serialize);
113         desc->setFamilyName(fFamilyName.c_str());
114         desc->setFontFileName(NULL);
115         *serialize = true;
116     }
117
118     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
119         *ttcIndex = fIndex;
120         return fStream->duplicate();
121     }
122
123 private:
124     SkAutoTUnref<SkStream> fStream;
125
126     typedef SkTypeface_Android INHERITED;
127 };
128
129 void get_path_for_sys_fonts(const char* basePath, const SkString& name, SkString* full) {
130     if (basePath) {
131         full->set(basePath);
132     } else {
133         full->set(getenv("ANDROID_ROOT"));
134         full->append(SK_FONT_FILE_PREFIX);
135     }
136     full->append(name);
137 }
138
139 class SkFontStyleSet_Android : public SkFontStyleSet {
140 public:
141     explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath,
142                                     const SkTypeface_FreeType::Scanner& scanner)
143     {
144         const SkString* cannonicalFamilyName = NULL;
145         if (family.fNames.count() > 0) {
146             cannonicalFamilyName = &family.fNames[0];
147         }
148         // TODO? make this lazy
149         for (int i = 0; i < family.fFonts.count(); ++i) {
150             const FontFileInfo& fontFile = family.fFonts[i];
151
152             SkString pathName;
153             get_path_for_sys_fonts(basePath, fontFile.fFileName, &pathName);
154
155             SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
156             if (!stream.get()) {
157                 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str()));
158                 continue;
159             }
160
161             const int ttcIndex = fontFile.fIndex;
162             SkString familyName;
163             SkFontStyle style;
164             bool isFixedWidth;
165             if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) {
166                 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str()));
167                 continue;
168             }
169
170             if (fontFile.fWeight != 0) {
171                 style = SkFontStyle(fontFile.fWeight, style.width(), style.slant());
172             }
173
174             const SkLanguage& lang = family.fLanguage;
175             uint32_t variant = family.fVariant;
176             if (kDefault_FontVariant == variant) {
177                 variant = kCompact_FontVariant | kElegant_FontVariant;
178             }
179
180             // The first specified family name overrides the family name found in the font.
181             // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
182             // all of the specified family names in addition to the names found in the font.
183             if (cannonicalFamilyName != NULL) {
184                 familyName = *cannonicalFamilyName;
185             }
186
187             fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
188                                                  (pathName, ttcIndex,
189                                                   style, isFixedWidth, familyName,
190                                                   lang, variant)));
191         }
192     }
193
194     virtual int count() SK_OVERRIDE {
195         return fStyles.count();
196     }
197     virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
198         if (index < 0 || fStyles.count() <= index) {
199             return;
200         }
201         if (style) {
202             *style = this->style(index);
203         }
204         if (name) {
205             name->reset();
206         }
207     }
208     virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
209         if (index < 0 || fStyles.count() <= index) {
210             return NULL;
211         }
212         return SkRef(fStyles[index].get());
213     }
214
215     /** Find the typeface in this style set that most closely matches the given pattern.
216      *  TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
217      *  this simpler version using match_score() passes all our tests.
218      */
219     virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
220         if (0 == fStyles.count()) {
221             return NULL;
222         }
223         SkTypeface_AndroidSystem* closest = fStyles[0];
224         int minScore = std::numeric_limits<int>::max();
225         for (int i = 0; i < fStyles.count(); ++i) {
226             SkFontStyle style = this->style(i);
227             int score = match_score(pattern, style);
228             if (score < minScore) {
229                 closest = fStyles[i];
230                 minScore = score;
231             }
232         }
233         return SkRef(closest);
234     }
235
236 private:
237     SkFontStyle style(int index) {
238         return fStyles[index]->fontStyle();
239     }
240     static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
241         int score = 0;
242         score += abs((pattern.width() - candidate.width()) * 100);
243         score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
244         score += abs(pattern.weight() - candidate.weight());
245         return score;
246     }
247
248     SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
249
250     friend struct NameToFamily;
251     friend class SkFontMgr_Android;
252
253     typedef SkFontStyleSet INHERITED;
254 };
255
256 /** On Android a single family can have many names, but our API assumes unique names.
257  *  Map names to the back end so that all names for a given family refer to the same
258  *  (non-replicated) set of typefaces.
259  *  SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
260  */
261 struct NameToFamily {
262     SkString name;
263     SkFontStyleSet_Android* styleSet;
264 };
265
266 class SkFontMgr_Android : public SkFontMgr {
267 public:
268     SkFontMgr_Android() {
269         SkTDArray<FontFamily*> fontFamilies;
270         SkFontConfigParser::GetFontFamilies(fontFamilies);
271         this->buildNameToFamilyMap(fontFamilies, NULL);
272         this->findDefaultFont();
273     }
274     SkFontMgr_Android(const char* mainConfigFile, const char* fallbackConfigFile,
275                       const char* basePath)
276     {
277         SkTDArray<FontFamily*> fontFamilies;
278         SkFontConfigParser::GetTestFontFamilies(fontFamilies, mainConfigFile, fallbackConfigFile);
279         this->buildNameToFamilyMap(fontFamilies, basePath);
280         this->findDefaultFont();
281     }
282
283 protected:
284     /** Returns not how many families we have, but how many unique names
285      *  exist among the families.
286      */
287     virtual int onCountFamilies() const SK_OVERRIDE {
288         return fNameToFamilyMap.count();
289     }
290
291     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
292         if (index < 0 || fNameToFamilyMap.count() <= index) {
293             familyName->reset();
294             return;
295         }
296         familyName->set(fNameToFamilyMap[index].name);
297     }
298
299     virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
300         if (index < 0 || fNameToFamilyMap.count() <= index) {
301             return NULL;
302         }
303         return SkRef(fNameToFamilyMap[index].styleSet);
304     }
305
306     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
307         if (!familyName) {
308             return NULL;
309         }
310         SkAutoAsciiToLC tolc(familyName);
311         for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
312             if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
313                 return SkRef(fNameToFamilyMap[i].styleSet);
314             }
315         }
316         // TODO: eventually we should not need to name fallback families.
317         for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
318             if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
319                 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
320             }
321         }
322         return NULL;
323     }
324
325     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
326                                            const SkFontStyle& style) const SK_OVERRIDE {
327         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
328         return sset->matchStyle(style);
329     }
330
331     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
332                                          const SkFontStyle& style) const SK_OVERRIDE {
333         for (int i = 0; i < fFontStyleSets.count(); ++i) {
334             for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
335                 if (fFontStyleSets[i]->fStyles[j] == typeface) {
336                     return fFontStyleSets[i]->matchStyle(style);
337                 }
338             }
339         }
340         return NULL;
341     }
342
343 static SkTypeface_AndroidSystem* find_family_style_character(
344         const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
345         const SkFontStyle& style, bool elegant,
346         const SkString& langTag, SkUnichar character)
347 {
348     for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
349         SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
350         SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
351
352         if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
353             continue;
354         }
355
356         if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
357             continue;
358         }
359
360         SkPaint paint;
361         paint.setTypeface(face);
362         paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
363
364         uint16_t glyphID;
365         paint.textToGlyphs(&character, sizeof(character), &glyphID);
366         if (glyphID != 0) {
367             return face.detach();
368         }
369     }
370     return NULL;
371 }
372 #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
373     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
374                                                     const SkFontStyle& style,
375                                                     const char* bcp47[],
376                                                     int bcp47Count,
377                                                     SkUnichar character) const SK_OVERRIDE
378     {
379 #else
380     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
381                                                     const SkFontStyle& style,
382                                                     const char bcp47_val[],
383                                                     SkUnichar character) const SK_OVERRIDE
384     {
385         const char** bcp47 = &bcp47_val;
386         int bcp47Count = bcp47_val ? 1 : 0;
387 #endif
388         // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
389         // The variant 'default' means 'compact and elegant'.
390         // As a result, it is not possible to know the variant context from the font alone.
391         // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
392
393         // The first time match anything elegant, second time anything not elegant.
394         for (int elegant = 2; elegant --> 0;) {
395             for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
396                 SkLanguage lang(bcp47[bcp47Index]);
397                 while (!lang.getTag().isEmpty()) {
398                     SkTypeface_AndroidSystem* matchingTypeface =
399                         find_family_style_character(fFallbackNameToFamilyMap,
400                                                     style, SkToBool(elegant),
401                                                     lang.getTag(), character);
402                     if (matchingTypeface) {
403                         return matchingTypeface;
404                     }
405
406                     lang = lang.getParent();
407                 }
408             }
409             SkTypeface_AndroidSystem* matchingTypeface =
410                 find_family_style_character(fFallbackNameToFamilyMap,
411                                             style, SkToBool(elegant),
412                                             SkString(), character);
413             if (matchingTypeface) {
414                 return matchingTypeface;
415             }
416         }
417         return NULL;
418     }
419
420     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
421         SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
422         return this->createFromStream(stream, ttcIndex);
423     }
424
425     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
426         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
427         return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
428     }
429
430     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
431         bool isFixedPitch;
432         SkFontStyle style;
433         SkString name;
434         if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
435             return NULL;
436         }
437         return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex,
438                                                      style, isFixedPitch, name));
439     }
440
441
442     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
443                                                unsigned styleBits) const SK_OVERRIDE {
444         SkFontStyle style = SkFontStyle(styleBits);
445
446         if (familyName) {
447             // On Android, we must return NULL when we can't find the requested
448             // named typeface so that the system/app can provide their own recovery
449             // mechanism. On other platforms we'd provide a typeface from the
450             // default family instead.
451             return this->onMatchFamilyStyle(familyName, style);
452         }
453         return fDefaultFamily->matchStyle(style);
454     }
455
456
457 private:
458
459     SkTypeface_FreeType::Scanner fScanner;
460
461     SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
462     SkFontStyleSet* fDefaultFamily;
463     SkTypeface* fDefaultTypeface;
464
465     SkTDArray<NameToFamily> fNameToFamilyMap;
466     SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
467
468     void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const char* basePath) {
469         for (int i = 0; i < families.count(); i++) {
470             FontFamily& family = *families[i];
471
472             SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
473             if (family.fIsFallbackFont) {
474                 nameToFamily = &fFallbackNameToFamilyMap;
475
476                 if (0 == family.fNames.count()) {
477                     SkString& fallbackName = family.fNames.push_back();
478                     fallbackName.printf("%.2x##fallback", i);
479                 }
480             }
481
482             SkFontStyleSet_Android* newSet =
483                 SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath, fScanner));
484             if (0 == newSet->count()) {
485                 SkDELETE(newSet);
486                 continue;
487             }
488             fFontStyleSets.push_back().reset(newSet);
489
490             for (int j = 0; j < family.fNames.count(); j++) {
491                 NameToFamily* nextEntry = nameToFamily->append();
492                 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
493                 nextEntry->styleSet = newSet;
494             }
495         }
496     }
497
498     void findDefaultFont() {
499         SkASSERT(!fFontStyleSets.empty());
500
501         static const char* gDefaultNames[] = { "sans-serif" };
502         for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
503             SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
504             if (NULL == set) {
505                 continue;
506             }
507             SkTypeface* tf = set->matchStyle(SkFontStyle());
508             if (NULL == tf) {
509                 continue;
510             }
511             fDefaultFamily = set;
512             fDefaultTypeface = tf;
513             break;
514         }
515         if (NULL == fDefaultTypeface) {
516             fDefaultFamily = fFontStyleSets[0];
517             fDefaultTypeface = fDefaultFamily->createTypeface(0);
518         }
519         SkASSERT(fDefaultFamily);
520         SkASSERT(fDefaultTypeface);
521     }
522
523     typedef SkFontMgr INHERITED;
524 };
525
526 ///////////////////////////////////////////////////////////////////////////////
527
528 SkFontMgr* SkFontMgr::Factory() {
529     // The call to SkGetTestFontConfiguration is so that Chromium can override the environment.
530     // TODO: these globals need to be removed, in favor of a constructor / separate Factory
531     // which can be used instead.
532     const char* mainConfigFile;
533     const char* fallbackConfigFile;
534     const char* basePath;
535     SkGetTestFontConfiguration(&mainConfigFile, &fallbackConfigFile, &basePath);
536     if (mainConfigFile) {
537         return SkNEW_ARGS(SkFontMgr_Android, (mainConfigFile, fallbackConfigFile, basePath));
538     }
539
540     return SkNEW(SkFontMgr_Android);
541 }
542
543 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
544                              const char* fontsdir) {
545     gTestMainConfigFile = mainconf;
546     gTestFallbackConfigFile = fallbackconf;
547     gTestFontFilePrefix = fontsdir;
548     SkASSERT(gTestMainConfigFile);
549     SkASSERT(gTestFallbackConfigFile);
550     SkASSERT(gTestFontFilePrefix);
551     SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
552               gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
553 }
554
555 void SkGetTestFontConfiguration(const char** mainconf, const char** fallbackconf,
556                                 const char** fontsdir) {
557     *mainconf = gTestMainConfigFile;
558     *fallbackconf = gTestFallbackConfigFile;
559     *fontsdir = gTestFontFilePrefix;
560 }