summaryrefslogtreecommitdiff
path: root/ext/ttml
diff options
context:
space:
mode:
authorChris Bass <floobleflam@gmail.com>2017-03-21 14:39:39 +0000
committerSebastian Dröge <sebastian@centricular.com>2017-04-09 10:42:08 +0300
commitce532ddcfd8aac684cd778c7300a68b0687498d1 (patch)
tree624b5835a75089bcbfa53fe0251a877cf755101e /ext/ttml
parentaec8406fd778ec109b9726b550028fe0b90a35e6 (diff)
downloadgstreamer-plugins-bad-ce532ddcfd8aac684cd778c7300a68b0687498d1.tar.gz
ttmlrender: extend UnifiedElement type to include font metrics
https://bugzilla.gnome.org/show_bug.cgi?id=780402
Diffstat (limited to 'ext/ttml')
-rw-r--r--ext/ttml/gstttmlrender.c123
1 files changed, 119 insertions, 4 deletions
diff --git a/ext/ttml/gstttmlrender.c b/ext/ttml/gstttmlrender.c
index d8e5f4798..da0922973 100644
--- a/ext/ttml/gstttmlrender.c
+++ b/ext/ttml/gstttmlrender.c
@@ -93,6 +93,14 @@ GST_STATIC_PAD_TEMPLATE ("text_sink",
#define GST_TTML_RENDER_SIGNAL(ov) (g_cond_signal (GST_TTML_RENDER_GET_COND (ov)))
#define GST_TTML_RENDER_BROADCAST(ov)(g_cond_broadcast (GST_TTML_RENDER_GET_COND (ov)))
+
+typedef struct
+{
+ guint height;
+ guint baseline;
+} FontMetrics;
+
+
static GstElementClass *parent_class = NULL;
static void gst_ttml_render_base_init (gpointer g_class);
static void gst_ttml_render_class_init (GstTtmlRenderClass * klass);
@@ -1240,9 +1248,14 @@ map_fail:
}
+/* @pango_font_size is the font size you would need to tell pango in order that
+ * the actual rendered height of @text matches the text height in @element's
+ * style set. */
typedef struct
{
GstSubtitleElement *element;
+ guint pango_font_size;
+ FontMetrics pango_font_metrics;
gchar *text;
} UnifiedElement;
@@ -1323,8 +1336,104 @@ gst_ttml_render_handle_whitespace (UnifiedBlock * block)
}
+/*
+ * Generates pango-markup'd version of @text that would make pango render it
+ * with the styling specified by @style_set.
+ */
+static gchar *
+gst_ttml_render_generate_pango_markup (GstSubtitleStyleSet * style_set,
+ guint font_height, const gchar * text)
+{
+ gchar *ret, *font_family, *font_size, *fgcolor;
+ const gchar *font_style, *font_weight, *underline;
+ gchar *escaped_text = g_markup_escape_text (text, -1);
+
+ fgcolor = gst_ttml_render_color_to_string (style_set->color);
+ font_size = g_strdup_printf ("%u", font_height);
+ font_family =
+ gst_ttml_render_resolve_generic_fontname (style_set->font_family);
+ if (!font_family)
+ font_family = g_strdup (style_set->font_family);
+ font_style = (style_set->font_style ==
+ GST_SUBTITLE_FONT_STYLE_NORMAL) ? "normal" : "italic";
+ font_weight = (style_set->font_weight ==
+ GST_SUBTITLE_FONT_WEIGHT_NORMAL) ? "normal" : "bold";
+ underline = (style_set->text_decoration ==
+ GST_SUBTITLE_TEXT_DECORATION_UNDERLINE) ? "single" : "none";
+
+ ret = g_strconcat ("<span "
+ "fgcolor=\"", fgcolor, "\" ",
+ "font=\"", font_size, "px\" ",
+ "font_family=\"", font_family, "\" ",
+ "font_style=\"", font_style, "\" ",
+ "font_weight=\"", font_weight, "\" ",
+ "underline=\"", underline, "\" ", ">", escaped_text, "</span>", NULL);
+
+ g_free (fgcolor);
+ g_free (font_family);
+ g_free (font_size);
+ g_free (escaped_text);
+ return ret;
+}
+
+
+/*
+ * Unfortunately, pango does not expose accurate metrics about fonts (their
+ * maximum height and baseline position), so we need to calculate this
+ * information ourselves by examining the ink rectangle of a string containing
+ * characters that extend to the maximum height/depth of the font.
+ */
+static FontMetrics
+gst_ttml_render_get_pango_font_metrics (GstTtmlRender * render,
+ GstSubtitleStyleSet * style_set, guint font_size)
+{
+ PangoRectangle ink_rect;
+ gchar *string;
+ FontMetrics ret;
+
+ string = gst_ttml_render_generate_pango_markup (style_set, font_size,
+ "Áĺľď¿gqy");
+ pango_layout_set_markup (render->layout, string, strlen (string));
+ pango_layout_get_pixel_extents (render->layout, &ink_rect, NULL);
+ g_free (string);
+
+ ret.height = ink_rect.height;
+ ret.baseline = PANGO_PIXELS (pango_layout_get_baseline (render->layout))
+ - ink_rect.y;
+ return ret;
+}
+
+
+/*
+ * Return the font size that you would need to pass to pango in order that the
+ * font applied to @element would be rendered at the text height applied to
+ * @element.
+ */
+static guint
+gst_ttml_render_get_pango_font_size (GstTtmlRender * render,
+ const GstSubtitleElement * element)
+{
+ guint desired_font_size =
+ (guint) ceil (element->style_set->font_size * render->height);
+ guint font_size = desired_font_size;
+ guint rendered_height = G_MAXUINT;
+ FontMetrics metrics;
+
+ while (rendered_height > desired_font_size) {
+ metrics =
+ gst_ttml_render_get_pango_font_metrics (render, element->style_set,
+ font_size);
+ rendered_height = metrics.height;
+ --font_size;
+ }
+
+ return font_size + 1;
+}
+
+
static UnifiedBlock *
-gst_ttml_render_unify_block (const GstSubtitleBlock * block, GstBuffer * buf)
+gst_ttml_render_unify_block (GstTtmlRender * render,
+ const GstSubtitleBlock * block, GstBuffer * buf)
{
UnifiedBlock *ret = g_slice_new0 (UnifiedBlock);
guint i;
@@ -1337,11 +1446,17 @@ gst_ttml_render_unify_block (const GstSubtitleBlock * block, GstBuffer * buf)
for (i = 0; i < gst_subtitle_block_get_element_count (block); ++i) {
gchar *text;
UnifiedElement *ue = g_slice_new0 (UnifiedElement);
-
- ue->element = gst_subtitle_block_get_element (block, i);
+ ue->element =
+ gst_subtitle_element_ref (gst_subtitle_block_get_element (block, i));
+ ue->pango_font_size =
+ gst_ttml_render_get_pango_font_size (render, ue->element);
+ ue->pango_font_metrics =
+ gst_ttml_render_get_pango_font_metrics (render, ue->element->style_set,
+ ue->pango_font_size);
ue->text =
gst_ttml_render_get_text_from_buffer (buf, ue->element->text_index);
g_ptr_array_add (ret->unified_elements, ue);
+
text = g_strjoin (NULL, ret->joined_text, ue->text, NULL);
g_free (ret->joined_text);
ret->joined_text = text;
@@ -1368,7 +1483,7 @@ gst_ttml_render_generate_marked_up_string (GstTtmlRender * render,
guint i;
joined_text = g_strdup ("");
- unified_block = gst_ttml_render_unify_block (block, text_buf);
+ unified_block = gst_ttml_render_unify_block (render, block, text_buf);
gst_ttml_render_handle_whitespace (unified_block);
for (i = 0; i < element_count; ++i) {