diff options
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass/meson.build | 13 | ||||
-rw-r--r-- | libass/ass_compat.h | 11 | ||||
-rw-r--r-- | libass/ass_directwrite.h | 7 | ||||
-rw-r--r-- | libass/ass_drawing.c | 3 | ||||
-rw-r--r-- | libass/ass_filesystem.c | 1 | ||||
-rw-r--r-- | libass/ass_font.c | 21 | ||||
-rw-r--r-- | libass/ass_font.h | 3 | ||||
-rw-r--r-- | libass/ass_fontselect.h | 1 | ||||
-rw-r--r-- | libass/ass_parse.c | 2 | ||||
-rw-r--r-- | libass/ass_render.c | 87 | ||||
-rw-r--r-- | libass/ass_render.h | 3 | ||||
-rw-r--r-- | libass/ass_shaper.c | 166 | ||||
-rw-r--r-- | libass/ass_shaper.h | 3 | ||||
-rw-r--r-- | libass/meson.build | 149 | ||||
-rw-r--r-- | libass/x86/x86inc.asm | 309 |
15 files changed, 534 insertions, 245 deletions
diff --git a/libass/ass/meson.build b/libass/ass/meson.build new file mode 100644 index 0000000..6b4de1f --- /dev/null +++ b/libass/ass/meson.build @@ -0,0 +1,13 @@ +# See: https://github.com/mesonbuild/meson/issues/2546 +# This hack is needed because the install directory of the libass public headers +# ('ass') is different than the name of the directory ('libass') that they live under +# in the source tree. In the scenario where the libass meson build system is being used +# as a subproject of some parent project, that parent project will need the libass +# headers to be copied into the appropriate 'ass' directory either before or during the +# build process so that they are in an appropriate include path prior to the time that +# the build system starts trying to build the parent project that needs to include +# them. +fs = import('fs') +foreach header : libass_headers + fake_installed_headers += fs.copyfile(header, fs.name(header)) +endforeach diff --git a/libass/ass_compat.h b/libass/ass_compat.h index 38df913..52ac282 100644 --- a/libass/ass_compat.h +++ b/libass/ass_compat.h @@ -43,4 +43,15 @@ char *ass_strndup_fallback(const char *s, size_t n); // definition in ass_utils. #define strndup ass_strndup_fallback #endif +#ifdef _WIN32 + +#ifdef WINAPI_FAMILY +#include <winapifamily.h> +#define ASS_WINAPI_DESKTOP WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#else +#define ASS_WINAPI_DESKTOP 1 +#endif + +#endif // _WIN32 + #endif /* LIBASS_COMPAT_H */ diff --git a/libass/ass_directwrite.h b/libass/ass_directwrite.h index a14b951..bb1159c 100644 --- a/libass/ass_directwrite.h +++ b/libass/ass_directwrite.h @@ -22,13 +22,6 @@ #ifndef ASS_DIRECTWRITE_H #define ASS_DIRECTWRITE_H -#ifdef WINAPI_FAMILY -#include <winapifamily.h> -#define ASS_WINAPI_DESKTOP WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#else -#define ASS_WINAPI_DESKTOP 1 -#endif - ASS_FontProvider * ass_directwrite_add_provider(ASS_Library *lib, ASS_FontSelector *selector, const char *config, FT_Library ftlib); diff --git a/libass/ass_drawing.c b/libass/ass_drawing.c index a4ed04c..770f555 100644 --- a/libass/ass_drawing.c +++ b/libass/ass_drawing.c @@ -124,8 +124,7 @@ static size_t add_many_points(const char **str, ASS_DrawingToken **tail, ASS_TokenType type, size_t batch_size, bool *error) { ASS_Vector buf[3]; - size_t max_buf = sizeof(buf) / sizeof(*buf); - assert(batch_size <= max_buf); + assert(batch_size <= (sizeof(buf) / sizeof(*buf))); if (!*str) return 0; diff --git a/libass/ass_filesystem.c b/libass/ass_filesystem.c index 79a0d80..eb330c2 100644 --- a/libass/ass_filesystem.c +++ b/libass/ass_filesystem.c @@ -118,7 +118,6 @@ void ass_close_dir(ASS_Dir *dir) #else // Windows #include <windows.h> -#include "ass_directwrite.h" // for ASS_WINAPI_DESKTOP static const uint8_t wtf8_len_table[256] = { diff --git a/libass/ass_font.c b/libass/ass_font.c index d17258a..72ec888 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -424,6 +424,7 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) int i, index, uid; ASS_FontStream stream = { NULL, NULL }; FT_Face face; + int ret = -1; if (font->n_faces == ASS_FONT_MAX_FACES) return -1; @@ -457,9 +458,16 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) set_font_metrics(face); font->faces[font->n_faces] = face; - font->faces_uid[font->n_faces++] = uid; - ass_face_set_size(face, font->size); - return font->n_faces - 1; + font->faces_uid[font->n_faces] = uid; + if (!ass_create_hb_font(font, font->n_faces)) { + FT_Done_Face(face); + goto fail; + } + + ret = font->n_faces++; + +fail: + return ret; } /** @@ -484,15 +492,12 @@ size_t ass_font_construct(void *key, void *value, void *priv) font->library = render_priv->library; font->ftlibrary = render_priv->ftlibrary; - font->shaper_priv = NULL; font->n_faces = 0; font->desc.family = desc->family; font->desc.bold = desc->bold; font->desc.italic = desc->italic; font->desc.vertical = desc->vertical; - font->size = 0.; - int error = add_face(render_priv->fontselect, font, 0); if (error == -1) font->library = NULL; @@ -701,11 +706,11 @@ bool ass_font_get_glyph(ASS_Font *font, int face_index, int index, void ass_font_clear(ASS_Font *font) { int i; - if (font->shaper_priv) - ass_shaper_font_data_free(font->shaper_priv); for (i = 0; i < font->n_faces; ++i) { if (font->faces[i]) FT_Done_Face(font->faces[i]); + if (font->hb_fonts[i]) + hb_font_destroy(font->hb_fonts[i]); } free((char *) font->desc.family.str); } diff --git a/libass/ass_font.h b/libass/ass_font.h index ea1130f..df9fb30 100644 --- a/libass/ass_font.h +++ b/libass/ass_font.h @@ -44,9 +44,8 @@ struct ass_font { FT_Library ftlibrary; int faces_uid[ASS_FONT_MAX_FACES]; FT_Face faces[ASS_FONT_MAX_FACES]; - ASS_ShaperFontData *shaper_priv; + struct hb_font_t *hb_fonts[ASS_FONT_MAX_FACES]; int n_faces; - double size; }; void ass_charmap_magic(ASS_Library *library, FT_Face face); diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h index 43366bb..23bcad4 100644 --- a/libass/ass_fontselect.h +++ b/libass/ass_fontselect.h @@ -24,7 +24,6 @@ #include <ft2build.h> #include FT_FREETYPE_H -typedef struct ass_shaper_font_data ASS_ShaperFontData; typedef struct font_selector ASS_FontSelector; typedef struct font_info ASS_FontInfo; typedef struct ass_font_stream ASS_FontStream; diff --git a/libass/ass_parse.c b/libass/ass_parse.c index fae575a..d1b6051 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -1022,7 +1022,7 @@ void ass_apply_transition_effects(RenderContext *state) */ void ass_process_karaoke_effects(RenderContext *state) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; long long tm_current = state->renderer->time - state->event->Start; int32_t timing = 0, skip_timing = 0; diff --git a/libass/ass_render.c b/libass/ass_render.c index f95479c..afcbf42 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -76,6 +76,29 @@ static void text_info_done(TextInfo* text_info) free(text_info->combined_bitmaps); } +static bool render_context_init(RenderContext *state, ASS_Renderer *priv) +{ + state->renderer = priv; + + if (!text_info_init(&state->text_info)) + return false; + + if (!(state->shaper = ass_shaper_new(priv->cache.metrics_cache))) + return false; + + return ass_rasterizer_init(&priv->engine, &state->rasterizer, RASTERIZER_PRECISION); +} + +static void render_context_done(RenderContext *state) +{ + ass_rasterizer_done(&state->rasterizer); + + if (state->shaper) + ass_shaper_free(state->shaper); + + text_info_done(&state->text_info); +} + ASS_Renderer *ass_renderer_init(ASS_Library *library) { int error; @@ -112,9 +135,6 @@ ASS_Renderer *ass_renderer_init(ASS_Library *library) #endif priv->engine = ass_bitmap_engine_init(flags); - if (!ass_rasterizer_init(&priv->engine, &priv->state.rasterizer, RASTERIZER_PRECISION)) - goto fail; - priv->cache.font_cache = ass_font_cache_create(); priv->cache.bitmap_cache = ass_bitmap_cache_create(); priv->cache.composite_cache = ass_composite_cache_create(); @@ -127,20 +147,14 @@ ASS_Renderer *ass_renderer_init(ASS_Library *library) priv->cache.bitmap_max_size = BITMAP_CACHE_MAX_SIZE; priv->cache.composite_max_size = COMPOSITE_CACHE_MAX_SIZE; - if (!text_info_init(&priv->text_info)) + if (!render_context_init(&priv->state, priv)) goto fail; priv->user_override_style.Name = "OverrideStyle"; // name insignificant - priv->state.renderer = priv; - priv->state.text_info = &priv->text_info; - priv->settings.font_size_coeff = 1.; priv->settings.selective_style_overrides = ASS_OVERRIDE_BIT_SELECTIVE_FONT_SCALE; - if (!(priv->state.shaper = ass_shaper_new(priv->cache.metrics_cache))) - goto fail; - ass_shaper_info(library); priv->settings.shaper = ASS_SHAPING_COMPLEX; @@ -167,18 +181,15 @@ void ass_renderer_done(ASS_Renderer *render_priv) ass_cache_done(render_priv->cache.bitmap_cache); ass_cache_done(render_priv->cache.outline_cache); ass_cache_done(render_priv->cache.metrics_cache); - ass_shaper_free(render_priv->state.shaper); ass_cache_done(render_priv->cache.font_cache); - ass_rasterizer_done(&render_priv->state.rasterizer); - if (render_priv->fontselect) ass_fontselect_free(render_priv->fontselect); if (render_priv->ftlibrary) FT_Done_FreeType(render_priv->ftlibrary); free(render_priv->eimg); - text_info_done(&render_priv->text_info); + render_context_done(&render_priv->state); free(render_priv->settings.default_font); free(render_priv->settings.default_family); @@ -809,8 +820,8 @@ static ASS_Image *render_text(RenderContext *state) { ASS_Image *head; ASS_Image **tail = &head; - unsigned n_bitmaps = state->text_info->n_bitmaps; - CombinedBitmapInfo *bitmaps = state->text_info->combined_bitmaps; + unsigned n_bitmaps = state->text_info.n_bitmaps; + CombinedBitmapInfo *bitmaps = state->text_info.combined_bitmaps; for (unsigned i = 0; i < n_bitmaps; i++) { CombinedBitmapInfo *info = &bitmaps[i]; @@ -1149,9 +1160,7 @@ static void free_render_context(RenderContext *state) state->family.len = 0; state->clip_drawing_text.str = NULL; state->clip_drawing_text.len = 0; - - if (state->text_info) - state->text_info->length = 0; + state->text_info.length = 0; } /** @@ -1580,7 +1589,7 @@ static void measure_text_on_eol(RenderContext *state, double scale, int cur_line int max_asc, int max_desc, double max_border_x, double max_border_y) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; text_info->lines[cur_line].asc = scale * max_asc; text_info->lines[cur_line].desc = scale * max_desc; text_info->height += scale * max_asc + scale * max_desc; @@ -1608,7 +1617,7 @@ static void measure_text_on_eol(RenderContext *state, double scale, int cur_line static void measure_text(RenderContext *state) { ASS_Renderer *render_priv = state->renderer; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; text_info->height = 0; text_info->border_x = 0; @@ -1661,7 +1670,7 @@ static void trim_whitespace(RenderContext *state) { int i, j; GlyphInfo *cur; - TextInfo *ti = state->text_info; + TextInfo *ti = &state->text_info; // Mark trailing spaces i = ti->length - 1; @@ -1732,7 +1741,7 @@ static void wrap_lines_naive(RenderContext *state, double max_text_width, char *unibrks) { ASS_Renderer *render_priv = state->renderer; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; GlyphInfo *s1 = text_info->glyphs; // current line start int last_breakable = -1; int break_type = 0; @@ -1812,7 +1821,7 @@ static inline GlyphInfo *rewind_trailing_spaces(GlyphInfo *start1, GlyphInfo* st static void wrap_lines_rebalance(RenderContext *state, double max_text_width, char *unibrks) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; int exit = 0; #define DIFF(x,y) (((x) < (y)) ? (y - x) : (x - y)) @@ -1881,7 +1890,7 @@ wrap_lines_rebalance(RenderContext *state, double max_text_width, char *unibrks) static void wrap_lines_measure(RenderContext *state, char *unibrks) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; int cur_line = 1; int i = 0; @@ -1933,7 +1942,7 @@ wrap_lines_smart(RenderContext *state, double max_text_width) #ifdef CONFIG_UNIBREAK ASS_Renderer *render_priv = state->renderer; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; if (render_priv->track->parser_priv->feature_flags & FEATURE_MASK(ASS_FEATURE_WRAP_UNICODE)) { unibrks = text_info->breaks; set_linebreaks_utf32( @@ -2033,7 +2042,7 @@ fix_glyph_scaling(ASS_Renderer *priv, GlyphInfo *glyph) // Initial run splitting based purely on the characters' styles static void split_style_runs(RenderContext *state) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; Effect last_effect_type = text_info->glyphs[0].effect_type; text_info->glyphs[0].starts_new_run = true; for (int i = 1; i < text_info->length; i++) { @@ -2079,7 +2088,7 @@ static void split_style_runs(RenderContext *state) // Fill render_priv->text_info. static bool parse_events(RenderContext *state, ASS_Event *event) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; ASS_Renderer *render_priv = state->renderer; char *p = event->Text, *q; @@ -2214,10 +2223,10 @@ fail: // Process render_priv->text_info and load glyph outlines. static void retrieve_glyphs(RenderContext *state) { - GlyphInfo *glyphs = state->text_info->glyphs; + GlyphInfo *glyphs = state->text_info.glyphs; int i; - for (i = 0; i < state->text_info->length; i++) { + for (i = 0; i < state->text_info.length; i++) { GlyphInfo *info = glyphs + i; do { get_outline_glyph(state, info); @@ -2245,8 +2254,8 @@ static void retrieve_glyphs(RenderContext *state) static void preliminary_layout(RenderContext *state) { ASS_Vector pen = { 0, 0 }; - for (int i = 0; i < state->text_info->length; i++) { - GlyphInfo *info = state->text_info->glyphs + i; + for (int i = 0; i < state->text_info.length; i++) { + GlyphInfo *info = state->text_info.glyphs + i; ASS_Vector cluster_pen = pen; do { info->pos.x = cluster_pen.x; @@ -2257,7 +2266,7 @@ static void preliminary_layout(RenderContext *state) info = info->next; } while (info); - info = state->text_info->glyphs + i; + info = state->text_info.glyphs + i; pen.x += info->cluster_advance.x; pen.y += info->cluster_advance.y; } @@ -2267,7 +2276,7 @@ static void preliminary_layout(RenderContext *state) static void reorder_text(RenderContext *state) { ASS_Renderer *render_priv = state->renderer; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; FriBidiStrIndex *cmap = ass_shaper_reorder(state->shaper, text_info); if (!cmap) { ass_msg(render_priv->library, MSGL_ERR, "Failed to reorder text"); @@ -2306,7 +2315,7 @@ static void reorder_text(RenderContext *state) static void apply_baseline_shear(RenderContext *state) { ASS_Renderer *render_priv = state->renderer; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; FriBidiStrIndex *cmap = ass_shaper_get_reorder_map(state->shaper); int32_t shear = 0; bool whole_text_layout = @@ -2329,7 +2338,7 @@ static void apply_baseline_shear(RenderContext *state) static void align_lines(RenderContext *state, double max_text_width) { - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; GlyphInfo *glyphs = text_info->glyphs; int i, j; double width = 0; @@ -2413,7 +2422,7 @@ static void calculate_rotation_params(RenderContext *state, ASS_DRect *bbox, center.y = device_y + by; } - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; for (int i = 0; i < text_info->length; i++) { GlyphInfo *info = text_info->glyphs + i; while (info) { @@ -2481,7 +2490,7 @@ static void render_and_combine_glyphs(RenderContext *state, double device_x, double device_y) { ASS_Renderer *render_priv = state->renderer; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; int left = render_priv->settings.left_margin; device_x = (device_x - left) * render_priv->par_scale_x + left; unsigned nb_bitmaps = 0; @@ -2852,7 +2861,7 @@ ass_render_event(RenderContext *state, ASS_Event *event, if (!parse_events(state, event)) return false; - TextInfo *text_info = state->text_info; + TextInfo *text_info = &state->text_info; if (text_info->length == 0) { // no valid symbols in the event; this can be smth like {comment} free_render_context(state); diff --git a/libass/ass_render.h b/libass/ass_render.h index 3c717b8..a3de04a 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -210,7 +210,7 @@ typedef struct { // Values like current font face, color, screen position, clipping and so on are stored here. struct render_context { ASS_Renderer *renderer; - TextInfo *text_info; + TextInfo text_info; ASS_Shaper *shaper; RasterizerData rasterizer; @@ -334,7 +334,6 @@ struct ass_renderer { double par_scale_x; // x scale applied to all glyphs to preserve text aspect ratio RenderContext state; - TextInfo text_info; CacheStore cache; BitmapEngine engine; diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index 1d83757..fa445da 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -65,6 +65,9 @@ struct ass_shaper { // Glyph metrics cache, to speed up shaping Cache *metrics_cache; + hb_font_funcs_t *font_funcs; + hb_buffer_t *buf; + #ifdef USE_FRIBIDI_EX_API FriBidiBracketType *btypes; bool bidi_brackets; @@ -79,12 +82,6 @@ struct ass_shaper_metrics_data { 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]; -}; - /** * \brief Print version information */ @@ -142,21 +139,11 @@ void ass_shaper_free(ASS_Shaper *shaper) free(shaper->emblevels); free(shaper->cmap); free(shaper->pbase_dir); + hb_font_funcs_destroy(shaper->font_funcs); + hb_buffer_destroy(shaper->buf); free(shaper); } -void ass_shaper_font_data_free(ASS_ShaperFontData *priv) -{ - 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); -} - /** * \brief set up the HarfBuzz OpenType feature list with some * standard features. @@ -296,8 +283,8 @@ static hb_bool_t get_glyph_nominal(hb_font_t *font, void *font_data, hb_codepoint_t unicode, hb_codepoint_t *glyph, void *user_data) { - FT_Face face = font_data; - struct ass_shaper_metrics_data *metrics_priv = user_data; + struct ass_shaper_metrics_data *metrics_priv = font_data; + FT_Face face = metrics_priv->hash_key.font->faces[metrics_priv->hash_key.face_index]; *glyph = ass_font_index_magic(face, unicode); if (*glyph) @@ -315,8 +302,8 @@ static hb_bool_t get_glyph_variation(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; - struct ass_shaper_metrics_data *metrics_priv = user_data; + struct ass_shaper_metrics_data *metrics_priv = font_data; + FT_Face face = metrics_priv->hash_key.font->faces[metrics_priv->hash_key.face_index]; *glyph = ass_font_index_magic(face, unicode); if (*glyph) @@ -334,7 +321,7 @@ static hb_position_t cached_h_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data) { - struct ass_shaper_metrics_data *metrics_priv = user_data; + struct ass_shaper_metrics_data *metrics_priv = font_data; FT_Glyph_Metrics *metrics = get_cached_metrics(metrics_priv, 0, glyph); if (!metrics) return 0; @@ -348,7 +335,7 @@ static hb_position_t cached_v_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data) { - struct ass_shaper_metrics_data *metrics_priv = user_data; + struct ass_shaper_metrics_data *metrics_priv = font_data; FT_Glyph_Metrics *metrics = get_cached_metrics(metrics_priv, 0, glyph); if (!metrics) return 0; @@ -369,7 +356,7 @@ 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) { - struct ass_shaper_metrics_data *metrics_priv = user_data; + struct ass_shaper_metrics_data *metrics_priv = font_data; FT_Glyph_Metrics *metrics = get_cached_metrics(metrics_priv, 0, glyph); if (!metrics) return false; @@ -384,7 +371,8 @@ 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; + struct ass_shaper_metrics_data *metrics_priv = font_data; + FT_Face face = metrics_priv->hash_key.font->faces[metrics_priv->hash_key.face_index]; FT_Vector kern; if (FT_Get_Kerning(face, first, second, FT_KERNING_DEFAULT, &kern)) @@ -404,7 +392,7 @@ 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) { - struct ass_shaper_metrics_data *metrics_priv = user_data; + struct ass_shaper_metrics_data *metrics_priv = font_data; FT_Glyph_Metrics *metrics = get_cached_metrics(metrics_priv, 0, glyph); if (!metrics) return false; @@ -422,7 +410,8 @@ 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; + struct ass_shaper_metrics_data *metrics_priv = font_data; + FT_Face face = metrics_priv->hash_key.font->faces[metrics_priv->hash_key.face_index]; int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_IGNORE_TRANSFORM; @@ -437,6 +426,26 @@ get_contour_point(hb_font_t *font, void *font_data, hb_codepoint_t glyph, return true; } +bool ass_create_hb_font(ASS_Font *font, int index) +{ + FT_Face face = font->faces[index]; + hb_face_t *hb_face = hb_face_create_for_tables(get_reference_table, face, NULL); + if (!hb_face) + return false; + + hb_face_set_index(hb_face, face->face_index); + hb_face_set_upem(hb_face, face->units_per_EM); + + hb_font_t *hb_font = hb_font_create(hb_face); + hb_face_destroy(hb_face); + if (!hb_font) + return false; + + font->hb_fonts[index] = hb_font; + + return true; +} + /** * \brief Retrieve HarfBuzz font from cache. * Create it from FreeType font, if needed. @@ -446,78 +455,25 @@ get_contour_point(hb_font_t *font, void *font_data, hb_codepoint_t glyph, 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); - if (!font->shaper_priv) + hb_font_t *hb_font = font->hb_fonts[info->face_index]; + if (!hb_font) return NULL; - hb_fonts = font->shaper_priv->fonts; - if (!hb_fonts[info->face_index]) { - FT_Face face = font->faces[info->face_index]; - hb_face_t *hb_face = hb_face_create_for_tables(get_reference_table, face, NULL); - if (!hb_face) - return NULL; - hb_face_set_index(hb_face, face->face_index); - hb_face_set_upem(hb_face, face->units_per_EM); - - hb_font_t *hb_font = hb_fonts[info->face_index] = hb_font_create(hb_face); - hb_face_destroy(hb_face); - if (!hb_font) - return NULL; - - hb_font_set_scale(hb_font, - (int)(((uint64_t)face->size->metrics.x_scale * face->units_per_EM + (1<<15)) >> 16), - (int)(((uint64_t)face->size->metrics.y_scale * face->units_per_EM + (1<<15)) >> 16)); - - // set up cached metrics access - struct ass_shaper_metrics_data *metrics = - font->shaper_priv->metrics_data[info->face_index] = - calloc(sizeof(struct ass_shaper_metrics_data), 1); - if (!metrics) - return NULL; - metrics->metrics_cache = shaper->metrics_cache; - metrics->vertical = info->font->desc.vertical; - - hb_font_funcs_t *funcs = hb_font_funcs_create(); - if (!funcs) - return NULL; - font->shaper_priv->font_funcs[info->face_index] = funcs; - hb_font_funcs_set_nominal_glyph_func(funcs, get_glyph_nominal, - metrics, NULL); - hb_font_funcs_set_variation_glyph_func(funcs, get_glyph_variation, - 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_font, funcs, face, NULL); - } - + // set up cached metrics access + struct ass_shaper_metrics_data *metrics = calloc(sizeof(struct ass_shaper_metrics_data), 1); + if (!metrics) + return 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]; + update_hb_size(hb_font, font->faces[info->face_index]); + metrics->metrics_cache = shaper->metrics_cache; metrics->hash_key.font = info->font; metrics->hash_key.face_index = info->face_index; metrics->hash_key.size = info->font_size; + metrics->vertical = info->font->desc.vertical; - return hb_fonts[info->face_index]; + hb_font_set_funcs(hb_font, shaper->font_funcs, metrics, free); + + return hb_font; } /** @@ -686,7 +642,7 @@ shape_harfbuzz_process_run(GlyphInfo *glyphs, hb_buffer_t *buf, int offset) static bool shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) { int i; - hb_buffer_t *buf = hb_buffer_create(); + hb_buffer_t *buf = shaper->buf; hb_segment_properties_t props = HB_SEGMENT_PROPERTIES_DEFAULT; // Initialize: skip all glyphs, this is undone later as needed @@ -745,8 +701,6 @@ static bool shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) hb_buffer_reset(buf); } - hb_buffer_destroy(buf); - return true; } @@ -1057,6 +1011,26 @@ ASS_Shaper *ass_shaper_new(Cache *metrics_cache) goto error; shaper->metrics_cache = metrics_cache; + hb_font_funcs_t *funcs = shaper->font_funcs = hb_font_funcs_create(); + if (!funcs) + goto error; + hb_font_funcs_set_nominal_glyph_func(funcs, get_glyph_nominal, NULL, NULL); + hb_font_funcs_set_variation_glyph_func(funcs, get_glyph_variation, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func(funcs, cached_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func(funcs, cached_v_advance, NULL, NULL); + hb_font_funcs_set_glyph_h_origin_func(funcs, cached_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func(funcs, cached_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func(funcs, get_h_kerning, NULL, NULL); + hb_font_funcs_set_glyph_v_kerning_func(funcs, get_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func(funcs, cached_extents, NULL, NULL); + hb_font_funcs_set_glyph_contour_point_func(funcs, get_contour_point, NULL, NULL); + + hb_font_funcs_make_immutable(funcs); + + shaper->buf = hb_buffer_create(); + if (!shaper->buf) + goto error; + return shaper; error: diff --git a/libass/ass_shaper.h b/libass/ass_shaper.h index 819a3fd..b4694b0 100644 --- a/libass/ass_shaper.h +++ b/libass/ass_shaper.h @@ -33,6 +33,7 @@ typedef struct ass_shaper ASS_Shaper; void ass_shaper_info(ASS_Library *lib); ASS_Shaper *ass_shaper_new(Cache *metrics_cache); void ass_shaper_free(ASS_Shaper *shaper); +bool ass_create_hb_font(ASS_Font *font, int index); void ass_shaper_set_kerning(ASS_Shaper *shaper, bool kern); void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv, GlyphInfo *glyphs, size_t len); @@ -49,6 +50,4 @@ FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info); FriBidiStrIndex *ass_shaper_get_reorder_map(ASS_Shaper *shaper); FriBidiParType ass_resolve_base_direction(int font_encoding); -void ass_shaper_font_data_free(ASS_ShaperFontData *priv); - #endif diff --git a/libass/meson.build b/libass/meson.build new file mode 100644 index 0000000..b63c5cf --- /dev/null +++ b/libass/meson.build @@ -0,0 +1,149 @@ +# Read library versioning from Automake +# (should we ever reorder those in Automake, it will correctly fail +# due to undefined variables rather than using bogus versions) +fs = import('fs') +am_lib_file = fs.read('Makefile_library.am').split('\n') +foreach line : am_lib_file + args = line.split('=') + name = args[0].strip() + val = args[1].strip() + if name == 'LIBASS_LT_CURRENT' + libass_lt_current = val.to_int() + elif name == 'LIBASS_LT_REVISION' + libass_lt_revision = val.to_int() + elif name == 'LIBASS_LT_AGE' + libass_lt_age = val.to_int() + break + endif +endforeach + +libass_so_version = '@0@.@1@.@2@'.format( + libass_lt_current - libass_lt_age, + libass_lt_age, + libass_lt_revision, +) + +src_x86 = files( + 'x86/be_blur.asm', + 'x86/blend_bitmaps.asm', + 'x86/blur.asm', + 'x86/cpuid.asm', + 'x86/rasterizer.asm', +) +src_aarch64 = files( + 'aarch64/asm.S', + 'aarch64/be_blur.S', + 'aarch64/blend_bitmaps.S', + 'aarch64/blur.S', + 'aarch64/rasterizer.S', +) +src_fontconfig = files('ass_fontconfig.c') +src_directwrite = files('ass_directwrite.c') +src_coretext = files('ass_coretext.c') + +libass_src = files( + 'c/c_be_blur.c', + 'c/c_blend_bitmaps.c', + 'c/c_blur.c', + 'c/c_rasterizer.c', + 'ass.c', + 'ass_bitmap.c', + 'ass_bitmap_engine.c', + 'ass_blur.c', + 'ass_cache.c', + 'ass_drawing.c', + 'ass_filesystem.c', + 'ass_font.c', + 'ass_fontselect.c', + 'ass_library.c', + 'ass_outline.c', + 'ass_parse.c', + 'ass_rasterizer.c', + 'ass_render.c', + 'ass_render_api.c', + 'ass_shaper.c', + 'ass_string.c', + 'ass_strtod.c', + 'ass_utils.c', +) + +libass_link_with = [] + +libass_headers = files('ass.h', 'ass_types.h') + +if fontconfig + libass_src += src_fontconfig +endif +if directwrite + libass_src += src_directwrite +endif +if coretext + libass_src += src_coretext +endif + +if enable_asm + asm_sources = [] + if cpu_family == 'x86' + asm_sources = src_x86 + elif cpu_subfamily == 'aarch64' + asm_sources = src_aarch64 + endif + + if asm_is_nasm + libass_src += asm_sources + else + asm_lib = sta |