summaryrefslogtreecommitdiffstats
path: root/ext/cairo
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2004-12-28 05:52:03 +0000
committerDavid Schleef <ds@schleef.org>2004-12-28 05:52:03 +0000
commit3065ec53ca028e3dda508227ac38cfd50faec078 (patch)
treed63afd21456b75ee001fe7d1c50647d1970268c1 /ext/cairo
parent257f1aa294213ecb48addf25ae343819ea371683 (diff)
ext/cairo/gsttextoverlay.c: Improvements to actually render text as white on black outline on video, including font s...
Original commit message from CVS: * ext/cairo/gsttextoverlay.c: (gst_textoverlay_render_text), (gst_text_overlay_blit_1), (gst_text_overlay_blit_sub2x2), (gst_textoverlay_video_chain), (gst_textoverlay_loop), (gst_textoverlay_font_init), (gst_textoverlay_init), (gst_textoverlay_set_property): Improvements to actually render text as white on black outline on video, including font selection and horizontal/vertical alignment. (Ronald's christmas present) * ext/cairo/gsttextoverlay.h:
Diffstat (limited to 'ext/cairo')
-rw-r--r--ext/cairo/gsttextoverlay.c203
-rw-r--r--ext/cairo/gsttextoverlay.h8
2 files changed, 136 insertions, 75 deletions
diff --git a/ext/cairo/gsttextoverlay.c b/ext/cairo/gsttextoverlay.c
index 4ca302ee..b2c1e875 100644
--- a/ext/cairo/gsttextoverlay.c
+++ b/ext/cairo/gsttextoverlay.c
@@ -213,18 +213,22 @@ gst_textoverlay_render_text (GstTextOverlay * overlay, gchar * text,
{
cairo_text_extents_t extents;
char *string;
+ double x, y;
- string = g_strdup_printf ("%.*s", textlen, text);
+ string = g_strndup (text, textlen);
- if (overlay->pixbuf)
- g_free (overlay->pixbuf);
- overlay->pixbuf = g_malloc (4 * overlay->width * overlay->text_height);
- cairo_set_target_image (overlay->cr, overlay->pixbuf, CAIRO_FORMAT_ARGB32,
- overlay->width, overlay->text_height, overlay->width * 4);
+ if (overlay->text_fill_image)
+ g_free (overlay->text_fill_image);
+ overlay->text_fill_image =
+ g_malloc (4 * overlay->width * overlay->text_height);
+ cairo_set_target_image (overlay->cr, overlay->text_fill_image,
+ CAIRO_FORMAT_ARGB32, overlay->width, overlay->text_height,
+ overlay->width * 4);
cairo_save (overlay->cr);
cairo_rectangle (overlay->cr, 0, 0, overlay->width, overlay->text_height);
- cairo_set_alpha (overlay->cr, 0.0);
+ cairo_set_rgb_color (overlay->cr, 0, 0, 0);
+ cairo_set_alpha (overlay->cr, 1.0);
cairo_set_operator (overlay->cr, CAIRO_OPERATOR_SRC);
cairo_fill (overlay->cr);
cairo_restore (overlay->cr);
@@ -232,19 +236,51 @@ gst_textoverlay_render_text (GstTextOverlay * overlay, gchar * text,
cairo_save (overlay->cr);
cairo_text_extents (overlay->cr, string, &extents);
cairo_set_rgb_color (overlay->cr, 1, 1, 1);
- cairo_move_to (overlay->cr, 0, overlay->text_height - 2);
+ cairo_set_alpha (overlay->cr, 1.0);
+ switch (overlay->halign) {
+ case GST_TEXT_OVERLAY_HALIGN_LEFT:
+ x = overlay->x0;
+ break;
+ case GST_TEXT_OVERLAY_HALIGN_CENTER:
+ x = overlay->x0 - extents.width / 2;
+ break;
+ case GST_TEXT_OVERLAY_HALIGN_RIGHT:
+ x = overlay->x0 - extents.width;
+ break;
+ default:
+ x = 0;
+ }
+ y = overlay->text_height - 2;
+ cairo_move_to (overlay->cr, x, y);
cairo_show_text (overlay->cr, string);
+ cairo_restore (overlay->cr);
- cairo_text_path (overlay->cr, string);
+ if (overlay->text_outline_image)
+ g_free (overlay->text_outline_image);
+ overlay->text_outline_image =
+ g_malloc (4 * overlay->width * overlay->text_height);
+ cairo_set_target_image (overlay->cr, overlay->text_outline_image,
+ CAIRO_FORMAT_ARGB32, overlay->width, overlay->text_height,
+ overlay->width * 4);
+
+ cairo_save (overlay->cr);
+ cairo_rectangle (overlay->cr, 0, 0, overlay->width, overlay->text_height);
cairo_set_rgb_color (overlay->cr, 0, 0, 0);
+ cairo_set_alpha (overlay->cr, 1.0);
+ cairo_set_operator (overlay->cr, CAIRO_OPERATOR_SRC);
+ cairo_fill (overlay->cr);
+ cairo_restore (overlay->cr);
+
+ cairo_save (overlay->cr);
+ cairo_move_to (overlay->cr, x, y);
+ cairo_set_rgb_color (overlay->cr, 1, 1, 1);
+ cairo_set_alpha (overlay->cr, 1.0);
cairo_set_line_width (overlay->cr, 1.0);
+ cairo_text_path (overlay->cr, string);
cairo_stroke (overlay->cr);
-
- g_free (string);
-
cairo_restore (overlay->cr);
- overlay->text_width = MIN (extents.width, overlay->width);
+ g_free (string);
}
/* static GstPadLinkReturn */
@@ -272,36 +308,47 @@ gst_textoverlay_video_sinkconnect (GstPad * pad, const GstCaps * caps)
static void
-gst_text_overlay_blit_yuv420 (GstTextOverlay * overlay, guchar * pixbuf,
- int x0, int y0)
+gst_text_overlay_blit_1 (GstTextOverlay * overlay, guchar * dest,
+ guchar * text_image, int val)
{
int i;
int j;
int x, a, y;
+ int y0 = 0;
- if (x0 < 0)
- x0 = 0;
- if (y0 < 0)
- y0 = 0;
-
- GST_LOG ("%d %d %d %d %d %d %p", overlay->text_width, overlay->text_height,
- overlay->width, overlay->height, x0, y0, pixbuf);
+ y = val;
for (i = 0; i < overlay->text_height; i++) {
- for (j = 0; j < overlay->text_width; j++) {
-#if 0
- x = pixbuf[(i + y0) * overlay->width + (j + x0)];
- a = overlay->pixbuf[4 * (i * overlay->width + j) + 0];
- y = overlay->pixbuf[4 * (i * overlay->width + j) + 1];
- pixbuf[(i + y0) * overlay->width + (j + x0)] =
- (y * a + x * (255 - a)) / 255;
-#endif
- x = a = 0;
- y = overlay->pixbuf[4 * (i * overlay->width + j) + 1];
- pixbuf[(i + y0) * overlay->width + (j + x0)] = y;
+ for (j = 0; j < overlay->width; j++) {
+ x = dest[(i + y0) * overlay->width + j];
+ a = text_image[4 * (i * overlay->width + j) + 1];
+ dest[(i + y0) * overlay->width + j] = (y * a + x * (255 - a)) / 255;
}
}
+}
+static void
+gst_text_overlay_blit_sub2x2 (GstTextOverlay * overlay, guchar * dest,
+ guchar * text_image, int val)
+{
+ int i;
+ int j;
+ int x, a, y;
+ int y0 = 0;
+
+ y = val;
+
+ for (i = 0; i < overlay->text_height; i += 2) {
+ for (j = 0; j < overlay->width; j += 2) {
+ x = dest[(i / 2 + y0) * (overlay->width / 2) + j / 2];
+ a = (text_image[4 * (i * overlay->width + j) + 1] +
+ text_image[4 * (i * overlay->width + j + 1) + 1] +
+ text_image[4 * ((i + 1) * overlay->width + j) + 1] +
+ text_image[4 * ((i + 1) * overlay->width + j + 1) + 1] + 2) / 4;
+ dest[(i / 2 + y0) * (overlay->width / 2) + j / 2] =
+ (y * a + x * (255 - a)) / 255;
+ }
+ }
}
@@ -311,7 +358,7 @@ gst_textoverlay_video_chain (GstPad * pad, GstData * _data)
GstBuffer *buf = GST_BUFFER (_data);
GstTextOverlay *overlay;
guchar *pixbuf;
- gint x0, y0;
+ gint y;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
@@ -325,32 +372,38 @@ gst_textoverlay_video_chain (GstPad * pad, GstData * _data)
pixbuf = GST_BUFFER_DATA (buf);
- x0 = overlay->x0;
- y0 = overlay->y0;
+ y = overlay->y0;
switch (overlay->valign) {
case GST_TEXT_OVERLAY_VALIGN_BOTTOM:
- y0 -= overlay->text_height;
+ y -= overlay->text_height;
break;
case GST_TEXT_OVERLAY_VALIGN_BASELINE:
#define BASELINE 2
- y0 -= (overlay->text_height - BASELINE);
+ y -= (overlay->text_height - BASELINE);
break;
case GST_TEXT_OVERLAY_VALIGN_TOP:
break;
}
- switch (overlay->halign) {
- case GST_TEXT_OVERLAY_HALIGN_LEFT:
- break;
- case GST_TEXT_OVERLAY_HALIGN_RIGHT:
- x0 -= overlay->text_width;
- break;
- case GST_TEXT_OVERLAY_HALIGN_CENTER:
- x0 -= overlay->text_width;
- break;
- }
-
- gst_text_overlay_blit_yuv420 (overlay, pixbuf, x0, y0);
+ gst_text_overlay_blit_1 (overlay,
+ pixbuf + y * overlay->width, overlay->text_outline_image, 0);
+ gst_text_overlay_blit_sub2x2 (overlay,
+ pixbuf + (overlay->height * overlay->width) +
+ (y / 2) * overlay->width / 2, overlay->text_outline_image, 128);
+ gst_text_overlay_blit_sub2x2 (overlay, pixbuf +
+ (overlay->height * overlay->width) +
+ (overlay->height * overlay->width) / 4 + (y / 2) * overlay->width / 2,
+ overlay->text_outline_image, 128);
+
+ gst_text_overlay_blit_1 (overlay, pixbuf + y * overlay->width,
+ overlay->text_fill_image, 255);
+ gst_text_overlay_blit_sub2x2 (overlay,
+ pixbuf + (overlay->height * overlay->width) +
+ (y / 2) * overlay->width / 2, overlay->text_fill_image, 128);
+ gst_text_overlay_blit_sub2x2 (overlay,
+ pixbuf + (overlay->height * overlay->width) +
+ (overlay->height * overlay->width) / 4 + (y / 2) * overlay->width / 2,
+ overlay->text_fill_image, 128);
gst_pad_push (overlay->srcpad, GST_DATA (buf));
}
@@ -443,6 +496,22 @@ gst_textoverlay_loop (GstElement * element)
gst_textoverlay_video_chain (overlay->srcpad, GST_DATA (video_frame));
}
+static void
+gst_textoverlay_font_init (GstTextOverlay * overlay)
+{
+ cairo_font_extents_t font_extents;
+
+ cairo_select_font (overlay->cr, overlay->font, overlay->slant,
+ overlay->weight);
+ cairo_scale_font (overlay->cr, overlay->scale);
+
+ cairo_current_font_extents (overlay->cr, &font_extents);
+ overlay->text_height = font_extents.height;
+ if (overlay->text_height & 1)
+ overlay->text_height++;
+
+ overlay->need_render = TRUE;
+}
static GstElementStateReturn
gst_textoverlay_change_state (GstElement * element)
@@ -480,8 +549,6 @@ gst_textoverlay_finalize (GObject * object)
static void
gst_textoverlay_init (GstTextOverlay * overlay)
{
- cairo_font_extents_t font_extents;
-
/* video sink */
overlay->video_sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get
@@ -511,16 +578,15 @@ gst_textoverlay_init (GstTextOverlay * overlay)
overlay->default_text = g_strdup ("");
overlay->need_render = TRUE;
- cairo_select_font (overlay->cr, "sans", 0, 0);
- cairo_scale_font (overlay->cr, 50);
-
- cairo_current_font_extents (overlay->cr, &font_extents);
- overlay->text_height = font_extents.height;
+ overlay->font = g_strdup ("sans");
+ overlay->slant = CAIRO_FONT_SLANT_NORMAL;
+ overlay->weight = CAIRO_FONT_WEIGHT_NORMAL;
+ overlay->scale = 20;
+ gst_textoverlay_font_init (overlay);
gst_element_set_loop_function (GST_ELEMENT (overlay), gst_textoverlay_loop);
}
-
static void
gst_textoverlay_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@@ -551,6 +617,7 @@ gst_textoverlay_set_property (GObject * object, guint prop_id,
else
g_warning ("Invalid 'valign' property value: %s",
g_value_get_string (value));
+ overlay->need_render = TRUE;
break;
case ARG_HALIGN:
@@ -563,6 +630,7 @@ gst_textoverlay_set_property (GObject * object, guint prop_id,
else
g_warning ("Invalid 'halign' property value: %s",
g_value_get_string (value));
+ overlay->need_render = TRUE;
break;
case ARG_X0:
@@ -574,22 +642,11 @@ gst_textoverlay_set_property (GObject * object, guint prop_id,
break;
case ARG_FONT_DESC:
- {
-#if 0
- PangoFontDescription *desc;
-
- desc = pango_font_description_from_string (g_value_get_string (value));
- if (desc) {
- g_message ("font description set: %s", g_value_get_string (value));
- pango_layout_set_font_description (overlay->layout, desc);
- pango_font_description_free (desc);
- render_text (overlay);
- } else
- g_warning ("font description parse failed: %s",
- g_value_get_string (value));
-#endif
+ if (overlay->font)
+ g_free (overlay->font);
+ overlay->font = g_strdup (g_value_get_string (value));
+ gst_textoverlay_font_init (overlay);
break;
- }
default:
break;
diff --git a/ext/cairo/gsttextoverlay.h b/ext/cairo/gsttextoverlay.h
index ff539131..00862f78 100644
--- a/ext/cairo/gsttextoverlay.h
+++ b/ext/cairo/gsttextoverlay.h
@@ -54,14 +54,18 @@ struct _GstTextOverlay {
gchar *default_text;
cairo_t *cr;
- guchar *pixbuf;
- int text_width;
+ guchar *text_fill_image;
+ guchar *text_outline_image;
int text_height;
GstBuffer *current_buffer;
GstBuffer *next_buffer;
gboolean need_render;
+ gchar *font;
+ int slant;
+ int weight;
+ double scale;
};
struct _GstTextOverlayClass {