diff options
author | greg <greg@blackbox> | 2009-06-18 17:54:08 +0200 |
---|---|---|
committer | greg <greg@blackbox> | 2009-06-20 03:38:00 +0200 |
commit | 2303b5430337da60f582613f95e605f08606759f (patch) | |
tree | 7ab52c9de634da3dfe55e1f36e87030beff2a3fe /libass/ass_render.c | |
parent | 9c7521c0224f16880870839f7492e50b1c8602f7 (diff) | |
download | libass-2303b5430337da60f582613f95e605f08606759f.tar.bz2 libass-2303b5430337da60f582613f95e605f08606759f.tar.xz |
Reindent all source code.
Reindent complete source code (*.c, *.h) with indent, the exact command
line being:
indent -kr -i4 -bap -nut -l76 *.c *.h
From now on, new code should use (more or less) K&R style,
only spaces and no tabs, 4 spaces indent width. Avoid long lines.
Fix function declaration pointer spacing.
Remove spaces that were added to many function declarations by indent,
like some_func(foo_t * bar).
Fix indenting of macros in ass.c
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r-- | libass/ass_render.c | 4695 |
1 files changed, 2510 insertions, 2185 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index 00a5f39a..33d059be 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -1,5 +1,3 @@ -// -*- c-basic-offset: 8; indent-tabs-mode: t -*- -// vim:ts=8:sw=8:noet:ai: /* * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> * @@ -46,292 +44,309 @@ #define BLUR_MAX_RADIUS 100.0 #define MAX_BE 100 #define ROUND(x) ((int) ((x) + .5)) -#define SUBPIXEL_MASK 56 // d6 bitmask for subpixel accuracy adjustment +#define SUBPIXEL_MASK 56 // d6 bitmask for subpixel accuracy adjustment static int last_render_id = 0; typedef struct ass_settings_s { - int frame_width; - int frame_height; - double font_size_coeff; // font size multiplier - double line_spacing; // additional line spacing (in frame pixels) - int top_margin; // height of top margin. Everything except toptitles is shifted down by top_margin. - int bottom_margin; // height of bottom margin. (frame_height - top_margin - bottom_margin) is original video height. - int left_margin; - int right_margin; - int use_margins; // 0 - place all subtitles inside original frame - // 1 - use margins for placing toptitles and subtitles - double aspect; // frame aspect ratio, d_width / d_height. - ass_hinting_t hinting; - - char* default_font; - char* default_family; + int frame_width; + int frame_height; + double font_size_coeff; // font size multiplier + double line_spacing; // additional line spacing (in frame pixels) + int top_margin; // height of top margin. Everything except toptitles is shifted down by top_margin. + int bottom_margin; // height of bottom margin. (frame_height - top_margin - bottom_margin) is original video height. + int left_margin; + int right_margin; + int use_margins; // 0 - place all subtitles inside original frame + // 1 - use margins for placing toptitles and subtitles + double aspect; // frame aspect ratio, d_width / d_height. + ass_hinting_t hinting; + + char *default_font; + char *default_family; } ass_settings_t; // a rendered event typedef struct event_images_s { - ass_image_t* imgs; - int top, height; - int detect_collisions; - int shift_direction; - ass_event_t* event; + ass_image_t *imgs; + int top, height; + int detect_collisions; + int shift_direction; + ass_event_t *event; } event_images_t; -typedef enum {EF_NONE = 0, EF_KARAOKE, EF_KARAOKE_KF, EF_KARAOKE_KO} effect_t; +typedef enum { EF_NONE = 0, EF_KARAOKE, EF_KARAOKE_KF, EF_KARAOKE_KO +} effect_t; // describes a glyph // glyph_info_t and text_info_t are used for text centering and word-wrapping operations typedef struct glyph_info_s { - unsigned symbol; - FT_Glyph glyph; - FT_Glyph outline_glyph; - bitmap_t* bm; // glyph bitmap - bitmap_t* bm_o; // outline bitmap - bitmap_t* bm_s; // shadow bitmap - FT_BBox bbox; - FT_Vector pos; - char linebreak; // the first (leading) glyph of some line ? - uint32_t c[4]; // colors - FT_Vector advance; // 26.6 - effect_t effect_type; - int effect_timing; // time duration of current karaoke word - // after process_karaoke_effects: distance in pixels from the glyph origin. - // part of the glyph to the left of it is displayed in a different color. - int effect_skip_timing; // delay after the end of last karaoke word - int asc, desc; // font max ascender and descender -// int height; - int be; // blur edges - double blur; // gaussian blur - double shadow; - double frx, fry, frz; // rotation - - bitmap_hash_key_t hash_key; + unsigned symbol; + FT_Glyph glyph; + FT_Glyph outline_glyph; + bitmap_t *bm; // glyph bitmap + bitmap_t *bm_o; // outline bitmap + bitmap_t *bm_s; // shadow bitmap + FT_BBox bbox; + FT_Vector pos; + char linebreak; // the first (leading) glyph of some line ? + uint32_t c[4]; // colors + FT_Vector advance; // 26.6 + effect_t effect_type; + int effect_timing; // time duration of current karaoke word + // after process_karaoke_effects: distance in pixels from the glyph origin. + // part of the glyph to the left of it is displayed in a different color. + int effect_skip_timing; // delay after the end of last karaoke word + int asc, desc; // font max ascender and descender +// int height; + int be; // blur edges + double blur; // gaussian blur + double shadow; + double frx, fry, frz; // rotation + + bitmap_hash_key_t hash_key; } glyph_info_t; typedef struct line_info_s { - int asc, desc; + int asc, desc; } line_info_t; typedef struct text_info_s { - glyph_info_t* glyphs; - int length; - line_info_t* lines; - int n_lines; - int height; - int max_glyphs; - int max_lines; + glyph_info_t *glyphs; + int length; + line_info_t *lines; + int n_lines; + int height; + int max_glyphs; + int max_lines; } text_info_t; // Renderer state. // Values like current font face, color, screen position, clipping and so on are stored here. typedef struct render_context_s { - ass_event_t* event; - ass_style_t* style; - - ass_font_t* font; - char* font_path; - double font_size; - - FT_Stroker stroker; - int alignment; // alignment overrides go here; if zero, style value will be used - double frx, fry, frz; - enum { EVENT_NORMAL, // "normal" top-, sub- or mid- title - EVENT_POSITIONED, // happens after pos(,), margins are ignored - EVENT_HSCROLL, // "Banner" transition effect, text_width is unlimited - EVENT_VSCROLL // "Scroll up", "Scroll down" transition effects - } evt_type; - double pos_x, pos_y; // position - double org_x, org_y; // origin - char have_origin; // origin is explicitly defined; if 0, get_base_point() is used - double scale_x, scale_y; - double hspacing; // distance between letters, in pixels - double border; // outline width - uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA - int clip_x0, clip_y0, clip_x1, clip_y1; - char detect_collisions; - uint32_t fade; // alpha from \fad - char be; // blur edges - double blur; // gaussian blur - double shadow; - int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags - - effect_t effect_type; - int effect_timing; - int effect_skip_timing; - - enum { SCROLL_LR, // left-to-right - SCROLL_RL, - SCROLL_TB, // top-to-bottom - SCROLL_BT - } scroll_direction; // for EVENT_HSCROLL, EVENT_VSCROLL - int scroll_shift; - - // face properties - char* family; - unsigned bold; - unsigned italic; - int treat_family_as_pattern; + ass_event_t *event; + ass_style_t *style; + + ass_font_t *font; + char *font_path; + double font_size; + + FT_Stroker stroker; + int alignment; // alignment overrides go here; if zero, style value will be used + double frx, fry, frz; + enum { EVENT_NORMAL, // "normal" top-, sub- or mid- title + EVENT_POSITIONED, // happens after pos(,), margins are ignored + EVENT_HSCROLL, // "Banner" transition effect, text_width is unlimited + EVENT_VSCROLL // "Scroll up", "Scroll down" transition effects + } evt_type; + double pos_x, pos_y; // position + double org_x, org_y; // origin + char have_origin; // origin is explicitly defined; if 0, get_base_point() is used + double scale_x, scale_y; + double hspacing; // distance between letters, in pixels + double border; // outline width + uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA + int clip_x0, clip_y0, clip_x1, clip_y1; + char detect_collisions; + uint32_t fade; // alpha from \fad + char be; // blur edges + double blur; // gaussian blur + double shadow; + int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags + + effect_t effect_type; + int effect_timing; + int effect_skip_timing; + + enum { SCROLL_LR, // left-to-right + SCROLL_RL, + SCROLL_TB, // top-to-bottom + SCROLL_BT + } scroll_direction; // for EVENT_HSCROLL, EVENT_VSCROLL + int scroll_shift; + + // face properties + char *family; + unsigned bold; + unsigned italic; + int treat_family_as_pattern; } render_context_t; typedef struct cache_store_s { - hashmap_t* font_cache; - hashmap_t* glyph_cache; - hashmap_t* bitmap_cache; - hashmap_t* composite_cache; + hashmap_t *font_cache; + hashmap_t *glyph_cache; + hashmap_t *bitmap_cache; + hashmap_t *composite_cache; } cache_store_t; struct ass_renderer_s { - ass_library_t* library; - FT_Library ftlibrary; - fc_instance_t* fontconfig_priv; - ass_settings_t settings; - int render_id; - ass_synth_priv_t* synth_priv; - - ass_image_t* images_root; // rendering result is stored here - ass_image_t* prev_images_root; - - event_images_t* eimg; // temporary buffer for sorting rendered events - int eimg_size; // allocated buffer size - - // frame-global data - int width, height; // screen dimensions - int orig_height; // frame height ( = screen height - margins ) - int orig_width; // frame width ( = screen width - margins ) - int orig_height_nocrop; // frame height ( = screen height - margins + cropheight) - int orig_width_nocrop; // frame width ( = screen width - margins + cropwidth) - ass_track_t* track; - long long time; // frame's timestamp, ms - double font_scale; - double font_scale_x; // x scale applied to all glyphs to preserve text aspect ratio - double border_scale; - - render_context_t state; - text_info_t text_info; - cache_store_t cache; + ass_library_t *library; + FT_Library ftlibrary; + fc_instance_t *fontconfig_priv; + ass_settings_t settings; + int render_id; + ass_synth_priv_t *synth_priv; + + ass_image_t *images_root; // rendering result is stored here + ass_image_t *prev_images_root; + + event_images_t *eimg; // temporary buffer for sorting rendered events + int eimg_size; // allocated buffer size + + // frame-global data + int width, height; // screen dimensions + int orig_height; // frame height ( = screen height - margins ) + int orig_width; // frame width ( = screen width - margins ) + int orig_height_nocrop; // frame height ( = screen height - margins + cropheight) + int orig_width_nocrop; // frame width ( = screen width - margins + cropwidth) + ass_track_t *track; + long long time; // frame's timestamp, ms + double font_scale; + double font_scale_x; // x scale applied to all glyphs to preserve text aspect ratio + double border_scale; + + render_context_t state; + text_info_t text_info; + cache_store_t cache; }; struct render_priv_s { - int top, height; - int render_id; + int top, height; + int render_id; }; -static void ass_lazy_track_init(ass_renderer_t* render_priv) +static void ass_lazy_track_init(ass_renderer_t *render_priv) { - ass_track_t* track = render_priv->track; - ass_settings_t* settings_priv = &render_priv->settings; - - if (track->PlayResX && track->PlayResY) - return; - if (!track->PlayResX && !track->PlayResY) { - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined); - track->PlayResX = 384; - track->PlayResY = 288; - } else { - double orig_aspect = (settings_priv->aspect * render_priv->height * render_priv->orig_width) / - render_priv->orig_height / render_priv->width; - if (!track->PlayResY && track->PlayResX == 1280) { - track->PlayResY = 1024; - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); - } else if (!track->PlayResY) { - track->PlayResY = track->PlayResX / orig_aspect + .5; - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); - } else if (!track->PlayResX && track->PlayResY == 1024) { - track->PlayResX = 1280; - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); - } else if (!track->PlayResX) { - track->PlayResX = track->PlayResY * orig_aspect + .5; - mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); - } - } + ass_track_t *track = render_priv->track; + ass_settings_t *settings_priv = &render_priv->settings; + + if (track->PlayResX && track->PlayResY) + return; + if (!track->PlayResX && !track->PlayResY) { + mp_msg(MSGT_ASS, MSGL_WARN, + MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined); + track->PlayResX = 384; + track->PlayResY = 288; + } else { + double orig_aspect = + (settings_priv->aspect * render_priv->height * + render_priv->orig_width) / render_priv->orig_height / + render_priv->width; + if (!track->PlayResY && track->PlayResX == 1280) { + track->PlayResY = 1024; + mp_msg(MSGT_ASS, MSGL_WARN, + MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); + } else if (!track->PlayResY) { + track->PlayResY = track->PlayResX / orig_aspect + .5; + mp_msg(MSGT_ASS, MSGL_WARN, + MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); + } else if (!track->PlayResX && track->PlayResY == 1024) { + track->PlayResX = 1280; + mp_msg(MSGT_ASS, MSGL_WARN, + MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); + } else if (!track->PlayResX) { + track->PlayResX = track->PlayResY * orig_aspect + .5; + mp_msg(MSGT_ASS, MSGL_WARN, + MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); + } + } } -ass_renderer_t* ass_renderer_init(ass_library_t* library) +ass_renderer_t *ass_renderer_init(ass_library_t *library) { - int error; - FT_Library ft; - ass_renderer_t* priv = 0; - int vmajor, vminor, vpatch; - - error = FT_Init_FreeType( &ft ); - if ( error ) { - mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_FT_Init_FreeTypeFailed); - goto ass_init_exit; - } - - FT_Library_Version(ft, &vmajor, &vminor, &vpatch); - mp_msg(MSGT_ASS, MSGL_V, "FreeType library version: %d.%d.%d\n", - vmajor, vminor, vpatch); - mp_msg(MSGT_ASS, MSGL_V, "FreeType headers version: %d.%d.%d\n", - FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH); - - priv = calloc(1, sizeof(ass_renderer_t)); - if (!priv) { - FT_Done_FreeType(ft); - goto ass_init_exit; - } - - priv->synth_priv = ass_synth_init(BLUR_MAX_RADIUS); - - priv->library = library; - priv->ftlibrary = ft; - // images_root and related stuff is zero-filled in calloc - - priv->cache.font_cache = ass_font_cache_init(); - priv->cache.bitmap_cache = ass_bitmap_cache_init(); - priv->cache.composite_cache = ass_composite_cache_init(); - priv->cache.glyph_cache = ass_glyph_cache_init(); - - priv->text_info.max_glyphs = MAX_GLYPHS_INITIAL; - priv->text_info.max_lines = MAX_LINES_INITIAL; - priv->text_info.glyphs = calloc(MAX_GLYPHS_INITIAL, sizeof(glyph_info_t)); - priv->text_info.lines = calloc(MAX_LINES_INITIAL, sizeof(line_info_t)); - -ass_init_exit: - if (priv) mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_Init); - else mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_InitFailed); - - return priv; + int error; + FT_Library ft; + ass_renderer_t *priv = 0; + int vmajor, vminor, vpatch; + + error = FT_Init_FreeType(&ft); + if (error) { + mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_FT_Init_FreeTypeFailed); + goto ass_init_exit; + } + + FT_Library_Version(ft, &vmajor, &vminor, &vpatch); + mp_msg(MSGT_ASS, MSGL_V, "FreeType library version: %d.%d.%d\n", + vmajor, vminor, vpatch); + mp_msg(MSGT_ASS, MSGL_V, "FreeType headers version: %d.%d.%d\n", + FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH); + + priv = calloc(1, sizeof(ass_renderer_t)); + if (!priv) { + FT_Done_FreeType(ft); + goto ass_init_exit; + } + + priv->synth_priv = ass_synth_init(BLUR_MAX_RADIUS); + + priv->library = library; + priv->ftlibrary = ft; + // images_root and related stuff is zero-filled in calloc + + priv->cache.font_cache = ass_font_cache_init(); + priv->cache.bitmap_cache = ass_bitmap_cache_init(); + priv->cache.composite_cache = ass_composite_cache_init(); + priv->cache.glyph_cache = ass_glyph_cache_init(); + + priv->text_info.max_glyphs = MAX_GLYPHS_INITIAL; + priv->text_info.max_lines = MAX_LINES_INITIAL; + priv->text_info.glyphs = + calloc(MAX_GLYPHS_INITIAL, sizeof(glyph_info_t)); + priv->text_info.lines = calloc(MAX_LINES_INITIAL, sizeof(line_info_t)); + + ass_init_exit: + if (priv) + mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_Init); + else + mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_InitFailed); + + return priv; } -void ass_renderer_done(ass_renderer_t* render_priv) +void ass_renderer_done(ass_renderer_t *render_priv) { - ass_font_cache_done(render_priv->cache.font_cache); - ass_bitmap_cache_done(render_priv->cache.bitmap_cache); - ass_composite_cache_done(render_priv->cache.composite_cache); - ass_glyph_cache_done(render_priv->cache.glyph_cache); - if (render_priv->state.stroker) { - FT_Stroker_Done(render_priv->state.stroker); - render_priv->state.stroker = 0; - } - if (render_priv && render_priv->ftlibrary) FT_Done_FreeType(render_priv->ftlibrary); - if (render_priv && render_priv->fontconfig_priv) fontconfig_done(render_priv->fontconfig_priv); - if (render_priv && render_priv->synth_priv) ass_synth_done(render_priv->synth_priv); - if (render_priv && render_priv->eimg) free(render_priv->eimg); - free(render_priv); - free(render_priv->text_info.glyphs); - free(render_priv->text_info.lines); + ass_font_cache_done(render_priv->cache.font_cache); + ass_bitmap_cache_done(render_priv->cache.bitmap_cache); + ass_composite_cache_done(render_priv->cache.composite_cache); + ass_glyph_cache_done(render_priv->cache.glyph_cache); + if (render_priv->state.stroker) { + FT_Stroker_Done(render_priv->state.stroker); + render_priv->state.stroker = 0; + } + if (render_priv && render_priv->ftlibrary) + FT_Done_FreeType(render_priv->ftlibrary); + if (render_priv && render_priv->fontconfig_priv) + fontconfig_done(render_priv->fontconfig_priv); + if (render_priv && render_priv->synth_priv) + ass_synth_done(render_priv->synth_priv); + if (render_priv && render_priv->eimg) + free(render_priv->eimg); + free(render_priv); + free(render_priv->text_info.glyphs); + free(render_priv->text_info.lines); } /** * \brief Create a new ass_image_t * Parameters are the same as ass_image_t fields. */ -static ass_image_t* my_draw_bitmap(unsigned char* bitmap, int bitmap_w, int bitmap_h, int stride, int dst_x, int dst_y, uint32_t color) +static ass_image_t *my_draw_bitmap(unsigned char *bitmap, int bitmap_w, + int bitmap_h, int stride, int dst_x, + int dst_y, uint32_t color) { - ass_image_t* img = calloc(1, sizeof(ass_image_t)); + ass_image_t *img = calloc(1, sizeof(ass_image_t)); - img->w = bitmap_w; - img->h = bitmap_h; - img->stride = stride; - img->bitmap = bitmap; - img->color = color; - img->dst_x = dst_x; - img->dst_y = dst_y; + img->w = bitmap_w; + img->h = bitmap_h; + img->stride = stride; + img->bitmap = bitmap; + img->color = color; + img->dst_x = dst_x; + img->dst_y = dst_y; - return img; + return img; } /** @@ -346,71 +361,76 @@ static ass_image_t* my_draw_bitmap(unsigned char* bitmap, int bitmap_w, int bitm * \return pointer to the new list tail * Performs clipping. Uses my_draw_bitmap for actual bitmap convertion. */ -static ass_image_t** render_glyph(ass_renderer_t* render_priv, bitmap_t* bm, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, ass_image_t** tail) +static ass_image_t **render_glyph(ass_renderer_t *render_priv, + bitmap_t *bm, int dst_x, int dst_y, + uint32_t color, uint32_t color2, int brk, + ass_image_t ** tail) { - // brk is relative to dst_x - // color = color left of brk - // color2 = color right of brk - int b_x0, b_y0, b_x1, b_y1; // visible part of the bitmap - int clip_x0, clip_y0, clip_x1, clip_y1; - int tmp; - ass_image_t* img; - - dst_x += bm->left; - dst_y += bm->top; - brk -= bm->left; - - // clipping - clip_x0 = render_priv->state.clip_x0; - clip_y0 = render_priv->state.clip_y0; - clip_x1 = render_priv->state.clip_x1; - clip_y1 = render_priv->state.clip_y1; - b_x0 = 0; - b_y0 = 0; - b_x1 = bm->w; - b_y1 = bm->h; - - tmp = dst_x - clip_x0; - if (tmp < 0) { - mp_msg(MSGT_ASS, MSGL_DBG2, "clip left\n"); - b_x0 = - tmp; - } - tmp = dst_y - clip_y0; - if (tmp < 0) { - mp_msg(MSGT_ASS, MSGL_DBG2, "clip top\n"); - b_y0 = - tmp; - } - tmp = clip_x1 - dst_x - bm->w; - if (tmp < 0) { - mp_msg(MSGT_ASS, MSGL_DBG2, "clip right\n"); - b_x1 = bm->w + tmp; - } - tmp = clip_y1 - dst_y - bm->h; - if (tmp < 0) { - mp_msg(MSGT_ASS, MSGL_DBG2, "clip bottom\n"); - b_y1 = bm->h + tmp; - } - - if ((b_y0 >= b_y1) || (b_x0 >= b_x1)) - return tail; - - if (brk > b_x0) { // draw left part - if (brk > b_x1) brk = b_x1; - img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + b_x0, - brk - b_x0, b_y1 - b_y0, bm->w, - dst_x + b_x0, dst_y + b_y0, color); - *tail = img; - tail = &img->next; - } - if (brk < b_x1) { // draw right part - if (brk < b_x0) brk = b_x0; - img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + brk, - b_x1 - brk, b_y1 - b_y0, bm->w, - dst_x + brk, dst_y + b_y0, color2); - *tail = img; - tail = &img->next; - } - return tail; + // brk is relative to dst_x + // color = color left of brk + // color2 = color right of brk + int b_x0, b_y0, b_x1, b_y1; // visible part of the bitmap + int clip_x0, clip_y0, clip_x1, clip_y1; + int tmp; + ass_image_t *img; + + dst_x += bm->left; + dst_y += bm->top; + brk -= bm->left; + + // clipping + clip_x0 = render_priv->state.clip_x0; + clip_y0 = render_priv->state.clip_y0; + clip_x1 = render_priv->state.clip_x1; + clip_y1 = render_priv->state.clip_y1; + b_x0 = 0; + b_y0 = 0; + b_x1 = bm->w; + b_y1 = bm->h; + + tmp = dst_x - clip_x0; + if (tmp < 0) { + mp_msg(MSGT_ASS, MSGL_DBG2, "clip left\n"); + b_x0 = -tmp; + } + tmp = dst_y - clip_y0; + if (tmp < 0) { + mp_msg(MSGT_ASS, MSGL_DBG2, "clip top\n"); + b_y0 = -tmp; + } + tmp = clip_x1 - dst_x - bm->w; + if (tmp < 0) { + mp_msg(MSGT_ASS, MSGL_DBG2, "clip right\n"); + b_x1 = bm->w + tmp; + } + tmp = clip_y1 - dst_y - bm->h; + if (tmp < 0) { + mp_msg(MSGT_ASS, MSGL_DBG2, "clip bottom\n"); + b_y1 = bm->h + tmp; + } + + if ((b_y0 >= b_y1) || (b_x0 >= b_x1)) + return tail; + + if (brk > b_x0) { // draw left part + if (brk > b_x1) + brk = b_x1; + img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + b_x0, + brk - b_x0, b_y1 - b_y0, bm->w, + dst_x + b_x0, dst_y + b_y0, color); + *tail = img; + tail = &img->next; + } + if (brk < b_x1) { // draw right part + if (brk < b_x0) + brk = b_x0; + img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + brk, + b_x1 - brk, b_y1 - b_y0, bm->w, + dst_x + brk, dst_y + b_y0, color2); + *tail = img; + tail = &img->next; + } + return tail; } /** @@ -419,331 +439,386 @@ static ass_image_t** render_glyph(ass_renderer_t* render_priv, bitmap_t* bm, int * Mainly useful for translucent glyphs and especially borders, to avoid the * luminance adding up where they overlap (which looks ugly) */ -static void render_overlap(ass_renderer_t* render_priv, ass_image_t** last_tail, ass_image_t** tail, bitmap_hash_key_t *last_hash, bitmap_hash_key_t* hash) { - int left, top, bottom, right; - int old_left, old_top, w, h, cur_left, cur_top; - int x, y, opos, cpos; - char m; - composite_hash_key_t hk; - composite_hash_val_t *hv; - composite_hash_key_t *nhk; - int ax = (*last_tail)->dst_x; - int ay = (*last_tail)->dst_y; - int aw = (*last_tail)->w; - int as = (*last_tail)->stride; - int ah = (*last_tail)->h; - int bx = (*tail)->dst_x; - int by = (*tail)->dst_y; - int bw = (*tail)->w; - int bs = (*tail)->stride; - int bh = (*tail)->h; - unsigned char* a; - unsigned char* b; - - if ((*last_tail)->bitmap == (*tail)->bitmap) - return; - - if ((*last_tail)->color != (*tail)->color) - return; - - // Calculate overlap coordinates - left = (ax > bx) ? ax : bx; - top = (ay > by) ? ay : by; - right = ((ax+aw) < (bx+bw)) ? (ax+aw) : (bx+bw); - bottom = ((ay+ah) < (by+bh)) ? (ay+ah) : (by+bh); - if ((right <= left) || (bottom <= top)) - return; - old_left = left-ax; - old_top = top-ay; - w = right-left; - h = bottom-top; - cur_left = left-bx; - cur_top = top-by; - - // Query cache - memset(&hk, 0, sizeof(hk)); - memcpy(&hk.a, last_hash, sizeof(*last_hash)); - memcpy(&hk.b, hash, sizeof(*hash)); - hk.aw = aw; - hk.ah = ah; - hk.bw = bw; - hk.bh = bh; - hk.ax = ax; - hk.ay = ay; - hk.bx = bx; - hk.by = by; - hv = cache_find_composite(render_priv->cache.composite_cache, &hk); - if (hv) { - (*last_tail)->bitmap = hv->a; - (*tail)->bitmap = hv->b; - return; - } - - // Allocate new bitmaps and copy over data - a = (*last_tail)->bitmap; - b = (*tail)->bitmap; - (*last_tail)->bitmap = malloc(as*ah); - (*tail)->bitmap = malloc(bs*bh); - memcpy((*last_tail)->bitmap, a, as*ah); - memcpy((*tail)->bitmap, b, bs*bh); - - // Composite overlapping area - for (y=0; y<h; y++) - for (x=0; x<w; x++) { - opos = (old_top+y)*(as) + (old_left+x); - cpos = (cur_top+y)*(bs) + (cur_left+x); - m = (a[opos] > b[cpos]) ? a[opos] : b[cpos]; - (*last_tail)->bitmap[opos] = 0; - (*tail)->bitmap[cpos] = m; - } - - // Insert bitmaps into the cache - nhk = calloc(1, sizeof(*nhk)); - memcpy(nhk, &hk, sizeof(*nhk)); - hv = calloc(1, sizeof(*hv)); - hv->a = (*last_tail)->bitmap; - hv->b = (*tail)->bitmap; - cache_add_composite(render_priv->cache.composite_cache, nhk, hv); +static void +render_overlap(ass_renderer_t *render_priv, ass_image_t ** last_tail, + ass_image_t ** tail, bitmap_hash_key_t *last_hash, + bitmap_hash_key_t *hash) +{ + int left, top, bottom, right; + int old_left, old_top, w, h, cur_left, cur_top; + int x, y, opos, cpos; + char m; + composite_hash_key_t hk; + composite_hash_val_t *hv; + composite_hash_key_t *nhk; + int ax = (*last_tail)->dst_x; + int ay = (*last_tail)->dst_y; + int aw = (*last_tail)->w; + int as = (*last_tail)->stride; + int ah = (*last_tail)->h; + int bx = (*tail)->dst_x; + int by = (*tail)->dst_y; + int bw = (*tail)->w; + int bs = (*tail)->stride; + int bh = (*tail)->h; + unsigned char *a; + unsigned char *b; + + if ((*last_tail)->bitmap == (*tail)->bitmap) + return; + + if ((*last_tail)->color != (*tail)->color) + return; + + // Calculate overlap coordinates + left = (ax > bx) ? ax : bx; + top = (ay > by) ? ay : by; + right = ((ax + aw) < (bx + bw)) ? (ax + aw) : (bx + bw); + bottom = ((ay + ah) < (by + bh)) ? (ay + ah) : (by + bh); + if ((right <= left) || (bottom <= top)) + return; + old_left = left - ax; + old_top = top - ay; + w = right - left; + h = bottom - top; + cur_left = left - bx; + cur_top = top - by; + + // Query cache + memset(&hk, 0, sizeof(hk)); + memcpy(&hk.a, last_hash, sizeof(*last_hash)); + memcpy(&hk.b, hash, sizeof(*hash)); + hk.aw = aw; + hk.ah = ah; + hk.bw = bw; + hk.bh = bh; + hk.ax = ax; + hk.ay = ay; + hk.bx = bx; + hk.by = by; + hv = cache_find_composite(render_priv->cache.composite_cache, &hk); + if (hv) { + (*last_tail)->bitmap = hv->a; + (*tail)->bitmap = hv->b; + return; + } + // Allocate new bitmaps and copy over data + a = (*last_tail)->bitmap; + b = (*tail)->bitmap; + (*last_tail)->bitmap = malloc(as * ah); + (*tail)->bitmap = malloc(bs * bh); + memcpy((*last_tail)->bitmap, a, as * ah); + memcpy((*tail)->bitmap, b, bs * bh); + + // Composite overlapping area + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) { + opos = (old_top + y) * (as) + (old_left + x); + cpos = (cur_top + y) * (bs) + (cur_left + x); + m = (a[opos] > b[cpos]) ? a[opos] : b[cpos]; + (*last_tail)->bitmap[opos] = 0; + (*tail)->bitmap[cpos] = m; + } + + // Insert bitmaps into the cache + nhk = calloc(1, sizeof(*nhk)); + memcpy(nhk, &hk, sizeof(*nhk)); + hv = calloc(1, sizeof(*hv)); + hv->a = (*last_tail)->bitmap; + hv->b = (*tail)->bitmap; + cache_add_composite(render_priv->cache.composite_cache, nhk, hv); } /** * \brief Convert text_info_t struct to ass_image_t list * Splits glyphs in halves when needed (for \kf karaoke). */ -static ass_image_t* render_text(ass_renderer_t* render_priv, int dst_x, int dst_y) +static ass_image_t *render_text(ass_renderer_t *render_priv, int dst_x, + int dst_y) { - int pen_x, pen_y; - int i; - bitmap_t* bm; - ass_image_t* head; - ass_image_t** tail = &head; - ass_image_t** last_tail = 0; - ass_image_t** here_tail = 0; - bitmap_hash_key_t* last_hash = 0; - text_info_t* text_info = &render_priv->text_info; - - for (i = 0; i < text_info->length; ++i) { - glyph_info_t* info = text_info->glyphs + i; - if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0)) - continue; - - pen_x = dst_x + info->pos.x + ROUND(info->shadow * render_priv->border_scale); - pen_y = dst_y + info->pos.y + ROUND(info->shadow * render_priv->border_scale); - bm = info->bm_s; - - here_tail = tail; - tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[3], 0, 1000000, tail); - if (last_tail && tail != here_tail && ((info->c[3] & 0xff) > 0)) - render_overlap(render_priv, last_tail, here_tail, last_hash, &info->hash_key); - last_tail = here_tail; - last_hash = &info->hash_key; - } - - last_tail = 0; - for (i = 0; i < text_info->length; ++i) { - glyph_info_t* info = text_info->glyphs + i; - if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o) - continue; - - pen_x = dst_x + info->pos.x; - pen_y = dst_y + info->pos.y; - bm = info->bm_o; - - if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) { - // do nothing - } else { - here_tail = tail; - tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[2], 0, 1000000, tail); - if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0)) - render_overlap(render_priv, last_tail, here_tail, last_hash, &info->hash_key); - last_tail = here_tail; - last_hash = &info->hash_key; - } - } - for (i = 0; i < text_info->length; ++i) { - glyph_info_t* info = text_info->glyphs + i; - if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm) - continue; - - pen_x = dst_x + info->pos.x; - pen_y = dst_y + info->pos.y; - bm = info->bm; - - if ((info->effect_type == EF_KARAOKE) || (info->effect_type == EF_KARAOKE_KO)) { - if (info->effect_timing > info->bbox.xMax) - tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[0], 0, 1000000, tail); - else - tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[1], 0, 1000000, tail); - } else if (info->effect_type == EF_KARAOKE_KF) { - tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[0], info->c[1], info->effect_timing, tail); - } else - tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[0], 0, 1000000, tail); - } - - *tail = 0; - return head; + int pen_x, pen_y; + int i; + bitmap_t *bm; + ass_image_t *head; + ass_image_t **tail = &head; + ass_image_t **last_tail = 0; + ass_image_t **here_tail = 0; + bitmap_hash_key_t *last_hash = 0; + text_info_t *text_info = &render_priv->text_info; + + for (i = 0; i < text_info->length; ++i) { + glyph_info_t *info = text_info->glyphs + i; + if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s + || (info->shadow == 0)) + continue; + + pen_x = + dst_x + info->pos.x + + ROUND(info->shadow * render_priv->border_scale); + pen_y = + dst_y + info->pos.y + + ROUND(info->shadow * render_priv->border_scale); + bm = info->bm_s; + + here_tail = tail; + tail = + render_glyph(render_priv, bm, pen_x, pen_y, info->c[3], 0, + 1000000, tail); + if (last_tail && tail != here_tail && ((info->c[3] & 0xff) > 0)) + render_overlap(render_priv, last_tail, here_tail, last_hash, + &info->hash_key); + last_tail = here_tail; + last_hash = &info->hash_key; + } + + last_tail = 0; + for (i = 0; i < text_info->length; ++i) { + glyph_info_t *info = text_info->glyphs + i; + if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o) + continue; + + pen_x = dst_x + info->pos.x; + pen_y = dst_y + info->pos.y; + bm = info->bm_o; + + if ((info->effect_type == EF_KARAOKE_KO) + && (info->effect_timing <= info->bbox.xMax)) { + // do nothing + } else { + here_tail = tail; |