[API] Changes to main shape API hb_shape() now accepts a shaper_options and a shaper_list argument. Both can be set to NULL to emulate previous API. And in most situations they are expected to be set to NULL. hb_shape() also returns a boolean for now. If shaper_list is NULL, the return value can be ignored. shaper_options is ignored for now, but otherwise it should be a NULL-terminated list of strings. shaper_list is a NULL-terminated list of strings. Currently recognized strings are "ot" for native OpenType Layout implementation, "uniscribe" for the Uniscribe backend, and "fallback" for the non-complex backend (that will be implemented shortly). The fallback backend never fails. The env var HB_SHAPER_LIST is also parsed and honored. It's a colon-separated list of shaper names. The fallback shaper is invoked if none of the env-listed shapers succeed. New API hb_buffer_guess_properties() added.
diff --git a/src/hb-shape.cc b/src/hb-shape.cc index 1b802d6..9ebbd81 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc
@@ -30,62 +30,89 @@ #include "hb-buffer-private.hh" -#include "hb-ot-shape.h" - -#ifdef HAVE_GRAPHITE -#include "hb-graphite.h" +#ifdef HAVE_UNISCRIBE +# include "hb-uniscribe.h" #endif +#ifdef HAVE_OT +# include "hb-ot-shape.h" +#endif +#include "hb-fallback-shape-private.hh" +typedef hb_bool_t (*hb_shape_func_t) (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + const char *shaper_options); +#define HB_SHAPER_IMPLEMENT(name) {#name, hb_##name##_shape} +static const struct hb_shaper_pair_t { + const char name[16]; + hb_shape_func_t func; +} shapers[] = { + /* v--- Add new shapers in the right place here */ +#ifdef HAVE_UNISCRIBE + HB_SHAPER_IMPLEMENT (uniscribe), +#endif +#ifdef HAVE_OT + HB_SHAPER_IMPLEMENT (ot), +#endif + HB_SHAPER_IMPLEMENT (fallback) /* should be last */ +}; +#undef HB_SHAPER_IMPLEMENT -static void -hb_shape_internal (hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features) +static class static_shaper_list_t { + public: + static_shaper_list_t (void) { + char *env = getenv ("HB_SHAPER_LIST"); + shaper_list = NULL; + if (!env || !*env) + return; + unsigned int count = 3; /* initial, fallback, null */ + for (const char *p = env; (p == strchr (p, ':')) && p++; ) + count++; + if (count <= ARRAY_LENGTH (static_shaper_list)) + shaper_list = static_shaper_list; + else + shaper_list = (const char **) malloc (count * sizeof (shaper_list[0])); + + count = 0; + shaper_list[count++] = env; + for (char *p = env; (p == strchr (p, ':')) && (*p = '\0', TRUE) && p++; ) + shaper_list[count++] = p; + shaper_list[count++] = "fallback"; + shaper_list[count] = NULL; + } + const char **shaper_list; + const char *static_shaper_list[10]; +} env_shaper_list; + +hb_bool_t +hb_shape (hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + const char *shaper_options, + const char **shaper_list) { - hb_ot_shape (font, buffer, features, num_features); -} + if (likely (!shaper_list)) + shaper_list = env_shaper_list.shaper_list; -void -hb_shape (hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features) -{ - hb_segment_properties_t orig_props; - - orig_props = buffer->props; - - /* If script is set to INVALID, guess from buffer contents */ - if (buffer->props.script == HB_SCRIPT_INVALID) { - hb_unicode_funcs_t *unicode = buffer->unicode; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) { - hb_script_t script = hb_unicode_script (unicode, buffer->info[i].codepoint); - if (likely (script != HB_SCRIPT_COMMON && - script != HB_SCRIPT_INHERITED && - script != HB_SCRIPT_UNKNOWN)) { - buffer->props.script = script; - break; - } + if (likely (!shaper_list)) { + for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++) + if (likely (shapers[i].func (font, buffer, + features, num_features, + shaper_options))) + return TRUE; + } else { + while (*shaper_list) { + for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++) + if (0 == strcmp (*shaper_list, shapers[i].name) && + likely (shapers[i].func (font, buffer, + features, num_features, + shaper_options))) + return TRUE; + shaper_list++; } } - - /* If direction is set to INVALID, guess from script */ - if (buffer->props.direction == HB_DIRECTION_INVALID) { - buffer->props.direction = hb_script_get_horizontal_direction (buffer->props.script); - } - - /* If language is not set, use default language from locale */ - if (buffer->props.language == HB_LANGUAGE_INVALID) { - /* TODO get_default_for_script? using $LANGUAGE */ - buffer->props.language = hb_language_get_default (); - } - - hb_shape_internal (font, buffer, features, num_features); - - buffer->props = orig_props; + return FALSE; } - -