gfx/skia/trunk/src/ports/SkFontConfigParser_android.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
     8 #include "SkFontConfigParser_android.h"
     9 #include "SkTDArray.h"
    10 #include "SkTypeface.h"
    12 #include <expat.h>
    13 #include <stdio.h>
    14 #include <sys/system_properties.h>
    16 #define SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml"
    17 #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml"
    18 #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml"
    20 // These defines are used to determine the kind of tag that we're currently
    21 // populating with data. We only care about the sibling tags nameset and fileset
    22 // for now.
    23 #define NO_TAG 0
    24 #define NAMESET_TAG 1
    25 #define FILESET_TAG 2
    27 /**
    28  * The FamilyData structure is passed around by the parser so that each handler
    29  * can read these variables that are relevant to the current parsing.
    30  */
    31 struct FamilyData {
    32     FamilyData(XML_Parser *parserRef, SkTDArray<FontFamily*> &familiesRef) :
    33         parser(parserRef),
    34         families(familiesRef),
    35         currentFamily(NULL),
    36         currentFontInfo(NULL),
    37         currentTag(NO_TAG) {};
    39     XML_Parser *parser;                // The expat parser doing the work
    40     SkTDArray<FontFamily*> &families;  // The array that each family is put into as it is parsed
    41     FontFamily *currentFamily;         // The current family being created
    42     FontFileInfo *currentFontInfo;     // The current fontInfo being created
    43     int currentTag;                    // A flag to indicate whether we're in nameset/fileset tags
    44 };
    46 /**
    47  * Handler for arbitrary text. This is used to parse the text inside each name
    48  * or file tag. The resulting strings are put into the fNames or FontFileInfo arrays.
    49  */
    50 static void textHandler(void *data, const char *s, int len) {
    51     FamilyData *familyData = (FamilyData*) data;
    52     // Make sure we're in the right state to store this name information
    53     if (familyData->currentFamily &&
    54             (familyData->currentTag == NAMESET_TAG || familyData->currentTag == FILESET_TAG)) {
    55         // Malloc new buffer to store the string
    56         char *buff;
    57         buff = (char*) malloc((len + 1) * sizeof(char));
    58         strncpy(buff, s, len);
    59         buff[len] = '\0';
    60         switch (familyData->currentTag) {
    61         case NAMESET_TAG:
    62             *(familyData->currentFamily->fNames.append()) = buff;
    63             break;
    64         case FILESET_TAG:
    65             if (familyData->currentFontInfo) {
    66                 familyData->currentFontInfo->fFileName = buff;
    67             }
    68             break;
    69         default:
    70             // Noop - don't care about any text that's not in the Fonts or Names list
    71             break;
    72         }
    73     }
    74 }
    76 /**
    77  * Handler for font files. This processes the attributes for language and
    78  * variants then lets textHandler handle the actual file name
    79  */
    80 static void fontFileElementHandler(FamilyData *familyData, const char **attributes) {
    81     FontFileInfo* newFileInfo = new FontFileInfo();
    82     if (attributes) {
    83         int currentAttributeIndex = 0;
    84         while (attributes[currentAttributeIndex]) {
    85             const char* attributeName = attributes[currentAttributeIndex];
    86             const char* attributeValue = attributes[currentAttributeIndex+1];
    87             int nameLength = strlen(attributeName);
    88             int valueLength = strlen(attributeValue);
    89             if (strncmp(attributeName, "variant", nameLength) == 0) {
    90                 if (strncmp(attributeValue, "elegant", valueLength) == 0) {
    91                     newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant);
    92                 } else if (strncmp(attributeValue, "compact", valueLength) == 0) {
    93                     newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kCompact_Variant);
    94                 }
    95             } else if (strncmp(attributeName, "lang", nameLength) == 0) {
    96                 newFileInfo->fPaintOptions.setLanguage(attributeValue);
    97             }
    98             //each element is a pair of attributeName/attributeValue string pairs
    99             currentAttributeIndex += 2;
   100         }
   101     }
   102     *(familyData->currentFamily->fFontFiles.append()) = newFileInfo;
   103     familyData->currentFontInfo = newFileInfo;
   104     XML_SetCharacterDataHandler(*familyData->parser, textHandler);
   105 }
   107 /**
   108  * Handler for the start of a tag. The only tags we expect are family, nameset,
   109  * fileset, name, and file.
   110  */
   111 static void startElementHandler(void *data, const char *tag, const char **atts) {
   112     FamilyData *familyData = (FamilyData*) data;
   113     int len = strlen(tag);
   114     if (strncmp(tag, "family", len)== 0) {
   115         familyData->currentFamily = new FontFamily();
   116         familyData->currentFamily->order = -1;
   117         // The Family tag has an optional "order" attribute with an integer value >= 0
   118         // If this attribute does not exist, the default value is -1
   119         for (int i = 0; atts[i] != NULL; i += 2) {
   120             const char* valueString = atts[i+1];
   121             int value;
   122             int len = sscanf(valueString, "%d", &value);
   123             if (len > 0) {
   124                 familyData->currentFamily->order = value;
   125             }
   126         }
   127     } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
   128         familyData->currentTag = NAMESET_TAG;
   129     } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
   130         familyData->currentTag = FILESET_TAG;
   131     } else if (strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) {
   132         // If it's a Name, parse the text inside
   133         XML_SetCharacterDataHandler(*familyData->parser, textHandler);
   134     } else if (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG) {
   135         // If it's a file, parse the attributes, then parse the text inside
   136         fontFileElementHandler(familyData, atts);
   137     }
   138 }
   140 /**
   141  * Handler for the end of tags. We only care about family, nameset, fileset,
   142  * name, and file.
   143  */
   144 static void endElementHandler(void *data, const char *tag) {
   145     FamilyData *familyData = (FamilyData*) data;
   146     int len = strlen(tag);
   147     if (strncmp(tag, "family", len)== 0) {
   148         // Done parsing a Family - store the created currentFamily in the families array
   149         *familyData->families.append() = familyData->currentFamily;
   150         familyData->currentFamily = NULL;
   151     } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
   152         familyData->currentTag = NO_TAG;
   153     } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
   154         familyData->currentTag = NO_TAG;
   155     } else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) ||
   156             (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) {
   157         // Disable the arbitrary text handler installed to load Name data
   158         XML_SetCharacterDataHandler(*familyData->parser, NULL);
   159     }
   160 }
   162 /**
   163  * This function parses the given filename and stores the results in the given
   164  * families array.
   165  */
   166 static void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) {
   168     FILE* file = NULL;
   170 #if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
   171     // if we are using a version of Android prior to Android 4.2 (JellyBean MR1
   172     // at API Level 17) then we need to look for files with a different suffix.
   173     char sdkVersion[PROP_VALUE_MAX];
   174     __system_property_get("ro.build.version.sdk", sdkVersion);
   175     const int sdkVersionInt = atoi(sdkVersion);
   177     if (0 != *sdkVersion && sdkVersionInt < 17) {
   178         SkString basename;
   179         SkString updatedFilename;
   180         SkString locale = SkFontConfigParser::GetLocale();
   182         basename.set(filename);
   183         // Remove the .xml suffix. We'll add it back in a moment.
   184         if (basename.endsWith(".xml")) {
   185             basename.resize(basename.size()-4);
   186         }
   187         // Try first with language and region
   188         updatedFilename.printf("%s-%s.xml", basename.c_str(), locale.c_str());
   189         file = fopen(updatedFilename.c_str(), "r");
   190         if (!file) {
   191             // If not found, try next with just language
   192             updatedFilename.printf("%s-%.2s.xml", basename.c_str(), locale.c_str());
   193             file = fopen(updatedFilename.c_str(), "r");
   194         }
   195     }
   196 #endif
   198     if (NULL == file) {
   199         file = fopen(filename, "r");
   200     }
   202     // Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml)
   203     // are optional - failure here is okay because one of these optional files may not exist.
   204     if (NULL == file) {
   205         return;
   206     }
   208     XML_Parser parser = XML_ParserCreate(NULL);
   209     FamilyData *familyData = new FamilyData(&parser, families);
   210     XML_SetUserData(parser, familyData);
   211     XML_SetElementHandler(parser, startElementHandler, endElementHandler);
   213     char buffer[512];
   214     bool done = false;
   215     while (!done) {
   216         fgets(buffer, sizeof(buffer), file);
   217         int len = strlen(buffer);
   218         if (feof(file) != 0) {
   219             done = true;
   220         }
   221         XML_Parse(parser, buffer, len, done);
   222     }
   223     XML_ParserFree(parser);
   224     fclose(file);
   225 }
   227 static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
   228     parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies);
   229 }
   231 static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) {
   232     SkTDArray<FontFamily*> vendorFonts;
   233     parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts);
   234     parseConfigFile(VENDOR_FONTS_FILE, vendorFonts);
   236     // This loop inserts the vendor fallback fonts in the correct order in the
   237     // overall fallbacks list.
   238     int currentOrder = -1;
   239     for (int i = 0; i < vendorFonts.count(); ++i) {
   240         FontFamily* family = vendorFonts[i];
   241         int order = family->order;
   242         if (order < 0) {
   243             if (currentOrder < 0) {
   244                 // Default case - just add it to the end of the fallback list
   245                 *fallbackFonts.append() = family;
   246             } else {
   247                 // no order specified on this font, but we're incrementing the order
   248                 // based on an earlier order insertion request
   249                 *fallbackFonts.insert(currentOrder++) = family;
   250             }
   251         } else {
   252             // Add the font into the fallback list in the specified order. Set
   253             // currentOrder for correct placement of other fonts in the vendor list.
   254             *fallbackFonts.insert(order) = family;
   255             currentOrder = order + 1;
   256         }
   257     }
   258 }
   260 /**
   261  * Loads data on font families from various expected configuration files. The
   262  * resulting data is returned in the given fontFamilies array.
   263  */
   264 void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
   266     getSystemFontFamilies(fontFamilies);
   268     // Append all the fallback fonts to system fonts
   269     SkTDArray<FontFamily*> fallbackFonts;
   270     getFallbackFontFamilies(fallbackFonts);
   271     for (int i = 0; i < fallbackFonts.count(); ++i) {
   272         fallbackFonts[i]->fIsFallbackFont = true;
   273         *fontFamilies.append() = fallbackFonts[i];
   274     }
   275 }
   277 void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*> &fontFamilies,
   278                                              const char* testMainConfigFile,
   279                                              const char* testFallbackConfigFile) {
   280     parseConfigFile(testMainConfigFile, fontFamilies);
   282     SkTDArray<FontFamily*> fallbackFonts;
   283     parseConfigFile(testFallbackConfigFile, fallbackFonts);
   285     // Append all fallback fonts to system fonts
   286     for (int i = 0; i < fallbackFonts.count(); ++i) {
   287         fallbackFonts[i]->fIsFallbackFont = true;
   288         *fontFamilies.append() = fallbackFonts[i];
   289     }
   290 }
   292 /**
   293  * Read the persistent locale.
   294  */
   295 SkString SkFontConfigParser::GetLocale()
   296 {
   297     char propLang[PROP_VALUE_MAX], propRegn[PROP_VALUE_MAX];
   298     __system_property_get("persist.sys.language", propLang);
   299     __system_property_get("persist.sys.country", propRegn);
   301     if (*propLang == 0 && *propRegn == 0) {
   302         /* Set to ro properties, default is en_US */
   303         __system_property_get("ro.product.locale.language", propLang);
   304         __system_property_get("ro.product.locale.region", propRegn);
   305         if (*propLang == 0 && *propRegn == 0) {
   306             strcpy(propLang, "en");
   307             strcpy(propRegn, "US");
   308         }
   309     }
   311     SkString locale(6);
   312     char* localeCStr = locale.writable_str();
   314     strncpy(localeCStr, propLang, 2);
   315     localeCStr[2] = '-';
   316     strncpy(&localeCStr[3], propRegn, 2);
   317     localeCStr[5] = '\0';
   319     return locale;
   320 }

mercurial