summaryrefslogtreecommitdiffstats
path: root/libass/ass_render.c
diff options
context:
space:
mode:
authorgreg <greg@blackbox>2009-06-18 17:54:08 +0200
committergreg <greg@blackbox>2009-06-20 03:38:00 +0200
commit2303b5430337da60f582613f95e605f08606759f (patch)
tree7ab52c9de634da3dfe55e1f36e87030beff2a3fe /libass/ass_render.c
parent9c7521c0224f16880870839f7492e50b1c8602f7 (diff)
downloadlibass-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.c4695
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;