summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-03-14 23:52:45 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-03-14 23:52:45 +0200
commitae2faad6669c313b7a5dd318baeee0bffdd47031 (patch)
tree0b383b5dde56d54be4b144e7e23e96bd8bdd43cf /libass
parentb93f4b7bba0e31d157b74685d3166f74a6c244d7 (diff)
parent642162c07460e439d1d81cda4643dc028ed238e0 (diff)
downloadmpv-ae2faad6669c313b7a5dd318baeee0bffdd47031.tar.bz2
mpv-ae2faad6669c313b7a5dd318baeee0bffdd47031.tar.xz
Merge svn changes up to r28951
Diffstat (limited to 'libass')
-rw-r--r--libass/ass.c1
-rw-r--r--libass/ass_cache.c2
-rw-r--r--libass/ass_font.c3
-rw-r--r--libass/ass_font.h1
-rw-r--r--libass/ass_fontconfig.c79
-rw-r--r--libass/ass_fontconfig.h2
-rw-r--r--libass/ass_mp.c1
-rw-r--r--libass/ass_render.c167
-rw-r--r--libass/ass_types.h1
9 files changed, 123 insertions, 134 deletions
diff --git a/libass/ass.c b/libass/ass.c
index 612c8d6aae..b0c38c2ce4 100644
--- a/libass/ass.c
+++ b/libass/ass.c
@@ -1128,6 +1128,7 @@ long long ass_step_sub(ass_track_t* track, long long now, int movement) {
ass_track_t* ass_new_track(ass_library_t* library) {
ass_track_t* track = calloc(1, sizeof(ass_track_t));
track->library = library;
+ track->ScaledBorderAndShadow = 1;
track->parser_priv = calloc(1, sizeof(parser_priv_t));
return track;
}
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index 8b9926915f..2c8ee26f85 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -192,6 +192,8 @@ static int font_compare(void* key1, void* key2, size_t key_size) {
return 0;
if (a->italic != b->italic)
return 0;
+ if (a->treat_family_as_pattern != b->treat_family_as_pattern)
+ return 0;
return 1;
}
diff --git a/libass/ass_font.c b/libass/ass_font.c
index f2214a345d..579e658f14 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -125,7 +125,7 @@ static int add_face(void* fc_priv, ass_font_t* font, uint32_t ch)
if (font->n_faces == ASS_FONT_MAX_FACES)
return -1;
- path = fontconfig_select(fc_priv, font->desc.family, font->desc.bold,
+ path = fontconfig_select(fc_priv, font->desc.family, font->desc.treat_family_as_pattern, font->desc.bold,
font->desc.italic, &index, ch);
mem_idx = find_font(font->library, path);
@@ -169,6 +169,7 @@ ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_
font.ftlibrary = ftlibrary;
font.n_faces = 0;
font.desc.family = strdup(desc->family);
+ font.desc.treat_family_as_pattern = desc->treat_family_as_pattern;
font.desc.bold = desc->bold;
font.desc.italic = desc->italic;
diff --git a/libass/ass_font.h b/libass/ass_font.h
index 03396a6f21..520431821b 100644
--- a/libass/ass_font.h
+++ b/libass/ass_font.h
@@ -33,6 +33,7 @@ typedef struct ass_font_desc_s {
char* family;
unsigned bold;
unsigned italic;
+ int treat_family_as_pattern;
} ass_font_desc_t;
#define ASS_FONT_MAX_FACES 10
diff --git a/libass/ass_fontconfig.c b/libass/ass_fontconfig.c
index 9a7bddecc4..d0042dcdfd 100644
--- a/libass/ass_fontconfig.c
+++ b/libass/ass_fontconfig.c
@@ -66,14 +66,15 @@ struct fc_instance_s {
* \brief Low-level font selection.
* \param priv private data
* \param family font family
+ * \param treat_family_as_pattern treat family as fontconfig pattern
* \param bold font weight value
* \param italic font slant value
* \param index out: font index inside a file
* \param code: the character that should be present in the font, can be 0
* \return font file path
*/
-static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index,
- uint32_t code)
+static char* _select_font(fc_instance_t* priv, const char* family, int treat_family_as_pattern,
+ unsigned bold, unsigned italic, int* index, uint32_t code)
{
FcBool rc;
FcResult result;
@@ -89,34 +90,40 @@ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold
*index = 0;
- pat = FcPatternCreate();
+ if (treat_family_as_pattern)
+ pat = FcNameParse((const FcChar8*)family);
+ else
+ pat = FcPatternCreate();
+
if (!pat)
goto error;
- FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)family);
-
- // In SSA/ASS fonts are sometimes referenced by their "full name",
- // which is usually a concatenation of family name and font
- // style (ex. Ottawa Bold). Full name is available from
- // FontConfig pattern element FC_FULLNAME, but it is never
- // used for font matching.
- // Therefore, I'm removing words from the end of the name one
- // by one, and adding shortened names to the pattern. It seems
- // that the first value (full name in this case) has
- // precedence in matching.
- // An alternative approach could be to reimplement FcFontSort
- // using FC_FULLNAME instead of FC_FAMILY.
- family_cnt = 1;
- {
- char* s = strdup(family);
- char* p = s + strlen(s);
- while (--p > s)
- if (*p == ' ' || *p == '-') {
- *p = '\0';
- FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)s);
- ++ family_cnt;
- }
- free(s);
+ if (!treat_family_as_pattern) {
+ FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)family);
+
+ // In SSA/ASS fonts are sometimes referenced by their "full name",
+ // which is usually a concatenation of family name and font
+ // style (ex. Ottawa Bold). Full name is available from
+ // FontConfig pattern element FC_FULLNAME, but it is never
+ // used for font matching.
+ // Therefore, I'm removing words from the end of the name one
+ // by one, and adding shortened names to the pattern. It seems
+ // that the first value (full name in this case) has
+ // precedence in matching.
+ // An alternative approach could be to reimplement FcFontSort
+ // using FC_FULLNAME instead of FC_FAMILY.
+ family_cnt = 1;
+ {
+ char* s = strdup(family);
+ char* p = s + strlen(s);
+ while (--p > s)
+ if (*p == ' ' || *p == '-') {
+ *p = '\0';
+ FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)s);
+ ++ family_cnt;
+ }
+ free(s);
+ }
}
FcPatternAddBool(pat, FC_OUTLINE, FcTrue);
FcPatternAddInteger(pat, FC_SLANT, italic);
@@ -182,7 +189,8 @@ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold
if (result != FcResultMatch)
r_fullname = NULL;
- if (!(r_family && strcasecmp((const char*)r_family, family) == 0) &&
+ if (!treat_family_as_pattern &&
+ !(r_family && strcasecmp((const char*)r_family, family) == 0) &&
!(r_fullname && strcasecmp((const char*)r_fullname, family) == 0))
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne,
(const char*)(r_fullname ? r_fullname : r_family), family);
@@ -219,14 +227,15 @@ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold
* \brief Find a font. Use default family or path if necessary.
* \param priv_ private data
* \param family font family
+ * \param treat_family_as_pattern treat family as fontconfig pattern
* \param bold font weight value
* \param italic font slant value
* \param index out: font index inside a file
* \param code: the character that should be present in the font, can be 0
* \return font file path
*/
-char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index,
- uint32_t code)
+char* fontconfig_select(fc_instance_t* priv, const char* family, int treat_family_as_pattern,
+ unsigned bold, unsigned italic, int* index, uint32_t code)
{
char* res = 0;
if (!priv->config) {
@@ -234,9 +243,9 @@ char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold,
return priv->path_default;
}
if (family && *family)
- res = _select_font(priv, family, bold, italic, index, code);
+ res = _select_font(priv, family, treat_family_as_pattern, bold, italic, index, code);
if (!res && priv->family_default) {
- res = _select_font(priv, priv->family_default, bold, italic, index, code);
+ res = _select_font(priv, priv->family_default, 0, bold, italic, index, code);
if (res)
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingDefaultFontFamily,
family, bold, italic, res, *index);
@@ -248,7 +257,7 @@ char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold,
family, bold, italic, res, *index);
}
if (!res) {
- res = _select_font(priv, "Arial", bold, italic, index, code);
+ res = _select_font(priv, "Arial", 0, bold, italic, index, code);
if (res)
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingArialFontFamily,
family, bold, italic, res, *index);
@@ -474,8 +483,8 @@ exit:
#else /* CONFIG_FONTCONFIG */
-char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index,
- uint32_t code)
+char* fontconfig_select(fc_instance_t* priv, const char* family, int treat_family_as_pattern,
+ unsigned bold, unsigned italic, int* index, uint32_t code)
{
*index = priv->index_default;
return priv->path_default;
diff --git a/libass/ass_fontconfig.h b/libass/ass_fontconfig.h
index e9a1ce1567..77806909cf 100644
--- a/libass/ass_fontconfig.h
+++ b/libass/ass_fontconfig.h
@@ -35,7 +35,7 @@
typedef struct fc_instance_s fc_instance_t;
fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path, int fc);
-char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index, uint32_t code);
+char* fontconfig_select(fc_instance_t* priv, const char* family, int treat_family_as_pattern, unsigned bold, unsigned italic, int* index, uint32_t code);
void fontconfig_done(fc_instance_t* priv);
#endif /* LIBASS_FONTCONFIG_H */
diff --git a/libass/ass_mp.c b/libass/ass_mp.c
index 40da63c348..7e25b8e316 100644
--- a/libass/ass_mp.c
+++ b/libass/ass_mp.c
@@ -94,6 +94,7 @@ ass_track_t* ass_default_track(ass_library_t* library) {
style = track->styles + sid;
style->Name = strdup("Default");
style->FontName = (font_fontconfig >= 0 && sub_font_name) ? strdup(sub_font_name) : (font_fontconfig >= 0 && font_name) ? strdup(font_name) : strdup("Sans");
+ style->treat_fontname_as_pattern = 1;
fs = track->PlayResY * text_font_scale_factor / 100.;
// approximate autoscale coefficients
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 5eb28ccff0..e52195e023 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -184,6 +184,7 @@ typedef struct render_context_s {
char* family;
unsigned bold;
unsigned italic;
+ int treat_family_as_pattern;
} render_context_t;
@@ -423,10 +424,12 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_h
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;
@@ -434,6 +437,9 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_h
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;
@@ -441,12 +447,12 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_h
bottom = ((ay+ah) < (by+bh)) ? (ay+ah) : (by+bh);
if ((right <= left) || (bottom <= top))
return;
- old_left = left-(ax);
- old_top = top-(ay);
+ old_left = left-ax;
+ old_top = top-ay;
w = right-left;
h = bottom-top;
- cur_left = left-(bx);
- cur_top = top-(by);
+ cur_left = left-bx;
+ cur_top = top-by;
// Query cache
memcpy(&hk.a, last_hash, sizeof(*last_hash));
@@ -469,16 +475,16 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_h
// Allocate new bitmaps and copy over data
a = (*last_tail)->bitmap;
b = (*tail)->bitmap;
- (*last_tail)->bitmap = malloc(aw*ah);
- (*tail)->bitmap = malloc(bw*bh);
- memcpy((*last_tail)->bitmap, a, aw*ah);
- memcpy((*tail)->bitmap, b, bw*bh);
+ (*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)*(aw) + (old_left+x);
- cpos = (cur_top+y)*(bw) + (cur_left+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;
@@ -671,6 +677,7 @@ static void update_font(void)
ass_renderer_t* priv = frame_context.ass_priv;
ass_font_desc_t desc;
desc.family = strdup(render_context.family);
+ desc.treat_family_as_pattern = render_context.treat_family_as_pattern;
val = render_context.bold;
// 0 = normal, 1 = bold, >1 = exact weight
@@ -1062,10 +1069,12 @@ static char* parse_tag(char* p, double pwr) {
skip(')');
mp_msg(MSGT_ASS, MSGL_DBG2, "org(%d, %d)\n", v1, v2);
// render_context.evt_type = EVENT_POSITIONED;
- render_context.org_x = v1;
- render_context.org_y = v2;
- render_context.have_origin = 1;
- render_context.detect_collisions = 0;
+ if (!render_context.have_origin) {
+ render_context.org_x = v1;
+ render_context.org_y = v2;
+ render_context.have_origin = 1;
+ render_context.detect_collisions = 0;
+ }
} else if (mystrcmp(&p, "t")) {
double v[3];
int v1, v2;
@@ -1355,6 +1364,7 @@ static void reset_render_context(void)
if (render_context.family)
free(render_context.family);
render_context.family = strdup(render_context.style->FontName);
+ render_context.treat_family_as_pattern = render_context.style->treat_fontname_as_pattern;
render_context.bold = render_context.style->Bold;
render_context.italic = render_context.style->Italic;
update_font();
@@ -1797,75 +1807,46 @@ static void get_base_point(FT_BBox bbox, int alignment, int* bx, int* by)
}
/**
- * \brief Multiply 4-vector by 4-matrix
- * \param a 4-vector
- * \param m 4-matrix]
- * \param b out: 4-vector
- * Calculates a * m and stores result in b
+ * \brief Apply transformation to outline points of a glyph
+ * Applies rotations given by frx, fry and frz and projects the points back
+ * onto the screen plane.
*/
-static inline void transform_point_3d(double *a, double *m, double *b)
-{
- b[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + a[3] * m[12];
- b[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + a[3] * m[13];
- b[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + a[3] * m[14];
- b[3] = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + a[3] * m[15];
-}
-
-/**
- * \brief Apply 3d transformation to a vector
- * \param v FreeType vector (2d)
- * \param m 4-matrix
- * Transforms v by m, projects the result back to the screen plane
- * Result is returned in v.
- */
-static inline void transform_vector_3d(FT_Vector* v, double *m) {
- const double camera = 2500 * frame_context.border_scale; // camera distance
- const double cutoff_z = 10.;
- double a[4], b[4];
- a[0] = d6_to_double(v->x);
- a[1] = d6_to_double(v->y);
- a[2] = 0.;
- a[3] = 1.;
- transform_point_3d(a, m, b);
- /* Apply perspective projection with the following matrix:
- 2500 0 0 0
- 0 2500 0 0
- 0 0 0 0
- 0 0 8 2500
- where 2500 is camera distance, 8 - z-axis scale.
- Camera is always located in (org_x, org_y, -2500). This means
- that different subtitle events can be displayed at the same time
- using different cameras. */
- b[0] *= camera;
- b[1] *= camera;
- b[3] = 8 * b[2] + camera;
- if (b[3] < cutoff_z)
- b[3] = cutoff_z;
- v->x = double_to_d6(b[0] / b[3]);
- v->y = double_to_d6(b[1] / b[3]);
-}
-
-/**
- * \brief Apply 3d transformation to a glyph
- * \param glyph FreeType glyph
- * \param m 4-matrix
- * Transforms glyph by m, projects the result back to the screen plane
- * Result is returned in glyph.
- */
-static inline void transform_glyph_3d(FT_Glyph glyph, double *m, FT_Vector shift) {
- int i;
- FT_Outline* outline = &((FT_OutlineGlyph)glyph)->outline;
+static void transform_3d_points(FT_Vector shift, FT_Glyph glyph, double frx, double fry, double frz) {
+ double sx = sin(frx);
+ double sy = sin(fry);
+ double sz = sin(frz);
+ double cx = cos(frx);
+ double cy = cos(fry);
+ double cz = cos(frz);
+ FT_Outline *outline = &((FT_OutlineGlyph) glyph)->outline;
FT_Vector* p = outline->points;
+ double x, y, z, xx, yy, zz;
+ int i;
for (i=0; i<outline->n_points; i++) {
- p[i].x += shift.x;
- p[i].y += shift.y;
- transform_vector_3d(p + i, m);
- p[i].x -= shift.x;
- p[i].y -= shift.y;
- }
+ x = p[i].x + shift.x;
+ y = p[i].y + shift.y;
+ z = 0.;
+
+ xx = x*cz + y*sz;
+ yy = -(x*sz - y*cz);
+ zz = z;
- //transform_vector_3d(&glyph->advance, m);
+ x = xx;
+ y = yy*cx + zz*sx;
+ z = yy*sx - zz*cx;
+
+ xx = x*cy + z*sy;
+ yy = y;
+ zz = x*sy - z*cy;
+
+ zz = FFMAX(zz, -19000);
+
+ x = (xx * 20000) / (zz + 20000);
+ y = (yy * 20000) / (zz + 20000);
+ p[i].x = x - shift.x + 0.5;
+ p[i].y = y - shift.y + 0.5;
+ }
}
/**
@@ -1880,28 +1861,18 @@ static inline void transform_glyph_3d(FT_Glyph glyph, double *m, FT_Vector shift
*/
static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, double frx, double fry, double frz)
{
- fry = - fry; // FreeType's y axis goes in the opposite direction
+ frx = - frx;
+ frz = - frz;
if (frx != 0. || fry != 0. || frz != 0.) {
- double m[16];
- double sx = sin(frx);
- double sy = sin(fry);
- double sz = sin(frz);
- double cx = cos(frx);
- double cy = cos(fry);
- double cz = cos(frz);
- m[0] = cy * cz; m[1] = cy*sz; m[2] = -sy; m[3] = 0.0;
- m[4] = -cx*sz + sx*sy*cz; m[5] = cx*cz + sx*sy*sz; m[6] = sx*cy; m[7] = 0.0;
- m[8] = sx*sz + cx*sy*cz; m[9] = -sx*cz + cx*sy*sz; m[10] = cx*cy; m[11] = 0.0;
- m[12] = 0.0; m[13] = 0.0; m[14] = 0.0; m[15] = 1.0;
-
if (glyph && *glyph)
- transform_glyph_3d(*glyph, m, shift);
+ transform_3d_points(shift, *glyph, frx, fry, frz);
if (glyph2 && *glyph2)
- transform_glyph_3d(*glyph2, m, shift);
+ transform_3d_points(shift, *glyph2, frx, fry, frz);
}
}
+
/**
* \brief Main ass rendering function, glues everything together
* \param event event to render
@@ -2145,11 +2116,11 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
}
// fix clip coordinates (they depend on alignment)
- render_context.clip_x0 = x2scr(render_context.clip_x0);
- render_context.clip_x1 = x2scr(render_context.clip_x1);
if (render_context.evt_type == EVENT_NORMAL ||
render_context.evt_type == EVENT_HSCROLL ||
render_context.evt_type == EVENT_VSCROLL) {
+ render_context.clip_x0 = x2scr(render_context.clip_x0);
+ render_context.clip_x1 = x2scr(render_context.clip_x1);
if (valign == VALIGN_TOP) {
render_context.clip_y0 = y2scr_top(render_context.clip_y0);
render_context.clip_y1 = y2scr_top(render_context.clip_y1);
@@ -2161,8 +2132,10 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
render_context.clip_y1 = y2scr_sub(render_context.clip_y1);
}
} else if (render_context.evt_type == EVENT_POSITIONED) {
- render_context.clip_y0 = y2scr(render_context.clip_y0);
- render_context.clip_y1 = y2scr(render_context.clip_y1);
+ render_context.clip_x0 = x2scr_pos(render_context.clip_x0);
+ render_context.clip_x1 = x2scr_pos(render_context.clip_x1);
+ render_context.clip_y0 = y2scr_pos(render_context.clip_y0);
+ render_context.clip_y1 = y2scr_pos(render_context.clip_y1);
}
// calculate rotation parameters
diff --git a/libass/ass_types.h b/libass/ass_types.h
index 52aff0fb85..01c36c5748 100644
--- a/libass/ass_types.h
+++ b/libass/ass_types.h
@@ -58,6 +58,7 @@ typedef struct ass_style_s {
int MarginV;
// int AlphaLevel;
int Encoding;
+ int treat_fontname_as_pattern;
} ass_style_t;
typedef struct render_priv_s render_priv_t;