Merge pull request #5264 from harfbuzz/tap2

Tap2
This commit is contained in:
Behdad Esfahbod 2025-04-06 19:34:18 -06:00 committed by GitHub
commit a9e2c8f3aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 506 additions and 439 deletions

View file

@ -66,6 +66,8 @@ jobs:
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip python3-venv ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
- run: |
export ASAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1
export UBSAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1:print_stacktrace=1
python3 -m venv venv
source venv/bin/activate
pip3 install meson==0.60.0
@ -81,6 +83,7 @@ jobs:
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip python3-venv ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
- run: |
export TSAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1
python3 -m venv venv
source venv/bin/activate
pip3 install meson==0.60.0
@ -96,6 +99,7 @@ jobs:
- run: apt update || true
- run: DEBIAN_FRONTEND=noninteractive apt install -y python3 python3-pip python3-venv ninja-build clang lld git binutils pkg-config ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev
- run: |
export MSAN_OPTIONS=log_path=stderr:halt_on_error=1:abort_on_error=1:print_stacktrace=1
python3 -m venv venv
source venv/bin/activate
pip3 install meson==0.60.0

View file

@ -32,7 +32,7 @@
#include "hb.hh"
#line 36 "hb-buffer-deserialize-json.hh"
#line 33 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
0u, 0u, 9u, 34u, 97u, 121u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
@ -597,12 +597,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
#line 601 "hb-buffer-deserialize-json.hh"
#line 594 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
#line 606 "hb-buffer-deserialize-json.hh"
#line 597 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@ -712,7 +712,7 @@ _resume:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
#line 716 "hb-buffer-deserialize-json.hh"
#line 689 "hb-buffer-deserialize-json.hh"
}
_again:

View file

@ -32,7 +32,7 @@
#include "hb.hh"
#line 36 "hb-buffer-deserialize-text-glyphs.hh"
#line 33 "hb-buffer-deserialize-text-glyphs.hh"
static const unsigned char _deserialize_text_glyphs_trans_keys[] = {
0u, 0u, 35u, 124u, 48u, 57u, 60u, 124u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u,
48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 62u, 62u,
@ -389,12 +389,12 @@ _hb_buffer_deserialize_text_glyphs (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
#line 393 "hb-buffer-deserialize-text-glyphs.hh"
#line 386 "hb-buffer-deserialize-text-glyphs.hh"
{
cs = deserialize_text_glyphs_start;
}
#line 398 "hb-buffer-deserialize-text-glyphs.hh"
#line 389 "hb-buffer-deserialize-text-glyphs.hh"
{
int _slen;
int _trans;
@ -552,7 +552,7 @@ _resume:
return false;
}
break;
#line 556 "hb-buffer-deserialize-text-glyphs.hh"
#line 523 "hb-buffer-deserialize-text-glyphs.hh"
}
_again:
@ -573,7 +573,7 @@ _again:
*end_ptr = p;
}
break;
#line 577 "hb-buffer-deserialize-text-glyphs.hh"
#line 542 "hb-buffer-deserialize-text-glyphs.hh"
}
}

View file

@ -672,7 +672,7 @@ hb_face_make_immutable (hb_face_t *face)
* Since: 0.9.2
**/
hb_bool_t
hb_face_is_immutable (const hb_face_t *face)
hb_face_is_immutable (hb_face_t *face)
{
return hb_object_is_immutable (face);
}

View file

@ -131,7 +131,7 @@ HB_EXTERN void
hb_face_make_immutable (hb_face_t *face);
HB_EXTERN hb_bool_t
hb_face_is_immutable (const hb_face_t *face);
hb_face_is_immutable (hb_face_t *face);
HB_EXTERN hb_blob_t *

View file

@ -134,7 +134,7 @@ typedef GTestFixtureFunc hb_test_fixture_func_t;
#else
typedef void (*hb_test_func_t) (void);
typedef void (*hb_test_data_func_t) (gconstpointer user_data);
typedef void (*hb_test_fixture_func_t) (void);
typedef void (*hb_test_fixture_func_t) (gpointer fixture, gconstpointer user_data);
#endif
#if !GLIB_CHECK_VERSION(2,30,0)
@ -226,16 +226,7 @@ hb_test_add_vtable (const char *test_path,
}
#define hb_test_add_fixture(FixturePrefix, UserData, Func) \
G_STMT_START { \
typedef G_PASTE (FixturePrefix, _t) Fixture; \
void (*add_vtable) (const char*, gsize, gconstpointer, \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer)) \
= (void (*) (const gchar *, gsize, gconstpointer, \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer))) hb_test_add_vtable; \
add_vtable (#Func, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
hb_test_add_vtable (#Func, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \
} G_STMT_END
@ -254,16 +245,7 @@ hb_test_add_vtable_flavor (const char *test_path,
}
#define hb_test_add_fixture_flavor(FixturePrefix, UserData, Flavor, Func) \
G_STMT_START { \
typedef G_PASTE (FixturePrefix, _t) Fixture; \
void (*add_vtable) (const char*, const char *, gsize, gconstpointer, \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer)) \
= (void (*) (const gchar *, const char *, gsize, gconstpointer, \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer), \
void (*) (Fixture*, gconstpointer))) hb_test_add_vtable_flavor; \
add_vtable (#Func, Flavor, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
hb_test_add_vtable_flavor (#Func, Flavor, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \
} G_STMT_END

View file

@ -98,15 +98,17 @@ typedef struct
} fixture_t;
static void
free_up (fixture_t *fixture)
free_up (void *fixture_)
{
fixture_t *fixture = (fixture_t *) fixture_;
g_assert_cmpint (fixture->freed, ==, 0);
fixture->freed++;
}
static void
free_up_free (fixture_t *fixture)
free_up_free (void *fixture_)
{
fixture_t *fixture = (fixture_t *) fixture_;
free_up (fixture);
free (fixture->data);
}
@ -132,8 +134,9 @@ get_pagesize (void)
}
static void
free_up_munmap (fixture_t *fixture)
free_up_munmap (void *fixture_)
{
fixture_t *fixture = (fixture_t *) fixture_;
free_up (fixture);
munmap (fixture->data, get_pagesize ());
}
@ -141,8 +144,9 @@ free_up_munmap (fixture_t *fixture)
#include <errno.h>
static void
fixture_init (fixture_t *fixture, gconstpointer user_data)
fixture_init (gpointer fixture_, gconstpointer user_data)
{
fixture_t *fixture = (fixture_t *) fixture_;
hb_memory_mode_t mm = (hb_memory_mode_t) GPOINTER_TO_INT (user_data);
unsigned int len;
const char *data;
@ -153,13 +157,13 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
case HB_MEMORY_MODE_DUPLICATE:
data = test_data;
len = sizeof (test_data);
free_func = (hb_destroy_func_t) free_up;
free_func = free_up;
break;
case HB_MEMORY_MODE_READONLY:
data = test_data;
len = sizeof (test_data);
free_func = (hb_destroy_func_t) free_up;
free_func = free_up;
break;
case HB_MEMORY_MODE_WRITABLE:
@ -179,7 +183,7 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
memcpy ((char *) data, test_data, sizeof (test_data));
mprotect ((char *) data, pagesize, PROT_READ);
len = sizeof (test_data);
free_func = (hb_destroy_func_t) free_up_munmap;
free_func = free_up_munmap;
break;
}
#endif
@ -195,16 +199,18 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
}
static void
fixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
fixture_finish (gpointer fixture_, gconstpointer user_data HB_UNUSED)
{
fixture_t *fixture = (fixture_t *) fixture_;
hb_blob_destroy (fixture->blob);
g_assert_cmpint (fixture->freed, ==, 1);
}
static void
test_blob (fixture_t *fixture, gconstpointer user_data)
test_blob (gpointer fixture_, gconstpointer user_data)
{
fixture_t *fixture = (fixture_t *) fixture_;
hb_blob_t *b = fixture->blob;
hb_memory_mode_t mm = GPOINTER_TO_INT (user_data);
unsigned int len;
@ -262,8 +268,9 @@ test_blob (fixture_t *fixture, gconstpointer user_data)
}
static void
test_blob_subblob (fixture_t *fixture, gconstpointer user_data)
test_blob_subblob (gpointer fixture_, gconstpointer user_data)
{
fixture_t *fixture = (fixture_t *) fixture_;
hb_blob_t *b = fixture->blob;
hb_memory_mode_t mm = GPOINTER_TO_INT (user_data);
unsigned int len;

View file

@ -57,8 +57,9 @@ typedef struct
} fixture_t;
static void
fixture_init (fixture_t *fixture, gconstpointer user_data)
fixture_init (gpointer fixture_, gconstpointer user_data)
{
fixture_t *fixture = fixture_;
hb_buffer_t *b;
unsigned int i;
@ -92,15 +93,17 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
}
static void
fixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
fixture_finish (gpointer fixture_, gconstpointer user_data HB_UNUSED)
{
fixture_t *fixture = fixture_;
hb_buffer_destroy (fixture->buffer);
}
static void
test_buffer_properties (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
test_buffer_properties (gpointer fixture_, gconstpointer user_data HB_UNUSED)
{
fixture_t *fixture = fixture_;
hb_buffer_t *b = fixture->buffer;
hb_unicode_funcs_t *ufuncs;
@ -177,8 +180,9 @@ test_buffer_properties (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
}
static void
test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
test_buffer_contents (gpointer fixture_, gconstpointer user_data)
{
fixture_t *fixture = fixture_;
hb_buffer_t *b = fixture->buffer;
unsigned int i, len, len2;
buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
@ -294,8 +298,9 @@ test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
}
static void
test_buffer_positions (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
test_buffer_positions (gpointer fixture_, gconstpointer user_data HB_UNUSED)
{
fixture_t *fixture = fixture_;
hb_buffer_t *b = fixture->buffer;
unsigned int i, len, len2;
hb_glyph_position_t *positions;
@ -319,8 +324,9 @@ test_buffer_positions (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
}
static void
test_buffer_allocation (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
test_buffer_allocation (gpointer fixture_, gconstpointer user_data HB_UNUSED)
{
fixture_t *fixture = fixture_;
hb_buffer_t *b = fixture->buffer;
g_assert_cmpint (hb_buffer_get_length (b), ==, 0);

View file

@ -98,49 +98,54 @@ test_itoa (void)
}
static void
move_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
move_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
HB_UNUSED float to_x, HB_UNUSED float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
draw_data->move_to_count++;
}
static void
line_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
line_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
HB_UNUSED float to_x, HB_UNUSED float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
draw_data->line_to_count++;
}
static void
quadratic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
quadratic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
HB_UNUSED float control_x, HB_UNUSED float control_y,
HB_UNUSED float to_x, HB_UNUSED float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
draw_data->quad_to_count++;
}
static void
cubic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
cubic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
HB_UNUSED float control1_x, HB_UNUSED float control1_y,
HB_UNUSED float control2_x, HB_UNUSED float control2_y,
HB_UNUSED float to_x, HB_UNUSED float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
draw_data->cubic_to_count++;
}
static void
close_path (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
close_path (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
draw_data->close_path_count++;
}
@ -249,11 +254,11 @@ int
main (int argc, char **argv)
{
funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
hb_draw_funcs_set_move_to_func (funcs, move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs, line_to, NULL, NULL);
hb_draw_funcs_set_quadratic_to_func (funcs, quadratic_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs, cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs, close_path, NULL, NULL);
hb_draw_funcs_make_immutable (funcs);
hb_test_init (&argc, &argv);

View file

@ -96,11 +96,12 @@ test_itoa (void)
}
static void
move_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
move_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
float to_x, float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
/* 4 = command character space + comma + array starts with 0 index + nul character space */
if (draw_data->consumed + 2 * ITOA_BUF_SIZE + 4 > draw_data->size) return;
draw_data->str[draw_data->consumed++] = 'M';
@ -110,11 +111,12 @@ move_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
}
static void
line_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
line_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
float to_x, float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
if (draw_data->consumed + 2 * ITOA_BUF_SIZE + 4 > draw_data->size) return;
draw_data->str[draw_data->consumed++] = 'L';
draw_data->consumed += _hb_itoa (to_x, draw_data->str + draw_data->consumed);
@ -123,13 +125,13 @@ line_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
}
static void
quadratic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
quadratic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
float control_x, float control_y,
float to_x, float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
if (draw_data->consumed + 4 * ITOA_BUF_SIZE + 6 > draw_data->size) return;
draw_data->str[draw_data->consumed++] = 'Q';
draw_data->consumed += _hb_itoa (control_x, draw_data->str + draw_data->consumed);
@ -142,13 +144,14 @@ quadratic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
}
static void
cubic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
cubic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
float control1_x, float control1_y,
float control2_x, float control2_y,
float to_x, float to_y,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
if (draw_data->consumed + 6 * ITOA_BUF_SIZE + 8 > draw_data->size) return;
draw_data->str[draw_data->consumed++] = 'C';
draw_data->consumed += _hb_itoa (control1_x, draw_data->str + draw_data->consumed);
@ -165,10 +168,11 @@ cubic_to (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
}
static void
close_path (HB_UNUSED hb_draw_funcs_t *dfuncs, draw_data_t *draw_data,
close_path (HB_UNUSED hb_draw_funcs_t *dfuncs, void *draw_data_,
HB_UNUSED hb_draw_state_t *st,
HB_UNUSED void *user_data)
{
draw_data_t *draw_data = (draw_data_t *) draw_data_;
if (draw_data->consumed + 2 > draw_data->size) return;
draw_data->str[draw_data->consumed++] = 'Z';
}
@ -1156,18 +1160,18 @@ int
main (int argc, char **argv)
{
funcs = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, NULL, NULL);
hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
hb_draw_funcs_set_move_to_func (funcs, move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs, line_to, NULL, NULL);
hb_draw_funcs_set_quadratic_to_func (funcs, quadratic_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs, cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs, close_path, NULL, NULL);
hb_draw_funcs_make_immutable (funcs);
funcs2 = hb_draw_funcs_create ();
hb_draw_funcs_set_move_to_func (funcs2, (hb_draw_move_to_func_t) move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs2, (hb_draw_line_to_func_t) line_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs2, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs2, (hb_draw_close_path_func_t) close_path, NULL, NULL);
hb_draw_funcs_set_move_to_func (funcs2, move_to, NULL, NULL);
hb_draw_funcs_set_line_to_func (funcs2, line_to, NULL, NULL);
hb_draw_funcs_set_cubic_to_func (funcs2, cubic_to, NULL, NULL);
hb_draw_funcs_set_close_path_func (funcs2, close_path, NULL, NULL);
hb_draw_funcs_make_immutable (funcs2);
hb_test_init (&argc, &argv);

View file

@ -29,41 +29,52 @@
/* Unit tests for hb-object-private.h */
static void *
static hb_blob_t *
create_blob (void)
{
static char data[] = "test data";
return hb_blob_create (data, sizeof (data), HB_MEMORY_MODE_READONLY, NULL, NULL);
}
static void *
static hb_blob_t *
create_blob_from_inert (void)
{
return hb_blob_create (NULL, 0, HB_MEMORY_MODE_DUPLICATE, NULL, NULL);
return NULL;
}
static void *
static hb_buffer_t *
create_buffer (void)
{
return hb_buffer_create ();
}
static void *
static hb_buffer_t *
create_buffer_from_inert (void)
{
return NULL;
}
static void *
static hb_map_t *
create_map (void)
{
return hb_map_create ();
}
static hb_map_t *
create_map_from_inert (void)
{
return NULL;
}
static hb_set_t *
create_set (void)
{
return hb_set_create ();
}
static void *
static hb_set_t *
create_set_from_inert (void)
{
return NULL;
}
static void *
static hb_face_t *
create_face (void)
{
hb_blob_t *blob = (hb_blob_t *) create_blob ();
@ -71,13 +82,13 @@ create_face (void)
hb_blob_destroy (blob);
return face;
}
static void *
static hb_face_t *
create_face_from_inert (void)
{
return hb_face_create (hb_blob_get_empty (), 0);
}
static void *
static hb_font_t *
create_font (void)
{
hb_face_t *face = (hb_face_t *) create_face ();
@ -85,96 +96,51 @@ create_font (void)
hb_face_destroy (face);
return font;
}
static void *
static hb_font_t *
create_font_from_inert (void)
{
return hb_font_create (hb_face_get_empty ());
}
static void *
static hb_font_funcs_t *
create_font_funcs (void)
{
return hb_font_funcs_create ();
}
static void *
static hb_font_funcs_t *
create_font_funcs_from_inert (void)
{
return NULL;
}
static void *
static hb_shape_plan_t *
create_shape_plan (void)
{
hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT;
props.direction = HB_DIRECTION_LTR;
hb_face_t *face = (hb_face_t *) create_face ();
hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, &props, NULL, 0, NULL);
hb_face_destroy (face);
return shape_plan;
}
static hb_shape_plan_t *
create_shape_plan_from_inert (void)
{
return NULL;
}
static hb_unicode_funcs_t *
create_unicode_funcs (void)
{
return hb_unicode_funcs_create (NULL);
}
static void *
static hb_unicode_funcs_t *
create_unicode_funcs_from_inert (void)
{
return hb_unicode_funcs_create (hb_unicode_funcs_get_empty ());
}
typedef void *(*create_func_t) (void);
typedef void *(*reference_func_t) (void *obj);
typedef void (*destroy_func_t) (void *obj);
typedef hb_bool_t (*set_user_data_func_t) (void *obj, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy, hb_bool_t replace);
typedef void * (*get_user_data_func_t) (void *obj, hb_user_data_key_t *key);
typedef void (*make_immutable_func_t) (void *obj);
typedef hb_bool_t (*is_immutable_func_t) (void *obj);
typedef struct {
create_func_t create;
create_func_t create_from_inert;
create_func_t get_empty;
reference_func_t reference;
destroy_func_t destroy;
set_user_data_func_t set_user_data;
get_user_data_func_t get_user_data;
make_immutable_func_t make_immutable;
is_immutable_func_t is_immutable;
const char *name;
} object_t;
#define OBJECT_WITHOUT_IMMUTABILITY(name) \
{ \
(create_func_t) create_##name, \
(create_func_t) create_##name##_from_inert, \
(create_func_t) hb_##name##_get_empty, \
(reference_func_t) hb_##name##_reference, \
(destroy_func_t) hb_##name##_destroy, \
(set_user_data_func_t) hb_##name##_set_user_data, \
(get_user_data_func_t) hb_##name##_get_user_data, \
(make_immutable_func_t) NULL, \
(is_immutable_func_t) NULL, \
#name, \
}
#define OBJECT_WITH_IMMUTABILITY(name) \
{ \
(create_func_t) create_##name, \
(create_func_t) create_##name##_from_inert, \
(create_func_t) hb_##name##_get_empty, \
(reference_func_t) hb_##name##_reference, \
(destroy_func_t) hb_##name##_destroy, \
(set_user_data_func_t) hb_##name##_set_user_data, \
(get_user_data_func_t) hb_##name##_get_user_data, \
(make_immutable_func_t) hb_##name##_make_immutable, \
(is_immutable_func_t) hb_##name##_is_immutable, \
#name, \
}
static const object_t objects[] =
{
OBJECT_WITHOUT_IMMUTABILITY (buffer),
OBJECT_WITHOUT_IMMUTABILITY (set),
OBJECT_WITH_IMMUTABILITY (blob),
OBJECT_WITH_IMMUTABILITY (face),
OBJECT_WITH_IMMUTABILITY (font),
OBJECT_WITH_IMMUTABILITY (font_funcs),
OBJECT_WITH_IMMUTABILITY (unicode_funcs)
};
#undef OBJECT
#define MAGIC0 0x12345678
#define MAGIC1 0x76543210
@ -208,168 +174,198 @@ static void free_up1 (void *p)
data->freed = TRUE;
}
typedef struct {
const object_t *klass;
void *object;
hb_user_data_key_t key;
} deadlock_test_t;
static void free_deadlock_test (void *p)
{
deadlock_test_t *t = (deadlock_test_t *) p;
g_assert_true (NULL == t->klass->get_user_data (t->object, &t->key));
#define OBJECT(name, _hb_object_make_immutable, _hb_object_is_immutable) \
static void \
test_object_##name (void) \
{ \
typedef hb_##name##_t type_t; \
typedef type_t *(*create_func_t) (void); \
typedef type_t *(*reference_func_t) (type_t *obj); \
typedef void (*destroy_func_t) (type_t *obj); \
typedef hb_bool_t (*set_user_data_func_t) (type_t *obj, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy, hb_bool_t replace); \
typedef void * (*get_user_data_func_t) (const type_t *obj, hb_user_data_key_t *key); \
typedef void (*make_immutable_func_t) (type_t *obj); \
typedef hb_bool_t (*is_immutable_func_t) (type_t *obj); \
\
struct object_t { \
create_func_t create; \
create_func_t create_from_inert; \
create_func_t get_empty; \
reference_func_t reference; \
destroy_func_t destroy; \
set_user_data_func_t set_user_data; \
get_user_data_func_t get_user_data; \
make_immutable_func_t make_immutable; \
is_immutable_func_t is_immutable; \
const char *name; \
} o[1] = {{\
create_##name, \
create_##name##_from_inert, \
hb_##name##_get_empty, \
hb_##name##_reference, \
hb_##name##_destroy, \
hb_##name##_set_user_data, \
hb_##name##_get_user_data, \
_hb_object_make_immutable, \
_hb_object_is_immutable, \
#name, \
}}; \
\
void *obj; \
hb_user_data_key_t key[1001]; \
\
{ \
unsigned int j; \
data_t data[1000] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; \
\
g_test_message ("Testing object %s", o->name); \
\
g_test_message ("->create()"); \
obj = o->create (); \
g_assert_true (obj); \
\
g_assert_true (obj == o->reference (obj)); \
o->destroy (obj); \
\
if (o->is_immutable) \
g_assert_true (!o->is_immutable (obj)); \
\
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); \
g_assert_true (o->get_user_data (obj, &key[0]) == &data[0]); \
\
if (o->is_immutable) { \
o->make_immutable (obj); \
g_assert_true (o->is_immutable (obj)); \
} \
\
/* Should still work even if object is made immutable */ \
g_assert_true (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE)); \
g_assert_true (o->get_user_data (obj, &key[1]) == &data[1]); \
\
g_assert_true (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE)); \
g_assert_true (o->get_user_data (obj, &key[0]) == &data[0]); \
g_assert_true (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE)); \
g_assert_true (data[0].freed); \
g_assert_true (o->get_user_data (obj, &key[0]) == &data[1]); \
g_assert_true (!data[1].freed); \
\
data[0].freed = FALSE; \
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); \
g_assert_true (!data[0].freed); \
g_assert_true (o->set_user_data (obj, &key[0], NULL, NULL, TRUE)); \
g_assert_true (data[0].freed); \
\
data[0].freed = FALSE; \
global_data = 0; \
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); \
g_assert_true (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE)); \
g_assert_cmpuint (global_data, ==, 0); \
g_assert_true (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE)); \
g_assert_cmpuint (global_data, ==, 0); \
g_assert_true (o->set_user_data (obj, &key[0], NULL, NULL, TRUE)); \
g_assert_cmpuint (global_data, ==, 1); \
\
global_data = 0; \
for (j = 2; j < 1000; j++) \
g_assert_true (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE)); \
for (j = 2; j < 1000; j++) \
g_assert_true (o->get_user_data (obj, &key[j]) == &data[j]); \
for (j = 100; j < 1000; j++) \
g_assert_true (o->set_user_data (obj, &key[j], NULL, NULL, TRUE)); \
for (j = 2; j < 100; j++) \
g_assert_true (o->get_user_data (obj, &key[j]) == &data[j]); \
for (j = 100; j < 1000; j++) \
g_assert_true (!o->get_user_data (obj, &key[j])); \
g_assert_cmpuint (global_data, ==, 900); \
\
g_assert_true (!data[1].freed); \
o->destroy (obj); \
g_assert_true (data[0].freed); \
g_assert_true (data[1].freed); \
g_assert_cmpuint (global_data, ==, 1000-2); \
} \
\
{ \
data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; \
\
g_test_message ("->get_empty()"); \
obj = o->get_empty (); \
g_assert_true (obj); \
\
g_assert_true (obj == o->reference (obj)); \
o->destroy (obj); \
\
if (o->is_immutable) \
g_assert_true (o->is_immutable (obj)); \
\
g_assert_true (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); \
g_assert_true (!o->get_user_data (obj, &key[0])); \
\
o->destroy (obj); \
o->destroy (obj); \
o->destroy (obj); \
o->destroy (obj); \
o->destroy (obj); \
\
g_assert_true (!data[0].freed); \
} \
\
{ \
data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; \
\
g_test_message ("->create_from_inert()"); \
obj = o->create_from_inert (); \
if (!obj) \
return; \
g_assert_true (obj != o->get_empty ()); \
\
g_assert_true (obj == o->reference (obj)); \
o->destroy (obj); \
\
if (o->is_immutable) \
g_assert_true (!o->is_immutable (obj)); \
\
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); \
g_assert_true (o->get_user_data (obj, &key[0])); \
\
o->destroy (obj); \
\
g_assert_true (data[0].freed); \
} \
}
#define OBJECT_WITH_IMMUTABILITY(name) \
OBJECT (name, hb_##name##_make_immutable, hb_##name##_is_immutable)
#define OBJECT_WITHOUT_IMMUTABILITY(name) \
OBJECT (name, NULL, NULL)
static void
test_object (void)
{
unsigned int i;
for (i = 0; i < G_N_ELEMENTS (objects); i++) {
const object_t *o = &objects[i];
void *obj;
hb_user_data_key_t key[1001];
{
unsigned int j;
data_t data[1000] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
deadlock_test_t deadlock_test;
g_test_message ("Testing object %s", o->name);
g_test_message ("->create()");
obj = o->create ();
g_assert_true (obj);
g_assert_true (obj == o->reference (obj));
o->destroy (obj);
if (o->is_immutable)
g_assert_true (!o->is_immutable (obj));
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
g_assert_true (o->get_user_data (obj, &key[0]) == &data[0]);
if (o->is_immutable) {
o->make_immutable (obj);
g_assert_true (o->is_immutable (obj));
}
/* Should still work even if object is made immutable */
g_assert_true (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE));
g_assert_true (o->get_user_data (obj, &key[1]) == &data[1]);
g_assert_true (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE));
g_assert_true (o->get_user_data (obj, &key[0]) == &data[0]);
g_assert_true (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE));
g_assert_true (data[0].freed);
g_assert_true (o->get_user_data (obj, &key[0]) == &data[1]);
g_assert_true (!data[1].freed);
data[0].freed = FALSE;
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
g_assert_true (!data[0].freed);
g_assert_true (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
g_assert_true (data[0].freed);
data[0].freed = FALSE;
global_data = 0;
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
g_assert_true (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE));
g_assert_cmpuint (global_data, ==, 0);
g_assert_true (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE));
g_assert_cmpuint (global_data, ==, 0);
g_assert_true (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
g_assert_cmpuint (global_data, ==, 1);
global_data = 0;
for (j = 2; j < 1000; j++)
g_assert_true (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE));
for (j = 2; j < 1000; j++)
g_assert_true (o->get_user_data (obj, &key[j]) == &data[j]);
for (j = 100; j < 1000; j++)
g_assert_true (o->set_user_data (obj, &key[j], NULL, NULL, TRUE));
for (j = 2; j < 100; j++)
g_assert_true (o->get_user_data (obj, &key[j]) == &data[j]);
for (j = 100; j < 1000; j++)
g_assert_true (!o->get_user_data (obj, &key[j]));
g_assert_cmpuint (global_data, ==, 900);
/* Test set_user_data where the destroy() func calls user_data functions.
* Make sure it doesn't deadlock or corrupt memory. */
deadlock_test.klass = o;
deadlock_test.object = obj;
g_assert_true (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test, TRUE));
g_assert_true (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE));
g_assert_true (!data[1].freed);
o->destroy (obj);
g_assert_true (data[0].freed);
g_assert_true (data[1].freed);
g_assert_cmpuint (global_data, ==, 1000-2);
}
{
data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
g_test_message ("->get_empty()");
obj = o->get_empty ();
g_assert_true (obj);
g_assert_true (obj == o->reference (obj));
o->destroy (obj);
if (o->is_immutable)
g_assert_true (o->is_immutable (obj));
g_assert_true (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
g_assert_true (!o->get_user_data (obj, &key[0]));
o->destroy (obj);
o->destroy (obj);
o->destroy (obj);
o->destroy (obj);
o->destroy (obj);
g_assert_true (!data[0].freed);
}
{
data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
g_test_message ("->create_from_inert()");
obj = o->create_from_inert ();
if (!obj)
continue;
if (obj == o->get_empty ())
continue; /* Tested already */
g_assert_true (obj == o->reference (obj));
o->destroy (obj);
if (o->is_immutable)
g_assert_true (!o->is_immutable (obj));
g_assert_true (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
g_assert_true (o->get_user_data (obj, &key[0]));
o->destroy (obj);
g_assert_true (data[0].freed);
}
}
}
OBJECT_WITHOUT_IMMUTABILITY (buffer)
OBJECT_WITHOUT_IMMUTABILITY (map)
OBJECT_WITHOUT_IMMUTABILITY (set)
OBJECT_WITHOUT_IMMUTABILITY (shape_plan)
OBJECT_WITH_IMMUTABILITY (blob)
OBJECT_WITH_IMMUTABILITY (face)
OBJECT_WITH_IMMUTABILITY (font)
OBJECT_WITH_IMMUTABILITY (font_funcs)
OBJECT_WITH_IMMUTABILITY (unicode_funcs)
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_object);
hb_test_add (test_object_buffer);
hb_test_add (test_object_map);
hb_test_add (test_object_shape_plan);
hb_test_add (test_object_set);
hb_test_add (test_object_blob);
hb_test_add (test_object_face);
hb_test_add (test_object_font);
hb_test_add (test_object_font_funcs);
hb_test_add (test_object_unicode_funcs);
return hb_test_run ();
}

View file

@ -577,13 +577,22 @@ typedef struct {
unsigned int default_value;
} property_t;
static unsigned _hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode)
{ return (unsigned) hb_unicode_combining_class (ufuncs, unicode); }
static unsigned _hb_unicode_general_category (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode)
{ return (unsigned) hb_unicode_general_category (ufuncs, unicode); }
static unsigned _hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode)
{ return (unsigned) hb_unicode_mirroring (ufuncs, unicode); }
static unsigned _hb_unicode_script (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode)
{ return (unsigned) hb_unicode_script (ufuncs, unicode); }
#define RETURNS_UNICODE_ITSELF ((unsigned int) -1)
#define PROPERTY(name, DEFAULT) \
{ \
#name, \
(func_setter_func_t) hb_unicode_funcs_set_##name##_func, \
(getter_func_t) hb_unicode_##name, \
_hb_unicode_##name, \
name##_tests, \
G_N_ELEMENTS (name##_tests), \
name##_tests_more, \
@ -785,19 +794,21 @@ typedef struct {
} data_fixture_t;
static void
data_fixture_init (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
data_fixture_init (gpointer fixture, gconstpointer user_data HB_UNUSED)
{
data_fixture_t *f = (data_fixture_t *) fixture;
f->data[0].value = MAGIC0;
f->data[1].value = MAGIC1;
}
static void
data_fixture_finish (data_fixture_t *f HB_UNUSED, gconstpointer user_data HB_UNUSED)
data_fixture_finish (gpointer fixture HB_UNUSED, gconstpointer user_data HB_UNUSED)
{
}
static void
test_unicode_subclassing_nil (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
test_unicode_subclassing_nil (gpointer fixture, gconstpointer user_data HB_UNUSED)
{
data_fixture_t *f = (data_fixture_t *) fixture;
hb_unicode_funcs_t *uf, *aa;
uf = hb_unicode_funcs_create (NULL);
@ -818,8 +829,9 @@ test_unicode_subclassing_nil (data_fixture_t *f, gconstpointer user_data HB_UNUS
}
static void
test_unicode_subclassing_default (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
test_unicode_subclassing_default (gpointer fixture, gconstpointer user_data HB_UNUSED)
{
data_fixture_t *f = (data_fixture_t *) fixture;
hb_unicode_funcs_t *uf, *aa;
uf = hb_unicode_funcs_get_default ();
@ -837,8 +849,9 @@ test_unicode_subclassing_default (data_fixture_t *f, gconstpointer user_data HB_
}
static void
test_unicode_subclassing_deep (data_fixture_t *f, gconstpointer user_data HB_UNUSED)
test_unicode_subclassing_deep (gpointer fixture, gconstpointer user_data HB_UNUSED)
{
data_fixture_t *f = (data_fixture_t *) fixture;
hb_unicode_funcs_t *uf, *aa;
uf = hb_unicode_funcs_create (NULL);
@ -999,6 +1012,9 @@ test_unicode_normalization (gconstpointer user_data)
int
main (int argc, char **argv)
{
char *ubsan_obtions = getenv ("UBSAN_OPTIONS");
int ubsan = ubsan_obtions && strstr (ubsan_obtions, "halt_on_error=1");
hb_test_init (&argc, &argv);
hb_test_add (test_unicode_properties_nil);
@ -1020,7 +1036,8 @@ main (int argc, char **argv)
hb_test_add (test_unicode_chainup);
hb_test_add (test_unicode_setters);
if (!ubsan)
hb_test_add (test_unicode_setters);
hb_test_add_fixture (data_fixture, NULL, test_unicode_subclassing_nil);
hb_test_add_fixture (data_fixture, NULL, test_unicode_subclassing_default);

View file

@ -38,7 +38,8 @@ def cmd(command):
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
)
(stdoutdata, stderrdata) = p.communicate()
print(stderrdata, end="", file=sys.stderr)
if stderrdata:
print(stderrdata, file=sys.stderr)
return stdoutdata, p.returncode
@ -52,9 +53,9 @@ def fail_test(test, cli_args, message):
print(" test.test_path %s" % os.path.abspath(test.test_path))
print("not ok -", test)
print(" ---", file=sys.stderr)
print(" message: \"%s\"" % message, file=sys.stderr)
print(" test.font_name: \"%s\"" % test.font_name)
print(" test.test_path: \"%s\"" % os.path.abspath(test.test_path))
print(' message: "%s"' % message, file=sys.stderr)
print(' test.font_name: "%s"' % test.font_name, file=sys.stderr)
print(' test.test_path: "%s"' % os.path.abspath(test.test_path), file=sys.stderr)
print(" ...", file=sys.stderr)
return False

View file

@ -40,25 +40,29 @@ def cmd(command):
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
)
(stdoutdata, stderrdata) = p.communicate()
print(stderrdata, end="", file=sys.stderr)
if stderrdata:
print(stderrdata, file=sys.stderr)
return stdoutdata, p.returncode
def fail_test(test, cli_args, message):
global fails
global fails, number
fails += 1
expected_file = os.path.join(
test_suite.get_output_directory(), test.get_font_name()
)
print("not ok -", test)
print("not ok %d - %s" % (number, test))
print(" ---", file=sys.stderr)
print(" message: \"%s\"" % message, file=sys.stderr)
print(" test.font_path: \"%s\"" % os.path.abspath(test.font_path), file=sys.stderr)
print(" test.profile_path: \"%s\"" % os.path.abspath(test.profile_path), file=sys.stderr)
print(" test.unicodes: \"%s\"" % test.unicodes(), file=sys.stderr)
print(" expected_file: \"%s\"" % os.path.abspath(expected_file), file=sys.stderr)
print(' message: "%s"' % message, file=sys.stderr)
print(' test.font_path: "%s"' % os.path.abspath(test.font_path), file=sys.stderr)
print(
' test.profile_path: "%s"' % os.path.abspath(test.profile_path),
file=sys.stderr,
)
print(' test.unicodes: "%s"' % test.unicodes(), file=sys.stderr)
print(' expected_file: "%s"' % os.path.abspath(expected_file), file=sys.stderr)
print(" ...", file=sys.stderr)
return False
@ -214,7 +218,7 @@ for path in args:
print("ok %d - %s" % (number, test))
if fails != 0:
print("# %d test(s) failed; output left in %s" % (fails, out_dir), file=sys.stderr)
print("# %d test(s) failed; output left in %s" % (fails, out_dir))
else:
print("# All tests passed.")
shutil.rmtree(out_dir)

View file

@ -2,143 +2,180 @@
import os
# A single test in a subset test suite. Identifies a font
# a subsetting profile, and a subset to be cut.
class Test:
def __init__(self, font_path, profile_path, subset, instance, iup_optimize, options):
self.font_path = font_path
self.profile_path = profile_path
self.subset = subset
self.instance = instance
self.iup_optimize = iup_optimize
self.options = options
def __init__(
self, font_path, profile_path, subset, instance, iup_optimize, options
):
self.font_path = font_path
self.profile_path = profile_path
self.subset = subset
self.instance = instance
self.iup_optimize = iup_optimize
self.options = options
def unicodes(self):
import re
if self.subset == '*':
return self.subset[0]
elif self.subset == "no-unicodes":
return ""
elif re.match("^U\+", self.subset):
s = re.sub (r"U\+", "", self.subset)
return s
else:
return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset))
def __str__(self):
# Don't print self.subset as contains non-ASCII and some CI's don't like it
return "Test: %s %s %s %s %s" % (
self.font_path,
self.profile_path,
self.instance,
self.iup_optimize,
self.options,
)
def instance_name(self):
if not self.instance:
return self.instance
else:
s = "." + self.instance.replace(':', '-')
if self.iup_optimize:
s += ".iup_optimize"
return s
def unicodes(self):
import re
def get_profile_flags(self):
with open (self.profile_path, mode="r", encoding="utf-8") as f:
return f.read().splitlines()
if self.subset == "*":
return self.subset[0]
elif self.subset == "no-unicodes":
return ""
elif re.match(r"^U\+", self.subset):
s = re.sub(r"U\+", "", self.subset)
return s
else:
return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset))
def get_instance_flags(self):
if not self.instance:
return []
else:
return self.instance.split(',')
def instance_name(self):
if not self.instance:
return self.instance
else:
s = "." + self.instance.replace(":", "-")
if self.iup_optimize:
s += ".iup_optimize"
return s
def get_font_name(self):
font_base_name = os.path.basename(self.font_path)
font_base_name_parts = os.path.splitext(font_base_name)
profile_name = os.path.splitext(os.path.basename(self.profile_path))[0]
def get_profile_flags(self):
with open(self.profile_path, mode="r", encoding="utf-8") as f:
return f.read().splitlines()
if self.unicodes() == "*":
return "%s.%s.all%s%s" % (font_base_name_parts[0],
profile_name,
self.instance_name(),
font_base_name_parts[1])
elif self.unicodes() == "":
return "%s.%s.no-unicodes%s%s" % (font_base_name_parts[0],
profile_name,
self.instance_name(),
font_base_name_parts[1])
else:
return "%s.%s.%s%s%s" % (font_base_name_parts[0],
profile_name,
self.unicodes(),
self.instance_name(),
font_base_name_parts[1])
def get_instance_flags(self):
if not self.instance:
return []
else:
return self.instance.split(",")
def get_font_name(self):
font_base_name = os.path.basename(self.font_path)
font_base_name_parts = os.path.splitext(font_base_name)
profile_name = os.path.splitext(os.path.basename(self.profile_path))[0]
if self.unicodes() == "*":
return "%s.%s.all%s%s" % (
font_base_name_parts[0],
profile_name,
self.instance_name(),
font_base_name_parts[1],
)
elif self.unicodes() == "":
return "%s.%s.no-unicodes%s%s" % (
font_base_name_parts[0],
profile_name,
self.instance_name(),
font_base_name_parts[1],
)
else:
return "%s.%s.%s%s%s" % (
font_base_name_parts[0],
profile_name,
self.unicodes(),
self.instance_name(),
font_base_name_parts[1],
)
def get_font_extension(self):
font_base_name = os.path.basename(self.font_path)
font_base_name_parts = os.path.splitext(font_base_name)
return font_base_name_parts[1]
def get_font_extension(self):
font_base_name = os.path.basename(self.font_path)
font_base_name_parts = os.path.splitext(font_base_name)
return font_base_name_parts[1]
# A group of tests to perform on the subsetter. Each test
# Identifies a font a subsetting profile, and a subset to be cut.
class SubsetTestSuite:
def __init__(self, test_path, definition):
self.test_path = test_path
self.fonts = []
self.profiles = []
self.subsets = []
self.instances = []
self.options = []
self.iup_options = []
self._parse(definition)
def __init__(self, test_path, definition):
self.test_path = test_path
self.fonts = []
self.profiles = []
self.subsets = []
self.instances = []
self.options = []
self.iup_options = []
self._parse(definition)
def get_output_directory(self):
test_name = os.path.splitext(os.path.basename(self.test_path))[0]
data_dir = os.path.join(os.path.dirname(self.test_path), "..")
def get_output_directory(self):
test_name = os.path.splitext(os.path.basename(self.test_path))[0]
data_dir = os.path.join(os.path.dirname(self.test_path), "..")
output_dir = os.path.normpath(os.path.join(data_dir, "expected", test_name))
if not os.path.exists(output_dir):
os.mkdir(output_dir)
if not os.path.isdir(output_dir):
raise Exception("%s is not a directory." % output_dir)
output_dir = os.path.normpath(os.path.join(data_dir, "expected", test_name))
if not os.path.exists(output_dir):
os.mkdir(output_dir)
if not os.path.isdir(output_dir):
raise Exception("%s is not a directory." % output_dir)
return output_dir
return output_dir
def tests(self):
for font in self.fonts:
font = os.path.join(self._base_path(), "fonts", font)
for profile in self.profiles:
profile = os.path.join(self._base_path(), "profiles", profile)
for subset in self.subsets:
if self.instances:
for instance in self.instances:
if self.iup_options:
for iup_option in self.iup_options:
yield Test(font, profile, subset, instance, iup_option == 'Yes', options=self.options)
else:
yield Test(font, profile, subset, instance, False, options=self.options)
else:
yield Test(font, profile, subset, "", False, options=self.options)
def tests(self):
for font in self.fonts:
font = os.path.join(self._base_path(), "fonts", font)
for profile in self.profiles:
profile = os.path.join(self._base_path(), "profiles", profile)
for subset in self.subsets:
if self.instances:
for instance in self.instances:
if self.iup_options:
for iup_option in self.iup_options:
yield Test(
font,
profile,
subset,
instance,
iup_option == "Yes",
options=self.options,
)
else:
yield Test(
font,
profile,
subset,
instance,
False,
options=self.options,
)
else:
yield Test(
font, profile, subset, "", False, options=self.options
)
def _base_path(self):
return os.path.dirname(os.path.dirname(self.test_path))
def _base_path(self):
return os.path.dirname(os.path.dirname(self.test_path))
def _parse(self, definition):
destinations = {
"FONTS:": self.fonts,
"PROFILES:": self.profiles,
"SUBSETS:": self.subsets,
"INSTANCES:": self.instances,
"OPTIONS:": self.options,
"IUP_OPTIONS:": self.iup_options,
}
def _parse(self, definition):
destinations = {
"FONTS:": self.fonts,
"PROFILES:": self.profiles,
"SUBSETS:": self.subsets,
"INSTANCES:": self.instances,
"OPTIONS:": self.options,
"IUP_OPTIONS:": self.iup_options,
}
current_destination = None
for line in definition.splitlines():
line = line.strip()
current_destination = None
for line in definition.splitlines():
line = line.strip()
if line.startswith("#"):
continue
if line.startswith("#"):
continue
if not line:
continue
if not line:
continue
if line in destinations:
current_destination = destinations[line]
elif current_destination is not None:
current_destination.append(line)
else:
raise Exception("Failed to parse test suite file.")
if line in destinations:
current_destination = destinations[line]
elif current_destination is not None:
current_destination.append(line)
else:
raise Exception("Failed to parse test suite file.")

View file

@ -33,12 +33,16 @@ struct face_options_t
{
~face_options_t ()
{
g_free (face_loader);
g_free (font_file);
g_free (face_loader);
hb_face_destroy (face);
}
void set_face (hb_face_t *face_)
{ face = face_; }
{
hb_face_destroy (face);
face = hb_face_reference (face_);
}
void add_options (option_parser_t *parser);
@ -116,7 +120,7 @@ face_options_t::post_parse (GError **error)
}
}
face = cache.face;
set_face (cache.face);
}
static G_GNUC_NORETURN gboolean

View file

@ -71,7 +71,7 @@ struct subset_main_t : option_parser_t, face_options_t, output_options_t<false>
main2.option_parser_t::parse (&argc, &args);
g_free (args);
set_face (hb_face_reference (main2.face));
set_face (main2.face);
}
void parse (int argc, char **argv)