[HarfBuzz] harfbuzz: Branch 'master' - 28 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Mon Feb 5 01:20:33 UTC 2018
CMakeLists.txt | 14
configure.ac | 2
src/Makefile.am | 17 -
src/Makefile.sources | 9
src/harfbuzz-subset.pc.in | 12
src/hb-subset.cc | 155 ++++++++++
src/hb-subset.h | 89 +++++
src/hb.h | 1
test/CMakeLists.txt | 1
test/Makefile.am | 2
test/api/Makefile.am | 1
test/api/test-subset.c | 67 ++++
test/subset/CMakeLists.txt | 9
test/subset/Makefile.am | 22 +
test/subset/data/Makefile.am | 23 +
test/subset/data/Makefile.sources | 9
test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf |binary
test/subset/data/fonts/Roboto-Regular.abc.ttf |binary
test/subset/data/tests/basics.tests | 8
test/subset/generate-expected-outputs.py | 41 ++
test/subset/run-tests.py | 86 +++++
test/subset/subset_test_suite.py | 82 +++++
util/Makefile.am | 5
util/Makefile.sources | 7
util/hb-subset.cc | 110 +++++++
25 files changed, 767 insertions(+), 5 deletions(-)
New commits:
commit ae39fc8171b2c26d4ae64954a8055732c9241bcc
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Feb 4 20:18:52 2018 -0500
[subset] Build hb-subset into separate libharfbuzz-subset.so
diff --git a/src/Makefile.am b/src/Makefile.am
index dd1c7ae6..59ca6482 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,9 +27,7 @@ HBNONPCLIBS =
HBDEPS =
HBSOURCES = $(HB_BASE_sources)
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
-HBSOURCES += $(HB_SUBSET_sources)
HBHEADERS = $(HB_BASE_headers)
-HBHEADERS += $(HB_SUBSET_headers)
HBNODISTHEADERS = $(HB_NODIST_headers)
if HAVE_OT
@@ -137,6 +135,15 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = harfbuzz.pc
EXTRA_DIST += harfbuzz.pc.in
+lib_LTLIBRARIES += libharfbuzz-subset.la
+libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources)
+libharfbuzz_subset_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS)
+libharfbuzz_subset_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
+libharfbuzz_subset_la_LIBADD = libharfbuzz.la
+pkginclude_HEADERS += $(HB_SUBSET_headers)
+pkgconfig_DATA += harfbuzz-subset.pc
+EXTRA_DIST += harfbuzz-subset.pc.in
+
FUZZING_CPPFLAGS = \
-DHB_NDEBUG \
-DHB_MAX_NESTING_LEVEL=3 \
@@ -166,8 +173,8 @@ HBHEADERS += $(HB_ICU_headers)
else
lib_LTLIBRARIES += libharfbuzz-icu.la
libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources)
-libharfbuzz_icu_la_CPPFLAGS = $(ICU_CFLAGS)
-libharfbuzz_icu_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
+libharfbuzz_icu_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(ICU_CFLAGS)
+libharfbuzz_icu_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la
pkginclude_HEADERS += $(HB_ICU_headers)
pkgconfig_DATA += harfbuzz-icu.pc
@@ -179,8 +186,8 @@ if HAVE_GOBJECT
lib_LTLIBRARIES += libharfbuzz-gobject.la
libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_sources)
nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_ENUM_sources)
-libharfbuzz_gobject_la_CPPFLAGS = $(GOBJECT_CFLAGS)
-libharfbuzz_gobject_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
+libharfbuzz_gobject_la_CPPFLAGS = $(libharfbuzz_la_CPPFLAGS) $(GOBJECT_CFLAGS)
+libharfbuzz_gobject_la_LDFLAGS = $(libharfbuzz_la_LDFLAGS)
libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la
pkginclude_HEADERS += $(HB_GOBJECT_headers)
nodist_pkginclude_HEADERS += $(HB_GOBJECT_ENUM_headers)
diff --git a/src/harfbuzz-subset.pc.in b/src/harfbuzz-subset.pc.in
new file mode 100644
index 00000000..5da64b3f
--- /dev/null
+++ b/src/harfbuzz-subset.pc.in
@@ -0,0 +1,12 @@
+prefix=%prefix%
+exec_prefix=%exec_prefix%
+libdir=%libdir%
+includedir=%includedir%
+
+Name: harfbuzz
+Description: HarfBuzz font subsetter
+Version: %VERSION%
+
+Requires: harfbuzz
+Libs: -L${libdir} -lharfbuzz-subset
+Cflags: -I${includedir}/harfbuzz
diff --git a/util/Makefile.am b/util/Makefile.am
index 283dd91f..3810e15e 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -47,6 +47,8 @@ hb_shape_SOURCES = $(HB_SHAPE_sources)
bin_PROGRAMS += hb-shape
hb_subset_SOURCES = $(HB_SUBSET_sources)
+hb_subset_SOURCES = $(HB_SUBSET_sources)
+hb_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
bin_PROGRAMS += hb-subset
if HAVE_OT
commit eac20e459564134e0087497ed76b1c84195ad7e3
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Feb 4 20:08:50 2018 -0500
[subset] Minor
diff --git a/util/Makefile.am b/util/Makefile.am
index cd5e31cb..283dd91f 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -46,7 +46,7 @@ endif # HAVE_FREETYPE
hb_shape_SOURCES = $(HB_SHAPE_sources)
bin_PROGRAMS += hb-shape
-hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
+hb_subset_SOURCES = $(HB_SUBSET_sources)
bin_PROGRAMS += hb-subset
if HAVE_OT
diff --git a/util/Makefile.sources b/util/Makefile.sources
index 6c815d26..c4516ebc 100644
--- a/util/Makefile.sources
+++ b/util/Makefile.sources
@@ -29,7 +29,7 @@ HB_OT_SHAPE_CLOSURE_sources = \
main-font-text.hh \
$(NULL)
-HB_SUBSET_CLI_sources = \
+HB_SUBSET_sources = \
hb-subset.cc \
options.cc \
options.hh \
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 808cb04f..21d0f767 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -52,8 +52,8 @@ struct subset_consumer_t
{
}
- hb_bool_t
- write_file (const char *output_file, hb_blob_t *blob) {
+ hb_bool_t
+ write_file (const char *output_file, hb_blob_t *blob) {
unsigned int data_length;
const char* data = hb_blob_get_data (blob, &data_length);
@@ -68,10 +68,10 @@ struct subset_consumer_t
return false;
}
if (bytes_written != data_length) {
- fprintf(stderr, "Expected %u bytes written, got %ld\n", data_length,
+ fprintf(stderr, "Expected %u bytes written, got %ld\n", data_length,
bytes_written);
return false;
- }
+ }
return true;
}
@@ -80,7 +80,7 @@ struct subset_consumer_t
// TODO(Q1) check for errors from creates and such
hb_subset_profile_t *subset_profile = hb_subset_profile_create();
hb_subset_input_t *subset_input = hb_subset_input_create();
- hb_face_t *face = hb_font_get_face (font);
+ hb_face_t *face = hb_font_get_face (font);
hb_subset_face_t *subset_face = hb_subset_face_create(face);
hb_blob_t *result = nullptr;
commit 257022b1789f928975b04b5d214bbe9192e11997
Merge: 3615f344 edcd3b80
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Feb 4 20:01:35 2018 -0500
Merge pull request #745 from googlefonts/master
Interface for hb_subset, skeleton for the hb-subset cli, and basic testing rigging.
commit edcd3b80e9617ec8c4c4a55536938fb510b6aeba
Author: Rod Sheeter <rsheeter at google.com>
Date: Sun Feb 4 12:31:24 2018 -0800
Actually call hb_subset
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 3dda9219..808cb04f 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -28,6 +28,7 @@
#include <unistd.h>
#include "main-font-text.hh"
+#include "hb-subset.h"
/*
* Command line interface to the harfbuzz font subsetter.
@@ -51,28 +52,44 @@ struct subset_consumer_t
{
}
- void finish (const font_options_t *font_opts)
- {
- hb_face_t *face = hb_font_get_face (font);
- hb_blob_t *result = hb_face_reference_blob (face);
+ hb_bool_t
+ write_file (const char *output_file, hb_blob_t *blob) {
unsigned int data_length;
- const char* data = hb_blob_get_data (result, &data_length);
+ const char* data = hb_blob_get_data (blob, &data_length);
- int fd_out = open(options.output_file, O_CREAT | O_WRONLY, S_IRWXU);
- if (fd_out != -1) {
- ssize_t bytes_written = write(fd_out, data, data_length);
- if (bytes_written == -1) {
- fprintf(stderr, "Unable to write output file");
- failed = true;
- } else if (bytes_written != data_length) {
- fprintf(stderr, "Wrong number of bytes written");
- failed = true;
- }
- } else {
+ int fd_out = open(output_file, O_CREAT | O_WRONLY, S_IRWXU);
+ if (fd_out == -1) {
fprintf(stderr, "Unable to open output file");
- failed = true;
+ return false;
}
+ ssize_t bytes_written = write(fd_out, data, data_length);
+ if (bytes_written == -1) {
+ fprintf(stderr, "Unable to write output file\n");
+ return false;
+ }
+ if (bytes_written != data_length) {
+ fprintf(stderr, "Expected %u bytes written, got %ld\n", data_length,
+ bytes_written);
+ return false;
+ }
+ return true;
+ }
+
+ void finish (const font_options_t *font_opts)
+ {
+ // TODO(Q1) check for errors from creates and such
+ hb_subset_profile_t *subset_profile = hb_subset_profile_create();
+ hb_subset_input_t *subset_input = hb_subset_input_create();
+ hb_face_t *face = hb_font_get_face (font);
+ hb_subset_face_t *subset_face = hb_subset_face_create(face);
+
+ hb_blob_t *result = nullptr;
+ failed = !(hb_subset(subset_profile, subset_input, subset_face, &result)
+ && write_file(options.output_file, result));
+ hb_subset_profile_destroy (subset_profile);
+ hb_subset_input_destroy (subset_input);
+ hb_subset_face_destroy (subset_face);
hb_blob_destroy (result);
hb_font_destroy (font);
}
commit 7b01761adef6f64f1139b30c985aa5f52314073a
Author: Garret Rieger <grieger at google.com>
Date: Fri Feb 2 17:54:11 2018 -0800
Add CMakeLists.txt to dist files for subset test.
diff --git a/test/subset/Makefile.am b/test/subset/Makefile.am
index dfc312e6..336d33df 100644
--- a/test/subset/Makefile.am
+++ b/test/subset/Makefile.am
@@ -10,6 +10,7 @@ lib:
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
EXTRA_DIST += \
+ CMakeLists.txt \
run-tests.py \
subset_test_suite.py \
$(NULL)
commit f83a43b56134188c2e1f3496d40ec0cd9109f250
Author: Garret Rieger <grieger at google.com>
Date: Fri Feb 2 17:50:45 2018 -0800
Add CMake configuration for all of the new subsetting code.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e067edf..bfe0e306 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -171,6 +171,12 @@ add_prefix_to_list(HB_OT_sources "${PROJECT_SOURCE_DIR}/src/")
extract_make_variable(HB_OT_headers ${SRCSOURCES})
add_prefix_to_list(HB_OT_headers "${PROJECT_SOURCE_DIR}/src/")
+extract_make_variable(HB_SUBSET_sources ${SRCSOURCES})
+add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/")
+
+extract_make_variable(HB_SUBSET_headers ${SRCSOURCES})
+add_prefix_to_list(HB_SUBSET_headers "${PROJECT_SOURCE_DIR}/src/")
+
extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES})
extract_make_variable(HB_OT_RAGEL_GENERATED_sources ${SRCSOURCES})
if (IN_HB_DIST)
@@ -185,6 +191,8 @@ extract_make_variable(HB_VIEW_sources ${UTILSOURCES})
add_prefix_to_list(HB_VIEW_sources "${PROJECT_SOURCE_DIR}/util/")
extract_make_variable(HB_SHAPE_sources ${UTILSOURCES})
add_prefix_to_list(HB_SHAPE_sources "${PROJECT_SOURCE_DIR}/util/")
+extract_make_variable(HB_SUBSET_CLI_sources ${UTILSOURCES})
+add_prefix_to_list(HB_SUBSET_CLI_sources "${PROJECT_SOURCE_DIR}/util/")
extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES})
add_prefix_to_list(HB_OT_SHAPE_CLOSURE_sources "${PROJECT_SOURCE_DIR}/util/")
@@ -246,6 +254,8 @@ set (project_sources
${HB_FALLBACK_sources}
${HB_OT_sources}
${HB_OT_RAGEL_GENERATED_sources}
+
+ ${HB_SUBSET_sources}
)
set (project_extra_sources)
@@ -255,6 +265,7 @@ set (project_headers
${HB_BASE_headers}
${HB_OT_headers}
+ ${HB_SUBSET_headers}
)
@@ -708,6 +719,9 @@ if (HB_BUILD_UTILS)
add_executable(hb-shape ${HB_SHAPE_sources})
target_link_libraries(hb-shape harfbuzz)
+ add_executable(hb-subset ${HB_SUBSET_CLI_sources})
+ target_link_libraries(hb-subset harfbuzz)
+
add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources})
target_link_libraries(hb-ot-shape-closure harfbuzz)
diff --git a/src/Makefile.sources b/src/Makefile.sources
index f223fcfe..0b9beb96 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -182,8 +182,13 @@ HB_ICU_sources = hb-icu.cc
HB_ICU_headers = hb-icu.h
# Sources for libharfbuzz-subset
-HB_SUBSET_sources = hb-subset.cc
-HB_SUBSET_headers = hb-subset.h
+HB_SUBSET_sources = \
+ hb-subset.cc \
+ $(NULL)
+
+HB_SUBSET_headers = \
+ hb-subset.h \
+ $(NULL)
HB_GOBJECT_sources = hb-gobject-structs.cc
HB_GOBJECT_STRUCTS_headers = hb-gobject-structs.h
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2c97f4f8..d2b19942 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,3 +1,4 @@
add_subdirectory(api)
add_subdirectory(shaping)
+add_subdirectory(subset)
add_subdirectory(fuzzing)
diff --git a/test/subset/CMakeLists.txt b/test/subset/CMakeLists.txt
new file mode 100644
index 00000000..0a1e8f95
--- /dev/null
+++ b/test/subset/CMakeLists.txt
@@ -0,0 +1,9 @@
+if (HB_BUILD_UTILS)
+ file (READ "${CMAKE_CURRENT_SOURCE_DIR}/data/Makefile.sources" SOURCES)
+ extract_make_variable (TESTS ${SOURCES})
+ foreach (test IN ITEMS ${TESTS})
+ add_test (NAME ${test}
+ COMMAND python run-tests.py $<TARGET_FILE:hb-subset> "data/${test}"
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ endforeach ()
+endif ()
diff --git a/util/Makefile.am b/util/Makefile.am
index 283dd91f..cd5e31cb 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -46,7 +46,7 @@ endif # HAVE_FREETYPE
hb_shape_SOURCES = $(HB_SHAPE_sources)
bin_PROGRAMS += hb-shape
-hb_subset_SOURCES = $(HB_SUBSET_sources)
+hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
bin_PROGRAMS += hb-subset
if HAVE_OT
diff --git a/util/Makefile.sources b/util/Makefile.sources
index c4516ebc..6c815d26 100644
--- a/util/Makefile.sources
+++ b/util/Makefile.sources
@@ -29,7 +29,7 @@ HB_OT_SHAPE_CLOSURE_sources = \
main-font-text.hh \
$(NULL)
-HB_SUBSET_sources = \
+HB_SUBSET_CLI_sources = \
hb-subset.cc \
options.cc \
options.hh \
commit 5bc0cda179bca452145d4523eeba415986edb6e3
Author: Garret Rieger <grieger at google.com>
Date: Fri Feb 2 17:49:14 2018 -0800
Add missing unistd header to hb-subset.
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index f5e8aaf3..3dda9219 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -25,6 +25,8 @@
* Google Author(s): Garret Rieger, Rod Sheeter
*/
+#include <unistd.h>
+
#include "main-font-text.hh"
/*
commit 06fe297f2a9fc6ee98179ddd26ef089b7fdb9e74
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 1 18:36:15 2018 -0800
Properly include subset test data files.
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index ecdab376..f1234db8 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -7,9 +7,9 @@ SUBDIRS =
EXTRA_DIST = \
$(TESTS) \
- expected/basics/*.ttf \
- fonts/*.ttf \
- profiles/*.txt \
+ expected/basics \
+ fonts \
+ profiles \
$(NULL)
# Convenience targets:
commit 058b1260ad1105d0d8d6bf21f8f65a336e735bd2
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 1 18:22:14 2018 -0800
Re-write hb-subset utility to use main-font-text driver.
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 0b4b96a6..b0054802 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -30,22 +30,25 @@ def fail_test(test, cli_args, message):
print ('Test State:')
print (' test.font_path %s' % os.path.abspath(test.font_path))
print (' test.profile_path %s' % os.path.abspath(test.profile_path))
- print (' test.unicodes %s' % test.unicodes())
+ print (' test.unicodes %s' % test.unicodes())
expected_file = os.path.join(test_suite.get_output_directory(),
- test.get_font_name())
- print (' expected_file %s' % os.path.abspath(expected_file))
+ test.get_font_name())
+ print (' expected_file %s' % os.path.abspath(expected_file))
return 1
def run_test(test):
- out_file = os.path.join(tempfile.mkdtemp(), test.get_font_name() + '-subset.ttf')
- cli_args = [hb_subset, test.font_path, out_file, "--unicodes=%s" % test.unicodes()]
+ out_file = os.path.join(tempfile.mkdtemp(), test.get_font_name() + '-subset.ttf')
+ cli_args = [hb_subset,
+ "--font-file=" + test.font_path,
+ "--output-file=" + out_file,
+ "--unicodes=%s" % test.unicodes()]
_, return_code = cmd(cli_args)
if return_code:
return fail_test(test, cli_args, "%s returned %d" % (' '.join(cli_args), return_code))
expected = read_binary(os.path.join(test_suite.get_output_directory(),
- test.get_font_name()))
+ test.get_font_name()))
actual = read_binary(out_file)
if len(actual) != len(expected):
diff --git a/util/Makefile.sources b/util/Makefile.sources
index 94a5fa8a..c4516ebc 100644
--- a/util/Makefile.sources
+++ b/util/Makefile.sources
@@ -31,4 +31,7 @@ HB_OT_SHAPE_CLOSURE_sources = \
HB_SUBSET_sources = \
hb-subset.cc \
+ options.cc \
+ options.hh \
+ main-font-text.hh \
$(NULL)
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 4beb6a1c..f5e8aaf3 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -1,82 +1,91 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
+/*
+ * Copyright © 2010 Behdad Esfahbod
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Rod Sheeter
+ */
-#include "hb-private.hh"
-#include "hb-blob.h"
+#include "main-font-text.hh"
-int
-main (int argc, char **argv)
-{
- int exit_code = 0;
+/*
+ * Command line interface to the harfbuzz font subsetter.
+ */
- if (argc != 4) {
- fprintf(stderr, "Must have 4 args\n");
- exit(1);
- }
+struct subset_consumer_t
+{
+ subset_consumer_t (option_parser_t *parser)
+ : failed (false), options(parser) {}
- int fd = open(argv[1], O_RDONLY);
- if (fd == -1) {
- perror("Unable to open font file");
- exit(1);
+ void init (hb_buffer_t *buffer_,
+ const font_options_t *font_opts)
+ {
+ font = hb_font_reference (font_opts->get_font ());
}
- void *mapped_file = MAP_FAILED;
- int fd_out = -1;
-
- struct stat stat;
- if (fstat(fd, &stat) != -1) {
-
- mapped_file = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (mapped_file == MAP_FAILED) {
- perror("Failed to map file");
- }
- } else {
- perror("Unable to fstat");
+ void consume_line (const char *text,
+ unsigned int text_len,
+ const char *text_before,
+ const char *text_after)
+ {
}
- if (mapped_file != MAP_FAILED) {
- hb_blob_t *font_blob = hb_blob_create(static_cast<const char*>(mapped_file),
- stat.st_size,
- HB_MEMORY_MODE_READONLY, nullptr,
- nullptr);
+ void finish (const font_options_t *font_opts)
+ {
+ hb_face_t *face = hb_font_get_face (font);
+ hb_blob_t *result = hb_face_reference_blob (face);
+ unsigned int data_length;
+ const char* data = hb_blob_get_data (result, &data_length);
- fd_out = open(argv[2], O_CREAT | O_WRONLY, S_IRWXU);
+ int fd_out = open(options.output_file, O_CREAT | O_WRONLY, S_IRWXU);
if (fd_out != -1) {
- ssize_t bytes_written = write(fd_out, mapped_file, stat.st_size);
+ ssize_t bytes_written = write(fd_out, data, data_length);
if (bytes_written == -1) {
- perror("Unable to write output file");
- exit_code = 1;
- } else if (bytes_written != stat.st_size) {
+ fprintf(stderr, "Unable to write output file");
+ failed = true;
+ } else if (bytes_written != data_length) {
fprintf(stderr, "Wrong number of bytes written");
- exit_code = 1;
+ failed = true;
}
} else {
- perror("Unable to open output file");
- exit_code = 1;
+ fprintf(stderr, "Unable to open output file");
+ failed = true;
}
- }
- if (mapped_file != MAP_FAILED) {
- if (munmap(mapped_file, stat.st_size) == -1) {
- perror("Unable to unmap file");
- exit_code = 1;
- }
+ hb_blob_destroy (result);
+ hb_font_destroy (font);
}
- if (fd_out != -1 && close(fd_out) == -1) {
- perror("Unable to close output file");
- exit_code = 1;
- }
+ public:
+ bool failed;
- if (fd != -1 && close(fd) == -1) {
- perror("Unable to close file");
- exit_code = 1;
- }
+ private:
+ output_options_t options;
+ hb_font_t *font;
+};
- return exit_code;
+int
+main (int argc, char **argv)
+{
+ main_font_text_t<subset_consumer_t, 10, 0> driver;
+ return driver.main (argc, argv);
}
commit ede84ffa426edb950c4ec4f89833c85475a1c64f
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 1 17:17:36 2018 -0800
Whitespace
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 5aafbe19..4beb6a1c 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -15,7 +15,7 @@ main (int argc, char **argv)
int exit_code = 0;
if (argc != 4) {
- fprintf(stderr, "Must have 4 args\n");
+ fprintf(stderr, "Must have 4 args\n");
exit(1);
}
@@ -39,26 +39,26 @@ main (int argc, char **argv)
perror("Unable to fstat");
}
- if (mapped_file != MAP_FAILED) {
- hb_blob_t *font_blob = hb_blob_create(static_cast<const char*>(mapped_file),
- stat.st_size,
- HB_MEMORY_MODE_READONLY, nullptr,
- nullptr);
+ if (mapped_file != MAP_FAILED) {
+ hb_blob_t *font_blob = hb_blob_create(static_cast<const char*>(mapped_file),
+ stat.st_size,
+ HB_MEMORY_MODE_READONLY, nullptr,
+ nullptr);
- fd_out = open(argv[2], O_CREAT | O_WRONLY, S_IRWXU);
- if (fd_out != -1) {
- ssize_t bytes_written = write(fd_out, mapped_file, stat.st_size);
- if (bytes_written == -1) {
- perror("Unable to write output file");
- exit_code = 1;
- } else if (bytes_written != stat.st_size) {
- fprintf(stderr, "Wrong number of bytes written");
- exit_code = 1;
- }
- } else {
- perror("Unable to open output file");
+ fd_out = open(argv[2], O_CREAT | O_WRONLY, S_IRWXU);
+ if (fd_out != -1) {
+ ssize_t bytes_written = write(fd_out, mapped_file, stat.st_size);
+ if (bytes_written == -1) {
+ perror("Unable to write output file");
+ exit_code = 1;
+ } else if (bytes_written != stat.st_size) {
+ fprintf(stderr, "Wrong number of bytes written");
exit_code = 1;
}
+ } else {
+ perror("Unable to open output file");
+ exit_code = 1;
+ }
}
if (mapped_file != MAP_FAILED) {
commit 2763a2c5982c0db072697abe8ba01342d5977237
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 1 17:14:51 2018 -0800
Include subset test files in distribution.
diff --git a/test/subset/Makefile.am b/test/subset/Makefile.am
index 3037261b..dfc312e6 100644
--- a/test/subset/Makefile.am
+++ b/test/subset/Makefile.am
@@ -9,8 +9,13 @@ SUBDIRS = data
lib:
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+EXTRA_DIST += \
+ run-tests.py \
+ subset_test_suite.py \
+ $(NULL)
+
CLEANFILES += \
- subset_test_suite.py[c0] \
+ subset_test_suite.py[co] \
$(NULL)
-include $(top_srcdir)/git.mk
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index c74f7fd8..ecdab376 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -5,6 +5,13 @@ EXTRA_DIST =
CLEANFILES =
SUBDIRS =
+EXTRA_DIST = \
+ $(TESTS) \
+ expected/basics/*.ttf \
+ fonts/*.ttf \
+ profiles/*.txt \
+ $(NULL)
+
# Convenience targets:
lib:
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
commit 34fa7b3ad23b544b0914bc6002d60525224c68e1
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 1 16:50:18 2018 -0800
Whitespace
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 7ceac9a7..84c0c3c2 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -45,10 +45,10 @@ HB_BEGIN_DECLS
typedef struct hb_subset_profile_t hb_subset_profile_t;
HB_EXTERN hb_subset_profile_t *
-hb_subset_profile_create();
+hb_subset_profile_create ();
HB_EXTERN void
-hb_subset_profile_destroy(hb_subset_profile_t *profile);
+hb_subset_profile_destroy (hb_subset_profile_t *profile);
/*
* hb_subset_input_t
@@ -58,10 +58,10 @@ hb_subset_profile_destroy(hb_subset_profile_t *profile);
typedef struct hb_subset_input_t hb_subset_input_t;
HB_EXTERN hb_subset_input_t *
-hb_subset_input_create();
+hb_subset_input_create ();
HB_EXTERN void
-hb_subset_input_destroy(hb_subset_input_t *subset_input);
+hb_subset_input_destroy (hb_subset_input_t *subset_input);
/*
* hb_subset_face_t
@@ -72,17 +72,17 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input);
typedef struct hb_subset_face_t hb_subset_face_t;
HB_EXTERN hb_subset_face_t *
-hb_subset_face_create(hb_face_t *face);
+hb_subset_face_create (hb_face_t *face);
HB_EXTERN void
-hb_subset_face_destroy(hb_subset_face_t *face);
+hb_subset_face_destroy (hb_subset_face_t *face);
HB_EXTERN hb_bool_t
-hb_subset(hb_subset_profile_t *profile,
- hb_subset_input_t *input,
- hb_subset_face_t *face,
- hb_blob_t **result /* OUT */);
+hb_subset (hb_subset_profile_t *profile,
+ hb_subset_input_t *input,
+ hb_subset_face_t *face,
+ hb_blob_t **result /* OUT */);
HB_END_DECLS
commit 8c3a6727377895f18e1b5c7076404d8aede17176
Author: Garret Rieger <grieger at google.com>
Date: Wed Jan 31 15:43:24 2018 -0800
Get test-subset to pass.
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 00146b9d..62f7f0ad 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -150,6 +150,6 @@ hb_subset(hb_subset_profile_t *profile,
{
if (!profile || !input || !face) return false;
- *result = hb_blob_get_empty();
+ *result = hb_face_reference_blob(face->face);
return true;
}
commit 74d39ed2639857d5f1a90d9c0d864227a6482b40
Author: Garret Rieger <grieger at google.com>
Date: Wed Jan 31 15:20:52 2018 -0800
Attach add a hb_face_t to hb_subset_face_t.
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index cabae4c4..00146b9d 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -43,6 +43,8 @@ struct hb_subset_input_t {
struct hb_subset_face_t {
hb_object_header_t header;
ASSERT_POD ();
+
+ hb_face_t *face;
};
@@ -108,7 +110,13 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
hb_subset_face_t *
hb_subset_face_create(hb_face_t *face)
{
- return hb_object_create<hb_subset_face_t>();
+ if (unlikely (!face))
+ face = hb_face_get_empty();
+
+ hb_subset_face_t *subset_face = hb_object_create<hb_subset_face_t> ();
+ subset_face->face = hb_face_reference (face);
+
+ return subset_face;
}
/**
@@ -117,11 +125,12 @@ hb_subset_face_create(hb_face_t *face)
* Since: 1.7.5
**/
void
-hb_subset_face_destroy(hb_subset_face_t *face)
+hb_subset_face_destroy(hb_subset_face_t *subset_face)
{
- if (!hb_object_destroy (face)) return;
+ if (!hb_object_destroy (subset_face)) return;
- free (face);
+ hb_face_destroy(subset_face->face);
+ free (subset_face);
}
/**
commit 76b84c36b9560e132918adb4c0c5a0d9bdfb0978
Author: Garret Rieger <grieger at google.com>
Date: Wed Jan 31 14:53:28 2018 -0800
Whitespace
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 3a4eacae..99849fc9 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -29,7 +29,7 @@ TEST_PROGS = \
test-object \
test-set \
test-shape \
- test-subset \
+ test-subset \
test-unicode \
test-version \
$(NULL)
commit a2965f2ea5428c19be54f998ef9152c5ff6975ea
Author: Garret Rieger <grieger at google.com>
Date: Wed Jan 31 14:53:09 2018 -0800
Add a basic implementation of hb-subset to enable compilation of test-subset.
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index e69de29b..cabae4c4 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Rod Sheeter
+ */
+
+#include "hb-private.hh"
+
+#include "hb-object-private.hh"
+
+
+struct hb_subset_profile_t {
+ hb_object_header_t header;
+ ASSERT_POD ();
+};
+
+struct hb_subset_input_t {
+ hb_object_header_t header;
+ ASSERT_POD ();
+};
+
+struct hb_subset_face_t {
+ hb_object_header_t header;
+ ASSERT_POD ();
+};
+
+
+/**
+ * hb_subset_profile_create:
+ *
+ * Return value: New profile with default settings.
+ *
+ * Since: 1.7.5
+ **/
+hb_subset_profile_t *
+hb_subset_profile_create ()
+{
+ return hb_object_create<hb_subset_profile_t>();
+}
+
+/**
+ * hb_subset_profile_destroy:
+ *
+ * Since: 1.7.5
+ **/
+void
+hb_subset_profile_destroy (hb_subset_profile_t *profile)
+{
+ if (!hb_object_destroy (profile)) return;
+
+ free (profile);
+}
+
+/**
+ * hb_subset_input_create:
+ *
+ * Return value: New subset input.
+ *
+ * Since: 1.7.5
+ **/
+hb_subset_input_t *
+hb_subset_input_create()
+{
+ return hb_object_create<hb_subset_input_t>();
+}
+
+/**
+ * hb_subset_input_destroy:
+ *
+ * Since: 1.7.5
+ **/
+void
+hb_subset_input_destroy(hb_subset_input_t *subset_input)
+{
+ if (!hb_object_destroy (subset_input)) return;
+
+ free (subset_input);
+}
+
+/**
+ * hb_subset_face_create:
+ *
+ * Return value: New subset face.
+ *
+ * Since: 1.7.5
+ **/
+hb_subset_face_t *
+hb_subset_face_create(hb_face_t *face)
+{
+ return hb_object_create<hb_subset_face_t>();
+}
+
+/**
+ * hb_subset_face_destroy:
+ *
+ * Since: 1.7.5
+ **/
+void
+hb_subset_face_destroy(hb_subset_face_t *face)
+{
+ if (!hb_object_destroy (face)) return;
+
+ free (face);
+}
+
+/**
+ * hb_subset:
+ * @profile: profile to use for the subsetting.
+ * @input: input to use for the subsetting.
+ * @face: font face data to be subset.
+ * @result: subsetting result.
+ *
+ * Subsets a font according to provided profile and input.
+ **/
+hb_bool_t
+hb_subset(hb_subset_profile_t *profile,
+ hb_subset_input_t *input,
+ hb_subset_face_t *face,
+ hb_blob_t **result /* OUT */)
+{
+ if (!profile || !input || !face) return false;
+
+ *result = hb_blob_get_empty();
+ return true;
+}
diff --git a/src/hb-subset.h b/src/hb-subset.h
index b7c1f569..7ceac9a7 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -38,7 +38,8 @@ HB_BEGIN_DECLS
/*
* hb_subset_profile_t
- * Things that change based on target environment, e.g. OS
+ * Things that change based on target environment, e.g. OS.
+ * Threadsafe for multiple concurrent subset operations.
*/
typedef struct hb_subset_profile_t hb_subset_profile_t;
@@ -81,7 +82,7 @@ HB_EXTERN hb_bool_t
hb_subset(hb_subset_profile_t *profile,
hb_subset_input_t *input,
hb_subset_face_t *face,
- hb_blob_t *result /* OUT */);
+ hb_blob_t **result /* OUT */);
HB_END_DECLS
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index e22d726a..3a4eacae 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -29,6 +29,7 @@ TEST_PROGS = \
test-object \
test-set \
test-shape \
+ test-subset \
test-unicode \
test-version \
$(NULL)
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
index 85b302d7..b6986ce2 100644
--- a/test/api/test-subset.c
+++ b/test/api/test-subset.c
@@ -28,7 +28,7 @@
/* Unit tests for hb-subset.h */
-static const char test_data[] = "OTTO";
+static const char test_data[] = { 0, 0, 1, 0 };
static void
test_subset (void)
@@ -41,12 +41,12 @@ test_subset (void)
hb_subset_input_t *input = hb_subset_input_create();
hb_subset_face_t *subset_face = hb_subset_face_create(face);
- char output_data[100];
- hb_blob_t *output = hb_blob_create(output_data, sizeof(output_data),
- HB_MEMORY_MODE_WRITABLE, NULL, NULL);
+ hb_blob_t *output;
+ g_assert(hb_subset(profile, input, subset_face, &output));
- g_assert(hb_subset(profile, input, subset_face, output));
- g_assert_cmpmem(test_data, 4, output_data, sizeof(output));
+ unsigned int output_length;
+ const char *output_data = hb_blob_get_data(output, &output_length);
+ g_assert_cmpmem(test_data, 4, output_data, output_length);
hb_blob_destroy(output);
hb_subset_face_destroy(subset_face);
commit 38af23b8df1a84f24d379d27d1a1e20f9ce07f34
Author: Garret Rieger <grieger at google.com>
Date: Wed Jan 31 11:32:23 2018 -0800
Make the expected output for subsetting basics test be equal to the input file for now.
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf
index 8e44886f..9d791f7f 100644
Binary files a/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf differ
commit b59c08eb045db2b6c952de81510b8159a4f72fb1
Author: Garret Rieger <grieger at google.com>
Date: Wed Jan 31 11:14:53 2018 -0800
Add the beginning of a unit test for hb-subset
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
new file mode 100644
index 00000000..85b302d7
--- /dev/null
+++ b/test/api/test-subset.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2011 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb-test.h"
+
+/* Unit tests for hb-subset.h */
+
+static const char test_data[] = "OTTO";
+
+static void
+test_subset (void)
+{
+ hb_blob_t *font_blob = hb_blob_create(test_data, sizeof(test_data),
+ HB_MEMORY_MODE_READONLY, NULL, NULL);
+ hb_face_t *face = hb_face_create(font_blob, 0);
+
+ hb_subset_profile_t *profile = hb_subset_profile_create();
+ hb_subset_input_t *input = hb_subset_input_create();
+ hb_subset_face_t *subset_face = hb_subset_face_create(face);
+
+ char output_data[100];
+ hb_blob_t *output = hb_blob_create(output_data, sizeof(output_data),
+ HB_MEMORY_MODE_WRITABLE, NULL, NULL);
+
+ g_assert(hb_subset(profile, input, subset_face, output));
+ g_assert_cmpmem(test_data, 4, output_data, sizeof(output));
+
+ hb_blob_destroy(output);
+ hb_subset_face_destroy(subset_face);
+ hb_subset_input_destroy(input);
+ hb_subset_profile_destroy(profile);
+ hb_face_destroy(face);
+ hb_blob_destroy(font_blob);
+}
+
+int
+main (int argc, char **argv)
+{
+ hb_test_init (&argc, &argv);
+
+ hb_test_add (test_subset);
+
+ return hb_test_run();
+}
commit e9d154ac8ddd2712a34c53c95a17e469f95e5b30
Author: Rod Sheeter <rsheeter at google.com>
Date: Tue Jan 30 19:27:11 2018 -0800
tweak test failure output. write to a temp file not stdout. test still fails because expected is not just an identical copy of input
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 90da9624..0b4b96a6 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -9,6 +9,7 @@ import io
import os
import subprocess
import sys
+import tempfile
from subset_test_suite import SubsetTestSuite
@@ -20,21 +21,39 @@ def cmd(command):
print (p.stderr.read (), end="") # file=sys.stderr
return p.stdout.read (), p.returncode
+def read_binary(file_path):
+ with open(file_path, 'rb') as f:
+ return f.read()
+
+def fail_test(test, cli_args, message):
+ print ('ERROR: %s' % message)
+ print ('Test State:')
+ print (' test.font_path %s' % os.path.abspath(test.font_path))
+ print (' test.profile_path %s' % os.path.abspath(test.profile_path))
+ print (' test.unicodes %s' % test.unicodes())
+ expected_file = os.path.join(test_suite.get_output_directory(),
+ test.get_font_name())
+ print (' expected_file %s' % os.path.abspath(expected_file))
+ return 1
def run_test(test):
- result, return_code = cmd([hb_subset,
- test.font_path,
- "--unicodes=%s" % test.unicodes()])
+ out_file = os.path.join(tempfile.mkdtemp(), test.get_font_name() + '-subset.ttf')
+ cli_args = [hb_subset, test.font_path, out_file, "--unicodes=%s" % test.unicodes()]
+ _, return_code = cmd(cli_args)
if return_code:
- print ("ERROR: hb-subset failed for %s, %s, %s" % (test.font_path, test.profile_path, test.unicodes()))
- return 1
-
- with open(os.path.join(test_suite.get_output_directory(),
- test.get_font_name())) as expected:
- if not result == expected.read():
- print ("ERROR: hb-subset %s, %s, %s does not match expected value." % (test.font_path, test.profile_path, test.unicodes()))
- return 1
+ return fail_test(test, cli_args, "%s returned %d" % (' '.join(cli_args), return_code))
+
+ expected = read_binary(os.path.join(test_suite.get_output_directory(),
+ test.get_font_name()))
+ actual = read_binary(out_file)
+
+ if len(actual) != len(expected):
+ return fail_test(test, cli_args, "expected %d bytes, actual %d: %s" % (
+ len(expected), len(actual), ' '.join(cli_args)))
+
+ if not actual == expected:
+ return fail_test(test, cli_args, 'files are the same length but not the same bytes')
return 0
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index ad7ceb14..5aafbe19 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -13,37 +13,52 @@ int
main (int argc, char **argv)
{
int exit_code = 0;
- int fd = open("/tmp/Lobster-Regular.ttf", O_RDONLY);
+
+ if (argc != 4) {
+ fprintf(stderr, "Must have 4 args\n");
+ exit(1);
+ }
+
+ int fd = open(argv[1], O_RDONLY);
if (fd == -1) {
- perror("Unable to open file");
+ perror("Unable to open font file");
exit(1);
}
void *mapped_file = MAP_FAILED;
- char *raw_font = nullptr;
+ int fd_out = -1;
struct stat stat;
if (fstat(fd, &stat) != -1) {
- printf("File is %zu bytes\n", stat.st_size);
- void *mapped_file = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (mapped_file != MAP_FAILED) {
- raw_font = static_cast<char*>(mapped_file);
- } else {
+ mapped_file = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (mapped_file == MAP_FAILED) {
perror("Failed to map file");
}
} else {
perror("Unable to fstat");
}
- if (raw_font) {
- printf("Mapped file\n");
- for (int i = 0; i < 4; i++) {
- printf("%02x", *(raw_font + i));
- }
- printf("\n");
+ if (mapped_file != MAP_FAILED) {
+ hb_blob_t *font_blob = hb_blob_create(static_cast<const char*>(mapped_file),
+ stat.st_size,
+ HB_MEMORY_MODE_READONLY, nullptr,
+ nullptr);
- hb_blob_t *font_blob = hb_blob_create(raw_font, stat.st_size, HB_MEMORY_MODE_READONLY, nullptr, nullptr);
+ fd_out = open(argv[2], O_CREAT | O_WRONLY, S_IRWXU);
+ if (fd_out != -1) {
+ ssize_t bytes_written = write(fd_out, mapped_file, stat.st_size);
+ if (bytes_written == -1) {
+ perror("Unable to write output file");
+ exit_code = 1;
+ } else if (bytes_written != stat.st_size) {
+ fprintf(stderr, "Wrong number of bytes written");
+ exit_code = 1;
+ }
+ } else {
+ perror("Unable to open output file");
+ exit_code = 1;
+ }
}
if (mapped_file != MAP_FAILED) {
@@ -53,9 +68,15 @@ main (int argc, char **argv)
}
}
- if (close(fd) == -1) {
+ if (fd_out != -1 && close(fd_out) == -1) {
+ perror("Unable to close output file");
+ exit_code = 1;
+ }
+
+ if (fd != -1 && close(fd) == -1) {
perror("Unable to close file");
exit_code = 1;
}
+
return exit_code;
}
commit cf403e1a53381f293aceac5cdbe031bbb2a7af77
Author: Garret Rieger <grieger at google.com>
Date: Tue Jan 30 18:40:23 2018 -0800
Add hb-subset.h to hb.h
diff --git a/src/hb.h b/src/hb.h
index 7402034f..e55decfe 100644
--- a/src/hb.h
+++ b/src/hb.h
@@ -41,6 +41,7 @@
#include "hb-set.h"
#include "hb-shape.h"
#include "hb-shape-plan.h"
+#include "hb-subset.h"
#include "hb-unicode.h"
#include "hb-version.h"
commit c02573516c05ac97acb243ef5dec26af86086ded
Author: Garret Rieger <grieger at google.com>
Date: Tue Jan 30 18:39:41 2018 -0800
Fix typo in hb-subset.h
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 8aaccd6e..b7c1f569 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -80,7 +80,7 @@ hb_subset_face_destroy(hb_subset_face_t *face);
HB_EXTERN hb_bool_t
hb_subset(hb_subset_profile_t *profile,
hb_subset_input_t *input,
- hb_subset_face_t *face
+ hb_subset_face_t *face,
hb_blob_t *result /* OUT */);
HB_END_DECLS
commit 76351518ca9bc88aa6fbc975e1e35bd86432d652
Author: Garret Rieger <grieger at google.com>
Date: Tue Jan 30 14:03:16 2018 -0800
Remove basic subset test from XFAIL
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index 00bd2b9f..37550b63 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -3,7 +3,6 @@ TESTS = \
$(NULL)
XFAIL_TESTS = \
- tests/basics.tests \
$(NULL)
DISABLED_TESTS = \
commit b029b7c19a733a2a39860238ad300e6c4a3f7802
Author: Garret Rieger <grieger at google.com>
Date: Mon Jan 29 13:31:49 2018 -0800
Whitespace
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index 574f9466..00bd2b9f 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -1,10 +1,10 @@
TESTS = \
tests/basics.tests \
- $(NULL)
+ $(NULL)
XFAIL_TESTS = \
tests/basics.tests \
- $(NULL)
+ $(NULL)
DISABLED_TESTS = \
$(NULL)
commit 0853260e997aded264f42bb369d4fcb39cccb7d6
Author: Garret Rieger <grieger at google.com>
Date: Mon Jan 29 13:30:02 2018 -0800
Configure automake to run the new subset tests.
diff --git a/configure.ac b/configure.ac
index dec994eb..12401f00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -500,6 +500,8 @@ test/shaping/Makefile
test/shaping/data/Makefile
test/shaping/data/in-house/Makefile
test/shaping/data/text-rendering-tests/Makefile
+test/subset/Makefile
+test/subset/data/Makefile
docs/Makefile
docs/version.xml
])
diff --git a/test/Makefile.am b/test/Makefile.am
index ad496f55..66b3e6e2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,7 +2,7 @@
NULL =
EXTRA_DIST =
-SUBDIRS = api shaping fuzzing
+SUBDIRS = api shaping fuzzing subset
EXTRA_DIST += \
CMakeLists.txt \
diff --git a/test/subset/Makefile.am b/test/subset/Makefile.am
new file mode 100644
index 00000000..3037261b
--- /dev/null
+++ b/test/subset/Makefile.am
@@ -0,0 +1,16 @@
+# Process this file with automake to produce Makefile.in
+
+NULL =
+EXTRA_DIST =
+CLEANFILES =
+SUBDIRS = data
+
+# Convenience targets:
+lib:
+ @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+
+CLEANFILES += \
+ subset_test_suite.py[c0] \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
new file mode 100644
index 00000000..c74f7fd8
--- /dev/null
+++ b/test/subset/data/Makefile.am
@@ -0,0 +1,16 @@
+# Process this file with automake to produce Makefile.in
+
+NULL =
+EXTRA_DIST =
+CLEANFILES =
+SUBDIRS =
+
+# Convenience targets:
+lib:
+ @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
+
+TEST_EXTENSIONS = .tests
+TESTS_LOG_COMPILER = $(srcdir)/../run-tests.py $(top_builddir)/util/hb-subset$(EXEEXT)
+include Makefile.sources
+
+-include $(top_srcdir)/git.mk
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
new file mode 100644
index 00000000..574f9466
--- /dev/null
+++ b/test/subset/data/Makefile.sources
@@ -0,0 +1,10 @@
+TESTS = \
+ tests/basics.tests \
+ $(NULL)
+
+XFAIL_TESTS = \
+ tests/basics.tests \
+ $(NULL)
+
+DISABLED_TESTS = \
+ $(NULL)
diff --git a/test/subset/data/tests/basics.txt b/test/subset/data/tests/basics.tests
similarity index 100%
rename from test/subset/data/tests/basics.txt
rename to test/subset/data/tests/basics.tests
commit 5c63c37b2b5aba8bf2f8ff35b7da0d116ebfe8b5
Author: Garret Rieger <grieger at google.com>
Date: Fri Jan 26 16:57:42 2018 -0800
WIP test runner for subset tests.
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
new file mode 100755
index 00000000..90da9624
--- /dev/null
+++ b/test/subset/run-tests.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+# Runs a subsetting test suite. Compares the results of subsetting via harfbuz
+# to subsetting via fonttools.
+
+from __future__ import print_function
+
+import io
+import os
+import subprocess
+import sys
+
+from subset_test_suite import SubsetTestSuite
+
+
+def cmd(command):
+ p = subprocess.Popen (
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ p.wait ()
+ print (p.stderr.read (), end="") # file=sys.stderr
+ return p.stdout.read (), p.returncode
+
+
+def run_test(test):
+ result, return_code = cmd([hb_subset,
+ test.font_path,
+ "--unicodes=%s" % test.unicodes()])
+
+ if return_code:
+ print ("ERROR: hb-subset failed for %s, %s, %s" % (test.font_path, test.profile_path, test.unicodes()))
+ return 1
+
+ with open(os.path.join(test_suite.get_output_directory(),
+ test.get_font_name())) as expected:
+ if not result == expected.read():
+ print ("ERROR: hb-subset %s, %s, %s does not match expected value." % (test.font_path, test.profile_path, test.unicodes()))
+ return 1
+
+ return 0
+
+
+args = sys.argv[1:]
+if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
+ print ("First argument does not seem to point to usable hb-subset.")
+ sys.exit (1)
+hb_subset, args = args[0], args[1:]
+
+if not len(args):
+ print ("No tests supplied.")
+ sys.exit (1)
+
+fails = 0
+for path in args:
+ with io.open(path, mode="r", encoding="utf-8") as f:
+ print ("Running tests in " + path)
+ test_suite = SubsetTestSuite(path, f.read())
+ for test in test_suite.tests():
+ fails += run_test(test)
+
+if fails != 0:
+ print (str (fails) + " test(s) failed.")
+ sys.exit(1)
+else:
+ print ("All tests passed.")
commit cc46cd88a1b84b02694fa6d88c4286e93336f096
Author: Garret Rieger <grieger at google.com>
Date: Fri Jan 26 14:25:39 2018 -0800
In generate-expected-outputs read the test definition with utf8 encoding.
diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py
index 87db5d5b..f6636de7 100755
--- a/test/subset/generate-expected-outputs.py
+++ b/test/subset/generate-expected-outputs.py
@@ -3,6 +3,7 @@
# Pre-generates the expected output subset files (via fonttools) for
# specified subset test suite(s).
+import io
import os
import sys
@@ -26,7 +27,7 @@ if not args:
usage()
for path in args:
- with open(path, 'r') as f:
+ with io.open(path, mode="r", encoding="utf-8") as f:
test_suite = SubsetTestSuite(path, f.read())
output_directory = test_suite.get_output_directory()
commit 4cdae914e2e2fff1ff91e2f42648a8acb82a5494
Author: Garret Rieger <grieger at google.com>
Date: Fri Jan 26 13:57:48 2018 -0800
Add basic directory structure for subsetter integration tests. Plus a utility for generating expected output files.
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf
new file mode 100644
index 00000000..8e44886f
Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.62.ttf differ
diff --git a/test/subset/data/fonts/Roboto-Regular.abc.ttf b/test/subset/data/fonts/Roboto-Regular.abc.ttf
new file mode 100644
index 00000000..9d791f7f
Binary files /dev/null and b/test/subset/data/fonts/Roboto-Regular.abc.ttf differ
diff --git a/test/subset/data/profiles/default.txt b/test/subset/data/profiles/default.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/test/subset/data/tests/basics.txt b/test/subset/data/tests/basics.txt
new file mode 100644
index 00000000..8a7246b9
--- /dev/null
+++ b/test/subset/data/tests/basics.txt
@@ -0,0 +1,8 @@
+FONTS:
+Roboto-Regular.abc.ttf
+
+PROFILES:
+default.txt
+
+SUBSETS:
+b
diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py
new file mode 100755
index 00000000..87db5d5b
--- /dev/null
+++ b/test/subset/generate-expected-outputs.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+# Pre-generates the expected output subset files (via fonttools) for
+# specified subset test suite(s).
+
+import os
+import sys
+
+from subprocess import check_call
+from subset_test_suite import SubsetTestSuite
+
+
+def usage():
+ print "Usage: generate-expected-outputs.py <test suite file> ..."
+
+
+def generate_expected_output(input_file, unicodes, output_path):
+ check_call(["fonttools", "subset",
+ input_file,
+ "--unicodes=%s" % unicodes,
+ "--output-file=%s" % output_path])
+
+
+args = sys.argv[1:]
+if not args:
+ usage()
+
+for path in args:
+ with open(path, 'r') as f:
+ test_suite = SubsetTestSuite(path, f.read())
+ output_directory = test_suite.get_output_directory()
+
+ print "Generating output files for %s" % output_directory
+ for test in test_suite.tests():
+ unicodes = test.unicodes()
+ font_name = test.get_font_name()
+ print "Creating subset %s/%s" % (output_directory, font_name)
+ generate_expected_output(test.font_path, unicodes,
+ os.path.join(output_directory,
+ font_name))
diff --git a/test/subset/subset_test_suite.py b/test/subset/subset_test_suite.py
new file mode 100644
index 00000000..256e2071
--- /dev/null
+++ b/test/subset/subset_test_suite.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+import os
+
+# A single test in a subset test suite. Identifies a font
+# a subsetting profile, and a subset to be cut.
+class Test:
+ def __init__(self, font_path, profile_path, subset):
+ self.font_path = font_path
+ self.profile_path = profile_path
+ self.subset = subset
+
+ def unicodes(self):
+ return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset))
+
+ def get_font_name(self):
+ font_base_name = os.path.basename(self.font_path)
+ font_base_name_parts = os.path.splitext(font_base_name)
+ profile_name = os.path.splitext(os.path.basename(self.profile_path))[0]
+
+ return "%s.%s.%s%s" % (font_base_name_parts[0],
+ profile_name,
+ self.unicodes(),
+ font_base_name_parts[1])
+
+# A group of tests to perform on the subsetter. Each test
+# Identifies a font a subsetting profile, and a subset to be cut.
+class SubsetTestSuite:
+
+ def __init__(self, test_path, definition):
+ self.test_path = test_path
+ self.fonts = set()
+ self.profiles = set()
+ self.subsets = set()
+ self._parse(definition)
+
+ def get_output_directory(self):
+ test_name = os.path.splitext(os.path.basename(self.test_path))[0]
+ data_dir = os.path.join(os.path.dirname(self.test_path), "..")
+
+ output_dir = os.path.normpath(os.path.join(data_dir, "expected", test_name))
+ if not os.path.exists(output_dir):
+ os.mkdir(output_dir)
+ if not os.path.isdir(output_dir):
+ raise Error("%s is not a directory." % output_dir)
+
+ return output_dir
+
+ def tests(self):
+ for font in self.fonts:
+ font = os.path.join(self._base_path(), "fonts", font)
+ for profile in self.profiles:
+ profile = os.path.join(self._base_path(), "profiles", profile)
+ for subset in self.subsets:
+ yield Test(font, profile, subset)
+
+ def _base_path(self):
+ return os.path.dirname(os.path.dirname(self.test_path))
+
+ def _parse(self, definition):
+ destinations = {
+ "FONTS:": self.fonts,
+ "PROFILES:": self.profiles,
+ "SUBSETS:": self.subsets
+ }
+
+ current_destination = None
+ for line in definition.splitlines():
+ line = line.strip()
+
+ if line.startswith("#"):
+ continue
+
+ if not line:
+ continue
+
+ if line in destinations:
+ current_destination = destinations[line]
+ elif current_destination is not None:
+ current_destination.add(line)
+ else:
+ raise Exception("Failed to parse test suite file.")
commit 9ccb8366f603a9e4a7a3c3f96420a19d4f6fb390
Author: Rod Sheeter <rsheeter at google.com>
Date: Wed Jan 17 22:09:07 2018 -0800
Start to sketch APIs for subsetting
diff --git a/src/Makefile.am b/src/Makefile.am
index 833d1f95..dd1c7ae6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,7 +27,9 @@ HBNONPCLIBS =
HBDEPS =
HBSOURCES = $(HB_BASE_sources)
HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
+HBSOURCES += $(HB_SUBSET_sources)
HBHEADERS = $(HB_BASE_headers)
+HBHEADERS += $(HB_SUBSET_headers)
HBNODISTHEADERS = $(HB_NODIST_headers)
if HAVE_OT
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 213aa22f..f223fcfe 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -181,6 +181,10 @@ HB_UCDN_sources = hb-ucdn.cc
HB_ICU_sources = hb-icu.cc
HB_ICU_headers = hb-icu.h
+# Sources for libharfbuzz-subset
+HB_SUBSET_sources = hb-subset.cc
+HB_SUBSET_headers = hb-subset.h
+
HB_GOBJECT_sources = hb-gobject-structs.cc
HB_GOBJECT_STRUCTS_headers = hb-gobject-structs.h
HB_GOBJECT_headers = hb-gobject.h $(HB_GOBJECT_STRUCTS_headers)
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
new file mode 100644
index 00000000..e69de29b
diff --git a/src/hb-subset.h b/src/hb-subset.h
new file mode 100644
index 00000000..8aaccd6e
--- /dev/null
+++ b/src/hb-subset.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2018 Google
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Rod Sheeter
+ */
+
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_SUBSET_H
+#define HB_SUBSET_H
+
+#include "hb-common.h"
+#include "hb-face.h"
+
+HB_BEGIN_DECLS
+
+/*
+ * hb_subset_profile_t
+ * Things that change based on target environment, e.g. OS
+ */
+
+typedef struct hb_subset_profile_t hb_subset_profile_t;
+
+HB_EXTERN hb_subset_profile_t *
+hb_subset_profile_create();
+
+HB_EXTERN void
+hb_subset_profile_destroy(hb_subset_profile_t *profile);
+
+/*
+ * hb_subset_input_t
+ * Things that change based on the input. Characters to keep, etc.
+ */
+
+typedef struct hb_subset_input_t hb_subset_input_t;
+
+HB_EXTERN hb_subset_input_t *
+hb_subset_input_create();
+
+HB_EXTERN void
+hb_subset_input_destroy(hb_subset_input_t *subset_input);
+
+/*
+ * hb_subset_face_t
+ * Reusable subset-ready plan for a given face. Threadsafe for multiple
+ * concurrent subset operations.
+ */
+
+typedef struct hb_subset_face_t hb_subset_face_t;
+
+HB_EXTERN hb_subset_face_t *
+hb_subset_face_create(hb_face_t *face);
+
+HB_EXTERN void
+hb_subset_face_destroy(hb_subset_face_t *face);
+
+
+HB_EXTERN hb_bool_t
+hb_subset(hb_subset_profile_t *profile,
+ hb_subset_input_t *input,
+ hb_subset_face_t *face
+ hb_blob_t *result /* OUT */);
+
+HB_END_DECLS
+
+#endif /* HB_SUBSET_H */
diff --git a/util/Makefile.am b/util/Makefile.am
index e6620a23..283dd91f 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -46,6 +46,9 @@ endif # HAVE_FREETYPE
hb_shape_SOURCES = $(HB_SHAPE_sources)
bin_PROGRAMS += hb-shape
+hb_subset_SOURCES = $(HB_SUBSET_sources)
+bin_PROGRAMS += hb-subset
+
if HAVE_OT
hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
bin_PROGRAMS += hb-ot-shape-closure
diff --git a/util/Makefile.sources b/util/Makefile.sources
index d6c00cc4..94a5fa8a 100644
--- a/util/Makefile.sources
+++ b/util/Makefile.sources
@@ -28,3 +28,7 @@ HB_OT_SHAPE_CLOSURE_sources = \
options.hh \
main-font-text.hh \
$(NULL)
+
+HB_SUBSET_sources = \
+ hb-subset.cc \
+ $(NULL)
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
new file mode 100644
index 00000000..ad7ceb14
--- /dev/null
+++ b/util/hb-subset.cc
@@ -0,0 +1,61 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "hb-private.hh"
+#include "hb-blob.h"
+
+int
+main (int argc, char **argv)
+{
+ int exit_code = 0;
+ int fd = open("/tmp/Lobster-Regular.ttf", O_RDONLY);
+ if (fd == -1) {
+ perror("Unable to open file");
+ exit(1);
+ }
+
+ void *mapped_file = MAP_FAILED;
+ char *raw_font = nullptr;
+
+ struct stat stat;
+ if (fstat(fd, &stat) != -1) {
+ printf("File is %zu bytes\n", stat.st_size);
+
+ void *mapped_file = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (mapped_file != MAP_FAILED) {
+ raw_font = static_cast<char*>(mapped_file);
+ } else {
+ perror("Failed to map file");
+ }
+ } else {
+ perror("Unable to fstat");
+ }
+
+ if (raw_font) {
+ printf("Mapped file\n");
+ for (int i = 0; i < 4; i++) {
+ printf("%02x", *(raw_font + i));
+ }
+ printf("\n");
+
+ hb_blob_t *font_blob = hb_blob_create(raw_font, stat.st_size, HB_MEMORY_MODE_READONLY, nullptr, nullptr);
+ }
+
+ if (mapped_file != MAP_FAILED) {
+ if (munmap(mapped_file, stat.st_size) == -1) {
+ perror("Unable to unmap file");
+ exit_code = 1;
+ }
+ }
+
+ if (close(fd) == -1) {
+ perror("Unable to close file");
+ exit_code = 1;
+ }
+ return exit_code;
+}
More information about the HarfBuzz
mailing list