• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 The Android Open Source Project
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 #ifndef SkFontMgr_android_parser_DEFINED
9 #define SkFontMgr_android_parser_DEFINED
10 
11 #include "SkFontMgr.h"
12 #include "SkString.h"
13 #include "SkTArray.h"
14 #include "SkTDArray.h"
15 #include "SkTypes.h"
16 
17 #include <climits>
18 #include <limits>
19 
20 /** \class SkLanguage
21 
22     The SkLanguage class represents a human written language, and is used by
23     text draw operations to determine which glyph to draw when drawing
24     characters with variants (ie Han-derived characters).
25 */
26 class SkLanguage {
27 public:
SkLanguage()28     SkLanguage() { }
SkLanguage(const SkString & tag)29     SkLanguage(const SkString& tag) : fTag(tag) { }
SkLanguage(const char * tag)30     SkLanguage(const char* tag) : fTag(tag) { }
SkLanguage(const char * tag,size_t len)31     SkLanguage(const char* tag, size_t len) : fTag(tag, len) { }
SkLanguage(const SkLanguage & b)32     SkLanguage(const SkLanguage& b) : fTag(b.fTag) { }
33 
34     /** Gets a BCP 47 language identifier for this SkLanguage.
35         @return a BCP 47 language identifier representing this language
36     */
getTag()37     const SkString& getTag() const { return fTag; }
38 
39     /** Performs BCP 47 fallback to return an SkLanguage one step more general.
40         @return an SkLanguage one step more general
41     */
42     SkLanguage getParent() const;
43 
44     bool operator==(const SkLanguage& b) const {
45         return fTag == b.fTag;
46     }
47     bool operator!=(const SkLanguage& b) const {
48         return fTag != b.fTag;
49     }
50     SkLanguage& operator=(const SkLanguage& b) {
51         fTag = b.fTag;
52         return *this;
53     }
54 
55 private:
56     //! BCP 47 language identifier
57     SkString fTag;
58 };
59 
60 enum FontVariants {
61    kDefault_FontVariant = 0x01,
62    kCompact_FontVariant = 0x02,
63    kElegant_FontVariant = 0x04,
64    kLast_FontVariant = kElegant_FontVariant,
65 };
66 typedef uint32_t FontVariant;
67 
68 // Must remain trivially movable (can be memmoved).
69 struct FontFileInfo {
FontFileInfoFontFileInfo70     FontFileInfo() : fIndex(0), fWeight(0), fStyle(Style::kAuto) { }
71 
72     SkString fFileName;
73     int fIndex;
74     int fWeight;
75     enum class Style { kAuto, kNormal, kItalic } fStyle;
76     SkTArray<SkFontArguments::VariationPosition::Coordinate, true> fVariationDesignPosition;
77 };
78 
79 /**
80  * A font family provides one or more names for a collection of fonts, each of
81  * which has a different style (normal, italic) or weight (thin, light, bold,
82  * etc).
83  * Some fonts may occur in compact variants for use in the user interface.
84  * Android distinguishes "fallback" fonts to support non-ASCII character sets.
85  */
86 struct FontFamily {
FontFamilyFontFamily87     FontFamily(const SkString& basePath, bool isFallbackFont)
88         : fVariant(kDefault_FontVariant)
89         , fOrder(-1)
90         , fIsFallbackFont(isFallbackFont)
91         , fBasePath(basePath)
92     { }
93 
94     SkTArray<SkString, true> fNames;
95     SkTArray<FontFileInfo, true> fFonts;
96     SkTArray<SkLanguage, true> fLanguages;
97     FontVariant fVariant;
98     int fOrder; // internal to the parser, not useful to users.
99     bool fIsFallbackFont;
100     const SkString fBasePath;
101 };
102 
103 namespace SkFontMgr_Android_Parser {
104 
105 /** Parses system font configuration files and appends result to fontFamilies. */
106 void GetSystemFontFamilies(SkTDArray<FontFamily*>& fontFamilies);
107 
108 /** Parses font configuration files and appends result to fontFamilies. */
109 void GetCustomFontFamilies(SkTDArray<FontFamily*>& fontFamilies,
110                            const SkString& basePath,
111                            const char* fontsXml,
112                            const char* fallbackFontsXml,
113                            const char* langFallbackFontsDir = nullptr);
114 
115 } // SkFontMgr_Android_Parser namespace
116 
117 
118 /** Parses a null terminated string into an integer type, checking for overflow.
119  *  http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-negative-def
120  *
121  *  If the string cannot be parsed into 'value', returns false and does not change 'value'.
122  */
parse_non_negative_integer(const char * s,T * value)123 template <typename T> static bool parse_non_negative_integer(const char* s, T* value) {
124     static_assert(std::numeric_limits<T>::is_integer, "T_must_be_integer");
125 
126     if (*s == '\0') {
127         return false;
128     }
129 
130     const T nMax = std::numeric_limits<T>::max() / 10;
131     const T dMax = std::numeric_limits<T>::max() - (nMax * 10);
132     T n = 0;
133     for (; *s; ++s) {
134         // Check if digit
135         if (*s < '0' || '9' < *s) {
136             return false;
137         }
138         T d = *s - '0';
139         // Check for overflow
140         if (n > nMax || (n == nMax && d > dMax)) {
141             return false;
142         }
143         n = (n * 10) + d;
144     }
145     *value = n;
146     return true;
147 }
148 
149 /** Parses a null terminated string into a signed fixed point value with bias N.
150  *
151  *  Like http://www.w3.org/TR/html-markup/datatypes.html#common.data.float-def ,
152  *  but may start with '.' and does not support 'e'. '-?((:digit:+(.:digit:+)?)|(.:digit:+))'
153  *
154  *  Checks for overflow.
155  *  Low bit rounding is not defined (is currently truncate).
156  *  Bias (N) required to allow for the sign bit and 4 bits of integer.
157  *
158  *  If the string cannot be parsed into 'value', returns false and does not change 'value'.
159  */
parse_fixed(const char * s,T * value)160 template <int N, typename T> static bool parse_fixed(const char* s, T* value) {
161     static_assert(std::numeric_limits<T>::is_integer, "T_must_be_integer");
162     static_assert(std::numeric_limits<T>::is_signed, "T_must_be_signed");
163     static_assert(sizeof(T) * CHAR_BIT - N >= 5, "N_must_leave_four_bits_plus_sign");
164 
165     bool negate = false;
166     if (*s == '-') {
167         ++s;
168         negate = true;
169     }
170     if (*s == '\0') {
171         return false;
172     }
173 
174     const T nMax = (std::numeric_limits<T>::max() >> N) / 10;
175     const T dMax = (std::numeric_limits<T>::max() >> N) - (nMax * 10);
176     T n = 0;
177     T frac = 0;
178     for (; *s; ++s) {
179         // Check if digit
180         if (*s < '0' || '9' < *s) {
181             // If it wasn't a digit, check if it is a '.' followed by something.
182             if (*s != '.' || s[1] == '\0') {
183                 return false;
184             }
185             // Find the end, verify digits.
186             for (++s; *s; ++s) {
187                 if (*s < '0' || '9' < *s) {
188                     return false;
189                 }
190             }
191             // Read back toward the '.'.
192             for (--s; *s != '.'; --s) {
193                 T d = *s - '0';
194                 frac = (frac + (d << N)) / 10; // This requires four bits overhead.
195             }
196             break;
197         }
198         T d = *s - '0';
199         // Check for overflow
200         if (n > nMax || (n == nMax && d > dMax)) {
201             return false;
202         }
203         n = (n * 10) + d;
204     }
205     if (negate) {
206         n = -n;
207         frac = -frac;
208     }
209     *value = SkLeftShift(n, N) + frac;
210     return true;
211 }
212 
213 #endif /* SkFontMgr_android_parser_DEFINED */
214