Home | History | Annotate | Download | only in ports
      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:
     28     SkLanguage() { }
     29     SkLanguage(const SkString& tag) : fTag(tag) { }
     30     SkLanguage(const char* tag) : fTag(tag) { }
     31     SkLanguage(const char* tag, size_t len) : fTag(tag, len) { }
     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     */
     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 {
     70     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 {
     87     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  */
    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  */
    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