Implemented seac for extents & subset along with API tests
This commit is contained in:
parent
41a8bc7fd9
commit
3787c07856
321
gtk-doc.make
321
gtk-doc.make
|
@ -1 +1,320 @@
|
||||||
EXTRA_DIST =
|
# -*- mode: makefile -*-
|
||||||
|
#
|
||||||
|
# gtk-doc.make - make rules for gtk-doc
|
||||||
|
# Copyright (C) 2003 James Henstridge
|
||||||
|
# 2004-2007 Damon Chaplin
|
||||||
|
# 2007-2017 Stefan Sauer
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
####################################
|
||||||
|
# Everything below here is generic #
|
||||||
|
####################################
|
||||||
|
|
||||||
|
if GTK_DOC_USE_LIBTOOL
|
||||||
|
GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
|
||||||
|
GTKDOC_RUN = $(LIBTOOL) --mode=execute
|
||||||
|
else
|
||||||
|
GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
|
||||||
|
GTKDOC_RUN =
|
||||||
|
endif
|
||||||
|
|
||||||
|
# We set GPATH here; this gives us semantics for GNU make
|
||||||
|
# which are more like other make's VPATH, when it comes to
|
||||||
|
# whether a source that is a target of one rule is then
|
||||||
|
# searched for in VPATH/GPATH.
|
||||||
|
#
|
||||||
|
GPATH = $(srcdir)
|
||||||
|
|
||||||
|
TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
|
||||||
|
|
||||||
|
SETUP_FILES = \
|
||||||
|
$(content_files) \
|
||||||
|
$(expand_content_files) \
|
||||||
|
$(DOC_MAIN_SGML_FILE) \
|
||||||
|
$(DOC_MODULE)-sections.txt \
|
||||||
|
$(DOC_MODULE)-overrides.txt
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
$(HTML_IMAGES) \
|
||||||
|
$(SETUP_FILES)
|
||||||
|
|
||||||
|
DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \
|
||||||
|
html-build.stamp pdf-build.stamp \
|
||||||
|
sgml.stamp html.stamp pdf.stamp
|
||||||
|
|
||||||
|
SCANOBJ_FILES = \
|
||||||
|
$(DOC_MODULE).args \
|
||||||
|
$(DOC_MODULE).hierarchy \
|
||||||
|
$(DOC_MODULE).interfaces \
|
||||||
|
$(DOC_MODULE).prerequisites \
|
||||||
|
$(DOC_MODULE).signals
|
||||||
|
|
||||||
|
REPORT_FILES = \
|
||||||
|
$(DOC_MODULE)-undocumented.txt \
|
||||||
|
$(DOC_MODULE)-undeclared.txt \
|
||||||
|
$(DOC_MODULE)-unused.txt
|
||||||
|
|
||||||
|
gtkdoc-check.test: Makefile
|
||||||
|
$(AM_V_GEN)echo "#!/bin/sh -e" > $@; \
|
||||||
|
echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \
|
||||||
|
chmod +x $@
|
||||||
|
|
||||||
|
CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test
|
||||||
|
|
||||||
|
if GTK_DOC_BUILD_HTML
|
||||||
|
HTML_BUILD_STAMP=html-build.stamp
|
||||||
|
else
|
||||||
|
HTML_BUILD_STAMP=
|
||||||
|
endif
|
||||||
|
if GTK_DOC_BUILD_PDF
|
||||||
|
PDF_BUILD_STAMP=pdf-build.stamp
|
||||||
|
else
|
||||||
|
PDF_BUILD_STAMP=
|
||||||
|
endif
|
||||||
|
|
||||||
|
all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
|
||||||
|
.PHONY: all-gtk-doc
|
||||||
|
|
||||||
|
if ENABLE_GTK_DOC
|
||||||
|
all-local: all-gtk-doc
|
||||||
|
endif
|
||||||
|
|
||||||
|
docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
|
||||||
|
|
||||||
|
$(REPORT_FILES): sgml-build.stamp
|
||||||
|
|
||||||
|
#### setup ####
|
||||||
|
|
||||||
|
GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_@AM_V@)
|
||||||
|
GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_SETUP_0=@echo " DOC Preparing build";
|
||||||
|
|
||||||
|
setup-build.stamp:
|
||||||
|
-$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
|
||||||
|
files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \
|
||||||
|
if test "x$$files" != "x" ; then \
|
||||||
|
for file in $$files ; do \
|
||||||
|
destdir=`dirname $(abs_builddir)/$$file`; \
|
||||||
|
test -d "$$destdir" || mkdir -p "$$destdir"; \
|
||||||
|
test -f $(abs_srcdir)/$$file && \
|
||||||
|
cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \
|
||||||
|
done; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
$(AM_V_at)touch setup-build.stamp
|
||||||
|
|
||||||
|
#### scan ####
|
||||||
|
|
||||||
|
GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_@AM_V@)
|
||||||
|
GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files";
|
||||||
|
|
||||||
|
GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_@AM_V@)
|
||||||
|
GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects";
|
||||||
|
|
||||||
|
scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB)
|
||||||
|
$(GTK_DOC_V_SCAN)_source_dir='' ; \
|
||||||
|
for i in $(DOC_SOURCE_DIR) ; do \
|
||||||
|
_source_dir="$${_source_dir} --source-dir=$$i" ; \
|
||||||
|
done ; \
|
||||||
|
gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES)
|
||||||
|
$(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \
|
||||||
|
scanobj_options=""; \
|
||||||
|
gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \
|
||||||
|
if test "$$?" = "0"; then \
|
||||||
|
if test "x$(V)" = "x1"; then \
|
||||||
|
scanobj_options="--verbose"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \
|
||||||
|
gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \
|
||||||
|
else \
|
||||||
|
for i in $(SCANOBJ_FILES) ; do \
|
||||||
|
test -f $$i || touch $$i ; \
|
||||||
|
done \
|
||||||
|
fi
|
||||||
|
$(AM_V_at)touch scan-build.stamp
|
||||||
|
|
||||||
|
$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
|
||||||
|
@true
|
||||||
|
|
||||||
|
#### xml ####
|
||||||
|
|
||||||
|
GTK_DOC_V_XML=$(GTK_DOC_V_XML_@AM_V@)
|
||||||
|
GTK_DOC_V_XML_=$(GTK_DOC_V_XML_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_XML_0=@echo " DOC Building XML";
|
||||||
|
|
||||||
|
sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent
|
||||||
|
$(GTK_DOC_V_XML)_source_dir='' ; \
|
||||||
|
for i in $(DOC_SOURCE_DIR) ; do \
|
||||||
|
_source_dir="$${_source_dir} --source-dir=$$i" ; \
|
||||||
|
done ; \
|
||||||
|
gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS)
|
||||||
|
$(AM_V_at)touch sgml-build.stamp
|
||||||
|
|
||||||
|
sgml.stamp: sgml-build.stamp
|
||||||
|
@true
|
||||||
|
|
||||||
|
$(DOC_MAIN_SGML_FILE): sgml-build.stamp
|
||||||
|
@true
|
||||||
|
|
||||||
|
xml/gtkdocentities.ent: Makefile
|
||||||
|
$(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \
|
||||||
|
echo "<!ENTITY package \"$(PACKAGE)\">"; \
|
||||||
|
echo "<!ENTITY package_bugreport \"$(PACKAGE_BUGREPORT)\">"; \
|
||||||
|
echo "<!ENTITY package_name \"$(PACKAGE_NAME)\">"; \
|
||||||
|
echo "<!ENTITY package_string \"$(PACKAGE_STRING)\">"; \
|
||||||
|
echo "<!ENTITY package_tarname \"$(PACKAGE_TARNAME)\">"; \
|
||||||
|
echo "<!ENTITY package_url \"$(PACKAGE_URL)\">"; \
|
||||||
|
echo "<!ENTITY package_version \"$(PACKAGE_VERSION)\">"; \
|
||||||
|
) > $@
|
||||||
|
|
||||||
|
#### html ####
|
||||||
|
|
||||||
|
GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_@AM_V@)
|
||||||
|
GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_HTML_0=@echo " DOC Building HTML";
|
||||||
|
|
||||||
|
GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_@AM_V@)
|
||||||
|
GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references";
|
||||||
|
|
||||||
|
html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
|
||||||
|
$(GTK_DOC_V_HTML)rm -rf html && mkdir html && \
|
||||||
|
mkhtml_options=""; \
|
||||||
|
gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \
|
||||||
|
if test "$$?" = "0"; then \
|
||||||
|
if test "x$(V)" = "x1"; then \
|
||||||
|
mkhtml_options="$$mkhtml_options --verbose"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \
|
||||||
|
if test "$$?" = "0"; then \
|
||||||
|
mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \
|
||||||
|
fi; \
|
||||||
|
cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
|
||||||
|
-@test "x$(HTML_IMAGES)" = "x" || \
|
||||||
|
for file in $(HTML_IMAGES) ; do \
|
||||||
|
test -f $(abs_srcdir)/$$file && cp $(abs_srcdir)/$$file $(abs_builddir)/html; \
|
||||||
|
test -f $(abs_builddir)/$$file && cp $(abs_builddir)/$$file $(abs_builddir)/html; \
|
||||||
|
done;
|
||||||
|
$(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
|
||||||
|
$(AM_V_at)touch html-build.stamp
|
||||||
|
|
||||||
|
#### pdf ####
|
||||||
|
|
||||||
|
GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_@AM_V@)
|
||||||
|
GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_@AM_DEFAULT_V@)
|
||||||
|
GTK_DOC_V_PDF_0=@echo " DOC Building PDF";
|
||||||
|
|
||||||
|
pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
|
||||||
|
$(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \
|
||||||
|
mkpdf_options=""; \
|
||||||
|
gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \
|
||||||
|
if test "$$?" = "0"; then \
|
||||||
|
if test "x$(V)" = "x1"; then \
|
||||||
|
mkpdf_options="$$mkpdf_options --verbose"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
if test "x$(HTML_IMAGES)" != "x"; then \
|
||||||
|
for img in $(HTML_IMAGES); do \
|
||||||
|
part=`dirname $$img`; \
|
||||||
|
echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \
|
||||||
|
if test $$? != 0; then \
|
||||||
|
mkpdf_options="$$mkpdf_options --imgdir=$$part"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
fi; \
|
||||||
|
gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS)
|
||||||
|
$(AM_V_at)touch pdf-build.stamp
|
||||||
|
|
||||||
|
##############
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
@rm -f *~ *.bak
|
||||||
|
@rm -rf .libs
|
||||||
|
@if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \
|
||||||
|
rm -f $(DOC_MODULE).types; \
|
||||||
|
fi
|
||||||
|
@if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \
|
||||||
|
rm -f $(DOC_MODULE)-sections.txt; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
distclean-local:
|
||||||
|
@rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \
|
||||||
|
$(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
|
||||||
|
@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
|
||||||
|
rm -f $(SETUP_FILES) $(DOC_MODULE).types; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
maintainer-clean-local:
|
||||||
|
@rm -rf xml html
|
||||||
|
|
||||||
|
install-data-local:
|
||||||
|
@installfiles=`echo $(builddir)/html/*`; \
|
||||||
|
if test "$$installfiles" = '$(builddir)/html/*'; \
|
||||||
|
then echo 1>&2 'Nothing to install' ; \
|
||||||
|
else \
|
||||||
|
if test -n "$(DOC_MODULE_VERSION)"; then \
|
||||||
|
installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
|
||||||
|
else \
|
||||||
|
installdir="$(DESTDIR)$(TARGET_DIR)"; \
|
||||||
|
fi; \
|
||||||
|
$(mkinstalldirs) $${installdir} ; \
|
||||||
|
for i in $$installfiles; do \
|
||||||
|
echo ' $(INSTALL_DATA) '$$i ; \
|
||||||
|
$(INSTALL_DATA) $$i $${installdir}; \
|
||||||
|
done; \
|
||||||
|
if test -n "$(DOC_MODULE_VERSION)"; then \
|
||||||
|
mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
|
||||||
|
$${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
|
||||||
|
fi; \
|
||||||
|
$(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
uninstall-local:
|
||||||
|
@if test -n "$(DOC_MODULE_VERSION)"; then \
|
||||||
|
installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
|
||||||
|
else \
|
||||||
|
installdir="$(DESTDIR)$(TARGET_DIR)"; \
|
||||||
|
fi; \
|
||||||
|
rm -rf $${installdir}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Require gtk-doc when making dist
|
||||||
|
#
|
||||||
|
if HAVE_GTK_DOC
|
||||||
|
dist-check-gtkdoc: docs
|
||||||
|
else
|
||||||
|
dist-check-gtkdoc:
|
||||||
|
@echo "*** gtk-doc is needed to run 'make dist'. ***"
|
||||||
|
@echo "*** gtk-doc was not found when 'configure' ran. ***"
|
||||||
|
@echo "*** please install gtk-doc and rerun 'configure'. ***"
|
||||||
|
@false
|
||||||
|
endif
|
||||||
|
|
||||||
|
dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local
|
||||||
|
@mkdir $(distdir)/html
|
||||||
|
@cp ./html/* $(distdir)/html
|
||||||
|
@-cp ./$(DOC_MODULE).pdf $(distdir)/
|
||||||
|
@-cp ./$(DOC_MODULE).types $(distdir)/
|
||||||
|
@-cp ./$(DOC_MODULE)-sections.txt $(distdir)/
|
||||||
|
@cd $(distdir) && rm -f $(DISTCLEANFILES)
|
||||||
|
@$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html
|
||||||
|
|
||||||
|
.PHONY : dist-hook-local docs
|
||||||
|
|
|
@ -169,7 +169,7 @@ inline unsigned int OpCode_Size (OpCode op) { return Is_OpCode_ESC (op)? 2: 1; }
|
||||||
#define OpCode_fixedcs 255 /* 32-bit fixed */
|
#define OpCode_fixedcs 255 /* 32-bit fixed */
|
||||||
|
|
||||||
/* Two byte escape operators 12, (0-41) */
|
/* Two byte escape operators 12, (0-41) */
|
||||||
#define OpCode_ReservedESC0 Make_OpCode_ESC(0)
|
#define OpCode_dotsection Make_OpCode_ESC(0) /* CFF (obsoleted) */
|
||||||
#define OpCode_ReservedESC1 Make_OpCode_ESC(1)
|
#define OpCode_ReservedESC1 Make_OpCode_ESC(1)
|
||||||
#define OpCode_ReservedESC2 Make_OpCode_ESC(2)
|
#define OpCode_ReservedESC2 Make_OpCode_ESC(2)
|
||||||
#define OpCode_and Make_OpCode_ESC(3) /* CFF */
|
#define OpCode_and Make_OpCode_ESC(3) /* CFF */
|
||||||
|
|
|
@ -88,9 +88,16 @@ struct Point
|
||||||
y.init ();
|
y.init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void set_int (int _x, int _y)
|
||||||
|
{
|
||||||
|
x.set_int (_x);
|
||||||
|
y.set_int (_y);
|
||||||
|
}
|
||||||
|
|
||||||
inline void move_x (const Number &dx) { x += dx; }
|
inline void move_x (const Number &dx) { x += dx; }
|
||||||
inline void move_y (const Number &dy) { y += dy; }
|
inline void move_y (const Number &dy) { y += dy; }
|
||||||
inline void move (const Number &dx, const Number &dy) { move_x (dx); move_y (dy); }
|
inline void move (const Number &dx, const Number &dy) { move_x (dx); move_y (dy); }
|
||||||
|
inline void move (const Point &d) { move_x (d.x); move_y (d.y); }
|
||||||
|
|
||||||
Number x;
|
Number x;
|
||||||
Number y;
|
Number y;
|
||||||
|
|
|
@ -84,6 +84,29 @@ template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF1CSInte
|
||||||
struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
|
struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
|
||||||
{
|
{
|
||||||
/* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
|
/* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
|
||||||
|
/* Type 1-originated deprecated opcodes, seac behavior of endchar and dotsection are supported */
|
||||||
|
|
||||||
|
static inline void process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case OpCode_dotsection:
|
||||||
|
SUPER::flush_args_and_op (op, env, param);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OpCode_endchar:
|
||||||
|
OPSET::check_width (op, env, param);
|
||||||
|
if (env.argStack.get_count () >= 4)
|
||||||
|
{
|
||||||
|
OPSET::process_seac (env, param);
|
||||||
|
}
|
||||||
|
OPSET::flush_args_and_op (op, env, param);
|
||||||
|
env.set_endchar (true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SUPER::process_op (op, env, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void check_width (OpCode op, CFF1CSInterpEnv &env, PARAM& param)
|
static inline void check_width (OpCode op, CFF1CSInterpEnv &env, PARAM& param)
|
||||||
{
|
{
|
||||||
|
@ -93,8 +116,6 @@ struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OpCode_endchar:
|
case OpCode_endchar:
|
||||||
has_width = (env.argStack.get_count () > 0);
|
|
||||||
break;
|
|
||||||
case OpCode_hstem:
|
case OpCode_hstem:
|
||||||
case OpCode_hstemhm:
|
case OpCode_hstemhm:
|
||||||
case OpCode_vstem:
|
case OpCode_vstem:
|
||||||
|
@ -117,6 +138,10 @@ struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void process_seac (CFF1CSInterpEnv &env, PARAM& param)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void flush_args (CFF1CSInterpEnv &env, PARAM& param)
|
static inline void flush_args (CFF1CSInterpEnv &env, PARAM& param)
|
||||||
{
|
{
|
||||||
SUPER::flush_args (env, param);
|
SUPER::flush_args (env, param);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
using namespace CFF;
|
using namespace CFF;
|
||||||
|
|
||||||
/* SID to code */
|
/* SID to code */
|
||||||
static const uint8_t standard_encoding [] =
|
static const uint8_t standard_encoding_to_code [] =
|
||||||
{
|
{
|
||||||
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
||||||
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
|
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
|
||||||
|
@ -45,7 +45,7 @@ static const uint8_t standard_encoding [] =
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SID to code */
|
/* SID to code */
|
||||||
static const uint8_t expert_encoding [] =
|
static const uint8_t expert_encoding_to_code [] =
|
||||||
{
|
{
|
||||||
0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 46,
|
0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 46,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 0, 0, 0,
|
||||||
|
@ -74,7 +74,7 @@ static const uint8_t expert_encoding [] =
|
||||||
};
|
};
|
||||||
|
|
||||||
/* glyph ID to SID */
|
/* glyph ID to SID */
|
||||||
static const uint16_t expert_charset [] =
|
static const uint16_t expert_charset_to_sid [] =
|
||||||
{
|
{
|
||||||
0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99,
|
0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99,
|
||||||
239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252,
|
239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252,
|
||||||
|
@ -90,7 +90,7 @@ static const uint16_t expert_charset [] =
|
||||||
};
|
};
|
||||||
|
|
||||||
/* glyph ID to SID */
|
/* glyph ID to SID */
|
||||||
static const uint16_t expert_subset_charset [] =
|
static const uint16_t expert_subset_charset_to_sid [] =
|
||||||
{
|
{
|
||||||
0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
|
0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
|
||||||
243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257,
|
243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257,
|
||||||
|
@ -100,66 +100,131 @@ static const uint16_t expert_subset_charset [] =
|
||||||
340, 341, 342, 343, 344, 345, 346
|
340, 341, 342, 343, 344, 345, 346
|
||||||
};
|
};
|
||||||
|
|
||||||
hb_codepoint_t OT::cff1::lookup_standard_encoding (hb_codepoint_t sid)
|
/* code to SID */
|
||||||
|
static const uint8_t standard_encoding_to_sid [] =
|
||||||
{
|
{
|
||||||
if (sid < ARRAY_LENGTH (standard_encoding))
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
return (hb_codepoint_t)standard_encoding[sid];
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||||
|
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||||
|
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||||
|
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
|
||||||
|
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
||||||
|
0, 111, 112, 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123,
|
||||||
|
0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136,
|
||||||
|
137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0, 0, 0, 0,
|
||||||
|
0, 144, 0, 0, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
|
||||||
|
{
|
||||||
|
if (sid < ARRAY_LENGTH (standard_encoding_to_code))
|
||||||
|
return (hb_codepoint_t)standard_encoding_to_code[sid];
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_codepoint_t OT::cff1::lookup_expert_encoding (hb_codepoint_t sid)
|
hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
|
||||||
{
|
{
|
||||||
if (sid < ARRAY_LENGTH (expert_encoding))
|
if (sid < ARRAY_LENGTH (expert_encoding_to_code))
|
||||||
return (hb_codepoint_t)expert_encoding[sid];
|
return (hb_codepoint_t)expert_encoding_to_code[sid];
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_codepoint_t OT::cff1::lookup_expert_charset (hb_codepoint_t glyph)
|
hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
|
||||||
{
|
{
|
||||||
if (glyph < ARRAY_LENGTH (expert_charset))
|
if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
|
||||||
return (hb_codepoint_t)expert_charset[glyph];
|
return (hb_codepoint_t)expert_charset_to_sid[glyph];
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_codepoint_t OT::cff1::lookup_expert_subset_charset (hb_codepoint_t glyph)
|
hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
|
||||||
{
|
{
|
||||||
if (glyph < ARRAY_LENGTH (expert_subset_charset))
|
if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
|
||||||
return (hb_codepoint_t)expert_subset_charset[glyph];
|
return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExtentsParam
|
hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
|
||||||
|
{
|
||||||
|
if (code < ARRAY_LENGTH (standard_encoding_to_sid))
|
||||||
|
return (hb_codepoint_t)standard_encoding_to_sid[code];
|
||||||
|
else
|
||||||
|
return CFF_UNDEF_SID;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bounds
|
||||||
{
|
{
|
||||||
inline void init (void)
|
inline void init (void)
|
||||||
|
{
|
||||||
|
min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
|
||||||
|
max.set_int (-0x80000000, -0x80000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update (const Point &pt)
|
||||||
|
{
|
||||||
|
if (pt.x < min.x) min.x = pt.x;
|
||||||
|
if (pt.x > max.x) max.x = pt.x;
|
||||||
|
if (pt.y < min.y) min.y = pt.y;
|
||||||
|
if (pt.y > max.y) max.y = pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void merge (const Bounds &b)
|
||||||
|
{
|
||||||
|
if (empty ())
|
||||||
|
*this = b;
|
||||||
|
else if (!b.empty ())
|
||||||
|
{
|
||||||
|
if (b.min.x < min.x) min.x = b.min.x;
|
||||||
|
if (b.max.x > max.x) max.x = b.max.x;
|
||||||
|
if (b.min.y < min.y) min.y = b.min.y;
|
||||||
|
if (b.max.y > max.y) max.y = b.max.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void offset (const Point &delta)
|
||||||
|
{
|
||||||
|
if (!empty ())
|
||||||
|
{
|
||||||
|
min.move (delta);
|
||||||
|
max.move (delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool empty (void) const
|
||||||
|
{
|
||||||
|
return (min.x >= max.x) || (min.y >= max.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point min;
|
||||||
|
Point max;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExtentsParam
|
||||||
|
{
|
||||||
|
inline void init (const OT::cff1::accelerator_t *_cff)
|
||||||
{
|
{
|
||||||
path_open = false;
|
path_open = false;
|
||||||
min_x.set_int (0x7FFFFFFF);
|
cff = _cff;
|
||||||
min_y.set_int (0x7FFFFFFF);
|
bounds.init ();
|
||||||
max_x.set_int (-0x80000000);
|
|
||||||
max_y.set_int (-0x80000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void start_path (void) { path_open = true; }
|
inline void start_path (void) { path_open = true; }
|
||||||
inline void end_path (void) { path_open = false; }
|
inline void end_path (void) { path_open = false; }
|
||||||
inline bool is_path_open (void) const { return path_open; }
|
inline bool is_path_open (void) const { return path_open; }
|
||||||
|
|
||||||
inline void update_bounds (const Point &pt)
|
bool path_open;
|
||||||
{
|
Bounds bounds;
|
||||||
if (pt.x < min_x) min_x = pt.x;
|
|
||||||
if (pt.x > max_x) max_x = pt.x;
|
|
||||||
if (pt.y < min_y) min_y = pt.y;
|
|
||||||
if (pt.y > max_y) max_y = pt.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool path_open;
|
const OT::cff1::accelerator_t *cff;
|
||||||
Number min_x;
|
|
||||||
Number min_y;
|
|
||||||
Number max_x;
|
|
||||||
Number max_y;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CFF1PathProcs_Extents : PathProcs<CFF1PathProcs_Extents, CFF1CSInterpEnv, ExtentsParam>
|
struct CFF1PathProcs_Extents : PathProcs<CFF1PathProcs_Extents, CFF1CSInterpEnv, ExtentsParam>
|
||||||
|
@ -175,10 +240,10 @@ struct CFF1PathProcs_Extents : PathProcs<CFF1PathProcs_Extents, CFF1CSInterpEnv,
|
||||||
if (!param.is_path_open ())
|
if (!param.is_path_open ())
|
||||||
{
|
{
|
||||||
param.start_path ();
|
param.start_path ();
|
||||||
param.update_bounds (env.get_pt ());
|
param.bounds.update (env.get_pt ());
|
||||||
}
|
}
|
||||||
env.moveto (pt1);
|
env.moveto (pt1);
|
||||||
param.update_bounds (env.get_pt ());
|
param.bounds.update (env.get_pt ());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void curve (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1, const Point &pt2, const Point &pt3)
|
static inline void curve (CFF1CSInterpEnv &env, ExtentsParam& param, const Point &pt1, const Point &pt2, const Point &pt3)
|
||||||
|
@ -186,50 +251,137 @@ struct CFF1PathProcs_Extents : PathProcs<CFF1PathProcs_Extents, CFF1CSInterpEnv,
|
||||||
if (!param.is_path_open ())
|
if (!param.is_path_open ())
|
||||||
{
|
{
|
||||||
param.start_path ();
|
param.start_path ();
|
||||||
param.update_bounds (env.get_pt ());
|
param.bounds.update (env.get_pt ());
|
||||||
}
|
}
|
||||||
/* include control points */
|
/* include control points */
|
||||||
param.update_bounds (pt1);
|
param.bounds.update (pt1);
|
||||||
param.update_bounds (pt2);
|
param.bounds.update (pt2);
|
||||||
env.moveto (pt3);
|
env.moveto (pt3);
|
||||||
param.update_bounds (env.get_pt ());
|
param.bounds.update (env.get_pt ());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CFF1CSOpSet_Extents : CFF1CSOpSet<CFF1CSOpSet_Extents, ExtentsParam, CFF1PathProcs_Extents> {};
|
static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, Bounds &bounds);
|
||||||
|
|
||||||
|
struct CFF1CSOpSet_Extents : CFF1CSOpSet<CFF1CSOpSet_Extents, ExtentsParam, CFF1PathProcs_Extents>
|
||||||
|
{
|
||||||
|
static inline void process_seac (CFF1CSInterpEnv &env, ExtentsParam& param)
|
||||||
|
{
|
||||||
|
unsigned int n = env.argStack.get_count ();
|
||||||
|
Point delta;
|
||||||
|
delta.x = env.argStack[n-4];
|
||||||
|
delta.y = env.argStack[n-3];
|
||||||
|
hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
|
||||||
|
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
|
||||||
|
|
||||||
|
Bounds base_bounds, accent_bounds;
|
||||||
|
if (likely (base && accent
|
||||||
|
&& _get_bounds (param.cff, base, base_bounds)
|
||||||
|
&& _get_bounds (param.cff, accent, accent_bounds)))
|
||||||
|
{
|
||||||
|
param.bounds.merge (base_bounds);
|
||||||
|
accent_bounds.offset (delta);
|
||||||
|
param.bounds.merge (accent_bounds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
env.set_error ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, Bounds &bounds)
|
||||||
|
{
|
||||||
|
bounds.init ();
|
||||||
|
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
|
||||||
|
|
||||||
|
unsigned int fd = cff->fdSelect->get_fd (glyph);
|
||||||
|
CFF1CSInterpreter<CFF1CSOpSet_Extents, ExtentsParam> interp;
|
||||||
|
const ByteStr str = (*cff->charStrings)[glyph];
|
||||||
|
interp.env.init (str, *cff, fd);
|
||||||
|
ExtentsParam param;
|
||||||
|
param.init (cff);
|
||||||
|
if (unlikely (!interp.interpret (param))) return false;
|
||||||
|
bounds = param.bounds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
||||||
{
|
{
|
||||||
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
|
Bounds bounds;
|
||||||
|
|
||||||
unsigned int fd = fdSelect->get_fd (glyph);
|
if (!_get_bounds (this, glyph, bounds))
|
||||||
CFF1CSInterpreter<CFF1CSOpSet_Extents, ExtentsParam> interp;
|
return false;
|
||||||
const ByteStr str = (*charStrings)[glyph];
|
|
||||||
interp.env.init (str, *this, fd);
|
|
||||||
ExtentsParam param;
|
|
||||||
param.init ();
|
|
||||||
if (unlikely (!interp.interpret (param))) return false;
|
|
||||||
|
|
||||||
if (param.min_x >= param.max_x)
|
if (bounds.min.x >= bounds.max.x)
|
||||||
{
|
{
|
||||||
extents->width = 0;
|
extents->width = 0;
|
||||||
extents->x_bearing = 0;
|
extents->x_bearing = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extents->x_bearing = (int32_t)param.min_x.floor ();
|
extents->x_bearing = (int32_t)bounds.min.x.floor ();
|
||||||
extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing;
|
extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
|
||||||
}
|
}
|
||||||
if (param.min_y >= param.max_y)
|
if (bounds.min.y >= bounds.max.y)
|
||||||
{
|
{
|
||||||
extents->height = 0;
|
extents->height = 0;
|
||||||
extents->y_bearing = 0;
|
extents->y_bearing = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extents->y_bearing = (int32_t)param.max_y.ceil ();
|
extents->y_bearing = (int32_t)bounds.max.y.ceil ();
|
||||||
extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
|
extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GetSeacParam
|
||||||
|
{
|
||||||
|
inline void init (const OT::cff1::accelerator_t *_cff)
|
||||||
|
{
|
||||||
|
cff = _cff;
|
||||||
|
base = 0;
|
||||||
|
accent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool has_seac (void) const
|
||||||
|
{ return base && accent; }
|
||||||
|
|
||||||
|
const OT::cff1::accelerator_t *cff;
|
||||||
|
hb_codepoint_t base;
|
||||||
|
hb_codepoint_t accent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CFF1CSOpSet_Seac : CFF1CSOpSet<CFF1CSOpSet_Seac, GetSeacParam>
|
||||||
|
{
|
||||||
|
static inline void process_seac (CFF1CSInterpEnv &env, GetSeacParam& param)
|
||||||
|
{
|
||||||
|
unsigned int n = env.argStack.get_count ();
|
||||||
|
hb_codepoint_t base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
|
||||||
|
hb_codepoint_t accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
|
||||||
|
|
||||||
|
param.base = param.cff->std_code_to_glyph (base_char);
|
||||||
|
param.accent = param.cff->std_code_to_glyph (accent_char);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
|
||||||
|
{
|
||||||
|
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
|
||||||
|
|
||||||
|
unsigned int fd = fdSelect->get_fd (glyph);
|
||||||
|
CFF1CSInterpreter<CFF1CSOpSet_Seac, GetSeacParam> interp;
|
||||||
|
const ByteStr str = (*charStrings)[glyph];
|
||||||
|
interp.env.init (str, *this, fd);
|
||||||
|
GetSeacParam param;
|
||||||
|
param.init (this);
|
||||||
|
if (unlikely (!interp.interpret (param))) return false;
|
||||||
|
|
||||||
|
if (param.has_seac ())
|
||||||
|
{
|
||||||
|
*base = param.base;
|
||||||
|
*accent = param.accent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -323,6 +323,19 @@ struct Charset0 {
|
||||||
return sids[glyph - 1];
|
return sids[glyph - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
|
||||||
|
{
|
||||||
|
if (sid == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
|
||||||
|
{
|
||||||
|
if (sids[glyph-1] == sid)
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (unsigned int num_glyphs) const
|
inline unsigned int get_size (unsigned int num_glyphs) const
|
||||||
{
|
{
|
||||||
assert (num_glyphs > 0);
|
assert (num_glyphs > 0);
|
||||||
|
@ -379,6 +392,20 @@ struct Charset1_2 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline hb_codepoint_t get_glyph (hb_codepoint_t sid) const
|
||||||
|
{
|
||||||
|
if (sid == 0) return 0;
|
||||||
|
hb_codepoint_t glyph = 1;
|
||||||
|
for (unsigned int i = 0;; i++)
|
||||||
|
{
|
||||||
|
if ((ranges[i].first <= sid) && sid <= ranges[i].first + ranges[i].nLeft)
|
||||||
|
return glyph + (sid - ranges[i].first);
|
||||||
|
glyph += (ranges[i].nLeft + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int get_size (unsigned int num_glyphs) const
|
inline unsigned int get_size (unsigned int num_glyphs) const
|
||||||
{
|
{
|
||||||
unsigned int size = HBUINT8::static_size;
|
unsigned int size = HBUINT8::static_size;
|
||||||
|
@ -518,6 +545,16 @@ struct Charset {
|
||||||
return u.format2.get_sid (glyph);
|
return u.format2.get_sid (glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
|
||||||
|
{
|
||||||
|
if (format == 0)
|
||||||
|
return u.format0.get_glyph (sid, num_glyphs);
|
||||||
|
else if (format == 1)
|
||||||
|
return u.format1.get_glyph (sid);
|
||||||
|
else
|
||||||
|
return u.format2.get_glyph (sid);
|
||||||
|
}
|
||||||
|
|
||||||
HBUINT8 format;
|
HBUINT8 format;
|
||||||
union {
|
union {
|
||||||
Charset0 format0;
|
Charset0 format0;
|
||||||
|
@ -997,6 +1034,14 @@ struct cff1
|
||||||
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
|
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_predef_charset ())
|
||||||
|
charset = &Null(Charset);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
|
||||||
|
if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
|
||||||
|
}
|
||||||
|
|
||||||
fdCount = 1;
|
fdCount = 1;
|
||||||
if (is_CID ())
|
if (is_CID ())
|
||||||
{
|
{
|
||||||
|
@ -1094,11 +1139,27 @@ struct cff1
|
||||||
inline bool is_valid (void) const { return blob != nullptr; }
|
inline bool is_valid (void) const { return blob != nullptr; }
|
||||||
inline bool is_CID (void) const { return topDict.is_CID (); }
|
inline bool is_CID (void) const { return topDict.is_CID (); }
|
||||||
|
|
||||||
|
inline bool is_predef_charset (void) const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
|
||||||
|
|
||||||
|
inline unsigned int std_code_to_glyph (hb_codepoint_t code) const
|
||||||
|
{
|
||||||
|
hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
|
||||||
|
if (unlikely (sid == CFF_UNDEF_SID))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (charset != &Null(Charset))
|
||||||
|
return charset->get_glyph (sid, num_glyphs);
|
||||||
|
else if ((topDict.CharsetOffset == ISOAdobeCharset)
|
||||||
|
&& (code <= 228 /*zcaron*/)) return sid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
hb_blob_t *blob;
|
hb_blob_t *blob;
|
||||||
hb_sanitize_context_t sc;
|
hb_sanitize_context_t sc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
const Charset *charset;
|
||||||
const CFF1NameIndex *nameIndex;
|
const CFF1NameIndex *nameIndex;
|
||||||
const CFF1TopDictIndex *topDictIndex;
|
const CFF1TopDictIndex *topDictIndex;
|
||||||
const CFF1StringIndex *stringIndex;
|
const CFF1StringIndex *stringIndex;
|
||||||
|
@ -1118,6 +1179,7 @@ struct cff1
|
||||||
struct accelerator_t : accelerator_templ_t<CFF1PrivateDictOpSet, CFF1PrivateDictValues>
|
struct accelerator_t : accelerator_templ_t<CFF1PrivateDictOpSet, CFF1PrivateDictValues>
|
||||||
{
|
{
|
||||||
HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
|
HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
|
||||||
|
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct accelerator_subset_t : accelerator_templ_t<CFF1PrivateDictOpSet_Subset, CFF1PrivateDictValues_Subset>
|
struct accelerator_subset_t : accelerator_templ_t<CFF1PrivateDictOpSet_Subset, CFF1PrivateDictValues_Subset>
|
||||||
|
@ -1129,13 +1191,6 @@ struct cff1
|
||||||
|
|
||||||
const OT::cff1 *cff = this->blob->as<OT::cff1> ();
|
const OT::cff1 *cff = this->blob->as<OT::cff1> ();
|
||||||
encoding = &Null(Encoding);
|
encoding = &Null(Encoding);
|
||||||
if (is_predef_charset ())
|
|
||||||
charset = &Null(Charset);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
|
|
||||||
if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
|
|
||||||
}
|
|
||||||
if (is_CID ())
|
if (is_CID ())
|
||||||
{
|
{
|
||||||
if (unlikely (charset == &Null(Charset))) { fini (); return; }
|
if (unlikely (charset == &Null(Charset))) { fini (); return; }
|
||||||
|
@ -1151,7 +1206,6 @@ struct cff1
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_predef_encoding (void) const { return topDict.EncodingOffset <= ExpertEncoding; }
|
inline bool is_predef_encoding (void) const { return topDict.EncodingOffset <= ExpertEncoding; }
|
||||||
inline bool is_predef_charset (void) const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
|
|
||||||
|
|
||||||
inline hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
|
inline hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
|
@ -1165,10 +1219,10 @@ struct cff1
|
||||||
switch (topDict.EncodingOffset)
|
switch (topDict.EncodingOffset)
|
||||||
{
|
{
|
||||||
case StandardEncoding:
|
case StandardEncoding:
|
||||||
code = lookup_standard_encoding (sid);
|
code = lookup_standard_encoding_for_code (sid);
|
||||||
break;
|
break;
|
||||||
case ExpertEncoding:
|
case ExpertEncoding:
|
||||||
code = lookup_expert_encoding (sid);
|
code = lookup_expert_encoding_for_code (sid);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1190,10 +1244,10 @@ struct cff1
|
||||||
if (glyph <= 228 /*zcaron*/) sid = glyph;
|
if (glyph <= 228 /*zcaron*/) sid = glyph;
|
||||||
break;
|
break;
|
||||||
case ExpertCharset:
|
case ExpertCharset:
|
||||||
sid = lookup_expert_charset (glyph);
|
sid = lookup_expert_charset_for_sid (glyph);
|
||||||
break;
|
break;
|
||||||
case ExpertSubsetCharset:
|
case ExpertSubsetCharset:
|
||||||
sid = lookup_expert_subset_charset (glyph);
|
sid = lookup_expert_subset_charset_for_sid (glyph);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1203,7 +1257,6 @@ struct cff1
|
||||||
}
|
}
|
||||||
|
|
||||||
const Encoding *encoding;
|
const Encoding *encoding;
|
||||||
const Charset *charset;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef accelerator_templ_t<CFF1PrivateDictOpSet_Subset, CFF1PrivateDictValues_Subset> SUPER;
|
typedef accelerator_templ_t<CFF1PrivateDictOpSet_Subset, CFF1PrivateDictValues_Subset> SUPER;
|
||||||
|
@ -1228,10 +1281,11 @@ struct cff1
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding (hb_codepoint_t sid);
|
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
|
||||||
HB_INTERNAL static hb_codepoint_t lookup_expert_encoding (hb_codepoint_t sid);
|
HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
|
||||||
HB_INTERNAL static hb_codepoint_t lookup_expert_charset (hb_codepoint_t glyph);
|
HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
|
||||||
HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset (hb_codepoint_t glyph);
|
HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
|
||||||
|
HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
|
FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "hb-ot-cmap-table.hh"
|
#include "hb-ot-cmap-table.hh"
|
||||||
#include "hb-ot-glyf-table.hh"
|
#include "hb-ot-glyf-table.hh"
|
||||||
|
#include "hb-ot-cff1-table.hh"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
||||||
|
@ -52,6 +53,19 @@ _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
|
||||||
|
hb_codepoint_t gid,
|
||||||
|
hb_set_t *gids_to_retain)
|
||||||
|
{
|
||||||
|
hb_codepoint_t base_gid, accent_gid;
|
||||||
|
if (cff.get_seac_components (gid, &base_gid, &accent_gid))
|
||||||
|
{
|
||||||
|
hb_set_add (gids_to_retain, base_gid);
|
||||||
|
hb_set_add (gids_to_retain, accent_gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
|
_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
|
||||||
{
|
{
|
||||||
|
@ -78,8 +92,10 @@ _populate_gids_to_retain (hb_face_t *face,
|
||||||
{
|
{
|
||||||
OT::cmap::accelerator_t cmap;
|
OT::cmap::accelerator_t cmap;
|
||||||
OT::glyf::accelerator_t glyf;
|
OT::glyf::accelerator_t glyf;
|
||||||
|
OT::cff1::accelerator_t cff;
|
||||||
cmap.init (face);
|
cmap.init (face);
|
||||||
glyf.init (face);
|
glyf.init (face);
|
||||||
|
cff.init (face);
|
||||||
|
|
||||||
hb_set_t *initial_gids_to_retain = hb_set_create ();
|
hb_set_t *initial_gids_to_retain = hb_set_create ();
|
||||||
initial_gids_to_retain->add (0); // Not-def
|
initial_gids_to_retain->add (0); // Not-def
|
||||||
|
@ -109,6 +125,8 @@ _populate_gids_to_retain (hb_face_t *face,
|
||||||
while (initial_gids_to_retain->next (&gid))
|
while (initial_gids_to_retain->next (&gid))
|
||||||
{
|
{
|
||||||
_add_gid_and_children (glyf, gid, all_gids_to_retain);
|
_add_gid_and_children (glyf, gid, all_gids_to_retain);
|
||||||
|
if (cff.is_valid ())
|
||||||
|
_add_cff_seac_components (cff, gid, all_gids_to_retain);
|
||||||
}
|
}
|
||||||
hb_set_destroy (initial_gids_to_retain);
|
hb_set_destroy (initial_gids_to_retain);
|
||||||
|
|
||||||
|
@ -117,6 +135,7 @@ _populate_gids_to_retain (hb_face_t *face,
|
||||||
while (all_gids_to_retain->next (&gid))
|
while (all_gids_to_retain->next (&gid))
|
||||||
glyphs->push (gid);
|
glyphs->push (gid);
|
||||||
|
|
||||||
|
cff.fini ();
|
||||||
glyf.fini ();
|
glyf.fini ();
|
||||||
cmap.fini ();
|
cmap.fini ();
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -90,6 +90,36 @@ test_extents_cff1_flex (void)
|
||||||
hb_font_destroy (font);
|
hb_font_destroy (font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_extents_cff1_seac (void)
|
||||||
|
{
|
||||||
|
hb_face_t *face = hb_test_open_font_file ("fonts/cff1_seac.otf");
|
||||||
|
g_assert (face);
|
||||||
|
hb_font_t *font = hb_font_create (face);
|
||||||
|
hb_face_destroy (face);
|
||||||
|
g_assert (font);
|
||||||
|
hb_ot_font_set_funcs (font);
|
||||||
|
|
||||||
|
hb_glyph_extents_t extents;
|
||||||
|
hb_bool_t result = hb_font_get_glyph_extents (font, 3, &extents); /* Agrave */
|
||||||
|
g_assert (result);
|
||||||
|
|
||||||
|
g_assert_cmpint (extents.x_bearing, ==, 3);
|
||||||
|
g_assert_cmpint (extents.y_bearing, ==, 861);
|
||||||
|
g_assert_cmpint (extents.width, ==, 538);
|
||||||
|
g_assert_cmpint (extents.height, ==, -861);
|
||||||
|
|
||||||
|
result = hb_font_get_glyph_extents (font, 4, &extents); /* Udieresis */
|
||||||
|
g_assert (result);
|
||||||
|
|
||||||
|
g_assert_cmpint (extents.x_bearing, ==, 87);
|
||||||
|
g_assert_cmpint (extents.y_bearing, ==, 827);
|
||||||
|
g_assert_cmpint (extents.width, ==, 471);
|
||||||
|
g_assert_cmpint (extents.height, ==, -839);
|
||||||
|
|
||||||
|
hb_font_destroy (font);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_extents_cff2 (void)
|
test_extents_cff2 (void)
|
||||||
{
|
{
|
||||||
|
@ -161,6 +191,7 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
hb_test_add (test_extents_cff1);
|
hb_test_add (test_extents_cff1);
|
||||||
hb_test_add (test_extents_cff1_flex);
|
hb_test_add (test_extents_cff1_flex);
|
||||||
|
hb_test_add (test_extents_cff1_seac);
|
||||||
hb_test_add (test_extents_cff2);
|
hb_test_add (test_extents_cff2);
|
||||||
hb_test_add (test_extents_cff2_vsindex);
|
hb_test_add (test_extents_cff2_vsindex);
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,24 @@ test_subset_cff1_expert (void)
|
||||||
hb_face_destroy (face);
|
hb_face_destroy (face);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_subset_cff1_seac (void)
|
||||||
|
{
|
||||||
|
hb_face_t *face = hb_test_open_font_file ("fonts/cff1_seac.otf");
|
||||||
|
hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_seac.C0.otf");
|
||||||
|
|
||||||
|
hb_set_t *codepoints = hb_set_create ();
|
||||||
|
hb_set_add (codepoints, 0xC0); /* Agrave */
|
||||||
|
hb_face_t *face_test = hb_subset_test_create_subset (face, hb_subset_test_create_input (codepoints));
|
||||||
|
hb_set_destroy (codepoints);
|
||||||
|
|
||||||
|
hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));
|
||||||
|
|
||||||
|
hb_face_destroy (face_test);
|
||||||
|
hb_face_destroy (face_subset);
|
||||||
|
hb_face_destroy (face);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -263,6 +281,7 @@ main (int argc, char **argv)
|
||||||
hb_test_add (test_subset_cff1_j_desubr);
|
hb_test_add (test_subset_cff1_j_desubr);
|
||||||
hb_test_add (test_subset_cff1_j_desubr_strip_hints);
|
hb_test_add (test_subset_cff1_j_desubr_strip_hints);
|
||||||
hb_test_add (test_subset_cff1_expert);
|
hb_test_add (test_subset_cff1_expert);
|
||||||
|
hb_test_add (test_subset_cff1_seac);
|
||||||
|
|
||||||
return hb_test_run ();
|
return hb_test_run ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue