[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/Makefile.am b/src/Makefile.am
index c4f35e9..ff5a6d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,8 @@
hb-buffer-private.hh \
hb-buffer.cc \
hb-common.cc \
+ hb-fallback-shape-private.hh \
+ hb-fallback-shape.cc \
hb-font-private.hh \
hb-font.cc \
hb-mutex-private.hh \
@@ -30,6 +32,7 @@
hb-shape.cc \
hb-unicode-private.hh \
hb-unicode.cc \
+ hb-ot-tag.cc \
$(NULL)
HBHEADERS = \
hb.h \
@@ -42,6 +45,11 @@
hb-version.h \
$(NULL)
+MAINTAINERCLEANFILES += \
+ $(srcdir)/hb-version.h \
+ $(NULL)
+
+if HAVE_OT
HBSOURCES += \
hb-ot-layout.cc \
hb-ot-layout-common-private.hh \
@@ -62,7 +70,6 @@
hb-ot-shape-complex-private.hh \
hb-ot-shape-normalize.cc \
hb-ot-shape-private.hh \
- hb-ot-tag.cc \
$(NULL)
HBHEADERS += \
hb-ot.h \
@@ -70,10 +77,7 @@
hb-ot-shape.h \
hb-ot-tag.h \
$(NULL)
-
-MAINTAINERCLEANFILES += \
- $(srcdir)/hb-version.h \
- $(NULL)
+endif
if HAVE_GLIB
HBCFLAGS += $(GLIB_CFLAGS)
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 1a4a423..f3f3ab0 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -94,6 +94,7 @@
HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
HB_INTERNAL void reverse (void);
HB_INTERNAL void reverse_clusters (void);
+ HB_INTERNAL void guess_properties (void);
HB_INTERNAL void swap_buffers (void);
HB_INTERNAL void clear_output (void);
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 749330b..e19e7dd 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -402,6 +402,35 @@
reverse_range (start, i);
}
+void
+hb_buffer_t::guess_properties (void)
+{
+ /* If script is set to INVALID, guess from buffer contents */
+ if (props.script == HB_SCRIPT_INVALID) {
+ for (unsigned int i = 0; i < len; i++) {
+ hb_script_t script = hb_unicode_script (unicode, info[i].codepoint);
+ if (likely (script != HB_SCRIPT_COMMON &&
+ script != HB_SCRIPT_INHERITED &&
+ script != HB_SCRIPT_UNKNOWN)) {
+ props.script = script;
+ break;
+ }
+ }
+ }
+
+ /* If direction is set to INVALID, guess from script */
+ if (props.direction == HB_DIRECTION_INVALID) {
+ props.direction = hb_script_get_horizontal_direction (props.script);
+ }
+
+ /* If language is not set, use default language from locale */
+ if (props.language == HB_LANGUAGE_INVALID) {
+ /* TODO get_default_for_script? using $LANGUAGE */
+ props.language = hb_language_get_default ();
+ }
+}
+
+
static inline void
dump_var_allocation (const hb_buffer_t *buffer)
{
@@ -675,6 +704,12 @@
buffer->reverse_clusters ();
}
+void
+hb_buffer_guess_properties (hb_buffer_t *buffer)
+{
+ buffer->guess_properties ();
+}
+
#define ADD_UTF(T) \
HB_STMT_START { \
const T *next = (const T *) text + item_offset; \
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 020a120..1c4a9a7 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -132,6 +132,9 @@
void
hb_buffer_reverse_clusters (hb_buffer_t *buffer);
+void
+hb_buffer_guess_properties (hb_buffer_t *buffer);
+
/* Filling the buffer in */
diff --git a/src/hb-fallback-shape-private.hh b/src/hb-fallback-shape-private.hh
new file mode 100644
index 0000000..40e9541
--- /dev/null
+++ b/src/hb-fallback-shape-private.hh
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2011 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_FALLBACK_SHAPE_PRIVATE_HH
+#define HB_FALLBACK_SHAPE_PRIVATE_HH
+
+#include "hb-private.hh"
+
+#include "hb-shape.h"
+
+
+HB_BEGIN_DECLS
+
+
+HB_INTERNAL hb_bool_t
+hb_fallback_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char *shaper_options);
+
+
+HB_END_DECLS
+
+#endif /* HB_FALLBACK_SHAPE_PRIVATE_HH */
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
new file mode 100644
index 0000000..6c3200d
--- /dev/null
+++ b/src/hb-fallback-shape.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2011 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-fallback-shape-private.hh"
+
+#include "hb-buffer-private.hh"
+
+hb_bool_t
+hb_fallback_shape (hb_font_t *font,
+ hb_buffer_t *buffer,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char *shaper_options)
+{
+ buffer->guess_properties ();
+
+ return TRUE;
+}
+
+
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 5f8b372..fc2fa41 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -428,16 +428,21 @@
hb_ot_shape_execute_internal (&c);
}
-void
+hb_bool_t
hb_ot_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
- unsigned int num_features)
+ unsigned int num_features,
+ const char *shaper_options)
{
hb_ot_shape_plan_t plan;
+ buffer->guess_properties ();
+
hb_ot_shape_plan_internal (&plan, font->face, &buffer->props, features, num_features);
hb_ot_shape_execute (&plan, font, buffer, features, num_features);
+
+ return TRUE;
}
diff --git a/src/hb-ot-shape.h b/src/hb-ot-shape.h
index f9560e5..0fa3f36 100644
--- a/src/hb-ot-shape.h
+++ b/src/hb-ot-shape.h
@@ -34,11 +34,12 @@
HB_BEGIN_DECLS
-void
+hb_bool_t
hb_ot_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
- unsigned int num_features);
+ unsigned int num_features,
+ const char *shaper_options);
HB_END_DECLS
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;
}
-
-
diff --git a/src/hb-shape.h b/src/hb-shape.h
index 39383af..b2193f7 100644
--- a/src/hb-shape.h
+++ b/src/hb-shape.h
@@ -41,11 +41,14 @@
unsigned int end;
} hb_feature_t;
-void
-hb_shape (hb_font_t *font,
- hb_buffer_t *buffer,
- const hb_feature_t *features,
- unsigned int num_features);
+
+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_END_DECLS
diff --git a/src/hb-uniscribe-shape.cc b/src/hb-uniscribe-shape.cc
index 3d5b1d5..6c93f3b 100644
--- a/src/hb-uniscribe-shape.cc
+++ b/src/hb-uniscribe-shape.cc
@@ -57,13 +57,6 @@
*/
static void
-fallback_shape (hb_font_t *font,
- hb_buffer_t *buffer)
-{
- DEBUG_MSG (UNISCRIBE, NULL, "Fallback shaper invoked");
-}
-
-static void
populate_log_font (LOGFONTW *lf,
HDC hdc,
hb_font_t *font,
@@ -78,18 +71,19 @@
lf->lfFaceName[i] = family_name[i];
}
-void
+hb_bool_t
hb_uniscribe_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
- unsigned int num_features)
+ unsigned int num_features,
+ const char *shaper_options)
{
+ buffer->guess_properties ();
+
HRESULT hr;
- if (unlikely (!buffer->len)) {
- fallback:
- fallback_shape (font, buffer);
- }
+ if (unlikely (!buffer->len))
+ return TRUE;
retry:
@@ -138,10 +132,10 @@
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
-#define FALLBACK(...) \
+#define FAIL(...) \
HB_STMT_START { \
DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
- goto fallback; \
+ return FALSE; \
} HB_STMT_END;
@@ -164,7 +158,7 @@
script_tags,
&item_count);
if (unlikely (FAILED (hr)))
- FALLBACK ("ScriptItemizeOpenType() failed: %d", hr);
+ FAIL ("ScriptItemizeOpenType() failed: %d", hr);
#undef MAX_ITEMS
@@ -178,17 +172,13 @@
hb_blob_t *blob = hb_face_get_blob (font->face);
unsigned int blob_length;
const char *blob_data = hb_blob_get_data (blob, &blob_length);
- if (unlikely (!blob_length)) {
- hb_blob_destroy (blob);
- FALLBACK ("Empty font blob");
- }
+ if (unlikely (!blob_length))
+ FAIL ("Empty font blob");
DWORD num_fonts_installed;
HANDLE fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
- if (unlikely (!fh)) {
- hb_blob_destroy (blob);
- FALLBACK ("AddFontMemResourceEx() failed");
- }
+ if (unlikely (!fh))
+ FAIL ("AddFontMemResourceEx() failed");
/* FREE stuff, specially when taking fallback... */
@@ -230,16 +220,16 @@
(int *) &glyphs_len);
if (unlikely (items[i].a.fNoGlyphIndex))
- FALLBACK ("ScriptShapeOpenType() set fNoGlyphIndex");
+ FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
if (unlikely (hr == E_OUTOFMEMORY))
{
buffer->ensure (buffer->allocated * 2);
if (buffer->in_error)
- FALLBACK ("Buffer resize failed");
+ FAIL ("Buffer resize failed");
goto retry;
}
if (unlikely (FAILED (hr)))
- FALLBACK ("ScriptShapeOpenType() failed: %d", hr);
+ FAIL ("ScriptShapeOpenType() failed: %d", hr);
hr = ScriptPlaceOpenType (hdc,
&script_cache,
@@ -261,7 +251,7 @@
offsets + glyphs_offset,
NULL);
if (unlikely (FAILED (hr)))
- FALLBACK ("ScriptPlaceOpenType() failed: %d", hr);
+ FAIL ("ScriptPlaceOpenType() failed: %d", hr);
glyphs_offset += glyphs_len;
}
@@ -285,9 +275,9 @@
buffer->ensure (glyphs_len);
if (buffer->in_error)
- FALLBACK ("Buffer in error");
+ FAIL ("Buffer in error");
-#undef FALLBACK
+#undef FAIL
/* Set glyph infos */
for (unsigned int i = 0; i < glyphs_len; i++)
@@ -317,7 +307,7 @@
}
/* Wow, done! */
- return;
+ return TRUE;
}
diff --git a/src/hb-uniscribe.h b/src/hb-uniscribe.h
index d498f97..aa893bd 100644
--- a/src/hb-uniscribe.h
+++ b/src/hb-uniscribe.h
@@ -34,11 +34,12 @@
HB_BEGIN_DECLS
-void
+hb_bool_t
hb_uniscribe_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
- unsigned int num_features);
+ unsigned int num_features,
+ const char *shaper_options);
HB_END_DECLS
diff --git a/src/hb-view.cc b/src/hb-view.cc
index dc3fc47..67070ef 100644
--- a/src/hb-view.cc
+++ b/src/hb-view.cc
@@ -370,7 +370,7 @@
len = strlen (utf8);
hb_buffer_add_utf8 (hb_buffer, utf8, len, 0, len);
- hb_shape (hb_font, hb_buffer, features, num_features);
+ hb_shape (hb_font, hb_buffer, features, num_features, NULL, NULL);
num_glyphs = hb_buffer_get_length (hb_buffer);
hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL);
diff --git a/src/test.cc b/src/test.cc
index 54141bc..8679b33 100644
--- a/src/test.cc
+++ b/src/test.cc
@@ -30,7 +30,6 @@
#endif
#include "hb.h"
-#include "hb-uniscribe.h"
#ifdef HAVE_GLIB
#include <glib.h>
@@ -97,7 +96,7 @@
hb_buffer_add_utf8 (buffer, "test", 4, 0, 4);
- hb_uniscribe_shape (font, buffer, NULL, 0);
+ hb_shape (font, buffer, NULL, 0, NULL, NULL);
unsigned int count = hb_buffer_get_length (buffer);
hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL);