#include "hb-buffer-private.hh"
#include "hb-font-private.hh"
-
-static void
-parse_space (const char **pp, const char *end)
-{
- char c;
-#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v')
- while (*pp < end && (c = **pp, ISSPACE (c)))
- (*pp)++;
-#undef ISSPACE
-}
-
-static hb_bool_t
-parse_char (const char **pp, const char *end, char c)
-{
- parse_space (pp, end);
-
- if (*pp == end || **pp != c)
- return false;
-
- (*pp)++;
- return true;
-}
-
-static hb_bool_t
-parse_uint (const char **pp, const char *end, unsigned int *pv)
-{
- char buf[32];
- strncpy (buf, *pp, end - *pp);
- buf[ARRAY_LENGTH (buf) - 1] = '\0';
-
- char *p = buf;
- char *pend = p;
- unsigned int v;
-
- v = strtol (p, &pend, 0);
-
- if (p == pend)
- return false;
-
- *pv = v;
- *pp += pend - p;
- return true;
-}
-
-static hb_bool_t
-parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
-{
- if (parse_char (pp, end, '-'))
- feature->value = 0;
- else {
- parse_char (pp, end, '+');
- feature->value = 1;
- }
-
- return true;
-}
-
-static hb_bool_t
-parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
-{
- const char *p = *pp;
- char c;
-
- parse_space (pp, end);
-
-#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
- while (*pp < end && (c = **pp, ISALNUM(c)))
- (*pp)++;
-#undef ISALNUM
-
- if (p == *pp)
- return false;
-
- feature->tag = hb_tag_from_string (p, *pp - p);
- return true;
-}
-
-static hb_bool_t
-parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
-{
- parse_space (pp, end);
-
- hb_bool_t has_start;
-
- feature->start = 0;
- feature->end = (unsigned int) -1;
-
- if (!parse_char (pp, end, '['))
- return true;
-
- has_start = parse_uint (pp, end, &feature->start);
-
- if (parse_char (pp, end, ':')) {
- parse_uint (pp, end, &feature->end);
- } else {
- if (has_start)
- feature->end = feature->start + 1;
- }
-
- return parse_char (pp, end, ']');
-}
-
-static hb_bool_t
-parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
-{
- return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value);
-}
-
-
-static hb_bool_t
-parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
-{
- return parse_feature_value_prefix (pp, end, feature) &&
- parse_feature_tag (pp, end, feature) &&
- parse_feature_indices (pp, end, feature) &&
- parse_feature_value_postfix (pp, end, feature) &&
- *pp == end;
-}
-
-hb_bool_t
-hb_feature_from_string (const char *str, int len,
- hb_feature_t *feature)
-{
- if (len < 0)
- len = strlen (str);
-
- return parse_one_feature (&str, str + len, feature);
-}
-
-void
-hb_feature_to_string (hb_feature_t *feature,
- char *buf, unsigned int size)
-{
- if (unlikely (!size)) return;
-
- char s[128];
- unsigned int len = 0;
- if (feature->value == 0)
- s[len++] = '-';
- hb_tag_to_string (feature->tag, s + len);
- len += 4;
- while (len && s[len - 1] == ' ')
- len--;
- if (feature->start != 0 || feature->end != (unsigned int) -1)
- {
- s[len++] = '[';
- if (feature->start)
- len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start);
- if (feature->end != feature->start + 1) {
- s[len++] = ':';
- if (feature->end != (unsigned int) -1)
- len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end);
- }
- s[len++] = ']';
- }
- if (feature->value > 1)
- {
- s[len++] = '=';
- len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value);
- }
- assert (len < ARRAY_LENGTH (s));
- len = MIN (len, size - 1);
- memcpy (buf, s, len);
- s[len] = '\0';
-}
-
+/**
+ * SECTION:hb-shape
+ * @title: Shaping
+ * @short_description: Conversion of text strings into positioned glyphs
+ * @include: hb.h
+ *
+ * Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
+ * which are sequences of Unicode characters that use the same font and have
+ * the same text direction, script and language. After shaping the buffer
+ * contains the output glyphs and their positions.
+ **/
static const char **static_shaper_list;
+#ifdef HB_USE_ATEXIT
static
void free_static_shaper_list (void)
{
- free (static_shaper_list);
+retry:
+ const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
+ if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr))
+ goto retry;
+
+ free (shaper_list);
}
+#endif
+/**
+ * hb_shape_list_shapers:
+ *
+ * Retrieves the list of shapers supported by HarfBuzz.
+ *
+ * Return value: (transfer none) (array zero-terminated=1): an array of
+ * constant strings
+ *
+ * Since: 0.9.2
+ **/
const char **
hb_shape_list_shapers (void)
{
/* Not found; allocate one. */
shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
if (unlikely (!shaper_list)) {
- static const char *nil_shaper_list[] = {NULL};
+ static const char *nil_shaper_list[] = {nullptr};
return nil_shaper_list;
}
unsigned int i;
for (i = 0; i < HB_SHAPERS_COUNT; i++)
shaper_list[i] = shapers[i].name;
- shaper_list[i] = NULL;
+ shaper_list[i] = nullptr;
- if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
+ if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
free (shaper_list);
goto retry;
}
-#ifdef HAVE_ATEXIT
+#ifdef HB_USE_ATEXIT
atexit (free_static_shaper_list); /* First person registers atexit() callback. */
#endif
}
}
+/**
+ * hb_shape_full:
+ * @font: an #hb_font_t to use for shaping
+ * @buffer: an #hb_buffer_t to shape
+ * @features: (array length=num_features) (allow-none): an array of user
+ * specified #hb_feature_t or %NULL
+ * @num_features: the length of @features array
+ * @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated
+ * array of shapers to use or %NULL
+ *
+ * See hb_shape() for details. If @shaper_list is not %NULL, the specified
+ * shapers will be used in the given order, otherwise the default shapers list
+ * will be used.
+ *
+ * Return value: false if all shapers failed, true otherwise
+ *
+ * Since: 0.9.2
+ **/
hb_bool_t
hb_shape_full (hb_font_t *font,
hb_buffer_t *buffer,
unsigned int num_features,
const char * const *shaper_list)
{
- if (unlikely (!buffer->len))
- return true;
-
- assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
-
- buffer->guess_segment_properties ();
-
- hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
+ hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
+ features, num_features,
+ font->coords, font->num_coords,
+ shaper_list);
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
hb_shape_plan_destroy (shape_plan);
return res;
}
+/**
+ * hb_shape:
+ * @font: an #hb_font_t to use for shaping
+ * @buffer: an #hb_buffer_t to shape
+ * @features: (array length=num_features) (allow-none): an array of user
+ * specified #hb_feature_t or %NULL
+ * @num_features: the length of @features array
+ *
+ * Shapes @buffer using @font turning its Unicode characters content to
+ * positioned glyphs. If @features is not %NULL, it will be used to control the
+ * features applied during shaping.
+ *
+ * Since: 0.9.2
+ **/
void
hb_shape (hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
- hb_shape_full (font, buffer, features, num_features, NULL);
+ hb_shape_full (font, buffer, features, num_features, nullptr);
}