Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-10-22 09:57:20 -07:00
commit 857c58279e
92 changed files with 1135 additions and 536 deletions

View File

@ -35,6 +35,8 @@ jobs:
- run: brew update-reset
- run: brew install cmake
# not needed to be a framework but we like to test that also
# TODO: wrong way of targeting iOS as it doesn't point to iOS headers thus building
# CoreText support is not possible, after the fix feel free HB_IOS from CMake altogether
- run: cmake -DBUILD_FRAMEWORK=ON -H. -Bbuild -GXcode -DHB_IOS=ON
- run: cd build && xcodebuild -sdk iphoneos12.0 -configuration Release build -arch arm64
@ -90,6 +92,22 @@ jobs:
- run: make -j32
- run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh
gcc-valgrind:
docker:
- image: ubuntu:18.10
steps:
- checkout
- run: apt update || true
- run: apt install -y gcc binutils libtool autoconf automake make pkg-config gtk-doc-tools ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip valgrind
- run: pip install fonttools
- run: ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
- run: make -j32
# run-shape-fuzzer-tests.py automatically runs valgrind if see available
# but test/api runs it by request, we probably should normalize the approaches
- run: RUN_VALGRIND=1 make check && make -Ctest/api check-valgrind || .ci/fail.sh
# informational for now
- run: make -Ctest/api check-symbols || true
clang-everything:
docker:
- image: ubuntu:18.10
@ -269,14 +287,14 @@ jobs:
- run: cmake -Bbuild -H. -GNinja
- run: ninja -Cbuild
crosscompile-cmake-notest-windows-x64:
docker:
- image: dockcross/windows-x64
steps:
- checkout
- run: apt update && apt install ragel
- run: cmake -Bbuild -H. -GNinja
- run: ninja -Cbuild
#crosscompile-cmake-notest-windows-x64:
# docker:
# - image: dockcross/windows-x64
# steps:
# - checkout
# - run: apt update && apt install ragel
# - run: cmake -Bbuild -H. -GNinja
# - run: ninja -Cbuild
workflows:
version: 2
@ -293,6 +311,7 @@ workflows:
# autotools based builds
- alpine-O3-NOMMAP
- archlinux-debug-O0-py3
- gcc-valgrind
- clang-O3-O0
- clang-everything
- clang-asan
@ -317,4 +336,4 @@ workflows:
- crosscompile-cmake-notest-browser-asmjs
- crosscompile-cmake-notest-linux-arm64
- crosscompile-cmake-notest-linux-mips
- crosscompile-cmake-notest-windows-x64
#- crosscompile-cmake-notest-windows-x64

View File

@ -26,7 +26,7 @@ as with any other standard package. That should leave you with a shared
library in `src/`, and a few utility programs including `hb-view` and `hb-shape`
under `util/`.
If you are bootstraping from git, you need a few more tools before you can
If you are bootstrapping from git, you need a few more tools before you can
run `autogen.sh` for the first time. Namely, `pkg-config` and `ragel`.
Again, on Ubuntu / Debian:

View File

@ -107,10 +107,10 @@ include (CheckFunctionExists)
include (CheckIncludeFile)
macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools
foreach (func_name ${ARGN})
string(TOUPPER ${func_name} definiton_to_add)
check_function_exists(${func_name} HAVE_${definiton_to_add})
if (${HAVE_${definiton_to_add}})
add_definitions(-DHAVE_${definiton_to_add})
string(TOUPPER ${func_name} definition_to_add)
check_function_exists(${func_name} HAVE_${definition_to_add})
if (${HAVE_${definition_to_add}})
add_definitions(-DHAVE_${definition_to_add})
endif ()
endforeach ()
endmacro ()

21
NEWS
View File

@ -1,5 +1,24 @@
Overview of changes leading to 2.0.2
Saturday, October 20, 2018
====================================
- Fix two minor memory access issues in AAT tables.
Overview of changes leading to 2.0.1
Friday, October 19, 2018
====================================
- Fix hb-version.h reported release version that went wrong (1.8.0)
with previous release.
- Fix extrapolation in 'trak' table.
- Fix hb-font infinite-recursion issue with some font funcs and
subclassed fonts.
- Implement variation-kerning format in kerx table, although without
variation.
- Fix return value of hb_map_is_empty().
Overview of changes leading to 2.0.0
Wednesday, October 17, 2018
Thursday, October 18, 2018
====================================
- Added AAT shaping support (morx/kerx/trak).
Automatically used if GSUB/GPOS are not available respectively.

View File

@ -23,7 +23,7 @@ Then make sure you also have GI_TYPELIB_PATH pointing to the resulting
$prefix/lib/girepository-* directory.
Make sure you have pygobject installed. Then check that the following
import works in your Python interpretter:
import works in your Python interpreter:
```python
from gi.repository import HarfBuzz

View File

@ -1,6 +1,6 @@
For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe,
as a widely used and tested shaper is used as more-or-less OpenType reference
implemenetation and that specially is important where OpenType specification
implementation and that specially is important where OpenType specification
is or wasn't that clear. For having access to Uniscribe on Linux/macOS these
steps are recommended:
@ -27,8 +27,8 @@ steps are recommended:
Now you can use hb-shape using `wine winbuild/util/hb-shape.exe` but if you like to
to use the original Uniscribe,
8. Bring a 32bit version of `usp10.dll` for youself from `C:\Windows\SysWOW64\usp10.dll` of your
Windows installation (asuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`)
8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your
Windows installation (assuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`)
that it is not a DirectWrite proxy ([for more info](https://en.wikipedia.org/wiki/Uniscribe)).
Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise
it is designed to work with DirectWrite which Wine can't work with its original one.

View File

@ -27,7 +27,10 @@ HarfBuzz release walk-through checklist:
Otherwise, fix things and commit them separately before making release,
Note: Check src/hb-version.h and make sure the new version number is
there. Sometimes, it does not get updated. If that's the case,
"touch configure.ac" and rebuild. TODO: debug.
"touch configure.ac" and rebuild. Also check that there is no hb-version.h
in your build/src file. Typically it will fail the distcheck if there is.
That's what happened to 2.0.0 going out with 1.8.0 hb-version.h... So, that's
a clue.
7. "make release-files". Enter your GPG password. This creates a sha256 hash
and signs it.

2
TODO
View File

@ -15,8 +15,6 @@ API additions
- Add sanitize API.
- BCP 47 language handling / API (language_matches?)
- Add query / enumeration API for aalt-like features?
- Add segmentation API

View File

@ -28,9 +28,19 @@ environment:
MINGW_CHOST: i686-w64-mingw32
MSYS2_ARCH: i686
- compiler: cygwin
CYGWIN_PREFIX: C:\Cygwin64
CYGWIN_ARCH: x86_64
# Lots of test failures here!
#- compiler: cygwin
# CYGWIN_PREFIX: C:\Cygwin
# CYGWIN_ARCH: x86
install:
- 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --force --noconfirm -Sy && pacman --noconfirm --force -S pacman-mirrors && pacman --force -Syu --noconfirm"'
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel"
- 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\setup-%CYGWIN_ARCH%.exe -g -q -P cygwin-devel,libfreetype-devel,libcairo-devel,libicu-devel,gcc,gcc-g++,gobject-introspection,libglib2.0-devel,libgraphite2-devel,pkg-config,python2'
build_script:
- 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" vcpkg install glib:%triplet% freetype:%triplet% cairo:%triplet%'
@ -49,8 +59,13 @@ build_script:
- '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; make check || .ci/fail.sh"'
- 'if "%compiler%"=="cygwin" set PATH=%PATH%;c:\msys64\mingw64\bin' # msys2 is added just for having "ragel" on PATH
- 'if "%compiler%"=="cygwin" curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h -o %CYGWIN_PREFIX%\usr\include\dwrite_1.h'
- 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite; make; make check || .ci/fail.sh"'
cache:
- c:\tools\vcpkg\installed\
- '%CYGWIN_PREFIX%\var\cache\setup'
notifications:
- provider: Email

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
[2.0.0],
[2.0.2],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])

View File

@ -62,7 +62,6 @@ CFILE_GLOB=$(top_srcdir)/src/hb-*.cc
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=$(top_builddir)/src/hb-version.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png

View File

@ -269,7 +269,7 @@ EXTRA_DIST += \
CLEANFILES += $(pkgconfig_DATA)
DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def
DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated.def
if HAVE_GOBJECT
DEF_FILES += harfbuzz-gobject.def
endif
@ -283,6 +283,8 @@ harfbuzz-icu.def: $(HB_ICU_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-deprecated.def: $(srcdir)/hb-deprecated.h
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
GENERATORS = \

View File

@ -181,6 +181,7 @@ HB_OT_RAGEL_sources = \
HB_OT_headers = \
hb-ot.h \
hb-ot-color.h \
hb-ot-font.h \
hb-ot-layout.h \
hb-ot-math.h \

View File

@ -1,5 +1,6 @@
/*
* Copyright © 2018 Ebrahim Byagowi
* Copyright © 2018 Khaled Hosny
*
* This is part of HarfBuzz, a text shaping library.
*
@ -45,8 +46,9 @@
#include <stdlib.h>
#include <stdio.h>
static void cbdt_callback (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)
static void
cbdt_callback (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)
{
char output_path[255];
sprintf (output_path, "out/cbdt-%d-%d.png", group, gid);
@ -55,8 +57,9 @@ static void cbdt_callback (const uint8_t* data, unsigned int length,
fclose (f);
}
static void sbix_callback (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)
static void
sbix_callback (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)
{
char output_path[255];
sprintf (output_path, "out/sbix-%d-%d.png", group, gid);
@ -65,8 +68,9 @@ static void sbix_callback (const uint8_t* data, unsigned int length,
fclose (f);
}
static void svg_callback (const uint8_t* data, unsigned int length,
unsigned int start_glyph, unsigned int end_glyph)
static void
svg_callback (const uint8_t* data, unsigned int length,
unsigned int start_glyph, unsigned int end_glyph)
{
char output_path[255];
if (start_glyph == end_glyph)
@ -83,13 +87,23 @@ static void svg_callback (const uint8_t* data, unsigned int length,
fclose (f);
}
static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upem, unsigned int num_glyphs,
const OT::COLR *colr, const OT::CPAL *cpal)
static void
colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face)
{
for (unsigned int i = 0; i < num_glyphs; ++i)
unsigned int upem = hb_face_get_upem (face);
unsigned glyph_count = hb_face_get_glyph_count (face);
for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid)
{
unsigned int first_layer_index, num_layers;
if (colr->get_base_glyph_record (i, &first_layer_index, &num_layers))
unsigned int num_layers = hb_ot_color_get_color_layers (face, gid, 0, nullptr, nullptr, nullptr);
if (!num_layers)
continue;
hb_codepoint_t *layer_gids = (hb_codepoint_t*) calloc (num_layers, sizeof (hb_codepoint_t));
unsigned int *color_indices = (unsigned int*) calloc (num_layers, sizeof (unsigned int));
hb_ot_color_get_color_layers (face, gid, 0, &num_layers, layer_gids, color_indices);
if (num_layers)
{
// Measure
cairo_text_extents_t extents;
@ -101,12 +115,7 @@ static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upe
cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t));
for (unsigned int j = 0; j < num_layers; ++j)
{
hb_codepoint_t glyph_id;
unsigned int color_index;
colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index);
glyphs[j].index = glyph_id;
}
glyphs[j].index = layer_gids[j];
cairo_glyph_extents (cr, glyphs, num_layers, &extents);
free (glyphs);
cairo_surface_destroy (surface);
@ -120,50 +129,62 @@ static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upe
extents.y_bearing -= extents.height / 20;
// Render
unsigned int pallet_count = cpal->get_palette_count ();
for (unsigned int pallet = 0; pallet < pallet_count; ++pallet) {
unsigned int palette_count = hb_ot_color_get_palette_count (face);
for (unsigned int palette = 0; palette < palette_count; palette++) {
char output_path[255];
// If we have more than one pallet, use a better namin
if (pallet_count == 1)
sprintf (output_path, "out/colr-%d.svg", i);
else
sprintf (output_path, "out/colr-%d-%d.svg", i, pallet);
unsigned int num_colors = hb_ot_color_get_palette_colors (face, palette, 0, nullptr, nullptr);
if (!num_colors)
continue;
cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
cairo_t *cr = cairo_create (surface);
cairo_set_font_face (cr, cairo_face);
cairo_set_font_size (cr, upem);
for (unsigned int j = 0; j < num_layers; ++j)
hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t));
hb_ot_color_get_palette_colors (face, palette, 0, &num_colors, colors);
if (num_colors)
{
hb_codepoint_t glyph_id;
unsigned int color_index;
colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index);
// If we have more than one palette, use a simpler naming
if (palette_count == 1)
sprintf (output_path, "out/colr-%d.svg", gid);
else
sprintf (output_path, "out/colr-%d-%d.svg", gid, palette);
uint32_t color = cpal->get_color_record_argb (color_index, pallet);
int alpha = color & 0xFF;
int r = (color >> 8) & 0xFF;
int g = (color >> 16) & 0xFF;
int b = (color >> 24) & 0xFF;
cairo_set_source_rgba (cr, r / 255., g / 255., b / 255., alpha);
cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
cairo_t *cr = cairo_create (surface);
cairo_set_font_face (cr, cairo_face);
cairo_set_font_size (cr, upem);
cairo_glyph_t glyph;
glyph.index = glyph_id;
glyph.x = -extents.x_bearing;
glyph.y = -extents.y_bearing;
cairo_show_glyphs (cr, &glyph, 1);
for (unsigned int layer = 0; layer < num_layers; ++layer)
{
hb_color_t color = 0x000000FF;
if (color_indices[layer] != 0xFFFF)
color = colors[color_indices[layer]];
cairo_set_source_rgba (cr,
hb_color_get_red (color) / 255.,
hb_color_get_green (color) / 255.,
hb_color_get_blue (color) / 255.,
hb_color_get_alpha (color) / 255.);
cairo_glyph_t glyph;
glyph.index = layer_gids[layer];
glyph.x = -extents.x_bearing;
glyph.y = -extents.y_bearing;
cairo_show_glyphs (cr, &glyph, 1);
}
cairo_surface_destroy (surface);
cairo_destroy (cr);
}
cairo_surface_destroy (surface);
cairo_destroy (cr);
free (colors);
}
}
free (layer_gids);
free (color_indices);
}
}
static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
unsigned int num_glyphs)
static void
dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
unsigned int num_glyphs)
{
// Dump every glyph available on the font
return; // disabled for now
@ -208,7 +229,8 @@ static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
}
}
int main (int argc, char **argv)
int
main (int argc, char **argv)
{
if (argc != 2) {
fprintf (stderr, "usage: %s font-file.ttf\n"
@ -228,7 +250,7 @@ int main (int argc, char **argv)
font_name_file = fopen ("out/_font_name_file.txt", "w");
if (font_name_file == nullptr)
{
fprintf (stderr, "./out is not accessible, create it please\n");
fprintf (stderr, "./out is not accessible as a folder, create it please\n");
exit (1);
}
fwrite (argv[1], 1, strlen (argv[1]), font_name_file);
@ -253,12 +275,6 @@ int main (int argc, char **argv)
svg.dump (svg_callback);
svg.fini ();
hb_blob_t* colr_blob = hb_sanitize_context_t ().reference_table<OT::COLR> (face);
const OT::COLR *colr = colr_blob->as<OT::COLR> ();
hb_blob_t* cpal_blob = hb_sanitize_context_t ().reference_table<OT::CPAL> (face);
const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> ();
cairo_font_face_t *cairo_face;
{
FT_Library library;
@ -267,12 +283,12 @@ int main (int argc, char **argv)
FT_New_Face (library, argv[1], 0, &ftface);
cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0);
}
colr_cpal_rendering (face, cairo_face);
unsigned int num_glyphs = hb_face_get_glyph_count (face);
unsigned int upem = hb_face_get_upem (face);
colr_cpal_rendering (cairo_face, upem, num_glyphs, colr, cpal);
dump_glyphs (cairo_face, upem, num_glyphs);
hb_font_destroy (font);
hb_face_destroy (face);
hb_blob_destroy (blob);

View File

@ -63,8 +63,10 @@ struct ankr
unsigned int num_glyphs,
const char *end) const
{
unsigned int offset = (this+lookupTable).get_value_or_null (glyph_id, num_glyphs);
const GlyphAnchors &anchors = StructAtOffset<GlyphAnchors> (&(this+anchorData), offset);
const Offset<HBUINT16, false> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
if (!offset)
return Null(Anchor);
const GlyphAnchors &anchors = StructAtOffset<GlyphAnchors> (&(this+anchorData), *offset);
/* TODO Use sanitizer; to avoid overflows and more. */
if (unlikely ((const char *) &anchors + anchors.get_size () > end))
return Null(Anchor);

View File

@ -246,6 +246,48 @@ struct LookupFormat8
DEFINE_SIZE_ARRAY (6, valueArrayZ);
};
template <typename T>
struct LookupFormat10
{
friend struct Lookup<T>;
private:
inline const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
{
if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
return Null(T);
const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
unsigned int v = 0;
unsigned int count = valueSize;
for (unsigned int i = 0; i < count; i++)
v = (v << 8) | *p++;
return v;
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
valueSize <= 4 &&
valueArrayZ.sanitize (c, glyphCount * valueSize));
}
protected:
HBUINT16 format; /* Format identifier--format = 8 */
HBUINT16 valueSize; /* Byte size of each value. */
GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
* glyph minus the value of firstGlyph plus 1). */
UnsizedArrayOf<HBUINT8>
valueArrayZ; /* The lookup values (indexed by the glyph index
* minus the value of firstGlyph). */
public:
DEFINE_SIZE_ARRAY (8, valueArrayZ);
};
template <typename T>
struct Lookup
{
@ -261,10 +303,15 @@ struct Lookup
}
}
inline const T& get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
inline const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
{
const T *v = get_value (glyph_id, num_glyphs);
return v ? *v : Null(T);
switch (u.format) {
/* Format 10 cannot return a pointer. */
case 10: return u.format10.get_value_or_null (glyph_id);
default:
const T *v = get_value (glyph_id, num_glyphs);
return v ? *v : Null(T);
}
}
inline bool sanitize (hb_sanitize_context_t *c) const
@ -277,6 +324,7 @@ struct Lookup
case 4: return_trace (u.format4.sanitize (c));
case 6: return_trace (u.format6.sanitize (c));
case 8: return_trace (u.format8.sanitize (c));
case 10: return_trace (u.format10.sanitize (c));
default:return_trace (true);
}
}
@ -289,6 +337,7 @@ struct Lookup
LookupFormat4<T> format4;
LookupFormat6<T> format6;
LookupFormat8<T> format8;
LookupFormat10<T> format10;
} u;
public:
DEFINE_SIZE_UNION (2, format);

View File

@ -45,6 +45,21 @@ namespace AAT {
using namespace OT;
static inline int
kerxTupleKern (int value,
unsigned int tupleCount,
const void *base,
hb_aat_apply_context_t *c)
{
if (likely (!tupleCount)) return value;
unsigned int offset = value;
const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
if (unlikely (!pv->sanitize (&c->sanitizer))) return 0;
return *pv;
}
struct KerxSubTableHeader
{
inline bool sanitize (hb_sanitize_context_t *c) const
@ -63,11 +78,14 @@ struct KerxSubTableHeader
struct KerxSubTableFormat0
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
hb_aat_apply_context_t *c) const
{
hb_glyph_pair_t pair = {left, right};
int i = pairs.bsearch (pair);
return i == -1 ? 0 : pairs[i].get_kerning ();
if (i == -1) return 0;
int v = pairs[i].get_kerning ();
return kerxTupleKern (v, header.tupleCount, this, c);
}
inline bool apply (hb_aat_apply_context_t *c) const
@ -77,17 +95,32 @@ struct KerxSubTableFormat0
if (!c->plan->requested_kerning)
return false;
hb_kern_machine_t<KerxSubTableFormat0> machine (*this);
accelerator_t accel (*this, c);
hb_kern_machine_t<accelerator_t> machine (accel);
machine.kern (c->font, c->buffer, c->plan->kern_mask);
return_trace (true);
}
struct accelerator_t
{
const KerxSubTableFormat0 &table;
hb_aat_apply_context_t *c;
inline accelerator_t (const KerxSubTableFormat0 &table_,
hb_aat_apply_context_t *c_) :
table (table_), c (c_) {}
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{ return table.get_kerning (left, right, c); }
};
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (pairs.sanitize (c)));
return_trace (likely (c->check_struct (this) &&
pairs.sanitize (c)));
}
protected:
@ -143,12 +176,12 @@ struct KerxSubTableFormat1
if (flags & Reset)
{
depth = 0;
depth = 0;
}
if (flags & Push)
{
if (likely (depth < ARRAY_LENGTH (stack)))
if (likely (depth < ARRAY_LENGTH (stack)))
stack[depth++] = buffer->idx;
else
depth = 0; /* Probably not what CoreText does, but better? */
@ -157,14 +190,14 @@ struct KerxSubTableFormat1
if (entry->data.kernActionIndex != 0xFFFF)
{
const FWORD *actions = &kernAction[entry->data.kernActionIndex];
if (!c->sanitizer.check_array (actions, depth))
if (!c->sanitizer.check_array (actions, depth))
{
depth = 0;
return false;
}
hb_mask_t kern_mask = c->plan->kern_mask;
for (unsigned int i = 0; i < depth; i++)
for (unsigned int i = 0; i < depth; i++)
{
/* Apparently, when spec says "Each pops one glyph from the kerning stack
* and applies the kerning value to it.", it doesn't mean it in that order.
@ -201,6 +234,9 @@ struct KerxSubTableFormat1
if (!c->plan->requested_kerning)
return false;
if (header.tupleCount)
return_trace (false); /* TODO kerxTupleKern */
driver_context_t dc (this, c);
StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face);
@ -236,7 +272,7 @@ struct KerxSubTableFormat2
unsigned int offset = l + r;
const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset);
if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
return *v;
return kerxTupleKern (*v, header.tupleCount, this, c);
}
inline bool apply (hb_aat_apply_context_t *c) const
@ -253,15 +289,6 @@ struct KerxSubTableFormat2
return_trace (true);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (rowWidth.sanitize (c) &&
leftClassTable.sanitize (c, this) &&
rightClassTable.sanitize (c, this) &&
c->check_range (this, array)));
}
struct accelerator_t
{
const KerxSubTableFormat2 &table;
@ -275,6 +302,15 @@ struct KerxSubTableFormat2
{ return table.get_kerning (left, right, c); }
};
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
leftClassTable.sanitize (c, this) &&
rightClassTable.sanitize (c, this) &&
c->check_range (this, array)));
}
protected:
KerxSubTableHeader header;
HBUINT32 rowWidth; /* The width, in bytes, of a row in the table. */
@ -482,7 +518,7 @@ struct KerxSubTableFormat6
if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
return *v;
return kerxTupleKern (*v, header.tupleCount, &(this+vector), c);
}
else
{
@ -492,7 +528,7 @@ struct KerxSubTableFormat6
unsigned int offset = l + r;
const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
return *v;
return kerxTupleKern (*v, header.tupleCount, &(this+vector), c);
}
}
@ -523,7 +559,9 @@ struct KerxSubTableFormat6
u.s.rowIndexTable.sanitize (c, this) &&
u.s.columnIndexTable.sanitize (c, this) &&
c->check_range (this, u.s.array)
))));
)) &&
(header.tupleCount == 0 ||
c->check_range (this, vector))));
}
struct accelerator_t
@ -559,8 +597,9 @@ struct KerxSubTableFormat6
LOffsetTo<UnsizedArrayOf<FWORD>, false> array;
} s;
} u;
LOffsetTo<UnsizedArrayOf<FWORD>, false> vector;
public:
DEFINE_SIZE_STATIC (32);
DEFINE_SIZE_STATIC (36);
};
struct KerxTable
@ -642,9 +681,8 @@ struct kerx
{
bool reverse;
if (table->u.header.coverage & (KerxTable::CrossStream | KerxTable::Variation) ||
table->u.header.tupleCount)
goto skip; /* We do NOT handle cross-stream or variation kerning. */
if (table->u.header.coverage & (KerxTable::CrossStream))
goto skip; /* We do NOT handle cross-stream. */
if (HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
bool (table->u.header.coverage & KerxTable::Vertical))

View File

@ -136,7 +136,7 @@ struct TrackData
/* TODO bfind() */
hb_array_t<Fixed> size_table ((base+sizeTable).arrayZ, sizes);
unsigned int size_index;
for (size_index = 0; size_index < sizes; size_index++)
for (size_index = 0; size_index < sizes - 1; size_index++)
if (size_table[size_index].to_float () >= csspx)
break;

View File

@ -487,8 +487,8 @@ hb_blob_t::try_make_writable (void)
#if defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
#else
# ifndef _O_BINARY
# define _O_BINARY 0
# ifndef O_BINARY
# define O_BINARY 0
# endif
#endif
@ -540,7 +540,7 @@ hb_blob_create_from_file (const char *file_name)
hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
if (unlikely (!file)) return hb_blob_get_empty ();
int fd = open (file_name, O_RDONLY | _O_BINARY, 0);
int fd = open (file_name, O_RDONLY | O_BINARY, 0);
if (unlikely (fd == -1)) goto fail_without_close;
struct stat st;

View File

@ -58,7 +58,7 @@ hb_buffer_serialize_list_formats (void)
* @str is a valid buffer serialization format, use
* hb_buffer_serialize_list_formats() to get the list of supported formats.
*
* Return value:
* Return value:
* The parsed #hb_buffer_serialize_format_t.
*
* Since: 0.9.7
@ -319,7 +319,7 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
* ## json
* TODO.
*
* Return value:
* Return value:
* The number of serialized items.
*
* Since: 0.9.7
@ -425,14 +425,14 @@ parse_int (const char *pp, const char *end, int32_t *pv)
* hb_buffer_deserialize_glyphs:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len):
* @buf_len:
* @buf_len:
* @end_ptr: (out):
* @font:
* @format:
* @font:
* @format:
*
*
*
* Return value:
*
* Return value:
*
* Since: 0.9.7
**/

View File

@ -89,11 +89,12 @@ typedef struct hb_glyph_info_t
* of each line after line-breaking, or limiting
* the reshaping to a small piece around the
* breaking point only.
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*/
typedef enum { /*< flags >*/
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
HB_GLYPH_FLAG_DEFINED = 0x00000001 /*< skip >*/ /* OR of all defined flags */
HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t

View File

@ -45,7 +45,7 @@ _hb_options_init (void)
{
hb_options_union_t u;
u.i = 0;
u.opts.initialized = 1;
u.opts.initialized = true;
const char *c = getenv ("HB_OPTIONS");
if (c)

View File

@ -444,6 +444,18 @@ HB_EXTERN void
hb_variation_to_string (hb_variation_t *variation,
char *buf, unsigned int size);
/**
* hb_color_t:
* ARGB data type for holding color values.
*
* Since: REPLACEME
*/
typedef uint32_t hb_color_t;
#define hb_color_get_alpha(color) (color & 0xFF)
#define hb_color_get_red(color) ((color >> 8) & 0xFF)
#define hb_color_get_green(color) ((color >> 16) & 0xFF)
#define hb_color_get_blue(color) ((color >> 24) & 0xFF)
HB_END_DECLS

View File

@ -643,7 +643,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
CFStringRef string_ref = nullptr;
CTLineRef line = nullptr;
if (0)
if (false)
{
resize_and_retry:
DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
@ -1054,7 +1054,7 @@ resize_and_retry:
*
* https://crbug.com/419769
*/
if (0)
if (false)
{
/* Make sure all runs had the expected direction. */
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);

View File

@ -146,12 +146,6 @@ hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
hb_unicode_decompose_compatibility_func_t func,
void *user_data, hb_destroy_func_t destroy);
/**
* hb_unicode_decompose_compatibility:
*
*
* Deprecated: 2.0.0
**/
HB_EXTERN HB_DEPRECATED unsigned int
hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
hb_codepoint_t u,

View File

@ -103,7 +103,7 @@ hb_font_get_nominal_glyph_default (hb_font_t *font,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
if (font->has_nominal_glyphs_func ())
if (font->has_nominal_glyphs_func_set ())
{
return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0);
}
@ -121,7 +121,7 @@ hb_font_get_nominal_glyphs_default (hb_font_t *font,
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
if (font->has_nominal_glyph_func ())
if (font->has_nominal_glyph_func_set ())
{
for (unsigned int i = 0; i < count; i++)
{
@ -176,7 +176,7 @@ hb_font_get_glyph_h_advance_default (hb_font_t *font,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
{
if (font->has_glyph_h_advances_func ())
if (font->has_glyph_h_advances_func_set ())
{
hb_position_t ret;
font->get_glyph_h_advances (1, &glyph, 0, &ret, 0);
@ -200,7 +200,7 @@ hb_font_get_glyph_v_advance_default (hb_font_t *font,
hb_codepoint_t glyph,
void *user_data HB_UNUSED)
{
if (font->has_glyph_v_advances_func ())
if (font->has_glyph_v_advances_func_set ())
{
hb_position_t ret;
font->get_glyph_v_advances (1, &glyph, 0, &ret, 0);
@ -220,7 +220,7 @@ hb_font_get_glyph_h_advances_default (hb_font_t* font,
unsigned int advance_stride,
void *user_data HB_UNUSED)
{
if (font->has_glyph_h_advance_func ())
if (font->has_glyph_h_advance_func_set ())
{
for (unsigned int i = 0; i < count; i++)
{
@ -252,7 +252,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
unsigned int advance_stride,
void *user_data HB_UNUSED)
{
if (font->has_glyph_v_advance_func ())
if (font->has_glyph_v_advance_func_set ())
{
for (unsigned int i = 0; i < count; i++)
{
@ -687,10 +687,16 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
bool
hb_font_t::has_func_set (unsigned int i)
{
return this->klass->get.array[i] != _hb_font_funcs_default.get.array[i];
}
bool
hb_font_t::has_func (unsigned int i)
{
return (this->klass->get.array[i] != _hb_font_funcs_default.get.array[i]) ||
return has_func_set (i) ||
(parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
}

View File

@ -171,6 +171,7 @@ struct hb_font_t
/* Public getters */
HB_INTERNAL bool has_func (unsigned int i);
HB_INTERNAL bool has_func_set (unsigned int i);
/* has_* ... */
#define HB_FONT_FUNC_IMPLEMENT(name) \
@ -180,6 +181,13 @@ struct hb_font_t
hb_font_funcs_t *funcs = this->klass; \
unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
return has_func (i); \
} \
bool \
has_##name##_func_set (void) \
{ \
hb_font_funcs_t *funcs = this->klass; \
unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
return has_func_set (i); \
}
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT

View File

@ -204,7 +204,7 @@ struct hb_dispatch_context_t
* The same argument can be made re GSUB/GPOS/GDEF, but there, the table
* structure is so complicated that by checking all offsets at sanitize() time,
* we make the code much simpler in other methods, as offsets and referenced
* objectes do not need to be validated at each use site.
* objects do not need to be validated at each use site.
*/
/* This limits sanitizing time on really broken fonts. */
@ -652,6 +652,7 @@ template <typename Type>
struct BEInt<Type, 1>
{
public:
typedef Type type;
inline void set (Type V)
{
v = V;
@ -666,6 +667,7 @@ template <typename Type>
struct BEInt<Type, 2>
{
public:
typedef Type type;
inline void set (Type V)
{
v[0] = (V >> 8) & 0xFF;
@ -682,6 +684,7 @@ template <typename Type>
struct BEInt<Type, 3>
{
public:
typedef Type type;
inline void set (Type V)
{
v[0] = (V >> 16) & 0xFF;
@ -700,6 +703,7 @@ template <typename Type>
struct BEInt<Type, 4>
{
public:
typedef Type type;
inline void set (Type V)
{
v[0] = (V >> 24) & 0xFF;

View File

@ -172,7 +172,7 @@ struct hb_map_t
inline bool is_empty (void) const
{
return population != 0;
return population == 0;
}
inline unsigned int get_population () const

View File

@ -49,7 +49,7 @@ static inline Type const & Null (void) {
}
#define Null(Type) Null<Type>()
/* Specializaitons for arbitrary-content Null objects expressed in bytes. */
/* Specializations for arbitrary-content Null objects expressed in bytes. */
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
} /* Close namespace. */ \
extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
@ -62,7 +62,7 @@ static inline Type const & Null (void) {
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
/* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
extern HB_INTERNAL const Type _hb_Null_##Type; \
template <> \

View File

@ -160,7 +160,7 @@ typedef struct OffsetTable
memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
/* 4-byte allignment. */
/* 4-byte alignment. */
c->align (4);
const char *end = (const char *) c->head;

View File

@ -56,6 +56,7 @@ namespace OT {
template <typename Type, unsigned int Size>
struct IntType
{
typedef Type type;
inline void set (Type i) { v.set (i); }
inline operator Type(void) const { return v; }
inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
@ -161,6 +162,8 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
template <typename Type, bool has_null=true>
struct Offset : Type
{
typedef Type type;
inline bool is_null (void) const { return has_null && 0 == *this; }
inline void *serialize (hb_serialize_context_t *c, const void *base)

View File

@ -39,25 +39,30 @@ namespace OT {
struct LayerRecord
{
friend struct COLR;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
protected:
GlyphID glyphid; /* Glyph ID of layer glyph */
HBUINT16 colorIdx; /* Index value to use with a selected color palette */
public:
GlyphID glyphId; /* Glyph ID of layer glyph */
HBUINT16 colorIdx; /* Index value to use with a
* selected color palette.
* An index value of 0xFFFF
* is a special case indicating
* that the text foreground
* color (defined by a
* higher-level client) should
* be used and shall not be
* treated as actual index
* into CPAL ColorRecord array. */
public:
DEFINE_SIZE_STATIC (4);
};
struct BaseGlyphRecord
{
friend struct COLR;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -65,28 +70,64 @@ struct BaseGlyphRecord
}
inline int cmp (hb_codepoint_t g) const {
return g < glyphid ? -1 : g > glyphid ? 1 : 0;
return g < glyphId ? -1 : g > glyphId ? 1 : 0;
}
protected:
GlyphID glyphid; /* Glyph ID of reference glyph */
HBUINT16 firstLayerIdx; /* Index to the layer record */
HBUINT16 numLayers; /* Number of color layers associated with this glyph */
static int cmp (const void *pa, const void *pb)
{
const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
return b->cmp (*a);
}
public:
GlyphID glyphId; /* Glyph ID of reference glyph */
HBUINT16 firstLayerIdx; /* Index (from beginning of
* the Layer Records) to the
* layer record. There will be
* numLayers consecutive entries
* for this base glyph. */
HBUINT16 numLayers; /* Number of color layers
* associated with this glyph */
public:
DEFINE_SIZE_STATIC (6);
};
static int compare_bgr (const void *pa, const void *pb)
{
const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
return b->cmp (*a);
}
struct COLR
{
static const hb_tag_t tableTag = HB_OT_TAG_COLR;
inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
unsigned int *first_layer /* OUT */,
unsigned int *num_layers /* OUT */) const
{
const BaseGlyphRecord* record;
record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
sizeof (BaseGlyphRecord), BaseGlyphRecord::cmp);
if (unlikely (!record))
return false;
if (first_layer) *first_layer = record->firstLayerIdx;
if (num_layers) *num_layers = record->numLayers;
return true;
}
inline bool get_layer_record (unsigned int record,
hb_codepoint_t *glyph_id /* OUT */,
unsigned int *color_index /* OUT */) const
{
if (unlikely (record >= numLayers))
{
*glyph_id = 0;
*color_index = 0xFFFF;
return false;
}
const LayerRecord &layer = (this+layersZ)[record];
if (glyph_id) *glyph_id = layer.glyphId;
if (color_index) *color_index = layer.colorIdx;
return true;
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -95,45 +136,14 @@ struct COLR
(this+layersZ).sanitize (c, numLayers)));
}
inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
unsigned int *first_layer /* OUT */,
unsigned int *num_layers /* OUT */) const
{
const BaseGlyphRecord* record;
record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
sizeof (BaseGlyphRecord), compare_bgr);
if (unlikely (!record))
return false;
*first_layer = record->firstLayerIdx;
*num_layers = record->numLayers;
return true;
}
inline bool get_layer_record (unsigned int record,
hb_codepoint_t *glyph_id /* OUT */,
unsigned int *palette_index /* OUT */) const
{
if (unlikely (record >= numLayers))
{
*glyph_id = 0;
*palette_index = 0xFFFF;
return false;
}
const LayerRecord &layer = (this+layersZ)[record];
*glyph_id = layer.glyphid;
*palette_index = layer.colorIdx;
return true;
}
protected:
HBUINT16 version; /* Table version number */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */
HBUINT16 version; /* Table version number (starts at 0). */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */
LOffsetTo<UnsizedArrayOf<BaseGlyphRecord>, false>
baseGlyphsZ; /* Offset to Base Glyph records. */
LOffsetTo<UnsizedArrayOf<LayerRecord>, false>
layersZ; /* Offset to Layer Records */
HBUINT16 numLayers; /* Number of Layer Records */
layersZ; /* Offset to Layer Records. */
HBUINT16 numLayers; /* Number of Layer Records. */
public:
DEFINE_SIZE_STATIC (14);
};

View File

@ -29,53 +29,8 @@
#define HB_OT_COLOR_CPAL_TABLE_HH
#include "hb-open-type.hh"
/*
* Following parts to be moved to a public header.
*/
/**
* hb_ot_color_t:
* ARGB data type for holding color values.
*
* Since: REPLACEME
*/
typedef uint32_t hb_ot_color_t;
/**
* hb_ot_color_palette_flags_t:
* @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
* @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background.
* @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background.
*
* Since: REPLACEME
*/
typedef enum { /*< flags >*/
HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u,
HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u,
HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
} hb_ot_color_palette_flags_t;
// HB_EXTERN unsigned int
// hb_ot_color_get_palette_count (hb_face_t *face);
// HB_EXTERN unsigned int
// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
// HB_EXTERN hb_ot_color_palette_flags_t
// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
// HB_EXTERN unsigned int
// hb_ot_color_get_palette_colors (hb_face_t *face,
// unsigned int palette, /* default=0 */
// unsigned int start_offset,
// unsigned int *color_count /* IN/OUT */,
// hb_ot_color_t *colors /* OUT */);
#include "hb-ot-color.h"
#include "hb-ot-name.h"
/*
@ -93,30 +48,47 @@ struct CPALV1Tail
friend struct CPAL;
inline bool
sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const
sanitize (hb_sanitize_context_t *c, const void *base,
unsigned int palettes, unsigned int paletteEntries) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
(base+paletteFlagsZ).sanitize (c, palettes) &&
(base+paletteLabelZ).sanitize (c, palettes) &&
(base+paletteEntryLabelZ).sanitize (c, palettes));
(base+paletteEntryLabelZ).sanitize (c, paletteEntries));
}
private:
inline hb_ot_color_palette_flags_t
get_palette_flags (const void *base, unsigned int palette) const
get_palette_flags (const void *base, unsigned int palette,
unsigned int palettes_count) const
{
// range checked at the CPAL caller
if (unlikely (palette >= palettes_count))
return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette];
}
inline unsigned int
get_palette_name_id (const void *base, unsigned int palette) const
get_palette_name_id (const void *base, unsigned int palette,
unsigned int palettes_count) const
{
// range checked at the CPAL caller
if (unlikely (palette >= palettes_count))
return HB_NAME_ID_INVALID;
return (base+paletteLabelZ)[palette];
}
inline unsigned int
get_palette_entry_name_id (const void *base, unsigned int palette_entry,
unsigned int palettes_entries_count) const
{
if (unlikely (palette_entry >= palettes_entries_count))
return HB_NAME_ID_INVALID;
return (base+paletteEntryLabelZ)[palette_entry];
}
protected:
LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
paletteFlagsZ; /* Offset from the beginning of CPAL table to
@ -143,22 +115,22 @@ struct CPAL
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this) && // it checks colorRecordIndices also
// see #get_size
if (unlikely (!(c->check_struct (this) && /* it checks colorRecordIndices also
* See #get_size */
(this+colorRecordsZ).sanitize (c, numColorRecords))))
return_trace (false);
// Check for indices sanity so no need for doing it runtime
/* Check for indices sanity so no need for doing it runtime */
for (unsigned int i = 0; i < numPalettes; ++i)
if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords))
return_trace (false);
// If version is zero, we are done here; otherwise we need to check tail also
/* If version is zero, we are done here; otherwise we need to check tail also */
if (version == 0)
return_trace (true);
const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
return_trace (likely (v1.sanitize (c, this, numPalettes)));
return_trace (likely (v1.sanitize (c, this, numPalettes, numPaletteEntries)));
}
inline unsigned int get_size (void) const
@ -168,36 +140,48 @@ struct CPAL
inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
{
if (unlikely (version == 0 || palette >= numPalettes))
if (unlikely (version == 0))
return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
return cpal1.get_palette_flags (this, palette);
return cpal1.get_palette_flags (this, palette, numPalettes);
}
inline unsigned int get_palette_name_id (unsigned int palette) const
{
if (unlikely (version == 0 || palette >= numPalettes))
return 0xFFFF;
if (unlikely (version == 0))
return HB_NAME_ID_INVALID;
const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
return cpal1.get_palette_name_id (this, palette);
return cpal1.get_palette_name_id (this, palette, numPalettes);
}
inline unsigned int get_palette_entry_name_id (unsigned int palette_entry) const
{
if (unlikely (version == 0))
return HB_NAME_ID_INVALID;
const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
return cpal1.get_palette_entry_name_id (this, palette_entry, numPaletteEntries);
}
inline unsigned int get_palette_count () const
{
return numPalettes;
}
{ return numPalettes; }
inline hb_ot_color_t
get_color_record_argb (unsigned int color_index, unsigned int palette) const
inline unsigned int get_palette_entries_count () const
{ return numPaletteEntries; }
bool
get_color_record_argb (unsigned int color_index, unsigned int palette, hb_color_t* color) const
{
if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
return 0;
return false;
// No need for more range check as it is already done on #sanitize
/* No need for more range check as it is already done on #sanitize */
const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
return color_records[colorRecordIndicesZ[palette] + color_index];
if (color)
*color = color_records[colorRecordIndicesZ[palette] + color_index];
return true;
}
protected:

View File

@ -28,33 +28,56 @@
#include "hb-open-type.hh"
#include "hb-ot-color-colr-table.hh"
#include "hb-ot-color-cpal-table.hh"
#include "hb-ot-face.hh"
#include "hb-ot.h"
#include <stdlib.h>
#include <string.h>
#include "hb-ot-layout.hh"
#include "hb-shaper.hh"
#if 0
HB_MARK_AS_FLAG_T (hb_ot_color_palette_flags_t)
//HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) Hmm?
static inline const OT::COLR&
_get_colr (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::COLR);
return *(hb_ot_face_data (face)->colr.get ());
return *(hb_ot_face_data (face)->COLR.get ());
}
static inline const OT::CPAL&
_get_cpal (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CPAL);
return *(hb_ot_face_data (face)->cpal.get ());
return *(hb_ot_face_data (face)->CPAL.get ());
}
/**
* hb_ot_color_has_cpal_data:
* @face: a font face.
*
* Returns: whether CPAL table is available.
*
* Since: REPLACEME
*/
hb_bool_t
hb_ot_color_has_cpal_data (hb_face_t *face)
{
return &_get_cpal (face) != &Null(OT::CPAL);
}
/**
* hb_ot_color_has_colr_data:
* @face: a font face.
*
* Returns: whether COLR table is available.
*
* Since: REPLACEME
*/
hb_bool_t
hb_ot_color_has_colr_data (hb_face_t *face)
{
return &_get_colr (face) != &Null(OT::COLR);
}
/**
* hb_ot_color_get_palette_count:
@ -68,14 +91,12 @@ _get_cpal (hb_face_t *face)
unsigned int
hb_ot_color_get_palette_count (hb_face_t *face)
{
const OT::CPAL& cpal = _get_cpal (face);
return cpal.get_palette_count ();
return _get_cpal (face).get_palette_count ();
}
/**
* hb_ot_color_get_palette_name_id:
* @face: a font face.
* @face: a font face.
* @palette: the index of the color palette whose name is being requested.
*
* Retrieves the name id of a color palette. For example, a color font can
@ -89,33 +110,27 @@ hb_ot_color_get_palette_count (hb_face_t *face)
*
* Since: REPLACEME
*/
unsigned int
hb_name_id_t
hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette)
{
const OT::CPAL& cpal = _get_cpal (face);
return cpal.get_palette_name_id (palette);
return _get_cpal (face).get_palette_name_id (palette);
}
/**
* hb_ot_color_get_palette_flags:
* @face: a font face
* @palette: the index of the color palette whose flags are being requested
* hb_ot_color_get_palette_entry_name_id:
* @face: a font face.
* @palette_entry:
*
* Returns: the flags for the requested color palette. If @face has no colors,
* or if @palette is not between 0 and hb_ot_color_get_palette_count(),
* the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT.
* Returns: Name ID associated with a palette entry, e.g. eye color
*
* Since: REPLACEME
*/
hb_ot_color_palette_flags_t
hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
hb_name_id_t
hb_ot_color_get_palette_entry_name_id (hb_face_t *face, unsigned int palette_entry)
{
const OT::CPAL& cpal = _get_cpal(face);
return cpal.get_palette_flags (palette);
return _get_cpal (face).get_palette_entry_name_id (palette_entry);
}
/**
* hb_ot_color_get_palette_colors:
* @face: a font face.
@ -125,8 +140,8 @@ hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
* @color_count: (inout) (optional): on input, how many colors
* can be maximally stored into the @colors array;
* on output, how many colors were actually stored.
* @colors: (array length=color_count) (optional):
* an array of #hb_ot_color_t records. After calling
* @colors: (array length=color_count) (out) (optional):
* an array of #hb_color_t records. After calling
* this function, @colors will be filled with
* the palette colors. If @colors is NULL, the function
* will just return the number of total colors
@ -144,38 +159,92 @@ hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
* Since: REPLACEME
*/
unsigned int
hb_ot_color_get_palette_colors (hb_face_t *face,
unsigned int palette, /* default=0 */
unsigned int start_offset,
unsigned int *color_count /* IN/OUT */,
hb_ot_color_t *colors /* OUT */)
hb_ot_color_get_palette_colors (hb_face_t *face,
unsigned int palette, /* default=0 */
unsigned int start_offset,
unsigned int *colors_count /* IN/OUT. May be NULL. */,
hb_color_t *colors /* OUT. May be NULL. */)
{
const OT::CPAL& cpal = _get_cpal(face);
if (unlikely (palette >= cpal.numPalettes))
if (unlikely (palette >= cpal.get_palette_count ()))
{
if (color_count) *color_count = 0;
if (colors_count) *colors_count = 0;
return 0;
}
const OT::ColorRecord* crec = &cpal.offsetFirstColorRecord (&cpal);
crec += cpal.colorRecordIndices[palette];
unsigned int num_results = 0;
if (likely (color_count && colors))
if (colors_count)
{
for (unsigned int i = start_offset;
i < cpal.numPaletteEntries && num_results < *color_count; ++i)
unsigned int platte_count;
platte_count = MIN<unsigned int>(*colors_count,
cpal.get_palette_entries_count () - start_offset);
for (unsigned int i = 0; i < platte_count; i++)
{
hb_ot_color_t* result = &colors[num_results];
result->red = crec[i].red;
result->green = crec[i].green;
result->blue = crec[i].blue;
result->alpha = crec[i].alpha;
++num_results;
if (cpal.get_color_record_argb(start_offset + i, palette, &colors[num_results]))
++num_results;
}
}
if (likely (color_count)) *color_count = num_results;
return cpal.numPaletteEntries;
if (likely (colors_count)) *colors_count = num_results;
return cpal.get_palette_entries_count ();
}
/**
* hb_ot_color_get_color_layers:
* @face: a font face.
* @gid:
* @start_offset:
* @count: (inout) (optional):
* @gids: (array length=count) (out) (optional):
* @color_indices: (array length=count) (out) (optional):
*
* Returns:
*
* Since: REPLACEME
*/
unsigned int
hb_ot_color_get_color_layers (hb_face_t *face,
hb_codepoint_t gid,
unsigned int start_offset,
unsigned int *count /* IN/OUT. May be NULL. */,
hb_codepoint_t *gids /* OUT. May be NULL. */,
unsigned int *color_indices /* OUT. May be NULL. */)
{
const OT::COLR& colr = _get_colr (face);
unsigned int num_results = 0;
unsigned int start_layer_index, num_layers = 0;
if (colr.get_base_glyph_record (gid, &start_layer_index, &num_layers))
{
if (count)
{
unsigned int layer_count = MIN<unsigned int>(*count, num_layers - start_offset);
for (unsigned int i = 0; i < layer_count; i++)
{
if (colr.get_layer_record (start_layer_index + start_offset + i,
&gids[num_results], &color_indices[num_results]))
++num_results;
}
}
}
if (likely (count)) *count = num_results;
return num_layers;
}
/**
* hb_ot_color_get_palette_flags:
* @face: a font face
* @palette: the index of the color palette whose flags are being requested
*
* Returns: the flags for the requested color palette. If @face has no colors,
* or if @palette is not between 0 and hb_ot_color_get_palette_count(),
* the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT.
*
* Since: REPLACEME
*/
hb_ot_color_palette_flags_t
hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
{
const OT::CPAL& cpal = _get_cpal(face);
return cpal.get_palette_flags (palette);
}
#endif

90
src/hb-ot-color.h Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright © 2016 Google, Inc.
* Copyright © 2018 Khaled Hosny
* 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.
*
* Google Author(s): Sascha Brawer
*/
#ifndef HB_OT_H_IN
#error "Include <hb-ot.h> instead."
#endif
#ifndef HB_OT_COLOR_H
#define HB_OT_COLOR_H
#include "hb.h"
#include "hb-ot-name.h"
HB_BEGIN_DECLS
HB_EXTERN hb_bool_t
hb_ot_color_has_cpal_data (hb_face_t *face);
HB_EXTERN hb_bool_t
hb_ot_color_has_colr_data (hb_face_t *face);
HB_EXTERN unsigned int
hb_ot_color_get_palette_count (hb_face_t *face);
HB_EXTERN hb_name_id_t
hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
HB_EXTERN hb_name_id_t
hb_ot_color_get_palette_entry_name_id (hb_face_t *face, unsigned int palette_entry);
HB_EXTERN unsigned int
hb_ot_color_get_palette_colors (hb_face_t *face,
unsigned int palette, /* default=0 */
unsigned int start_offset,
unsigned int *color_count /* IN/OUT. May be NULL. */,
hb_color_t *colors /* OUT. May be NULL. */);
HB_EXTERN unsigned int
hb_ot_color_get_color_layers (hb_face_t *face,
hb_codepoint_t gid,
unsigned int start_offset,
unsigned int *count /* IN/OUT. May be NULL. */,
hb_codepoint_t *gids /* OUT. May be NULL. */,
unsigned int *color_indices /* OUT. May be NULL. */);
/**
* hb_ot_color_palette_flags_t:
* @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
* @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background.
* @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background.
*
* Since: REPLACEME
*/
typedef enum { /*< flags >*/
HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u,
HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u,
HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
} hb_ot_color_palette_flags_t;
HB_EXTERN hb_ot_color_palette_flags_t
hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
HB_END_DECLS
#endif /* HB_OT_COLOR_H */

View File

@ -47,6 +47,9 @@
/* OpenType shaping. */ \
HB_OT_TABLE(OT, JSTF) \
HB_OT_TABLE(OT, BASE) \
/* OpenType color */ \
HB_OT_TABLE(OT, COLR) \
HB_OT_TABLE(OT, CPAL) \
/* AAT shaping. */ \
HB_OT_TABLE(AAT, morx) \
HB_OT_TABLE(AAT, kerx) \

View File

@ -718,7 +718,7 @@ struct Lookup
return_trace (true);
}
/* Older compileres need this to NOT be locally defined in a function. */
/* Older compilers need this to NOT be locally defined in a function. */
template <typename TSubTable>
struct SubTableSubsetWrapper
{
@ -1475,7 +1475,7 @@ struct VarRegionAxis
struct VarRegionList
{
inline float evaluate (unsigned int region_index,
int *coords, unsigned int coord_len) const
const int *coords, unsigned int coord_len) const
{
if (unlikely (region_index >= regionCount))
return 0.;
@ -1526,7 +1526,7 @@ struct VarData
{ return itemCount * get_row_size (); }
inline float get_delta (unsigned int inner,
int *coords, unsigned int coord_count,
const int *coords, unsigned int coord_count,
const VarRegionList &regions) const
{
if (unlikely (inner >= itemCount))
@ -1591,7 +1591,7 @@ struct VarData
struct VariationStore
{
inline float get_delta (unsigned int outer, unsigned int inner,
int *coords, unsigned int coord_count) const
const int *coords, unsigned int coord_count) const
{
if (unlikely (outer >= dataSets.len))
return 0.;
@ -1602,7 +1602,7 @@ struct VariationStore
}
inline float get_delta (unsigned int index,
int *coords, unsigned int coord_count) const
const int *coords, unsigned int coord_count) const
{
unsigned int outer = index >> 16;
unsigned int inner = index & 0xFFFF;

View File

@ -388,7 +388,7 @@ struct GDEF
{ return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
/* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
* glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
* glyph class and other bits, and high 8-bit the mark attachment type (if any).
* Not to be confused with lookup_props which is very similar. */
inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
{

View File

@ -1164,7 +1164,7 @@ struct MarkBasePosFormat1
))
break;
skippy_iter.reject ();
} while (1);
} while (true);
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }

View File

@ -103,7 +103,7 @@ struct SingleSubstFormat1
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
deltaGlyphID.set (delta); /* TODO(serialize) overflow? */
return_trace (true);
}

View File

@ -199,8 +199,6 @@ struct hb_collect_glyphs_context_t :
after = old_after;
recursed_lookups->add (lookup_index);
return;
}
hb_face_t *face;
@ -582,7 +580,7 @@ struct hb_ot_apply_context_t :
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
/* In the only place that the MULTIPLIED bit is used, Uniscribe
* seems to only care about the "last" transformation between
* Ligature and Multiple substitions. Ie. if you ligate, expand,
* Ligature and Multiple substitutions. Ie. if you ligate, expand,
* and ligate again, it forgives the multiplication and acts as
* if only ligation happened. As such, clear MULTIPLIED bit.
*/
@ -903,7 +901,7 @@ static inline bool match_input (hb_ot_apply_context_t *c,
}
static inline bool ligate_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
unsigned int match_length,
hb_codepoint_t lig_glyph,
unsigned int total_component_count)

View File

@ -1115,8 +1115,8 @@ hb_ot_layout_get_size_params (hb_face_t *face,
/**
* hb_ot_layout_feature_get_name_ids:
* @face: #hb_face_t to work upon
* @table_tag:
* @feature_index:
* @table_tag: table tag to query, "GSUB" or "GPOS".
* @feature_index: index of feature to query.
* @label_id: (out) (allow-none): The name table name ID that specifies a string
* for a user-interface label for this feature. (May be NULL.)
* @tooltip_id: (out) (allow-none): The name table name ID that specifies a string
@ -1188,10 +1188,10 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face,
}
/**
* hb_ot_layout_feature_get_characters::
* hb_ot_layout_feature_get_characters:
* @face: #hb_face_t to work upon
* @table_tag:
* @feature_index:
* @table_tag: table tag to query, "GSUB" or "GPOS".
* @feature_index: index of feature to query.
* @start_offset: In case the resulting char_count was equal to its input value, there
* is a chance there were more characters on the tag so this API can be
* called with an offset till resulting char_count gets to a number

View File

@ -201,7 +201,7 @@ subtag_matches (const char *lang_str,
if (!ISALNUM (s[strlen (subtag)]))
return true;
lang_str = s + strlen (subtag);
} while (1);
} while (true);
}
static hb_bool_t

View File

@ -115,7 +115,7 @@ struct HVARVVAR
}
inline float get_advance_var (hb_codepoint_t glyph,
int *coords, unsigned int coord_count) const
const int *coords, unsigned int coord_count) const
{
unsigned int varidx = (this+advMap).map (glyph);
return (this+varStore).get_delta (varidx, coords, coord_count);

View File

@ -72,7 +72,7 @@ struct MVAR
}
inline float get_var (hb_tag_t tag,
int *coords, unsigned int coord_count) const
const int *coords, unsigned int coord_count) const
{
const VariationValueRecord *record;
record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,

View File

@ -30,6 +30,7 @@
#include "hb.h"
#include "hb-ot-color.h"
#include "hb-ot-font.h"
#include "hb-ot-layout.h"
#include "hb-ot-math.h"

View File

@ -64,7 +64,7 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
if (likely (!shaper_list)) {
for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
if (0)
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
else if (shapers[i].func == _hb_##shaper##_shape) \
@ -73,7 +73,7 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
#undef HB_SHAPER_IMPLEMENT
} else {
for (; *shaper_list; shaper_list++)
if (0)
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
else if (0 == strcmp (*shaper_list, #shaper)) \
@ -346,7 +346,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
_hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
} HB_STMT_END
if (0)
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
@ -501,7 +501,7 @@ hb_shape_plan_create_cached2 (hb_face_t *face,
/* Choose shaper. Adapted from hb_shape_plan_plan().
* Must choose shaper exactly the same way as that function. */
for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
if (0)
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
else if (0 == strcmp (*shaper_item, #shaper) && \

View File

@ -442,6 +442,7 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
* Return value:
*
* Since: 0.9.2
* Deprecated: 2.0.0
**/
unsigned int
hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,

View File

@ -38,9 +38,9 @@ HB_BEGIN_DECLS
#define HB_VERSION_MAJOR 2
#define HB_VERSION_MINOR 0
#define HB_VERSION_MICRO 0
#define HB_VERSION_MICRO 2
#define HB_VERSION_STRING "2.0.0"
#define HB_VERSION_STRING "2.0.2"
#define HB_VERSION_ATLEAST(major,minor,micro) \
((major)*10000+(minor)*100+(micro) <= \

View File

@ -33,6 +33,7 @@ TEST_PROGS = \
test-collect-unicodes \
test-common \
test-font \
test-map \
test-object \
test-set \
test-shape \
@ -171,13 +172,18 @@ symbols-tested.txt: $(TEST_PROGS)
$(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \
| grep ' U hb_' | sed 's/.* U hb_/hb_/' \
| sort | uniq > $@.tmp && mv $@.tmp $@
symbols-tested-or-deprecated.txt: symbols-tested.txt $(top_builddir)/src/harfbuzz-deprecated.def
$(AM_V_GEN)cat $^ | sort | uniq > $@.tmp; mv $@.tmp $@
symbols-exported.txt: $(top_builddir)/src/.libs/libharfbuzz.so
$(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \
| grep ' T ' | sed 's/.* T //' | grep -v '^\(_init\|_fini\)$$' \
| sort | uniq > $@.tmp && mv $@.tmp $@
symbols-untested.txt: symbols-tested.txt symbols-exported.txt
symbols-untested.txt: symbols-tested-or-deprecated.txt symbols-exported.txt
$(AM_V_GEN)diff $^ > $@.tmp; mv $@.tmp $@
CLEANFILES += symbols-tested.txt symbols-exported.txt symbols-untested.txt
CLEANFILES += symbols-tested.txt \
symbols-exported.txt \
symbols-untested.txt \
symbols-tested-or-deprecated.txt
check-symbols: symbols-untested.txt
@! cat $^ | grep .

View File

@ -47,27 +47,6 @@ typedef short bool;
HB_BEGIN_DECLS
static inline hb_face_t *
hb_subset_test_open_font (const char *font_path)
{
#if GLIB_CHECK_VERSION(2,37,2)
char *path = g_test_build_filename (G_TEST_DIST, font_path, NULL);
#else
char *path = g_strdup (font_path);
#endif
hb_blob_t *blob = hb_blob_create_from_file (path);
if (hb_blob_get_length (blob) == 0)
g_error ("Font not found.");
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
g_free (path);
return face;
}
static inline hb_subset_input_t *
hb_subset_test_create_input(const hb_set_t *codepoints)
{

View File

@ -277,6 +277,27 @@ G_STMT_START { \
} G_STMT_END
static inline hb_face_t *
hb_test_open_font_file (const char *font_path)
{
#if GLIB_CHECK_VERSION(2,37,2)
char *path = g_test_build_filename (G_TEST_DIST, font_path, NULL);
#else
char *path = g_strdup (font_path);
#endif
hb_blob_t *blob = hb_blob_create_from_file (path);
if (hb_blob_get_length (blob) == 0)
g_error ("Font not found.");
hb_face_t *face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
g_free (path);
return face;
}
HB_END_DECLS
#endif /* HB_TEST_H */

View File

@ -30,7 +30,7 @@
static void
test_collect_unicodes_format4 (void)
{
hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format4.ttf");
hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.format4.ttf");
hb_set_t *codepoints = hb_set_create();
hb_codepoint_t cp;
@ -52,7 +52,7 @@ test_collect_unicodes_format4 (void)
static void
test_collect_unicodes_format12 (void)
{
hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.format12.ttf");
hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.format12.ttf");
hb_set_t *codepoints = hb_set_create();
hb_codepoint_t cp;
@ -74,7 +74,7 @@ test_collect_unicodes_format12 (void)
static void
test_collect_unicodes (void)
{
hb_face_t *face = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_set_t *codepoints = hb_set_create();
hb_codepoint_t cp;

View File

@ -364,6 +364,71 @@ test_fontfuncs_subclassing (void)
hb_font_destroy (font2);
}
static hb_bool_t
nominal_glyph_func (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
hb_codepoint_t unicode HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
*glyph = 0;
return FALSE;
}
static unsigned int
nominal_glyphs_func (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
unsigned int count HB_UNUSED,
const hb_codepoint_t *first_unicode HB_UNUSED,
unsigned int unicode_stride HB_UNUSED,
hb_codepoint_t *first_glyph HB_UNUSED,
unsigned int glyph_stride HB_UNUSED,
void *user_data HB_UNUSED)
{
return 0;
}
static void
test_fontfuncs_parallels (void)
{
hb_blob_t *blob;
hb_face_t *face;
hb_font_funcs_t *ffuncs1;
hb_font_funcs_t *ffuncs2;
hb_font_t *font0;
hb_font_t *font1;
hb_font_t *font2;
blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
face = hb_face_create (blob, 0);
hb_blob_destroy (blob);
font0 = hb_font_create (face);
hb_face_destroy (face);
/* setup sub-font1 */
font1 = hb_font_create_sub_font (font0);
hb_font_destroy (font0);
ffuncs1 = hb_font_funcs_create ();
hb_font_funcs_set_nominal_glyph_func (ffuncs1, nominal_glyph_func, NULL, NULL);
hb_font_set_funcs (font1, ffuncs1, NULL, NULL);
hb_font_funcs_destroy (ffuncs1);
/* setup sub-font2 */
font2 = hb_font_create_sub_font (font1);
hb_font_destroy (font1);
ffuncs2 = hb_font_funcs_create ();
hb_font_funcs_set_nominal_glyphs_func (ffuncs1, nominal_glyphs_func, NULL, NULL);
hb_font_set_funcs (font2, ffuncs2, NULL, NULL);
hb_font_funcs_destroy (ffuncs2);
/* Just test that calling get_nominal_glyph doesn't infinite-loop. */
hb_codepoint_t glyph;
hb_font_get_nominal_glyph (font2, 0x0020u, &glyph);
hb_font_destroy (font2);
}
static void
test_font_empty (void)
@ -543,6 +608,7 @@ main (int argc, char **argv)
hb_test_add (test_fontfuncs_empty);
hb_test_add (test_fontfuncs_nil);
hb_test_add (test_fontfuncs_subclassing);
hb_test_add (test_fontfuncs_parallels);
hb_test_add (test_font_empty);
hb_test_add (test_font_properties);

114
test/api/test-map.c Normal file
View File

@ -0,0 +1,114 @@
/*
* 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"
/* Unit tests for hb-map.h */
static void
test_map_basic (void)
{
hb_map_t *empty = hb_map_get_empty ();
g_assert (hb_map_is_empty (empty));
g_assert (!hb_map_allocation_successful (empty));
hb_map_destroy (empty);
hb_map_t *m = hb_map_create ();
g_assert (hb_map_allocation_successful (m));
g_assert (hb_map_is_empty (m));
hb_map_set (m, 213, 223);
hb_map_set (m, 643, 675);
g_assert_cmpint (hb_map_get_population (m), ==, 2);
g_assert_cmpint (hb_map_get (m, 213), ==, 223);
g_assert (!hb_map_has (m, 123));
g_assert (hb_map_has (m, 213));
hb_map_del (m, 213);
g_assert (!hb_map_has (m, 213));
g_assert_cmpint (hb_map_get (m, 643), ==, 675);
hb_map_set (m, 237, 673);
g_assert (hb_map_has (m, 237));
hb_map_clear (m);
g_assert (!hb_map_has (m, 237));
g_assert (!hb_map_has (m, 643));
g_assert_cmpint (hb_map_get_population (m), ==, 0);
hb_map_destroy (m);
}
static void
test_map_userdata (void)
{
hb_map_t *m = hb_map_create ();
hb_user_data_key_t key[2];
int *data = (int *) malloc (sizeof (int));
*data = 3123;
hb_map_set_user_data (m, &key[0], data, free, TRUE);
g_assert_cmpint (*((int *) hb_map_get_user_data (m, &key[0])), ==, 3123);
int *data2 = (int *) malloc (sizeof (int));
*data2 = 6343;
hb_map_set_user_data (m, &key[0], data2, free, FALSE);
g_assert_cmpint (*((int *) hb_map_get_user_data (m, &key[0])), ==, 3123);
hb_map_set_user_data (m, &key[0], data2, free, TRUE);
g_assert_cmpint (*((int *) hb_map_get_user_data (m, &key[0])), ==, 6343);
hb_map_destroy (m);
}
static void
test_map_refcount (void)
{
hb_map_t *m = hb_map_create ();
hb_map_set (m, 213, 223);
g_assert_cmpint (hb_map_get (m, 213), ==, 223);
hb_map_t *m2 = hb_map_reference (m);
hb_map_destroy (m);
/* We copied its reference so it is still usable after one destroy */
g_assert (hb_map_has (m, 213));
g_assert (hb_map_has (m2, 213));
hb_map_destroy (m2);
/* Now you can't access them anymore */
}
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_map_basic);
hb_test_add (test_map_userdata);
hb_test_add (test_map_refcount);
return hb_test_run();
}

View File

@ -23,16 +23,13 @@
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <hb.h>
#include <hb-ft.h>
#include <hb-ot.h>
#include <glib.h>
#include "hb-test.h"
static const char *font_path = "fonts/Inconsolata-Regular.abc.ttf";
static const char *text = "abc";
@ -127,15 +124,9 @@ test_body (void)
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
hb_test_init (&argc, &argv);
#if GLIB_CHECK_VERSION(2,37,2)
gchar *default_path = g_test_build_filename (G_TEST_DIST, font_path, NULL);
#else
gchar *default_path = g_strdup (font_path);
#endif
char *path = argc > 1 && *argv[1] ? argv[1] : (char *) default_path;
char *path = argc > 1 && *argv[1] ? argv[1] : (char *) font_path;
if (argc > 2)
num_threads = atoi (argv[2]);
if (argc > 3)
@ -147,11 +138,7 @@ main (int argc, char **argv)
* https://github.com/harfbuzz/harfbuzz/issues/1191 */
hb_language_get_default ();
hb_blob_t *blob = hb_blob_create_from_file (path);
if (hb_blob_get_length (blob) == 0)
g_error ("Font not found.");
hb_face_t *face = hb_face_create (blob, 0);
hb_face_t *face = hb_test_open_font_file (path);
font = hb_font_create (face);
/* Fill the reference */
@ -170,9 +157,6 @@ main (int argc, char **argv)
hb_font_destroy (font);
hb_face_destroy (face);
hb_blob_destroy (blob);
g_free (default_path);
return 0;
}

View File

@ -1,5 +1,6 @@
/*
* Copyright © 2016 Google, Inc.
* Copyright © 2018 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
@ -98,27 +99,25 @@ static hb_face_t *cpal_v0 = NULL;
*/
static hb_face_t *cpal_v1 = NULL;
#if 0
#define assert_color_rgba(colors, i, r, g, b, a) G_STMT_START { \
const hb_ot_color_t *_colors = (colors); \
const hb_color_t *_colors = (colors); \
const size_t _i = (i); \
const uint8_t red = (r), green = (g), blue = (b), alpha = (a); \
if (_colors[_i].red != red) { \
if (hb_color_get_red (_colors[_i]) != red) { \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
"colors[" #i "].red", _colors[_i].red, "==", red, 'x'); \
"colors[" #i "]", _colors[_i], "==", red, 'x'); \
} \
if (_colors[_i].green != green) { \
if (hb_color_get_green (_colors[_i]) != green) { \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
"colors[" #i "].green", _colors[_i].green, "==", green, 'x'); \
"colors[" #i "]", _colors[_i], "==", green, 'x'); \
} \
if (_colors[_i].blue != blue) { \
if (hb_color_get_blue (_colors[_i]) != blue) { \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
"colors[" #i "].blue", colors[i].blue, "==", blue, 'x'); \
"colors[" #i "]", colors[_i], "==", blue, 'x'); \
} \
if (_colors[_i].alpha != alpha) { \
if (hb_color_get_alpha (_colors[_i]) != alpha) { \
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
"colors[" #i "].alpha", _colors[_i].alpha, "==", alpha, 'x'); \
"colors[" #i "]", _colors[_i], "==", alpha, 'x'); \
} \
} G_STMT_END
@ -136,19 +135,19 @@ static void
test_hb_ot_color_get_palette_name_id_empty (void)
{
/* numPalettes=0, so all calls are for out-of-bounds palette indices */
g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 0), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 1), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 0), ==, HB_NAME_ID_INVALID);
g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 1), ==, HB_NAME_ID_INVALID);
}
static void
test_hb_ot_color_get_palette_name_id_v0 (void)
{
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 0), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 1), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 0), ==, HB_NAME_ID_INVALID);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 1), ==, HB_NAME_ID_INVALID);
/* numPalettes=2, so palette #2 is out of bounds */
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 2), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 2), ==, HB_NAME_ID_INVALID);
}
@ -156,13 +155,14 @@ static void
test_hb_ot_color_get_palette_name_id_v1 (void)
{
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 0), ==, 257);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 1), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 1), ==, HB_NAME_ID_INVALID);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 2), ==, 258);
/* numPalettes=3, so palette #3 is out of bounds */
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 3), ==, 0xffff);
g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 3), ==, HB_NAME_ID_INVALID);
}
static void
test_hb_ot_color_get_palette_flags_empty (void)
{
@ -207,7 +207,7 @@ static void
test_hb_ot_color_get_palette_colors_v0 (void)
{
unsigned int num_colors = hb_ot_color_get_palette_colors (cpal_v0, 0, 0, NULL, NULL);
hb_ot_color_t *colors = (hb_ot_color_t*) alloca (num_colors * sizeof (hb_ot_color_t));
hb_color_t *colors = (hb_color_t*) alloca (num_colors * sizeof (hb_color_t));
size_t colors_size = num_colors * sizeof(*colors);
g_assert_cmpint (num_colors, ==, 2);
@ -243,7 +243,7 @@ test_hb_ot_color_get_palette_colors_v0 (void)
assert_color_rgba (colors, 1, 0x44, 0x44, 0x44, 0x44); /* untouched */
/* start_index > numPaletteEntries */
memset(colors, 0x44, colors_size);
memset (colors, 0x44, colors_size);
num_colors = 2;
g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 9876, &num_colors, colors), ==, 2);
g_assert_cmpint (num_colors, ==, 0);
@ -255,13 +255,13 @@ test_hb_ot_color_get_palette_colors_v0 (void)
static void
test_hb_ot_color_get_palette_colors_v1 (void)
{
hb_ot_color_t colors[3];
hb_color_t colors[3];
unsigned int num_colors = hb_ot_color_get_palette_colors (cpal_v1, 0, 0, NULL, NULL);
size_t colors_size = 3 * sizeof(*colors);
size_t colors_size = 3 * sizeof (hb_color_t);
g_assert_cmpint (num_colors, ==, 2);
/* Palette #0, start_index=0 */
memset(colors, 0x77, colors_size);
memset (colors, 0x77, colors_size);
g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 0, 0, &num_colors, colors), ==, 2);
g_assert_cmpint (num_colors, ==, 2);
assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
@ -269,7 +269,7 @@ test_hb_ot_color_get_palette_colors_v1 (void)
assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77); /* untouched */
/* Palette #1, start_index=0 */
memset(colors, 0x77, colors_size);
memset (colors, 0x77, colors_size);
g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 1, 0, &num_colors, colors), ==, 2);
g_assert_cmpint (num_colors, ==, 2);
assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
@ -277,7 +277,7 @@ test_hb_ot_color_get_palette_colors_v1 (void)
assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77); /* untouched */
/* Palette #2, start_index=0 */
memset(colors, 0x77, colors_size);
memset (colors, 0x77, colors_size);
g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 2, 0, &num_colors, colors), ==, 2);
g_assert_cmpint (num_colors, ==, 2);
assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff);
@ -285,14 +285,78 @@ test_hb_ot_color_get_palette_colors_v1 (void)
assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77); /* untouched */
/* Palette #3 (out of bounds), start_index=0 */
memset(colors, 0x77, colors_size);
memset (colors, 0x77, colors_size);
g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 3, 0, &num_colors, colors), ==, 0);
g_assert_cmpint (num_colors, ==, 0);
assert_color_rgba (colors, 0, 0x77, 0x77, 0x77, 0x77); /* untouched */
assert_color_rgba (colors, 1, 0x77, 0x77, 0x77, 0x77); /* untouched */
assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77); /* untouched */
}
#endif
static void
test_hb_ot_color_get_palette_entry_name_id (void)
{
hb_face_t *empty = hb_face_get_empty ();
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (empty, 0), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (empty, 1), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (empty, 2), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v0, 0), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v0, 1), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v0, 2), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v1, 0), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v1, 1), ==, 256);
g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v1, 2), ==, HB_NAME_ID_INVALID);
}
static void
test_hb_ot_color_get_color_layers (void)
{
hb_codepoint_t layer_gids[1];
unsigned int color_indices[1];
unsigned int count = 1;
g_assert_cmpuint (hb_ot_color_get_color_layers (cpal_v1, 0, 0,
NULL, NULL, NULL), ==, 0);
g_assert_cmpuint (hb_ot_color_get_color_layers (cpal_v1, 1, 0,
NULL, NULL, NULL), ==, 0);
g_assert_cmpuint (hb_ot_color_get_color_layers (cpal_v1, 2, 0,
NULL, NULL, NULL), ==, 2);
unsigned int num_layers;
num_layers = hb_ot_color_get_color_layers (cpal_v1, 2, 0, &count, layer_gids,
color_indices);
g_assert_cmpuint (num_layers, ==, 2);
g_assert_cmpuint (count, ==, 1);
g_assert_cmpuint (layer_gids[0], ==, 3);
g_assert_cmpuint (color_indices[0], ==, 1);
count = 1;
hb_ot_color_get_color_layers (cpal_v1, 2, 1, &count, layer_gids,
color_indices);
g_assert_cmpuint (num_layers, ==, 2);
g_assert_cmpuint (count, ==, 1);
g_assert_cmpuint (layer_gids[0], ==, 4);
g_assert_cmpuint (color_indices[0], ==, 0);
}
static void
test_hb_ot_color_has_data (void)
{
hb_face_t *empty = hb_face_get_empty ();
g_assert (hb_ot_color_has_colr_data (empty) == FALSE);
g_assert (hb_ot_color_has_colr_data (cpal_v0) == TRUE);
g_assert (hb_ot_color_has_colr_data (cpal_v1) == TRUE);
g_assert (hb_ot_color_has_cpal_data (empty) == FALSE);
g_assert (hb_ot_color_has_cpal_data (cpal_v0) == TRUE);
g_assert (hb_ot_color_has_cpal_data (cpal_v1) == TRUE);
}
int
main (int argc, char **argv)
@ -300,18 +364,21 @@ main (int argc, char **argv)
int status = 0;
hb_test_init (&argc, &argv);
// cpal_v0 = hb_test_load_face ("../shaping/data/in-house/fonts/e90374e5e439e00725b4fe7a8d73db57c5a97f82.ttf");
// cpal_v1 = hb_test_load_face ("../shaping/data/in-house/fonts/319f5d7ebffbefc5c5e6569f8cea73444d7a7268.ttf");
// hb_test_add (test_hb_ot_color_get_palette_count);
// hb_test_add (test_hb_ot_color_get_palette_name_id_empty);
// hb_test_add (test_hb_ot_color_get_palette_name_id_v0);
// hb_test_add (test_hb_ot_color_get_palette_name_id_v1);
// hb_test_add (test_hb_ot_color_get_palette_flags_empty);
// hb_test_add (test_hb_ot_color_get_palette_flags_v0);
// hb_test_add (test_hb_ot_color_get_palette_flags_v1);
// hb_test_add (test_hb_ot_color_get_palette_colors_empty);
// hb_test_add (test_hb_ot_color_get_palette_colors_v0);
// hb_test_add (test_hb_ot_color_get_palette_colors_v1);
cpal_v0 = hb_test_open_font_file ("fonts/cpal-v0.ttf");
cpal_v1 = hb_test_open_font_file ("fonts/cpal-v1.ttf");
hb_test_add (test_hb_ot_color_get_palette_count);
hb_test_add (test_hb_ot_color_get_palette_name_id_empty);
hb_test_add (test_hb_ot_color_get_palette_name_id_v0);
hb_test_add (test_hb_ot_color_get_palette_name_id_v1);
hb_test_add (test_hb_ot_color_get_palette_flags_empty);
hb_test_add (test_hb_ot_color_get_palette_flags_v0);
hb_test_add (test_hb_ot_color_get_palette_flags_v1);
hb_test_add (test_hb_ot_color_get_palette_colors_empty);
hb_test_add (test_hb_ot_color_get_palette_colors_v0);
hb_test_add (test_hb_ot_color_get_palette_colors_v1);
hb_test_add (test_hb_ot_color_get_palette_entry_name_id);
hb_test_add (test_hb_ot_color_get_color_layers);
hb_test_add (test_hb_ot_color_has_data);
status = hb_test_run();
hb_face_destroy (cpal_v0);
hb_face_destroy (cpal_v1);

View File

@ -27,12 +27,10 @@
#include <hb-ot.h>
static const char *font_path = "fonts/cv01.otf";
static hb_face_t *face;
static void
test_ot_layout_feature_get_name_ids_and_characters ()
test_ot_layout_feature_get_name_ids_and_characters (void)
{
hb_face_t *face = hb_test_open_font_file ("fonts/cv01.otf");
hb_tag_t cv01 = HB_TAG ('c','v','0','1');
unsigned int feature_index;
if (!hb_ot_layout_language_find_feature (face,
@ -53,11 +51,11 @@ test_ot_layout_feature_get_name_ids_and_characters ()
&num_named_parameters, &first_param_id))
g_error ("Failed to get name ids");
g_assert (label_id == 256);
g_assert (tooltip_id == 257);
g_assert (sample_id == 258);
g_assert (num_named_parameters == 2);
g_assert (first_param_id == 259);
g_assert_cmpint (label_id, ==, 256);
g_assert_cmpint (tooltip_id, ==, 257);
g_assert_cmpint (sample_id, ==, 258);
g_assert_cmpint (num_named_parameters, ==, 2);
g_assert_cmpint (first_param_id, ==, 259);
hb_codepoint_t characters[100];
unsigned int char_count = 100;
@ -66,10 +64,12 @@ test_ot_layout_feature_get_name_ids_and_characters ()
all_chars = hb_ot_layout_feature_get_characters (face, HB_OT_TAG_GSUB, feature_index,
0, &char_count, characters);
g_assert (all_chars == 2);
g_assert (char_count == 2);
g_assert (characters[0] == 10);
g_assert (characters[1] == 24030);
g_assert_cmpint (all_chars, ==, 2);
g_assert_cmpint (char_count, ==, 2);
g_assert_cmpint (characters[0], ==, 10);
g_assert_cmpint (characters[1], ==, 24030);
hb_face_destroy (face);
}
int
@ -77,26 +77,7 @@ main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
#if GLIB_CHECK_VERSION(2,37,2)
gchar *default_path = g_test_build_filename (G_TEST_DIST, font_path, NULL);
#else
gchar *default_path = g_strdup (font_path);
#endif
hb_blob_t *blob;
char *path = argc > 1 && *argv[1] ? argv[1] : (char *) default_path;
blob = hb_blob_create_from_file (path);
if (hb_blob_get_length (blob) == 0)
g_error ("Font not found.");
face = hb_face_create (blob, 0);
hb_test_add (test_ot_layout_feature_get_name_ids_and_characters);
unsigned int result = hb_test_run ();
hb_face_destroy (face);
hb_blob_destroy (blob);
g_free (default_path);
return result;
return hb_test_run ();
}

View File

@ -118,6 +118,9 @@ test_set_basic (void)
g_assert (!hb_set_has (s, 801));
g_assert (!hb_set_has (s, 802));
hb_set_del (s, 800);
g_assert (!hb_set_has (s, 800));
hb_set_destroy (s);
}

View File

@ -32,8 +32,8 @@
static void
test_subset_cmap (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -52,7 +52,7 @@ test_subset_cmap (void)
static void
test_subset_cmap_non_consecutive_glyphs (void)
{
hb_face_t *face = hb_subset_test_open_font ("fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf");
hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_subset;
@ -74,7 +74,7 @@ test_subset_cmap_non_consecutive_glyphs (void)
static void
test_subset_cmap_noop (void)
{
hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_abc_subset;

View File

@ -60,8 +60,8 @@ static void check_maxp_num_glyphs (hb_face_t *face, uint16_t expected_num_glyphs
static void
test_subset_glyf (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_abc_subset;
@ -82,8 +82,8 @@ test_subset_glyf (void)
static void
test_subset_glyf_with_components (void)
{
hb_face_t *face_components = hb_subset_test_open_font ("fonts/Roboto-Regular.components.ttf");
hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Roboto-Regular.components.subset.ttf");
hb_face_t *face_components = hb_test_open_font_file ("fonts/Roboto-Regular.components.ttf");
hb_face_t *face_subset = hb_test_open_font_file ("fonts/Roboto-Regular.components.subset.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_generated_subset;
@ -103,8 +103,8 @@ test_subset_glyf_with_components (void)
static void
test_subset_glyf_with_gsub (void)
{
hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf");
hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fi.ttf");
hb_face_t *face_fil = hb_test_open_font_file ("fonts/Roboto-Regular.gsub.fil.ttf");
hb_face_t *face_fi = hb_test_open_font_file ("fonts/Roboto-Regular.gsub.fi.ttf");
hb_subset_input_t *input;
hb_face_t *face_subset;
@ -130,8 +130,8 @@ test_subset_glyf_with_gsub (void)
static void
test_subset_glyf_without_gsub (void)
{
hb_face_t *face_fil = hb_subset_test_open_font ("fonts/Roboto-Regular.gsub.fil.ttf");
hb_face_t *face_fi = hb_subset_test_open_font ("fonts/Roboto-Regular.nogsub.fi.ttf");
hb_face_t *face_fil = hb_test_open_font_file ("fonts/Roboto-Regular.gsub.fil.ttf");
hb_face_t *face_fi = hb_test_open_font_file ("fonts/Roboto-Regular.nogsub.fi.ttf");
hb_subset_input_t *input;
hb_face_t *face_subset;
@ -157,7 +157,7 @@ test_subset_glyf_without_gsub (void)
static void
test_subset_glyf_noop (void)
{
hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_abc_subset;
@ -178,8 +178,8 @@ test_subset_glyf_noop (void)
static void
test_subset_glyf_strip_hints_simple (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.nohints.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.nohints.ttf");
hb_set_t *codepoints = hb_set_create();
hb_subset_input_t *input;
@ -203,8 +203,8 @@ test_subset_glyf_strip_hints_simple (void)
static void
test_subset_glyf_strip_hints_composite (void)
{
hb_face_t *face_components = hb_subset_test_open_font ("fonts/Roboto-Regular.components.ttf");
hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Roboto-Regular.components.1fc.nohints.ttf");
hb_face_t *face_components = hb_test_open_font_file ("fonts/Roboto-Regular.components.ttf");
hb_face_t *face_subset = hb_test_open_font_file ("fonts/Roboto-Regular.components.1fc.nohints.ttf");
hb_set_t *codepoints = hb_set_create();
hb_subset_input_t *input;
@ -228,7 +228,7 @@ test_subset_glyf_strip_hints_composite (void)
static void
test_subset_glyf_strip_hints_invalid (void)
{
hb_face_t *face = hb_subset_test_open_font ("../fuzzing/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
hb_set_t *codepoints = hb_set_create();
const hb_codepoint_t text[] =

View File

@ -33,8 +33,8 @@
static void
test_subset_hdmx_simple_subset (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -53,8 +53,8 @@ test_subset_hdmx_simple_subset (void)
static void
test_subset_hdmx_multiple_device_records (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.multihdmx.abc.ttf");
hb_face_t *face_a = hb_subset_test_open_font ("fonts/Roboto-Regular.multihdmx.a.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.multihdmx.abc.ttf");
hb_face_t *face_a = hb_test_open_font_file ("fonts/Roboto-Regular.multihdmx.a.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -72,7 +72,7 @@ test_subset_hdmx_multiple_device_records (void)
static void
test_subset_hdmx_invalid (void)
{
hb_face_t *face = hb_subset_test_open_font("../fuzzing/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@ -94,7 +94,7 @@ test_subset_hdmx_invalid (void)
static void
test_subset_hdmx_fails_sanitize (void)
{
hb_face_t *face = hb_subset_test_open_font("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016");
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@ -116,7 +116,7 @@ test_subset_hdmx_fails_sanitize (void)
static void
test_subset_hdmx_noop (void)
{
hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_abc_subset;

View File

@ -47,8 +47,8 @@ static void check_num_hmetrics(hb_face_t *face, uint16_t expected_num_hmetrics)
static void
test_subset_hmtx_simple_subset (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -69,8 +69,8 @@ test_subset_hmtx_simple_subset (void)
static void
test_subset_hmtx_monospace (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Inconsolata-Regular.abc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Inconsolata-Regular.ac.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Inconsolata-Regular.abc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Inconsolata-Regular.ac.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -91,8 +91,8 @@ test_subset_hmtx_monospace (void)
static void
test_subset_hmtx_keep_num_metrics (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Inconsolata-Regular.abc.widerc.ttf");
hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Inconsolata-Regular.ac.widerc.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Inconsolata-Regular.abc.widerc.ttf");
hb_face_t *face_ac = hb_test_open_font_file ("fonts/Inconsolata-Regular.ac.widerc.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -112,8 +112,8 @@ test_subset_hmtx_keep_num_metrics (void)
static void
test_subset_hmtx_decrease_num_metrics (void)
{
hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Inconsolata-Regular.abc.widerc.ttf");
hb_face_t *face_ab = hb_subset_test_open_font ("fonts/Inconsolata-Regular.ab.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Inconsolata-Regular.abc.widerc.ttf");
hb_face_t *face_ab = hb_test_open_font_file ("fonts/Inconsolata-Regular.ab.ttf");
hb_set_t *codepoints = hb_set_create ();
hb_face_t *face_abc_subset;
@ -133,7 +133,7 @@ test_subset_hmtx_decrease_num_metrics (void)
static void
test_subset_hmtx_noop (void)
{
hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_abc_subset;
@ -153,7 +153,7 @@ test_subset_hmtx_noop (void)
static void
test_subset_invalid_hmtx (void)
{
hb_face_t *face = hb_subset_test_open_font("../fuzzing/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480");
hb_face_t *subset;
hb_subset_input_t *input = hb_subset_input_create_or_fail ();

View File

@ -31,8 +31,8 @@
static void
test_subset_os2 (void)
{
hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_b = hb_subset_test_open_font("fonts/Roboto-Regular.b.ttf");
hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
hb_face_t *face_b = hb_test_open_font_file ("fonts/Roboto-Regular.b.ttf");
hb_set_t *codepoints = hb_set_create();
hb_face_t *face_abc_subset;

View File

@ -32,8 +32,8 @@
static void
test_post_drops_glyph_names (void)
{
hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
hb_face_t *face_full = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
hb_face_t *face_subset = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E.ttf");
hb_face_t *face_full_subset;
hb_set_t *codepoints = hb_set_create ();

View File

@ -46,8 +46,8 @@ static void check_num_vmetrics(hb_face_t *face, uint16_t expected_num_vmetrics)
static void
test_subset_vmtx_simple_subset (void)
{
hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
hb_face_t *face_full = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
hb_face_t *face_subset = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E.ttf");
hb_face_t *face_full_subset;
hb_set_t *codepoints = hb_set_create ();
@ -67,7 +67,7 @@ test_subset_vmtx_simple_subset (void)
static void
test_subset_vmtx_noop (void)
{
hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
hb_face_t *face_full = hb_test_open_font_file ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
hb_face_t *face_full_subset;
hb_set_t *codepoints = hb_set_create();

View File

@ -32,7 +32,7 @@
static void
test_subset_32_tables (void)
{
hb_face_t *face = hb_subset_test_open_font("../fuzzing/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653");
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@ -54,7 +54,7 @@ test_subset_32_tables (void)
static void
test_subset_no_inf_loop (void)
{
hb_face_t *face = hb_subset_test_open_font("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016");
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
@ -76,7 +76,7 @@ test_subset_no_inf_loop (void)
static void
test_subset_crash (void)
{
hb_face_t *face = hb_subset_test_open_font("../fuzzing/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249");
hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249");
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
hb_set_t *codepoints = hb_subset_input_unicode_set (input);

View File

@ -5,29 +5,29 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
hb_blob_t *blob = hb_blob_create((const char *)data, size,
HB_MEMORY_MODE_READONLY, NULL, NULL);
hb_face_t *face = hb_face_create(blob, 0);
hb_font_t *font = hb_font_create(face);
hb_ot_font_set_funcs(font);
hb_font_set_scale(font, 12, 12);
hb_blob_t *blob = hb_blob_create ((const char *)data, size,
HB_MEMORY_MODE_READONLY, NULL, NULL);
hb_face_t *face = hb_face_create (blob, 0);
hb_font_t *font = hb_font_create (face);
hb_ot_font_set_funcs (font);
hb_font_set_scale (font, 12, 12);
{
const char text[] = "ABCDEXYZ123@_%&)*$!";
hb_buffer_t *buffer = hb_buffer_create();
hb_buffer_add_utf8(buffer, text, -1, 0, -1);
hb_buffer_guess_segment_properties(buffer);
hb_shape(font, buffer, NULL, 0);
hb_buffer_destroy(buffer);
hb_buffer_t *buffer = hb_buffer_create ();
hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
hb_buffer_guess_segment_properties (buffer);
hb_shape (font, buffer, NULL, 0);
hb_buffer_destroy (buffer);
}
uint32_t text32[16];
if (size > sizeof(text32)) {
memcpy(text32, data + size - sizeof(text32), sizeof(text32));
hb_buffer_t *buffer = hb_buffer_create();
hb_buffer_add_utf32(buffer, text32, sizeof(text32)/sizeof(text32[0]), 0, -1);
hb_buffer_guess_segment_properties(buffer);
hb_shape(font, buffer, NULL, 0);
if (size > sizeof (text32)) {
memcpy(text32, data + size - sizeof (text32), sizeof (text32));
hb_buffer_t *buffer = hb_buffer_create ();
hb_buffer_add_utf32 (buffer, text32, sizeof (text32) / sizeof (text32[0]), 0, -1);
hb_buffer_guess_segment_properties (buffer);
hb_shape (font, buffer, NULL, 0);
unsigned int len = hb_buffer_get_length (buffer);
hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL);
@ -41,12 +41,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
hb_font_get_glyph_extents (font, info.codepoint, &extents);
}
hb_buffer_destroy(buffer);
hb_buffer_destroy (buffer);
}
hb_font_destroy(font);
hb_face_destroy(face);
hb_blob_destroy(blob);
hb_font_destroy (font);
hb_face_destroy (face);
hb_blob_destroy (blob);
return 0;
}

View File

@ -5,6 +5,24 @@ from __future__ import print_function, division, absolute_import
import sys, os, subprocess, tempfile, threading
def which(program):
# https://stackoverflow.com/a/377028
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, _ = os.path.split(program)
if fpath:
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):
return exe_file
return None
def cmd(command):
# https://stackoverflow.com/a/4408409
# https://stackoverflow.com/a/10012262
@ -49,6 +67,10 @@ please provide it as the first argument to the tool""")
print ('hb_shape_fuzzer:', hb_shape_fuzzer)
fails = 0
valgrind = None
if os.environ.get('RUN_VALGRIND', ''):
valgrind = which ('valgrind')
parent_path = os.path.join (srcdir, "fonts")
for file in os.listdir (parent_path):
path = os.path.join(parent_path, file)
@ -56,8 +78,19 @@ for file in os.listdir (parent_path):
text, returncode = cmd ([hb_shape_fuzzer, path])
print (text)
failed = False
if returncode != 0 or 'error' in text:
print ('failure on %s' % file)
failed = True
if valgrind:
text, returncode = cmd ([valgrind, '--error-exitcode=1', hb_shape_fuzzer, path])
if returncode:
print (text)
print ('failure on %s' % file)
failed = True
if failed:
fails = fails + 1
if fails:

View File

@ -5,4 +5,4 @@
../fonts/TestTRAK.ttf:--font-ptem=9:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000]
../fonts/TestTRAK.ttf:--font-ptem=24:U+0041,U+0042,U+0043:[A.alt=0@-12,0+976|B=1@-12,0+976|C.alt=2@-12,0+976]
../fonts/TestTRAK.ttf:--font-ptem=72:U+0041,U+0042,U+0043:[A.alt=0@-50,0+900|B=1@-50,0+900|C.alt=2@-50,0+900]
../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-100,0+800|B=1@-100,0+800|C.alt=2@-100,0+800]
../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786]

View File

@ -586,7 +586,7 @@ struct output_options_t : option_group_t
if (output_format)
{
output_format++; /* skip the dot */
output_format = strdup (output_format);
output_format = g_strdup (output_format);
}
}