summaryrefslogtreecommitdiffstats
path: root/libass/ass_font.c
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@hein>2009-07-07 20:25:55 +0200
committerGrigori Goronzy <greg@blackbox>2009-07-07 23:07:50 +0200
commitf54a0cf94853d8372225bb0b45d6bd2b8e4e6fde (patch)
tree9c0e3b14e8ecf6e8cc1fe3f2107aad94d134cdd4 /libass/ass_font.c
parent5a2b270b218a429763f0a032386705f55bca0a92 (diff)
downloadlibass-f54a0cf94853d8372225bb0b45d6bd2b8e4e6fde.tar.bz2
libass-f54a0cf94853d8372225bb0b45d6bd2b8e4e6fde.tar.xz
Support for underline and strikethrough
Add support for the underline (\u) and strikethrough/strikeout (\s) properties. This is a bit tricky, since FreeType doesn't offer any method of adding the lines, so you have to draw them yourself. libass uses various information from TrueType tables to get position and size of the lines, does a few simple consistency checks (some fonts might be broken) and if everything is alright, adds new contours for the lines. Sometimes, rendering errors can occur: - Currently, kerning isn't taken into account, which means the lines can overlap a little, leading to small optical glitches. - Some (broken) fonts use the wrong winding direction. In this case, the FreeType stroker will only consider the added lines to be "outside" and only stroke the line instead of the whole glyph.
Diffstat (limited to 'libass/ass_font.c')
-rw-r--r--libass/ass_font.c86
1 files changed, 85 insertions, 1 deletions
diff --git a/libass/ass_font.c b/libass/ass_font.c
index 52e6d3a..0aeeec6 100644
--- a/libass/ass_font.c
+++ b/libass/ass_font.c
@@ -276,12 +276,93 @@ void ass_font_get_asc_desc(ass_font_t *font, uint32_t ch, int *asc,
*asc = *desc = 0;
}
+/*
+ * Strike a glyph with a horizontal line; it's possible to underline it
+ * and/or strike through it. For the line's position and size, truetype
+ * tables are consulted. Obviously this relies on the data in the tables
+ * being accurate.
+ *
+ */
+static int ass_strike_outline_glyph(FT_Face face, ass_font_t *font,
+ FT_Glyph glyph, int under, int through)
+{
+ TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+ TT_Postscript *ps = FT_Get_Sfnt_Table(face, ft_sfnt_post);
+ FT_Outline *ol = &((FT_OutlineGlyph) glyph)->outline;
+ int bear, advance, y_scale, i;
+
+ // Grow outline
+ i = (under ? 4 : 0) + (through ? 4 : 0);
+ ol->points = realloc(ol->points, sizeof(FT_Vector) *
+ (ol->n_points + i));
+ ol->tags = realloc(ol->tags, ol->n_points + i);
+ i = !!under + !!through;
+ ol->contours = realloc(ol->contours, sizeof(short) *
+ (ol->n_contours + i));
+
+ // If the bearing is negative, the glyph starts left of the current
+ // pen position
+ bear = FFMIN(face->glyph->metrics.horiBearingX, 0);
+ // We're adding half a pixel to avoid small gaps
+ advance = d16_to_d6(glyph->advance.x) + 32;
+ y_scale = face->size->metrics.y_scale;
+
+ // Add points to the outline
+ if (under) {
+ int pos, size;
+ pos = FT_MulFix(ps->underlinePosition, y_scale * font->scale_y);
+ size = FT_MulFix(ps->underlineThickness,
+ y_scale * font->scale_y / 2);
+
+ if (pos > 0 || size <= 0)
+ return 0;
+
+ FT_Vector points[4] = {
+ {.x = bear, .y = pos + size},
+ {.x = advance, .y = pos + size},
+ {.x = advance, .y = pos - size},
+ {.x = bear, .y = pos - size},
+ };
+
+ for (i = 0; i < 4; i++) {
+ ol->points[ol->n_points] = points[i];
+ ol->tags[ol->n_points++] = 1;
+ }
+ ol->contours[ol->n_contours++] = ol->n_points - 1;
+ }
+
+ if (through) {
+ int pos, size;
+ pos = FT_MulFix(os2->yStrikeoutPosition, y_scale * font->scale_y);
+ size = FT_MulFix(os2->yStrikeoutSize, y_scale * font->scale_y / 2);
+
+ if (pos < 0 || size <= 0)
+ return 0;
+
+ FT_Vector points[4] = {
+ {.x = bear, .y = pos + size},
+ {.x = advance, .y = pos + size},
+ {.x = advance, .y = pos - size},
+ {.x = bear, .y = pos - size},
+ };
+
+ for (i = 0; i < 4; i++) {
+ ol->points[ol->n_points] = points[i];
+ ol->tags[ol->n_points++] = 1;
+ }
+
+ ol->contours[ol->n_contours++] = ol->n_points - 1;
+ }
+
+ return 1;
+}
+
/**
* \brief Get a glyph
* \param ch character code
**/
FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ass_font_t *font,
- uint32_t ch, ass_hinting_t hinting)
+ uint32_t ch, ass_hinting_t hinting, int deco)
{
int error;
int index = 0;
@@ -356,6 +437,9 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ass_font_t *font,
return 0;
}
+ ass_strike_outline_glyph(face, font, glyph, deco & DECO_UNDERLINE,
+ deco & DECO_STRIKETHROUGH);
+
return glyph;
}