mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 04:56:24 +00:00
ttmlrender: extend UnifiedElement type to include font metrics
https://bugzilla.gnome.org/show_bug.cgi?id=780402
This commit is contained in:
parent
aec8406fd7
commit
ce532ddcfd
1 changed files with 119 additions and 4 deletions
|
@ -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_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)))
|
#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 GstElementClass *parent_class = NULL;
|
||||||
static void gst_ttml_render_base_init (gpointer g_class);
|
static void gst_ttml_render_base_init (gpointer g_class);
|
||||||
static void gst_ttml_render_class_init (GstTtmlRenderClass * klass);
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
GstSubtitleElement *element;
|
GstSubtitleElement *element;
|
||||||
|
guint pango_font_size;
|
||||||
|
FontMetrics pango_font_metrics;
|
||||||
gchar *text;
|
gchar *text;
|
||||||
} UnifiedElement;
|
} 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 *
|
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);
|
UnifiedBlock *ret = g_slice_new0 (UnifiedBlock);
|
||||||
guint i;
|
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) {
|
for (i = 0; i < gst_subtitle_block_get_element_count (block); ++i) {
|
||||||
gchar *text;
|
gchar *text;
|
||||||
UnifiedElement *ue = g_slice_new0 (UnifiedElement);
|
UnifiedElement *ue = g_slice_new0 (UnifiedElement);
|
||||||
|
ue->element =
|
||||||
ue->element = gst_subtitle_block_get_element (block, i);
|
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 =
|
ue->text =
|
||||||
gst_ttml_render_get_text_from_buffer (buf, ue->element->text_index);
|
gst_ttml_render_get_text_from_buffer (buf, ue->element->text_index);
|
||||||
g_ptr_array_add (ret->unified_elements, ue);
|
g_ptr_array_add (ret->unified_elements, ue);
|
||||||
|
|
||||||
text = g_strjoin (NULL, ret->joined_text, ue->text, NULL);
|
text = g_strjoin (NULL, ret->joined_text, ue->text, NULL);
|
||||||
g_free (ret->joined_text);
|
g_free (ret->joined_text);
|
||||||
ret->joined_text = text;
|
ret->joined_text = text;
|
||||||
|
@ -1368,7 +1483,7 @@ gst_ttml_render_generate_marked_up_string (GstTtmlRender * render,
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
joined_text = g_strdup ("");
|
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);
|
gst_ttml_render_handle_whitespace (unified_block);
|
||||||
|
|
||||||
for (i = 0; i < element_count; ++i) {
|
for (i = 0; i < element_count; ++i) {
|
||||||
|
|
Loading…
Reference in a new issue