Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions tools/font-subset/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 "
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions tools/font-subset/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@
(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',
Expand Down