Flutter Engine
The Flutter Engine
Classes | Namespaces | Macros | Functions | Variables
SkFontMgr_android_parser.cpp File Reference
#include "include/core/SkFontMgr.h"
#include "include/core/SkStream.h"
#include "include/private/base/SkFixed.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTDArray.h"
#include "include/private/base/SkTLogic.h"
#include "include/private/base/SkTemplates.h"
#include "src/base/SkTSearch.h"
#include "src/core/SkOSFile.h"
#include "src/ports/SkFontMgr_android_parser.h"
#include <expat.h>
#include <stdlib.h>
#include <string.h>
#include <memory>

Go to the source code of this file.

Classes

struct  TagHandler
 
struct  FamilyData
 

Namespaces

namespace  lmpParser
 
namespace  jbParser
 

Macros

#define LMP_SYSTEM_FONTS_FILE   "/system/etc/fonts.xml"
 
#define OLD_SYSTEM_FONTS_FILE   "/system/etc/system_fonts.xml"
 
#define FALLBACK_FONTS_FILE   "/system/etc/fallback_fonts.xml"
 
#define VENDOR_FONTS_FILE   "/vendor/etc/fallback_fonts.xml"
 
#define LOCALE_FALLBACK_FONTS_SYSTEM_DIR   "/system/etc"
 
#define LOCALE_FALLBACK_FONTS_VENDOR_DIR   "/vendor/etc"
 
#define LOCALE_FALLBACK_FONTS_PREFIX   "fallback_fonts-"
 
#define LOCALE_FALLBACK_FONTS_SUFFIX   ".xml"
 
#define SK_FONT_FILE_PREFIX   "/fonts/"
 
#define MEMEQ(c, s, n)   memeq(c, s, sizeof(c) - 1, n)
 
#define ATTS_NON_NULL(a, i)   (a[i] != nullptr && a[i+1] != nullptr)
 
#define SK_FONTMGR_ANDROID_PARSER_PREFIX   "[SkFontMgr Android Parser] "
 
#define SK_FONTCONFIGPARSER_WARNING(message, ...)
 

Functions

static bool memeq (const char *s1, const char *s2, size_t n1, size_t n2)
 
static bool is_whitespace (char c)
 
static void trim_string (SkString *s)
 
static void parse_space_separated_languages (const char *value, size_t valueLen, TArray< SkLanguage, true > &languages)
 
static FontFamilylmpParser::find_family (FamilyData *self, const SkString &familyName)
 
static void XMLCALL start_element_handler (void *data, const char *tag, const char **attributes)
 
static void XMLCALL end_element_handler (void *data, const char *tag)
 
static void XMLCALL xml_entity_decl_handler (void *data, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
 
static int parse_config_file (const char *filename, SkTDArray< FontFamily * > &families, const SkString &basePath, bool isFallback)
 
static int append_system_font_families (SkTDArray< FontFamily * > &fontFamilies, const SkString &basePath)
 
static void append_fallback_font_families_for_locale (SkTDArray< FontFamily * > &fallbackFonts, const char *dir, const SkString &basePath)
 
static void append_system_fallback_font_families (SkTDArray< FontFamily * > &fallbackFonts, const SkString &basePath)
 
static void mixin_vendor_fallback_font_families (SkTDArray< FontFamily * > &fallbackFonts, const SkString &basePath)
 

Variables

static const TagHandler lmpParser::axisHandler
 
static const TagHandler lmpParser::fontHandler
 
static const TagHandler lmpParser::familyHandler
 
static const TagHandler lmpParser::aliasHandler
 
static const TagHandler lmpParser::familySetHandler
 
static const TagHandler jbParser::fileHandler
 
static const TagHandler jbParser::fileSetHandler
 
static const TagHandler jbParser::nameHandler
 
static const TagHandler jbParser::nameSetHandler
 
static const TagHandler jbParser::familyHandler
 
static const TagHandler jbParser::familySetHandler
 
static const TagHandler topLevelHandler
 
static const XML_Memory_Handling_Suite sk_XML_alloc
 

Macro Definition Documentation

◆ ATTS_NON_NULL

#define ATTS_NON_NULL (   a,
  i 
)    (a[i] != nullptr && a[i+1] != nullptr)

Definition at line 127 of file SkFontMgr_android_parser.cpp.

◆ FALLBACK_FONTS_FILE

#define FALLBACK_FONTS_FILE   "/system/etc/fallback_fonts.xml"

Definition at line 32 of file SkFontMgr_android_parser.cpp.

◆ LMP_SYSTEM_FONTS_FILE

#define LMP_SYSTEM_FONTS_FILE   "/system/etc/fonts.xml"

Definition at line 30 of file SkFontMgr_android_parser.cpp.

◆ LOCALE_FALLBACK_FONTS_PREFIX

#define LOCALE_FALLBACK_FONTS_PREFIX   "fallback_fonts-"

Definition at line 37 of file SkFontMgr_android_parser.cpp.

◆ LOCALE_FALLBACK_FONTS_SUFFIX

#define LOCALE_FALLBACK_FONTS_SUFFIX   ".xml"

Definition at line 38 of file SkFontMgr_android_parser.cpp.

◆ LOCALE_FALLBACK_FONTS_SYSTEM_DIR

#define LOCALE_FALLBACK_FONTS_SYSTEM_DIR   "/system/etc"

Definition at line 35 of file SkFontMgr_android_parser.cpp.

◆ LOCALE_FALLBACK_FONTS_VENDOR_DIR

#define LOCALE_FALLBACK_FONTS_VENDOR_DIR   "/vendor/etc"

Definition at line 36 of file SkFontMgr_android_parser.cpp.

◆ MEMEQ

#define MEMEQ (   c,
  s,
 
)    memeq(c, s, sizeof(c) - 1, n)

Definition at line 125 of file SkFontMgr_android_parser.cpp.

◆ OLD_SYSTEM_FONTS_FILE

#define OLD_SYSTEM_FONTS_FILE   "/system/etc/system_fonts.xml"

Definition at line 31 of file SkFontMgr_android_parser.cpp.

◆ SK_FONT_FILE_PREFIX

#define SK_FONT_FILE_PREFIX   "/fonts/"

Definition at line 41 of file SkFontMgr_android_parser.cpp.

◆ SK_FONTCONFIGPARSER_WARNING

#define SK_FONTCONFIGPARSER_WARNING (   message,
  ... 
)
Value:
SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "%s:%d:%d: warning: " message "\n", \
self->fFilename, \
(int)XML_GetCurrentLineNumber(self->fParser), \
(int)XML_GetCurrentColumnNumber(self->fParser), \
##__VA_ARGS__)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SK_FONTMGR_ANDROID_PARSER_PREFIX
Win32Message message

Definition at line 131 of file SkFontMgr_android_parser.cpp.

◆ SK_FONTMGR_ANDROID_PARSER_PREFIX

#define SK_FONTMGR_ANDROID_PARSER_PREFIX   "[SkFontMgr Android Parser] "

Definition at line 129 of file SkFontMgr_android_parser.cpp.

◆ VENDOR_FONTS_FILE

#define VENDOR_FONTS_FILE   "/vendor/etc/fallback_fonts.xml"

Definition at line 33 of file SkFontMgr_android_parser.cpp.

Function Documentation

◆ append_fallback_font_families_for_locale()

static void append_fallback_font_families_for_locale ( SkTDArray< FontFamily * > &  fallbackFonts,
const char *  dir,
const SkString basePath 
)
static

In some versions of Android prior to Android 4.2 (JellyBean MR1 at API Level 17) the fallback fonts for certain locales were encoded in their own XML files with a suffix that identified the locale. We search the provided directory for those files,add all of their entries to the fallback chain, and include the locale as part of each entry.

Definition at line 722 of file SkFontMgr_android_parser.cpp.

725{
726 SkOSFile::Iter iter(dir, nullptr);
727 SkString fileName;
728 while (iter.next(&fileName, false)) {
729 // The size of the prefix and suffix.
730 static const size_t fixedLen = sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1
731 + sizeof(LOCALE_FALLBACK_FONTS_SUFFIX) - 1;
732
733 // The size of the prefix, suffix, and a minimum valid language code
734 static const size_t minSize = fixedLen + 2;
735
736 if (fileName.size() < minSize ||
739 {
740 continue;
741 }
742
743 SkString locale(fileName.c_str() + sizeof(LOCALE_FALLBACK_FONTS_PREFIX) - 1,
744 fileName.size() - fixedLen);
745
746 SkString absoluteFilename;
747 absoluteFilename.printf("%s/%s", dir, fileName.c_str());
748
749 SkTDArray<FontFamily*> langSpecificFonts;
750 parse_config_file(absoluteFilename.c_str(), langSpecificFonts, basePath, true);
751
752 for (int i = 0; i < langSpecificFonts.size(); ++i) {
753 FontFamily* family = langSpecificFonts[i];
754 family->fLanguages.emplace_back(locale);
755 *fallbackFonts.append() = family;
756 }
757 }
758}
static int parse_config_file(const char *filename, SkTDArray< FontFamily * > &families, const SkString &basePath, bool isFallback)
#define LOCALE_FALLBACK_FONTS_SUFFIX
#define LOCALE_FALLBACK_FONTS_PREFIX
bool startsWith(const char prefixStr[]) const
Definition: SkString.h:140
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:534
size_t size() const
Definition: SkString.h:131
bool endsWith(const char suffixStr[]) const
Definition: SkString.h:146
const char * c_str() const
Definition: SkString.h:133
int size() const
Definition: SkTDArray.h:138
T * append()
Definition: SkTDArray.h:191
T & emplace_back(Args &&... args)
Definition: SkTArray.h:248
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
skia_private::TArray< SkLanguage, true > fLanguages

◆ append_system_fallback_font_families()

static void append_system_fallback_font_families ( SkTDArray< FontFamily * > &  fallbackFonts,
const SkString basePath 
)
static

Definition at line 760 of file SkFontMgr_android_parser.cpp.

762{
763 parse_config_file(FALLBACK_FONTS_FILE, fallbackFonts, basePath, true);
766 basePath);
767}
static void append_fallback_font_families_for_locale(SkTDArray< FontFamily * > &fallbackFonts, const char *dir, const SkString &basePath)
#define FALLBACK_FONTS_FILE
#define LOCALE_FALLBACK_FONTS_SYSTEM_DIR

◆ append_system_font_families()

static int append_system_font_families ( SkTDArray< FontFamily * > &  fontFamilies,
const SkString basePath 
)
static

Returns the version of the system font file actually found, negative if none.

Definition at line 704 of file SkFontMgr_android_parser.cpp.

706{
707 int initialCount = fontFamilies.size();
708 int version = parse_config_file(LMP_SYSTEM_FONTS_FILE, fontFamilies, basePath, false);
709 if (version < 0 || fontFamilies.size() == initialCount) {
710 version = parse_config_file(OLD_SYSTEM_FONTS_FILE, fontFamilies, basePath, false);
711 }
712 return version;
713}
#define OLD_SYSTEM_FONTS_FILE
#define LMP_SYSTEM_FONTS_FILE

◆ end_element_handler()

static void XMLCALL end_element_handler ( void *  data,
const char *  tag 
)
static

Definition at line 601 of file SkFontMgr_android_parser.cpp.

601 {
602 FamilyData* self = static_cast<FamilyData*>(data);
603 --self->fDepth;
604
605 if (!self->fSkip) {
606 const TagHandler* child = self->fHandler.back();
607 if (child->end) {
608 child->end(self, tag);
609 }
610 self->fHandler.pop_back();
611 const TagHandler* parent = self->fHandler.back();
612 XML_SetCharacterDataHandler(self->fParser, parent->chars);
613 }
614
615 if (self->fSkip == self->fDepth) {
616 self->fSkip = 0;
617 const TagHandler* parent = self->fHandler.back();
618 XML_SetCharacterDataHandler(self->fParser, parent->chars);
619 }
620}
XML_CharacterDataHandler chars
void(* end)(FamilyData *data, const char *tag)
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ is_whitespace()

static bool is_whitespace ( char  c)
static

Definition at line 138 of file SkFontMgr_android_parser.cpp.

138 {
139 return c == ' ' || c == '\n'|| c == '\r' || c == '\t';
140}

◆ memeq()

static bool memeq ( const char *  s1,
const char *  s2,
size_t  n1,
size_t  n2 
)
static

Definition at line 122 of file SkFontMgr_android_parser.cpp.

122 {
123 return n1 == n2 && 0 == memcmp(s1, s2, n1);
124}

◆ mixin_vendor_fallback_font_families()

static void mixin_vendor_fallback_font_families ( SkTDArray< FontFamily * > &  fallbackFonts,
const SkString basePath 
)
static

Definition at line 769 of file SkFontMgr_android_parser.cpp.

771{
772 SkTDArray<FontFamily*> vendorFonts;
773 parse_config_file(VENDOR_FONTS_FILE, vendorFonts, basePath, true);
776 basePath);
777
778 // This loop inserts the vendor fallback fonts in the correct order in the
779 // overall fallbacks list.
780 int currentOrder = -1;
781 for (int i = 0; i < vendorFonts.size(); ++i) {
782 FontFamily* family = vendorFonts[i];
783 int order = family->fOrder;
784 if (order < 0) {
785 if (currentOrder < 0) {
786 // Default case - just add it to the end of the fallback list
787 *fallbackFonts.append() = family;
788 } else {
789 // no order specified on this font, but we're incrementing the order
790 // based on an earlier order insertion request
791 *fallbackFonts.insert(currentOrder++) = family;
792 }
793 } else {
794 // Add the font into the fallback list in the specified order. Set
795 // currentOrder for correct placement of other fonts in the vendor list.
796 *fallbackFonts.insert(order) = family;
797 currentOrder = order + 1;
798 }
799 }
800}
#define LOCALE_FALLBACK_FONTS_VENDOR_DIR
#define VENDOR_FONTS_FILE
T * insert(int index)
Definition: SkTDArray.h:203

◆ parse_config_file()

static int parse_config_file ( const char *  filename,
SkTDArray< FontFamily * > &  families,
const SkString basePath,
bool  isFallback 
)
static

This function parses the given filename and stores the results in the given families array. Returns the version of the file, negative if the file does not exist.

Definition at line 647 of file SkFontMgr_android_parser.cpp.

649{
650 SkFILEStream file(filename);
651
652 // Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml)
653 // are optional - failure here is okay because one of these optional files may not exist.
654 if (!file.isValid()) {
655 SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "'%s' could not be opened\n", filename);
656 return -1;
657 }
658
660 XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr));
661 if (!parser) {
662 SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "could not create XML parser\n");
663 return -1;
664 }
665
666 FamilyData self(parser, families, basePath, isFallback, filename, &topLevelHandler);
667 XML_SetUserData(parser, &self);
668
669 // Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340
670 XML_SetEntityDeclHandler(parser, xml_entity_decl_handler);
671
672 // Start parsing oldschool; switch these in flight if we detect a newer version of the file.
673 XML_SetElementHandler(parser, start_element_handler, end_element_handler);
674
675 // One would assume it would be faster to have a buffer on the stack and call XML_Parse.
676 // But XML_Parse will call XML_GetBuffer anyway and memmove the passed buffer into it.
677 // (Unless XML_CONTEXT_BYTES is undefined, but all users define it.)
678 // In debug, buffer a small odd number of bytes to detect slicing in XML_CharacterDataHandler.
679 static const int bufferSize = 512 SkDEBUGCODE( - 507);
680 bool done = false;
681 while (!done) {
682 void* buffer = XML_GetBuffer(parser, bufferSize);
683 if (!buffer) {
684 SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "could not buffer enough to continue\n");
685 return -1;
686 }
687 size_t len = file.read(buffer, bufferSize);
688 done = file.isAtEnd();
689 XML_Status status = XML_ParseBuffer(parser, len, done);
690 if (XML_STATUS_ERROR == status) {
691 XML_Error error = XML_GetErrorCode(parser);
692 int line = XML_GetCurrentLineNumber(parser);
693 int column = XML_GetCurrentColumnNumber(parser);
694 const XML_LChar* errorString = XML_ErrorString(error);
695 SkDebugf(SK_FONTMGR_ANDROID_PARSER_PREFIX "%s:%d:%d error %d: %s.\n",
696 filename, line, column, error, errorString);
697 return -1;
698 }
699 }
700 return self.fVersion;
701}
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition: DM.cpp:263
static void XMLCALL start_element_handler(void *data, const char *tag, const char **attributes)
static void XMLCALL end_element_handler(void *data, const char *tag)
static void XMLCALL xml_entity_decl_handler(void *data, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
static const TagHandler topLevelHandler
static const XML_Memory_Handling_Suite sk_XML_alloc
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
const uint8_t uint32_t uint32_t GError ** error
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
parser
Definition: zip.py:78

◆ parse_space_separated_languages()

static void parse_space_separated_languages ( const char *  value,
size_t  valueLen,
TArray< SkLanguage, true > &  languages 
)
static

Definition at line 157 of file SkFontMgr_android_parser.cpp.

159{
160 size_t i = 0;
161 while (true) {
162 for (; i < valueLen && is_whitespace(value[i]); ++i) { }
163 if (i == valueLen) { break; }
164 size_t j;
165 for (j = i + 1; j < valueLen && !is_whitespace(value[j]); ++j) { }
166 languages.emplace_back(value + i, j - i);
167 i = j;
168 if (i == valueLen) { break; }
169 }
170}
static bool is_whitespace(char c)
uint8_t value

◆ start_element_handler()

static void XMLCALL start_element_handler ( void *  data,
const char *  tag,
const char **  attributes 
)
static

Definition at line 579 of file SkFontMgr_android_parser.cpp.

579 {
580 FamilyData* self = static_cast<FamilyData*>(data);
581
582 if (!self->fSkip) {
583 const TagHandler* parent = self->fHandler.back();
584 const TagHandler* child = parent->tag ? parent->tag(self, tag, attributes) : nullptr;
585 if (child) {
586 if (child->start) {
587 child->start(self, tag, attributes);
588 }
589 self->fHandler.push_back(child);
590 XML_SetCharacterDataHandler(self->fParser, child->chars);
591 } else {
592 SK_FONTCONFIGPARSER_WARNING("'%s' tag not recognized, skipping", tag);
593 XML_SetCharacterDataHandler(self->fParser, nullptr);
594 self->fSkip = self->fDepth;
595 }
596 }
597
598 ++self->fDepth;
599}
#define SK_FONTCONFIGPARSER_WARNING(message,...)
const TagHandler *(* tag)(FamilyData *data, const char *tag, const char **attributes)
void(* start)(FamilyData *data, const char *tag, const char **attributes)

◆ trim_string()

static void trim_string ( SkString s)
static

Definition at line 142 of file SkFontMgr_android_parser.cpp.

142 {
143 char* str = s->data();
144 const char* start = str; // start is inclusive
145 const char* end = start + s->size(); // end is exclusive
146 while (is_whitespace(*start)) { ++start; }
147 if (start != end) {
148 --end; // make end inclusive
149 while (is_whitespace(*end)) { --end; }
150 ++end; // make end exclusive
151 }
152 size_t len = end - start;
153 memmove(str, start, len);
154 s->resize(len);
155}
struct MyStruct s
glong glong end

◆ xml_entity_decl_handler()

static void XMLCALL xml_entity_decl_handler ( void *  data,
const XML_Char *  entityName,
int  is_parameter_entity,
const XML_Char *  value,
int  value_length,
const XML_Char *  base,
const XML_Char *  systemId,
const XML_Char *  publicId,
const XML_Char *  notationName 
)
static

Definition at line 622 of file SkFontMgr_android_parser.cpp.

631{
632 FamilyData* self = static_cast<FamilyData*>(data);
633 SK_FONTCONFIGPARSER_WARNING("'%s' entity declaration found, stopping processing", entityName);
634 XML_StopParser(self->fParser, XML_FALSE);
635}

Variable Documentation

◆ sk_XML_alloc

const XML_Memory_Handling_Suite sk_XML_alloc
static
Initial value:
= {
}
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
SK_API void * sk_realloc_throw(void *buffer, size_t size)

Definition at line 637 of file SkFontMgr_android_parser.cpp.

◆ topLevelHandler

const TagHandler topLevelHandler
static
Initial value:
= {
nullptr,
nullptr,
[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* {
size_t len = strlen(tag);
if (MEMEQ("familyset", tag, len)) {
for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) {
const char* name = attributes[i];
size_t nameLen = strlen(name);
if (MEMEQ("version", name, nameLen)) {
const char* value = attributes[i+1];
if (self->fVersion >= 21) {
}
}
}
}
}
return nullptr;
},
nullptr,
}
#define ATTS_NON_NULL(a, i)
#define MEMEQ(c, s, n)
bool parse_non_negative_integer(const char *s, T *value)
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
static const TagHandler familySetHandler
static const TagHandler familySetHandler

Definition at line 553 of file SkFontMgr_android_parser.cpp.