[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.
This commit is contained in:
Behdad Esfahbod 2011-08-04 22:31:05 -04:00
parent 57692adf12
commit 02aeca985b
17 changed files with 270 additions and 103 deletions

2
TODO
View File

@ -23,8 +23,6 @@ API issues to fix before 1.0:
- Add sanitize API (and a cached version, that saves result on blob user-data) - Add sanitize API (and a cached version, that saves result on blob user-data)
- hb_shape() currently does a bit more than hb_ot_shape(). Shouldn't.
- Add glib GBoxedType stuff and introspection - Add glib GBoxedType stuff and introspection

View File

@ -138,12 +138,21 @@ AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype)
dnl =========================================================================== dnl ===========================================================================
have_ot=true;
if $have_ot; then
AC_DEFINE(HAVE_OT, 1, [Have native OpenType Layout backend])
fi
AM_CONDITIONAL(HAVE_OT, $have_ot)
dnl ===========================================================================
AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true, have_uniscribe=false) AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true, have_uniscribe=false)
if $have_uniscribe; then if $have_uniscribe; then
UNISCRIBE_CFLAGS= UNISCRIBE_CFLAGS=
UNISCRIBE_LIBS="-lusp10 -lgdi32" UNISCRIBE_LIBS="-lusp10 -lgdi32"
AC_SUBST(UNISCRIBE_CFLAGS) AC_SUBST(UNISCRIBE_CFLAGS)
AC_SUBST(UNISCRIBE_LIBS) AC_SUBST(UNISCRIBE_LIBS)
AC_DEFINE(HAVE_UNISCRIBE, 1, [Have Uniscribe backend])
fi fi
AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe) AM_CONDITIONAL(HAVE_UNISCRIBE, $have_uniscribe)

View File

@ -18,6 +18,8 @@ HBSOURCES = \
hb-buffer-private.hh \ hb-buffer-private.hh \
hb-buffer.cc \ hb-buffer.cc \
hb-common.cc \ hb-common.cc \
hb-fallback-shape-private.hh \
hb-fallback-shape.cc \
hb-font-private.hh \ hb-font-private.hh \
hb-font.cc \ hb-font.cc \
hb-mutex-private.hh \ hb-mutex-private.hh \
@ -30,6 +32,7 @@ HBSOURCES = \
hb-shape.cc \ hb-shape.cc \
hb-unicode-private.hh \ hb-unicode-private.hh \
hb-unicode.cc \ hb-unicode.cc \
hb-ot-tag.cc \
$(NULL) $(NULL)
HBHEADERS = \ HBHEADERS = \
hb.h \ hb.h \
@ -42,6 +45,11 @@ HBHEADERS = \
hb-version.h \ hb-version.h \
$(NULL) $(NULL)
MAINTAINERCLEANFILES += \
$(srcdir)/hb-version.h \
$(NULL)
if HAVE_OT
HBSOURCES += \ HBSOURCES += \
hb-ot-layout.cc \ hb-ot-layout.cc \
hb-ot-layout-common-private.hh \ hb-ot-layout-common-private.hh \
@ -62,7 +70,6 @@ HBSOURCES += \
hb-ot-shape-complex-private.hh \ hb-ot-shape-complex-private.hh \
hb-ot-shape-normalize.cc \ hb-ot-shape-normalize.cc \
hb-ot-shape-private.hh \ hb-ot-shape-private.hh \
hb-ot-tag.cc \
$(NULL) $(NULL)
HBHEADERS += \ HBHEADERS += \
hb-ot.h \ hb-ot.h \
@ -70,10 +77,7 @@ HBHEADERS += \
hb-ot-shape.h \ hb-ot-shape.h \
hb-ot-tag.h \ hb-ot-tag.h \
$(NULL) $(NULL)
endif
MAINTAINERCLEANFILES += \
$(srcdir)/hb-version.h \
$(NULL)
if HAVE_GLIB if HAVE_GLIB
HBCFLAGS += $(GLIB_CFLAGS) HBCFLAGS += $(GLIB_CFLAGS)

View File

@ -94,6 +94,7 @@ struct _hb_buffer_t {
HB_INTERNAL void reverse_range (unsigned int start, unsigned int end); HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
HB_INTERNAL void reverse (void); HB_INTERNAL void reverse (void);
HB_INTERNAL void reverse_clusters (void); HB_INTERNAL void reverse_clusters (void);
HB_INTERNAL void guess_properties (void);
HB_INTERNAL void swap_buffers (void); HB_INTERNAL void swap_buffers (void);
HB_INTERNAL void clear_output (void); HB_INTERNAL void clear_output (void);

View File

@ -402,6 +402,35 @@ hb_buffer_t::reverse_clusters (void)
reverse_range (start, i); 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 static inline void
dump_var_allocation (const hb_buffer_t *buffer) dump_var_allocation (const hb_buffer_t *buffer)
{ {
@ -675,6 +704,12 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer)
buffer->reverse_clusters (); buffer->reverse_clusters ();
} }
void
hb_buffer_guess_properties (hb_buffer_t *buffer)
{
buffer->guess_properties ();
}
#define ADD_UTF(T) \ #define ADD_UTF(T) \
HB_STMT_START { \ HB_STMT_START { \
const T *next = (const T *) text + item_offset; \ const T *next = (const T *) text + item_offset; \

View File

@ -132,6 +132,9 @@ hb_buffer_reverse (hb_buffer_t *buffer);
void void
hb_buffer_reverse_clusters (hb_buffer_t *buffer); hb_buffer_reverse_clusters (hb_buffer_t *buffer);
void
hb_buffer_guess_properties (hb_buffer_t *buffer);
/* Filling the buffer in */ /* Filling the buffer in */

View File

@ -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 */

43
src/hb-fallback-shape.cc Normal file
View File

@ -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;
}

View File

@ -428,16 +428,21 @@ hb_ot_shape_execute (hb_ot_shape_plan_t *plan,
hb_ot_shape_execute_internal (&c); hb_ot_shape_execute_internal (&c);
} }
void hb_bool_t
hb_ot_shape (hb_font_t *font, hb_ot_shape (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features) unsigned int num_features,
const char *shaper_options)
{ {
hb_ot_shape_plan_t plan; 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_plan_internal (&plan, font->face, &buffer->props, features, num_features);
hb_ot_shape_execute (&plan, font, buffer, features, num_features); hb_ot_shape_execute (&plan, font, buffer, features, num_features);
return TRUE;
} }

View File

@ -34,11 +34,12 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
void hb_bool_t
hb_ot_shape (hb_font_t *font, hb_ot_shape (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features); unsigned int num_features,
const char *shaper_options);
HB_END_DECLS HB_END_DECLS

View File

@ -30,62 +30,89 @@
#include "hb-buffer-private.hh" #include "hb-buffer-private.hh"
#include "hb-ot-shape.h" #ifdef HAVE_UNISCRIBE
# include "hb-uniscribe.h"
#ifdef HAVE_GRAPHITE
#include "hb-graphite.h"
#endif #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,
static void
hb_shape_internal (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features) unsigned int num_features,
{ const char *shaper_options);
hb_ot_shape (font, buffer, features, num_features);
}
void #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 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_shape (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features) unsigned int num_features,
const char *shaper_options,
const char **shaper_list)
{ {
hb_segment_properties_t orig_props; if (likely (!shaper_list))
shaper_list = env_shaper_list.shaper_list;
orig_props = buffer->props; if (likely (!shaper_list)) {
for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
/* If script is set to INVALID, guess from buffer contents */ if (likely (shapers[i].func (font, buffer,
if (buffer->props.script == HB_SCRIPT_INVALID) { features, num_features,
hb_unicode_funcs_t *unicode = buffer->unicode; shaper_options)))
unsigned int count = buffer->len; return TRUE;
for (unsigned int i = 0; i < count; i++) { } else {
hb_script_t script = hb_unicode_script (unicode, buffer->info[i].codepoint); while (*shaper_list) {
if (likely (script != HB_SCRIPT_COMMON && for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
script != HB_SCRIPT_INHERITED && if (0 == strcmp (*shaper_list, shapers[i].name) &&
script != HB_SCRIPT_UNKNOWN)) { likely (shapers[i].func (font, buffer,
buffer->props.script = script; features, num_features,
break; shaper_options)))
return TRUE;
shaper_list++;
} }
} }
return FALSE;
} }
/* 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;
}

View File

@ -41,11 +41,14 @@ typedef struct _hb_feature_t {
unsigned int end; unsigned int end;
} hb_feature_t; } hb_feature_t;
void
hb_bool_t
hb_shape (hb_font_t *font, hb_shape (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features); unsigned int num_features,
const char *shaper_options,
const char **shaper_list);
HB_END_DECLS HB_END_DECLS

View File

@ -56,13 +56,6 @@ DWORD GetFontData(
); );
*/ */
static void
fallback_shape (hb_font_t *font,
hb_buffer_t *buffer)
{
DEBUG_MSG (UNISCRIBE, NULL, "Fallback shaper invoked");
}
static void static void
populate_log_font (LOGFONTW *lf, populate_log_font (LOGFONTW *lf,
HDC hdc, HDC hdc,
@ -78,18 +71,19 @@ populate_log_font (LOGFONTW *lf,
lf->lfFaceName[i] = family_name[i]; lf->lfFaceName[i] = family_name[i];
} }
void hb_bool_t
hb_uniscribe_shape (hb_font_t *font, hb_uniscribe_shape (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features) unsigned int num_features,
const char *shaper_options)
{ {
buffer->guess_properties ();
HRESULT hr; HRESULT hr;
if (unlikely (!buffer->len)) { if (unlikely (!buffer->len))
fallback: return TRUE;
fallback_shape (font, buffer);
}
retry: retry:
@ -138,10 +132,10 @@ retry:
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size); ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
#define FALLBACK(...) \ #define FAIL(...) \
HB_STMT_START { \ HB_STMT_START { \
DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \ DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
goto fallback; \ return FALSE; \
} HB_STMT_END; } HB_STMT_END;
@ -164,7 +158,7 @@ retry:
script_tags, script_tags,
&item_count); &item_count);
if (unlikely (FAILED (hr))) if (unlikely (FAILED (hr)))
FALLBACK ("ScriptItemizeOpenType() failed: %d", hr); FAIL ("ScriptItemizeOpenType() failed: %d", hr);
#undef MAX_ITEMS #undef MAX_ITEMS
@ -178,17 +172,13 @@ retry:
hb_blob_t *blob = hb_face_get_blob (font->face); hb_blob_t *blob = hb_face_get_blob (font->face);
unsigned int blob_length; unsigned int blob_length;
const char *blob_data = hb_blob_get_data (blob, &blob_length); const char *blob_data = hb_blob_get_data (blob, &blob_length);
if (unlikely (!blob_length)) { if (unlikely (!blob_length))
hb_blob_destroy (blob); FAIL ("Empty font blob");
FALLBACK ("Empty font blob");
}
DWORD num_fonts_installed; DWORD num_fonts_installed;
HANDLE fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed); HANDLE fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
if (unlikely (!fh)) { if (unlikely (!fh))
hb_blob_destroy (blob); FAIL ("AddFontMemResourceEx() failed");
FALLBACK ("AddFontMemResourceEx() failed");
}
/* FREE stuff, specially when taking fallback... */ /* FREE stuff, specially when taking fallback... */
@ -230,16 +220,16 @@ retry:
(int *) &glyphs_len); (int *) &glyphs_len);
if (unlikely (items[i].a.fNoGlyphIndex)) if (unlikely (items[i].a.fNoGlyphIndex))
FALLBACK ("ScriptShapeOpenType() set fNoGlyphIndex"); FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
if (unlikely (hr == E_OUTOFMEMORY)) if (unlikely (hr == E_OUTOFMEMORY))
{ {
buffer->ensure (buffer->allocated * 2); buffer->ensure (buffer->allocated * 2);
if (buffer->in_error) if (buffer->in_error)
FALLBACK ("Buffer resize failed"); FAIL ("Buffer resize failed");
goto retry; goto retry;
} }
if (unlikely (FAILED (hr))) if (unlikely (FAILED (hr)))
FALLBACK ("ScriptShapeOpenType() failed: %d", hr); FAIL ("ScriptShapeOpenType() failed: %d", hr);
hr = ScriptPlaceOpenType (hdc, hr = ScriptPlaceOpenType (hdc,
&script_cache, &script_cache,
@ -261,7 +251,7 @@ retry:
offsets + glyphs_offset, offsets + glyphs_offset,
NULL); NULL);
if (unlikely (FAILED (hr))) if (unlikely (FAILED (hr)))
FALLBACK ("ScriptPlaceOpenType() failed: %d", hr); FAIL ("ScriptPlaceOpenType() failed: %d", hr);
glyphs_offset += glyphs_len; glyphs_offset += glyphs_len;
} }
@ -285,9 +275,9 @@ retry:
buffer->ensure (glyphs_len); buffer->ensure (glyphs_len);
if (buffer->in_error) if (buffer->in_error)
FALLBACK ("Buffer in error"); FAIL ("Buffer in error");
#undef FALLBACK #undef FAIL
/* Set glyph infos */ /* Set glyph infos */
for (unsigned int i = 0; i < glyphs_len; i++) for (unsigned int i = 0; i < glyphs_len; i++)
@ -317,7 +307,7 @@ retry:
} }
/* Wow, done! */ /* Wow, done! */
return; return TRUE;
} }

View File

@ -34,11 +34,12 @@
HB_BEGIN_DECLS HB_BEGIN_DECLS
void hb_bool_t
hb_uniscribe_shape (hb_font_t *font, hb_uniscribe_shape (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
const hb_feature_t *features, const hb_feature_t *features,
unsigned int num_features); unsigned int num_features,
const char *shaper_options);
HB_END_DECLS HB_END_DECLS

View File

@ -370,7 +370,7 @@ _hb_cr_text_glyphs (cairo_t *cr,
len = strlen (utf8); len = strlen (utf8);
hb_buffer_add_utf8 (hb_buffer, utf8, len, 0, len); 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); num_glyphs = hb_buffer_get_length (hb_buffer);
hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL); hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL);

View File

@ -30,7 +30,6 @@
#endif #endif
#include "hb.h" #include "hb.h"
#include "hb-uniscribe.h"
#ifdef HAVE_GLIB #ifdef HAVE_GLIB
#include <glib.h> #include <glib.h>
@ -97,7 +96,7 @@ main (int argc, char **argv)
hb_buffer_add_utf8 (buffer, "test", 4, 0, 4); 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); unsigned int count = hb_buffer_get_length (buffer);
hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL); hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL);

View File

@ -110,7 +110,7 @@ test_shape (void)
hb_buffer_set_direction (buffer, HB_DIRECTION_LTR); hb_buffer_set_direction (buffer, HB_DIRECTION_LTR);
hb_buffer_add_utf8 (buffer, TesT, 4, 0, 4); hb_buffer_add_utf8 (buffer, TesT, 4, 0, 4);
hb_shape (font, buffer, NULL, 0); hb_shape (font, buffer, NULL, 0, NULL, NULL);
len = hb_buffer_get_length (buffer); len = hb_buffer_get_length (buffer);
glyphs = hb_buffer_get_glyph_infos (buffer, NULL); glyphs = hb_buffer_get_glyph_infos (buffer, NULL);