[repacker] expose hb_subset_repack() API, hb_object_t and hb_link_t structs
diff --git a/src/Makefile.sources b/src/Makefile.sources
index ce65014..40fbd99 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -275,6 +275,7 @@
hb-subset-input.hh \
hb-subset-plan.cc \
hb-subset-plan.hh \
+ hb-subset-repacker.cc \
hb-subset.cc \
hb-subset.hh \
hb-repacker.hh \
@@ -282,6 +283,7 @@
HB_SUBSET_headers = \
hb-subset.h \
+ hb-subset-repacker.h \
$(NULL)
HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
diff --git a/src/gen-def.py b/src/gen-def.py
index 7b609a9..205ed7e 100755
--- a/src/gen-def.py
+++ b/src/gen-def.py
@@ -19,7 +19,7 @@
if '--experimental-api' not in sys.argv:
# Move these to harfbuzz-sections.txt when got stable
experimental_symbols = \
-"""""".splitlines ()
+"""hb_subset_repack_or_fail""".splitlines ()
symbols = [x for x in symbols if x not in experimental_symbols]
symbols = "\n".join (symbols)
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index b1726d8..2a9e75c 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -37,7 +37,6 @@
* For a detailed writeup on the overflow resolution algorithm see:
* docs/repacker.md
*/
-
struct graph_t
{
struct vertex_t
@@ -140,7 +139,8 @@
* the 'packed' object stack used internally in the
* serializer
*/
- graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
+ template<typename T>
+ graph_t (const T& objects)
: parents_invalid (true),
distance_invalid (true),
positions_invalid (true),
@@ -1098,8 +1098,9 @@
hb_vector_t<unsigned> num_roots_for_space_;
};
-static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
- graph_t& sorted_graph)
+static inline
+bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+ graph_t& sorted_graph)
{
unsigned space = 0;
hb_set_t roots_to_isolate;
@@ -1147,9 +1148,10 @@
return true;
}
-static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
- hb_set_t& priority_bumped_parents,
- graph_t& sorted_graph)
+static inline
+bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+ hb_set_t& priority_bumped_parents,
+ graph_t& sorted_graph)
{
bool resolution_attempted = false;
@@ -1207,8 +1209,9 @@
* For a detailed writeup describing how the algorithm operates see:
* docs/repacker.md
*/
+template<typename T>
inline hb_blob_t*
-hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
+hb_resolve_overflows (const T& packed,
hb_tag_t table_tag,
unsigned max_rounds = 20) {
// Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh
index 6615f03..40895a4 100644
--- a/src/hb-serialize.hh
+++ b/src/hb-serialize.hh
@@ -36,6 +36,9 @@
#include "hb-map.hh"
#include "hb-pool.hh"
+#ifdef HB_EXPERIMENTAL_API
+#include "hb-subset-repacker.h"
+#endif
/*
* Serialize
@@ -70,6 +73,24 @@
virtual_links.fini ();
}
+ object_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+ object_t (const hb_object_t &o)
+ {
+ head = o.head;
+ tail = o.tail;
+ next = nullptr;
+ real_links.alloc (o.num_real_links);
+ for (unsigned i = 0 ; i < o.num_real_links; i++)
+ real_links.push (o.real_links[i]);
+
+ virtual_links.alloc (o.num_virtual_links);
+ for (unsigned i = 0; i < o.num_virtual_links; i++)
+ virtual_links.push (o.virtual_links[i]);
+ }
+#endif
+
bool operator == (const object_t &o) const
{
// Virtual links aren't considered for equality since they don't affect the functionality
@@ -95,6 +116,20 @@
unsigned position: 28;
unsigned bias;
objidx_t objidx;
+
+ link_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+ link_t (const hb_link_t &o)
+ {
+ width = o.width;
+ is_signed = 0;
+ whence = 0;
+ position = o.position;
+ bias = 0;
+ objidx = o.objidx;
+ }
+#endif
};
char *head;
diff --git a/src/hb-subset-repacker.cc b/src/hb-subset-repacker.cc
new file mode 100644
index 0000000..2447d29
--- /dev/null
+++ b/src/hb-subset-repacker.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+#include "hb-repacker.hh"
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_repack_or_fail:
+ * @hb_objects: raw array of struct hb_object_t, which provides
+ * object graph info
+ * @num_hb_objs: number of hb_object_t in the hb_objects array.
+ *
+ * Given the input object graph info, repack a table to eliminate
+ * offset overflows. A nullptr is returned if the repacking attempt fails.
+ *
+ * Since: EXPERIMENTAL
+ **/
+hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs)
+{
+ hb_vector_t<const hb_object_t *> packed;
+ packed.alloc (num_hb_objs + 1);
+ packed.push (nullptr);
+ for (unsigned i = 0 ; i < num_hb_objs ; i++)
+ packed.push (&(hb_objects[i]));
+ return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
+}
+#endif
+
diff --git a/src/hb-subset-repacker.h b/src/hb-subset-repacker.h
new file mode 100644
index 0000000..f9a2383
--- /dev/null
+++ b/src/hb-subset-repacker.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef HB_SUBSET_REPACKER_H
+#define HB_SUBSET_REPACKER_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * struct hb_link_t
+ * width: offsetSize in bytes
+ * position: position of the offset field in bytes
+ * from beginning of subtable
+ * objidx: index of subtable
+ **/
+struct hb_link_t
+{
+ unsigned width;
+ unsigned position;
+ unsigned objidx;
+};
+
+typedef struct hb_link_t hb_link_t;
+
+/**
+ * struct hb_object_t
+ * head: start of object data
+ * tail: end of object data
+ * num_real_links: num of offset field in the object
+ * real_links: pointer to array of offset info
+ * num_virtual_links: num of objects that must be packed
+ * after current object in the final serialized order
+ * virtual_links: array of virtual link info
+ **/
+struct hb_object_t
+{
+ char *head;
+ char *tail;
+ unsigned num_real_links;
+ hb_link_t *real_links;
+ unsigned num_virtual_links;
+ hb_link_t *virtual_links;
+};
+
+typedef struct hb_object_t hb_object_t;
+
+HB_EXTERN hb_blob_t*
+hb_subset_repack_or_fail (hb_object_t* hb_objects,
+ unsigned num_hb_objs);
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_SUBSET_REPACKER_H */
diff --git a/src/meson.build b/src/meson.build
index c9d3f17..e6a5f22 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -276,11 +276,15 @@
'hb-subset-input.hh',
'hb-subset-plan.cc',
'hb-subset-plan.hh',
+ 'hb-subset-repacker.cc',
'hb-subset.cc',
'hb-subset.hh',
)
-hb_subset_headers = files('hb-subset.h')
+hb_subset_headers = files(
+ 'hb-subset.h',
+ 'hb-subset-repacker.h'
+)
hb_gobject_sources = files(
'hb-gobject-structs.cc'
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index a2412f9..ffd4a0f 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -78,6 +78,7 @@
test-subset-gpos \
test-subset-colr \
test-subset-cbdt \
+ test-subset-repacker \
test-unicode \
test-var-coords \
test-version \
@@ -105,6 +106,7 @@
test_subset_nameids_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_gpos_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_subset_colr_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_repacker_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
test_unicode_CPPFLAGS = \
$(AM_CPPFLAGS) \
diff --git a/test/api/fonts/repacker_expected.otf b/test/api/fonts/repacker_expected.otf
new file mode 100644
index 0000000..d8ed678
--- /dev/null
+++ b/test/api/fonts/repacker_expected.otf
Binary files differ
diff --git a/test/api/meson.build b/test/api/meson.build
index ab64338..f5cdce8 100644
--- a/test/api/meson.build
+++ b/test/api/meson.build
@@ -32,6 +32,7 @@
'test-ot-tag.c',
'test-ot-extents-cff.c',
'test-ot-metrics-tt-var.c',
+ 'test-subset-repacker.c',
'test-set.c',
'test-shape.c',
'test-style.c',
diff --git a/test/api/test-subset-repacker.c b/test/api/test-subset-repacker.c
new file mode 100644
index 0000000..e92683d
--- /dev/null
+++ b/test/api/test-subset-repacker.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+#ifdef HB_EXPERIMENTAL_API
+#include "hb-subset-repacker.h"
+
+char test_gsub_data[106] = "\x0\x1\x0\x0\x0\xa\x0\x1e\x0\x2c\x0\x1\x6c\x61\x74\x6e\x0\x8\x0\x4\x0\x0\x0\x0\xff\xff\x0\x1\x0\x0\x0\x1\x74\x65\x73\x74\x0\x8\x0\x0\x0\x1\x0\x1\x0\x2\x0\x2a\x0\x6\x0\x5\x0\x0\x0\x1\x0\x8\x0\x1\x0\x8\x0\x1\x0\xe\x0\x1\x0\x1\x0\x1\x0\x1\x0\x4\x0\x2\x0\x1\x0\x2\x0\x1\x0\x0\x0\x1\x0\x0\x0\x1\x0\x8\x0\x1\x0\x6\x0\x1\x0\x1\x0\x1\x0\x2";
+
+static void
+test_hb_repack_with_cy_struct (void)
+{
+ hb_object_t *hb_objs = calloc (15, sizeof (hb_object_t));
+
+ hb_objs[0].head = &(test_gsub_data[100]);
+ hb_objs[0].tail = &(test_gsub_data[105]) + 1;
+ hb_objs[0].num_real_links = 0;
+ hb_objs[0].num_virtual_links = 0;
+ hb_objs[0].real_links = NULL;
+ hb_objs[0].virtual_links = NULL;
+
+ hb_objs[1].head = &(test_gsub_data[94]);
+ hb_objs[1].tail = &(test_gsub_data[100]);
+ hb_objs[1].num_real_links = 1;
+ hb_objs[1].num_virtual_links = 0;
+ hb_objs[1].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[1].real_links[0].width = 2;
+ hb_objs[1].real_links[0].position = 2;
+ hb_objs[1].real_links[0].objidx = 1;
+ hb_objs[1].virtual_links = NULL;
+
+
+ hb_objs[2].head = &(test_gsub_data[86]);
+ hb_objs[2].tail = &(test_gsub_data[94]);
+ hb_objs[2].num_real_links = 1;
+ hb_objs[2].num_virtual_links = 0;
+ hb_objs[2].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[2].real_links[0].width = 2;
+ hb_objs[2].real_links[0].position = 6;
+ hb_objs[2].real_links[0].objidx = 2;
+ hb_objs[2].virtual_links = NULL;
+
+ hb_objs[3].head = &(test_gsub_data[76]);
+ hb_objs[3].tail = &(test_gsub_data[86]);
+ hb_objs[3].num_real_links = 0;
+ hb_objs[3].num_virtual_links = 0;
+ hb_objs[3].real_links = NULL;
+ hb_objs[3].virtual_links = NULL;
+
+ hb_objs[4].head = &(test_gsub_data[72]);
+ hb_objs[4].tail = &(test_gsub_data[76]);
+ hb_objs[4].num_real_links = 1;
+ hb_objs[4].num_virtual_links = 0;
+ hb_objs[4].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[4].real_links[0].width = 2;
+ hb_objs[4].real_links[0].position = 2;
+ hb_objs[4].real_links[0].objidx = 4;
+ hb_objs[4].virtual_links = NULL;
+
+ hb_objs[5].head = &(test_gsub_data[66]);
+ hb_objs[5].tail = &(test_gsub_data[72]);
+ hb_objs[5].num_real_links = 0;
+ hb_objs[5].num_virtual_links = 0;
+ hb_objs[5].real_links = NULL;
+ hb_objs[5].virtual_links = NULL;
+
+ hb_objs[6].head = &(test_gsub_data[58]);
+ hb_objs[6].tail = &(test_gsub_data[66]);
+ hb_objs[6].num_real_links = 2;
+ hb_objs[6].num_virtual_links = 0;
+ hb_objs[6].real_links = calloc (2, sizeof (hb_link_t));
+ hb_objs[6].real_links[0].width = 2;
+ hb_objs[6].real_links[0].position = 6;
+ hb_objs[6].real_links[0].objidx = 5;
+ hb_objs[6].real_links[1].width = 2;
+ hb_objs[6].real_links[1].position = 2;
+ hb_objs[6].real_links[1].objidx = 6;
+ hb_objs[6].virtual_links = NULL;
+
+ hb_objs[7].head = &(test_gsub_data[50]);
+ hb_objs[7].tail = &(test_gsub_data[58]);
+ hb_objs[7].num_real_links = 1;
+ hb_objs[7].num_virtual_links = 0;
+ hb_objs[7].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[7].real_links[0].width = 2;
+ hb_objs[7].real_links[0].position = 6;
+ hb_objs[7].real_links[0].objidx = 7;
+ hb_objs[7].virtual_links = NULL;
+
+ hb_objs[8].head = &(test_gsub_data[44]);
+ hb_objs[8].tail = &(test_gsub_data[50]);
+ hb_objs[8].num_real_links = 2;
+ hb_objs[8].num_virtual_links = 0;
+ hb_objs[8].real_links = calloc (2, sizeof (hb_link_t));
+ hb_objs[8].real_links[0].width = 2;
+ hb_objs[8].real_links[0].position = 2;
+ hb_objs[8].real_links[0].objidx = 3;
+ hb_objs[8].real_links[1].width = 2;
+ hb_objs[8].real_links[1].position = 4;
+ hb_objs[8].real_links[1].objidx = 8;
+ hb_objs[8].virtual_links = NULL;
+
+ hb_objs[9].head = &(test_gsub_data[38]);
+ hb_objs[9].tail = &(test_gsub_data[44]);
+ hb_objs[9].num_real_links = 0;
+ hb_objs[9].num_virtual_links = 0;
+ hb_objs[9].real_links = NULL;
+ hb_objs[9].virtual_links = NULL;
+
+ hb_objs[10].head = &(test_gsub_data[30]);
+ hb_objs[10].tail = &(test_gsub_data[38]);
+ hb_objs[10].num_real_links = 1;
+ hb_objs[10].num_virtual_links = 0;
+ hb_objs[10].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[10].real_links[0].width = 2;
+ hb_objs[10].real_links[0].position = 6;
+ hb_objs[10].real_links[0].objidx = 10;
+ hb_objs[10].virtual_links = NULL;
+
+ hb_objs[11].head = &(test_gsub_data[22]);
+ hb_objs[11].tail = &(test_gsub_data[30]);
+ hb_objs[11].num_real_links = 0;
+ hb_objs[11].num_virtual_links = 0;
+ hb_objs[11].real_links = NULL;
+ hb_objs[11].virtual_links = NULL;
+
+ hb_objs[12].head = &(test_gsub_data[18]);
+ hb_objs[12].tail = &(test_gsub_data[22]);
+ hb_objs[12].num_real_links = 1;
+ hb_objs[12].num_virtual_links = 0;
+ hb_objs[12].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[12].real_links[0].width = 2;
+ hb_objs[12].real_links[0].position = 0;
+ hb_objs[12].real_links[0].objidx = 12;
+ hb_objs[12].virtual_links = NULL;
+
+ hb_objs[13].head = &(test_gsub_data[10]);
+ hb_objs[13].tail = &(test_gsub_data[18]);
+ hb_objs[13].num_real_links = 1;
+ hb_objs[13].num_virtual_links = 0;
+ hb_objs[13].real_links = malloc (sizeof (hb_link_t));
+ hb_objs[13].real_links[0].width = 2;
+ hb_objs[13].real_links[0].position = 6;
+ hb_objs[13].real_links[0].objidx = 13;
+ hb_objs[13].virtual_links = NULL;
+
+ hb_objs[14].head = &(test_gsub_data[0]);
+ hb_objs[14].tail = &(test_gsub_data[10]);
+ hb_objs[14].num_real_links = 3;
+ hb_objs[14].num_virtual_links = 0;
+ hb_objs[14].real_links = calloc (3, sizeof (hb_link_t));
+ hb_objs[14].real_links[0].width = 2;
+ hb_objs[14].real_links[0].position = 8;
+ hb_objs[14].real_links[0].objidx = 9;
+ hb_objs[14].real_links[1].width = 2;
+ hb_objs[14].real_links[1].position = 6;
+ hb_objs[14].real_links[1].objidx = 11;
+ hb_objs[14].real_links[2].width = 2;
+ hb_objs[14].real_links[2].position = 4;
+ hb_objs[14].real_links[2].objidx = 14;
+ hb_objs[14].virtual_links = NULL;
+
+ hb_blob_t *result = hb_subset_repack_or_fail (hb_objs, 15);
+
+ hb_face_t *face_expected = hb_test_open_font_file ("fonts/repacker_expected.otf");
+ hb_blob_t *expected_blob = hb_face_reference_table (face_expected, HB_TAG ('G','S','U','B'));
+ fprintf(stderr, "expected %d bytes, actual %d bytes\n", hb_blob_get_length(expected_blob), hb_blob_get_length (result));
+
+ if (hb_blob_get_length (expected_blob) != 0 ||
+ hb_blob_get_length (result) != 0)
+ hb_test_assert_blobs_equal (expected_blob, result);
+
+ hb_face_destroy (face_expected);
+ hb_blob_destroy (expected_blob);
+ hb_blob_destroy (result);
+
+ for (unsigned i = 0 ; i < 15; i++)
+ {
+ if (hb_objs[i].real_links != NULL)
+ free (hb_objs[i].real_links);
+ }
+
+ free (hb_objs);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ hb_test_init (&argc, &argv);
+
+ hb_test_add (test_hb_repack_with_cy_struct);
+
+ return hb_test_run();
+}
+#else
+int main (int argc HB_UNUSED, char **argv HB_UNUSED)
+{
+ return 0;
+}
+#endif