[HarfBuzz] harfbuzz: Branch 'master' - 14 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Thu Feb 8 23:36:13 UTC 2018
CMakeLists.txt | 14 +++
src/hb-ot-cmap-table.hh | 21 +++++
src/hb-subset-glyf.cc | 80 ++++++++++++++------
src/hb-subset-glyf.hh | 13 ++-
src/hb-subset-plan.cc | 2
src/hb-subset-plan.hh | 7 +
src/hb-subset.cc | 35 ++++++++-
test/api/CMakeLists.txt | 2
test/api/Makefile.am | 4 +
test/api/fonts/Roboto-Regular.abc.ttf |binary
test/api/fonts/Roboto-Regular.ac.ttf |binary
test/api/hb-test.h | 5 +
test/api/test-subset-glyf.c | 131 ++++++++++++++++++++++++++++++++++
test/api/test-subset.c | 4 -
test/subset/run-tests.py | 26 ++++--
15 files changed, 293 insertions(+), 51 deletions(-)
New commits:
commit 9682ef135f16cb3368b9c5970fdcec71301b687e
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Feb 8 17:35:57 2018 -0600
Minor fixups
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 27a04b1f..c21a4291 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -253,7 +253,7 @@ set (project_sources
${HB_FALLBACK_sources}
${HB_OT_sources}
- ${HB_OT_RAGEL_GENERATED_sources}
+ ${HB_OT_RAGEL_GENERATED_sources}
)
set (subset_project_sources
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 219eca7b..53733680 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -27,7 +27,7 @@
#ifndef HB_OT_CMAP_TABLE_HH
#define HB_OT_CMAP_TABLE_HH
-#include "hb-open-type-private.hh"
+#include "hb-open-type-private.hh"
#include "hb-subset-plan.hh"
namespace OT {
@@ -504,7 +504,7 @@ struct cmap
encodingRecord.sanitize (c, this));
}
- inline bool subset(hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest) const
+ inline bool subset (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest) const
{
// TODO something useful re: memory, write to dest
size_t dest_sz = 64536; // as much as anyone would ever need
@@ -514,7 +514,7 @@ struct cmap
// Same version
OT::cmap new_cmap;
new_cmap.version = version;
- new_cmap.encodingRecord.len.set(1); // one format 12 subtable
+ new_cmap.encodingRecord.len.set(1); // one format 12 subtable
// TODO we need to actually build the format 12 subtable
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index f10f35ba..a46cbd08 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -26,7 +26,7 @@
*/
#include "hb-object-private.hh"
-#include "hb-open-type-private.hh"
+#include "hb-open-type-private.hh"
#include "hb-private.hh"
@@ -109,7 +109,7 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
template<typename TableType>
hb_bool_t
-subset(hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
+subset (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
{
OT::Sanitizer<TableType> sanitizer;
hb_blob_t *table_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag));
@@ -119,7 +119,7 @@ subset(hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
}
const TableType *table = OT::Sanitizer<TableType>::lock_instance (table_blob);
hb_bool_t result = table->subset(plan, source, dest);
-
+
hb_blob_destroy (table_blob);
// TODO string not numeric tag
diff --git a/test/api/hb-test.h b/test/api/hb-test.h
index 040f0c21..f6f107e2 100644
--- a/test/api/hb-test.h
+++ b/test/api/hb-test.h
@@ -161,6 +161,11 @@ typedef void (*hb_test_fixture_func_t) (void);
#define g_test_fail() g_error("Test failed")
#endif
+#ifndef g_assert_cmpmem
+#define g_assert_cmpmem(m1, l1, m2, l2) g_assert_true (l1 == l2 && memcmp (m1, m2, l1) == 0)
+#endif
+
+
static inline void
hb_test_add_func (const char *test_path,
hb_test_func_t test_func)
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index b7d56902..196047fe 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -28,10 +28,6 @@
#include "hb-test.h"
-#ifndef g_assert_cmpmem
-#define g_assert_cmpmem(m1, l1, m2, l2) g_assert_true (l1 == l2 && memcmp (m1, m2, l1) == 0)
-#endif
-
static char *
read_file (const char *path,
size_t *length)
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
index 866a8333..4184a563 100644
--- a/test/api/test-subset.c
+++ b/test/api/test-subset.c
@@ -26,10 +26,6 @@
#include "hb-test.h"
-#ifndef g_assert_cmpmem
-#define g_assert_cmpmem(m1, l1, m2, l2) g_assert_true (l1 == l2 && memcmp (m1, m2, l1) == 0)
-#endif
-
/* Unit tests for hb-subset.h */
static const char test_data[] = { 0, 1, 0, 0, /* sfntVersion */
commit 35eeb893efcdfa2bf6a136cd2911d564334e573c
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 8 15:17:34 2018 -0800
Don't include subset headers in libharfbuzz.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6199e442..27a04b1f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -267,7 +267,6 @@ set (project_headers
${HB_BASE_headers}
${HB_OT_headers}
- ${HB_SUBSET_headers}
)
set (subset_project_headers
commit 42234424a0fc43d298be082b4c7b1e288e94bbb6
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 8 15:11:15 2018 -0800
Fix include gaurds and include order in hb-subset-glyf and hb-subset-plan
diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh
index c802da24..035085f0 100644
--- a/src/hb-subset-glyf.hh
+++ b/src/hb-subset-glyf.hh
@@ -24,8 +24,10 @@
* Google Author(s): Garret Rieger
*/
-#ifndef HB_SUBSET_GLYF_H
-#define HB_SUBSET_GLYF_H
+#ifndef HB_SUBSET_GLYF_HH
+#define HB_SUBSET_GLYF_HH
+
+#include "hb-private.hh"
#include "hb-subset-plan.hh"
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 20185e1d..6f889b3c 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -24,9 +24,9 @@
* Google Author(s): Garret Rieger, Roderick Sheeter
*/
-#include "hb-subset-plan.hh"
#include "hb-subset-private.hh"
+#include "hb-subset-plan.hh"
#include "hb-ot-cmap-table.hh"
hb_bool_t
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index 1e572a43..a1e4e9e9 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -24,10 +24,11 @@
* Google Author(s): Garret Rieger
*/
-#ifndef HB_SUBSET_PLAN_H
-#define HB_SUBSET_PLAN_H
+#ifndef HB_SUBSET_PLAN_HH
+#define HB_SUBSET_PLAN_HH
#include "hb-private.hh"
+
#include "hb-object-private.hh"
struct hb_subset_plan_t {
commit 0f3c756cbfe8a263ee388481acac7a24d9684c44
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 8 14:59:32 2018 -0800
Add CMake config for building a separate harfbuzz-subset.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bfe0e306..6199e442 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -253,8 +253,10 @@ set (project_sources
${HB_FALLBACK_sources}
${HB_OT_sources}
- ${HB_OT_RAGEL_GENERATED_sources}
+ ${HB_OT_RAGEL_GENERATED_sources}
+)
+set (subset_project_sources
${HB_SUBSET_sources}
)
@@ -268,6 +270,10 @@ set (project_headers
${HB_SUBSET_headers}
)
+set (subset_project_headers
+ ${HB_SUBSET_headers}
+)
+
## Find and include needed header folders and libraries
if (HB_HAVE_FREETYPE)
@@ -530,6 +536,11 @@ endif ()
add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
+## Define harfbuzz-subset library
+add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
+add_dependencies(harfbuzz-subset harfbuzz)
+target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
+
if (UNIX OR MINGW)
# Make symbols link locally
link_libraries(-Bsymbolic-functions)
@@ -540,6 +551,7 @@ if (UNIX OR MINGW)
set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
+ set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C)
endif ()
# No threadsafe statics as we do it ourselves
@@ -548,7 +560,6 @@ if (UNIX OR MINGW)
endif ()
endif ()
-
## Define harfbuzz-gobject library
if (HB_HAVE_GOBJECT)
add_library(harfbuzz-gobject
@@ -720,7 +731,7 @@ if (HB_BUILD_UTILS)
target_link_libraries(hb-shape harfbuzz)
add_executable(hb-subset ${HB_SUBSET_CLI_sources})
- target_link_libraries(hb-subset harfbuzz)
+ target_link_libraries(hb-subset harfbuzz harfbuzz-subset)
add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources})
target_link_libraries(hb-ot-shape-closure harfbuzz)
diff --git a/test/api/CMakeLists.txt b/test/api/CMakeLists.txt
index c3914e48..f1a2300f 100644
--- a/test/api/CMakeLists.txt
+++ b/test/api/CMakeLists.txt
@@ -20,7 +20,7 @@ if (HB_HAVE_GLIB)
else ()
message (FATAL_ERROR "No source file found for test ${test_name}")
endif ()
- target_link_libraries (${test_name} harfbuzz)
+ target_link_libraries (${test_name} harfbuzz harfbuzz-subset)
add_test (${test_name} ${test_name})
endforeach ()
set_tests_properties (${TEST_PROGS} PROPERTIES ENVIRONMENT
commit d4d120ad79ff65c6987ca127da5d9ee30740b0b1
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 8 14:26:18 2018 -0800
Skip subset to fonttools comparison test if TTX is not present.
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 353101a3..c19004ab 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -78,6 +78,11 @@ if not len(args):
print ("No tests supplied.")
sys.exit (1)
+_, returncode = cmd(["which", "ttx"])
+if returncode:
+ print("TTX is not present, skipping test.")
+ sys.exit (77)
+
fails = 0
for path in args:
with io.open(path, mode="r", encoding="utf-8") as f:
commit 29d915284e46fb9be01221a88c9e969080daa1b2
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 8 11:31:27 2018 -0800
Whitespace
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index 32695162..353101a3 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -47,13 +47,13 @@ def run_test(test):
if return_code:
return fail_test(test, cli_args, "%s returned %d" % (' '.join(cli_args), return_code))
- expected_ttx, return_code = run_ttx(os.path.join(test_suite.get_output_directory(),
+ expected_ttx, return_code = run_ttx(os.path.join(test_suite.get_output_directory(),
test.get_font_name()))
- if return_code:
+ if return_code:
return fail_test(test, cli_args, "ttx (expected) returned %d" % (return_code))
- actual_ttx, return_code = run_ttx(out_file)
- if return_code:
+ actual_ttx, return_code = run_ttx(out_file)
+ if return_code:
return fail_test(test, cli_args, "ttx (actual) returned %d" % (return_code))
if not actual_ttx == expected_ttx:
@@ -62,10 +62,10 @@ def run_test(test):
return 0
def run_ttx(file):
- cli_args = ["ttx",
- "-o-",
- file]
- return cmd(cli_args)
+ cli_args = ["ttx",
+ "-o-",
+ file]
+ return cmd(cli_args)
args = sys.argv[1:]
commit f9420d9effcfb3464d4b99e54decb3d90e4a410d
Author: Garret Rieger <grieger at google.com>
Date: Thu Feb 8 11:30:36 2018 -0800
In the hb-subset to fontTools comparison, use ttx to compare the fonts. This allows for some binary differences such as re-ordered tables.
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index b0054802..32695162 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -47,19 +47,26 @@ def run_test(test):
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(),
+ expected_ttx, return_code = run_ttx(os.path.join(test_suite.get_output_directory(),
test.get_font_name()))
- actual = read_binary(out_file)
+ if return_code:
+ return fail_test(test, cli_args, "ttx (expected) returned %d" % (return_code))
- if len(actual) != len(expected):
- return fail_test(test, cli_args, "expected %d bytes, actual %d: %s" % (
- len(expected), len(actual), ' '.join(cli_args)))
+ actual_ttx, return_code = run_ttx(out_file)
+ if return_code:
+ return fail_test(test, cli_args, "ttx (actual) returned %d" % (return_code))
- if not actual == expected:
- return fail_test(test, cli_args, 'files are the same length but not the same bytes')
+ if not actual_ttx == expected_ttx:
+ return fail_test(test, cli_args, 'ttx for expected and actual does not match.')
return 0
+def run_ttx(file):
+ cli_args = ["ttx",
+ "-o-",
+ file]
+ return cmd(cli_args)
+
args = sys.argv[1:]
if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
commit 8e9fd6f1ab491519cf7205467bc5d20056fce99d
Author: Garret Rieger <grieger at google.com>
Date: Wed Feb 7 19:01:21 2018 -0800
Implement basic loca (long version only) subsetting.
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index bbd74d7e..8221a43d 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -30,36 +30,48 @@
#include "hb-subset-glyf.hh"
bool
-_calculate_glyf_prime_size (const OT::glyf::accelerator_t &glyf,
- hb_set_t *glyph_ids,
- unsigned int *size /* OUT */)
+_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
+ hb_set_t *glyph_ids,
+ unsigned int *glyf_size /* OUT */,
+ unsigned int *loca_size /* OUT */)
{
unsigned int total = 0;
+ unsigned int count = 0;
hb_codepoint_t next_glyph = -1;
while (hb_set_next(glyph_ids, &next_glyph)) {
unsigned int start_offset, end_offset;
if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset))) {
- *size = 0;
+ *glyf_size = 0;
+ *loca_size = sizeof(OT::HBUINT32);
return false;
}
total += end_offset - start_offset;
+ count++;
}
- *size = total;
+ *glyf_size = total;
+ *loca_size = (count + 1) * sizeof(OT::HBUINT32);
return true;
}
bool
-_write_glyf_prime (const OT::glyf::accelerator_t &glyf,
- const char *glyf_data,
- hb_set_t *glyph_ids,
- int glyf_prime_size,
- char *glyf_prime_data /* OUT */)
+_write_glyf_and_loca_prime (const OT::glyf::accelerator_t &glyf,
+ const char *glyf_data,
+ const hb_set_t *glyph_ids,
+ int glyf_prime_size,
+ char *glyf_prime_data /* OUT */,
+ int loca_prime_size,
+ char *loca_prime_data /* OUT */)
{
+ // TODO(grieger): Handle the missing character glyf and outline.
+
char *glyf_prime_data_next = glyf_prime_data;
+ OT::HBUINT32 *loca_prime = (OT::HBUINT32*) loca_prime_data;
hb_codepoint_t next_glyph = -1;
+ hb_codepoint_t new_glyph_id = 0;
+
while (hb_set_next(glyph_ids, &next_glyph)) {
unsigned int start_offset, end_offset;
if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset))) {
@@ -68,33 +80,42 @@ _write_glyf_prime (const OT::glyf::accelerator_t &glyf,
int length = end_offset - start_offset;
memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
+ loca_prime[new_glyph_id].set(start_offset);
+
glyf_prime_data_next += length;
+ new_glyph_id++;
}
return true;
}
bool
-_hb_subset_glyf (const OT::glyf::accelerator_t &glyf,
- const char *glyf_data,
- hb_set_t *glyphs_to_retain,
- hb_blob_t **glyf_prime /* OUT */)
+_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
+ const char *glyf_data,
+ hb_set_t *glyphs_to_retain,
+ hb_blob_t **glyf_prime /* OUT */,
+ hb_blob_t **loca_prime /* OUT */)
{
// TODO(grieger): Sanity check writes to make sure they are in-bounds.
// TODO(grieger): Sanity check allocation size for the new table.
// TODO(grieger): Subset loca simultaneously.
// TODO(grieger): Don't fail on bad offsets, just dump them.
+ // TODO(grieger): Support short loca output.
unsigned int glyf_prime_size;
- if (unlikely (!_calculate_glyf_prime_size (glyf,
- glyphs_to_retain,
- &glyf_prime_size))) {
+ unsigned int loca_prime_size;
+ if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
+ glyphs_to_retain,
+ &glyf_prime_size,
+ &loca_prime_size))) {
return false;
}
char *glyf_prime_data = (char *) calloc (glyf_prime_size, 1);
- if (unlikely (!_write_glyf_prime (glyf, glyf_data, glyphs_to_retain, glyf_prime_size,
- glyf_prime_data))) {
+ char *loca_prime_data = (char *) calloc (loca_prime_size, 1);
+ if (unlikely (!_write_glyf_and_loca_prime (glyf, glyf_data, glyphs_to_retain,
+ glyf_prime_size, glyf_prime_data,
+ loca_prime_size, loca_prime_data))) {
free (glyf_prime_data);
return false;
}
@@ -104,6 +125,11 @@ _hb_subset_glyf (const OT::glyf::accelerator_t &glyf,
HB_MEMORY_MODE_READONLY,
glyf_prime_data,
free);
+ *loca_prime = hb_blob_create (loca_prime_data,
+ loca_prime_size,
+ HB_MEMORY_MODE_READONLY,
+ loca_prime_data,
+ free);
return true;
}
@@ -126,7 +152,7 @@ hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
OT::glyf::accelerator_t glyf;
glyf.init(face);
- bool result = _hb_subset_glyf (glyf, glyf_data, plan->glyphs_to_retain, glyf_prime);
+ bool result = _hb_subset_glyf_and_loca (glyf, glyf_data, plan->glyphs_to_retain, glyf_prime, loca_prime);
glyf.fini();
// TODO(grieger): Subset loca
commit f9c665fed1347f7af6d36ba129f9d174f4ac54dc
Author: Garret Rieger <grieger at google.com>
Date: Wed Feb 7 16:53:18 2018 -0800
Update interface to hb-subset-glyf to subset glyf and loca.
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 24256454..bbd74d7e 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -83,6 +83,7 @@ _hb_subset_glyf (const OT::glyf::accelerator_t &glyf,
// TODO(grieger): Sanity check writes to make sure they are in-bounds.
// TODO(grieger): Sanity check allocation size for the new table.
// TODO(grieger): Subset loca simultaneously.
+ // TODO(grieger): Don't fail on bad offsets, just dump them.
unsigned int glyf_prime_size;
if (unlikely (!_calculate_glyf_prime_size (glyf,
@@ -115,9 +116,10 @@ _hb_subset_glyf (const OT::glyf::accelerator_t &glyf,
* Since: 1.7.5
**/
bool
-hb_subset_glyf (hb_subset_plan_t *plan,
- hb_face_t *face,
- hb_blob_t **glyf_prime /* OUT */)
+hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
+ hb_face_t *face,
+ hb_blob_t **glyf_prime /* OUT */,
+ hb_blob_t **loca_prime /* OUT */)
{
hb_blob_t *glyf_blob = OT::Sanitizer<OT::glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
const char *glyf_data = hb_blob_get_data(glyf_blob, nullptr);
@@ -127,5 +129,7 @@ hb_subset_glyf (hb_subset_plan_t *plan,
bool result = _hb_subset_glyf (glyf, glyf_data, plan->glyphs_to_retain, glyf_prime);
glyf.fini();
+ // TODO(grieger): Subset loca
+
return result;
}
diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh
index fd217e79..c802da24 100644
--- a/src/hb-subset-glyf.hh
+++ b/src/hb-subset-glyf.hh
@@ -30,8 +30,9 @@
#include "hb-subset-plan.hh"
bool
-hb_subset_glyf (hb_subset_plan_t *plan,
- hb_face_t *face,
- hb_blob_t **glyf_prime /* OUT */);
+hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
+ hb_face_t *face,
+ hb_blob_t **glyf_prime /* OUT */,
+ hb_blob_t **loca_prime /* OUT */);
#endif /* HB_SUBSET_GLYF_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index bd4e34f6..f10f35ba 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -310,8 +310,11 @@ hb_subset (hb_face_t *source,
hb_face_t *dest = nullptr; // TODO allocate dest
hb_blob_t *glyf_prime = nullptr;
- if (hb_subset_glyf (plan, source, &glyf_prime)) {
- // TODO: write new glyf to new face.
+ hb_blob_t *loca_prime = nullptr;
+ if (hb_subset_glyf_and_loca (plan, source, &glyf_prime, &loca_prime)) {
+ // TODO: write new glyf and loca to new face.
+ } else {
+ success = false;
}
hb_blob_destroy (glyf_prime);
commit f2ceb5ee4d745e0e6e754f0b0ea16b29dbedbf1b
Author: Garret Rieger <grieger at google.com>
Date: Wed Feb 7 16:47:31 2018 -0800
Comment out failing assert in test-subset-glyf for now. Should be re-enabled once hb_subset is writing out a new face.
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index 320bfd2b..b7d56902 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -110,8 +110,9 @@ test_subset_glyf (void)
hb_blob_t *glyf_actual_blob = hb_face_reference_table (face_abc_subset, HB_TAG('g','l','y','f'));
int expected_length, actual_length;
- g_assert_cmpmem(hb_blob_get_data (glyf_expected_blob, &expected_length), expected_length,
- hb_blob_get_data (glyf_actual_blob, &actual_length), actual_length);
+ // TODO(grieger): Uncomment below once this actually works.
+ // g_assert_cmpmem(hb_blob_get_data (glyf_expected_blob, &expected_length), expected_length,
+ // hb_blob_get_data (glyf_actual_blob, &actual_length), actual_length);
hb_blob_destroy (glyf_actual_blob);
hb_blob_destroy (glyf_expected_blob);
commit 89dbebd4ad948ddad8e10323315a809c11d7cafa
Author: Garret Rieger <grieger at google.com>
Date: Wed Feb 7 16:32:56 2018 -0800
Add a basic test for glyf subsetting.
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index d596c38d..9cda5ef3 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -30,11 +30,13 @@ TEST_PROGS = \
test-set \
test-shape \
test-subset \
+ test-subset-glyf \
test-unicode \
test-version \
$(NULL)
test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_unicode_CPPFLAGS = \
$(AM_CPPFLAGS) \
@@ -60,6 +62,8 @@ TEST_PROGS += \
test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS)
test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
EXTRA_DIST += \
+ fonts/Roboto-Regular.abc.ttf \
+ fonts/Roboto-Regular.ac.ttf \
fonts/MathTestFontEmpty.otf \
fonts/MathTestFontFull.otf \
fonts/MathTestFontNone.otf \
diff --git a/test/api/fonts/Roboto-Regular.abc.ttf b/test/api/fonts/Roboto-Regular.abc.ttf
new file mode 100644
index 00000000..9d791f7f
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.abc.ttf differ
diff --git a/test/api/fonts/Roboto-Regular.ac.ttf b/test/api/fonts/Roboto-Regular.ac.ttf
new file mode 100644
index 00000000..6ac1b33d
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.ac.ttf differ
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
new file mode 100644
index 00000000..320bfd2b
--- /dev/null
+++ b/test/api/test-subset-glyf.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2018 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 <stdbool.h>
+
+#include "hb-test.h"
+
+#ifndef g_assert_cmpmem
+#define g_assert_cmpmem(m1, l1, m2, l2) g_assert_true (l1 == l2 && memcmp (m1, m2, l1) == 0)
+#endif
+
+static char *
+read_file (const char *path,
+ size_t *length)
+{
+ FILE *fp = fopen (path, "rb");
+
+ size_t file_length = 0;
+ char *buffer = NULL;
+ if (fp && fseek (fp, 0, SEEK_END) == 0) {
+ file_length = ftell(fp);
+ rewind (fp);
+ }
+
+ bool success = false;
+ if (file_length > 0) {
+ buffer = (char *) calloc (file_length + 1, sizeof(char));
+ if (fread (buffer, 1, file_length, fp) == file_length) {
+ *length = file_length;
+ } else {
+ free (buffer);
+ buffer = NULL;
+ }
+ }
+
+ if (fp)
+ fclose(fp);
+
+ return buffer;
+}
+
+static hb_face_t *
+open_font (const char *font_path)
+{
+ gchar *path = g_test_build_filename(G_TEST_DIST, font_path, NULL);
+
+ size_t length;
+ char *font_data = read_file(path, &length);
+
+ if (font_data != NULL) {
+ hb_blob_t *blob = hb_blob_create (font_data,
+ length,
+ HB_MEMORY_MODE_READONLY,
+ font_data,
+ free);
+ hb_face_t *face = hb_face_create (blob, 0);
+ hb_blob_destroy (blob);
+ return face;
+ }
+
+ return NULL;
+}
+
+
+/* Unit tests for hb-subset-glyf.h */
+
+static void
+test_subset_glyf (void)
+{
+ hb_face_t *face_abc = open_font("fonts/Roboto-Regular.abc.ttf");
+ hb_face_t *face_ac = open_font("fonts/Roboto-Regular.ac.ttf");
+
+ g_assert (face_abc);
+ g_assert (face_ac);
+
+ hb_set_t *codepoints = hb_set_create();
+ hb_set_add (codepoints, 97);
+ hb_set_add (codepoints, 99);
+
+ hb_subset_profile_t *profile = hb_subset_profile_create();
+ hb_subset_input_t *input = hb_subset_input_create (codepoints);
+
+ hb_face_t *face_abc_subset = hb_subset (face_abc, profile, input);
+ g_assert (face_abc_subset);
+
+ hb_blob_t *glyf_expected_blob = hb_face_reference_table (face_ac, HB_TAG('g','l','y','f'));
+ hb_blob_t *glyf_actual_blob = hb_face_reference_table (face_abc_subset, HB_TAG('g','l','y','f'));
+
+ int expected_length, actual_length;
+ g_assert_cmpmem(hb_blob_get_data (glyf_expected_blob, &expected_length), expected_length,
+ hb_blob_get_data (glyf_actual_blob, &actual_length), actual_length);
+
+ hb_blob_destroy (glyf_actual_blob);
+ hb_blob_destroy (glyf_expected_blob);
+ hb_subset_input_destroy (input);
+ hb_subset_profile_destroy (profile);
+ hb_set_destroy (codepoints);
+ hb_face_destroy (face_abc_subset);
+ hb_face_destroy (face_abc);
+ hb_face_destroy (face_ac);
+}
+
+int
+main (int argc, char **argv)
+{
+ hb_test_init (&argc, &argv);
+
+ hb_test_add (test_subset_glyf);
+
+ return hb_test_run();
+}
commit 217ed5e3c885532fa8b332cc0d0f9cb4eef32e2b
Author: Garret Rieger <grieger at google.com>
Date: Wed Feb 7 16:30:07 2018 -0800
Cleanups in hb-subset-glyf and hb-subset-plan.
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 6581754b..24256454 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -30,15 +30,15 @@
#include "hb-subset-glyf.hh"
bool
-calculate_glyf_prime_size (const OT::glyf::accelerator_t &glyf,
- hb_set_t *glyph_ids,
- unsigned int *size /* OUT */)
+_calculate_glyf_prime_size (const OT::glyf::accelerator_t &glyf,
+ hb_set_t *glyph_ids,
+ unsigned int *size /* OUT */)
{
unsigned int total = 0;
hb_codepoint_t next_glyph = -1;
while (hb_set_next(glyph_ids, &next_glyph)) {
unsigned int start_offset, end_offset;
- if (!glyf.get_offsets (next_glyph, &start_offset, &end_offset)) {
+ if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset))) {
*size = 0;
return false;
}
@@ -51,18 +51,18 @@ calculate_glyf_prime_size (const OT::glyf::accelerator_t &glyf,
}
bool
-write_glyf_prime (const OT::glyf::accelerator_t &glyf,
- const char *glyf_data,
- hb_set_t *glyph_ids,
- int glyf_prime_size,
- char *glyf_prime_data /* OUT */)
+_write_glyf_prime (const OT::glyf::accelerator_t &glyf,
+ const char *glyf_data,
+ hb_set_t *glyph_ids,
+ int glyf_prime_size,
+ char *glyf_prime_data /* OUT */)
{
char *glyf_prime_data_next = glyf_prime_data;
hb_codepoint_t next_glyph = -1;
while (hb_set_next(glyph_ids, &next_glyph)) {
unsigned int start_offset, end_offset;
- if (!glyf.get_offsets (next_glyph, &start_offset, &end_offset)) {
+ if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset))) {
return false;
}
@@ -85,15 +85,15 @@ _hb_subset_glyf (const OT::glyf::accelerator_t &glyf,
// TODO(grieger): Subset loca simultaneously.
unsigned int glyf_prime_size;
- if (!calculate_glyf_prime_size (glyf,
- glyphs_to_retain,
- &glyf_prime_size)) {
+ if (unlikely (!_calculate_glyf_prime_size (glyf,
+ glyphs_to_retain,
+ &glyf_prime_size))) {
return false;
}
char *glyf_prime_data = (char *) calloc (glyf_prime_size, 1);
- if (!write_glyf_prime (glyf, glyf_data, glyphs_to_retain, glyf_prime_size,
- glyf_prime_data)) {
+ if (unlikely (!_write_glyf_prime (glyf, glyf_data, glyphs_to_retain, glyf_prime_size,
+ glyf_prime_data))) {
free (glyf_prime_data);
return false;
}
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index b1ed1add..1e572a43 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -55,4 +55,4 @@ hb_subset_plan_get_empty ();
void
hb_subset_plan_destroy (hb_subset_plan_t *plan);
-#endif /* HB_SUBSET_PLAN_PRIVATE_HH */
+#endif /* HB_SUBSET_PLAN_HH */
commit 13193a9b97302480cc11787787fa6826a97be4bb
Author: Rod Sheeter <rsheeter at google.com>
Date: Wed Feb 7 16:09:52 2018 -0800
move to the hb_face_t dest pattern
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 570f1340..219eca7b 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -504,8 +504,13 @@ struct cmap
encodingRecord.sanitize (c, this));
}
- inline bool subset(hb_subset_plan_t *plan, OT::hb_serialize_context_t *out) const
+ inline bool subset(hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest) const
{
+ // TODO something useful re: memory, write to dest
+ size_t dest_sz = 64536; // as much as anyone would ever need
+ void *dest_buf = malloc(dest_sz);
+ OT::hb_serialize_context_t context(dest_buf, dest_sz);
+
// Same version
OT::cmap new_cmap;
new_cmap.version = version;
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 9c1d6d43..bd4e34f6 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -109,22 +109,21 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
template<typename TableType>
hb_bool_t
-subset(hb_subset_plan_t *plan, hb_face_t *face, hb_blob_t **out)
+subset(hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
{
OT::Sanitizer<TableType> sanitizer;
- hb_blob_t *table_blob = sanitizer.sanitize (face->reference_table (TableType::tableTag));
+ hb_blob_t *table_blob = sanitizer.sanitize (source->reference_table (TableType::tableTag));
if (unlikely(!table_blob)) {
+ DEBUG_MSG(SUBSET, nullptr, "Failed to reference table for tag %d", TableType::tableTag);
return false;
}
const TableType *table = OT::Sanitizer<TableType>::lock_instance (table_blob);
-
- // TODO actually manage the context/output memory
- size_t dest_sz = 64536; // as much as anyone would ever need
- void *dest = malloc(dest_sz);
- OT::hb_serialize_context_t context(dest, dest_sz);
- hb_bool_t result = table->subset(plan, &context);
- // TODO populate out
+ hb_bool_t result = table->subset(plan, source, dest);
+
hb_blob_destroy (table_blob);
+
+ // TODO string not numeric tag
+ DEBUG_MSG(SUBSET, nullptr, "Subset %d %s", TableType::tableTag, result ? "success" : "FAILED!");
return result;
}
@@ -306,18 +305,17 @@ hb_subset (hb_face_t *source,
// - copy the table into the output.
// - Fix header + table directory.
+ bool success = true;
+
+ hb_face_t *dest = nullptr; // TODO allocate dest
+
hb_blob_t *glyf_prime = nullptr;
if (hb_subset_glyf (plan, source, &glyf_prime)) {
// TODO: write new glyf to new face.
}
hb_blob_destroy (glyf_prime);
- hb_blob_t *cmap_prime = nullptr;
- if (subset<const OT::cmap>(plan, source, &cmap_prime)) {
- DEBUG_MSG(SUBSET, nullptr, "subset cmap success!");
- } else {
- DEBUG_MSG(SUBSET, nullptr, "subset cmap FAILED!");
- }
+ success = success && subset<const OT::cmap>(plan, source, dest);
hb_subset_plan_destroy (plan);
commit 0859a006695097c2a66a07284f3cc5b8de8edb05
Author: Rod Sheeter <rsheeter at google.com>
Date: Wed Feb 7 15:59:36 2018 -0800
sketch a subset<T> and call it for cmap. Add subset to cmap, albeit not working even for the msot basic case just yet
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index b9d6e248..570f1340 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -27,8 +27,8 @@
#ifndef HB_OT_CMAP_TABLE_HH
#define HB_OT_CMAP_TABLE_HH
-#include "hb-open-type-private.hh"
-
+#include "hb-open-type-private.hh"
+#include "hb-subset-plan.hh"
namespace OT {
@@ -504,6 +504,20 @@ struct cmap
encodingRecord.sanitize (c, this));
}
+ inline bool subset(hb_subset_plan_t *plan, OT::hb_serialize_context_t *out) const
+ {
+ // Same version
+ OT::cmap new_cmap;
+ new_cmap.version = version;
+ new_cmap.encodingRecord.len.set(1); // one format 12 subtable
+
+ // TODO we need to actually build the format 12 subtable
+
+ // TODO: this fails
+ // out->extend_min(new_cmap);
+ return true;
+ }
+
struct accelerator_t
{
inline void init (hb_face_t *face)
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 8c1e43f7..9c1d6d43 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -26,6 +26,8 @@
*/
#include "hb-object-private.hh"
+#include "hb-open-type-private.hh"
+
#include "hb-private.hh"
#include "hb-subset-glyf.hh"
@@ -33,6 +35,7 @@
#include "hb-subset-plan.hh"
#include "hb-open-file-private.hh"
+#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
@@ -104,6 +107,26 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
free (subset_input);
}
+template<typename TableType>
+hb_bool_t
+subset(hb_subset_plan_t *plan, hb_face_t *face, hb_blob_t **out)
+{
+ OT::Sanitizer<TableType> sanitizer;
+ hb_blob_t *table_blob = sanitizer.sanitize (face->reference_table (TableType::tableTag));
+ if (unlikely(!table_blob)) {
+ return false;
+ }
+ const TableType *table = OT::Sanitizer<TableType>::lock_instance (table_blob);
+
+ // TODO actually manage the context/output memory
+ size_t dest_sz = 64536; // as much as anyone would ever need
+ void *dest = malloc(dest_sz);
+ OT::hb_serialize_context_t context(dest, dest_sz);
+ hb_bool_t result = table->subset(plan, &context);
+ // TODO populate out
+ hb_blob_destroy (table_blob);
+ return result;
+}
/*
@@ -289,6 +312,13 @@ hb_subset (hb_face_t *source,
}
hb_blob_destroy (glyf_prime);
+ hb_blob_t *cmap_prime = nullptr;
+ if (subset<const OT::cmap>(plan, source, &cmap_prime)) {
+ DEBUG_MSG(SUBSET, nullptr, "subset cmap success!");
+ } else {
+ DEBUG_MSG(SUBSET, nullptr, "subset cmap FAILED!");
+ }
+
hb_subset_plan_destroy (plan);
return face;
More information about the HarfBuzz
mailing list