summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@blackbox>2011-06-13 23:15:27 +0200
committerGrigori Goronzy <greg@blackbox>2011-06-13 23:17:28 +0200
commit2f9733ef09e6a6c57697c442e8a697728a25677c (patch)
tree9253933cdeb1d92273a6b560017852453795a4da
parent2c1c093253daf69b2244f654893456ff7f80fa27 (diff)
downloadlibass-2f9733ef09e6a6c57697c442e8a697728a25677c.tar.bz2
libass-2f9733ef09e6a6c57697c442e8a697728a25677c.tar.xz
Stroker: process outlines directly
-rw-r--r--libass/ass_font.c38
-rw-r--r--libass/ass_font.h2
-rw-r--r--libass/ass_render.c55
3 files changed, 54 insertions, 41 deletions
diff --git a/libass/ass_font.c b/libass/ass_font.c
index a80c0a0..7b55e81 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -606,9 +606,9 @@ static int get_contour_direction(FT_Vector *points, int start, int end)
* \brief Fix-up stroker result for huge borders by removing inside contours
* that would reverse in size
*/
-void fix_freetype_stroker(FT_OutlineGlyph glyph, int border_x, int border_y)
+void fix_freetype_stroker(FT_Outline *outline, int border_x, int border_y)
{
- int nc = glyph->outline.n_contours;
+ int nc = outline->n_contours;
int begin, stop;
char modified = 0;
char *valid_cont = malloc(nc);
@@ -618,14 +618,14 @@ void fix_freetype_stroker(FT_OutlineGlyph glyph, int border_x, int border_y)
int i, j;
int inside_direction;
- inside_direction = FT_Outline_Get_Orientation(&glyph->outline) ==
+ inside_direction = FT_Outline_Get_Orientation(outline) ==
FT_ORIENTATION_TRUETYPE;
// create a list of cboxes of the contours
for (i = 0; i < nc; i++) {
start = end + 1;
- end = glyph->outline.contours[i];
- get_contour_cbox(&boxes[i], glyph->outline.points, start, end);
+ end = outline->contours[i];
+ get_contour_cbox(&boxes[i], outline->points, start, end);
}
// for each contour, check direction and whether it's "outside"
@@ -633,8 +633,8 @@ void fix_freetype_stroker(FT_OutlineGlyph glyph, int border_x, int border_y)
end = -1;
for (i = 0; i < nc; i++) {
start = end + 1;
- end = glyph->outline.contours[i];
- int dir = get_contour_direction(glyph->outline.points, start, end);
+ end = outline->contours[i];
+ int dir = get_contour_direction(outline->points, start, end);
valid_cont[i] = 1;
if (dir == inside_direction) {
for (j = 0; j < nc; j++) {
@@ -650,19 +650,19 @@ void fix_freetype_stroker(FT_OutlineGlyph glyph, int border_x, int border_y)
* inside of - assume the font is buggy and it should be
* an "outside" contour, and reverse it */
for (j = 0; j < (end + 1 - start) / 2; j++) {
- FT_Vector temp = glyph->outline.points[start + j];
- char temp2 = glyph->outline.tags[start + j];
- glyph->outline.points[start + j] = glyph->outline.points[end - j];
- glyph->outline.points[end - j] = temp;
- glyph->outline.tags[start + j] = glyph->outline.tags[end - j];
- glyph->outline.tags[end - j] = temp2;
+ FT_Vector temp = outline->points[start + j];
+ char temp2 = outline->tags[start + j];
+ outline->points[start + j] = outline->points[end - j];
+ outline->points[end - j] = temp;
+ outline->tags[start + j] = outline->tags[end - j];
+ outline->tags[end - j] = temp2;
}
dir ^= 1;
}
check_inside:
if (dir == inside_direction) {
FT_BBox box;
- get_contour_cbox(&box, glyph->outline.points, start, end);
+ get_contour_cbox(&box, outline->points, start, end);
int width = box.xMax - box.xMin;
int height = box.yMax - box.yMin;
if (width < border_x * 2 || height < border_y * 2) {
@@ -677,12 +677,12 @@ void fix_freetype_stroker(FT_OutlineGlyph glyph, int border_x, int border_y)
for (i = 0; i < nc; i++) {
if (valid_cont[i])
continue;
- begin = (i == 0) ? 0 : glyph->outline.contours[i - 1] + 1;
- stop = glyph->outline.contours[i];
+ begin = (i == 0) ? 0 : outline->contours[i - 1] + 1;
+ stop = outline->contours[i];
for (j = begin; j <= stop; j++) {
- glyph->outline.points[j].x = 0;
- glyph->outline.points[j].y = 0;
- glyph->outline.tags[j] = 0;
+ outline->points[j].x = 0;
+ outline->points[j].y = 0;
+ outline->tags[j] = 0;
}
}
}
diff --git a/libass/ass_font.h b/libass/ass_font.h
index a0d6660..6f16821 100644
--- a/libass/ass_font.h
+++ b/libass/ass_font.h
@@ -62,6 +62,6 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ASS_Font *font,
uint32_t ch, ASS_Hinting hinting, int flags);
FT_Vector ass_font_get_kerning(ASS_Font *font, uint32_t c1, uint32_t c2);
void ass_font_free(ASS_Font *font);
-void fix_freetype_stroker(FT_OutlineGlyph glyph, int border_x, int border_y);
+void fix_freetype_stroker(FT_Outline *outline, int border_x, int border_y);
#endif /* LIBASS_FONT_H */
diff --git a/libass/ass_render.c b/libass/ass_render.c
index ef888ac..497d77e 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -955,40 +955,53 @@ static void draw_opaque_box(ASS_Renderer *render_priv, uint32_t ch,
* Stroke an outline glyph in x/y direction. Applies various fixups to get
* around limitations of the FreeType stroker.
*/
-static void stroke_outline_glyph(ASS_Renderer *render_priv,
- FT_OutlineGlyph *glyph, int sx, int sy)
+static void stroke_outline(ASS_Renderer *render_priv, FT_Outline *outline,
+ int sx, int sy)
{
if (sx <= 0 && sy <= 0)
return;
- fix_freetype_stroker(*glyph, sx, sy);
+ fix_freetype_stroker(outline, sx, sy);
// Borders are equal; use the regular stroker
if (sx == sy && render_priv->state.stroker) {
int error;
- error = FT_Glyph_StrokeBorder((FT_Glyph *) glyph,
- render_priv->state.stroker, 0, 1);
- if (error)
+ unsigned n_points, n_contours;
+
+ FT_StrokerBorder border = FT_Outline_GetOutsideBorder(outline);
+ error = FT_Stroker_ParseOutline(render_priv->state.stroker, outline, 0);
+ if (error) {
ass_msg(render_priv->library, MSGL_WARN,
- "FT_Glyph_Stroke error: %d", error);
+ "FT_Stroker_ParseOutline failed, error: %d", error);
+ }
+ error = FT_Stroker_GetBorderCounts(render_priv->state.stroker, border,
+ &n_points, &n_contours);
+ if (error) {
+ ass_msg(render_priv->library, MSGL_WARN,
+ "FT_Stroker_GetBorderCounts failed, error: %d", error);
+ }
+ FT_Outline_Done(render_priv->ftlibrary, outline);
+ FT_Outline_New(render_priv->ftlibrary, n_points, n_contours, outline);
+ outline->n_points = outline->n_contours = 0;
+ FT_Stroker_ExportBorder(render_priv->state.stroker, border, outline);
// "Stroke" with the outline emboldener in two passes.
// The outlines look uglier, but the emboldening never adds any points
} else {
int i;
- FT_Outline *ol = &(*glyph)->outline;
FT_Outline nol;
- FT_Outline_New(render_priv->ftlibrary, ol->n_points,
- ol->n_contours, &nol);
- FT_Outline_Copy(ol, &nol);
- FT_Outline_Embolden(ol, sx * 2);
- FT_Outline_Translate(ol, -sx, -sx);
+ FT_Outline_New(render_priv->ftlibrary, outline->n_points,
+ outline->n_contours, &nol);
+ FT_Outline_Copy(outline, &nol);
+
+ FT_Outline_Embolden(outline, sx * 2);
+ FT_Outline_Translate(outline, -sx, -sx);
FT_Outline_Embolden(&nol, sy * 2);
FT_Outline_Translate(&nol, -sy, -sy);
- for (i = 0; i < ol->n_points; i++)
- ol->points[i].y = nol.points[i].y;
+ for (i = 0; i < outline->n_points; i++)
+ outline->points[i].y = nol.points[i].y;
FT_Outline_Done(render_priv->ftlibrary, &nol);
}
@@ -1091,12 +1104,12 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
&& key.scale_x && key.scale_y) {
FT_Glyph_Copy(info->glyph, &info->outline_glyph);
- stroke_outline_glyph(render_priv,
- (FT_OutlineGlyph *) &info->outline_glyph,
- double_to_d6(render_priv->state.border_x *
- render_priv->border_scale),
- double_to_d6(render_priv->state.border_y *
- render_priv->border_scale));
+ stroke_outline(render_priv,
+ &((FT_OutlineGlyph) info->outline_glyph)->outline,
+ double_to_d6(render_priv->state.border_x *
+ render_priv->border_scale),
+ double_to_d6(render_priv->state.border_y *
+ render_priv->border_scale));
}
memset(&v, 0, sizeof(v));