aboutsummaryrefslogtreecommitdiff
path: root/test/threads/hb-subset-threads.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/threads/hb-subset-threads.cc')
-rw-r--r--test/threads/hb-subset-threads.cc180
1 files changed, 180 insertions, 0 deletions
diff --git a/test/threads/hb-subset-threads.cc b/test/threads/hb-subset-threads.cc
new file mode 100644
index 000000000..9d86d8d51
--- /dev/null
+++ b/test/threads/hb-subset-threads.cc
@@ -0,0 +1,180 @@
+#include <cassert>
+#include <cstring>
+#include <thread>
+#include <condition_variable>
+#include <vector>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "hb-subset.h"
+
+enum operation_t
+{
+ subset_codepoints,
+ subset_glyphs
+};
+
+#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
+
+struct test_input_t
+{
+ const char *font_path;
+ const unsigned max_subset_size;
+} default_tests[] =
+{
+ {SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 4000},
+ {SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4000},
+ {SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1000},
+ {SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000},
+ {SUBSET_FONT_BASE_PATH "Mplus1p-Regular.ttf", 10000},
+ {SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000},
+ {SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000},
+};
+
+
+static test_input_t *tests = default_tests;
+static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
+
+
+// https://en.cppreference.com/w/cpp/thread/condition_variable/wait
+static std::condition_variable cv;
+static std::mutex cv_m;
+static bool ready = false;
+
+static unsigned num_repetitions = 1;
+static unsigned num_threads = 3;
+
+static void AddCodepoints(const hb_set_t* codepoints_in_font,
+ unsigned subset_size,
+ hb_subset_input_t* input)
+{
+ auto *unicodes = hb_subset_input_unicode_set (input);
+ hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+ for (unsigned i = 0; i < subset_size; i++) {
+ if (!hb_set_next (codepoints_in_font, &cp)) return;
+ hb_set_add (unicodes, cp);
+ }
+}
+
+static void AddGlyphs(unsigned num_glyphs_in_font,
+ unsigned subset_size,
+ hb_subset_input_t* input)
+{
+ auto *glyphs = hb_subset_input_glyph_set (input);
+ for (unsigned i = 0; i < subset_size && i < num_glyphs_in_font; i++) {
+ hb_set_add (glyphs, i);
+ }
+}
+
+static void subset (operation_t operation,
+ const test_input_t &test_input,
+ hb_face_t *face)
+{
+ // Wait till all threads are ready.
+ {
+ std::unique_lock<std::mutex> lk (cv_m);
+ cv.wait(lk, [] {return ready;});
+ }
+
+ unsigned subset_size = test_input.max_subset_size;
+
+ hb_subset_input_t* input = hb_subset_input_create_or_fail ();
+ assert (input);
+
+ switch (operation)
+ {
+ case subset_codepoints:
+ {
+ hb_set_t* all_codepoints = hb_set_create ();
+ hb_face_collect_unicodes (face, all_codepoints);
+ AddCodepoints(all_codepoints, subset_size, input);
+ hb_set_destroy (all_codepoints);
+ }
+ break;
+
+ case subset_glyphs:
+ {
+ unsigned num_glyphs = hb_face_get_glyph_count (face);
+ AddGlyphs(num_glyphs, subset_size, input);
+ }
+ break;
+ }
+
+ for (unsigned i = 0; i < num_repetitions; i++)
+ {
+ hb_face_t* subset = hb_subset_or_fail (face, input);
+ assert (subset);
+ hb_face_destroy (subset);
+ }
+
+ hb_subset_input_destroy (input);
+}
+
+static void test_operation (operation_t operation,
+ const char *operation_name,
+ const test_input_t &test_input)
+{
+ char name[1024] = "subset";
+ const char *p;
+ strcat (name, "/");
+ p = strrchr (test_input.font_path, '/');
+ strcat (name, p ? p + 1 : test_input.font_path);
+ strcat (name, "/");
+ strcat (name, operation_name);
+
+ printf ("Testing %s\n", name);
+
+ hb_face_t *face;
+ {
+ hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
+ assert (blob);
+ face = hb_face_create (blob, 0);
+ hb_blob_destroy (blob);
+ }
+
+ std::vector<std::thread> threads;
+ for (unsigned i = 0; i < num_threads; i++)
+ threads.push_back (std::thread (subset, operation, test_input, face));
+
+ {
+ std::unique_lock<std::mutex> lk (cv_m);
+ ready = true;
+ }
+ cv.notify_all();
+
+ for (unsigned i = 0; i < num_threads; i++)
+ threads[i].join ();
+
+ hb_face_destroy (face);
+}
+
+int main(int argc, char** argv)
+{
+ if (argc > 1)
+ num_threads = atoi (argv[1]);
+ if (argc > 2)
+ num_repetitions = atoi (argv[2]);
+
+ if (argc > 4)
+ {
+ num_tests = argc - 3;
+ tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
+ for (unsigned i = 0; i < num_tests; i++)
+ {
+ tests[i].font_path = argv[3 + i];
+ }
+ }
+
+ printf ("Num threads %u; num repetitions %u\n", num_threads, num_repetitions);
+ for (unsigned i = 0; i < num_tests; i++)
+ {
+ auto& test_input = tests[i];
+ test_operation (subset_codepoints, "codepoints", test_input);
+ test_operation (subset_glyphs, "glyphs", test_input);
+ }
+
+ if (tests != default_tests)
+ free (tests);
+}