Allow optional codepoints to be expressed to the font subset generator. (flutter/engine#44864)

This is the engine side change to fix https://github.com/flutter/flutter/issues/132711. There will be a subsequent framework change to express the space character as an "optional" character.
This commit is contained in:
Jackson Gardner 2023-08-18 15:08:10 -07:00 committed by GitHub
parent a1a247f7a2
commit ab84ec613c
2 changed files with 31 additions and 5 deletions

View File

@ -13,15 +13,22 @@
#include "hb_wrappers.h"
hb_codepoint_t ParseCodepoint(const std::string& arg) {
hb_codepoint_t ParseCodepoint(std::string_view arg, bool& optional) {
constexpr std::string_view kOptionalPrefix = "optional:";
if (arg.substr(0, kOptionalPrefix.length()) == kOptionalPrefix) {
optional = true;
arg = arg.substr(kOptionalPrefix.length());
} else {
optional = false;
}
uint64_t value = 0;
// Check for \u123, u123, otherwise let strtoul work it out.
if (arg[0] == 'u') {
value = strtoul(arg.c_str() + 1, nullptr, 16);
value = strtoul(arg.data() + 1, nullptr, 16);
} else if (arg[0] == '\\' && arg[1] == 'u') {
value = strtoul(arg.c_str() + 2, nullptr, 16);
value = strtoul(arg.data() + 2, nullptr, 16);
} else {
value = strtoul(arg.c_str(), nullptr, 0);
value = strtoul(arg.data(), nullptr, 0);
}
if (value == 0 || value > std::numeric_limits<hb_codepoint_t>::max()) {
std::cerr << "The value '" << arg << "' (" << value
@ -43,6 +50,10 @@ void Usage() {
"and must be input as decimal numbers (123), hexadecimal "
"numbers (0x7B), or unicode hexadecimal characters (\\u7B)."
<< std::endl;
std::cout << "Codepoints can be prefixed by the string \"optional:\" to "
"specify that the codepoint can be omitted if it isn't found "
"in the input font file."
<< std::endl;
std::cout << "Input terminates with a newline." << std::endl;
std::cout
<< "This program will de-duplicate codepoints if the same codepoint is "
@ -113,13 +124,21 @@ int main(int argc, char** argv) {
hb_face_collect_unicodes(font_face.get(), actual_codepoints.get());
std::string raw_codepoint;
while (std::cin >> raw_codepoint) {
auto codepoint = ParseCodepoint(raw_codepoint);
bool optional = false;
auto codepoint =
ParseCodepoint(std::string_view(raw_codepoint), optional);
if (!codepoint) {
std::cerr << "Invalid codepoint for " << raw_codepoint << "; exiting."
<< std::endl;
return -1;
}
if (!hb_set_has(actual_codepoints.get(), codepoint)) {
if (optional) {
// Code point is optional, so omit it.
continue;
}
std::cerr << "Codepoint " << raw_codepoint
<< " not found in font, aborting." << std::endl;
return -1;

View File

@ -60,6 +60,13 @@ COMPARE_TESTS = (
(False, '1.ttf', MATERIAL_TTF, [r'57348'
]), # False because different codepoint
(True, '2.ttf', MATERIAL_TTF, [r'0xE003', r'0xE004']),
(True, '2.ttf', MATERIAL_TTF, [r'0xE003', r'optional:0xE004'
]), # Optional codepoint that is found
(True, '2.ttf', MATERIAL_TTF, [
r'0xE003',
r'0xE004',
r'optional:0x12',
]), # Optional codepoint that is not found
(True, '2.ttf', MATERIAL_TTF, [
r'0xE003',
r'0xE004',