summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/Makefile.am5
-rw-r--r--util/Makefile.in91
-rw-r--r--util/Makefile.sources9
-rw-r--r--util/ansi-print.cc2
-rw-r--r--util/ansi-print.hh1
-rw-r--r--util/hb-ot-shape-closure.cc18
-rw-r--r--util/hb-shape.cc54
-rw-r--r--util/hb-subset.cc127
-rw-r--r--util/helper-cairo-ansi.hh5
-rw-r--r--util/helper-cairo.cc14
-rw-r--r--util/helper-cairo.hh7
-rw-r--r--util/main-font-text.hh36
-rw-r--r--util/options.cc274
-rw-r--r--util/options.hh313
-rw-r--r--util/shape-consumer.hh38
-rw-r--r--util/view-cairo.hh18
16 files changed, 779 insertions, 233 deletions
diff --git a/util/Makefile.am b/util/Makefile.am
index 2543a60..d4ab9cd 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -1,5 +1,6 @@
# Process this file with automake to produce Makefile.in
+NULL =
EXTRA_DIST =
CLEANFILES =
DISTCLEANFILES =
@@ -45,6 +46,10 @@ endif # HAVE_FREETYPE
hb_shape_SOURCES = $(HB_SHAPE_sources)
bin_PROGRAMS += hb-shape
+hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
+hb_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+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.in b/util/Makefile.in
index f6fe331..21092cf 100644
--- a/util/Makefile.in
+++ b/util/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -17,7 +17,17 @@
# Process this file with automake to produce Makefile.in
VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@@ -80,27 +90,27 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-DIST_COMMON = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \
- $(srcdir)/Makefile.am $(top_srcdir)/depcomp
bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__append_1 = hb-view
-@HAVE_GLIB_TRUE@am__append_2 = hb-shape
+@HAVE_GLIB_TRUE@am__append_2 = hb-shape hb-subset
@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__append_3 = hb-ot-shape-closure
subdir = util
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
- $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/gtk-doc.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__EXEEXT_1 = hb-view$(EXEEXT)
-@HAVE_GLIB_TRUE@am__EXEEXT_2 = hb-shape$(EXEEXT)
+@HAVE_GLIB_TRUE@am__EXEEXT_2 = hb-shape$(EXEEXT) hb-subset$(EXEEXT)
@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__EXEEXT_3 = \
@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ hb-ot-shape-closure$(EXEEXT)
am__installdirs = "$(DESTDIR)$(bindir)"
@@ -131,20 +141,27 @@ hb_shape_LDADD = $(LDADD)
hb_shape_DEPENDENCIES = $(top_builddir)/src/libharfbuzz.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
+am__hb_subset_SOURCES_DIST = hb-subset.cc options.cc options.hh \
+ main-font-text.hh
+am__objects_4 = hb-subset.$(OBJEXT) options.$(OBJEXT) $(am__objects_1)
+@HAVE_GLIB_TRUE@am_hb_subset_OBJECTS = $(am__objects_4)
+hb_subset_OBJECTS = $(am_hb_subset_OBJECTS)
+am__DEPENDENCIES_2 = $(top_builddir)/src/libharfbuzz.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+@HAVE_GLIB_TRUE@hb_subset_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz-subset.la
am__hb_view_SOURCES_DIST = hb-view.cc options.cc options.hh \
main-font-text.hh shape-consumer.hh ansi-print.cc \
ansi-print.hh helper-cairo.cc helper-cairo.hh \
helper-cairo-ansi.cc helper-cairo-ansi.hh view-cairo.cc \
view-cairo.hh
-am__objects_4 = hb-view.$(OBJEXT) options.$(OBJEXT) \
+am__objects_5 = hb-view.$(OBJEXT) options.$(OBJEXT) \
ansi-print.$(OBJEXT) helper-cairo.$(OBJEXT) \
helper-cairo-ansi.$(OBJEXT) view-cairo.$(OBJEXT) \
$(am__objects_1)
-@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am_hb_view_OBJECTS = $(am__objects_4)
+@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am_hb_view_OBJECTS = $(am__objects_5)
hb_view_OBJECTS = $(am_hb_view_OBJECTS)
-am__DEPENDENCIES_2 = $(top_builddir)/src/libharfbuzz.la \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@hb_view_DEPENDENCIES = $(am__DEPENDENCIES_2) \
@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) \
@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) \
@@ -202,9 +219,10 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(hb_ot_shape_closure_SOURCES) $(hb_shape_SOURCES) \
- $(hb_view_SOURCES)
+ $(hb_subset_SOURCES) $(hb_view_SOURCES)
DIST_SOURCES = $(am__hb_ot_shape_closure_SOURCES_DIST) \
- $(am__hb_shape_SOURCES_DIST) $(am__hb_view_SOURCES_DIST)
+ $(am__hb_shape_SOURCES_DIST) $(am__hb_subset_SOURCES_DIST) \
+ $(am__hb_view_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -229,6 +247,8 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.sources \
+ $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -245,6 +265,12 @@ CAIRO_LIBS = @CAIRO_LIBS@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
+CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
+CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
CORETEXT_CFLAGS = @CORETEXT_CFLAGS@
CORETEXT_LIBS = @CORETEXT_LIBS@
CPP = @CPP@
@@ -272,6 +298,8 @@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
FREETYPE_DEPS = @FREETYPE_DEPS@
FREETYPE_LIBS = @FREETYPE_LIBS@
+GCOV = @GCOV@
+GENHTML = @GENHTML@
GIT = @GIT@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_DEPS = @GLIB_DEPS@
@@ -311,6 +339,7 @@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
@@ -319,6 +348,7 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
@@ -375,6 +405,7 @@ datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
+have_gobject = @have_gobject@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -395,6 +426,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -403,11 +435,11 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+NULL =
EXTRA_DIST =
CLEANFILES =
DISTCLEANFILES =
MAINTAINERCLEANFILES =
-NULL =
HB_VIEW_sources = \
hb-view.cc \
options.cc \
@@ -439,6 +471,13 @@ HB_OT_SHAPE_CLOSURE_sources = \
main-font-text.hh \
$(NULL)
+HB_SUBSET_CLI_sources = \
+ hb-subset.cc \
+ options.cc \
+ options.hh \
+ main-font-text.hh \
+ $(NULL)
+
AM_CPPFLAGS = \
-DHB_DISABLE_DEPRECATED \
-I$(top_srcdir)/src/ \
@@ -463,6 +502,8 @@ LDADD = \
@HAVE_CAIRO_FT_TRUE@@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@ $(NULL)
@HAVE_GLIB_TRUE@hb_shape_SOURCES = $(HB_SHAPE_sources)
+@HAVE_GLIB_TRUE@hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
+@HAVE_GLIB_TRUE@hb_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
all: all-am
@@ -480,7 +521,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(am__c
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits util/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnits util/Makefile
-.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -489,7 +529,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
-$(srcdir)/Makefile.sources:
+$(srcdir)/Makefile.sources $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
@@ -573,6 +613,10 @@ hb-shape$(EXEEXT): $(hb_shape_OBJECTS) $(hb_shape_DEPENDENCIES) $(EXTRA_hb_shape
@rm -f hb-shape$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(hb_shape_OBJECTS) $(hb_shape_LDADD) $(LIBS)
+hb-subset$(EXEEXT): $(hb_subset_OBJECTS) $(hb_subset_DEPENDENCIES) $(EXTRA_hb_subset_DEPENDENCIES)
+ @rm -f hb-subset$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(hb_subset_OBJECTS) $(hb_subset_LDADD) $(LIBS)
+
hb-view$(EXEEXT): $(hb_view_OBJECTS) $(hb_view_DEPENDENCIES) $(EXTRA_hb_view_DEPENDENCIES)
@rm -f hb-view$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(hb_view_OBJECTS) $(hb_view_LDADD) $(LIBS)
@@ -586,6 +630,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ansi-print.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb-ot-shape-closure.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb-shape.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb-subset.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hb-view.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper-cairo-ansi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper-cairo.Po@am__quote@
@@ -828,6 +873,8 @@ uninstall-am: uninstall-binPROGRAMS
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-binPROGRAMS
+.PRECIOUS: Makefile
+
# Convenience targets:
lib:
diff --git a/util/Makefile.sources b/util/Makefile.sources
index 368fdb0..6c815d2 100644
--- a/util/Makefile.sources
+++ b/util/Makefile.sources
@@ -1,5 +1,3 @@
-NULL =
-
HB_VIEW_sources = \
hb-view.cc \
options.cc \
@@ -30,3 +28,10 @@ HB_OT_SHAPE_CLOSURE_sources = \
options.hh \
main-font-text.hh \
$(NULL)
+
+HB_SUBSET_CLI_sources = \
+ hb-subset.cc \
+ options.cc \
+ options.hh \
+ main-font-text.hh \
+ $(NULL)
diff --git a/util/ansi-print.cc b/util/ansi-print.cc
index e0ce7b3..0daee1f 100644
--- a/util/ansi-print.cc
+++ b/util/ansi-print.cc
@@ -353,7 +353,7 @@ block_best (const biimage_t &bi, bool *inverse)
} else
qs += quad[i][j];
if (qs < score) {
- const char *c = NULL;
+ const char *c = nullptr;
bool inv = false;
switch (q) {
case 1: c = "▟"; inv = true; break;
diff --git a/util/ansi-print.hh b/util/ansi-print.hh
index dad4d4c..1ea5b37 100644
--- a/util/ansi-print.hh
+++ b/util/ansi-print.hh
@@ -27,6 +27,7 @@
#ifndef ANSI_PRINT_HH
#define ANSI_PRINT_HH
+#include "hb-private.hh"
#include <hb.h> /* for int types */
void
diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc
index 859f9a6..77ca201 100644
--- a/util/hb-ot-shape-closure.cc
+++ b/util/hb-ot-shape-closure.cc
@@ -43,8 +43,8 @@ struct shape_closure_consumer_t : option_group_t
{
GOptionEntry entries[] =
{
- {"no-glyph-names", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_glyph_names, "Use glyph indices instead of names", NULL},
- {NULL}
+ {"no-glyph-names", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_glyph_names, "Use glyph indices instead of names", nullptr},
+ {nullptr}
};
parser->add_group (entries,
"format",
@@ -53,14 +53,15 @@ struct shape_closure_consumer_t : option_group_t
this);
}
- void init (const font_options_t *font_opts)
+ void init (hb_buffer_t *buffer_,
+ const font_options_t *font_opts)
{
glyphs = hb_set_create ();
font = hb_font_reference (font_opts->get_font ());
failed = false;
+ buffer = hb_buffer_reference (buffer_);
}
- void consume_line (hb_buffer_t *buffer,
- const char *text,
+ void consume_line (const char *text,
unsigned int text_len,
const char *text_before,
const char *text_after)
@@ -92,9 +93,11 @@ struct shape_closure_consumer_t : option_group_t
{
printf ("\n");
hb_font_destroy (font);
- font = NULL;
+ font = nullptr;
hb_set_destroy (glyphs);
- glyphs = NULL;
+ glyphs = nullptr;
+ hb_buffer_destroy (buffer);
+ buffer = nullptr;
}
bool failed;
@@ -105,6 +108,7 @@ struct shape_closure_consumer_t : option_group_t
hb_set_t *glyphs;
hb_font_t *font;
+ hb_buffer_t *buffer;
};
int
diff --git a/util/hb-shape.cc b/util/hb-shape.cc
index 75c3793..337cd43 100644
--- a/util/hb-shape.cc
+++ b/util/hb-shape.cc
@@ -33,16 +33,16 @@ struct output_buffer_t
output_buffer_t (option_parser_t *parser)
: options (parser, hb_buffer_serialize_list_formats ()),
format (parser),
- gs (NULL),
+ gs (nullptr),
line_no (0),
- font (NULL),
+ font (nullptr),
output_format (HB_BUFFER_SERIALIZE_FORMAT_INVALID),
format_flags (HB_BUFFER_SERIALIZE_FLAG_DEFAULT) {}
- void init (const font_options_t *font_opts)
+ void init (hb_buffer_t *buffer, const font_options_t *font_opts)
{
options.get_file_handle ();
- gs = g_string_new (NULL);
+ gs = g_string_new (nullptr);
line_no = 0;
font = hb_font_reference (font_opts->get_font ());
@@ -72,9 +72,16 @@ struct output_buffer_t
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS;
if (!format.show_positions)
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
+ if (!format.show_advances)
+ flags |= HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES;
if (format.show_extents)
flags |= HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS;
+ if (format.show_flags)
+ flags |= HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS;
format_flags = (hb_buffer_serialize_flags_t) flags;
+
+ if (format.trace)
+ hb_buffer_set_message_func (buffer, message_func, this, nullptr);
}
void new_line (void)
{
@@ -89,13 +96,10 @@ struct output_buffer_t
format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, gs);
fprintf (options.fp, "%s", gs->str);
}
- void shape_failed (hb_buffer_t *buffer,
- const char *text,
- unsigned int text_len,
- hb_bool_t utf8_clusters)
+ void error (const char *message)
{
g_string_set_size (gs, 0);
- format.serialize_message (line_no, "msg: all shapers failed", gs);
+ format.serialize_message (line_no, "error", message, gs);
fprintf (options.fp, "%s", gs->str);
}
void consume_glyphs (hb_buffer_t *buffer,
@@ -108,14 +112,40 @@ struct output_buffer_t
output_format, format_flags, gs);
fprintf (options.fp, "%s", gs->str);
}
- void finish (const font_options_t *font_opts)
+ void finish (hb_buffer_t *buffer, const font_options_t *font_opts)
{
+ hb_buffer_set_message_func (buffer, nullptr, nullptr, nullptr);
hb_font_destroy (font);
g_string_free (gs, true);
- gs = NULL;
- font = NULL;
+ gs = nullptr;
+ font = nullptr;
+ }
+
+ static hb_bool_t
+ message_func (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *message,
+ void *user_data)
+ {
+ output_buffer_t *that = (output_buffer_t *) user_data;
+ that->trace (buffer, font, message);
+ return true;
}
+ void
+ trace (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *message)
+ {
+ g_string_set_size (gs, 0);
+ format.serialize_line_no (line_no, gs);
+ g_string_append_printf (gs, "trace: %s buffer: ", message);
+ format.serialize_glyphs (buffer, font, output_format, format_flags, gs);
+ g_string_append_c (gs, '\n');
+ fprintf (options.fp, "%s", gs->str);
+ }
+
+
protected:
output_options_t options;
format_options_t format;
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
new file mode 100644
index 0000000..2061755
--- /dev/null
+++ b/util/hb-subset.cc
@@ -0,0 +1,127 @@
+/*
+ * 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 <stdio.h>
+
+#include "main-font-text.hh"
+#include "hb-subset.h"
+#include "hb-subset-private.hh"
+
+/*
+ * Command line interface to the harfbuzz font subsetter.
+ */
+
+struct subset_consumer_t
+{
+ subset_consumer_t (option_parser_t *parser)
+ : failed (false), options (parser), subset_options (parser), font (nullptr), input (nullptr) {}
+
+ void init (hb_buffer_t *buffer_,
+ const font_options_t *font_opts)
+ {
+ font = hb_font_reference (font_opts->get_font ());
+ input = hb_subset_input_create_or_fail ();
+ }
+
+ void consume_line (const char *text,
+ unsigned int text_len,
+ const char *text_before,
+ const char *text_after)
+ {
+ // TODO(Q1) does this only get called with at least 1 codepoint?
+ hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+ gchar *c = (gchar *)text;
+ do {
+ gunichar cp = g_utf8_get_char(c);
+ hb_codepoint_t hb_cp = cp;
+ hb_set_add (codepoints, hb_cp);
+ } while ((c = g_utf8_find_next_char(c, text + text_len)) != nullptr);
+ }
+
+ 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);
+
+ FILE *fp_out = fopen(output_file, "wb");
+ if (fp_out == nullptr) {
+ fprintf(stderr, "Unable to open output file\n");
+ return false;
+ }
+ int bytes_written = fwrite(data, 1, data_length, fp_out);
+
+ fclose (fp_out);
+
+ if (bytes_written == -1) {
+ fprintf(stderr, "Unable to write output file\n");
+ return false;
+ }
+ if ((unsigned int) bytes_written != data_length) {
+ fprintf(stderr, "Expected %u bytes written, got %d\n", data_length,
+ bytes_written);
+ return false;
+ }
+ return true;
+ }
+
+ void finish (const font_options_t *font_opts)
+ {
+ input->drop_hints = subset_options.drop_hints;
+
+ hb_subset_profile_t *subset_profile = hb_subset_profile_create();
+ hb_face_t *face = hb_font_get_face (font);
+
+ hb_face_t *new_face = hb_subset(face, subset_profile, input);
+ hb_blob_t *result = hb_face_reference_blob (new_face);
+
+ failed = !hb_blob_get_length (result);
+ if (!failed)
+ write_file (options.output_file, result);
+
+ hb_subset_profile_destroy (subset_profile);
+ hb_subset_input_destroy (input);
+ hb_blob_destroy (result);
+ hb_face_destroy (new_face);
+ hb_font_destroy (font);
+ }
+
+ public:
+ bool failed;
+
+ private:
+ output_options_t options;
+ subset_options_t subset_options;
+ hb_font_t *font;
+ hb_subset_input_t *input;
+};
+
+int
+main (int argc, char **argv)
+{
+ main_font_text_t<subset_consumer_t, 10, 0> driver;
+ return driver.main (argc, argv);
+}
diff --git a/util/helper-cairo-ansi.hh b/util/helper-cairo-ansi.hh
index eeaaa50..cf18ea4 100644
--- a/util/helper-cairo-ansi.hh
+++ b/util/helper-cairo-ansi.hh
@@ -24,11 +24,12 @@
* Google Author(s): Behdad Esfahbod
*/
-#include <cairo.h>
-
#ifndef HELPER_CAIRO_ANSI_HH
#define HELPER_CAIRO_ANSI_HH
+#include "hb-private.hh"
+
+#include <cairo.h>
cairo_status_t
helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface,
diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc
index 2e2952b..b9f4985 100644
--- a/util/helper-cairo.cc
+++ b/util/helper-cairo.cc
@@ -79,7 +79,7 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
/* We cannot use the FT_Face from hb_font_t, as doing so will confuse hb_font_t because
* cairo will reset the face size. As such, create new face...
* TODO Perhaps add API to hb-ft to encapsulate this code. */
- FT_Face ft_face = NULL;//hb_ft_font_get_face (font);
+ FT_Face ft_face = nullptr;//hb_ft_font_get_face (font);
if (!ft_face)
{
if (!ft_library)
@@ -103,6 +103,7 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
}
else
{
+#ifdef HAVE_FT_SET_VAR_BLEND_COORDINATES
unsigned int num_coords;
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
if (num_coords)
@@ -116,6 +117,7 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts)
free (ft_coords);
}
}
+#endif
cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
}
@@ -325,7 +327,7 @@ const char *helper_cairo_supported_formats[] =
"eps",
#endif
#endif
- NULL
+ nullptr
};
cairo_t *
@@ -337,12 +339,12 @@ helper_cairo_create_context (double w, double h,
cairo_surface_t *(*constructor) (cairo_write_func_t write_func,
void *closure,
double width,
- double height) = NULL;
+ double height) = nullptr;
cairo_surface_t *(*constructor2) (cairo_write_func_t write_func,
void *closure,
double width,
double height,
- cairo_content_t content) = NULL;
+ cairo_content_t content) = nullptr;
const char *extension = out_opts->output_format;
if (!extension) {
@@ -471,8 +473,8 @@ helper_cairo_line_from_buffer (helper_cairo_line_t *l,
memset (l, 0, sizeof (*l));
l->num_glyphs = hb_buffer_get_length (buffer);
- hb_glyph_info_t *hb_glyph = hb_buffer_get_glyph_infos (buffer, NULL);
- hb_glyph_position_t *hb_position = hb_buffer_get_glyph_positions (buffer, NULL);
+ hb_glyph_info_t *hb_glyph = hb_buffer_get_glyph_infos (buffer, nullptr);
+ hb_glyph_position_t *hb_position = hb_buffer_get_glyph_positions (buffer, nullptr);
l->glyphs = cairo_glyph_allocate (l->num_glyphs + 1);
if (text) {
diff --git a/util/helper-cairo.hh b/util/helper-cairo.hh
index 27b6eb3..50bc0af 100644
--- a/util/helper-cairo.hh
+++ b/util/helper-cairo.hh
@@ -24,13 +24,14 @@
* Google Author(s): Behdad Esfahbod
*/
+#ifndef HELPER_CAIRO_HH
+#define HELPER_CAIRO_HH
+
+#include "hb-private.hh"
#include "options.hh"
#include <cairo.h>
-#ifndef HELPER_CAIRO_HH
-#define HELPER_CAIRO_HH
-
cairo_scaled_font_t *
helper_cairo_create_scaled_font (const font_options_t *font_opts);
diff --git a/util/main-font-text.hh b/util/main-font-text.hh
index 55de567..3390371 100644
--- a/util/main-font-text.hh
+++ b/util/main-font-text.hh
@@ -24,20 +24,21 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "options.hh"
-
#ifndef HB_MAIN_FONT_TEXT_HH
#define HB_MAIN_FONT_TEXT_HH
+#include "hb-private.hh"
+#include "options.hh"
+
/* main() body for utilities taking font and processing text.*/
static char *
locale_to_utf8 (char *s)
{
char *t;
- GError *error = NULL;
+ GError *error = nullptr;
- t = g_locale_to_utf8 (s, -1, NULL, NULL, &error);
+ t = g_locale_to_utf8 (s, -1, nullptr, nullptr, &error);
if (!t)
{
fail (true, "Failed converting text to UTF-8");
@@ -46,23 +47,6 @@ locale_to_utf8 (char *s)
return t;
}
-static hb_bool_t
-message_func (hb_buffer_t *buffer,
- hb_font_t *font,
- const char *message,
- void *user_data)
-{
- fprintf (stderr, "HB: %s\n", message);
- char buf[4096];
- hb_buffer_serialize_glyphs (buffer, 0, hb_buffer_get_length (buffer),
- buf, sizeof (buf), NULL,
- font,
- HB_BUFFER_SERIALIZE_FORMAT_TEXT,
- HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
- fprintf (stderr, "HB: buffer [%s]\n", buf);
- return true;
-}
-
template <typename consumer_t, int default_font_size, int subpixel_bits>
struct main_font_text_t
{
@@ -87,16 +71,14 @@ struct main_font_text_t
if (!input.text && !input.text_file)
input.text_file = g_strdup ("-");
- consumer.init (&font_opts);
-
hb_buffer_t *buffer = hb_buffer_create ();
- if (debug)
- hb_buffer_set_message_func (buffer, message_func, NULL, NULL);
+ consumer.init (buffer, &font_opts);
+ hb_buffer_destroy (buffer);
+
unsigned int text_len;
const char *text;
while ((text = input.get_line (&text_len)))
- consumer.consume_line (buffer, text, text_len, input.text_before, input.text_after);
- hb_buffer_destroy (buffer);
+ consumer.consume_line (text, text_len, input.text_before, input.text_after);
consumer.finish (&font_opts);
diff --git a/util/options.cc b/util/options.cc
index 0f2e207..db7115c 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -70,7 +70,7 @@ hb_bool_t debug = false;
static gchar *
shapers_to_string (void)
{
- GString *shapers = g_string_new (NULL);
+ GString *shapers = g_string_new (nullptr);
const char **shaper_list = hb_shape_list_shapers ();
for (; *shaper_list; shaper_list++) {
@@ -106,11 +106,11 @@ option_parser_t::add_main_options (void)
GOptionEntry entries[] =
{
{"version", 0, G_OPTION_FLAG_NO_ARG,
- G_OPTION_ARG_CALLBACK, (gpointer) &show_version, "Show version numbers", NULL},
- {"debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Free all resources before exit", NULL},
- {NULL}
+ G_OPTION_ARG_CALLBACK, (gpointer) &show_version, "Show version numbers", nullptr},
+ {"debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Free all resources before exit", nullptr},
+ {nullptr}
};
- g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_add_main_entries (context, entries, nullptr);
}
static gboolean
@@ -121,7 +121,7 @@ pre_parse (GOptionContext *context G_GNUC_UNUSED,
{
option_group_t *option_group = (option_group_t *) data;
option_group->pre_parse (error);
- return *error == NULL;
+ return *error == nullptr;
}
static gboolean
@@ -132,7 +132,7 @@ post_parse (GOptionContext *context G_GNUC_UNUSED,
{
option_group_t *option_group = static_cast<option_group_t *>(data);
option_group->post_parse (error);
- return *error == NULL;
+ return *error == nullptr;
}
void
@@ -143,7 +143,7 @@ option_parser_t::add_group (GOptionEntry *entries,
option_group_t *option_group)
{
GOptionGroup *group = g_option_group_new (name, description, help_description,
- static_cast<gpointer>(option_group), NULL);
+ static_cast<gpointer>(option_group), nullptr);
g_option_group_add_entries (group, entries);
g_option_group_set_parse_hooks (group, pre_parse, post_parse);
g_option_context_add_group (context, group);
@@ -154,10 +154,10 @@ option_parser_t::parse (int *argc, char ***argv)
{
setlocale (LC_ALL, "");
- GError *parse_error = NULL;
+ GError *parse_error = nullptr;
if (!g_option_context_parse (context, argc, argv, &parse_error))
{
- if (parse_error != NULL) {
+ if (parse_error != nullptr) {
fail (true, "%s", parse_error->message);
//g_error_free (parse_error);
} else
@@ -225,7 +225,7 @@ parse_features (const char *name G_GNUC_UNUSED,
shape_opts->num_features = 0;
g_free (shape_opts->features);
- shape_opts->features = NULL;
+ shape_opts->features = nullptr;
if (!*s)
return true;
@@ -240,6 +240,8 @@ parse_features (const char *name G_GNUC_UNUSED,
} while (p);
shape_opts->features = (hb_feature_t *) calloc (shape_opts->num_features, sizeof (*shape_opts->features));
+ if (!shape_opts->features)
+ return false;
/* now do the actual parsing */
p = s;
@@ -248,7 +250,7 @@ parse_features (const char *name G_GNUC_UNUSED,
char *end = strchr (p, ',');
if (hb_feature_from_string (p, end ? end - p : -1, &shape_opts->features[shape_opts->num_features]))
shape_opts->num_features++;
- p = end ? end + 1 : NULL;
+ p = end ? end + 1 : nullptr;
}
return true;
@@ -266,7 +268,7 @@ parse_variations (const char *name G_GNUC_UNUSED,
font_opts->num_variations = 0;
g_free (font_opts->variations);
- font_opts->variations = NULL;
+ font_opts->variations = nullptr;
if (!*s)
return true;
@@ -281,6 +283,8 @@ parse_variations (const char *name G_GNUC_UNUSED,
} while (p);
font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations));
+ if (!font_opts->variations)
+ return false;
/* now do the actual parsing */
p = s;
@@ -289,24 +293,86 @@ parse_variations (const char *name G_GNUC_UNUSED,
char *end = strchr (p, ',');
if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations]))
font_opts->num_variations++;
- p = end ? end + 1 : NULL;
+ p = end ? end + 1 : nullptr;
}
return true;
}
+static gboolean
+parse_text (const char *name G_GNUC_UNUSED,
+ const char *arg,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
+{
+ text_options_t *text_opts = (text_options_t *) data;
+
+ if (text_opts->text)
+ {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Either --text or --unicodes can be provided but not both");
+ return false;
+ }
+
+ text_opts->text = g_strdup (arg);
+ return true;
+}
+
+
+static gboolean
+parse_unicodes (const char *name G_GNUC_UNUSED,
+ const char *arg,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
+{
+ text_options_t *text_opts = (text_options_t *) data;
+
+ if (text_opts->text)
+ {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Either --text or --unicodes can be provided but not both");
+ return false;
+ }
+
+ GString *gs = g_string_new (nullptr);
+ char *s = (char *) arg;
+ char *p;
+
+ while (s && *s)
+ {
+ while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t", *s))
+ s++;
+
+ errno = 0;
+ hb_codepoint_t u = strtoul (s, &p, 16);
+ if (errno || s == p)
+ {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Failed parsing Unicode values at: '%s'", s);
+ return false;
+ }
+
+ g_string_append_unichar (gs, u);
+
+ s = p;
+ }
+
+ text_opts->text = g_string_free (gs, FALSE);
+ return true;
+}
+
void
view_options_t::add_options (option_parser_t *parser)
{
GOptionEntry entries[] =
{
- {"annotate", 0, 0, G_OPTION_ARG_NONE, &this->annotate, "Annotate output rendering", NULL},
+ {"annotate", 0, 0, G_OPTION_ARG_NONE, &this->annotate, "Annotate output rendering", nullptr},
{"background", 0, 0, G_OPTION_ARG_STRING, &this->back, "Set background color (default: " DEFAULT_BACK ")", "rrggbb/rrggbbaa"},
{"foreground", 0, 0, G_OPTION_ARG_STRING, &this->fore, "Set foreground color (default: " DEFAULT_FORE ")", "rrggbb/rrggbbaa"},
{"line-space", 0, 0, G_OPTION_ARG_DOUBLE, &this->line_space, "Set space between lines (default: 0)", "units"},
{"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: " G_STRINGIFY(DEFAULT_MARGIN) ")","one to four numbers"},
- {NULL}
+ {nullptr}
};
parser->add_group (entries,
"view",
@@ -321,21 +387,23 @@ shape_options_t::add_options (option_parser_t *parser)
GOptionEntry entries[] =
{
{"list-shapers", 0, G_OPTION_FLAG_NO_ARG,
- G_OPTION_ARG_CALLBACK, (gpointer) &list_shapers, "List available shapers and quit", NULL},
+ G_OPTION_ARG_CALLBACK, (gpointer) &list_shapers, "List available shapers and quit", nullptr},
{"shaper", 0, G_OPTION_FLAG_HIDDEN,
- G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Hidden duplicate of --shapers", NULL},
+ G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Hidden duplicate of --shapers", nullptr},
{"shapers", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Set comma-separated list of shapers to try","list"},
{"direction", 0, 0, G_OPTION_ARG_STRING, &this->direction, "Set text direction (default: auto)", "ltr/rtl/ttb/btt"},
{"language", 0, 0, G_OPTION_ARG_STRING, &this->language, "Set text language (default: $LANG)", "langstr"},
{"script", 0, 0, G_OPTION_ARG_STRING, &this->script, "Set text script (default: auto)", "ISO-15924 tag"},
- {"bot", 0, 0, G_OPTION_ARG_NONE, &this->bot, "Treat text as beginning-of-paragraph", NULL},
- {"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", NULL},
- {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", NULL},
- {"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", NULL},
+ {"bot", 0, 0, G_OPTION_ARG_NONE, &this->bot, "Treat text as beginning-of-paragraph", nullptr},
+ {"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", nullptr},
+ {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", nullptr},
+ {"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->remove_default_ignorables, "Remove Default-Ignorable characters", nullptr},
+ {"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr},
{"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"},
- {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", NULL},
+ {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr},
+ {"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr},
{"num-iterations", 0, 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
- {NULL}
+ {nullptr}
};
parser->add_group (entries,
"shape",
@@ -382,7 +450,7 @@ shape_options_t::add_options (option_parser_t *parser)
GOptionEntry entries2[] =
{
{"features", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_features, features_help, "list"},
- {NULL}
+ {nullptr}
};
parser->add_group (entries2,
"features",
@@ -408,19 +476,39 @@ parse_font_size (const char *name G_GNUC_UNUSED,
case 2: return true;
default:
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
- "%s argument should be one to four space-separated numbers",
+ "%s argument should be one or two space-separated numbers",
name);
return false;
}
}
+
+static gboolean
+parse_font_ppem (const char *name G_GNUC_UNUSED,
+ const char *arg,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
+{
+ font_options_t *font_opts = (font_options_t *) data;
+ switch (sscanf (arg, "%d%*[ ,]%d", &font_opts->x_ppem, &font_opts->y_ppem)) {
+ case 1: font_opts->y_ppem = font_opts->x_ppem;
+ case 2: return true;
+ default:
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "%s argument should be one or two space-separated numbers",
+ name);
+ return false;
+ }
+}
+
void
font_options_t::add_options (option_parser_t *parser)
{
- char *text = NULL;
+ char *text = nullptr;
{
- ASSERT_STATIC (ARRAY_LENGTH_CONST (supported_font_funcs) > 0);
- GString *s = g_string_new (NULL);
+ static_assert ((ARRAY_LENGTH_CONST (supported_font_funcs) > 0),
+ "No supported font-funcs found.");
+ GString *s = g_string_new (nullptr);
g_string_printf (s, "Set font functions implementation to use (default: %s)\n\n Supported font function implementations are: %s",
supported_font_funcs[0].name,
supported_font_funcs[0].name);
@@ -444,12 +532,14 @@ font_options_t::add_options (option_parser_t *parser)
GOptionEntry entries[] =
{
- {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"},
- {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"},
+ {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"},
+ {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"},
{"font-size", 0, default_font_size ? 0 : G_OPTION_FLAG_HIDDEN,
- G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 numbers or 'upem'"},
- {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
- {NULL}
+ G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 integers or 'upem'"},
+ {"font-ppem", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"},
+ {"font-ptem", 0, 0, G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"},
+ {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
+ {nullptr}
};
parser->add_group (entries,
"font",
@@ -472,11 +562,11 @@ font_options_t::add_options (option_parser_t *parser)
GOptionEntry entries2[] =
{
{"variations", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_variations, variations_help, "list"},
- {NULL}
+ {nullptr}
};
parser->add_group (entries2,
"variations",
- "Varitions options:",
+ "Variations options:",
"Options for font variations used",
this);
}
@@ -486,11 +576,12 @@ text_options_t::add_options (option_parser_t *parser)
{
GOptionEntry entries[] =
{
- {"text", 0, 0, G_OPTION_ARG_STRING, &this->text, "Set input text", "string"},
+ {"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Set input text", "string"},
{"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name\n\n If no text is provided, standard input is used for input.\n", "filename"},
+ {"unicodes", 'u', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"},
{"text-before", 0, 0, G_OPTION_ARG_STRING, &this->text_before, "Set text context before each line", "string"},
{"text-after", 0, 0, G_OPTION_ARG_STRING, &this->text_after, "Set text context after each line", "string"},
- {NULL}
+ {nullptr}
};
parser->add_group (entries,
"text",
@@ -504,7 +595,7 @@ output_options_t::add_options (option_parser_t *parser)
{
const char *text;
- if (NULL == supported_formats)
+ if (nullptr == supported_formats)
text = "Set output serialization format";
else
{
@@ -516,9 +607,9 @@ output_options_t::add_options (option_parser_t *parser)
GOptionEntry entries[] =
{
- {"output-file", 0, 0, G_OPTION_ARG_STRING, &this->output_file, "Set output file-name (default: stdout)","filename"},
- {"output-format", 0, 0, G_OPTION_ARG_STRING, &this->output_format, text, "format"},
- {NULL}
+ {"output-file", 'o', 0, G_OPTION_ARG_STRING, &this->output_file, "Set output file-name (default: stdout)","filename"},
+ {"output-format", 'O', 0, G_OPTION_ARG_STRING, &this->output_format, text, "format"},
+ {nullptr}
};
parser->add_group (entries,
"output",
@@ -535,7 +626,7 @@ font_options_t::get_font (void) const
if (font)
return font;
- hb_blob_t *blob = NULL;
+ hb_blob_t *blob = nullptr;
/* Create the blob */
{
@@ -551,7 +642,7 @@ font_options_t::get_font (void) const
if (0 == strcmp (font_file, "-")) {
/* read it */
- GString *gs = g_string_new (NULL);
+ GString *gs = g_string_new (nullptr);
char buf[BUFSIZ];
#if defined(_WIN32) || defined(__CYGWIN__)
setmode (fileno (stdin), O_BINARY);
@@ -569,7 +660,7 @@ font_options_t::get_font (void) const
destroy = (hb_destroy_func_t) g_free;
mm = HB_MEMORY_MODE_WRITABLE;
} else {
- GError *error = NULL;
+ GError *error = nullptr;
GMappedFile *mf = g_mapped_file_new (font_file, false, &error);
if (mf) {
font_data = g_mapped_file_get_contents (mf);
@@ -588,7 +679,7 @@ font_options_t::get_font (void) const
/* GMappedFile is buggy, it doesn't fail if file isn't regular.
* Try reading.
* https://bugzilla.gnome.org/show_bug.cgi?id=659212 */
- GError *error = NULL;
+ GError *error = nullptr;
gsize l;
if (g_file_get_contents (font_file, &font_data, &l, &error)) {
len = l;
@@ -620,6 +711,9 @@ font_options_t::get_font (void) const
if (font_size_y == FONT_SIZE_UPEM)
font_size_y = hb_face_get_upem (face);
+ hb_font_set_ppem (font, x_ppem, y_ppem);
+ hb_font_set_ptem (font, ptem);
+
int scale_x = (int) scalbnf (font_size_x, subpixel_bits);
int scale_y = (int) scalbnf (font_size_y, subpixel_bits);
hb_font_set_scale (font, scale_x, scale_y);
@@ -627,7 +721,7 @@ font_options_t::get_font (void) const
hb_font_set_variations (font, variations, num_variations);
- void (*set_font_funcs) (hb_font_t *) = NULL;
+ void (*set_font_funcs) (hb_font_t *) = nullptr;
if (!font_funcs)
{
set_font_funcs = supported_font_funcs[0].func;
@@ -642,7 +736,7 @@ font_options_t::get_font (void) const
}
if (!set_font_funcs)
{
- GString *s = g_string_new (NULL);
+ GString *s = g_string_new (nullptr);
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
{
if (i)
@@ -673,7 +767,7 @@ text_options_t::get_line (unsigned int *len)
if (!line_len) {
*len = 0;
- return NULL;
+ return nullptr;
}
const char *ret = line;
@@ -706,9 +800,15 @@ text_options_t::get_line (unsigned int *len)
fail (false, "Failed opening text file `%s': %s",
text_file, strerror (errno));
- gs = g_string_new (NULL);
+ gs = g_string_new (nullptr);
}
+#ifdef HAVE_SETLINEBUF
+ setlinebuf (fp);
+#else
+ setvbuf(fp, NULL, _IOLBF, BUFSIZ);
+#endif
+
g_string_set_size (gs, 0);
char buf[BUFSIZ];
while (fgets (buf, sizeof (buf), fp)) {
@@ -724,7 +824,7 @@ text_options_t::get_line (unsigned int *len)
fail (false, "Failed reading text: %s",
strerror (errno));
*len = gs->len;
- return !*len && feof (fp) ? NULL : gs->str;
+ return !*len && feof (fp) ? nullptr : gs->str;
}
@@ -746,6 +846,12 @@ output_options_t::get_file_handle (void)
fail (false, "Cannot open output file `%s': %s",
g_filename_display_name (output_file), strerror (errno));
+#ifdef HAVE_SETLINEBUF
+ setlinebuf (fp);
+#else
+ setvbuf(fp, NULL, _IOLBF, BUFSIZ);
+#endif
+
return fp;
}
@@ -760,24 +866,41 @@ parse_verbose (const char *name G_GNUC_UNUSED,
return true;
}
+static gboolean
+parse_ned (const char *name G_GNUC_UNUSED,
+ const char *arg G_GNUC_UNUSED,
+ gpointer data G_GNUC_UNUSED,
+ GError **error G_GNUC_UNUSED)
+{
+ format_options_t *format_opts = (format_options_t *) data;
+ format_opts->show_clusters = format_opts->show_advances = false;
+ return true;
+}
+
void
format_options_t::add_options (option_parser_t *parser)
{
GOptionEntry entries[] =
{
- {"show-text", 0, 0, G_OPTION_ARG_NONE, &this->show_text, "Prefix each line of output with its corresponding input text", NULL},
- {"show-unicode", 0, 0, G_OPTION_ARG_NONE, &this->show_unicode, "Prefix each line of output with its corresponding input codepoint(s)", NULL},
- {"show-line-num", 0, 0, G_OPTION_ARG_NONE, &this->show_line_num, "Prefix each line of output with its corresponding input line number", NULL},
- {"verbose", 0, G_OPTION_FLAG_NO_ARG,
- G_OPTION_ARG_CALLBACK, (gpointer) &parse_verbose, "Prefix each line of output with all of the above", NULL},
+ {"show-text", 0, 0, G_OPTION_ARG_NONE, &this->show_text, "Prefix each line of output with its corresponding input text", nullptr},
+ {"show-unicode", 0, 0, G_OPTION_ARG_NONE, &this->show_unicode, "Prefix each line of output with its corresponding input codepoint(s)", nullptr},
+ {"show-line-num", 0, 0, G_OPTION_ARG_NONE, &this->show_line_num, "Prefix each line of output with its corresponding input line number", nullptr},
+ {"verbose", 'v', G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK, (gpointer) &parse_verbose, "Prefix each line of output with all of the above", nullptr},
{"no-glyph-names", 0, G_OPTION_FLAG_REVERSE,
- G_OPTION_ARG_NONE, &this->show_glyph_names, "Output glyph indices instead of names", NULL},
+ G_OPTION_ARG_NONE, &this->show_glyph_names, "Output glyph indices instead of names", nullptr},
{"no-positions", 0, G_OPTION_FLAG_REVERSE,
- G_OPTION_ARG_NONE, &this->show_positions, "Do not output glyph positions", NULL},
+ G_OPTION_ARG_NONE, &this->show_positions, "Do not output glyph positions", nullptr},
+ {"no-advances", 0, G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &this->show_advances, "Do not output glyph advances", nullptr},
{"no-clusters", 0, G_OPTION_FLAG_REVERSE,
- G_OPTION_ARG_NONE, &this->show_clusters, "Do not output cluster indices", NULL},
- {"show-extents", 0, 0, G_OPTION_ARG_NONE, &this->show_extents, "Output glyph extents", NULL},
- {NULL}
+ G_OPTION_ARG_NONE, &this->show_clusters, "Do not output cluster indices", nullptr},
+ {"show-extents", 0, 0, G_OPTION_ARG_NONE, &this->show_extents, "Output glyph extents", nullptr},
+ {"show-flags", 0, 0, G_OPTION_ARG_NONE, &this->show_flags, "Output glyph flags", nullptr},
+ {"ned", 'v', G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK, (gpointer) &parse_ned, "No Extra Data; Do not output clusters or advances", nullptr},
+ {"trace", 'V', 0, G_OPTION_ARG_NONE, &this->trace, "Output interim shaping results", nullptr},
+ {nullptr}
};
parser->add_group (entries,
"output-syntax",
@@ -794,7 +917,7 @@ format_options_t::serialize_unicode (hb_buffer_t *buffer,
GString *gs)
{
unsigned int num_glyphs = hb_buffer_get_length (buffer);
- hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
g_string_append_c (gs, '<');
for (unsigned int i = 0; i < num_glyphs; i++)
@@ -818,7 +941,8 @@ format_options_t::serialize_glyphs (hb_buffer_t *buffer,
unsigned int num_glyphs = hb_buffer_get_length (buffer);
unsigned int start = 0;
- while (start < num_glyphs) {
+ while (start < num_glyphs)
+ {
char buf[1024];
unsigned int consumed;
start += hb_buffer_serialize_glyphs (buffer, start, num_glyphs,
@@ -845,7 +969,8 @@ format_options_t::serialize_buffer_of_text (hb_buffer_t *buffer,
hb_font_t *font,
GString *gs)
{
- if (show_text) {
+ if (show_text)
+ {
serialize_line_no (line_no, gs);
g_string_append_c (gs, '(');
g_string_append_len (gs, text, text_len);
@@ -853,7 +978,8 @@ format_options_t::serialize_buffer_of_text (hb_buffer_t *buffer,
g_string_append_c (gs, '\n');
}
- if (show_unicode) {
+ if (show_unicode)
+ {
serialize_line_no (line_no, gs);
serialize_unicode (buffer, gs);
g_string_append_c (gs, '\n');
@@ -861,11 +987,12 @@ format_options_t::serialize_buffer_of_text (hb_buffer_t *buffer,
}
void
format_options_t::serialize_message (unsigned int line_no,
+ const char *type,
const char *msg,
GString *gs)
{
serialize_line_no (line_no, gs);
- g_string_append_printf (gs, "%s", msg);
+ g_string_append_printf (gs, "%s: %s", type, msg);
g_string_append_c (gs, '\n');
}
void
@@ -882,3 +1009,18 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t *buffer,
serialize_glyphs (buffer, font, output_format, format_flags, gs);
g_string_append_c (gs, '\n');
}
+
+void
+subset_options_t::add_options (option_parser_t *parser)
+{
+ GOptionEntry entries[] =
+ {
+ {"no-hinting", 0, 0, G_OPTION_ARG_NONE, &this->drop_hints, "Whether to drop hints", nullptr},
+ {nullptr}
+ };
+ parser->add_group (entries,
+ "subset",
+ "Subset options:",
+ "Options subsetting",
+ this);
+}
diff --git a/util/options.hh b/util/options.hh
index 9ed4fd0..467350a 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -27,15 +27,13 @@
#ifndef OPTIONS_HH
#define OPTIONS_HH
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "hb-private.hh"
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
+#include <assert.h>
#include <math.h>
#include <locale.h>
#include <errno.h>
@@ -58,35 +56,8 @@
# define g_mapped_file_unref g_mapped_file_free
#endif
-
-/* A few macros copied from hb-private.hh. */
-
-#if __GNUC__ >= 4
-#define HB_UNUSED __attribute__((unused))
-#else
-#define HB_UNUSED
-#endif
-
-#undef MIN
-template <typename Type> static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
-
-#undef MAX
-template <typename Type> static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
-
-#undef ARRAY_LENGTH
-template <typename Type, unsigned int n>
-static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
-/* A const version, but does not detect erratically being called on pointers. */
-#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-
-#define _ASSERT_STATIC1(_line, _cond) HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
-#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
-#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
-
-
void fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN G_GNUC_PRINTF (2, 3);
-
extern hb_bool_t debug;
struct option_group_t
@@ -110,7 +81,7 @@ struct option_parser_t
}
~option_parser_t (void) {
g_option_context_free (context);
- g_ptr_array_foreach (to_free, (GFunc) g_free, NULL);
+ g_ptr_array_foreach (to_free, (GFunc) g_free, nullptr);
g_ptr_array_free (to_free, TRUE);
}
@@ -150,8 +121,8 @@ struct view_options_t : option_group_t
{
view_options_t (option_parser_t *parser) {
annotate = false;
- fore = NULL;
- back = NULL;
+ fore = nullptr;
+ back = nullptr;
line_space = 0;
margin.t = margin.r = margin.b = margin.l = DEFAULT_MARGIN;
@@ -179,14 +150,15 @@ struct shape_options_t : option_group_t
{
shape_options_t (option_parser_t *parser)
{
- direction = language = script = NULL;
- bot = eot = preserve_default_ignorables = false;
- features = NULL;
+ direction = language = script = nullptr;
+ bot = eot = preserve_default_ignorables = remove_default_ignorables = false;
+ features = nullptr;
num_features = 0;
- shapers = NULL;
+ shapers = nullptr;
utf8_clusters = false;
cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
normalize_glyphs = false;
+ verify = false;
num_iterations = 1;
add_options (parser);
@@ -207,14 +179,26 @@ struct shape_options_t : option_group_t
hb_buffer_set_direction (buffer, hb_direction_from_string (direction, -1));
hb_buffer_set_script (buffer, hb_script_from_string (script, -1));
hb_buffer_set_language (buffer, hb_language_from_string (language, -1));
- hb_buffer_set_flags (buffer, (hb_buffer_flags_t) (HB_BUFFER_FLAG_DEFAULT |
- (bot ? HB_BUFFER_FLAG_BOT : 0) |
- (eot ? HB_BUFFER_FLAG_EOT : 0) |
- (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0)));
+ hb_buffer_set_flags (buffer, (hb_buffer_flags_t)
+ (HB_BUFFER_FLAG_DEFAULT |
+ (bot ? HB_BUFFER_FLAG_BOT : 0) |
+ (eot ? HB_BUFFER_FLAG_EOT : 0) |
+ (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) |
+ (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) |
+ 0));
hb_buffer_set_cluster_level (buffer, cluster_level);
hb_buffer_guess_segment_properties (buffer);
}
+ static void copy_buffer_properties (hb_buffer_t *dst, hb_buffer_t *src)
+ {
+ hb_segment_properties_t props;
+ hb_buffer_get_segment_properties (src, &props);
+ hb_buffer_set_segment_properties (dst, &props);
+ hb_buffer_set_flags (dst, hb_buffer_get_flags (src));
+ hb_buffer_set_cluster_level (dst, hb_buffer_get_cluster_level (src));
+ }
+
void populate_buffer (hb_buffer_t *buffer, const char *text, int text_len,
const char *text_before, const char *text_after)
{
@@ -232,7 +216,7 @@ struct shape_options_t : option_group_t
/* Reset cluster values to refer to Unicode character index
* instead of UTF-8 index. */
unsigned int num_glyphs = hb_buffer_get_length (buffer);
- hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
for (unsigned int i = 0; i < num_glyphs; i++)
{
info->cluster = i;
@@ -243,12 +227,188 @@ struct shape_options_t : option_group_t
setup_buffer (buffer);
}
- hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer)
+ hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer, const char **error=nullptr)
{
- hb_bool_t res = hb_shape_full (font, buffer, features, num_features, shapers);
+ hb_buffer_t *text_buffer = nullptr;
+ if (verify)
+ {
+ text_buffer = hb_buffer_create ();
+ hb_buffer_append (text_buffer, buffer, 0, -1);
+ }
+
+ if (!hb_shape_full (font, buffer, features, num_features, shapers))
+ {
+ if (error)
+ *error = "all shapers failed.";
+ goto fail;
+ }
+
if (normalize_glyphs)
hb_buffer_normalize_glyphs (buffer);
- return res;
+
+ if (verify && !verify_buffer (buffer, text_buffer, font, error))
+ goto fail;
+
+ if (text_buffer)
+ hb_buffer_destroy (text_buffer);
+
+ return true;
+
+ fail:
+ if (text_buffer)
+ hb_buffer_destroy (text_buffer);
+
+ return false;
+ }
+
+ bool verify_buffer (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const char **error=nullptr)
+ {
+ if (!verify_buffer_monotone (buffer, error))
+ return false;
+ if (!verify_buffer_safe_to_break (buffer, text_buffer, font, error))
+ return false;
+ return true;
+ }
+
+ bool verify_buffer_monotone (hb_buffer_t *buffer, const char **error=nullptr)
+ {
+ /* Check that clusters are monotone. */
+ if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
+ cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ for (unsigned int i = 1; i < num_glyphs; i++)
+ if (info[i-1].cluster != info[i].cluster &&
+ (info[i-1].cluster < info[i].cluster) != is_forward)
+ {
+ if (error)
+ *error = "clusters are not monotone.";
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool verify_buffer_safe_to_break (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const char **error=nullptr)
+ {
+ if (cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters.
+ * Then again, unsafe-to-break flag is much harder to use without
+ * monotone clusters. */
+ return true;
+ }
+
+ /* Check that breaking up shaping at safe-to-break is indeed safe. */
+
+ hb_buffer_t *fragment = hb_buffer_create ();
+ hb_buffer_t *reconstruction = hb_buffer_create ();
+ copy_buffer_properties (reconstruction, buffer);
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned int num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ /* Chop text and shape fragments. */
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+ unsigned int start = 0;
+ unsigned int text_start = forward ? 0 : num_chars;
+ unsigned int text_end = text_start;
+ for (unsigned int end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK))
+ continue;
+
+ /* Shape segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ {
+ if (forward)
+ text_end = num_chars;
+ else
+ text_start = 0;
+ }
+ else
+ {
+ if (forward)
+ {
+ unsigned int cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ else
+ {
+ unsigned int cluster = info[end - 1].cluster;
+ while (text_start && text[text_start - 1].cluster >= cluster)
+ text_start--;
+ }
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+ hb_buffer_clear_contents (fragment);
+ copy_buffer_properties (fragment, buffer);
+
+ /* TODO: Add pre/post context text. */
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (fragment, flags);
+
+ hb_buffer_append (fragment, text_buffer, text_start, text_end);
+ if (!hb_shape_full (font, fragment, features, num_features, shapers))
+ {
+ if (error)
+ *error = "all shapers failed while shaping fragment.";
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+ return false;
+ }
+ hb_buffer_append (reconstruction, fragment, 0, -1);
+
+ start = end;
+ if (forward)
+ text_start = text_end;
+ else
+ text_end = text_start;
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ if (error)
+ *error = "Safe-to-break test failed.";
+ ret = false;
+
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
+
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+
+ return ret;
}
void shape_closure (const char *text, int text_len,
@@ -270,6 +430,7 @@ struct shape_options_t : option_group_t
hb_bool_t bot;
hb_bool_t eot;
hb_bool_t preserve_default_ignorables;
+ hb_bool_t remove_default_ignorables;
hb_feature_t *features;
unsigned int num_features;
@@ -277,6 +438,7 @@ struct shape_options_t : option_group_t
hb_bool_t utf8_clusters;
hb_buffer_cluster_level_t cluster_level;
hb_bool_t normalize_glyphs;
+ hb_bool_t verify;
unsigned int num_iterations;
};
@@ -287,16 +449,19 @@ struct font_options_t : option_group_t
int default_font_size_,
unsigned int subpixel_bits_)
{
- variations = NULL;
+ variations = nullptr;
num_variations = 0;
default_font_size = default_font_size_;
+ x_ppem = 0;
+ y_ppem = 0;
+ ptem = 0.;
subpixel_bits = subpixel_bits_;
- font_file = NULL;
+ font_file = nullptr;
face_index = 0;
font_size_x = font_size_y = default_font_size;
- font_funcs = NULL;
+ font_funcs = nullptr;
- font = NULL;
+ font = nullptr;
add_options (parser);
}
@@ -316,6 +481,9 @@ struct font_options_t : option_group_t
hb_variation_t *variations;
unsigned int num_variations;
int default_font_size;
+ int x_ppem;
+ int y_ppem;
+ double ptem;
unsigned int subpixel_bits;
mutable double font_size_x;
mutable double font_size_y;
@@ -329,15 +497,15 @@ struct font_options_t : option_group_t
struct text_options_t : option_group_t
{
text_options_t (option_parser_t *parser) {
- text_before = NULL;
- text_after = NULL;
+ text_before = nullptr;
+ text_after = nullptr;
- text = NULL;
- text_file = NULL;
+ text = nullptr;
+ text_file = nullptr;
- fp = NULL;
- gs = NULL;
- line = NULL;
+ fp = nullptr;
+ gs = nullptr;
+ line = nullptr;
line_len = (unsigned int) -1;
add_options (parser);
@@ -380,13 +548,13 @@ struct text_options_t : option_group_t
struct output_options_t : option_group_t
{
output_options_t (option_parser_t *parser,
- const char **supported_formats_ = NULL) {
- output_file = NULL;
- output_format = NULL;
+ const char **supported_formats_ = nullptr) {
+ output_file = nullptr;
+ output_format = nullptr;
supported_formats = supported_formats_;
explicit_output_format = false;
- fp = NULL;
+ fp = nullptr;
add_options (parser);
}
@@ -414,7 +582,7 @@ struct output_options_t : option_group_t
}
if (output_file && 0 == strcmp (output_file, "-"))
- output_file = NULL; /* STDOUT */
+ output_file = nullptr; /* STDOUT */
}
FILE *get_file_handle (void);
@@ -432,11 +600,14 @@ struct format_options_t : option_group_t
format_options_t (option_parser_t *parser) {
show_glyph_names = true;
show_positions = true;
+ show_advances = true;
show_clusters = true;
show_text = false;
show_unicode = false;
show_line_num = false;
show_extents = false;
+ show_flags = false;
+ trace = false;
add_options (parser);
}
@@ -459,6 +630,7 @@ struct format_options_t : option_group_t
hb_font_t *font,
GString *gs);
void serialize_message (unsigned int line_no,
+ const char *type,
const char *msg,
GString *gs);
void serialize_buffer_of_glyphs (hb_buffer_t *buffer,
@@ -473,11 +645,28 @@ struct format_options_t : option_group_t
hb_bool_t show_glyph_names;
hb_bool_t show_positions;
+ hb_bool_t show_advances;
hb_bool_t show_clusters;
hb_bool_t show_text;
hb_bool_t show_unicode;
hb_bool_t show_line_num;
hb_bool_t show_extents;
+ hb_bool_t show_flags;
+ hb_bool_t trace;
+};
+
+struct subset_options_t : option_group_t
+{
+ subset_options_t (option_parser_t *parser)
+ {
+ drop_hints = false;
+
+ add_options (parser);
+ }
+
+ void add_options (option_parser_t *parser);
+
+ hb_bool_t drop_hints;
};
/* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
diff --git a/util/shape-consumer.hh b/util/shape-consumer.hh
index 422c8cd..fa419f1 100644
--- a/util/shape-consumer.hh
+++ b/util/shape-consumer.hh
@@ -24,11 +24,12 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "options.hh"
-
#ifndef HB_SHAPE_CONSUMER_HH
#define HB_SHAPE_CONSUMER_HH
+#include "hb-private.hh"
+#include "options.hh"
+
template <typename output_t>
struct shape_consumer_t
@@ -37,16 +38,19 @@ struct shape_consumer_t
: failed (false),
shaper (parser),
output (parser),
- font (NULL) {}
+ font (nullptr),
+ buffer (nullptr) {}
- void init (const font_options_t *font_opts)
+ void init (hb_buffer_t *buffer_,
+ const font_options_t *font_opts)
{
font = hb_font_reference (font_opts->get_font ());
- output.init (font_opts);
failed = false;
+ buffer = hb_buffer_reference (buffer_);
+
+ output.init (buffer, font_opts);
}
- void consume_line (hb_buffer_t *buffer,
- const char *text,
+ void consume_line (const char *text,
unsigned int text_len,
const char *text_before,
const char *text_after)
@@ -55,14 +59,19 @@ struct shape_consumer_t
for (unsigned int n = shaper.num_iterations; n; n--)
{
+ const char *error = nullptr;
+
shaper.populate_buffer (buffer, text, text_len, text_before, text_after);
if (n == 1)
output.consume_text (buffer, text, text_len, shaper.utf8_clusters);
- if (!shaper.shape (font, buffer)) {
+ if (!shaper.shape (font, buffer, &error))
+ {
failed = true;
- hb_buffer_set_length (buffer, 0);
- output.shape_failed (buffer, text, text_len, shaper.utf8_clusters);
- return;
+ output.error (error);
+ if (hb_buffer_get_content_type (buffer) == HB_BUFFER_CONTENT_TYPE_GLYPHS)
+ break;
+ else
+ return;
}
}
@@ -70,9 +79,11 @@ struct shape_consumer_t
}
void finish (const font_options_t *font_opts)
{
- output.finish (font_opts);
+ output.finish (buffer, font_opts);
hb_font_destroy (font);
- font = NULL;
+ font = nullptr;
+ hb_buffer_destroy (buffer);
+ buffer = nullptr;
}
public:
@@ -83,6 +94,7 @@ struct shape_consumer_t
output_t output;
hb_font_t *font;
+ hb_buffer_t *buffer;
};
diff --git a/util/view-cairo.hh b/util/view-cairo.hh
index f55d4bb..d28c3cd 100644
--- a/util/view-cairo.hh
+++ b/util/view-cairo.hh
@@ -24,12 +24,13 @@
* Google Author(s): Behdad Esfahbod
*/
-#include "options.hh"
-#include "helper-cairo.hh"
-
#ifndef VIEW_CAIRO_HH
#define VIEW_CAIRO_HH
+#include "hb-private.hh"
+#include "options.hh"
+#include "helper-cairo.hh"
+
struct view_cairo_t
{
@@ -43,7 +44,7 @@ struct view_cairo_t
cairo_debug_reset_static_data ();
}
- void init (const font_options_t *font_opts)
+ void init (hb_buffer_t *buffer, const font_options_t *font_opts)
{
lines = g_array_new (false, false, sizeof (helper_cairo_line_t));
scale_bits = -font_opts->subpixel_bits;
@@ -57,12 +58,9 @@ struct view_cairo_t
hb_bool_t utf8_clusters)
{
}
- void shape_failed (hb_buffer_t *buffer,
- const char *text,
- unsigned int text_len,
- hb_bool_t utf8_clusters)
+ void error (const char *message)
{
- fail (false, "all shapers failed");
+ g_printerr ("%s: %s\n", g_get_prgname (), message);
}
void consume_glyphs (hb_buffer_t *buffer,
const char *text,
@@ -74,7 +72,7 @@ struct view_cairo_t
helper_cairo_line_from_buffer (&l, buffer, text, text_len, scale_bits, utf8_clusters);
g_array_append_val (lines, l);
}
- void finish (const font_options_t *font_opts)
+ void finish (hb_buffer_t *buffer, const font_options_t *font_opts)
{
render (font_opts);