mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-13 08:42:59 +00:00
Merge pull request #5122 from harfbuzz/using
Add API for querying font-funcs / face-loaders and setting them using strings
This commit is contained in:
commit
0a01fc558b
23 changed files with 458 additions and 292 deletions
|
@ -365,6 +365,8 @@ hb_face_t
|
|||
hb_face_create
|
||||
hb_face_create_or_fail
|
||||
hb_face_create_from_file_or_fail
|
||||
hb_face_create_from_file_or_fail_using
|
||||
hb_face_list_loaders
|
||||
hb_reference_table_func_t
|
||||
hb_face_create_for_tables
|
||||
hb_face_get_empty
|
||||
|
@ -458,6 +460,8 @@ hb_font_get_serial
|
|||
hb_font_changed
|
||||
hb_font_set_funcs
|
||||
hb_font_set_funcs_data
|
||||
hb_font_set_funcs_using
|
||||
hb_font_list_funcs
|
||||
hb_font_subtract_glyph_origin_for_direction
|
||||
hb_font_funcs_create
|
||||
hb_font_funcs_get_empty
|
||||
|
|
|
@ -21,8 +21,6 @@ struct test_input_t
|
|||
static test_input_t *tests = default_tests;
|
||||
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
|
||||
|
||||
enum backend_t { HARFBUZZ, FREETYPE, FONTATIONS, CORETEXT };
|
||||
|
||||
enum operation_t
|
||||
{
|
||||
nominal_glyphs,
|
||||
|
@ -81,7 +79,8 @@ _draw_funcs_create (void)
|
|||
}
|
||||
|
||||
static void BM_Font (benchmark::State &state,
|
||||
bool is_var, backend_t backend, operation_t operation,
|
||||
bool is_var, const char * backend,
|
||||
operation_t operation,
|
||||
const test_input_t &test_input)
|
||||
{
|
||||
hb_font_t *font;
|
||||
|
@ -100,29 +99,12 @@ static void BM_Font (benchmark::State &state,
|
|||
hb_font_set_variations (font, &wght, 1);
|
||||
}
|
||||
|
||||
switch (backend)
|
||||
bool ret = hb_font_set_funcs_using (font, backend);
|
||||
if (!ret)
|
||||
{
|
||||
case HARFBUZZ:
|
||||
hb_ot_font_set_funcs (font);
|
||||
break;
|
||||
|
||||
case FREETYPE:
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FONTATIONS:
|
||||
#ifdef HAVE_FONTATIONS
|
||||
hb_fontations_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CORETEXT:
|
||||
#ifdef HAVE_CORETEXT
|
||||
hb_coretext_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
state.SkipWithError("Backend failed to initialize for font.");
|
||||
hb_font_destroy (font);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (operation)
|
||||
|
@ -210,29 +192,12 @@ static void BM_Font (benchmark::State &state,
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
|
||||
switch (backend)
|
||||
bool ret = hb_font_set_funcs_using (font, backend);
|
||||
if (!ret)
|
||||
{
|
||||
case HARFBUZZ:
|
||||
hb_ot_font_set_funcs (font);
|
||||
break;
|
||||
|
||||
case FREETYPE:
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FONTATIONS:
|
||||
#ifdef HAVE_FONTATIONS
|
||||
hb_fontations_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CORETEXT:
|
||||
#ifdef HAVE_CORETEXT
|
||||
hb_coretext_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
state.SkipWithError("Backend failed to initialize for font.");
|
||||
hb_font_destroy (font);
|
||||
return;
|
||||
}
|
||||
|
||||
hb_buffer_t *buffer = hb_buffer_create ();
|
||||
|
@ -252,8 +217,7 @@ static void BM_Font (benchmark::State &state,
|
|||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
static void test_backend (backend_t backend,
|
||||
const char *backend_name,
|
||||
static void test_backend (const char *backend,
|
||||
bool variable,
|
||||
operation_t op,
|
||||
const char *op_name,
|
||||
|
@ -267,7 +231,7 @@ static void test_backend (backend_t backend,
|
|||
strcat (name, p ? p + 1 : test_input.font_path);
|
||||
strcat (name, variable ? "/var" : "");
|
||||
strcat (name, "/");
|
||||
strcat (name, backend_name);
|
||||
strcat (name, backend);
|
||||
|
||||
benchmark::RegisterBenchmark (name, BM_Font, variable, backend, op, test_input)
|
||||
->Unit(time_unit);
|
||||
|
@ -277,6 +241,7 @@ static void test_operation (operation_t op,
|
|||
const char *op_name,
|
||||
benchmark::TimeUnit time_unit)
|
||||
{
|
||||
const char **supported_backends = hb_font_list_funcs ();
|
||||
for (unsigned i = 0; i < num_tests; i++)
|
||||
{
|
||||
auto& test_input = tests[i];
|
||||
|
@ -284,16 +249,8 @@ static void test_operation (operation_t op,
|
|||
{
|
||||
bool is_var = (bool) variable;
|
||||
|
||||
test_backend (HARFBUZZ, "hb", is_var, op, op_name, time_unit, test_input);
|
||||
#ifdef HAVE_FREETYPE
|
||||
test_backend (FREETYPE, "ft", is_var, op, op_name, time_unit, test_input);
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
test_backend (FONTATIONS, "fontations", is_var, op, op_name, time_unit, test_input);
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
test_backend (CORETEXT, "coretext", is_var, op, op_name, time_unit, test_input);
|
||||
#endif
|
||||
for (const char **backend = supported_backends; *backend; backend++)
|
||||
test_backend (*backend, is_var, op, op_name, time_unit, test_input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,22 +56,7 @@ static inline hb_face_t *
|
|||
hb_benchmark_face_create_from_file_or_fail (const char *font_path,
|
||||
unsigned face_index)
|
||||
{
|
||||
const char *loader = getenv ("HB_FACE_LOADER");
|
||||
if (loader && !*loader)
|
||||
loader = nullptr;
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
if (loader && !strcmp (loader, "ft"))
|
||||
return hb_ft_face_create_from_file_or_fail (font_path, face_index);
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
if (loader && !strcmp (loader, "coretext"))
|
||||
return hb_coretext_face_create_from_file_or_fail (font_path, face_index);
|
||||
#endif
|
||||
if (!loader || !strcmp (loader, "ot"))
|
||||
return hb_face_create_from_file_or_fail (font_path, face_index);
|
||||
|
||||
assert (false);
|
||||
return hb_face_create_from_file_or_fail_using (font_path, face_index, nullptr);
|
||||
}
|
||||
|
||||
HB_END_DECLS
|
||||
|
|
|
@ -3,8 +3,8 @@ name = "harfbuzz_fontations"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
read-fonts = "0.27.2"
|
||||
skrifa = "0.28.1"
|
||||
read-fonts = "0.27"
|
||||
skrifa = "0.28"
|
||||
|
||||
[lib]
|
||||
name = "harfbuzz_fontations"
|
||||
|
|
|
@ -14,7 +14,14 @@ cargo = find_program('cargo')
|
|||
rustfmt = find_program('rustfmt')
|
||||
|
||||
rust_flags = ''
|
||||
cargo_args = []
|
||||
cargo_args = [
|
||||
'--package', 'harfbuzz_fontations',
|
||||
'--lib',
|
||||
'--target-dir', meson.current_build_dir(),
|
||||
'--manifest-path', meson.current_source_dir() / 'Cargo.toml',
|
||||
'-Z', 'build-std=std,panic_abort',
|
||||
'-Z', 'build-std-features=panic_immediate_abort',
|
||||
]
|
||||
|
||||
buildtype = get_option('buildtype')
|
||||
if buildtype == 'release' or buildtype == 'debugoptimized'
|
||||
|
@ -24,9 +31,6 @@ endif
|
|||
opt_level = get_option('optimization')
|
||||
rust_flags += ' -C opt-level=' + opt_level
|
||||
|
||||
cargo_args += ['-Z', 'build-std=std,panic_abort',
|
||||
'-Z', 'build-std-features=panic_immediate_abort']
|
||||
|
||||
harfbuzz_fontations = custom_target(
|
||||
'harfbuzz_fontations',
|
||||
input: ['lib.rs', 'Cargo.toml', 'Cargo.lock'],
|
||||
|
@ -38,11 +42,8 @@ harfbuzz_fontations = custom_target(
|
|||
command: [
|
||||
cargo, 'build',
|
||||
] + cargo_args + [
|
||||
'--lib',
|
||||
'--target-dir', meson.current_build_dir(),
|
||||
'-Z', 'unstable-options',
|
||||
'--artifact-dir', meson.current_build_dir(),
|
||||
'--manifest-path', meson.current_source_dir() / 'Cargo.toml'
|
||||
],
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('prefix'), 'lib'),
|
||||
|
@ -55,13 +56,11 @@ harfbuzz_fontations_dep = declare_dependency(
|
|||
clippy_fix = run_target(
|
||||
'clippy-fix',
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs, harfbuzz_fontations],
|
||||
command: [
|
||||
cargo, 'clippy',
|
||||
'--allow-dirty', '--fix',
|
||||
] + cargo_args + [
|
||||
'--lib', '-p', 'harfbuzz_fontations',
|
||||
'--target-dir', meson.current_build_dir(),
|
||||
'--manifest-path', meson.current_source_dir() / 'Cargo.toml',
|
||||
'--allow-dirty', '--fix',
|
||||
],
|
||||
)
|
||||
if get_option('tests').enabled() and cargo.found()
|
||||
|
@ -69,20 +68,20 @@ if get_option('tests').enabled() and cargo.found()
|
|||
'clippy',
|
||||
cargo,
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs, harfbuzz_fontations],
|
||||
args: [
|
||||
'clippy',
|
||||
] + cargo_args + [
|
||||
'--lib', '-p', 'harfbuzz_fontations',
|
||||
'--target-dir', meson.current_build_dir(),
|
||||
'--manifest-path', meson.current_source_dir() / 'Cargo.toml',
|
||||
'--', '-D', 'warnings',
|
||||
],
|
||||
timeout: 120,
|
||||
)
|
||||
endif
|
||||
|
||||
rustfmt_fix = run_target(
|
||||
'rustfmt-fix',
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs],
|
||||
command: [
|
||||
rustfmt,
|
||||
'--edition', '2021',
|
||||
|
@ -95,6 +94,7 @@ if get_option('tests').enabled() and rustfmt.found()
|
|||
'rustfmt',
|
||||
rustfmt,
|
||||
env: ['OUT_DIR=' + meson.current_build_dir()],
|
||||
depends: [hb_rs],
|
||||
args: [
|
||||
'--check',
|
||||
'--edition', '2021',
|
||||
|
|
|
@ -186,6 +186,8 @@ struct hb_atomic_int_t
|
|||
|
||||
hb_atomic_int_t& operator = (int v_) { set_relaxed (v_); return *this; }
|
||||
operator int () const { return get_relaxed (); }
|
||||
int operator ++ (int) { return inc (); }
|
||||
int operator -- (int) { return dec (); }
|
||||
|
||||
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set_release (int v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
|
|
135
src/hb-face.cc
135
src/hb-face.cc
|
@ -34,6 +34,13 @@
|
|||
#include "hb-ot-face.hh"
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include "hb-coretext.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-face
|
||||
|
@ -318,7 +325,135 @@ hb_face_create_from_file_or_fail (const char *file_name,
|
|||
|
||||
return face;
|
||||
}
|
||||
|
||||
static struct supported_face_loaders_t {
|
||||
char name[9];
|
||||
hb_face_t * (*func) (const char *font_file, unsigned face_index);
|
||||
} supported_face_loaders[] =
|
||||
{
|
||||
#ifndef HB_NO_OPEN
|
||||
{"ot", hb_face_create_from_file_or_fail},
|
||||
#endif
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft", hb_ft_face_create_from_file_or_fail},
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
{"coretext", hb_coretext_face_create_from_file_or_fail},
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* hb_face_create_from_file_or_fail_using:
|
||||
* @file_name: A font filename
|
||||
* @index: The index of the face within the file
|
||||
* @loader_name: (nullable): The name of the loader to use, or `NULL`
|
||||
*
|
||||
* A thin wrapper around the face loader functions registered with HarfBuzz.
|
||||
* If @loader_name is `NULL` or the empty string, the first available loader
|
||||
* is used.
|
||||
*
|
||||
* For example, the FreeType ("ft") loader might be able to load
|
||||
* .woff and .woff2 files if FreeType is built with those features,
|
||||
* whereas the OpenType ("ot") loader will not.
|
||||
*
|
||||
* Return value: (transfer full): The new face object, or `NULL` if
|
||||
* the file cannot be read or the loader fails to load the face.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
hb_face_t *
|
||||
hb_face_create_from_file_or_fail_using (const char *file_name,
|
||||
unsigned int index,
|
||||
const char *loader_name)
|
||||
{
|
||||
bool retry = false;
|
||||
|
||||
if (!loader_name || !*loader_name)
|
||||
{
|
||||
static hb_atomic_ptr_t<const char> static_funcs_name;
|
||||
loader_name = static_funcs_name.get_acquire ();
|
||||
if (!loader_name)
|
||||
{
|
||||
loader_name = getenv ("HB_FACE_LOADER");
|
||||
if (!loader_name)
|
||||
loader_name = "";
|
||||
if (!static_funcs_name.cmpexch (nullptr, loader_name))
|
||||
loader_name = static_funcs_name.get_acquire ();
|
||||
}
|
||||
retry = true;
|
||||
}
|
||||
if (loader_name && !*loader_name) loader_name = nullptr;
|
||||
|
||||
retry:
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
{
|
||||
if (!loader_name || !strcmp (supported_face_loaders[i].name, loader_name))
|
||||
return supported_face_loaders[i].func (file_name, index);
|
||||
}
|
||||
|
||||
if (retry)
|
||||
{
|
||||
retry = false;
|
||||
loader_name = nullptr;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static inline void free_static_face_loader_list ();
|
||||
|
||||
static const char * const nil_face_loader_list[] = {nullptr};
|
||||
|
||||
static struct hb_face_loader_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
||||
hb_face_loader_list_lazy_loader_t>
|
||||
{
|
||||
static const char ** create ()
|
||||
{
|
||||
const char **face_loader_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_face_loaders), sizeof (const char *));
|
||||
if (unlikely (!face_loader_list))
|
||||
return nullptr;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
face_loader_list[i] = supported_face_loaders[i].name;
|
||||
face_loader_list[i] = nullptr;
|
||||
|
||||
hb_atexit (free_static_face_loader_list);
|
||||
|
||||
return face_loader_list;
|
||||
}
|
||||
static void destroy (const char **l)
|
||||
{ hb_free (l); }
|
||||
static const char * const * get_null ()
|
||||
{ return nil_face_loader_list; }
|
||||
} static_face_loader_list;
|
||||
|
||||
static inline
|
||||
void free_static_face_loader_list ()
|
||||
{
|
||||
static_face_loader_list.free_instance ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_list_loaders:
|
||||
*
|
||||
* Retrieves the list of face loaders supported by HarfBuzz.
|
||||
*
|
||||
* Return value: (transfer none) (array zero-terminated=1): a
|
||||
* `NULL`-terminated array of supported face loaders
|
||||
* constant strings. The returned array is owned by HarfBuzz
|
||||
* and should not be modified or freed.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
const char **
|
||||
hb_face_list_loaders ()
|
||||
{
|
||||
return static_face_loader_list.get_unconst ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* hb_face_get_empty:
|
||||
|
|
|
@ -67,6 +67,15 @@ HB_EXTERN hb_face_t *
|
|||
hb_face_create_from_file_or_fail (const char *file_name,
|
||||
unsigned int index);
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_face_create_from_file_or_fail_using (const char *file_name,
|
||||
unsigned int index,
|
||||
const char *loader_name);
|
||||
|
||||
HB_EXTERN const char **
|
||||
hb_face_list_loaders (void);
|
||||
|
||||
|
||||
/**
|
||||
* hb_reference_table_func_t:
|
||||
* @face: an #hb_face_t to reference table for
|
||||
|
|
160
src/hb-font.cc
160
src/hb-font.cc
|
@ -38,6 +38,19 @@
|
|||
#include "hb-ot-var-avar-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
|
||||
#ifndef HB_NO_OT_FONT
|
||||
#include "hb-ot.h"
|
||||
#endif
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
#include "hb-fontations.h"
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include "hb-coretext.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:hb-font
|
||||
|
@ -1854,10 +1867,7 @@ hb_font_create (hb_face_t *face)
|
|||
{
|
||||
hb_font_t *font = _hb_font_create (face);
|
||||
|
||||
#ifndef HB_NO_OT_FONT
|
||||
/* Install our in-house, very lightweight, funcs. */
|
||||
hb_ot_font_set_funcs (font);
|
||||
#endif
|
||||
hb_font_set_funcs_using (font, nullptr);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (face && face->index >> 16)
|
||||
|
@ -2292,6 +2302,133 @@ hb_font_set_funcs_data (hb_font_t *font,
|
|||
font->destroy = destroy;
|
||||
}
|
||||
|
||||
static struct supported_font_funcs_t {
|
||||
char name[12];
|
||||
void (*func) (hb_font_t *);
|
||||
} supported_font_funcs[] =
|
||||
{
|
||||
#ifndef HB_NO_OT_FONT
|
||||
{"ot", hb_ot_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft", hb_ft_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
{"fontations",hb_fontations_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
{"coretext", hb_coretext_font_set_funcs},
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* hb_font_set_funcs_using:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @name: The name of the font-functions structure to use, or `NULL`
|
||||
*
|
||||
* Sets the font-functions structure to use for a font, based on the
|
||||
* specified name.
|
||||
*
|
||||
* If @name is `NULL` or the empty string, the default (first) functioning font-functions
|
||||
* are used. This default can be changed by setting the `HB_FONT_FUNCS` environment
|
||||
* variable to the name of the desired font-functions.
|
||||
*
|
||||
* Return value: `true` if the font-functions was found and set, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_set_funcs_using (hb_font_t *font,
|
||||
const char *name)
|
||||
{
|
||||
bool retry = false;
|
||||
|
||||
if (!name || !*name)
|
||||
{
|
||||
static hb_atomic_ptr_t<const char> static_funcs_name;
|
||||
name = static_funcs_name.get_acquire ();
|
||||
if (!name)
|
||||
{
|
||||
name = getenv ("HB_FONT_FUNCS");
|
||||
if (!name)
|
||||
name = "";
|
||||
if (!static_funcs_name.cmpexch (nullptr, name))
|
||||
name = static_funcs_name.get_acquire ();
|
||||
}
|
||||
retry = true;
|
||||
}
|
||||
if (name && !*name) name = nullptr;
|
||||
|
||||
retry:
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
if (!name || strcmp (supported_font_funcs[i].name, name) == 0)
|
||||
{
|
||||
supported_font_funcs[i].func (font);
|
||||
if (name || font->klass != hb_font_funcs_get_empty ())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (retry)
|
||||
{
|
||||
retry = false;
|
||||
name = nullptr;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void free_static_font_funcs_list ();
|
||||
|
||||
static const char * const nil_font_funcs_list[] = {nullptr};
|
||||
|
||||
static struct hb_font_funcs_list_lazy_loader_t : hb_lazy_loader_t<const char *,
|
||||
hb_font_funcs_list_lazy_loader_t>
|
||||
{
|
||||
static const char ** create ()
|
||||
{
|
||||
const char **font_funcs_list = (const char **) hb_calloc (1 + ARRAY_LENGTH (supported_font_funcs), sizeof (const char *));
|
||||
if (unlikely (!font_funcs_list))
|
||||
return nullptr;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
font_funcs_list[i] = supported_font_funcs[i].name;
|
||||
font_funcs_list[i] = nullptr;
|
||||
|
||||
hb_atexit (free_static_font_funcs_list);
|
||||
|
||||
return font_funcs_list;
|
||||
}
|
||||
static void destroy (const char **l)
|
||||
{ hb_free (l); }
|
||||
static const char * const * get_null ()
|
||||
{ return nil_font_funcs_list; }
|
||||
} static_font_funcs_list;
|
||||
|
||||
static inline
|
||||
void free_static_font_funcs_list ()
|
||||
{
|
||||
static_font_funcs_list.free_instance ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_list_funcs:
|
||||
*
|
||||
* Retrieves the list of font functions supported by HarfBuzz.
|
||||
*
|
||||
* Return value: (transfer none) (array zero-terminated=1): a
|
||||
* `NULL`-terminated array of supported font functions
|
||||
* constant strings. The returned array is owned by HarfBuzz
|
||||
* and should not be modified or freed.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
**/
|
||||
const char **
|
||||
hb_font_list_funcs ()
|
||||
{
|
||||
return static_font_funcs_list.get_unconst ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_scale:
|
||||
|
@ -2607,7 +2744,8 @@ hb_font_set_variations (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
font->serial++;
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
|
||||
{
|
||||
|
@ -2677,7 +2815,8 @@ hb_font_set_variation (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
font->serial++;
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
// TODO Share some of this code with set_variations()
|
||||
|
||||
|
@ -2749,7 +2888,8 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
font->serial++;
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
@ -2787,7 +2927,8 @@ hb_font_set_var_named_instance (hb_font_t *font,
|
|||
if (font->instance_index == instance_index)
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
font->serial++;
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
font->instance_index = instance_index;
|
||||
hb_font_set_variations (font, nullptr, 0);
|
||||
|
@ -2834,7 +2975,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
font->serial++;
|
||||
font->serial_coords = font->serial;
|
||||
|
||||
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
|
|
|
@ -1052,6 +1052,12 @@ hb_font_set_funcs_data (hb_font_t *font,
|
|||
void *font_data,
|
||||
hb_destroy_func_t destroy);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_set_funcs_using (hb_font_t *font,
|
||||
const char *name);
|
||||
|
||||
HB_EXTERN const char **
|
||||
hb_font_list_funcs (void);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_scale (hb_font_t *font,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "hb.hh"
|
||||
|
||||
#include "hb-face.hh"
|
||||
#include "hb-atomic.hh"
|
||||
#include "hb-shaper.hh"
|
||||
|
||||
|
||||
|
@ -105,8 +106,8 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
|
|||
struct hb_font_t
|
||||
{
|
||||
hb_object_header_t header;
|
||||
unsigned int serial;
|
||||
unsigned int serial_coords;
|
||||
hb_atomic_int_t serial;
|
||||
hb_atomic_int_t serial_coords;
|
||||
|
||||
hb_font_t *parent;
|
||||
hb_face_t *face;
|
||||
|
|
29
src/hb-ft.cc
29
src/hb-ft.cc
|
@ -101,7 +101,7 @@ struct hb_ft_font_t
|
|||
|
||||
mutable hb_mutex_t lock; /* Protects members below. */
|
||||
FT_Face ft_face;
|
||||
mutable unsigned cached_serial;
|
||||
mutable hb_atomic_int_t cached_serial;
|
||||
mutable hb_ft_advance_cache_t advance_cache;
|
||||
};
|
||||
|
||||
|
@ -118,7 +118,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
|
|||
|
||||
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
|
||||
|
||||
ft_font->cached_serial = (unsigned) -1;
|
||||
ft_font->cached_serial = -1;
|
||||
new (&ft_font->advance_cache) hb_ft_advance_cache_t;
|
||||
|
||||
return ft_font;
|
||||
|
@ -213,9 +213,10 @@ _hb_ft_hb_font_check_changed (hb_font_t *font,
|
|||
{
|
||||
if (font->serial != ft_font->cached_serial)
|
||||
{
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
_hb_ft_hb_font_changed (font, ft_font->ft_face);
|
||||
ft_font->advance_cache.clear ();
|
||||
ft_font->cached_serial = font->serial;
|
||||
ft_font->cached_serial.set_release (font->serial.get_acquire ());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -478,6 +479,8 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
@ -561,6 +564,8 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Fixed v;
|
||||
float y_mult;
|
||||
|
@ -614,6 +619,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
float x_mult, y_mult;
|
||||
|
@ -658,6 +665,8 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Vector kerningv;
|
||||
|
||||
|
@ -677,6 +686,8 @@ hb_ft_get_glyph_extents (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
float x_mult, y_mult;
|
||||
|
@ -749,6 +760,8 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
|
@ -826,6 +839,8 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
float y_mult;
|
||||
|
@ -916,6 +931,8 @@ hb_ft_draw_glyph (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
|
@ -990,6 +1007,8 @@ hb_ft_paint_glyph (hb_font_t *font,
|
|||
void *user_data)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
|
||||
|
@ -1456,6 +1475,10 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
* variation-axis settings on the @font.
|
||||
* This call is fast if nothing has changed on @font.
|
||||
*
|
||||
* Note that as of version REPLACEME, calling this function is not necessary,
|
||||
* as HarfBuzz will automatically detect changes to the font and update
|
||||
* the underlying FT_Face as needed.
|
||||
*
|
||||
* Return value: true if changed, false otherwise
|
||||
*
|
||||
* Since: 4.4.0
|
||||
|
|
|
@ -91,8 +91,10 @@ void free_static_shaper_list ()
|
|||
*
|
||||
* Retrieves the list of shapers supported by HarfBuzz.
|
||||
*
|
||||
* Return value: (transfer none) (array zero-terminated=1): an array of
|
||||
* constant strings
|
||||
* Return value: (transfer none) (array zero-terminated=1): a
|
||||
* `NULL`-terminated array of supported shapers constant string.
|
||||
* The returned array is owned by HarfBuzz and should not be
|
||||
* modified or freed.
|
||||
*
|
||||
* Since: 0.9.2
|
||||
**/
|
||||
|
|
|
@ -1077,23 +1077,6 @@ test_hb_draw_immutable (void)
|
|||
hb_draw_funcs_destroy (draw_funcs);
|
||||
}
|
||||
|
||||
static void
|
||||
set_font_funcs (hb_font_t *font, const char *font_funcs_name)
|
||||
{
|
||||
if (strcmp (font_funcs_name, "ft") == 0)
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#else
|
||||
g_assert_not_reached ();
|
||||
#endif
|
||||
else if (strcmp (font_funcs_name, "fontations") == 0)
|
||||
#ifdef HAVE_FONTATIONS
|
||||
hb_fontations_font_set_funcs (font);
|
||||
#else
|
||||
g_assert_not_reached ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_hb_draw_funcs (const char* font_funcs_name)
|
||||
{
|
||||
|
@ -1105,7 +1088,8 @@ test_hb_draw_funcs (const char* font_funcs_name)
|
|||
{
|
||||
hb_face_t *face = hb_test_open_font_file ("fonts/glyphs.ttf");
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
set_font_funcs (font, font_funcs_name);
|
||||
hb_bool_t ret = hb_font_set_funcs_using (font, font_funcs_name);
|
||||
g_assert (ret);
|
||||
hb_face_destroy (face);
|
||||
{
|
||||
draw_data.consumed = 0;
|
||||
|
@ -1124,7 +1108,8 @@ test_hb_draw_funcs (const char* font_funcs_name)
|
|||
{
|
||||
hb_face_t *face = hb_test_open_font_file ("fonts/cff1_flex.otf");
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
set_font_funcs (font, font_funcs_name);
|
||||
hb_bool_t ret = hb_font_set_funcs_using (font, font_funcs_name);
|
||||
g_assert (ret);
|
||||
hb_face_destroy (face);
|
||||
|
||||
draw_data.consumed = 0;
|
||||
|
@ -1165,7 +1150,8 @@ test_hb_draw_compare_ot_funcs (const char* font_funcs_name)
|
|||
hb_font_draw_glyph (font, 1, funcs, &draw_data);
|
||||
draw_data.str[draw_data.consumed] = '\0';
|
||||
|
||||
set_font_funcs (font, font_funcs_name);
|
||||
hb_bool_t ret = hb_font_set_funcs_using (font, font_funcs_name);
|
||||
g_assert (ret);
|
||||
|
||||
hb_font_draw_glyph (font, 1, funcs, &draw_data2);
|
||||
draw_data2.str[draw_data2.consumed] = '\0';
|
||||
|
|
|
@ -93,8 +93,11 @@ thread_func (void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
test_body (void)
|
||||
test_body (const char *backend)
|
||||
{
|
||||
bool ret = hb_font_set_funcs_using (font, backend);
|
||||
g_assert (ret);
|
||||
|
||||
int i;
|
||||
pthread_t *threads = calloc (num_threads, sizeof (pthread_t));
|
||||
hb_buffer_t **buffers = calloc (num_threads, sizeof (hb_buffer_t *));
|
||||
|
@ -145,13 +148,8 @@ main (int argc, char **argv)
|
|||
ref_buffer = hb_buffer_create ();
|
||||
fill_the_buffer (ref_buffer);
|
||||
|
||||
/* Unnecessary, since version 2 it is ot-font by default */
|
||||
hb_ot_font_set_funcs (font);
|
||||
test_body ();
|
||||
|
||||
/* Test hb-ft in multithread */
|
||||
hb_ft_font_set_funcs (font);
|
||||
test_body ();
|
||||
for (const char **font_funcs = hb_font_list_funcs (); *font_funcs; font_funcs++)
|
||||
test_body (*font_funcs);
|
||||
|
||||
hb_buffer_destroy (ref_buffer);
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ test_extents_cff1 (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
|
||||
|
@ -55,7 +54,6 @@ test_extents_cff1 (void)
|
|||
hb_font_t *font_j = hb_font_create (face_j);
|
||||
hb_face_destroy (face_j);
|
||||
g_assert (font_j);
|
||||
hb_ot_font_set_funcs (font_j);
|
||||
|
||||
hb_bool_t result_j = hb_font_get_glyph_extents (font_j, 3, &extents);
|
||||
g_assert (result_j);
|
||||
|
@ -76,7 +74,6 @@ test_extents_cff1_flex (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
|
||||
|
@ -98,7 +95,6 @@ test_extents_cff1_seac (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 3, &extents); /* Agrave */
|
||||
|
@ -128,7 +124,6 @@ test_extents_cff2 (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
|
||||
|
@ -160,7 +155,6 @@ test_extents_cff2_vsindex (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
float coords[2] = { 800.0f, 50.0f };
|
||||
|
@ -192,7 +186,6 @@ test_extents_cff2_vsindex_named_instance (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_font_set_var_named_instance (font, 6); // 6 (BlackMediumContrast): 900, 50
|
||||
hb_glyph_extents_t extents;
|
||||
|
|
|
@ -45,7 +45,6 @@ test_font (hb_font_t *font, hb_codepoint_t cp)
|
|||
char buf[5] = {0};
|
||||
unsigned int len = 0;
|
||||
hb_glyph_extents_t extents = {0, 0, 0, 0};
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
set = hb_set_create ();
|
||||
hb_face_collect_unicodes (face, set);
|
||||
|
|
|
@ -37,7 +37,6 @@ test_extents_tt_var (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 2, &extents);
|
||||
|
@ -69,7 +68,6 @@ test_advance_tt_var_nohvar (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_position_t x, y;
|
||||
hb_font_get_glyph_advance_for_direction(font, 2, HB_DIRECTION_LTR, &x, &y);
|
||||
|
@ -105,7 +103,6 @@ test_advance_tt_var_hvarvvar (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_position_t x, y;
|
||||
hb_font_get_glyph_advance_for_direction(font, 1, HB_DIRECTION_LTR, &x, &y);
|
||||
|
@ -141,7 +138,6 @@ test_advance_tt_var_anchor (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 2, &extents);
|
||||
|
@ -173,7 +169,6 @@ test_extents_tt_var_comp (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
float coords[1] = { 800.0f };
|
||||
|
@ -215,7 +210,6 @@ test_advance_tt_var_comp_v (void)
|
|||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
float coords[1] = { 800.0f };
|
||||
hb_font_set_var_coords_design (font, coords, 1);
|
||||
|
@ -239,7 +233,6 @@ test_advance_tt_var_gvar_infer (void)
|
|||
{
|
||||
hb_face_t *face = hb_test_open_font_file ("fonts/TestGVAREight.ttf");
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
hb_ot_font_set_funcs (font);
|
||||
hb_face_destroy (face);
|
||||
|
||||
int coords[6] = {100};
|
||||
|
|
|
@ -17,7 +17,6 @@ extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
|||
HB_MEMORY_MODE_READONLY, nullptr, nullptr);
|
||||
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);
|
||||
|
||||
unsigned num_coords = 0;
|
||||
|
|
|
@ -75,7 +75,6 @@ runTest(const char *testName,
|
|||
unsigned int upem = hb_face_get_upem (face);
|
||||
|
||||
hb_font_set_scale(font, upem, upem);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
// setup buffer
|
||||
hb_buffer_t *buffer = hb_buffer_create();
|
||||
|
|
|
@ -11,10 +11,6 @@
|
|||
#endif
|
||||
|
||||
#include "hb.h"
|
||||
#include "hb-ot.h"
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "hb-ft.h"
|
||||
#endif
|
||||
|
||||
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
|
||||
|
||||
|
@ -51,8 +47,6 @@ struct test_input_t
|
|||
static test_input_t *tests = default_tests;
|
||||
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
|
||||
|
||||
enum backend_t { HARFBUZZ, FREETYPE };
|
||||
|
||||
// https://en.cppreference.com/w/cpp/thread/condition_variable/wait
|
||||
static std::condition_variable cv;
|
||||
static std::mutex cv_m;
|
||||
|
@ -105,8 +99,7 @@ static void shape (const test_input_t &input,
|
|||
hb_blob_destroy (text_blob);
|
||||
}
|
||||
|
||||
static void test_backend (backend_t backend,
|
||||
const char *backend_name,
|
||||
static void test_backend (const char *backend,
|
||||
bool variable,
|
||||
const test_input_t &test_input)
|
||||
{
|
||||
|
@ -120,7 +113,7 @@ static void test_backend (backend_t backend,
|
|||
strcat (name, p ? p + 1 : test_input.text_path);
|
||||
strcat (name, variable ? "/var" : "");
|
||||
strcat (name, "/");
|
||||
strcat (name, backend_name);
|
||||
strcat (name, backend);
|
||||
|
||||
printf ("Testing %s\n", name);
|
||||
|
||||
|
@ -140,18 +133,8 @@ static void test_backend (backend_t backend,
|
|||
hb_font_set_variations (font, &wght, 1);
|
||||
}
|
||||
|
||||
switch (backend)
|
||||
{
|
||||
case HARFBUZZ:
|
||||
hb_ot_font_set_funcs (font);
|
||||
break;
|
||||
|
||||
case FREETYPE:
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_funcs (font);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
bool ret = hb_font_set_funcs_using (font, backend);
|
||||
assert (ret);
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for (unsigned i = 0; i < num_threads; i++)
|
||||
|
@ -200,10 +183,8 @@ int main(int argc, char** argv)
|
|||
{
|
||||
bool is_var = (bool) variable;
|
||||
|
||||
test_backend (HARFBUZZ, "hb", is_var, test_input);
|
||||
#ifdef HAVE_FREETYPE
|
||||
test_backend (FREETYPE, "ft", is_var, test_input);
|
||||
#endif
|
||||
for (const char **font_funcs = hb_font_list_funcs (); *font_funcs; font_funcs++)
|
||||
test_backend (*font_funcs, is_var, test_input);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,6 @@
|
|||
|
||||
#include "options.hh"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include <hb-ft.h>
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include <hb-coretext.h>
|
||||
#endif
|
||||
|
||||
struct face_options_t
|
||||
{
|
||||
~face_options_t ()
|
||||
|
@ -74,20 +67,6 @@ struct face_options_t
|
|||
|
||||
face_options_t::cache_t face_options_t::cache {};
|
||||
|
||||
static struct supported_face_loaders_t {
|
||||
char name[9];
|
||||
hb_face_t * (*func) (const char *font_file, unsigned face_index);
|
||||
} supported_face_loaders[] =
|
||||
{
|
||||
{"ot", hb_face_create_from_file_or_fail},
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft", hb_ft_face_create_from_file_or_fail},
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
{"coretext", hb_coretext_face_create_from_file_or_fail},
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
face_options_t::post_parse (GError **error)
|
||||
{
|
||||
|
@ -112,46 +91,12 @@ face_options_t::post_parse (GError **error)
|
|||
#endif
|
||||
}
|
||||
|
||||
hb_face_t * (*face_load) (const char *file_name, unsigned face_index) = nullptr;
|
||||
if (!face_loader)
|
||||
{
|
||||
face_load = supported_face_loaders[0].func;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
if (0 == g_ascii_strcasecmp (face_loader, supported_face_loaders[i].name))
|
||||
{
|
||||
face_load = supported_face_loaders[i].func;
|
||||
break;
|
||||
}
|
||||
if (!face_load)
|
||||
{
|
||||
GString *s = g_string_new (nullptr);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
{
|
||||
if (i)
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_face_loaders[i].name);
|
||||
}
|
||||
g_string_append_c (s, '\n');
|
||||
char *p = g_string_free (s, FALSE);
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Unknown face loader `%s'; supported values are: %s; default is %s",
|
||||
face_loader,
|
||||
p,
|
||||
supported_face_loaders[0].name);
|
||||
free (p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cache.font_path ||
|
||||
0 != strcmp (cache.font_path, font_path) ||
|
||||
cache.face_index != face_index)
|
||||
{
|
||||
hb_face_destroy (cache.face);
|
||||
cache.face = face_load (font_path, face_index);
|
||||
cache.face = hb_face_create_from_file_or_fail_using (font_path, face_index, face_loader);
|
||||
cache.face_index = face_index;
|
||||
|
||||
free ((char *) cache.font_path);
|
||||
|
@ -168,21 +113,37 @@ face_options_t::post_parse (GError **error)
|
|||
face = cache.face;
|
||||
}
|
||||
|
||||
static G_GNUC_NORETURN gboolean
|
||||
list_face_loaders (const char *name G_GNUC_UNUSED,
|
||||
const char *arg G_GNUC_UNUSED,
|
||||
gpointer data G_GNUC_UNUSED,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
for (const char **funcs = hb_face_list_loaders (); *funcs; funcs++)
|
||||
g_printf ("%s\n", *funcs);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
face_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
char *face_loaders_text = nullptr;
|
||||
{
|
||||
static_assert ((ARRAY_LENGTH_CONST (supported_face_loaders) > 0),
|
||||
"No supported face-loaders found.");
|
||||
const char **supported_face_loaders = hb_face_list_loaders ();
|
||||
GString *s = g_string_new (nullptr);
|
||||
g_string_printf (s, "Set face loader to use (default: %s)\n Supported face loaders are: %s",
|
||||
supported_face_loaders[0].name,
|
||||
supported_face_loaders[0].name);
|
||||
for (unsigned int i = 1; i < ARRAY_LENGTH (supported_face_loaders); i++)
|
||||
if (unlikely (!supported_face_loaders))
|
||||
g_string_printf (s, "Set face loader to use (default: none)\n No supported face loaders found");
|
||||
else
|
||||
{
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_face_loaders[i].name);
|
||||
g_string_printf (s, "Set face loader to use (default: %s)\n Supported face loaders are: %s",
|
||||
supported_face_loaders[0],
|
||||
supported_face_loaders[0]);
|
||||
for (unsigned i = 1; supported_face_loaders[i]; i++)
|
||||
{
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_face_loaders[i]);
|
||||
}
|
||||
}
|
||||
face_loaders_text = g_string_free (s, FALSE);
|
||||
parser->free_later (face_loaders_text);
|
||||
|
@ -193,6 +154,8 @@ face_options_t::add_options (option_parser_t *parser)
|
|||
{"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"},
|
||||
{"face-index", 'y', 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"},
|
||||
{"face-loader", 0, 0, G_OPTION_ARG_STRING, &this->face_loader, face_loaders_text, "loader"},
|
||||
{"list-face-loaders",0, G_OPTION_FLAG_NO_ARG,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &list_face_loaders, "List available face loaders and quit", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
|
|
|
@ -29,16 +29,9 @@
|
|||
|
||||
#include "face-options.hh"
|
||||
|
||||
#include <hb-ot.h>
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include <hb-ft.h>
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
#include <hb-fontations.h>
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
#include <hb-coretext.h>
|
||||
#endif
|
||||
|
||||
#define FONT_SIZE_UPEM 0x7FFFFFFF
|
||||
#define FONT_SIZE_NONE 0
|
||||
|
@ -84,24 +77,6 @@ struct font_options_t : face_options_t
|
|||
};
|
||||
|
||||
|
||||
static struct supported_font_funcs_t {
|
||||
char name[11];
|
||||
void (*func) (hb_font_t *);
|
||||
} supported_font_funcs[] =
|
||||
{
|
||||
{"ot", hb_ot_font_set_funcs},
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft", hb_ft_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_FONTATIONS
|
||||
{"fontations",hb_fontations_font_set_funcs},
|
||||
#endif
|
||||
#ifdef HAVE_CORETEXT
|
||||
{"coretext", hb_coretext_font_set_funcs},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
font_options_t::post_parse (GError **error)
|
||||
{
|
||||
|
@ -130,39 +105,35 @@ font_options_t::post_parse (GError **error)
|
|||
hb_font_set_variations (font, variations, num_variations);
|
||||
#endif
|
||||
|
||||
void (*set_font_funcs) (hb_font_t *) = nullptr;
|
||||
if (!font_funcs)
|
||||
if (font_funcs)
|
||||
{
|
||||
set_font_funcs = supported_font_funcs[0].func;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
if (0 == g_ascii_strcasecmp (font_funcs, supported_font_funcs[i].name))
|
||||
{
|
||||
set_font_funcs = supported_font_funcs[i].func;
|
||||
break;
|
||||
}
|
||||
if (!set_font_funcs)
|
||||
if (!hb_font_set_funcs_using (font, font_funcs))
|
||||
{
|
||||
const char **supported_font_funcs = hb_font_list_funcs ();
|
||||
if (unlikely (!supported_font_funcs[0]))
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Unknown font function implementation `%s'; no supported values found",
|
||||
font_funcs);
|
||||
return;
|
||||
}
|
||||
GString *s = g_string_new (nullptr);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
for (unsigned i = 0; supported_font_funcs[i]; i++)
|
||||
{
|
||||
if (i)
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_font_funcs[i].name);
|
||||
g_string_append (s, supported_font_funcs[i]);
|
||||
}
|
||||
char *p = g_string_free (s, FALSE);
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Unknown font function implementation `%s'; supported values are: %s; default is %s",
|
||||
font_funcs,
|
||||
p,
|
||||
supported_font_funcs[0].name);
|
||||
supported_font_funcs[0]);
|
||||
free (p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_font_funcs (font);
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_load_flags (font, ft_load_flags);
|
||||
#endif
|
||||
|
@ -176,6 +147,18 @@ font_options_t::post_parse (GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
static G_GNUC_NORETURN gboolean
|
||||
list_font_funcs (const char *name G_GNUC_UNUSED,
|
||||
const char *arg G_GNUC_UNUSED,
|
||||
gpointer data G_GNUC_UNUSED,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
for (const char **funcs = hb_font_list_funcs (); *funcs; funcs++)
|
||||
g_printf ("%s\n", *funcs);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
static gboolean
|
||||
parse_variations (const char *name G_GNUC_UNUSED,
|
||||
|
@ -309,16 +292,20 @@ font_options_t::add_options (option_parser_t *parser)
|
|||
|
||||
char *font_funcs_text = nullptr;
|
||||
{
|
||||
static_assert ((ARRAY_LENGTH_CONST (supported_font_funcs) > 0),
|
||||
"No supported font-funcs found.");
|
||||
const char **supported_font_funcs = hb_font_list_funcs ();
|
||||
GString *s = g_string_new (nullptr);
|
||||
g_string_printf (s, "Set font functions implementation to use (default: %s)\n Supported font function implementations are: %s",
|
||||
supported_font_funcs[0].name,
|
||||
supported_font_funcs[0].name);
|
||||
for (unsigned int i = 1; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
if (unlikely (!supported_font_funcs[0]))
|
||||
g_string_printf (s, "Set font functions implementation to use (default: none)\n No supported font function implementations found");
|
||||
else
|
||||
{
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_font_funcs[i].name);
|
||||
g_string_printf (s, "Set font functions implementation to use (default: %s)\n Supported font function implementations are: %s",
|
||||
supported_font_funcs[0],
|
||||
supported_font_funcs[0]);
|
||||
for (unsigned i = 1; supported_font_funcs[i]; i++)
|
||||
{
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_font_funcs[i]);
|
||||
}
|
||||
}
|
||||
font_funcs_text = g_string_free (s, FALSE);
|
||||
parser->free_later (font_funcs_text);
|
||||
|
@ -349,6 +336,8 @@ font_options_t::add_options (option_parser_t *parser)
|
|||
{"font-slant", 0, font_size_flags,
|
||||
G_OPTION_ARG_DOUBLE, &this->slant, "Set synthetic slant (default: 0)", "slant ratio; eg. 0.2"},
|
||||
{"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, font_funcs_text, "impl"},
|
||||
{"list-font-funcs", 0, G_OPTION_FLAG_NO_ARG,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &list_font_funcs, "List available font functions and quit", nullptr},
|
||||
{"sub-font", 0, G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_NONE, &this->sub_font, "Create a sub-font (default: false)", "boolean"},
|
||||
{"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"},
|
||||
|
|
Loading…
Add table
Reference in a new issue