[MPlayer-dev-eng] Update libass to 0.10.1
Klaus Burton
subjunk at gmail.com
Sun Nov 4 06:42:58 CET 2012
The first commit I'd like to do is this, which updates libass to 0.10.1:
Index: libass/ass.c
===================================================================
--- libass/ass.c (revision 35339)
+++ libass/ass.c (working copy)
@@ -191,30 +191,6 @@
style->MarginL = style->MarginR = style->MarginV = 20;
}
-/**
- * \brief find style by name
- * \param track track
- * \param name style name
- * \return index in track->styles
- * Returnes 0 if no styles found => expects at least 1 style.
- * Parsing code always adds "Default" style in the end.
- */
-static int lookup_style(ASS_Track *track, char *name)
-{
- int i;
- if (*name == '*')
- ++name; // FIXME: what does '*' really mean ?
- for (i = track->n_styles - 1; i >= 0; --i) {
- if (strcmp(track->styles[i].Name, name) == 0)
- return i;
- }
- i = track->default_style;
- ass_msg(track->library, MSGL_WARN,
- "[%p]: Warning: no style named '%s' found, using '%s'",
- track, name, track->styles[i].Name);
- return i; // use the first style
-}
-
static uint32_t string2color(ASS_Library *library, char *p)
{
uint32_t tmp;
Index: libass/ass.h
===================================================================
--- libass/ass.h (revision 35339)
+++ libass/ass.h (working copy)
@@ -23,7 +23,7 @@
#include <stdarg.h>
#include "ass_types.h"
-#define LIBASS_VERSION 0x01000000
+#define LIBASS_VERSION 0x01010000
/*
* A linked list of images produced by an ass renderer.
@@ -214,6 +214,14 @@
void ass_set_line_spacing(ASS_Renderer *priv, double line_spacing);
/**
+ * \brief Set vertical line position.
+ * \param priv renderer handle
+ * \param line_position vertical line position of subtitles in percent
+ * (0-100: 0 = on the bottom (default), 100 = on top)
+ */
+void ass_set_line_position(ASS_Renderer *priv, double line_position);
+
+/**
* \brief Set font lookup defaults.
* \param default_font path to default font to use. Must be supplied if
* fontconfig is disabled or unavailable.
Index: libass/ass_drawing.c
===================================================================
--- libass/ass_drawing.c (revision 35339)
+++ libass/ass_drawing.c (working copy)
@@ -87,6 +87,7 @@
static void drawing_finish(ASS_Drawing *drawing, int raw_mode)
{
int i, offset;
+ double pbo;
FT_BBox bbox = drawing->cbox;
FT_Outline *ol = &drawing->outline;
@@ -103,11 +104,12 @@
drawing->advance.x = bbox.xMax - bbox.xMin;
- drawing->desc = double_to_d6(-drawing->pbo * drawing->scale_y);
+ pbo = drawing->pbo / (64.0 / (1 << (drawing->scale - 1)));
+ drawing->desc = double_to_d6(-pbo * drawing->scale_y);
drawing->asc = bbox.yMax - bbox.yMin + drawing->desc;
// Place it onto the baseline
- offset = (bbox.yMax - bbox.yMin) + double_to_d6(-drawing->pbo *
+ offset = (bbox.yMax - bbox.yMin) + double_to_d6(-pbo *
drawing->scale_y);
for (i = 0; i < ol->n_points; i++)
ol->points[i].y += offset;
Index: libass/ass_parse.c
===================================================================
--- libass/ass_parse.c (revision 35339)
+++ libass/ass_parse.c (working copy)
@@ -105,28 +105,36 @@
}
/**
- * \brief Change border width
- * negative value resets border to style value
+ * \brief Calculate valid border size. Makes sure the border sizes make sense.
+ *
+ * \param priv renderer state object
+ * \param border_x requested x border size
+ * \param border_y requested y border size
*/
-void change_border(ASS_Renderer *render_priv, double border_x,
- double border_y)
+void calc_border(ASS_Renderer *priv, double border_x, double border_y)
{
- int bord;
- if (!render_priv->state.font)
- return;
-
if (border_x < 0 && border_y < 0) {
- if (render_priv->state.style->BorderStyle == 1 ||
- render_priv->state.style->BorderStyle == 3)
- border_x = border_y = render_priv->state.style->Outline;
+ if (priv->state.border_style == 1 ||
+ priv->state.border_style == 3)
+ border_x = border_y = priv->state.style->Outline;
else
border_x = border_y = 1.;
}
- render_priv->state.border_x = border_x;
- render_priv->state.border_y = border_y;
+ priv->state.border_x = border_x;
+ priv->state.border_y = border_y;
+}
- bord = 64 * border_x * render_priv->border_scale;
+/**
+ * \brief Change border width
+ *
+ * \param render_priv renderer state object
+ * \param info glyph state object
+ */
+void change_border(ASS_Renderer *render_priv, double border_x, double border_y)
+{
+ int bord = 64 * border_x * render_priv->border_scale;
+
if (bord > 0 && border_x == border_y) {
if (!render_priv->state.stroker) {
int error;
@@ -138,11 +146,14 @@
"failed to get stroker");
render_priv->state.stroker = 0;
}
+ render_priv->state.stroker_radius = -1.0;
}
- if (render_priv->state.stroker)
+ if (render_priv->state.stroker && render_priv->state.stroker_radius != bord) {
FT_Stroker_Set(render_priv->state.stroker, bord,
FT_STROKER_LINECAP_ROUND,
FT_STROKER_LINEJOIN_ROUND, 0);
+ render_priv->state.stroker_radius = bord;
+ }
} else {
FT_Stroker_Done(render_priv->state.stroker);
render_priv->state.stroker = 0;
@@ -242,7 +253,7 @@
* \param p string to parse
* \param pwr multiplier for some tag effects (comes from \t tags)
*/
-static char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr)
+char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr)
{
skip_to('\\');
skip('\\');
@@ -256,7 +267,7 @@
val = render_priv->state.border_x * (1 - pwr) + val * pwr;
else
val = -1.;
- change_border(render_priv, val, render_priv->state.border_y);
+ calc_border(render_priv, val, render_priv->state.border_y);
render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "ybord")) {
double val;
@@ -264,7 +275,8 @@
val = render_priv->state.border_y * (1 - pwr) + val * pwr;
else
val = -1.;
- change_border(render_priv, render_priv->state.border_x, val);
+ calc_border(render_priv, render_priv->state.border_x, val);
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "xshad")) {
double val;
if (mystrtod(&p, &val))
@@ -388,11 +400,10 @@
} else if (mystrcmp(&p, "bord")) {
double val;
if (mystrtod(&p, &val)) {
- if (render_priv->state.border_x == render_priv->state.border_y)
val = render_priv->state.border_x * (1 - pwr) + val * pwr;
} else
val = -1.; // reset to default
- change_border(render_priv, val, val);
+ calc_border(render_priv, val, val);
render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "move")) {
double x1, x2, y1, y2;
@@ -730,7 +741,18 @@
ass_msg(render_priv->library, MSGL_DBG2, "single c/a at %f: %c%c = %X",
pwr, n, cmd, render_priv->state.c[cidx]);
} else if (mystrcmp(&p, "r")) {
- reset_render_context(render_priv);
+ char *start = p;
+ char *style;
+ skip_to('\\');
+ if (p > start) {
+ style = malloc(p - start + 1);
+ strncpy(style, start, p - start);
+ style[p - start] = '\0';
+ reset_render_context(render_priv,
+ render_priv->track->styles + lookup_style(render_priv->track, style));
+ free(style);
+ } else
+ reset_render_context(render_priv, NULL);
} else if (mystrcmp(&p, "be")) {
int val;
if (mystrtoi(&p, &val)) {
@@ -977,7 +999,7 @@
/**
- * \brief Get next ucs4 char from string, parsing and executing style overrides
+ * \brief Get next ucs4 char from string, parsing UTF-8 and escapes
* \param str string pointer
* \return ucs4 code of the next char
* On return str points to the unparsed part of the string
@@ -986,24 +1008,6 @@
{
char *p = *str;
unsigned chr;
- if (*p == '{') { // '\0' goes here
- p++;
- while (1) {
- p = parse_tag(render_priv, p, 1.);
- if (*p == '}') { // end of tag
- p++;
- if (*p == '{') {
- p++;
- continue;
- } else
- break;
- } else if (*p != '\\')
- ass_msg(render_priv->library, MSGL_V,
- "Unable to parse: '%.30s'", p);
- if (*p == 0)
- break;
- }
- }
if (*p == '\t') {
++p;
*str = p;
Index: libass/ass_parse.h
===================================================================
--- libass/ass_parse.h (revision 35339)
+++ libass/ass_parse.h (working copy)
@@ -28,11 +28,13 @@
void update_font(ASS_Renderer *render_priv);
double ensure_font_size(ASS_Renderer *priv, double size);
+void calc_border(ASS_Renderer *priv, double border_x, double border_y);
void change_border(ASS_Renderer *render_priv, double border_x,
double border_y);
void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event);
void process_karaoke_effects(ASS_Renderer *render_priv);
unsigned get_next_char(ASS_Renderer *render_priv, char **str);
+char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr);
extern void change_alpha(uint32_t *var, uint32_t new, double pwr);
extern uint32_t mult_alpha(uint32_t a, uint32_t b);
Index: libass/ass_render.c
===================================================================
--- libass/ass_render.c (revision 35339)
+++ libass/ass_render.c (working copy)
@@ -841,39 +841,44 @@
* \brief partially reset render_context to style values
* Works like {\r}: resets some style overrides
*/
-void reset_render_context(ASS_Renderer *render_priv)
+void reset_render_context(ASS_Renderer *render_priv, ASS_Style *style)
{
- render_priv->state.c[0] = render_priv->state.style->PrimaryColour;
- render_priv->state.c[1] = render_priv->state.style->SecondaryColour;
- render_priv->state.c[2] = render_priv->state.style->OutlineColour;
- render_priv->state.c[3] = render_priv->state.style->BackColour;
+ if (!style)
+ style = render_priv->state.style;
+
+ render_priv->state.c[0] = style->PrimaryColour;
+ render_priv->state.c[1] = style->SecondaryColour;
+ render_priv->state.c[2] = style->OutlineColour;
+ render_priv->state.c[3] = style->BackColour;
render_priv->state.flags =
- (render_priv->state.style->Underline ? DECO_UNDERLINE : 0) |
- (render_priv->state.style->StrikeOut ? DECO_STRIKETHROUGH : 0);
- render_priv->state.font_size = render_priv->state.style->FontSize;
+ (style->Underline ? DECO_UNDERLINE : 0) |
+ (style->StrikeOut ? DECO_STRIKETHROUGH : 0);
+ render_priv->state.font_size = style->FontSize;
free(render_priv->state.family);
render_priv->state.family = NULL;
- render_priv->state.family = strdup(render_priv->state.style->FontName);
+ render_priv->state.family = strdup(style->FontName);
render_priv->state.treat_family_as_pattern =
- render_priv->state.style->treat_fontname_as_pattern;
- render_priv->state.bold = render_priv->state.style->Bold;
- render_priv->state.italic = render_priv->state.style->Italic;
+ style->treat_fontname_as_pattern;
+ render_priv->state.bold = style->Bold;
+ render_priv->state.italic = style->Italic;
update_font(render_priv);
- change_border(render_priv, -1., -1.);
- render_priv->state.scale_x = render_priv->state.style->ScaleX;
- render_priv->state.scale_y = render_priv->state.style->ScaleY;
- render_priv->state.hspacing = render_priv->state.style->Spacing;
+ render_priv->state.border_style = style->BorderStyle;
+ calc_border(render_priv, style->Outline, style->Outline);
+ change_border(render_priv, render_priv->state.border_x, render_priv->state.border_y);
+ render_priv->state.scale_x = style->ScaleX;
+ render_priv->state.scale_y = style->ScaleY;
+ render_priv->state.hspacing = style->Spacing;
render_priv->state.be = 0;
render_priv->state.blur = 0.0;
- render_priv->state.shadow_x = render_priv->state.style->Shadow;
- render_priv->state.shadow_y = render_priv->state.style->Shadow;
+ render_priv->state.shadow_x = style->Shadow;
+ render_priv->state.shadow_y = style->Shadow;
render_priv->state.frx = render_priv->state.fry = 0.;
- render_priv->state.frz = M_PI * render_priv->state.style->Angle / 180.;
+ render_priv->state.frz = M_PI * style->Angle / 180.;
render_priv->state.fax = render_priv->state.fay = 0.;
render_priv->state.wrap_style = render_priv->track->WrapStyle;
- render_priv->state.font_encoding = render_priv->state.style->Encoding;
+ render_priv->state.font_encoding = style->Encoding;
}
/**
@@ -886,7 +891,7 @@
render_priv->state.style = render_priv->track->styles + event->Style;
render_priv->state.parsed_tags = 0;
- reset_render_context(render_priv);
+ reset_render_context(render_priv, render_priv->state.style);
render_priv->state.evt_type = EVENT_NORMAL;
render_priv->state.alignment = render_priv->state.style->Alignment;
@@ -1036,7 +1041,7 @@
key->scale_y = double_to_d16(info->scale_y);
key->outline.x = double_to_d16(info->border_x);
key->outline.y = double_to_d16(info->border_y);
- key->border_style = priv->state.style->BorderStyle;
+ key->border_style = info->border_style;
key->hash = info->drawing->hash;
key->text = info->drawing->text;
key->pbo = info->drawing->pbo;
@@ -1055,7 +1060,7 @@
key->outline.x = double_to_d16(info->border_x);
key->outline.y = double_to_d16(info->border_y);
key->flags = info->flags;
- key->border_style = priv->state.style->BorderStyle;
+ key->border_style = info->border_style;
}
}
@@ -1095,10 +1100,14 @@
v.desc = drawing->desc;
key.u.drawing.text = strdup(drawing->text);
} else {
- ass_face_set_size(info->font->faces[info->face_index],
- info->font_size);
- ass_font_set_transform(info->font, info->scale_x,
- info->scale_y, NULL);
+ // arbitrary, not too small to prevent grid fitting rounding effects
+ // XXX: this is a rather crude hack
+ const double ft_size = 256.0;
+ ass_face_set_size(info->font->faces[info->face_index], ft_size);
+ ass_font_set_transform(info->font,
+ info->scale_x * info->font_size / ft_size,
+ info->scale_y * info->font_size / ft_size,
+ NULL);
FT_Glyph glyph =
ass_font_get_glyph(priv->fontconfig_priv, info->font,
info->symbol, info->face_index, info->glyph_index,
@@ -1113,8 +1122,8 @@
FT_Done_Glyph(glyph);
ass_font_get_asc_desc(info->font, info->symbol,
&v.asc, &v.desc);
- v.asc *= info->scale_y;
- v.desc *= info->scale_y;
+ v.asc *= info->scale_y * info->font_size / ft_size;
+ v.desc *= info->scale_y * info->font_size / ft_size;
}
}
@@ -1123,7 +1132,7 @@
FT_Outline_Get_CBox(v.outline, &v.bbox_scaled);
- if (priv->state.style->BorderStyle == 3 &&
+ if (info->border_style == 3 &&
(info->border_x > 0 || info->border_y > 0)) {
FT_Vector advance;
@@ -1141,6 +1150,7 @@
} else if ((info->border_x > 0 || info->border_y > 0)
&& double_to_d6(info->scale_x) && double_to_d6(info->scale_y)) {
+ change_border(priv, info->border_x, info->border_y);
outline_copy(priv->ftlibrary, v.outline, &v.border);
stroke_outline(priv, v.border,
double_to_d6(info->border_x * priv->border_scale),
@@ -1275,8 +1285,8 @@
// calculating rotation shift vector (from rotation origin to the glyph basepoint)
shift.x = key->shift_x;
shift.y = key->shift_y;
- fax_scaled = info->fax * render_priv->state.scale_x;
- fay_scaled = info->fay * render_priv->state.scale_y;
+ fax_scaled = info->fax / info->scale_y * info->scale_x;
+ fay_scaled = info->fay / info->scale_x * info->scale_y;
// apply rotation
transform_3d(shift, outline, border,
@@ -1308,7 +1318,7 @@
&hash_val.bm_s, info->be,
info->blur * render_priv->border_scale,
key->shadow_offset,
- render_priv->state.style->BorderStyle);
+ info->border_style);
if (error)
info->symbol = 0;
@@ -1707,15 +1717,43 @@
num_glyphs = 0;
p = event->Text;
+ int in_tag = 0;
+
// Event parsing.
while (1) {
// get next char, executing style override
// this affects render_context
do {
- code = get_next_char(render_priv, &p);
- if (render_priv->state.drawing_mode && code)
- ass_drawing_add_char(drawing, (char) code);
- } while (code && render_priv->state.drawing_mode); // skip everything in drawing mode
+ code = 0;
+ if (!in_tag && *p == '{') { // '\0' goes here
+ p++;
+ in_tag = 1;
+ }
+ if (in_tag) {
+ int prev_drawing_mode = render_priv->state.drawing_mode;
+ p = parse_tag(render_priv, p, 1.);
+ if (*p == '}') { // end of tag
+ p++;
+ in_tag = 0;
+ } else if (*p != '\\') {
+ ass_msg(render_priv->library, MSGL_V,
+ "Unable to parse: '%.30s'", p);
+ }
+ if (prev_drawing_mode && !render_priv->state.drawing_mode) {
+ // Drawing mode was just disabled. We must exit and draw it
+ // immediately, instead of letting further tags affect it.
+ // See bug #47.
+ break;
+ }
+ } else {
+ code = get_next_char(render_priv, &p);
+ if (code && render_priv->state.drawing_mode) {
+ ass_drawing_add_char(drawing, (char) code);
+ continue; // skip everything in drawing mode
+ }
+ break;
+ }
+ } while (*p);
if (text_info->length >= text_info->max_glyphs) {
// Raise maximum number of glyphs
@@ -1734,7 +1772,6 @@
render_priv->font_scale;
drawing->scale_y = render_priv->state.scale_y *
render_priv->font_scale;
- p--;
code = 0xfffc; // object replacement character
glyphs[text_info->length].drawing = drawing;
}
@@ -1762,16 +1799,18 @@
render_priv->state.effect_timing;
glyphs[text_info->length].effect_skip_timing =
render_priv->state.effect_skip_timing;
- glyphs[text_info->length].font_size = ensure_font_size(render_priv,
- render_priv->state.font_size * render_priv->font_scale);
+ glyphs[text_info->length].font_size =
+ render_priv->state.font_size * render_priv->font_scale;
glyphs[text_info->length].be = render_priv->state.be;
glyphs[text_info->length].blur = render_priv->state.blur;
glyphs[text_info->length].shadow_x = render_priv->state.shadow_x;
glyphs[text_info->length].shadow_y = render_priv->state.shadow_y;
glyphs[text_info->length].scale_x= render_priv->state.scale_x;
glyphs[text_info->length].scale_y = render_priv->state.scale_y;
+ glyphs[text_info->length].border_style = render_priv->state.border_style;
glyphs[text_info->length].border_x= render_priv->state.border_x;
glyphs[text_info->length].border_y = render_priv->state.border_y;
+ glyphs[text_info->length].hspacing = render_priv->state.hspacing;
glyphs[text_info->length].bold = render_priv->state.bold;
glyphs[text_info->length].italic = render_priv->state.italic;
glyphs[text_info->length].flags = render_priv->state.flags;
@@ -1829,11 +1868,11 @@
}
// add horizontal letter spacing
- info->cluster_advance.x += double_to_d6(render_priv->state.hspacing *
+ info->cluster_advance.x += double_to_d6(info->hspacing *
render_priv->font_scale * info->scale_x);
// add displacement for vertical shearing
- info->cluster_advance.y += (info->fay * info->scale_y) * info->cluster_advance.x;
+ info->cluster_advance.y += (info->fay / info->scale_x * info->scale_y) * info->cluster_advance.x;
}
@@ -1906,6 +1945,7 @@
for (i = 0; i < text_info->length; i++) {
GlyphInfo *info = glyphs + cmap[i];
if (glyphs[i].linebreak) {
+ pen.y -= (info->fay / info->scale_x * info->scale_y) * pen.x;
pen.x = 0;
pen.y += double_to_d6(text_info->lines[lineno-1].desc);
pen.y += double_to_d6(text_info->lines[lineno].asc);
@@ -1995,16 +2035,25 @@
y2scr(render_priv, render_priv->track->PlayResY / 2.0);
device_y = scr_y - (bbox.yMax + bbox.yMin) / 2.0;
} else { // subtitle
- double scr_y;
+ double scr_top, scr_bottom, scr_y0;
if (valign != VALIGN_SUB)
ass_msg(render_priv->library, MSGL_V,
"Invalid valign, assuming 0 (subtitle)");
- scr_y =
+ scr_bottom =
y2scr_sub(render_priv,
render_priv->track->PlayResY - MarginV);
- device_y = scr_y;
+ scr_top = y2scr_top(render_priv, 0); //xxx not always 0?
+ device_y = scr_bottom + (scr_top - scr_bottom) *
+ render_priv->settings.line_position / 100.0;
device_y -= text_info->height;
device_y += text_info->lines[0].asc;
+ // clip to top to avoid confusion if line_position is very high,
+ // turning the subtitle into a toptitle
+ // also, don't change behavior if line_position is not used
+ scr_y0 = scr_top + text_info->lines[0].asc;
+ if (device_y < scr_y0 && render_priv->settings.line_position > 0) {
+ device_y = scr_y0;
+ }
}
} else if (render_priv->state.evt_type == EVENT_VSCROLL) {
if (render_priv->state.scroll_direction == SCROLL_TB)
@@ -2158,12 +2207,14 @@
ass_cache_empty(cache->composite_cache, 0);
ass_free_images(priv->prev_images_root);
priv->prev_images_root = 0;
+ priv->cache_cleared = 1;
}
if (ass_cache_empty(cache->outline_cache, cache->glyph_max)) {
ass_cache_empty(cache->bitmap_cache, 0);
ass_cache_empty(cache->composite_cache, 0);
ass_free_images(priv->prev_images_root);
priv->prev_images_root = 0;
+ priv->cache_cleared = 1;
}
}
@@ -2429,6 +2480,9 @@
ASS_Image *img, *img2;
int diff;
+ if (priv->cache_cleared)
+ return 2;
+
img = priv->prev_images_root;
img2 = priv->images_root;
diff = 0;
@@ -2474,8 +2528,12 @@
// init frame
rc = ass_start_frame(priv, track, now);
- if (rc != 0)
+ if (rc != 0) {
+ if (detect_change) {
+ *detect_change = 2;
+ }
return 0;
+ }
// render events separately
cnt = 0;
@@ -2525,6 +2583,7 @@
// free the previous image list
ass_free_images(priv->prev_images_root);
priv->prev_images_root = 0;
+ priv->cache_cleared = 0;
return priv->images_root;
}
Index: libass/ass_render.h
===================================================================
--- libass/ass_render.h (revision 35339)
+++ libass/ass_render.h (working copy)
@@ -67,6 +67,7 @@
int frame_height;
double font_size_coeff; // font size multiplier
double line_spacing; // additional line spacing (in frame pixels)
+ double line_position; // vertical position for subtitles, 0-100 (0 = no change)
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;
@@ -133,7 +134,9 @@
double frx, fry, frz; // rotation
double fax, fay; // text shearing
double scale_x, scale_y;
+ int border_style;
double border_x, border_y;
+ double hspacing;
unsigned italic;
unsigned bold;
int flags;
@@ -174,6 +177,7 @@
int flags; // decoration flags (underline/strike-through)
FT_Stroker stroker;
+ int stroker_radius; // last stroker radius, for caching stroker objects
int alignment; // alignment overrides go here; if zero, style value will be used
double frx, fry, frz;
double fax, fay; // text shearing
@@ -188,6 +192,7 @@
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
+ int border_style;
double border_x; // outline width
double border_y;
uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA
@@ -248,6 +253,7 @@
ASS_Image *images_root; // rendering result is stored here
ASS_Image *prev_images_root;
+ int cache_cleared;
EventImages *eimg; // temporary buffer for sorting rendered events
int eimg_size; // allocated buffer size
@@ -289,7 +295,7 @@
int ha, hb; // left and width
} Segment;
-void reset_render_context(ASS_Renderer *render_priv);
+void reset_render_context(ASS_Renderer *render_priv, ASS_Style *style);
void ass_free_images(ASS_Image *img);
// XXX: this is actually in ass.c, includes should be fixed later on
Index: libass/ass_render_api.c
===================================================================
--- libass/ass_render_api.c (revision 35339)
+++ libass/ass_render_api.c (working copy)
@@ -116,6 +116,14 @@
priv->settings.line_spacing = line_spacing;
}
+void ass_set_line_position(ASS_Renderer *priv, double line_position)
+{
+ if (priv->settings.line_position != line_position) {
+ priv->settings.line_position = line_position;
+ ass_reconfigure(priv);
+ }
+}
+
void ass_set_fonts(ASS_Renderer *priv, const char *default_font,
const char *default_family, int fc, const char *config,
int update)
Index: libass/ass_shaper.c
===================================================================
--- libass/ass_shaper.c (revision 35339)
+++ libass/ass_shaper.c (working copy)
@@ -401,7 +401,9 @@
font->faces[info->face_index], NULL);
}
- ass_face_set_size(font->faces[info->face_index], info->font_size);
+ // XXX: this is a rather crude hack
+ const double ft_size = 256.0;
+ ass_face_set_size(font->faces[info->face_index], ft_size);
update_hb_size(hb_fonts[info->face_index], font->faces[info->face_index]);
// update hash key for cached metrics
@@ -431,8 +433,8 @@
hb_buffer_t *buf;
hb_font_t *font;
} runs[MAX_RUNS];
+ const double ft_size = 256.0;
-
for (i = 0; i < len && run < MAX_RUNS; i++, run++) {
// get length and level of the current run
int k = i;
@@ -484,10 +486,10 @@
// set position and advance
info->skip = 0;
info->glyph_index = glyph_info[j].codepoint;
- info->offset.x = pos[j].x_offset * info->scale_x;
- info->offset.y = -pos[j].y_offset * info->scale_y;
- info->advance.x = pos[j].x_advance * info->scale_x;
- info->advance.y = -pos[j].y_advance * info->scale_y;
+ info->offset.x = pos[j].x_offset * info->scale_x * (info->font_size / ft_size);
+ info->offset.y = -pos[j].y_offset * info->scale_y * (info->font_size / ft_size);
+ info->advance.x = pos[j].x_advance * info->scale_x * (info->font_size / ft_size);
+ info->advance.y = -pos[j].y_advance * info->scale_y * (info->font_size / ft_size);
// accumulate advance in the root glyph
root->cluster_advance.x += info->advance.x;
@@ -602,6 +604,29 @@
}
/**
+ * \brief Remove all zero-width invisible characters from the text.
+ * \param text_info text
+ */
+static void ass_shaper_skip_characters(TextInfo *text_info)
+{
+ int i;
+ GlyphInfo *glyphs = text_info->glyphs;
+
+ for (i = 0; i < text_info->length; i++) {
+ // Skip direction override control characters
+ if ((glyphs[i].symbol <= 0x202e && glyphs[i].symbol >= 0x202a)
+ || (glyphs[i].symbol <= 0x200f && glyphs[i].symbol >= 0x200b)
+ || (glyphs[i].symbol <= 0x2063 && glyphs[i].symbol >= 0x2060)
+ || glyphs[i].symbol == 0xfeff
+ || glyphs[i].symbol == 0x00ad
+ || glyphs[i].symbol == 0x034f) {
+ glyphs[i].symbol = 0;
+ glyphs[i].skip++;
+ }
+ }
+}
+
+/**
* \brief Shape an event's text. Calculates directional runs and shapes them.
* \param text_info event's text
*/
@@ -639,27 +664,15 @@
#ifdef CONFIG_HARFBUZZ
switch (shaper->shaping_level) {
case ASS_SHAPING_SIMPLE:
- shape_fribidi(shaper, glyphs, text_info->length);
+ ass_shaper_skip_characters(text_info);
break;
case ASS_SHAPING_COMPLEX:
shape_harfbuzz(shaper, glyphs, text_info->length);
break;
}
#else
- shape_fribidi(shaper, glyphs, text_info->length);
+ ass_shaper_skip_characters(text_info);
#endif
-
-
- // clean up
- for (i = 0; i < text_info->length; i++) {
- // Skip direction override control characters
- // NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't
- // been implemented yet
- if (glyphs[i].symbol <= 0x202F && glyphs[i].symbol >= 0x202a) {
- glyphs[i].symbol = 0;
- glyphs[i].skip++;
- }
- }
#endif
}
@@ -733,17 +746,18 @@
}
/**
- * \brief Resolve a Windows font encoding number to a suitable
+ * \brief Resolve a Windows font charset number to a suitable
* base direction. 177 and 178 are Hebrew and Arabic respectively, and
- * they map to RTL. 1 is autodetection and is mapped to just that.
- * Everything else is mapped to LTR.
+ * they map to RTL. Everything else maps to LTR for compatibility
+ * reasons. The special value -1, which is not a legal Windows font charset
+ * number, can be used for autodetection.
* \param enc Windows font encoding
*/
FriBidiParType resolve_base_direction(int enc)
{
#ifdef CONFIG_FRIBIDI
switch (enc) {
- case 1:
+ case -1:
return FRIBIDI_PAR_ON;
case 177:
case 178:
Index: libass/ass_utils.c
===================================================================
--- libass/ass_utils.c (revision 35339)
+++ libass/ass_utils.c (working copy)
@@ -160,6 +160,30 @@
return c;
}
+/**
+ * \brief find style by name
+ * \param track track
+ * \param name style name
+ * \return index in track->styles
+ * Returnes 0 if no styles found => expects at least 1 style.
+ * Parsing code always adds "Default" style in the end.
+ */
+int lookup_style(ASS_Track *track, char *name)
+{
+ int i;
+ if (*name == '*')
+ ++name; // FIXME: what does '*' really mean ?
+ for (i = track->n_styles - 1; i >= 0; --i) {
+ if (strcmp(track->styles[i].Name, name) == 0)
+ return i;
+ }
+ i = track->default_style;
+ ass_msg(track->library, MSGL_WARN,
+ "[%p]: Warning: no style named '%s' found, using '%s'",
+ track, name, track->styles[i].Name);
+ return i; // use the first style
+}
+
#ifdef CONFIG_ENCA
void *ass_guess_buffer_cp(ASS_Library *library, unsigned char *buffer,
int buflen, char *preferred_language,
Index: libass/ass_utils.h
===================================================================
--- libass/ass_utils.h (revision 35339)
+++ libass/ass_utils.h (working copy)
@@ -51,6 +51,7 @@
char parse_bool(char *str);
unsigned ass_utf8_get_char(char **str);
void ass_msg(ASS_Library *priv, int lvl, char *fmt, ...);
+int lookup_style(ASS_Track *track, char *name);
#ifdef CONFIG_ENCA
void *ass_guess_buffer_cp(ASS_Library *library, unsigned char *buffer,
int buflen, char *preferred_language,
More information about the MPlayer-dev-eng
mailing list