Merge branch 'master' into subset-varstore

This commit is contained in:
blueshade7 2019-07-29 14:21:05 -07:00
commit f0dd724c1e
108 changed files with 1899 additions and 915 deletions

View File

@ -264,7 +264,7 @@ jobs:
- image: dockcross/android-arm
steps:
- checkout
- run: cmake -Bbuild -H. -GNinja
- run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF
- run: ninja -Cbuild
crosscompile-cmake-notest-browser-asmjs-hb_tiny:
@ -272,7 +272,7 @@ jobs:
- image: dockcross/browser-asmjs
steps:
- checkout
- run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY"
- run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY" -DHB_BUILD_TESTS=OFF
- run: ninja -Cbuild
crosscompile-cmake-notest-linux-arm64:
@ -280,7 +280,7 @@ jobs:
- image: dockcross/linux-arm64
steps:
- checkout
- run: cmake -Bbuild -H. -GNinja
- run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF
- run: ninja -Cbuild
crosscompile-cmake-notest-linux-mips:
@ -288,7 +288,7 @@ jobs:
- image: dockcross/linux-mips
steps:
- checkout
- run: cmake -Bbuild -H. -GNinja
- run: cmake -Bbuild -H. -GNinja -DHB_BUILD_TESTS=OFF
- run: ninja -Cbuild
#crosscompile-cmake-notest-windows-x64:

View File

@ -43,6 +43,7 @@ if (APPLE)
endif ()
if (WIN32)
option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF)
option(HB_HAVE_GDI "Enable GDI integration helpers on Windows" OFF)
option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF)
endif ()
option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF)
@ -77,6 +78,7 @@ if (HB_CHECK)
set (HB_HAVE_GRAPHITE2 ON)
if (WIN32)
set (HB_HAVE_UNISCRIBE ON)
set (HB_HAVE_GDI ON)
set (HB_HAVE_DIRECTWRITE ON)
elseif (APPLE)
set (HB_HAVE_CORETEXT ON)
@ -140,8 +142,8 @@ endif ()
## Extract variables from Makefile files
function (extract_make_variable variable makefile_source)
string(REGEX MATCH "${variable} = ([^$]+)\\$" temp ${makefile_source})
string(REGEX MATCHALL "[^ \n\t\\]+" listVar ${CMAKE_MATCH_1})
string(REGEX MATCH "${variable} = ([^$]+)\\$" temp "${makefile_source}")
string(REGEX MATCHALL "[^ \n\t\\]+" listVar "${CMAKE_MATCH_1}")
set (${variable} ${listVar} PARENT_SCOPE)
endfunction ()
@ -157,8 +159,6 @@ endfunction ()
file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES)
file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES)
extract_make_variable(HB_BASE_sources ${SRCSOURCES})
add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/")
extract_make_variable(HB_BASE_headers ${SRCSOURCES})
add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/")
@ -192,59 +192,12 @@ set (HB_VERSION_MAJOR ${CMAKE_MATCH_2})
set (HB_VERSION_MINOR ${CMAKE_MATCH_3})
set (HB_VERSION_MICRO ${CMAKE_MATCH_4})
## Define ragel tasks
# if (NOT IN_HB_DIST)
# foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources})
# string(REGEX MATCH "([^/]+)\\.hh" temp ${ragel_output})
# set (target_name ${CMAKE_MATCH_1})
# add_custom_command(OUTPUT ${ragel_output}
# COMMAND ${RAGEL} -G2 -o ${ragel_output} ${PROJECT_SOURCE_DIR}/src/${target_name}.rl -I ${PROJECT_SOURCE_DIR} ${ARGN}
# DEPENDS ${PROJECT_SOURCE_DIR}/src/${target_name}.rl
# )
# add_custom_target(harfbuzz_${target_name} DEPENDS ${PROJECT_BINARY_DIR}/src/${target_name})
# endforeach ()
# mark_as_advanced(RAGEL)
# endif ()
## Generate hb-version.h
# if (NOT IN_HB_DIST)
# set (HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in")
# set (HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h")
# set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true)
# configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY)
# execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different
# "${HB_VERSION_H}.tmp"
# "${HB_VERSION_H}"
# )
# file(REMOVE "${HB_VERSION_H}.tmp")
# endif ()
## Define sources and headers of the project
set (project_sources
${HB_BASE_sources}
${HB_BASE_RAGEL_GENERATED_sources}
)
set (subset_project_sources
${HB_SUBSET_sources}
)
set (project_sources ${PROJECT_SOURCE_DIR}/src/harfbuzz.cc) # use amalgam source
set (subset_project_sources ${HB_SUBSET_sources})
set (project_extra_sources)
set (project_headers
#${HB_VERSION_H}
${HB_BASE_headers}
)
set (subset_project_headers
${HB_SUBSET_headers}
)
set (project_headers ${HB_BASE_headers})
set (subset_project_headers ${HB_SUBSET_headers})
## Find and include needed header folders and libraries
if (HB_HAVE_FREETYPE)
@ -257,7 +210,6 @@ if (HB_HAVE_FREETYPE)
include_directories(AFTER ${FREETYPE_INCLUDE_DIRS})
add_definitions(-DHAVE_FREETYPE=1)
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ft.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h)
# So check_funcs can find its headers
@ -275,7 +227,6 @@ if (HB_HAVE_GRAPHITE2)
include_directories(${GRAPHITE2_INCLUDE_DIR})
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-graphite2.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h)
list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY})
@ -296,7 +247,6 @@ if (HB_HAVE_GLIB)
include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR})
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-glib.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h)
list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES})
@ -316,7 +266,6 @@ if (HB_HAVE_ICU)
include_directories(${ICU_INCLUDE_DIR})
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-icu.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h)
list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY})
@ -328,7 +277,6 @@ if (APPLE AND HB_HAVE_CORETEXT)
# Apple Advanced Typography
add_definitions(-DHAVE_CORETEXT)
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h)
if (HB_IOS)
@ -359,21 +307,21 @@ if (APPLE AND HB_HAVE_CORETEXT)
endif ()
endif ()
if (WIN32 AND HB_HAVE_GDI)
add_definitions(-DHAVE_GDI)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-gdi.h)
list(APPEND THIRD_PARTY_LIBS gdi32)
endif ()
if (WIN32 AND HB_HAVE_UNISCRIBE)
add_definitions(-DHAVE_UNISCRIBE)
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h)
list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4)
endif ()
if (WIN32 AND HB_HAVE_DIRECTWRITE)
add_definitions(-DHAVE_DIRECTWRITE)
list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-directwrite.cc)
list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h)
list(APPEND THIRD_PARTY_LIBS dwrite rpcrt4)
endif ()
@ -481,7 +429,6 @@ if (HB_HAVE_GOBJECT)
)
endif ()
## Atomic ops availability detection
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c"
" void memory_barrier (void) { __sync_synchronize (); }
@ -590,7 +537,6 @@ if (WIN32)
endif ()
if (HB_HAVE_INTROSPECTION)
find_package(PkgConfig)
pkg_check_modules(PC_GI QUIET gobject-introspection-1.0)
@ -824,7 +770,7 @@ endif ()
if (HB_BUILD_TESTS)
## src/ executables
foreach (prog main test test-gsub-would-substitute test-gpos-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
foreach (prog main test test-gsub-would-substitute test-gpos-size-params test-buffer-serialize test-unicode-ranges) # hb-ot-tag
set (prog_name ${prog})
if (${prog_name} STREQUAL "test")
# test can not be used as a valid executable name on cmake, lets special case it
@ -833,7 +779,7 @@ if (HB_BUILD_TESTS)
add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc)
target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS})
endforeach ()
set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
# set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN")
## Tests
if (UNIX OR MINGW)

View File

@ -73,7 +73,7 @@ build_script:
- 'if "%compiler%"=="msvc2" cmake --build build --config %configuration%'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"'
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --with-gdi --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"'
cache:
- c:\tools\vcpkg\installed\

View File

@ -361,6 +361,28 @@ AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)
dnl ===========================================================================
AC_ARG_WITH(gdi,
[AS_HELP_STRING([--with-gdi=@<:@yes/no/auto@:>@],
[Provide GDI integration helpers @<:@default=no@:>@])],,
[with_gdi=no])
have_gdi=false
if test "x$with_gdi" = "xyes" -o "x$with_gdi" = "xauto"; then
AC_CHECK_HEADERS(windows.h, have_gdi=true)
fi
if test "x$with_gdi" = "xyes" -a "x$have_gdi" != "xtrue"; then
AC_MSG_ERROR([gdi support requested but not found])
fi
if $have_gdi; then
GDI_CFLAGS=
GDI_LIBS="-lgdi32"
AC_SUBST(GDI_CFLAGS)
AC_SUBST(GDI_LIBS)
AC_DEFINE(HAVE_GDI, 1, [Have GDI library])
fi
AM_CONDITIONAL(HAVE_GDI, $have_gdi)
dnl ===========================================================================
AC_ARG_WITH(directwrite,
[AS_HELP_STRING([--with-directwrite=@<:@yes/no/auto@:>@],
[Use the DirectWrite library (experimental) @<:@default=no@:>@])],,
@ -510,6 +532,7 @@ Additional shapers (the more the merrier):
Platform shapers (not normally needed):
CoreText: ${have_coretext}
DirectWrite: ${have_directwrite}
GDI: ${have_gdi}
Uniscribe: ${have_uniscribe}
Other features:

View File

@ -1,6 +1,7 @@
<SUBSECTION Private>
HB_H_IN
HB_OT_H_IN
HB_AAT_H_IN
</SECTION>
<SECTION>
@ -179,6 +180,7 @@ HB_BUFFER_SERIALIZE_FLAGS_DEFAULT
HB_SCRIPT_CANADIAN_ABORIGINAL
hb_font_funcs_set_glyph_func
hb_font_get_glyph_func_t
HB_MATH_GLYPH_PART_FLAG_EXTENDER
hb_ot_layout_table_choose_script
hb_ot_layout_table_find_script
hb_ot_tag_from_language
@ -367,6 +369,11 @@ hb_ft_font_get_load_flags
hb_ft_font_set_funcs
</SECTION>
<SECTION>
<FILE>hb-gdi</FILE>
hb_gdi_face_create
</SECTION>
<SECTION>
<FILE>hb-glib</FILE>
hb_glib_get_unicode_funcs
@ -600,6 +607,22 @@ hb_ot_math_get_min_connector_overlap
hb_ot_math_get_glyph_assembly
</SECTION>
<SECTION>
<FILE>hb-ot-meta</FILE>
hb_ot_meta_t
hb_ot_meta_get_entries
hb_ot_meta_reference_entry
</SECTION>
<SECTION>
<FILE>hb-ot-metrics</FILE>
hb_ot_metrics_t
hb_ot_metrics_get_position
hb_ot_metrics_get_variation
hb_ot_metrics_get_x_variation
hb_ot_metrics_get_y_variation
</SECTION>
<SECTION>
<FILE>hb-ot-shape</FILE>
hb_ot_shape_glyphs_closure

View File

@ -156,14 +156,16 @@
order.
</para>
<para>
For left-to-right scripts (LTR) and top-to-bottom scripts (TTB),
For buffers in the left-to-right (LTR)
or top-to-bottom (TTB) text flow direction,
HarfBuzz will preserve the monotonic property: client programs
are guaranteed that monotonically increasing initial cluster
values will be returned as monotonically increasing final
cluster values.
</para>
<para>
For right-to-left scripts (RTL) and bottom-to-top scripts (BTT),
For buffers in the right-to-left (RTL)
or bottom-to-top (BTT) text flow direction,
the directionality of the buffer itself is reversed for final
output as a matter of design. Therefore, HarfBuzz inverts the
monotonic property: client programs are guaranteed that

View File

@ -86,7 +86,7 @@
objects. <function>hb_font_set_ppem(font, x_ppem,
y_ppem)</function> sets the pixels-per-EM value of the font. You
can also set the point size of the font with
<function>hb_font_set_ppem(font, ptem)</function>. HarfBuzz uses the
<function>hb_font_set_ptem(font, ptem)</function>. HarfBuzz uses the
industry standard 72 points per inch.
</para>
<para>

View File

@ -12,6 +12,8 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
TESTS =
check_PROGRAMS =
EXTRA_DIST += harfbuzz.cc
# Convenience targets:
lib: $(BUILT_SOURCES) libharfbuzz.la
libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES)
@ -80,6 +82,13 @@ HBSOURCES += $(HB_DIRECTWRITE_sources)
HBHEADERS += $(HB_DIRECTWRITE_headers)
endif
if HAVE_GDI
HBCFLAGS += $(GDI_CXXFLAGS)
HBNONPCLIBS += $(GDI_LIBS)
HBSOURCES += $(HB_GDI_sources)
HBHEADERS += $(HB_GDI_headers)
endif
if HAVE_CORETEXT
HBCFLAGS += $(CORETEXT_CFLAGS)
HBNONPCLIBS += $(CORETEXT_LIBS)
@ -253,31 +262,38 @@ GENERATORS = \
$(NULL)
EXTRA_DIST += $(GENERATORS)
unicode-tables: arabic-table indic-table tag-table use-table emoji-table
unicode-tables: \
arabic-table \
emoji-table \
indic-table \
tag-table \
ucd-table \
use-table \
emoji-table \
$(NULL)
arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-arabic-table.hh \
|| ($(RM) $(srcdir)/hb-ot-shape-complex-arabic-table.hh; false)
emoji-table: gen-emoji-table.py emoji-data.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
indic-table: gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-indic-table.cc \
|| ($(RM) $(srcdir)/hb-ot-shape-complex-indic-table.cc; false)
tag-table: gen-tag-table.py languagetags language-subtag-registry
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-tag-table.hh \
|| ($(RM) $(srcdir)/hb-ot-tag-table.hh; false)
ucd-table: gen-ucd-table.py ucd.nounihan.grouped.zip hb-common.h
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ucd-table.hh \
|| ($(RM) $(srcdir)/hb-ucd-table.hh; false)
use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \
|| ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false)
vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \
|| ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false)
emoji-table: gen-emoji-table.py emoji-data.txt
$(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \
|| ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false)
built-sources: $(BUILT_SOURCES)
@ -296,10 +312,27 @@ $(srcdir)/%.hh: $(srcdir)/%.rl
$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
|| ($(RM) "$@"; false)
harfbuzz.cc: Makefile.sources
$(AM_V_GEN) \
for f in \
$(HB_BASE_sources) \
$(HB_GLIB_sources) \
$(HB_FT_sources) \
$(HB_GRAPHITE2_sources) \
$(HB_UNISCRIBE_sources) \
$(HB_GDI_sources) \
$(HB_DIRECTWRITE_sources) \
$(HB_CORETEXT_sources) \
; do echo '#include "'$$f'"'; done | \
grep '[.]cc"' > $(srcdir)/harfbuzz.cc \
|| ($(RM) $(srcdir)/harfbuzz.cc; false)
BUILT_SOURCES += harfbuzz.cc
noinst_PROGRAMS = \
main \
test \
test-buffer-serialize \
test-ot-meta \
test-ot-name \
test-gpos-size-params \
test-gsub-would-substitute \
@ -318,6 +351,10 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc
test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
test_ot_meta_SOURCES = test-ot-meta.cc
test_ot_meta_CPPFLAGS = $(HBCFLAGS)
test_ot_meta_LDADD = libharfbuzz.la $(HBLIBS)
test_ot_name_SOURCES = test-ot-name.cc
test_ot_name_CPPFLAGS = $(HBCFLAGS)
test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)

View File

@ -88,6 +88,10 @@ HB_BASE_sources = \
hb-ot-math-table.hh \
hb-ot-math.cc \
hb-ot-maxp-table.hh \
hb-ot-meta-table.hh \
hb-ot-meta.cc \
hb-ot-metrics.cc \
hb-ot-metrics.hh \
hb-ot-name-language-static.hh \
hb-ot-name-language.hh \
hb-ot-name-table.hh \
@ -191,6 +195,8 @@ HB_BASE_headers = \
hb-ot-font.h \
hb-ot-layout.h \
hb-ot-math.h \
hb-ot-meta.h \
hb-ot-metrics.h \
hb-ot-name.h \
hb-ot-shape.h \
hb-ot-var.h \
@ -222,6 +228,9 @@ HB_CORETEXT_headers = hb-coretext.h
HB_DIRECTWRITE_sources = hb-directwrite.cc
HB_DIRECTWRITE_headers = hb-directwrite.h
HB_GDI_sources = hb-gdi.cc
HB_GDI_headers = hb-gdi.h
HB_UNISCRIBE_sources = hb-uniscribe.cc
HB_UNISCRIBE_headers = hb-uniscribe.h

View File

@ -6,8 +6,8 @@ import io, os.path, sys, re
import logging
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
if len (sys.argv) != 2:
print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml", file=sys.stderr)
if len (sys.argv) not in (2, 3):
print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml [/path/to/hb-common.h]", file=sys.stderr)
sys.exit(1)
# https://github.com/harfbuzz/packtab
@ -18,6 +18,8 @@ logging.info('Loading UCDXML...')
ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
hb_common_h = 'hb-common.h' if len (sys.argv) < 3 else sys.argv[2]
logging.info('Preparing data tables...')
gc = [u['gc'] for u in ucd]
@ -68,7 +70,7 @@ for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu'
sc_order = dict()
sc_array = []
sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
for line in open('hb-common.h'):
for line in open(hb_common_h):
m = sc_re.search (line)
if not m: continue
name = m.group(1)

53
src/harfbuzz.cc Normal file
View File

@ -0,0 +1,53 @@
#include "hb-aat-layout.cc"
#include "hb-aat-map.cc"
#include "hb-blob.cc"
#include "hb-buffer-serialize.cc"
#include "hb-buffer.cc"
#include "hb-common.cc"
#include "hb-face.cc"
#include "hb-fallback-shape.cc"
#include "hb-font.cc"
#include "hb-map.cc"
#include "hb-ot-cff1-table.cc"
#include "hb-ot-cff2-table.cc"
#include "hb-ot-color.cc"
#include "hb-ot-face.cc"
#include "hb-ot-font.cc"
#include "hb-ot-layout.cc"
#include "hb-ot-map.cc"
#include "hb-ot-math.cc"
#include "hb-ot-meta.cc"
#include "hb-ot-metrics.cc"
#include "hb-ot-name.cc"
#include "hb-ot-shape-complex-arabic.cc"
#include "hb-ot-shape-complex-default.cc"
#include "hb-ot-shape-complex-hangul.cc"
#include "hb-ot-shape-complex-hebrew.cc"
#include "hb-ot-shape-complex-indic-table.cc"
#include "hb-ot-shape-complex-indic.cc"
#include "hb-ot-shape-complex-khmer.cc"
#include "hb-ot-shape-complex-myanmar.cc"
#include "hb-ot-shape-complex-thai.cc"
#include "hb-ot-shape-complex-use-table.cc"
#include "hb-ot-shape-complex-use.cc"
#include "hb-ot-shape-complex-vowel-constraints.cc"
#include "hb-ot-shape-fallback.cc"
#include "hb-ot-shape-normalize.cc"
#include "hb-ot-shape.cc"
#include "hb-ot-tag.cc"
#include "hb-ot-var.cc"
#include "hb-set.cc"
#include "hb-shape-plan.cc"
#include "hb-shape.cc"
#include "hb-shaper.cc"
#include "hb-static.cc"
#include "hb-ucd.cc"
#include "hb-unicode.cc"
#include "hb-warning.cc"
#include "hb-glib.cc"
#include "hb-ft.cc"
#include "hb-graphite2.cc"
#include "hb-uniscribe.cc"
#include "hb-gdi.cc"
#include "hb-directwrite.cc"
#include "hb-coretext.cc"

View File

@ -174,9 +174,7 @@ struct feat
}
const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
{
return namesZ.bsearch (featureNameCount, feature_type);
}
{ return namesZ.bsearch (featureNameCount, feature_type); }
hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
{ return get_feature (feature).get_feature_name_id (); }

View File

@ -85,7 +85,7 @@ typedef enum
HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE = 39,
HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE = 103,
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
_HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_aat_layout_feature_type_t;
/**
@ -424,7 +424,7 @@ typedef enum
HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN = 2,
HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN = 3,
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
_HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_aat_layout_feature_selector_t;
HB_EXTERN unsigned int

View File

@ -50,31 +50,31 @@
struct
{
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
template <typename T> auto
template <typename T> constexpr auto
operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
}
HB_FUNCOBJ (hb_identity);
struct
{
/* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
template <typename T> T&
template <typename T> constexpr T&
operator () (T& v) const { return v; }
template <typename T> hb_remove_reference<T>
template <typename T> constexpr hb_remove_reference<T>
operator () (T&& v) const { return v; }
}
HB_FUNCOBJ (hb_lidentity);
struct
{
/* Like identity(), but always returns rvalue. */
template <typename T> hb_remove_reference<T>
template <typename T> constexpr hb_remove_reference<T>
operator () (T&& v) const { return v; }
}
HB_FUNCOBJ (hb_ridentity);
struct
{
template <typename T> bool
template <typename T> constexpr bool
operator () (T&& v) const { return bool (hb_forward<T> (v)); }
}
HB_FUNCOBJ (hb_bool);
@ -82,11 +82,11 @@ HB_FUNCOBJ (hb_bool);
struct
{
private:
template <typename T> auto
template <typename T> constexpr auto
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
template <typename T,
hb_enable_if (hb_is_integral (T))> auto
hb_enable_if (hb_is_integral (T))> constexpr auto
impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
(
/* Knuth's multiplicative method: */
@ -95,7 +95,7 @@ struct
public:
template <typename T> auto
template <typename T> constexpr auto
operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
}
HB_FUNCOBJ (hb_hash);
@ -328,14 +328,14 @@ hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
struct
{
template <typename Pair> typename Pair::first_t
template <typename Pair> constexpr typename Pair::first_t
operator () (const Pair& pair) const { return pair.first; }
}
HB_FUNCOBJ (hb_first);
struct
{
template <typename Pair> typename Pair::second_t
template <typename Pair> constexpr typename Pair::second_t
operator () (const Pair& pair) const { return pair.second; }
}
HB_FUNCOBJ (hb_second);
@ -346,14 +346,14 @@ HB_FUNCOBJ (hb_second);
* comparing integers of different signedness. */
struct
{
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
(hb_forward<T> (a) <= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
}
HB_FUNCOBJ (hb_min);
struct
{
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
(hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
}
@ -917,7 +917,7 @@ struct hb_bitwise_and
{ HB_PARTIALIZE(2);
static constexpr bool passthru_left = false;
static constexpr bool passthru_right = false;
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
}
HB_FUNCOBJ (hb_bitwise_and);
@ -925,7 +925,7 @@ struct hb_bitwise_or
{ HB_PARTIALIZE(2);
static constexpr bool passthru_left = true;
static constexpr bool passthru_right = true;
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
}
HB_FUNCOBJ (hb_bitwise_or);
@ -933,7 +933,7 @@ struct hb_bitwise_xor
{ HB_PARTIALIZE(2);
static constexpr bool passthru_left = true;
static constexpr bool passthru_right = true;
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
}
HB_FUNCOBJ (hb_bitwise_xor);
@ -941,56 +941,56 @@ struct hb_bitwise_sub
{ HB_PARTIALIZE(2);
static constexpr bool passthru_left = true;
static constexpr bool passthru_right = false;
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
}
HB_FUNCOBJ (hb_bitwise_sub);
struct
{
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a) const HB_AUTO_RETURN (~a)
}
HB_FUNCOBJ (hb_bitwise_neg);
struct
{ HB_PARTIALIZE(2);
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
}
HB_FUNCOBJ (hb_add);
struct
{ HB_PARTIALIZE(2);
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
}
HB_FUNCOBJ (hb_sub);
struct
{ HB_PARTIALIZE(2);
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
}
HB_FUNCOBJ (hb_mul);
struct
{ HB_PARTIALIZE(2);
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
}
HB_FUNCOBJ (hb_div);
struct
{ HB_PARTIALIZE(2);
template <typename T, typename T2> auto
template <typename T, typename T2> constexpr auto
operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
}
HB_FUNCOBJ (hb_mod);
struct
{
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a) const HB_AUTO_RETURN (+a)
}
HB_FUNCOBJ (hb_pos);
struct
{
template <typename T> auto
template <typename T> constexpr auto
operator () (const T &a) const HB_AUTO_RETURN (-a)
}
HB_FUNCOBJ (hb_neg);

View File

@ -378,7 +378,7 @@ typedef hb_vector_t<byte_str_t> byte_str_array_t;
/* stack */
template <typename ELEM, int LIMIT>
struct stack_t
struct cff_stack_t
{
void init ()
{
@ -469,7 +469,7 @@ struct stack_t
/* argument stack */
template <typename ARG=number_t>
struct arg_stack_t : stack_t<ARG, 513>
struct arg_stack_t : cff_stack_t<ARG, 513>
{
void push_int (int v)
{
@ -523,7 +523,7 @@ struct arg_stack_t : stack_t<ARG, 513>
{ return S::elements.sub_array (start); }
private:
typedef stack_t<ARG, 513> S;
typedef cff_stack_t<ARG, 513> S;
};
/* an operator prefixed by its operands in a byte string */

View File

@ -57,7 +57,7 @@ struct call_context_t
/* call stack */
const unsigned int kMaxCallLimit = 10;
struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {};
struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {};
template <typename SUBRS>
struct biased_subrs_t

View File

@ -66,6 +66,8 @@
#define HB_NO_LAYOUT_COLLECT_GLYPHS
#define HB_NO_LAYOUT_UNUSED
#define HB_NO_MATH
#define HB_NO_META
#define HB_NO_METRICS
#define HB_NO_MMAP
#define HB_NO_NAME
#define HB_NO_OPEN

View File

@ -75,7 +75,7 @@ release_table_data (void *user_data)
}
static hb_blob_t *
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
_hb_cg_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
{
CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data);
CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag);
@ -299,7 +299,7 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
hb_face_t *
hb_coretext_face_create (CGFontRef cg_font)
{
return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
return hb_face_create_for_tables (_hb_cg_reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
}
/*

View File

@ -539,11 +539,6 @@ protected:
Run mRunHead;
};
static inline uint16_t hb_uint16_swap (const uint16_t v)
{ return (v >> 8) | (v << 8); }
static inline uint32_t hb_uint32_swap (const uint32_t v)
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
/*
* shaper
*/
@ -934,7 +929,7 @@ _hb_directwrite_table_data_release (void *data)
}
static hb_blob_t *
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
_hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
{
IDWriteFontFace *dw_face = ((IDWriteFontFace *) user_data);
const void *data;
@ -979,7 +974,7 @@ hb_directwrite_face_create (IDWriteFontFace *font_face)
{
if (font_face)
font_face->AddRef ();
return hb_face_create_for_tables (reference_table, font_face,
return hb_face_create_for_tables (_hb_directwrite_reference_table, font_face,
_hb_directwrite_font_release);
}

View File

@ -1300,6 +1300,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
1000, /* x_scale */
1000, /* y_scale */
1<<16, /* x_mult */
1<<16, /* y_mult */
0, /* x_ppem */
0, /* y_ppem */
@ -1330,6 +1332,7 @@ _hb_font_create (hb_face_t *face)
font->klass = hb_font_funcs_get_empty ();
font->data.init0 (font);
font->x_scale = font->y_scale = hb_face_get_upem (face);
font->x_mult = font->y_mult = 1 << 16;
return font;
}
@ -1601,7 +1604,9 @@ hb_font_set_face (hb_font_t *font,
hb_face_t *old = font->face;
hb_face_make_immutable (face);
font->face = hb_face_reference (face);
font->mults_changed ();
hb_face_destroy (old);
}
@ -1711,6 +1716,7 @@ hb_font_set_scale (hb_font_t *font,
font->x_scale = x_scale;
font->y_scale = y_scale;
font->mults_changed ();
}
/**

View File

@ -107,8 +107,10 @@ struct hb_font_t
hb_font_t *parent;
hb_face_t *face;
int x_scale;
int y_scale;
int32_t x_scale;
int32_t y_scale;
int64_t x_mult;
int64_t y_mult;
unsigned int x_ppem;
unsigned int y_ppem;
@ -127,16 +129,16 @@ struct hb_font_t
/* Convert from font-space to user-space */
int dir_scale (hb_direction_t direction)
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
int64_t dir_mult (hb_direction_t direction)
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); }
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_scale (v, dir_scale (direction)); }
{ return em_mult (v, dir_mult (direction)); }
/* Convert from parent-font user-space to our user-space */
hb_position_t parent_scale_x_distance (hb_position_t v)
@ -607,12 +609,16 @@ struct hb_font_t
return false;
}
hb_position_t em_scale (int16_t v, int scale)
void mults_changed ()
{
int upem = face->get_upem ();
int64_t scaled = v * (int64_t) scale;
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
return (hb_position_t) (scaled / upem);
signed upem = face->get_upem ();
x_mult = ((int64_t) x_scale << 16) / upem;
y_mult = ((int64_t) y_scale << 16) / upem;
}
hb_position_t em_mult (int16_t v, int64_t mult)
{
return (hb_position_t) ((v * mult) >> 16);
}
hb_position_t em_scalef (float v, int scale)
{ return (hb_position_t) roundf (v * scale / face->get_upem ()); }

View File

@ -564,7 +564,7 @@ _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
static hb_blob_t *
reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
_hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
{
FT_Face ft_face = (FT_Face) user_data;
FT_Byte *buffer;
@ -619,7 +619,7 @@ hb_ft_face_create (FT_Face ft_face,
face = hb_face_create (blob, ft_face->face_index);
hb_blob_destroy (blob);
} else {
face = hb_face_create_for_tables (reference_table, ft_face, destroy);
face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy);
}
hb_face_set_index (face, ft_face->face_index);

73
src/hb-gdi.cc Normal file
View File

@ -0,0 +1,73 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#include "hb.hh"
#ifdef HAVE_GDI
#include "hb-gdi.h"
static hb_blob_t *
_hb_gdi_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
{
char *buffer = nullptr;
DWORD length = 0;
HDC hdc = GetDC (nullptr);
if (unlikely (!SelectObject (hdc, (HFONT) user_data))) goto fail;
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc;
buffer = (char *) malloc (length);
if (unlikely (!buffer)) goto fail_with_releasedc;
length = GetFontData (hdc, hb_uint32_swap (tag), 0, buffer, length);
if (unlikely (length == GDI_ERROR)) goto fail_with_releasedc_and_free;
ReleaseDC (nullptr, hdc);
return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free);
fail_with_releasedc_and_free:
free (buffer);
fail_with_releasedc:
ReleaseDC (nullptr, hdc);
fail:
return hb_blob_get_empty ();
}
/**
* hb_gdi_face_create:
* @hdc: a HFONT object.
*
* Return value: #hb_face_t object corresponding to the given input
*
* Since: REPLACEME
**/
hb_face_t *
hb_gdi_face_create (HFONT hfont)
{
return hb_face_create_for_tables (_hb_gdi_reference_table, (void *) hfont, nullptr);
}
#endif

39
src/hb-gdi.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_GDI_H
#define HB_GDI_H
#include "hb.h"
#include <windows.h>
HB_BEGIN_DECLS
HB_EXTERN hb_face_t *
hb_gdi_face_create (HFONT hfont);
HB_END_DECLS
#endif /* HB_GDI_H */

View File

@ -106,32 +106,6 @@ retry:
return d;
}
static void hb_graphite2_release_table(const void *data, const void *table_buffer)
{
hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data;
hb_graphite2_tablelist_t *tlist = face_data->tlist;
hb_graphite2_tablelist_t *prev = nullptr;
hb_graphite2_tablelist_t *curr = tlist;
while (curr)
{
if (hb_blob_get_data(curr->blob, nullptr) == table_buffer)
{
if (prev == nullptr)
face_data->tlist.cmpexch(tlist, curr->next);
else
prev->next = curr->next;
hb_blob_destroy(curr->blob);
free(curr);
break;
}
prev = curr;
curr = curr->next;
}
}
static gr_face_ops hb_graphite2_face_ops = { sizeof(gr_face_ops), hb_graphite2_get_table, hb_graphite2_release_table };
hb_graphite2_face_data_t *
_hb_graphite2_shaper_face_data_create (hb_face_t *face)
{
@ -150,7 +124,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
return nullptr;
data->face = face;
data->grface = gr_make_face_with_ops (data, &hb_graphite2_face_ops, gr_face_preloadAll);
data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
if (unlikely (!data->grface)) {
free (data);

View File

@ -480,7 +480,7 @@ struct hb_reduce_t
template <typename Iter,
hb_requires (hb_is_iterator (Iter)),
typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
typename AccuT = hb_decay<decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>>
AccuT
operator () (Iter it)
{

View File

@ -80,8 +80,8 @@ template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::t
struct
{
template <typename T>
T* operator () (T& arg) const
template <typename T> constexpr T*
operator () (T& arg) const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
@ -171,29 +171,29 @@ using hb_is_cr_convertible = hb_bool_constant<
/* std::move and std::forward */
template <typename T>
static hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
static constexpr hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
template <typename T>
static T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
static constexpr T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
template <typename T>
static T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
static constexpr T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
struct
{
template <typename T> auto
template <typename T> constexpr auto
operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
template <typename T> auto
template <typename T> constexpr auto
operator () (T *v) const HB_AUTO_RETURN (*v)
}
HB_FUNCOBJ (hb_deref);
struct
{
template <typename T> auto
template <typename T> constexpr auto
operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
template <typename T> auto
template <typename T> constexpr auto
operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
}
HB_FUNCOBJ (hb_ref);

View File

@ -141,14 +141,15 @@ typedef struct OffsetTable
TableRecord &rec = tables.arrayZ[i];
hb_blob_t *blob = items[i].blob;
rec.tag = items[i].tag;
rec.length = hb_blob_get_length (blob);
rec.length = blob->length;
rec.offset.serialize (c, this);
/* Allocate room for the table and copy it. */
char *start = (char *) c->allocate_size<void> (rec.length);
if (unlikely (!start)) {return false;}
if (unlikely (!start)) return false;
memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
if (likely (rec.length))
memcpy (start, blob->data, rec.length);
/* 4-byte alignment. */
c->align (4);

View File

@ -576,13 +576,13 @@ struct ArrayOf
operator writer_t () { return writer (); }
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
{
@ -826,13 +826,13 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
operator writer_t () { return writer (); }
hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
bool serialize (hb_serialize_context_t *c, unsigned int items_len)
{

View File

@ -210,7 +210,7 @@ struct bounds_t
point_t max;
};
struct extents_param_t
struct cff1_extents_param_t
{
void init (const OT::cff1::accelerator_t *_cff)
{
@ -229,15 +229,15 @@ struct extents_param_t
const OT::cff1::accelerator_t *cff;
};
struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
{
static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
{
param.end_path ();
env.moveto (pt);
}
static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
{
if (!param.is_path_open ())
{
@ -248,7 +248,7 @@ struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_
param.bounds.update (env.get_pt ());
}
static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
static void curve (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
if (!param.is_path_open ())
{
@ -265,9 +265,9 @@ struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_
static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t>
{
static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
{
unsigned int n = env.argStack.get_count ();
point_t delta;
@ -296,11 +296,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp;
const byte_str_t str = (*cff->charStrings)[glyph];
interp.env.init (str, *cff, fd);
interp.env.set_in_seac (in_seac);
extents_param_t param;
cff1_extents_param_t param;
param.init (cff);
if (unlikely (!interp.interpret (param))) return false;
bounds = param.bounds;

View File

@ -33,7 +33,7 @@
using namespace CFF;
struct extents_param_t
struct cff2_extents_param_t
{
void init ()
{
@ -63,15 +63,15 @@ struct extents_param_t
number_t max_y;
};
struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, extents_param_t>
struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, cff2_extents_param_t>
{
static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt)
{
param.end_path ();
env.moveto (pt);
}
static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1)
{
if (!param.is_path_open ())
{
@ -82,7 +82,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
param.update_bounds (env.get_pt ());
}
static void curve (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
if (!param.is_path_open ())
{
@ -97,7 +97,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
}
};
struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {};
struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, cff2_path_procs_extents_t> {};
bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
hb_codepoint_t glyph,
@ -113,10 +113,10 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
unsigned int num_coords;
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
unsigned int fd = fdSelect->get_fd (glyph);
cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp;
cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
const byte_str_t str = (*charStrings)[glyph];
interp.env.init (str, *this, fd, coords, num_coords);
extents_param_t param;
cff2_extents_param_t param;
param.init ();
if (unlikely (!interp.interpret (param))) return false;

View File

@ -979,6 +979,14 @@ struct cmap
if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
return false;
}
else
{
// FIXME: Merge this with above or, remove and tweak #final_size
// and rebase all the tests expectations
HBUINT32 empty;
empty = 0;
for (unsigned int i = 0; i < 4; ++i) c.copy (empty);
}
c.end_serialize ();

View File

@ -235,9 +235,9 @@ struct sbix
const PNGHeader &png = *blob->as<PNGHeader>();
extents->x_bearing = x_offset;
extents->y_bearing = y_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
extents->height = png.IHDR.height;
extents->height = -png.IHDR.height;
/* Convert to font units. */
if (strike_ppem)

View File

@ -50,9 +50,10 @@ HB_OT_TABLE (OT, head)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
HB_OT_TABLE (OT, hhea)
HB_OT_ACCELERATOR (OT, hmtx)
HB_OT_TABLE (OT, OS2)
#ifndef HB_NO_OT_FONT_GLYPH_NAMES
#if !defined(HB_NO_OT_FONT_GLYPH_NAMES) || !defined(HB_NO_METRICS)
HB_OT_ACCELERATOR (OT, post)
#endif
#ifndef HB_NO_NAME
@ -61,8 +62,12 @@ HB_OT_ACCELERATOR (OT, name)
#ifndef HB_NO_STAT
HB_OT_TABLE (OT, STAT)
#endif
#ifndef HB_NO_META
HB_OT_ACCELERATOR (OT, meta)
#endif
/* Vertical layout. */
HB_OT_TABLE (OT, vhea)
HB_OT_ACCELERATOR (OT, vmtx)
/* TrueType outlines. */

View File

@ -32,6 +32,7 @@
#include "hb-ot-cff2-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-kern-table.hh"
#include "hb-ot-meta-table.hh"
#include "hb-ot-name-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-color-cbdt-table.hh"

View File

@ -230,32 +230,24 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
static hb_bool_t
hb_ot_get_font_h_extents (hb_font_t *font,
void *font_data,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
metrics->ascender = font->em_scale_y (hmtx.ascender);
metrics->descender = font->em_scale_y (hmtx.descender);
metrics->line_gap = font->em_scale_y (hmtx.line_gap);
// TODO Hook up variations.
return hmtx.has_font_extents;
return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_HORIZONTAL_ASCENDER, &metrics->ascender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_HORIZONTAL_DESCENDER, &metrics->descender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_HORIZONTAL_LINE_GAP, &metrics->line_gap);
}
static hb_bool_t
hb_ot_get_font_v_extents (hb_font_t *font,
void *font_data,
void *font_data HB_UNUSED,
hb_font_extents_t *metrics,
void *user_data HB_UNUSED)
{
const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
metrics->ascender = font->em_scale_x (vmtx.ascender);
metrics->descender = font->em_scale_x (vmtx.descender);
metrics->line_gap = font->em_scale_x (vmtx.line_gap);
// TODO Hook up variations.
return vmtx.has_font_extents;
return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_VERTICAL_ASCENDER, &metrics->ascender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_VERTICAL_DESCENDER, &metrics->descender) &&
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_VERTICAL_LINE_GAP, &metrics->line_gap);
}
#if HB_USE_ATEXIT

View File

@ -45,6 +45,8 @@ namespace OT {
template <typename T>
struct _hea
{
bool has_data () const { return version.major; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -29,8 +29,8 @@
#include "hb-open-type.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-metrics.hh"
/*
* hmtx -- Horizontal Metrics
@ -162,28 +162,7 @@ struct hmtxvmtx
{
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
bool got_font_extents = false;
if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
{
ascender = abs (face->table.OS2->sTypoAscender);
descender = -abs (face->table.OS2->sTypoDescender);
line_gap = face->table.OS2->sTypoLineGap;
got_font_extents = (ascender | descender) != 0;
}
hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
const H *_hea_table = _hea_blob->as<H> ();
num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents)
{
ascender = abs (_hea_table->ascender);
descender = -abs (_hea_table->descender);
line_gap = _hea_table->lineGap;
got_font_extents = (ascender | descender) != 0;
}
hb_blob_destroy (_hea_blob);
has_font_extents = got_font_extents;
num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
@ -277,12 +256,6 @@ struct hmtxvmtx
return get_advance (old_gid);
}
public:
bool has_font_extents;
int ascender;
int descender;
int line_gap;
protected:
unsigned int num_metrics;
unsigned int num_advances;
@ -322,12 +295,12 @@ struct hmtxvmtx
struct hmtx : hmtxvmtx<hmtx, hhea> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
static constexpr bool is_horizontal = true;
};
struct vmtx : hmtxvmtx<vmtx, vhea> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
static constexpr bool is_horizontal = false;
};
struct hmtx_accelerator_t : hmtx::accelerator_t {};

View File

@ -1,7 +1,7 @@
/*
* Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
* Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
* Copyright © 2018 Google, Inc.
* Copyright © 2018 Ebrahim Byagowi
* Copyright © 2018-2019 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
@ -116,6 +116,8 @@ struct BaseCoordFormat3
struct BaseCoord
{
bool has_data () const { return u.format; }
hb_position_t get_coord (hb_font_t *font,
const VariationStore &var_store,
hb_direction_t direction) const
@ -142,10 +144,10 @@ struct BaseCoord
protected:
union {
HBUINT16 format;
BaseCoordFormat1 format1;
BaseCoordFormat2 format2;
BaseCoordFormat3 format3;
HBUINT16 format;
BaseCoordFormat1 format1;
BaseCoordFormat2 format2;
BaseCoordFormat3 format3;
} u;
public:
DEFINE_SIZE_UNION (2, format);
@ -153,14 +155,9 @@ struct BaseCoord
struct FeatMinMaxRecord
{
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
{
hb_tag_t key = * (hb_tag_t *) key_;
const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
return key < (unsigned int) entry.tag ? -1 :
key > (unsigned int) entry.tag ? 1 :
0;
}
int cmp (hb_tag_t key) const { return tag.cmp (key); }
bool has_data () const { return tag; }
void get_min_max (const BaseCoord **min, const BaseCoord **max) const
{
@ -195,17 +192,12 @@ struct FeatMinMaxRecord
struct MinMax
{
void get_min_max (hb_tag_t feature_tag,
const BaseCoord **min,
const BaseCoord **max) const
const BaseCoord **min,
const BaseCoord **max) const
{
/* TODO Replace hb_bsearch() with .bsearch(). */
const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *)
hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ,
featMinMaxRecords.len,
FeatMinMaxRecord::static_size,
FeatMinMaxRecord::cmp);
if (minMaxCoord)
minMaxCoord->get_min_max (min, max);
const FeatMinMaxRecord &minMaxCoord = featMinMaxRecords.bsearch (feature_tag);
if (minMaxCoord.has_data ())
minMaxCoord.get_min_max (min, max);
else
{
if (likely (min)) *min = &(this+minCoord);
@ -271,17 +263,11 @@ struct BaseValues
struct BaseLangSysRecord
{
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
{
hb_tag_t key = * (hb_tag_t *) key_;
const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
return key < (unsigned int) entry.baseLangSysTag ? -1 :
key > (unsigned int) entry.baseLangSysTag ? 1 :
0;
}
int cmp (hb_tag_t key) const { return baseLangSysTag.cmp (key); }
const MinMax &get_min_max () const
{ return this+minMax; }
bool has_data () const { return baseLangSysTag; }
const MinMax &get_min_max () const { return this+minMax; }
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
@ -303,19 +289,14 @@ struct BaseScript
{
const MinMax &get_min_max (hb_tag_t language_tag) const
{
/* TODO Replace hb_bsearch() with .bsearch(). */
const BaseLangSysRecord* record = (const BaseLangSysRecord *)
hb_bsearch (&language_tag, baseLangSysRecords.arrayZ,
baseLangSysRecords.len,
BaseLangSysRecord::static_size,
BaseLangSysRecord::cmp);
return record ? record->get_min_max () : this+defaultMinMax;
const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
return record.has_data () ? record.get_min_max () : this+defaultMinMax;
}
const BaseCoord &get_base_coord (int baseline_tag_index) const
{ return (this+baseValues).get_base_coord (baseline_tag_index); }
bool is_empty () const { return !baseValues; }
bool has_data () const { return baseValues; }
bool sanitize (hb_sanitize_context_t *c) const
{
@ -345,14 +326,9 @@ struct BaseScript
struct BaseScriptList;
struct BaseScriptRecord
{
HB_INTERNAL static int cmp (const void *key_, const void *entry_)
{
hb_tag_t key = * (hb_tag_t *) key_;
const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
return key < (unsigned int) entry.baseScriptTag ? -1 :
key > (unsigned int) entry.baseScriptTag ? 1 :
0;
}
int cmp (hb_tag_t key) const { return baseScriptTag.cmp (key); }
bool has_data () const { return baseScriptTag; }
const BaseScript &get_base_script (const BaseScriptList *list) const
{ return list+baseScript; }
@ -376,22 +352,11 @@ struct BaseScriptRecord
struct BaseScriptList
{
const BaseScriptRecord *find_record (hb_tag_t script) const
{
/* TODO Replace hb_bsearch() with .bsearch(). */
return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ,
baseScriptRecords.len,
BaseScriptRecord::static_size,
BaseScriptRecord::cmp);
}
/* TODO: Or client should handle fallback? */
const BaseScript &get_base_script (hb_tag_t script) const
{
const BaseScriptRecord *record = find_record (script);
if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T'));
return record ? record->get_base_script (this) : Null (BaseScript);
const BaseScriptRecord *record = &baseScriptRecords.bsearch (script);
if (!record->has_data ()) record = &baseScriptRecords.bsearch (HB_TAG ('D','F','L','T'));
return record->has_data () ? record->get_base_script (this) : Null (BaseScript);
}
bool sanitize (hb_sanitize_context_t *c) const
@ -412,14 +377,19 @@ struct BaseScriptList
struct Axis
{
bool get_baseline (hb_ot_layout_baseline_t baseline,
hb_tag_t script_tag,
hb_tag_t language_tag,
const BaseCoord **coord) const
hb_tag_t script_tag,
hb_tag_t language_tag,
const BaseCoord **coord) const
{
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
if (base_script.is_empty ()) return false;
if (!base_script.has_data ()) return false;
if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline));
if (likely (coord))
{
unsigned int tag_index = 0;
(this+baseTagList).bfind (baseline, &tag_index);
*coord = &base_script.get_base_coord (tag_index);
}
return true;
}
@ -431,7 +401,7 @@ struct Axis
const BaseCoord **max_coord) const
{
const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
if (base_script.is_empty ()) return false;
if (!base_script.has_data ()) return false;
base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);
@ -479,13 +449,14 @@ struct BASE
hb_tag_t language_tag,
hb_position_t *base) const
{
const BaseCoord *base_coord;
if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord))
const BaseCoord *base_coord = nullptr;
if (unlikely (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord) ||
!base_coord || !base_coord->has_data ()))
return false;
if (likely (base && base_coord)) *base = base_coord->get_coord (font,
get_var_store (),
direction);
if (likely (base))
*base = base_coord->get_coord (font, get_var_store (), direction);
return true;
}

View File

@ -733,7 +733,7 @@ struct PairPosFormat1
+ hb_zip (this+coverage, pairSet)
| hb_filter (*glyphs, hb_first)
| hb_map (hb_second)
| hb_map ([=] (const OffsetTo<PairSet> &_)
| hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
{ return (this+_).intersects (glyphs, valueFormat); })
| hb_any
;

View File

@ -248,7 +248,7 @@ struct SingleSubst
if (unlikely (!c->extend_min (u.format))) return_trace (false);
unsigned format = 2;
unsigned delta = 0;
if (glyphs.len ())
if (glyphs)
{
format = 1;
auto get_delta = [=] (hb_codepoint_pair_t _) {

View File

@ -43,7 +43,6 @@
#include "hb-map.hh"
#include "hb-ot-kern-table.hh"
#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
@ -1980,7 +1979,9 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n'),
_HB_OT_LAYOUT_BASELINE_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_t;

View File

@ -168,6 +168,17 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
return start;
}
static inline void
_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
}
/* unicode_props */
@ -551,6 +562,17 @@ _hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
}
static inline void
_hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
_hb_glyph_info_clear_substituted (&info[i]);
}
/* Allocation / deallocation. */

View File

@ -154,8 +154,8 @@ struct hb_ot_map_t
HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
template <typename Proxy>
HB_INTERNAL inline void apply (const Proxy &proxy,
const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
HB_INTERNAL void apply (const Proxy &proxy,
const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;

View File

@ -453,14 +453,14 @@ struct MathGlyphPartRecord
}
void extract (hb_ot_math_glyph_part_t &out,
int scale,
int64_t mult,
hb_font_t *font) const
{
out.glyph = glyph;
out.start_connector_length = font->em_scale (startConnectorLength, scale);
out.end_connector_length = font->em_scale (endConnectorLength, scale);
out.full_advance = font->em_scale (fullAdvance, scale);
out.start_connector_length = font->em_mult (startConnectorLength, mult);
out.end_connector_length = font->em_mult (endConnectorLength, mult);
out.full_advance = font->em_mult (fullAdvance, mult);
static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER ==
(unsigned int) PartFlags::Extender, "");
@ -508,11 +508,11 @@ struct MathGlyphAssembly
{
if (parts_count)
{
int scale = font->dir_scale (direction);
int64_t mult = font->dir_mult (direction);
hb_array_t<const MathGlyphPartRecord> arr = partRecords.sub_array (start_offset, parts_count);
unsigned int count = arr.length;
for (unsigned int i = 0; i < count; i++)
arr[i].extract (parts[i], scale, font);
arr[i].extract (parts[i], mult, font);
}
if (italics_correction)
@ -553,13 +553,13 @@ struct MathGlyphConstruction
{
if (variants_count)
{
int scale = font->dir_scale (direction);
int64_t mult = font->dir_mult (direction);
hb_array_t<const MathGlyphVariantRecord> arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
unsigned int count = arr.length;
for (unsigned int i = 0; i < count; i++)
{
variants[i].glyph = arr[i].variantGlyph;
variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
variants[i].advance = font->em_mult (arr[i].advanceMeasurement, mult);
}
}
return mathGlyphVariantRecord.len;

View File

@ -158,7 +158,7 @@ typedef enum { /*< flags >*/
* hb_ot_math_glyph_part_t:
* @glyph: The glyph index of the variant part
* @start_connector_length: The length of the connector on the starting side of the variant part
* @end_connection_length: The length of the connector on the ending side of the variant part
* @end_connector_length: The length of the connector on the ending side of the variant part
* @full_advance: The total advance of the part
* @flags: #hb_ot_math_glyph_part_flags_t flags for the part
*

124
src/hb-ot-meta-table.hh Normal file
View File

@ -0,0 +1,124 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_OT_META_TABLE_HH
#define HB_OT_META_TABLE_HH
#include "hb-open-type.hh"
/*
* meta -- Metadata Table
* https://docs.microsoft.com/en-us/typography/opentype/spec/meta
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html
*/
#define HB_OT_TAG_meta HB_TAG ('m','e','t','a')
namespace OT {
struct DataMap
{
int cmp (hb_tag_t a) const { return tag.cmp (a); }
hb_tag_t get_tag () const { return tag; }
hb_blob_t *reference_entry (hb_blob_t *meta_blob) const
{ return hb_blob_create_sub_blob (meta_blob, dataZ, dataLength); }
bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
dataZ.sanitize (c, base, dataLength)));
}
protected:
Tag tag; /* A tag indicating the type of metadata. */
LOffsetTo<UnsizedArrayOf<HBUINT8>>
dataZ; /* Offset in bytes from the beginning of the
* metadata table to the data for this tag. */
HBUINT32 dataLength; /* Length of the data. The data is not required to
* be padded to any byte boundary. */
public:
DEFINE_SIZE_STATIC (12);
};
struct meta
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_meta;
struct accelerator_t
{
void init (hb_face_t *face)
{ table = hb_sanitize_context_t ().reference_table<meta> (face); }
void fini () { table.destroy (); }
hb_blob_t *reference_entry (hb_tag_t tag) const
{ return table->dataMaps.lsearch (tag).reference_entry (table.get_blob ()); }
unsigned int get_entries (unsigned int start_offset,
unsigned int *count,
hb_ot_meta_tag_t *entries) const
{
if (count)
{
hb_array_t<const DataMap> arr = table->dataMaps.sub_array (start_offset, count);
for (unsigned int i = 0; i < arr.length; i++)
entries[i] = (hb_ot_meta_tag_t) arr[i].get_tag ();
}
return table->dataMaps.len;
}
private:
hb_blob_ptr_t<meta> table;
};
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
version == 1 &&
dataMaps.sanitize (c, this)));
}
protected:
HBUINT32 version; /* Version number of the metadata table — set to 1. */
HBUINT32 flags; /* Flags — currently unused; set to 0. */
HBUINT32 dataOffset; /* Per Apple specification:
* Offset from the beginning of the table to the data.
* Per OT specification:
* Reserved. Not used; should be set to 0. */
LArrayOf<DataMap>
dataMaps; /* Array of data map records. */
public:
DEFINE_SIZE_ARRAY (16, dataMaps);
};
struct meta_accelerator_t : meta::accelerator_t {};
} /* namespace OT */
#endif /* HB_OT_META_TABLE_HH */

77
src/hb-ot-meta.cc Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#include "hb.hh"
#ifndef HB_NO_META
#include "hb-ot-meta-table.hh"
/**
* SECTION:hb-ot-meta
* @title: hb-ot-meta
* @short_description: OpenType Metadata
* @include: hb-ot.h
*
* Functions for fetching metadata from fonts.
**/
/**
* hb_ot_meta_reference_entry:
* @face: a face object
* @start_offset: iteration's start offset
* @entries_count:(inout) (allow-none): buffer size as input, filled size as output
* @entries: (out caller-allocates) (array length=entries_count): entries tags buffer
*
* Return value: Number of all available feature types.
*
* Since: REPLACEME
**/
unsigned int
hb_ot_meta_get_entries (hb_face_t *face,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT. May be NULL. */
hb_ot_meta_tag_t *entries /* OUT. May be NULL. */)
{
return face->table.meta->get_entries (start_offset, entries_count, entries);
}
/**
* hb_ot_meta_reference_entry:
* @face: a #hb_face_t object.
* @meta_tag: tag of metadata you like to have.
*
* It fetches metadata entry of a given tag from a font.
*
* Returns: (transfer full): A blob containing the blob.
*
* Since: REPLACEME
**/
hb_blob_t *
hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag)
{
return face->table.meta->reference_entry (meta_tag);
}
#endif

65
src/hb-ot-meta.h Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_OT_H_IN
#error "Include <hb-ot.h> instead."
#endif
#ifndef HB_OT_META_H
#define HB_OT_META_H
#include "hb.h"
HB_BEGIN_DECLS
/**
* hb_ot_meta_tag_t:
*
* From https://docs.microsoft.com/en-us/typography/opentype/spec/meta
*
* Since: REPLACEME
**/
typedef enum {
/*
HB_OT_META_APPL = HB_TAG ('a','p','p','l'),
HB_OT_META_BILD = HB_TAG ('b','i','l','d'),
*/
HB_OT_META_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'),
HB_OT_META_SUPPORTED_LANGUAGES= HB_TAG ('s','l','n','g'),
_HB_OT_META_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_meta_tag_t;
HB_EXTERN unsigned int
hb_ot_meta_get_entries (hb_face_t *face,
unsigned int start_offset,
unsigned int *entries_count, /* IN/OUT. May be NULL. */
hb_ot_meta_tag_t *entries /* OUT. May be NULL. */);
HB_EXTERN hb_blob_t *
hb_ot_meta_reference_entry (hb_face_t *face, hb_ot_meta_tag_t meta_tag);
HB_END_DECLS
#endif /* HB_OT_META_H */

231
src/hb-ot-metrics.cc Normal file
View File

@ -0,0 +1,231 @@
/*
* Copyright © 2018-2019 Ebrahim Byagowi
*
* 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.
*/
#include "hb.hh"
#include "hb-ot-var-mvar-table.hh"
#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-os2-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-metrics.hh"
#include "hb-ot-face.hh"
static float
_fix_ascender_descender (float value, hb_ot_metrics_tag_t metrics_tag)
{
if (metrics_tag == HB_OT_METRICS_HORIZONTAL_ASCENDER ||
metrics_tag == HB_OT_METRICS_VERTICAL_ASCENDER)
return fabs ((double) value);
if (metrics_tag == HB_OT_METRICS_HORIZONTAL_DESCENDER ||
metrics_tag == HB_OT_METRICS_VERTICAL_DESCENDER)
return -fabs ((double) value);
return value;
}
/* The common part of _get_position logic needed on hb-ot-font and here
to be able to have slim builds without the not always needed parts */
bool
_hb_ot_metrics_get_position_common (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */)
{
hb_face_t *face = font->face;
switch ((unsigned) metrics_tag)
{
#ifndef HB_NO_VAR
#define GET_VAR face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords)
#else
#define GET_VAR .0f
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
(position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
(position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
case HB_OT_METRICS_HORIZONTAL_ASCENDER:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
GET_METRIC_Y (hhea, ascender);
case HB_OT_METRICS_HORIZONTAL_DESCENDER:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoDescender)) ||
GET_METRIC_Y (hhea, descender);
case HB_OT_METRICS_HORIZONTAL_LINE_GAP:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoLineGap)) ||
GET_METRIC_Y (hhea, lineGap);
case HB_OT_METRICS_VERTICAL_ASCENDER: return GET_METRIC_X (vhea, ascender);
case HB_OT_METRICS_VERTICAL_DESCENDER: return GET_METRIC_X (vhea, descender);
case HB_OT_METRICS_VERTICAL_LINE_GAP: return GET_METRIC_X (vhea, lineGap);
#undef GET_METRIC_Y
#undef GET_METRIC_X
#undef GET_VAR
default: assert (0); return false;
}
}
#ifndef HB_NO_METRICS
#if 0
static bool
_get_gasp (hb_face_t *face, float *result, hb_ot_metrics_tag_t metrics_tag)
{
const OT::GaspRange& range = face->table.gasp->get_gasp_range (metrics_tag - HB_TAG ('g','s','p','0'));
if (&range == &Null (OT::GaspRange)) return false;
if (result) *result = range.rangeMaxPPEM + font->face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords);
return true;
}
#endif
/* Private tags for https://github.com/harfbuzz/harfbuzz/issues/1866 */
#define _HB_OT_METRICS_HORIZONTAL_ASCENDER_OS2 HB_TAG ('O','a','s','c')
#define _HB_OT_METRICS_HORIZONTAL_ASCENDER_HHEA HB_TAG ('H','a','s','c')
#define _HB_OT_METRICS_HORIZONTAL_DESCENDER_OS2 HB_TAG ('O','d','s','c')
#define _HB_OT_METRICS_HORIZONTAL_DESCENDER_HHEA HB_TAG ('H','d','s','c')
#define _HB_OT_METRICS_HORIZONTAL_LINE_GAP_OS2 HB_TAG ('O','l','g','p')
#define _HB_OT_METRICS_HORIZONTAL_LINE_GAP_HHEA HB_TAG ('H','l','g','p')
/**
* hb_ot_metrics_get_position:
* @font: a #hb_font_t object.
* @metrics_tag: tag of metrics value you like to fetch.
* @position: (out) (optional): result of metrics value from the font.
*
* It fetches metrics value corresponding to a given tag from a font.
*
* Returns: Whether found the requested metrics in the font.
* Since: REPLACEME
**/
hb_bool_t
hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */)
{
hb_face_t *face = font->face;
switch ((unsigned) metrics_tag)
{
case HB_OT_METRICS_HORIZONTAL_ASCENDER:
case HB_OT_METRICS_HORIZONTAL_DESCENDER:
case HB_OT_METRICS_HORIZONTAL_LINE_GAP:
case HB_OT_METRICS_VERTICAL_ASCENDER:
case HB_OT_METRICS_VERTICAL_DESCENDER:
case HB_OT_METRICS_VERTICAL_LINE_GAP: return _hb_ot_metrics_get_position_common (font, metrics_tag, position);
#ifndef HB_NO_VAR
#define GET_VAR hb_ot_metrics_get_variation (font, metrics_tag)
#else
#define GET_VAR 0
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
(position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
(position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
case HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
case HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
case HB_OT_METRICS_HORIZONTAL_CARET_RISE: return GET_METRIC_Y (hhea, caretSlopeRise);
case HB_OT_METRICS_HORIZONTAL_CARET_RUN: return GET_METRIC_X (hhea, caretSlopeRun);
case HB_OT_METRICS_HORIZONTAL_CARET_OFFSET: return GET_METRIC_X (hhea, caretOffset);
case HB_OT_METRICS_VERTICAL_CARET_RISE: return GET_METRIC_X (vhea, caretSlopeRise);
case HB_OT_METRICS_VERTICAL_CARET_RUN: return GET_METRIC_Y (vhea, caretSlopeRun);
case HB_OT_METRICS_VERTICAL_CARET_OFFSET: return GET_METRIC_Y (vhea, caretOffset);
case HB_OT_METRICS_X_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sxHeight);
case HB_OT_METRICS_CAP_HEIGHT: return GET_METRIC_Y (OS2->v2 (), sCapHeight);
case HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySubscriptXSize);
case HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE: return GET_METRIC_Y (OS2, ySubscriptYSize);
case HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET: return GET_METRIC_X (OS2, ySubscriptXOffset);
case HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET: return GET_METRIC_Y (OS2, ySubscriptYOffset);
case HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE: return GET_METRIC_X (OS2, ySuperscriptXSize);
case HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE: return GET_METRIC_Y (OS2, ySuperscriptYSize);
case HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET: return GET_METRIC_X (OS2, ySuperscriptXOffset);
case HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET: return GET_METRIC_Y (OS2, ySuperscriptYOffset);
case HB_OT_METRICS_STRIKEOUT_SIZE: return GET_METRIC_Y (OS2, yStrikeoutSize);
case HB_OT_METRICS_STRIKEOUT_OFFSET: return GET_METRIC_Y (OS2, yStrikeoutPosition);
case HB_OT_METRICS_UNDERLINE_SIZE: return GET_METRIC_Y (post->table, underlineThickness);
case HB_OT_METRICS_UNDERLINE_OFFSET: return GET_METRIC_Y (post->table, underlinePosition);
/* Private tags */
case _HB_OT_METRICS_HORIZONTAL_ASCENDER_OS2: return GET_METRIC_Y (OS2, sTypoAscender);
case _HB_OT_METRICS_HORIZONTAL_ASCENDER_HHEA: return GET_METRIC_Y (hhea, ascender);
case _HB_OT_METRICS_HORIZONTAL_DESCENDER_OS2: return GET_METRIC_Y (OS2, sTypoDescender);
case _HB_OT_METRICS_HORIZONTAL_DESCENDER_HHEA: return GET_METRIC_Y (hhea, descender);
case _HB_OT_METRICS_HORIZONTAL_LINE_GAP_OS2: return GET_METRIC_Y (OS2, sTypoLineGap);
case _HB_OT_METRICS_HORIZONTAL_LINE_GAP_HHEA: return GET_METRIC_Y (hhea, lineGap);
#undef GET_METRIC_Y
#undef GET_METRIC_X
#undef GET_VAR
default: return false;
}
}
#ifndef HB_NO_VAR
/**
* hb_ot_metrics_get_variation:
* @font:
* @metrics_tag:
*
* Returns:
*
* Since: REPLACEME
**/
float
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
{
return font->face->table.MVAR->get_var (metrics_tag, font->coords, font->num_coords);
}
/**
* hb_ot_metrics_get_x_variation:
* @font:
* @metrics_tag:
*
* Returns:
*
* Since: REPLACEME
**/
hb_position_t
hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
{
return font->em_scalef_x (hb_ot_metrics_get_variation (font, metrics_tag));
}
/**
* hb_ot_metrics_get_y_variation:
* @font:
* @metrics_tag:
*
* Returns:
*
* Since: REPLACEME
**/
hb_position_t
hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag)
{
return font->em_scalef_y (hb_ot_metrics_get_variation (font, metrics_tag));
}
#endif
#endif

94
src/hb-ot-metrics.h Normal file
View File

@ -0,0 +1,94 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_OT_H_IN
#error "Include <hb-ot.h> instead."
#endif
#ifndef HB_OT_METRICS_H
#define HB_OT_METRICS_H
#include "hb.h"
#include "hb-ot-name.h"
HB_BEGIN_DECLS
/**
* hb_ot_metrics_tag_t:
*
* From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags
*
* Since: REPLACEME
**/
typedef enum {
HB_OT_METRICS_HORIZONTAL_ASCENDER = HB_TAG ('h','a','s','c'),
HB_OT_METRICS_HORIZONTAL_DESCENDER = HB_TAG ('h','d','s','c'),
HB_OT_METRICS_HORIZONTAL_LINE_GAP = HB_TAG ('h','l','g','p'),
HB_OT_METRICS_HORIZONTAL_CLIPPING_ASCENT = HB_TAG ('h','c','l','a'),
HB_OT_METRICS_HORIZONTAL_CLIPPING_DESCENT = HB_TAG ('h','c','l','d'),
HB_OT_METRICS_VERTICAL_ASCENDER = HB_TAG ('v','a','s','c'),
HB_OT_METRICS_VERTICAL_DESCENDER = HB_TAG ('v','d','s','c'),
HB_OT_METRICS_VERTICAL_LINE_GAP = HB_TAG ('v','l','g','p'),
HB_OT_METRICS_HORIZONTAL_CARET_RISE = HB_TAG ('h','c','r','s'),
HB_OT_METRICS_HORIZONTAL_CARET_RUN = HB_TAG ('h','c','r','n'),
HB_OT_METRICS_HORIZONTAL_CARET_OFFSET = HB_TAG ('h','c','o','f'),
HB_OT_METRICS_VERTICAL_CARET_RISE = HB_TAG ('v','c','r','s'),
HB_OT_METRICS_VERTICAL_CARET_RUN = HB_TAG ('v','c','r','n'),
HB_OT_METRICS_VERTICAL_CARET_OFFSET = HB_TAG ('v','c','o','f'),
HB_OT_METRICS_X_HEIGHT = HB_TAG ('x','h','g','t'),
HB_OT_METRICS_CAP_HEIGHT = HB_TAG ('c','p','h','t'),
HB_OT_METRICS_SUBSCRIPT_EM_X_SIZE = HB_TAG ('s','b','x','s'),
HB_OT_METRICS_SUBSCRIPT_EM_Y_SIZE = HB_TAG ('s','b','y','s'),
HB_OT_METRICS_SUBSCRIPT_EM_X_OFFSET = HB_TAG ('s','b','x','o'),
HB_OT_METRICS_SUBSCRIPT_EM_Y_OFFSET = HB_TAG ('s','b','y','o'),
HB_OT_METRICS_SUPERSCRIPT_EM_X_SIZE = HB_TAG ('s','p','x','s'),
HB_OT_METRICS_SUPERSCRIPT_EM_Y_SIZE = HB_TAG ('s','p','y','s'),
HB_OT_METRICS_SUPERSCRIPT_EM_X_OFFSET = HB_TAG ('s','p','x','o'),
HB_OT_METRICS_SUPERSCRIPT_EM_Y_OFFSET = HB_TAG ('s','p','y','o'),
HB_OT_METRICS_STRIKEOUT_SIZE = HB_TAG ('s','t','r','s'),
HB_OT_METRICS_STRIKEOUT_OFFSET = HB_TAG ('s','t','r','o'),
HB_OT_METRICS_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'),
HB_OT_METRICS_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o'),
_HB_OT_METRICS_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_metrics_tag_t;
HB_EXTERN hb_bool_t
hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
HB_EXTERN float
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
HB_EXTERN hb_position_t
hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
HB_EXTERN hb_position_t
hb_ot_metrics_get_y_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
HB_END_DECLS
#endif /* HB_OT_METRICS_H */

35
src/hb-ot-metrics.hh Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* 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.
*/
#ifndef HB_OT_METRICS_HH
#define HB_OT_METRICS_HH
#include "hb.hh"
HB_INTERNAL bool
_hb_ot_metrics_get_position_common (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
#endif /* HB_OT_METRICS_HH */

View File

@ -59,6 +59,10 @@ struct OS2V1Tail
struct OS2V2Tail
{
bool has_data () const { return this != &Null (OS2V2Tail); }
const OS2V2Tail * operator -> () const { return this; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -113,9 +117,9 @@ struct OS2
OBLIQUE = 1u<<9
};
bool is_italic () const { return fsSelection & ITALIC; }
bool is_oblique () const { return fsSelection & OBLIQUE; }
bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
bool is_italic () const { return fsSelection & ITALIC; }
bool is_oblique () const { return fsSelection & OBLIQUE; }
bool use_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
enum width_class_t {
FWIDTH_ULTRA_CONDENSED = 1, /* 50% */
@ -192,13 +196,14 @@ struct OS2
}
static void find_min_and_max_codepoint (const hb_set_t *codepoints,
uint16_t *min_cp, /* OUT */
uint16_t *max_cp /* OUT */)
uint16_t *min_cp, /* OUT */
uint16_t *max_cp /* OUT */)
{
*min_cp = codepoints->get_min ();
*max_cp = codepoints->get_max ();
}
/* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */
enum font_page_t {
HEBREW_FONT_PAGE = 0xB100, // Hebrew Windows 3.1 font page
SIMP_ARABIC_FONT_PAGE = 0xB200, // Simplified Arabic Windows 3.1 font page
@ -208,8 +213,6 @@ struct OS2
TRAD_FARSI_FONT_PAGE = 0xBB00, // Traditional Farsi Windows 3.1 font page
THAI_FONT_PAGE = 0xDE00 // Thai Windows 3.1 font page
};
// https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
font_page_t get_font_page () const
{ return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }

View File

@ -178,6 +178,8 @@ struct post
return false;
}
hb_blob_ptr_t<post> table;
protected:
unsigned int get_glyph_count () const
@ -237,7 +239,6 @@ struct post
}
private:
hb_blob_ptr_t<post> table;
uint32_t version;
const ArrayOf<HBUINT16> *glyphNameIndex;
hb_vector_t<uint32_t> index_to_offset;
@ -245,6 +246,8 @@ struct post
hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
};
bool has_data () const { return version.to_int (); }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -395,13 +395,13 @@ static const int indic_syllable_machine_en_main = 39;
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_indic (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act;
int cs;
@ -569,4 +569,6 @@ _again:
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */

View File

@ -96,13 +96,13 @@ main := |*
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_indic (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act;
int cs;
@ -121,4 +121,6 @@ find_syllables (hb_buffer_t *buffer)
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */

View File

@ -144,49 +144,45 @@ indic_features[] =
* Must be in the same order as the indic_features array.
*/
enum {
_NUKT,
_AKHN,
RPHF,
_RKRF,
PREF,
BLWF,
ABVF,
HALF,
PSTF,
_VATU,
_CJCT,
_INDIC_NUKT,
_INDIC_AKHN,
INDIC_RPHF,
_INDIC_RKRF,
INDIC_PREF,
INDIC_BLWF,
INDIC_ABVF,
INDIC_HALF,
INDIC_PSTF,
_INDIC_VATU,
_INDIC_CJCT,
INIT,
_PRES,
_ABVS,
_BLWS,
_PSTS,
_HALN,
INDIC_INIT,
_INDIC_PRES,
_INDIC_ABVS,
_INDIC_BLWS,
_INDIC_PSTS,
_INDIC_HALN,
_DIST,
_ABVM,
_BLWM,
_INDIC_DIST,
_INDIC_ABVM,
_INDIC_BLWM,
INDIC_NUM_FEATURES,
INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
setup_syllables_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
final_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_indic (hb_ot_shape_planner_t *plan)
@ -194,7 +190,7 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_gsub_pause (setup_syllables_indic);
map->enable_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
@ -203,14 +199,14 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
unsigned int i = 0;
map->add_gsub_pause (initial_reordering);
map->add_gsub_pause (initial_reordering_indic);
for (; i < INDIC_BASIC_FEATURES; i++) {
map->add_feature (indic_features[i]);
map->add_gsub_pause (nullptr);
}
map->add_gsub_pause (final_reordering);
map->add_gsub_pause (final_reordering_indic);
for (; i < INDIC_NUM_FEATURES; i++)
map->add_feature (indic_features[i]);
@ -218,7 +214,7 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
map->enable_feature (HB_TAG('c','a','l','t'));
map->enable_feature (HB_TAG('c','l','i','g'));
map->add_gsub_pause (clear_syllables);
map->add_gsub_pause (_hb_clear_syllables);
}
static void
@ -228,32 +224,6 @@ override_features_indic (hb_ot_shape_planner_t *plan)
}
struct would_substitute_feature_t
{
void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
{
zero_context = zero_context_;
map->get_stage_lookups (0/*GSUB*/,
map->get_feature_stage (0/*GSUB*/, feature_tag),
&lookups, &count);
}
bool would_substitute (const hb_codepoint_t *glyphs,
unsigned int glyphs_count,
hb_face_t *face) const
{
for (unsigned int i = 0; i < count; i++)
if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
return true;
return false;
}
private:
const hb_ot_map_t::lookup_map_t *lookups;
unsigned int count;
bool zero_context;
};
struct indic_shape_plan_t
{
bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
@ -285,10 +255,10 @@ struct indic_shape_plan_t
#endif
mutable hb_atomic_int_t virama_glyph;
would_substitute_feature_t rphf;
would_substitute_feature_t pref;
would_substitute_feature_t blwf;
would_substitute_feature_t pstf;
hb_indic_would_substitute_feature_t rphf;
hb_indic_would_substitute_feature_t pref;
hb_indic_would_substitute_feature_t blwf;
hb_indic_would_substitute_feature_t pstf;
hb_mask_t mask_array[INDIC_NUM_FEATURES];
};
@ -371,13 +341,13 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan,
}
enum syllable_type_t {
consonant_syllable,
vowel_syllable,
standalone_cluster,
symbol_cluster,
broken_cluster,
non_indic_cluster,
enum indic_syllable_type_t {
indic_consonant_syllable,
indic_vowel_syllable,
indic_standalone_cluster,
indic_symbol_cluster,
indic_broken_cluster,
indic_non_indic_cluster,
};
#include "hb-ot-shape-complex-indic-machine.hh"
@ -401,11 +371,11 @@ setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
find_syllables_indic (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
}
@ -422,9 +392,9 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
static void
update_consonant_positions (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
@ -497,7 +467,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* and has more than one consonant, Ra is excluded from candidates for
* base consonants. */
unsigned int limit = start;
if (indic_plan->mask_array[RPHF] &&
if (indic_plan->mask_array[INDIC_RPHF] &&
start + 3 <= end &&
(
(indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
@ -833,13 +803,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Reph */
for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
info[i].mask |= indic_plan->mask_array[RPHF];
info[i].mask |= indic_plan->mask_array[INDIC_RPHF];
/* Pre-base */
mask = indic_plan->mask_array[HALF];
mask = indic_plan->mask_array[INDIC_HALF];
if (!indic_plan->is_old_spec &&
indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST)
mask |= indic_plan->mask_array[BLWF];
mask |= indic_plan->mask_array[INDIC_BLWF];
for (unsigned int i = start; i < base; i++)
info[i].mask |= mask;
/* Base */
@ -847,7 +817,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (base < end)
info[base].mask |= mask;
/* Post-base */
mask = indic_plan->mask_array[BLWF] | indic_plan->mask_array[ABVF] | indic_plan->mask_array[PSTF];
mask = indic_plan->mask_array[INDIC_BLWF] |
indic_plan->mask_array[INDIC_ABVF] |
indic_plan->mask_array[INDIC_PSTF];
for (unsigned int i = base + 1; i < end; i++)
info[i].mask |= mask;
}
@ -879,13 +851,13 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
(i + 2 == base ||
info[i+2].indic_category() != OT_ZWJ))
{
info[i ].mask |= indic_plan->mask_array[BLWF];
info[i+1].mask |= indic_plan->mask_array[BLWF];
info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
}
}
unsigned int pref_len = 2;
if (indic_plan->mask_array[PREF] && base + pref_len < end)
if (indic_plan->mask_array[INDIC_PREF] && base + pref_len < end)
{
/* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
@ -895,7 +867,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
{
for (unsigned int j = 0; j < pref_len; j++)
info[i++].mask |= indic_plan->mask_array[PREF];
info[i++].mask |= indic_plan->mask_array[INDIC_PREF];
break;
}
}
@ -916,7 +888,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* A ZWNJ disables HALF. */
if (non_joiner)
info[j].mask &= ~indic_plan->mask_array[HALF];
info[j].mask &= ~indic_plan->mask_array[INDIC_HALF];
} while (j > start && !is_consonant (info[j]));
}
@ -945,34 +917,34 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type)
{
case vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
case consonant_syllable:
case indic_vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
case indic_consonant_syllable:
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
break;
case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
case standalone_cluster:
case indic_broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
case indic_standalone_cluster:
initial_reordering_standalone_cluster (plan, face, buffer, start, end);
break;
case symbol_cluster:
case non_indic_cluster:
case indic_symbol_cluster:
case indic_non_indic_cluster:
break;
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
@ -983,7 +955,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_cluster)
if ((info[i].syllable() & 0x0F) == indic_broken_cluster)
{
has_broken_syllables = true;
break;
@ -1008,8 +980,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster))
{
last_syllable = syllable;
@ -1033,21 +1005,21 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
initial_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
initial_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
update_consonant_positions (plan, font, buffer);
insert_dotted_circles (plan, font, buffer);
update_consonant_positions_indic (plan, font, buffer);
insert_dotted_circles_indic (plan, font, buffer);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
}
static void
final_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
hb_glyph_info_t *info = buffer->info;
@ -1083,7 +1055,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* syllable.
*/
bool try_pref = !!indic_plan->mask_array[PREF];
bool try_pref = !!indic_plan->mask_array[INDIC_PREF];
/* Find base again */
unsigned int base;
@ -1093,7 +1065,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (try_pref && base + 1 < end)
{
for (unsigned int i = base + 1; i < end; i++)
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
{
if (!(_hb_glyph_info_substituted (&info[i]) &&
_hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
@ -1415,7 +1387,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
{
for (unsigned int i = base + 1; i < end; i++)
if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
{
/* 1. Only reorder a glyph produced by substitution during application
* of the <pref> feature. (Note that a font may shape a Ra consonant with
@ -1478,7 +1450,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (!start ||
!(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
info[start].mask |= indic_plan->mask_array[INIT];
info[start].mask |= indic_plan->mask_array[INDIC_INIT];
else
buffer->unsafe_to_break (start - 1, start + 1);
}
@ -1508,33 +1480,21 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
static void
final_reordering (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
final_reordering_indic (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
if (unlikely (!count)) return;
foreach_syllable (buffer, start, end)
final_reordering_syllable (plan, buffer, start, end);
final_reordering_syllable_indic (plan, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
}
static void
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
}
static void
preprocess_text_indic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,

View File

@ -64,7 +64,14 @@ enum indic_category_t {
OT_Ra = 16,
OT_CM = 17, /* Consonant-Medial. */
OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
OT_CS = 19
OT_CS = 19,
/* The following are used by Khmer & Myanmar shapers. Defined
* here for them to share. */
OT_VAbv = 26,
OT_VBlw = 27,
OT_VPre = 28,
OT_VPst = 29,
};
#define MEDIAL_FLAGS (FLAG (OT_CM))
@ -398,5 +405,31 @@ set_indic_properties (hb_glyph_info_t &info)
info.indic_position() = pos;
}
struct hb_indic_would_substitute_feature_t
{
void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
{
zero_context = zero_context_;
map->get_stage_lookups (0/*GSUB*/,
map->get_feature_stage (0/*GSUB*/, feature_tag),
&lookups, &count);
}
bool would_substitute (const hb_codepoint_t *glyphs,
unsigned int glyphs_count,
hb_face_t *face) const
{
for (unsigned int i = 0; i < count; i++)
if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
return true;
return false;
}
private:
const hb_ot_map_t::lookup_map_t *lookups;
unsigned int count;
bool zero_context;
};
#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */

View File

@ -226,13 +226,13 @@ static const int khmer_syllable_machine_en_main = 20;
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_khmer (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
int cs;
@ -367,4 +367,6 @@ _again:
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */

View File

@ -83,13 +83,13 @@ main := |*
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_khmer (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
int cs;
@ -108,4 +108,6 @@ find_syllables (hb_buffer_t *buffer)
}%%
}
#undef found_syllable
#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */

View File

@ -69,37 +69,33 @@ khmer_features[] =
* Must be in the same order as the khmer_features array.
*/
enum {
PREF,
BLWF,
ABVF,
PSTF,
CFAR,
KHMER_PREF,
KHMER_BLWF,
KHMER_ABVF,
KHMER_PSTF,
KHMER_CFAR,
_PRES,
_ABVS,
_BLWS,
_PSTS,
_KHMER_PRES,
_KHMER_ABVS,
_KHMER_BLWS,
_KHMER_PSTS,
_DIST,
_ABVM,
_BLWM,
_KHMER_DIST,
_KHMER_ABVM,
_KHMER_BLWM,
KHMER_NUM_FEATURES,
KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */
KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_khmer (hb_ot_shape_planner_t *plan)
@ -107,8 +103,8 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_gsub_pause (reorder);
map->add_gsub_pause (setup_syllables_khmer);
map->add_gsub_pause (reorder_khmer);
/* Testing suggests that Uniscribe does NOT pause between basic
* features. Test with KhmerUI.ttf and the following three
@ -127,7 +123,7 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
for (; i < KHMER_BASIC_FEATURES; i++)
map->add_feature (khmer_features[i]);
map->add_gsub_pause (clear_syllables);
map->add_gsub_pause (_hb_clear_syllables);
for (; i < KHMER_NUM_FEATURES; i++)
map->add_feature (khmer_features[i]);
@ -153,32 +149,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan)
}
struct would_substitute_feature_t
{
void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
{
zero_context = zero_context_;
map->get_stage_lookups (0/*GSUB*/,
map->get_feature_stage (0/*GSUB*/, feature_tag),
&lookups, &count);
}
bool would_substitute (const hb_codepoint_t *glyphs,
unsigned int glyphs_count,
hb_face_t *face) const
{
for (unsigned int i = 0; i < count; i++)
if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
return true;
return false;
}
private:
const hb_ot_map_t::lookup_map_t *lookups;
unsigned int count;
bool zero_context;
};
struct khmer_shape_plan_t
{
bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
@ -202,7 +172,7 @@ struct khmer_shape_plan_t
mutable hb_codepoint_t virama_glyph;
would_substitute_feature_t pref;
hb_indic_would_substitute_feature_t pref;
hb_mask_t mask_array[KHMER_NUM_FEATURES];
};
@ -232,10 +202,10 @@ data_destroy_khmer (void *data)
}
enum syllable_type_t {
consonant_syllable,
broken_cluster,
non_khmer_cluster,
enum khmer_syllable_type_t {
khmer_consonant_syllable,
khmer_broken_cluster,
khmer_non_khmer_cluster,
};
#include "hb-ot-shape-complex-khmer-machine.hh"
@ -257,11 +227,11 @@ setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
find_syllables_khmer (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
}
@ -282,7 +252,9 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Setup masks. */
{
/* Post-base */
hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
hb_mask_t mask = khmer_plan->mask_array[KHMER_BLWF] |
khmer_plan->mask_array[KHMER_ABVF] |
khmer_plan->mask_array[KHMER_PSTF];
for (unsigned int i = start + 1; i < end; i++)
info[i].mask |= mask;
}
@ -309,7 +281,7 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (info[i + 1].khmer_category() == OT_Ra)
{
for (unsigned int j = 0; j < 2; j++)
info[i + j].mask |= khmer_plan->mask_array[PREF];
info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF];
/* Move the Coeng,Ro sequence to the start. */
buffer->merge_clusters (start, i + 2);
@ -325,9 +297,9 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
* U+1784,U+17D2,U+179A,U+17D2,U+1782
* U+1784,U+17D2,U+1782,U+17D2,U+179A
*/
if (khmer_plan->mask_array[CFAR])
if (khmer_plan->mask_array[KHMER_CFAR])
for (unsigned int j = i + 2; j < end; j++)
info[j].mask |= khmer_plan->mask_array[CFAR];
info[j].mask |= khmer_plan->mask_array[KHMER_CFAR];
num_coengs = 2; /* Done. */
}
@ -346,28 +318,28 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
hb_face_t *face,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type)
{
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case consonant_syllable:
case khmer_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case khmer_consonant_syllable:
reorder_consonant_syllable (plan, face, buffer, start, end);
break;
case non_khmer_cluster:
case khmer_non_khmer_cluster:
break;
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
insert_dotted_circles_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
@ -378,7 +350,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_cluster)
if ((info[i].syllable() & 0x0F) == khmer_broken_cluster)
{
has_broken_syllables = true;
break;
@ -403,8 +375,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == khmer_broken_cluster))
{
last_syllable = syllable;
@ -428,29 +400,18 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
reorder_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
insert_dotted_circles_khmer (plan, font, buffer);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
reorder_syllable_khmer (plan, font->face, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
}
static void
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
}
static bool
decompose_khmer (const hb_ot_shape_normalize_context_t *c,

View File

@ -43,11 +43,10 @@ enum khmer_category_t
OT_Robatic = 20,
OT_Xgroup = 21,
OT_Ygroup = 22,
OT_VAbv = 26,
OT_VBlw = 27,
OT_VPre = 28,
OT_VPst = 29,
//OT_VAbv = 26,
//OT_VBlw = 27,
//OT_VPre = 28,
//OT_VPst = 29,
};
static inline void
@ -100,10 +99,10 @@ set_khmer_properties (hb_glyph_info_t &info)
if (cat == (khmer_category_t) OT_M)
switch ((int) pos)
{
case POS_PRE_C: cat = OT_VPre; break;
case POS_BELOW_C: cat = OT_VBlw; break;
case POS_ABOVE_C: cat = OT_VAbv; break;
case POS_POST_C: cat = OT_VPst; break;
case POS_PRE_C: cat = (khmer_category_t) OT_VPre; break;
case POS_BELOW_C: cat = (khmer_category_t) OT_VBlw; break;
case POS_ABOVE_C: cat = (khmer_category_t) OT_VAbv; break;
case POS_POST_C: cat = (khmer_category_t) OT_VPst; break;
default: assert (0);
}

View File

@ -304,13 +304,13 @@ static const int myanmar_syllable_machine_en_main = 0;
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_myanmar (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
int cs;

View File

@ -97,13 +97,13 @@ main := |*
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_myanmar (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act HB_UNUSED;
int cs;

View File

@ -36,7 +36,7 @@
*/
static const hb_tag_t
basic_features[] =
myanmar_basic_features[] =
{
/*
* Basic features.
@ -48,7 +48,7 @@ basic_features[] =
HB_TAG('p','s','t','f'),
};
static const hb_tag_t
other_features[] =
myanmar_other_features[] =
{
/*
* Other features.
@ -60,7 +60,7 @@ other_features[] =
HB_TAG('p','s','t','s'),
};
static const hb_tag_t
positioning_features[] =
myanmar_positioning_features[] =
{
/*
* Positioning features.
@ -80,15 +80,11 @@ positioning_features[] =
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_syllables (const hb_ot_shape_plan_t *plan,
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
@ -98,7 +94,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_gsub_pause (setup_syllables_myanmar);
map->enable_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
@ -106,21 +102,21 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
map->enable_feature (HB_TAG('c','c','m','p'));
map->add_gsub_pause (reorder);
map->add_gsub_pause (reorder_myanmar);
for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++)
{
map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ);
map->add_gsub_pause (nullptr);
}
map->add_gsub_pause (clear_syllables);
map->add_gsub_pause (_hb_clear_syllables);
for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
map->enable_feature (other_features[i], F_MANUAL_ZWJ);
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
map->enable_feature (positioning_features[i]);
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_positioning_features); i++)
map->enable_feature (myanmar_positioning_features[i]);
}
static void
@ -130,11 +126,11 @@ override_features_myanmar (hb_ot_shape_planner_t *plan)
}
enum syllable_type_t {
consonant_syllable,
punctuation_cluster,
broken_cluster,
non_myanmar_cluster,
enum myanmar_syllable_type_t {
myanmar_consonant_syllable,
myanmar_punctuation_cluster,
myanmar_broken_cluster,
myanmar_non_myanmar_cluster,
};
#include "hb-ot-shape-complex-myanmar-machine.hh"
@ -158,11 +154,11 @@ setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
find_syllables_myanmar (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
}
@ -278,29 +274,29 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
}
static void
initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_face_t *face HB_UNUSED,
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type) {
case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case consonant_syllable:
case myanmar_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
case myanmar_consonant_syllable:
initial_reordering_consonant_syllable (buffer, start, end);
break;
case punctuation_cluster:
case non_myanmar_cluster:
case myanmar_punctuation_cluster:
case myanmar_non_myanmar_cluster:
break;
}
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
insert_dotted_circles_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
@ -311,7 +307,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_cluster)
if ((info[i].syllable() & 0x0F) == myanmar_broken_cluster)
{
has_broken_syllables = true;
break;
@ -336,8 +332,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == myanmar_broken_cluster))
{
last_syllable = syllable;
@ -355,30 +351,19 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
reorder_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
insert_dotted_circles_myanmar (plan, font, buffer);
foreach_syllable (buffer, start, end)
initial_reordering_syllable (plan, font->face, buffer, start, end);
reorder_syllable_myanmar (plan, font->face, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
}
static void
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
}
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
{

View File

@ -49,10 +49,10 @@ enum myanmar_category_t {
OT_MW = 23, /* Various consonant medial types */
OT_MY = 24, /* Various consonant medial types */
OT_PT = 25, /* Pwo and other tones */
OT_VAbv = 26,
OT_VBlw = 27,
OT_VPre = 28,
OT_VPst = 29,
//OT_VAbv = 26,
//OT_VBlw = 27,
//OT_VPre = 28,
//OT_VPst = 29,
OT_VS = 30, /* Variation selectors */
OT_P = 31, /* Punctuation */
OT_D = 32, /* Digits except zero */
@ -155,11 +155,11 @@ set_myanmar_properties (hb_glyph_info_t &info)
{
switch ((int) pos)
{
case POS_PRE_C: cat = OT_VPre;
case POS_PRE_C: cat = (myanmar_category_t) OT_VPre;
pos = POS_PRE_M; break;
case POS_ABOVE_C: cat = OT_VAbv; break;
case POS_BELOW_C: cat = OT_VBlw; break;
case POS_POST_C: cat = OT_VPst; break;
case POS_ABOVE_C: cat = (myanmar_category_t) OT_VAbv; break;
case POS_BELOW_C: cat = (myanmar_category_t) OT_VBlw; break;
case POS_POST_C: cat = (myanmar_category_t) OT_VPst; break;
}
}

View File

@ -380,13 +380,13 @@ static const int use_syllable_machine_en_main = 5;
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_use (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act;
int cs;

View File

@ -165,13 +165,13 @@ main := |*
HB_STMT_START { \
if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
for (unsigned int i = ts; i < te; i++) \
info[i].syllable() = (syllable_serial << 4) | syllable_type; \
info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \
syllable_serial++; \
if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
} HB_STMT_END
static void
find_syllables (hb_buffer_t *buffer)
find_syllables_use (hb_buffer_t *buffer)
{
unsigned int p, pe, eof, ts, te, act;
int cs;

View File

@ -44,7 +44,7 @@
*/
static const hb_tag_t
basic_features[] =
use_basic_features[] =
{
/*
* Basic features.
@ -59,28 +59,23 @@ basic_features[] =
HB_TAG('c','j','c','t'),
};
static const hb_tag_t
arabic_features[] =
use_topographical_features[] =
{
HB_TAG('i','s','o','l'),
HB_TAG('i','n','i','t'),
HB_TAG('m','e','d','i'),
HB_TAG('f','i','n','a'),
/* The spec doesn't specify these but we apply anyway, since our Arabic shaper
* does. These are only used in Syriac spec. */
HB_TAG('m','e','d','2'),
HB_TAG('f','i','n','2'),
HB_TAG('f','i','n','3'),
};
/* Same order as arabic_features. Don't need Syriac stuff.*/
/* Same order as use_topographical_features. */
enum joining_form_t {
ISOL,
INIT,
MEDI,
FINA,
_NONE
USE_ISOL,
USE_INIT,
USE_MEDI,
USE_FINA,
_USE_NONE
};
static const hb_tag_t
other_features[] =
use_other_features[] =
{
/*
* Other features.
@ -94,7 +89,7 @@ other_features[] =
HB_TAG('p','s','t','s'),
};
static const hb_tag_t
positioning_features[] =
use_positioning_features[] =
{
/*
* Positioning features.
@ -106,29 +101,21 @@ positioning_features[] =
};
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
record_rphf_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_substitution_flags (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
record_rphf (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
record_pref (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
clear_syllables (const hb_ot_shape_plan_t *plan,
record_pref_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
static void
collect_features_use (hb_ot_shape_planner_t *plan)
@ -136,7 +123,7 @@ collect_features_use (hb_ot_shape_planner_t *plan)
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
map->add_gsub_pause (setup_syllables);
map->add_gsub_pause (setup_syllables_use);
/* "Default glyph pre-processing group" */
map->enable_feature (HB_TAG('l','o','c','l'));
@ -145,32 +132,32 @@ collect_features_use (hb_ot_shape_planner_t *plan)
map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
/* "Reordering group" */
map->add_gsub_pause (clear_substitution_flags);
map->add_gsub_pause (_hb_clear_substitution_flags);
map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
map->add_gsub_pause (record_rphf);
map->add_gsub_pause (clear_substitution_flags);
map->add_gsub_pause (record_rphf_use);
map->add_gsub_pause (_hb_clear_substitution_flags);
map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
map->add_gsub_pause (record_pref);
map->add_gsub_pause (record_pref_use);
/* "Orthographic unit shaping group" */
for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++)
map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ);
map->add_gsub_pause (reorder);
map->add_gsub_pause (clear_syllables);
map->add_gsub_pause (reorder_use);
map->add_gsub_pause (_hb_clear_syllables);
/* "Topographical features" */
for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
map->add_feature (arabic_features[i]);
for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
map->add_feature (use_topographical_features[i]);
map->add_gsub_pause (nullptr);
/* "Standard typographic presentation" */
for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
map->enable_feature (other_features[i], F_MANUAL_ZWJ);
for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++)
map->enable_feature (use_other_features[i], F_MANUAL_ZWJ);
/* "Positional feature application" */
for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
map->enable_feature (positioning_features[i]);
for (unsigned int i = 0; i < ARRAY_LENGTH (use_positioning_features); i++)
map->enable_feature (use_positioning_features[i]);
}
struct use_shape_plan_t
@ -247,16 +234,16 @@ data_destroy_use (void *data)
free (data);
}
enum syllable_type_t {
independent_cluster,
virama_terminated_cluster,
sakot_terminated_cluster,
standard_cluster,
number_joiner_terminated_cluster,
numeral_cluster,
symbol_cluster,
broken_cluster,
non_cluster,
enum use_syllable_type_t {
use_independent_cluster,
use_virama_terminated_cluster,
use_sakot_terminated_cluster,
use_standard_cluster,
use_number_joiner_terminated_cluster,
use_numeral_cluster,
use_symbol_cluster,
use_broken_cluster,
use_non_cluster,
};
#include "hb-ot-shape-complex-use-machine.hh"
@ -313,11 +300,11 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
if (use_plan->arabic_plan)
return;
static_assert ((INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4), "");
static_assert ((USE_INIT < 4 && USE_ISOL < 4 && USE_MEDI < 4 && USE_FINA < 4), "");
hb_mask_t masks[4], all_masks = 0;
for (unsigned int i = 0; i < 4; i++)
{
masks[i] = plan->map.get_1_mask (arabic_features[i]);
masks[i] = plan->map.get_1_mask (use_topographical_features[i]);
if (masks[i] == plan->map.get_global_mask ())
masks[i] = 0;
all_masks |= masks[i];
@ -327,39 +314,39 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
hb_mask_t other_masks = ~all_masks;
unsigned int last_start = 0;
joining_form_t last_form = _NONE;
joining_form_t last_form = _USE_NONE;
hb_glyph_info_t *info = buffer->info;
foreach_syllable (buffer, start, end)
{
syllable_type_t syllable_type = (syllable_type_t) (info[start].syllable() & 0x0F);
use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
switch (syllable_type)
{
case independent_cluster:
case symbol_cluster:
case non_cluster:
case use_independent_cluster:
case use_symbol_cluster:
case use_non_cluster:
/* These don't join. Nothing to do. */
last_form = _NONE;
last_form = _USE_NONE;
break;
case virama_terminated_cluster:
case sakot_terminated_cluster:
case standard_cluster:
case number_joiner_terminated_cluster:
case numeral_cluster:
case broken_cluster:
case use_virama_terminated_cluster:
case use_sakot_terminated_cluster:
case use_standard_cluster:
case use_number_joiner_terminated_cluster:
case use_numeral_cluster:
case use_broken_cluster:
bool join = last_form == FINA || last_form == ISOL;
bool join = last_form == USE_FINA || last_form == USE_ISOL;
if (join)
{
/* Fixup previous syllable's form. */
last_form = last_form == FINA ? MEDI : INIT;
last_form = last_form == USE_FINA ? USE_MEDI : USE_INIT;
for (unsigned int i = last_start; i < start; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
}
/* Form for this syllable. */
last_form = join ? FINA : ISOL;
last_form = join ? USE_FINA : USE_ISOL;
for (unsigned int i = start; i < end; i++)
info[i].mask = (info[i].mask & other_masks) | masks[last_form];
@ -371,11 +358,11 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan,
}
static void
setup_syllables (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
find_syllables (buffer);
find_syllables_use (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
setup_rphf_mask (plan, buffer);
@ -383,20 +370,9 @@ setup_syllables (const hb_ot_shape_plan_t *plan,
}
static void
clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
_hb_glyph_info_clear_substituted (&info[i]);
}
static void
record_rphf (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
record_rphf_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
@ -417,9 +393,9 @@ record_rphf (const hb_ot_shape_plan_t *plan,
}
static void
record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
@ -436,22 +412,22 @@ record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static inline bool
is_halant (const hb_glyph_info_t &info)
is_halant_use (const hb_glyph_info_t &info)
{
return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
!_hb_glyph_info_ligated (&info);
}
static void
reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
{
syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
use_syllable_type_t syllable_type = (use_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
/* Only a few syllable types need reordering. */
if (unlikely (!(FLAG_UNSAFE (syllable_type) &
(FLAG (virama_terminated_cluster) |
FLAG (sakot_terminated_cluster) |
FLAG (standard_cluster) |
FLAG (broken_cluster) |
(FLAG (use_virama_terminated_cluster) |
FLAG (use_sakot_terminated_cluster) |
FLAG (use_standard_cluster) |
FLAG (use_broken_cluster) |
0))))
return;
@ -482,7 +458,7 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
for (unsigned int i = start + 1; i < end; i++)
{
bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
is_halant (info[i]);
is_halant_use (info[i]);
if (is_post_base_glyph || i == end - 1)
{
/* If we hit a post-base glyph, move before it; otherwise move to the
@ -506,7 +482,7 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
for (unsigned int i = start; i < end; i++)
{
uint32_t flag = FLAG_UNSAFE (info[i].use_category());
if (is_halant (info[i]))
if (is_halant_use (info[i]))
{
/* If we hit a halant, move after it; otherwise move to the beginning, and
* shift things in between forward. */
@ -526,9 +502,9 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
}
static inline void
insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
insert_dotted_circles_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
@ -539,7 +515,7 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
if ((info[i].syllable() & 0x0F) == broken_cluster)
if ((info[i].syllable() & 0x0F) == use_broken_cluster)
{
has_broken_syllables = true;
break;
@ -559,8 +535,8 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
use_syllable_type_t syllable_type = (use_syllable_type_t) (syllable & 0x0F);
if (unlikely (last_syllable != syllable && syllable_type == use_broken_cluster))
{
last_syllable = syllable;
@ -584,29 +560,18 @@ insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
static void
reorder (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
reorder_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
insert_dotted_circles (plan, font, buffer);
insert_dotted_circles_use (plan, font, buffer);
foreach_syllable (buffer, start, end)
reorder_syllable (buffer, start, end);
reorder_syllable_use (buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
}
static void
clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
hb_glyph_info_t *info = buffer->info;
unsigned int count = buffer->len;
for (unsigned int i = 0; i < count; i++)
info[i].syllable() = 0;
}
static void
preprocess_text_use (const hb_ot_shape_plan_t *plan,

View File

@ -68,7 +68,7 @@ hb_ot_var_get_axis_count (hb_face_t *face);
typedef enum { /*< flags >*/
HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u,
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/
_HB_OT_VAR_AXIS_FLAG_MAX_VALUE= HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_var_axis_flags_t;
/**

View File

@ -85,7 +85,7 @@ struct VORG
this->vertYOrigins.len = it.len ();
+ it
| hb_apply ([c] (const VertOriginMetric& _) { c->copy (_);})
| hb_apply ([c] (const VertOriginMetric& _) { c->copy (_); })
;
}

View File

@ -35,6 +35,8 @@
#include "hb-ot-font.h"
#include "hb-ot-layout.h"
#include "hb-ot-math.h"
#include "hb-ot-meta.h"
#include "hb-ot-metrics.h"
#include "hb-ot-name.h"
#include "hb-ot-shape.h"
#include "hb-ot-var.h"

View File

@ -479,7 +479,7 @@ hb_set_next (const hb_set_t *set,
* @set: a set.
* @codepoint: (inout):
*
* Gets the previous number in @set that is slower than current value of @codepoint.
* Gets the previous number in @set that is lower than current value of @codepoint.
*
* Set @codepoint to %HB_SET_VALUE_INVALID to get started.
*
@ -524,7 +524,7 @@ hb_set_next_range (const hb_set_t *set,
* @last: (out): output last codepoint in the range.
*
* Gets the previous consecutive range of numbers in @set that
* are greater than current value of @last.
* are less than current value of @first.
*
* Set @first to %HB_SET_VALUE_INVALID to get started.
*

View File

@ -46,16 +46,16 @@ struct hb_shape_plan_key_t
hb_shape_func_t *shaper_func;
const char *shaper_name;
HB_INTERNAL inline bool init (bool copy,
hb_face_t *face,
const hb_segment_properties_t *props,
const hb_feature_t *user_features,
unsigned int num_user_features,
const int *coords,
unsigned int num_coords,
const char * const *shaper_list);
HB_INTERNAL bool init (bool copy,
hb_face_t *face,
const hb_segment_properties_t *props,
const hb_feature_t *user_features,
unsigned int num_user_features,
const int *coords,
unsigned int num_coords,
const char * const *shaper_list);
HB_INTERNAL inline void free () { ::free ((void *) user_features); }
HB_INTERNAL void free () { ::free ((void *) user_features); }
HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);

View File

@ -179,7 +179,7 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
unsigned max_glyph =
+ hb_iter (all_gids_to_retain)
| hb_reduce (hb_max, 0)
| hb_reduce (hb_max, 0u)
;
*num_glyphs = max_glyph + 1;
}

View File

@ -15,6 +15,7 @@
*/
#include "hb.hh"
#include "hb-unicode.hh"
#include "hb-machinery.hh"
#include "hb-ucd-table.hh"
@ -235,10 +236,6 @@ void free_static_ucd_funcs ()
}
#endif
extern "C" HB_INTERNAL
hb_unicode_funcs_t *
hb_ucd_get_unicode_funcs ();
hb_unicode_funcs_t *
hb_ucd_get_unicode_funcs ()
{

View File

@ -126,10 +126,12 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED
}
#endif
extern "C" hb_unicode_funcs_t *hb_ucd_get_unicode_funcs ();
extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB)
#include "hb-glib.h"
#endif
#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
#include "hb-icu.h"
#endif
hb_unicode_funcs_t *
hb_unicode_funcs_get_default ()

View File

@ -105,9 +105,6 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
unsigned int
modified_combining_class (hb_codepoint_t u)
{
/* XXX This hack belongs to the Myanmar shaper. */
if (unlikely (u == 0x1037u)) u = 0x103Au;
/* XXX This hack belongs to the USE shaper (for Tai Tham):
* Reorder SAKOT to ensure it comes after any tone marks. */
if (unlikely (u == 0x1A60u)) return 254;
@ -395,4 +392,7 @@ HB_INTERNAL bool
_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp);
extern "C" HB_INTERNAL hb_unicode_funcs_t *hb_ucd_get_unicode_funcs ();
#endif /* HB_UNICODE_HH */

View File

@ -58,13 +58,6 @@
* Functions for using HarfBuzz with the Windows fonts.
**/
static inline uint16_t hb_uint16_swap (const uint16_t v)
{ return (v >> 8) | (v << 8); }
static inline uint32_t hb_uint32_swap (const uint32_t v)
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/(
const WCHAR *pwcInChars,
int cInChars,
@ -245,8 +238,9 @@ struct hb_uniscribe_shaper_funcs_t
}
};
#if HB_USE_ATEXIT
static void free_static_uniscribe_shaper_funcs ();
#endif
static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_uniscribe_shaper_funcs_t,
hb_uniscribe_shaper_funcs_lazy_loader_t>

View File

@ -143,13 +143,13 @@ struct hb_vector_t
operator writer_t () { return writer (); }
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
{ return as_array ().sub_array (start_offset, count);}
{ return as_array ().sub_array (start_offset, count); }
hb_sorted_array_t<Type> as_sorted_array ()
{ return hb_sorted_array (arrayZ, length); }

View File

@ -98,6 +98,7 @@
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
#pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
#pragma GCC diagnostic warning "-Wdeprecated"
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
#pragma GCC diagnostic warning "-Wdisabled-optimization"
#pragma GCC diagnostic warning "-Wdouble-promotion"
#pragma GCC diagnostic warning "-Wformat=2"
@ -317,7 +318,8 @@ extern "C" void hb_free_impl(void *ptr);
# define HB_FALLTHROUGH /* FALLTHROUGH */
#endif
#ifdef __clang__
/* https://github.com/harfbuzz/harfbuzz/issues/1852 */
#if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)))
/* Disable certain sanitizer errors. */
/* https://github.com/harfbuzz/harfbuzz/issues/1247 */
#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
@ -475,6 +477,11 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
/* Size signifying variable-sized array */
#define VAR 1
/* Endian swap, used in Windows related backends */
static inline uint16_t hb_uint16_swap (const uint16_t v)
{ return (v >> 8) | (v << 8); }
static inline uint32_t hb_uint32_swap (const uint32_t v)
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
/*
* Big-endian integers. Here because fundamental.

70
src/test-ot-meta.cc Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#include "hb.hh"
#include "hb-ot.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HB_NO_OPEN
#define hb_blob_create_from_file(x) hb_blob_get_empty ()
#endif
int
main (int argc, char **argv)
{
if (argc != 2) {
fprintf (stderr, "usage: %s font-file\n", argv[0]);
exit (1);
}
hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
hb_blob_destroy (blob);
blob = nullptr;
unsigned int count = 0;
#ifndef HB_NO_META
count = hb_ot_meta_get_entries (face, 0, nullptr, nullptr);
hb_ot_meta_tag_t *tags = (hb_ot_meta_tag_t *)
malloc (sizeof (hb_ot_meta_tag_t) * count);
hb_ot_meta_get_entries (face, 0, &count, tags);
for (unsigned i = 0; i < count; ++i)
{
hb_blob_t *entry = hb_ot_meta_reference_entry (face, tags[i]);
printf ("%c%c%c%c, size: %d: %.*s\n",
HB_UNTAG (tags[i]), hb_blob_get_length (entry),
hb_blob_get_length (entry), hb_blob_get_data (entry, nullptr));
hb_blob_destroy (entry);
}
free (tags);
#endif
hb_face_destroy (face);
return !count;
}

View File

@ -84,6 +84,8 @@ TEST_PROGS += \
test-ot-color \
test-ot-ligature-carets \
test-ot-name \
test-ot-meta \
test-ot-metrics \
test-ot-tag \
test-ot-extents-cff \
$(NULL)

Binary file not shown.

BIN
test/api/fonts/meta.ttf Normal file

Binary file not shown.

View File

@ -426,9 +426,9 @@ test_hb_ot_color_png (void)
g_assert (strncmp (data + 1, "PNG", 3) == 0);
hb_font_get_glyph_extents (sbix_font, 1, &extents);
g_assert_cmpint (extents.x_bearing, ==, 0);
g_assert_cmpint (extents.y_bearing, ==, 0);
g_assert_cmpint (extents.y_bearing, ==, 800);
g_assert_cmpint (extents.width, ==, 800);
g_assert_cmpint (extents.height, ==, 800);
g_assert_cmpint (extents.height, ==, -800);
hb_blob_destroy (blob);
hb_font_destroy (sbix_font);

84
test/api/test-ot-meta.c Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright © 2019 Ebrahim Byagowi
*
* 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.
*/
#include "hb-test.h"
#include <hb-ot.h>
/* Unit tests for hb-ot-meta.h */
static void
test_ot_meta_get_entries (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/meta.ttf");
hb_ot_meta_tag_t entries[2];
unsigned int entries_count = 2;
g_assert_cmpint (hb_ot_meta_get_entries (face, 0, &entries_count, entries), ==, 5);
g_assert_cmpint (entries_count, ==, 2);
g_assert_cmpint (entries[0], ==, HB_TAG ('a','p','p','l'));
g_assert_cmpint (entries[1], ==, HB_TAG ('b','i','l','d'));
entries_count = 1;
g_assert_cmpint (hb_ot_meta_get_entries (face, 2, &entries_count, entries), ==, 5);
g_assert_cmpint (entries_count, ==, 1);
g_assert_cmpint (entries[0], ==, HB_TAG ('d','l','n','g'));
entries_count = 2;
g_assert_cmpint (hb_ot_meta_get_entries (face, 4, &entries_count, entries), ==, 5);
g_assert_cmpint (entries_count, ==, 1);
g_assert_cmpint (entries[0], ==, HB_TAG ('s','l','n','g'));
hb_face_destroy (face);
}
static void
test_ot_meta_reference_entry (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/meta.ttf");
hb_blob_t *dlng = hb_ot_meta_reference_entry (face, HB_OT_META_DESIGN_LANGUAGES);
g_assert_cmpint (hb_blob_get_length (dlng), ==, 8);
g_assert_cmpmem (hb_blob_get_data (dlng, NULL), 8, "ar,de,fa", 8);
hb_blob_destroy (dlng);
hb_blob_t *fslf = hb_ot_meta_reference_entry (face, (hb_ot_meta_tag_t) HB_TAG ('f','s','l','f'));
g_assert_cmpint (hb_blob_get_length (fslf), ==, 12);
hb_blob_destroy (fslf);
hb_blob_t *nacl = hb_ot_meta_reference_entry (face, (hb_ot_meta_tag_t) HB_TAG ('n','a','c','l'));
g_assert_cmpint (hb_blob_get_length (nacl), ==, 0);
hb_blob_destroy (nacl);
hb_blob_t *slng = hb_ot_meta_reference_entry (face, HB_OT_META_SUPPORTED_LANGUAGES);
g_assert_cmpint (hb_blob_get_length (slng), ==, 11);
g_assert_cmpmem (hb_blob_get_data (slng, NULL), 11, "ar,de,en,fa", 11);
hb_blob_destroy (slng);
hb_face_destroy (face);
}
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_ot_meta_get_entries);
hb_test_add (test_ot_meta_reference_entry);
return hb_test_run ();
}

View File

@ -0,0 +1,78 @@
/*
* Copyright © 2018 Ebrahim Byagowi
*
* 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.
*/
#include "hb-test.h"
#include <hb-ot.h>
#include <math.h>
/* Unit tests for hb-ot-metrics.h */
static void
test_ot_metrics_get_no_var (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/cpal-v0.ttf");
hb_font_t *font = hb_font_create (face);
hb_position_t value;
g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_HORIZONTAL_ASCENDER, &value));
g_assert_cmpint (value, ==, 1000);
g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
g_assert_cmpint (hb_ot_metrics_get_y_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_X_HEIGHT), ==, 0);
// g_assert_cmpint ((int) hb_ot_metrics_get_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
hb_font_destroy (font);
hb_face_destroy (face);
}
static void
test_ot_metrics_get_var (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/TestCFF2VF.otf");
hb_font_t *font = hb_font_create (face);
hb_position_t value;
g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_X_HEIGHT, &value));
g_assert_cmpint (value, ==, 486);
g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
g_assert_cmpint (hb_ot_metrics_get_y_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_X_HEIGHT), ==, 0);
float coords[] = {100.f};
hb_font_set_var_coords_design (font, coords, 1);
g_assert (hb_ot_metrics_get_position (font, HB_OT_METRICS_X_HEIGHT, &value));
g_assert_cmpint (value, ==, 478);
g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
g_assert_cmpint (hb_ot_metrics_get_y_variation (font, HB_OT_METRICS_HORIZONTAL_ASCENDER), ==, 0);
g_assert_cmpint (hb_ot_metrics_get_x_variation (font, HB_OT_METRICS_X_HEIGHT), ==, -8);
hb_font_destroy (font);
hb_face_destroy (face);
}
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_ot_metrics_get_no_var);
hb_test_add (test_ot_metrics_get_var);
return hb_test_run ();
}

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "hb-subset.h"
@ -32,6 +33,19 @@ trySubset (hb_face_t *face,
}
hb_face_t *result = hb_subset (face, input);
{
hb_blob_t *blob = hb_face_reference_blob (result);
unsigned int length;
const char *data = hb_blob_get_data (blob, &length);
// Something not optimizable just to access all the blob data
unsigned int bytes_count = 0;
for (unsigned int i = 0; i < length; ++i)
if (data[i]) ++bytes_count;
assert (bytes_count || !length);
hb_blob_destroy (blob);
}
hb_face_destroy (result);
hb_subset_input_destroy (input);

View File

@ -5,41 +5,41 @@ from __future__ import print_function, division, absolute_import
import sys, os, subprocess, tempfile, threading
def which(program):
def which (program):
# https://stackoverflow.com/a/377028
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
def is_exe (fpath):
return os.path.isfile (fpath) and os.access (fpath, os.X_OK)
fpath, _ = os.path.split(program)
fpath, _ = os.path.split (program)
if fpath:
if is_exe(program):
if is_exe (program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
for path in os.environ["PATH"].split (os.pathsep):
exe_file = os.path.join (path, program)
if is_exe (exe_file):
return exe_file
return None
def cmd(command):
def cmd (command):
# https://stackoverflow.com/a/4408409
# https://stackoverflow.com/a/10012262
with tempfile.TemporaryFile() as tempf:
with tempfile.TemporaryFile () as tempf:
p = subprocess.Popen (command, stderr=tempf)
is_killed = {'value': False}
def timeout(p, is_killed):
def timeout (p, is_killed):
is_killed['value'] = True
p.kill()
p.kill ()
timer = threading.Timer (2, timeout, [p, is_killed])
try:
timer.start()
p.wait ()
tempf.seek (0)
text = tempf.read().decode ("utf-8").strip ()
text = tempf.read ().decode ("utf-8").strip ()
returncode = p.returncode
finally:
timer.cancel()
@ -67,9 +67,9 @@ please provide it as the first argument to the tool""")
print ('hb_shape_fuzzer:', hb_shape_fuzzer)
fails = 0
libtool = os.environ.get('LIBTOOL')
libtool = os.environ.get ('LIBTOOL')
valgrind = None
if os.environ.get('RUN_VALGRIND', ''):
if os.environ.get ('RUN_VALGRIND', ''):
valgrind = which ('valgrind')
if valgrind is None:
print ("""Valgrind requested but not found.""")
@ -80,7 +80,7 @@ if os.environ.get('RUN_VALGRIND', ''):
parent_path = os.path.join (srcdir, "fonts")
for file in os.listdir (parent_path):
path = os.path.join(parent_path, file)
path = os.path.join (parent_path, file)
if valgrind:
text, returncode = cmd (libtool.split(' ') + ['--mode=execute', valgrind + ' --leak-check=full --error-exitcode=1', '--', hb_shape_fuzzer, path])
@ -89,7 +89,7 @@ for file in os.listdir (parent_path):
if 'error' in text:
returncode = 1
if not valgrind and text.strip ():
if (not valgrind or returncode) and text.strip ():
print (text)
if returncode != 0:

View File

@ -33,7 +33,7 @@ def cmd(command):
def timeout(p, is_killed):
is_killed['value'] = True
p.kill()
timer = threading.Timer (2, timeout, [p, is_killed])
timer = threading.Timer (8, timeout, [p, is_killed])
try:
timer.start()
@ -82,6 +82,8 @@ def run_dir (parent_path):
global fails
for file in os.listdir (parent_path):
path = os.path.join(parent_path, file)
# TODO: Run on all the fonts not just subset related ones
if "subset" not in path: continue
print ("running subset fuzzer against %s" % path)
if valgrind:
@ -91,7 +93,7 @@ def run_dir (parent_path):
if 'error' in text:
returncode = 1
if not valgrind and text.strip ():
if (not valgrind or returncode) and text.strip ():
print (text)
if returncode != 0:
@ -100,8 +102,7 @@ def run_dir (parent_path):
run_dir (os.path.join (srcdir, "..", "subset", "data", "fonts"))
# TODO running these tests very slow tests. Fix and re-enable
#run_dir (os.path.join (srcdir, "fonts"))
run_dir (os.path.join (srcdir, "fonts"))
if fails:
print ("%i subset fuzzer related tests failed." % fails)

View File

@ -1 +1,2 @@
../fonts/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf:--font-funcs=ot --show-extents:U+1F42F:[gid1=0+2963<0,2179,2963,-2789>]
../fonts/fcbaa518d3cce441ed37ae3b1fed6a19e9b54efd.ttf:--font-funcs=ot --show-extents:U+1F600:[gid4=0+2550<0,1898,2555,-2405>]

Some files were not shown because too many files have changed in this diff Show More