Mercurial > mplayer.hg
changeset 34300:77976b68285b
Commit added forgotten in previous commit.
author | reimar |
---|---|
date | Sat, 03 Dec 2011 23:08:03 +0000 |
parents | 1237a0a79119 |
children | d3488ac22468 |
files | libass/ass_shaper.c libass/ass_shaper.h |
diffstat | 2 files changed, 776 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libass/ass_shaper.c Sat Dec 03 23:08:03 2011 +0000 @@ -0,0 +1,733 @@ +/* + * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx> + * + * This file is part of libass. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include <fribidi/fribidi.h> + +#include "ass_shaper.h" +#include "ass_render.h" +#include "ass_font.h" +#include "ass_parse.h" +#include "ass_cache.h" + +#define MAX_RUNS 50 + +#ifdef CONFIG_HARFBUZZ +#include <hb-ft.h> +enum { + VERT = 0, + VKNA, + KERN +}; +#define NUM_FEATURES 3 +#endif + +struct ass_shaper { + ASS_ShapingLevel shaping_level; + + // FriBidi log2vis + int n_glyphs; + FriBidiChar *event_text; + FriBidiCharType *ctypes; + FriBidiLevel *emblevels; + FriBidiStrIndex *cmap; + FriBidiParType base_direction; + +#ifdef CONFIG_HARFBUZZ + // OpenType features + int n_features; + hb_feature_t *features; + hb_language_t language; + + // Glyph metrics cache, to speed up shaping + Cache *metrics_cache; +#endif +}; + +#ifdef CONFIG_HARFBUZZ +struct ass_shaper_metrics_data { + Cache *metrics_cache; + GlyphMetricsHashKey hash_key; + int vertical; +}; + +struct ass_shaper_font_data { + hb_font_t *fonts[ASS_FONT_MAX_FACES]; + hb_font_funcs_t *font_funcs[ASS_FONT_MAX_FACES]; + struct ass_shaper_metrics_data *metrics_data[ASS_FONT_MAX_FACES]; +}; +#endif + +/** + * \brief Print version information + */ +void ass_shaper_info(ASS_Library *lib) +{ + ass_msg(lib, MSGL_V, "Shaper: FriBidi " + FRIBIDI_VERSION " (SIMPLE)" +#ifdef CONFIG_HARFBUZZ + " HarfBuzz-ng %s (COMPLEX)", hb_version_string() +#endif + ); +} + +/** + * \brief grow arrays, if needed + * \param new_size requested size + */ +static void check_allocations(ASS_Shaper *shaper, size_t new_size) +{ + if (new_size > shaper->n_glyphs) { + shaper->event_text = realloc(shaper->event_text, sizeof(FriBidiChar) * new_size); + shaper->ctypes = realloc(shaper->ctypes, sizeof(FriBidiCharType) * new_size); + shaper->emblevels = realloc(shaper->emblevels, sizeof(FriBidiLevel) * new_size); + shaper->cmap = realloc(shaper->cmap, sizeof(FriBidiStrIndex) * new_size); + } +} + +/** + * \brief Free shaper and related data + */ +void ass_shaper_free(ASS_Shaper *shaper) +{ +#ifdef CONFIG_HARFBUZZ + ass_cache_done(shaper->metrics_cache); + free(shaper->features); +#endif + free(shaper->event_text); + free(shaper->ctypes); + free(shaper->emblevels); + free(shaper->cmap); + free(shaper); +} + +void ass_shaper_font_data_free(ASS_ShaperFontData *priv) +{ +#ifdef CONFIG_HARFBUZZ + int i; + for (i = 0; i < ASS_FONT_MAX_FACES; i++) + if (priv->fonts[i]) { + free(priv->metrics_data[i]); + hb_font_destroy(priv->fonts[i]); + hb_font_funcs_destroy(priv->font_funcs[i]); + } + free(priv); +#endif +} + +#ifdef CONFIG_HARFBUZZ +/** + * \brief set up the HarfBuzz OpenType feature list with some + * standard features. + */ +static void init_features(ASS_Shaper *shaper) +{ + shaper->features = calloc(sizeof(hb_feature_t), NUM_FEATURES); + + shaper->n_features = NUM_FEATURES; + shaper->features[VERT].tag = HB_TAG('v', 'e', 'r', 't'); + shaper->features[VERT].end = INT_MAX; + shaper->features[VKNA].tag = HB_TAG('v', 'k', 'n', 'a'); + shaper->features[VKNA].end = INT_MAX; + shaper->features[KERN].tag = HB_TAG('k', 'e', 'r', 'n'); + shaper->features[KERN].end = INT_MAX; +} + +/** + * \brief Set features depending on properties of the run + */ +static void set_run_features(ASS_Shaper *shaper, GlyphInfo *info) +{ + // enable vertical substitutions for @font runs + if (info->font->desc.vertical) + shaper->features[VERT].value = shaper->features[VKNA].value = 1; + else + shaper->features[VERT].value = shaper->features[VKNA].value = 0; +} + +/** + * \brief Update HarfBuzz's idea of font metrics + * \param hb_font HarfBuzz font + * \param face associated FreeType font face + */ +static void update_hb_size(hb_font_t *hb_font, FT_Face face) +{ + hb_font_set_scale (hb_font, + ((uint64_t) face->size->metrics.x_scale * (uint64_t) face->units_per_EM) >> 16, + ((uint64_t) face->size->metrics.y_scale * (uint64_t) face->units_per_EM) >> 16); + hb_font_set_ppem (hb_font, face->size->metrics.x_ppem, + face->size->metrics.y_ppem); +} + + +/* + * Cached glyph metrics getters follow + * + * These functions replace HarfBuzz' standard FreeType font functions + * and provide cached access to essential glyph metrics. This usually + * speeds up shaping a lot. It also allows us to use custom load flags. + * + */ + +GlyphMetricsHashValue * +get_cached_metrics(struct ass_shaper_metrics_data *metrics, FT_Face face, + hb_codepoint_t glyph) +{ + GlyphMetricsHashValue *val; + + metrics->hash_key.glyph_index = glyph; + val = ass_cache_get(metrics->metrics_cache, &metrics->hash_key); + + if (!val) { + int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH + | FT_LOAD_IGNORE_TRANSFORM; + GlyphMetricsHashValue new_val; + + if (FT_Load_Glyph(face, glyph, load_flags)) + return NULL; + + memcpy(&new_val.metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics)); + val = ass_cache_put(metrics->metrics_cache, &metrics->hash_key, &new_val); + } + + return val; +} + +static hb_bool_t +get_glyph(hb_font_t *font, void *font_data, hb_codepoint_t unicode, + hb_codepoint_t variation, hb_codepoint_t *glyph, void *user_data) +{ + FT_Face face = font_data; + + if (variation) + *glyph = FT_Face_GetCharVariantIndex(face, unicode, variation); + else + *glyph = FT_Get_Char_Index(face, unicode); + + return *glyph != 0; +} + +static hb_position_t +cached_h_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph, + void *user_data) +{ + FT_Face face = font_data; + struct ass_shaper_metrics_data *metrics_priv = user_data; + GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph); + + if (!metrics) + return 0; + + if (metrics_priv->vertical && glyph > VERTICAL_LOWER_BOUND) + return metrics->metrics.vertAdvance; + + return metrics->metrics.horiAdvance; +} + +static hb_position_t +cached_v_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph, + void *user_data) +{ + FT_Face face = font_data; + struct ass_shaper_metrics_data *metrics_priv = user_data; + GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph); + + if (!metrics) + return 0; + + return metrics->metrics.vertAdvance; + +} + +static hb_bool_t +cached_h_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y, void *user_data) +{ + return 1; +} + +static hb_bool_t +cached_v_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y, void *user_data) +{ + FT_Face face = font_data; + struct ass_shaper_metrics_data *metrics_priv = user_data; + GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph); + + if (!metrics) + return 0; + + *x = metrics->metrics.horiBearingX - metrics->metrics.vertBearingX; + *y = metrics->metrics.horiBearingY - (-metrics->metrics.vertBearingY); + + return 1; +} + +static hb_position_t +get_h_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first, + hb_codepoint_t second, void *user_data) +{ + FT_Face face = font_data; + FT_Vector kern; + + if (FT_Get_Kerning (face, first, second, FT_KERNING_DEFAULT, &kern)) + return 0; + + return kern.x; +} + +static hb_position_t +get_v_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first, + hb_codepoint_t second, void *user_data) +{ + return 0; +} + +static hb_bool_t +cached_extents(hb_font_t *font, void *font_data, hb_codepoint_t glyph, + hb_glyph_extents_t *extents, void *user_data) +{ + FT_Face face = font_data; + struct ass_shaper_metrics_data *metrics_priv = user_data; + GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph); + + if (!metrics) + return 0; + + extents->x_bearing = metrics->metrics.horiBearingX; + extents->y_bearing = metrics->metrics.horiBearingY; + extents->width = metrics->metrics.width; + extents->height = metrics->metrics.height; + + return 1; +} + +static hb_bool_t +get_contour_point(hb_font_t *font, void *font_data, hb_codepoint_t glyph, + unsigned int point_index, hb_position_t *x, + hb_position_t *y, void *user_data) +{ + FT_Face face = font_data; + int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH + | FT_LOAD_IGNORE_TRANSFORM; + + if (FT_Load_Glyph(face, glyph, load_flags)) + return 0; + + if (point_index >= (unsigned)face->glyph->outline.n_points) + return 0; + + *x = face->glyph->outline.points[point_index].x; + *y = face->glyph->outline.points[point_index].y; + + return 1; +} + +/** + * \brief Retrieve HarfBuzz font from cache. + * Create it from FreeType font, if needed. + * \param info glyph cluster + * \return HarfBuzz font + */ +static hb_font_t *get_hb_font(ASS_Shaper *shaper, GlyphInfo *info) +{ + ASS_Font *font = info->font; + hb_font_t **hb_fonts; + + if (!font->shaper_priv) + font->shaper_priv = calloc(sizeof(ASS_ShaperFontData), 1); + + + hb_fonts = font->shaper_priv->fonts; + if (!hb_fonts[info->face_index]) { + hb_fonts[info->face_index] = + hb_ft_font_create(font->faces[info->face_index], NULL); + + // set up cached metrics access + font->shaper_priv->metrics_data[info->face_index] = + calloc(sizeof(struct ass_shaper_metrics_data), 1); + struct ass_shaper_metrics_data *metrics = + font->shaper_priv->metrics_data[info->face_index]; + metrics->metrics_cache = shaper->metrics_cache; + metrics->vertical = info->font->desc.vertical; + + hb_font_funcs_t *funcs = hb_font_funcs_create(); + font->shaper_priv->font_funcs[info->face_index] = funcs; + hb_font_funcs_set_glyph_func(funcs, get_glyph, + metrics, NULL); + hb_font_funcs_set_glyph_h_advance_func(funcs, cached_h_advance, + metrics, NULL); + hb_font_funcs_set_glyph_v_advance_func(funcs, cached_v_advance, + metrics, NULL); + hb_font_funcs_set_glyph_h_origin_func(funcs, cached_h_origin, + metrics, NULL); + hb_font_funcs_set_glyph_v_origin_func(funcs, cached_v_origin, + metrics, NULL); + hb_font_funcs_set_glyph_h_kerning_func(funcs, get_h_kerning, + metrics, NULL); + hb_font_funcs_set_glyph_v_kerning_func(funcs, get_v_kerning, + metrics, NULL); + hb_font_funcs_set_glyph_extents_func(funcs, cached_extents, + metrics, NULL); + hb_font_funcs_set_glyph_contour_point_func(funcs, get_contour_point, + metrics, NULL); + hb_font_set_funcs(hb_fonts[info->face_index], funcs, + font->faces[info->face_index], NULL); + } + + ass_face_set_size(font->faces[info->face_index], info->font_size); + update_hb_size(hb_fonts[info->face_index], font->faces[info->face_index]); + + // update hash key for cached metrics + struct ass_shaper_metrics_data *metrics = + font->shaper_priv->metrics_data[info->face_index]; + metrics->hash_key.font = info->font; + metrics->hash_key.face_index = info->face_index; + metrics->hash_key.size = info->font_size; + metrics->hash_key.scale_x = double_to_d6(info->scale_x); + metrics->hash_key.scale_y = double_to_d6(info->scale_y); + + return hb_fonts[info->face_index]; +} + +/** + * \brief Shape event text with HarfBuzz. Full OpenType shaping. + * \param glyphs glyph clusters + * \param len number of clusters + */ +static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) +{ + int i, j; + int run = 0; + struct { + int offset; + int end; + hb_buffer_t *buf; + hb_font_t *font; + } runs[MAX_RUNS]; + + + for (i = 0; i < len && run < MAX_RUNS; i++, run++) { + // get length and level of the current run + int k = i; + int level = glyphs[i].shape_run_id; + int direction = shaper->emblevels[k] % 2; + while (i < (len - 1) && level == glyphs[i+1].shape_run_id) + i++; + runs[run].offset = k; + runs[run].end = i; + runs[run].buf = hb_buffer_create(); + runs[run].font = get_hb_font(shaper, glyphs + k); + set_run_features(shaper, glyphs + k); + hb_buffer_pre_allocate(runs[run].buf, i - k + 1); + hb_buffer_set_direction(runs[run].buf, direction ? HB_DIRECTION_RTL : + HB_DIRECTION_LTR); + hb_buffer_set_language(runs[run].buf, shaper->language); + hb_buffer_add_utf32(runs[run].buf, shaper->event_text + k, i - k + 1, + 0, i - k + 1); + hb_shape(runs[run].font, runs[run].buf, shaper->features, + shaper->n_features); + } + + // Initialize: skip all glyphs, this is undone later as needed + for (i = 0; i < len; i++) + glyphs[i].skip = 1; + + // Update glyph indexes, positions and advances from the shaped runs + for (i = 0; i < run; i++) { + int num_glyphs = hb_buffer_get_length(runs[i].buf); + hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(runs[i].buf, NULL); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(runs[i].buf, NULL); + + for (j = 0; j < num_glyphs; j++) { + int idx = glyph_info[j].cluster + runs[i].offset; + GlyphInfo *info = glyphs + idx; + GlyphInfo *root = info; + + // if we have more than one glyph per cluster, allocate a new one + // and attach to the root glyph + if (info->skip == 0) { + while (info->next) + info = info->next; + info->next = malloc(sizeof(GlyphInfo)); + memcpy(info->next, info, sizeof(GlyphInfo)); + info = info->next; + info->next = NULL; + } + + // set position and advance + info->skip = 0; + info->glyph_index = glyph_info[j].codepoint; + info->offset.x = pos[j].x_offset * info->scale_x; + info->offset.y = -pos[j].y_offset * info->scale_y; + info->advance.x = pos[j].x_advance * info->scale_x; + info->advance.y = -pos[j].y_advance * info->scale_y; + + // accumulate advance in the root glyph + root->cluster_advance.x += info->advance.x; + root->cluster_advance.y += info->advance.y; + } + } + + // Free runs and associated data + for (i = 0; i < run; i++) { + hb_buffer_destroy(runs[i].buf); + } + +} +#endif + +/** + * \brief Shape event text with FriBidi. Does mirroring and simple + * Arabic shaping. + * \param len number of clusters + */ +static void shape_fribidi(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) +{ + int i; + FriBidiJoiningType *joins = calloc(sizeof(*joins), len); + + // shape on codepoint level + fribidi_get_joining_types(shaper->event_text, len, joins); + fribidi_join_arabic(shaper->ctypes, len, shaper->emblevels, joins); + fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, + shaper->emblevels, len, joins, shaper->event_text); + + // update indexes + for (i = 0; i < len; i++) { + GlyphInfo *info = glyphs + i; + FT_Face face = info->font->faces[info->face_index]; + info->symbol = shaper->event_text[i]; + info->glyph_index = FT_Get_Char_Index(face, shaper->event_text[i]); + } + + free(joins); +} + +/** + * \brief Toggle kerning for HarfBuzz shaping. + * NOTE: currently only works with OpenType fonts, the TrueType fallback *always* + * kerns. It's a bug in HarfBuzz. + */ +void ass_shaper_set_kerning(ASS_Shaper *shaper, int kern) +{ +#ifdef CONFIG_HARFBUZZ + shaper->features[KERN].value = !!kern; +#endif +} + +/** + * \brief Find shape runs according to the event's selected fonts + */ +void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv, + GlyphInfo *glyphs, size_t len) +{ + int i; + int shape_run = 0; + + for (i = 0; i < len; i++) { + GlyphInfo *last = glyphs + i - 1; + GlyphInfo *info = glyphs + i; + // skip drawings + if (info->symbol == 0xfffc) + continue; + // set size and get glyph index + ass_font_get_index(render_priv->fontconfig_priv, info->font, + info->symbol, &info->face_index, &info->glyph_index); + // shape runs share the same font face and size + if (i > 0 && (last->font != info->font || + last->font_size != info->font_size || + last->face_index != info->face_index)) + shape_run++; + info->shape_run_id = shape_run; + } + +} + +/** + * \brief Set base direction (paragraph direction) of the text. + * \param dir base direction + */ +void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir) +{ + shaper->base_direction = dir; +} + +/** + * \brief Set language hint. Some languages have specific character variants, + * like Serbian Cyrillic. + * \param lang ISO 639-1 two-letter language code + */ +void ass_shaper_set_language(ASS_Shaper *shaper, const char *code) +{ +#ifdef CONFIG_HARFBUZZ + shaper->language = hb_language_from_string(code, -1); +#endif +} + +/** + * Set shaping level. Essentially switches between FriBidi and HarfBuzz. + */ +void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level) +{ + shaper->shaping_level = level; +} + +/** + * \brief Shape an event's text. Calculates directional runs and shapes them. + * \param text_info event's text + */ +void ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info) +{ + int i, last_break; + FriBidiParType dir; + GlyphInfo *glyphs = text_info->glyphs; + + check_allocations(shaper, text_info->length); + + // Get bidi character types and embedding levels + last_break = 0; + for (i = 0; i < text_info->length; i++) { + shaper->event_text[i] = glyphs[i].symbol; + // embedding levels should be calculated paragraph by paragraph + if (glyphs[i].symbol == '\n' || i == text_info->length - 1) { + dir = shaper->base_direction; + fribidi_get_bidi_types(shaper->event_text + last_break, + i - last_break + 1, shaper->ctypes + last_break); + fribidi_get_par_embedding_levels(shaper->ctypes + last_break, + i - last_break + 1, &dir, shaper->emblevels + last_break); + last_break = i + 1; + } + } + + // add embedding levels to shape runs for final runs + for (i = 0; i < text_info->length; i++) { + glyphs[i].shape_run_id += shaper->emblevels[i]; + } + +#ifdef CONFIG_HARFBUZZ + switch (shaper->shaping_level) { + case ASS_SHAPING_SIMPLE: + shape_fribidi(shaper, glyphs, text_info->length); + break; + case ASS_SHAPING_COMPLEX: + shape_harfbuzz(shaper, glyphs, text_info->length); + break; + } +#else + shape_fribidi(shaper, glyphs, text_info->length); +#endif + + + // clean up + for (i = 0; i < text_info->length; i++) { + // Skip direction override control characters + // NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't + // been implemented yet + if (glyphs[i].symbol <= 0x202F && glyphs[i].symbol >= 0x202a) { + glyphs[i].symbol = 0; + glyphs[i].skip++; + } + } +} + +/** + * \brief Create a new shaper instance and preallocate data structures + * \param prealloc preallocation size + */ +ASS_Shaper *ass_shaper_new(size_t prealloc) +{ + ASS_Shaper *shaper = calloc(sizeof(*shaper), 1); + + shaper->base_direction = FRIBIDI_PAR_ON; + check_allocations(shaper, prealloc); + +#ifdef CONFIG_HARFBUZZ + init_features(shaper); + shaper->metrics_cache = ass_glyph_metrics_cache_create(); +#endif + + return shaper; +} + + +/** + * \brief clean up additional data temporarily needed for shaping and + * (e.g. additional glyphs allocated) + */ +void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info) +{ + int i; + + for (i = 0; i < text_info->length; i++) { + GlyphInfo *info = text_info->glyphs + i; + info = info->next; + while (info) { + GlyphInfo *next = info->next; + free(info); + info = next; + } + } +} + +/** + * \brief Calculate reorder map to render glyphs in visual order + */ +FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info) +{ + int i; + + // Initialize reorder map + for (i = 0; i < text_info->length; i++) + shaper->cmap[i] = i; + + // Create reorder map line-by-line + for (i = 0; i < text_info->n_lines; i++) { + LineInfo *line = text_info->lines + i; + int level; + FriBidiParType dir = FRIBIDI_PAR_ON; + + level = fribidi_reorder_line(0, + shaper->ctypes + line->offset, line->len, 0, dir, + shaper->emblevels + line->offset, NULL, + shaper->cmap + line->offset); + } + + return shaper->cmap; +} + +/** + * \brief Resolve a Windows font encoding number to a suitable + * base direction. 177 and 178 are Hebrew and Arabic respectively, and + * they map to RTL. 1 is autodetection and is mapped to just that. + * Everything else is mapped to LTR. + * \param enc Windows font encoding + */ +FriBidiParType resolve_base_direction(int enc) +{ + switch (enc) { + case 1: + return FRIBIDI_PAR_ON; + case 177: + case 178: + return FRIBIDI_PAR_RTL; + default: + return FRIBIDI_PAR_LTR; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libass/ass_shaper.h Sat Dec 03 23:08:03 2011 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx> + * + * This file is part of libass. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef LIBASS_SHAPER_H +#define LIBASS_SHAPER_H + +#include "config.h" + +#include <fribidi/fribidi.h> +#include "ass_render.h" + +void ass_shaper_info(ASS_Library *lib); +ASS_Shaper *ass_shaper_new(size_t prealloc); +void ass_shaper_free(ASS_Shaper *shaper); +void ass_shaper_set_kerning(ASS_Shaper *shaper, int kern); +void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv, + GlyphInfo *glyphs, size_t len); +void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir); +void ass_shaper_set_language(ASS_Shaper *shaper, const char *code); +void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level); +void ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info); +void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info); +FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info); +FriBidiParType resolve_base_direction(int font_encoding); + +void ass_shaper_font_data_free(ASS_ShaperFontData *priv); + +#endif