Index: configure.ac
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/configure.ac,v
retrieving revision 1.637
diff -u -r1.637 configure.ac
--- configure.ac	9 May 2006 17:40:41 -0000	1.637
+++ configure.ac	13 May 2006 13:08:07 -0000
@@ -441,7 +441,7 @@
 dnl *** pango ***
 translit(dnm, m, l) AM_CONDITIONAL(USE_PANGO, true)
 GST_CHECK_FEATURE(PANGO, [pango], pango, [
-  PKG_CHECK_MODULES(PANGO, pango pangoft2,
+  PKG_CHECK_MODULES(PANGO, pango pangocairo,
       HAVE_PANGO="yes", HAVE_PANGO="no")
   AC_SUBST(PANGO_CFLAGS)
   AC_SUBST(PANGO_LIBS)
Index: ext/pango/gsttextoverlay.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ext/pango/gsttextoverlay.c,v
retrieving revision 1.42
diff -u -r1.42 gsttextoverlay.c
--- ext/pango/gsttextoverlay.c	9 May 2006 19:24:45 -0000	1.42
+++ ext/pango/gsttextoverlay.c	13 May 2006 13:08:07 -0000
@@ -2,6 +2,7 @@
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
  * Copyright (C) <2003> David Schleef <ds@schleef.org>
  * Copyright (C) <2006> Julien Moutte <julien@moutte.net>
+ * Copyright (C) <2006> Young-Ho Cha <ganadist@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -82,6 +83,7 @@
 #include "gsttimeoverlay.h"
 #include "gstclockoverlay.h"
 #include "gsttextrender.h"
+#include <string.h>
 
 /* FIXME:
  *  - use proper strides and offset for I420
@@ -290,6 +292,7 @@
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
+  PangoFontMap *fontmap;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
@@ -302,7 +305,9 @@
       GST_DEBUG_FUNCPTR (gst_text_overlay_change_state);
 
   klass->get_text = gst_text_overlay_get_text;
-  klass->pango_context = pango_ft2_get_context (72, 72);
+  fontmap = pango_cairo_font_map_get_default ();
+  klass->pango_context =
+      pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TEXT,
       g_param_spec_string ("text", "text",
@@ -362,7 +367,11 @@
   GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
 
   g_free (overlay->default_text);
-  g_free (overlay->bitmap.buffer);
+
+  if (overlay->text_image) {
+    g_free (overlay->text_image);
+    overlay->text_image = NULL;
+  }
 
   if (overlay->layout) {
     g_object_unref (overlay->layout);
@@ -437,7 +446,6 @@
   overlay->layout =
       pango_layout_new (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_context);
   pango_layout_set_alignment (overlay->layout, PANGO_ALIGN_CENTER);
-  memset (&overlay->bitmap, 0, sizeof (overlay->bitmap));
 
   overlay->halign = DEFAULT_PROP_HALIGNMENT;
   overlay->valign = DEFAULT_PROP_VALIGNMENT;
@@ -452,6 +460,7 @@
   overlay->shading_value = DEFAULT_SHADING_VALUE;
 
   overlay->default_text = g_strdup (DEFAULT_PROP_TEXT);
+  overlay->text_image = NULL;
   overlay->need_render = TRUE;
 
   overlay->fps_n = 0;
@@ -620,6 +629,8 @@
       if (desc) {
         GST_LOG_OBJECT (overlay, "font description set: %s", fontdesc_str);
         pango_layout_set_font_description (overlay->layout, desc);
+        overlay->font_size =
+            pango_font_description_get_size (desc) / PANGO_SCALE;
         pango_font_description_free (desc);
       } else {
         GST_WARNING_OBJECT (overlay, "font description parse failed: %s",
@@ -797,136 +808,193 @@
   }
 }
 
-/* FIXME:
- *  - use proper strides and offset for I420
- *  - don't draw over the edge of the picture (try a longer
- *    text with a huge font size)
- */
-
 static inline void
-gst_text_overlay_blit_yuv420 (GstTextOverlay * overlay, FT_Bitmap * bitmap,
-    guint8 * yuv_pixels, gint x0, gint y0)
+gst_text_overlay_blit_1 (GstTextOverlay * overlay, guchar * dest, gint xpos,
+    gint ypos, guchar * text_image, guint dest_stride)
 {
-  int y;                        /* text bitmap coordinates */
-  int x1, y1;                   /* video buffer coordinates */
-  int bit_rowinc, uv_rowinc;
-  guint8 *p, *bitp, *u_p;
-  int video_width, video_height;
-  int bitmap_x0 = 0;            //x0 < 1 ? -(x0 - 1) : 1;       /* 1 pixel border */
-  int bitmap_y0 = y0 < 1 ? -(y0 - 1) : 1;       /* 1 pixel border */
-  int bitmap_width = bitmap->width - bitmap_x0;
-  int bitmap_height = bitmap->rows - bitmap_y0;
-  int u_plane_size;
-  int skip_y, skip_x;
-  guint8 v;
-
-  video_width = I420_Y_ROWSTRIDE (overlay->width);
-  video_height = overlay->height;
-
-/*
-  if (x0 < 0 && abs (x0) < bitmap_width) {
-    bitmap_x0 = abs (x0);
-    x0 = 0;
-  }
-*/
-
-  if (x0 + bitmap_x0 + bitmap_width > overlay->width - 1)       /* 1 pixel border */
-    bitmap_width -= x0 + bitmap_x0 + bitmap_width - overlay->width + 1;
-  if (y0 + bitmap_y0 + bitmap_height > video_height - 1)        /* 1 pixel border */
-    bitmap_height -= y0 + bitmap_y0 + bitmap_height - video_height + 1;
-
-  uv_rowinc = video_width / 2 - bitmap_width / 2;
-  bit_rowinc = bitmap->pitch - bitmap_width;
-  u_plane_size = (video_width / 2) * (video_height / 2);
-
-  y1 = y0 + bitmap_y0;
-  x1 = x0 + bitmap_x0;
-  bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
-  for (y = bitmap_y0; y < bitmap_y0 + bitmap_height; y++) {
-    int n;
-
-    p = yuv_pixels + (y + y0) * I420_Y_ROWSTRIDE (overlay->width) + x1;
-    for (n = bitmap_width; n > 0; --n) {
-      v = *bitp;
-      if (v) {
-        p[-1] = CLAMP (p[-1] - v, 0, 255);
-        p[1] = CLAMP (p[1] - v, 0, 255);
-        p[-video_width] = CLAMP (p[-video_width] - v, 0, 255);
-        p[video_width] = CLAMP (p[video_width] - v, 0, 255);
-      }
-      p++;
-      bitp++;
+  gint i, j = 0;
+  gint x, y;
+  gint y0 = 0;
+  guchar r, g, b, a;
+  guchar *pimage;
+  guchar *py;
+  gint width = overlay->image_width;
+  gint height = overlay->image_height;
+
+  if (xpos < 0) {
+    xpos = 0;
+  }
+
+  if (xpos + width > overlay->width) {
+    width = overlay->width - xpos;
+  }
+
+  if (ypos + height > overlay->height) {
+    height = overlay->height - ypos;
+  }
+
+  for (i = 0; i < height; i++) {
+    pimage = text_image + 4 * (i * overlay->image_width);
+    py = dest + (i + y0) * dest_stride + xpos;
+    for (j = 0; j < width; j++) {
+      b = *pimage++;
+      g = *pimage++;
+      r = *pimage++;
+      a = *pimage++;
+      y = (int) (((19595 * r) >> 16) + ((38470 * g) >> 16) +
+          ((7471 * b) >> 16));
+      y = CLAMP (y, 0, 255);
+      x = *py;
+      *py++ = (y * a + x * (255 - a)) / 255;
     }
-    bitp += bit_rowinc;
   }
+}
 
-  y = bitmap_y0;
-  y1 = y0 + bitmap_y0;
-  x1 = x0 + bitmap_x0;
-  bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
-  p = yuv_pixels + video_width * y1 + x1;
-  u_p =
-      yuv_pixels + video_width * video_height + (video_width >> 1) * (y1 >> 1) +
-      (x1 >> 1);
-  skip_y = 0;
-  skip_x = 0;
-
-  for (; y < bitmap_y0 + bitmap_height; y++) {
-    int n;
-
-    x1 = x0 + bitmap_x0;
-    skip_x = 0;
-    for (n = bitmap_width; n > 0; --n) {
-      v = *bitp;
-      if (v) {
-        *p = v;
-        if (!skip_y) {
-          u_p[0] = u_p[u_plane_size] = 0x80;
-        }
-      }
-      if (!skip_y) {
-        skip_x = !skip_x;
-        if (!skip_x)
-          u_p++;
-      }
-      p++;
-      bitp++;
+static inline void
+gst_text_overlay_blit_sub2x2cbcr (GstTextOverlay * overlay,
+    guchar * destcb, guchar * destcr, gint xpos, gint ypos, guchar * text_image,
+    guint destcb_stride, guint destcr_stride)
+{
+  gint i, j;
+  gint x, cb, cr;
+  gint y0 = 0;
+  gushort r, g, b, a;
+  guchar *pimage1, *pimage2;
+  guchar *pcb, *pcr;
+  gint width = overlay->image_width - 2;
+  gint height = overlay->image_height - 2;
+
+  if (xpos < 0) {
+    xpos = 0;
+  }
+
+  if (xpos + width > overlay->width) {
+    width = overlay->width - xpos;
+  }
+
+  if (ypos + height > overlay->height) {
+    height = overlay->height - ypos;
+  }
+
+  for (i = 0; i < height; i += 2) {
+    pimage1 = text_image + 4 * (i * overlay->image_width);
+    pimage2 = pimage1 + 4 * overlay->image_width;
+    pcb = destcb + (i / 2 + y0) * destcb_stride + xpos / 2;
+    pcr = destcr + (i / 2 + y0) * destcr_stride + xpos / 2;
+    for (j = 0; j < width; j += 2) {
+      b = *pimage1++;
+      g = *pimage1++;
+      r = *pimage1++;
+      a = *pimage1++;
+
+      b += *pimage1++;
+      g += *pimage1++;
+      r += *pimage1++;
+      a += *pimage1++;
+
+      b += *pimage2++;
+      g += *pimage2++;
+      r += *pimage2++;
+      a += *pimage2++;
+
+      b += *pimage2++ + 2;
+      g += *pimage2++ + 2;
+      r += *pimage2++ + 2;
+      a += *pimage2++ + 2;
+
+      b /= 4;
+      g /= 4;
+      r /= 4;
+      a /= 4;
+
+      cb = (int) (-((11059 * r) >> 16) - ((21709 * g) >> 16) +
+          ((32768 * b) >> 16) + 128);
+      cb = CLAMP (cb, 0, 255);
+
+      cr = (int) (((32768 * r) >> 16) - ((27439 * g) >> 16) -
+          ((5329 * b) >> 16) + 128);
+      cr = CLAMP (cr, 0, 255);
+
+      x = *pcb;
+      *pcb++ = (cb * a + x * (255 - a)) / 255;
+
+      x = *pcr;
+      *pcr++ = (cr * a + x * (255 - a)) / 255;
     }
-    /*if (!skip_x && !skip_y) u_p--; */
-    p += I420_Y_ROWSTRIDE (overlay->width) - bitmap_width;
-    bitp += bit_rowinc;
-    skip_y = !skip_y;
-    u_p += skip_y ? uv_rowinc : 0;
   }
 }
 
 static void
-gst_text_overlay_resize_bitmap (GstTextOverlay * overlay, gint width,
-    gint height)
+gst_text_overlay_render_pangocairo (GstTextOverlay * overlay, gint width,
+    gint height, const gchar * string, gint textlen)
 {
-  FT_Bitmap *bitmap = &overlay->bitmap;
-  int pitch = (width | 3) + 1;
-  int size = pitch * height;
-
-  /* no need to keep reallocating; just keep the maximum size so far */
-  if (size <= overlay->bitmap_buffer_size) {
-    bitmap->rows = height;
-    bitmap->width = width;
-    bitmap->pitch = pitch;
-    memset (bitmap->buffer, 0, overlay->bitmap_buffer_size);
-    return;
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  cairo_t *cr_shadow;
+  cairo_surface_t *surface_shadow;
+
+  /* add some margin for text shadow */
+  if (width)
+    width += overlay->font_size / 4;
+  if (height)
+    height += overlay->font_size / 4;
+
+  /* reassign pangolayout wrapping mode for setup center align */
+  if (width < overlay->width)
+    pango_layout_set_width (overlay->layout, -1);
+  else {
+    PangoRectangle ink_rect, logical_rect;
+    gst_text_overlay_update_wrap_mode (overlay);
+    pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect);
+    width = ink_rect.width;
+    height = ink_rect.height + ink_rect.y;
   }
-  if (!bitmap->buffer) {
-    /* initialize */
-    bitmap->pixel_mode = ft_pixel_mode_grays;
-    bitmap->num_grays = 256;
-  }
-  overlay->bitmap_buffer_size = size;
-  bitmap->buffer = g_realloc (bitmap->buffer, size);
-  memset (bitmap->buffer, 0, size);
-  bitmap->rows = height;
-  bitmap->width = width;
-  bitmap->pitch = pitch;
+  /* set text on pango layout */
+  pango_layout_set_markup (overlay->layout, string, textlen);
+
+  /* clear shadow surface */
+  surface_shadow = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+  cr_shadow = cairo_create (surface_shadow);
+
+  cairo_set_source_rgba (cr_shadow, 0.0, 0.0, 0.0, 0.0);
+  cairo_set_operator (cr_shadow, CAIRO_OPERATOR_CLEAR);
+  cairo_paint (cr_shadow);
+  cairo_set_operator (cr_shadow, CAIRO_OPERATOR_OVER);
+
+  /* set shadow color */
+  cairo_set_source_rgb (cr_shadow, 0.0, 0.0, 0.0);
+
+  /* draw text shadow */
+  pango_cairo_update_layout (cr_shadow, overlay->layout);
+  pango_cairo_show_layout (cr_shadow, overlay->layout);
+  cairo_destroy (cr_shadow);
+
+  /* clear image surface */
+  overlay->text_image = g_realloc (overlay->text_image, 4 * width * height);
+  memset (overlay->text_image, 0, 4 * width * height);
+
+  surface = cairo_image_surface_create_for_data (overlay->text_image,
+      CAIRO_FORMAT_ARGB32, width, height, width * 4);
+  cr = cairo_create (surface);
+
+  /* set default color */
+  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+
+  /* draw text */
+  pango_cairo_update_layout (cr, overlay->layout);
+  pango_cairo_show_layout (cr, overlay->layout);
+
+  /* composite shadow with offset */
+  cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
+  cairo_set_source_surface (cr, surface_shadow, overlay->font_size / 20.0,
+      overlay->font_size / 20.0);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+  cairo_surface_destroy (surface_shadow);
+  cairo_surface_destroy (surface);
+  overlay->image_width = width;
+  overlay->image_height = height;
 }
 
 static void
@@ -960,9 +1028,8 @@
   pango_layout_set_markup (overlay->layout, string, textlen);
 
   pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect);
-  gst_text_overlay_resize_bitmap (overlay, ink_rect.width,
-      ink_rect.height + ink_rect.y);
-  pango_ft2_render_layout (&overlay->bitmap, overlay->layout, -ink_rect.x, 0);
+  gst_text_overlay_render_pangocairo (overlay, ink_rect.width,
+      ink_rect.height + ink_rect.y, string, textlen);
   overlay->baseline_y = ink_rect.y;
 
   g_free (string);
@@ -974,18 +1041,21 @@
 gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
 {
   gint xpos, ypos;
+  gint width, height;
+  guchar *y, *u, *v;
 
-  video_frame = gst_buffer_make_writable (video_frame);
+  width = overlay->image_width;
+  height = overlay->image_height;
 
   switch (overlay->halign) {
     case GST_TEXT_OVERLAY_HALIGN_LEFT:
       xpos = overlay->xpad;
       break;
     case GST_TEXT_OVERLAY_HALIGN_CENTER:
-      xpos = (overlay->width - overlay->bitmap.width) / 2;
+      xpos = (overlay->width - width) / 2;
       break;
     case GST_TEXT_OVERLAY_HALIGN_RIGHT:
-      xpos = overlay->width - overlay->bitmap.width - overlay->xpad;
+      xpos = overlay->width - width - overlay->xpad;
       break;
     default:
       xpos = 0;
@@ -995,10 +1065,10 @@
 
   switch (overlay->valign) {
     case GST_TEXT_OVERLAY_VALIGN_BOTTOM:
-      ypos = overlay->height - overlay->bitmap.rows - overlay->ypad;
+      ypos = overlay->height - height - overlay->ypad;
       break;
     case GST_TEXT_OVERLAY_VALIGN_BASELINE:
-      ypos = overlay->height - (overlay->bitmap.rows + overlay->ypad);
+      ypos = overlay->height - (height + overlay->ypad);
       break;
     case GST_TEXT_OVERLAY_VALIGN_TOP:
       ypos = overlay->ypad;
@@ -1009,18 +1079,30 @@
   }
   ypos += overlay->deltay;
 
+  if (ypos < 0)
+    ypos = 0;
+
+  y = GST_BUFFER_DATA (video_frame);
+  u = y + I420_U_OFFSET (overlay->width, overlay->height);
+  v = y + I420_V_OFFSET (overlay->width, overlay->height);
+
   /* shaded background box */
   if (overlay->want_shading) {
     gst_text_overlay_shade_y (overlay,
-        GST_BUFFER_DATA (video_frame),
-        I420_Y_ROWSTRIDE (overlay->width),
-        xpos, xpos + overlay->bitmap.width, ypos, ypos + overlay->bitmap.rows);
+        y, I420_Y_ROWSTRIDE (overlay->width),
+        xpos, xpos + width, ypos, ypos + height);
   }
 
-
-  if (overlay->bitmap.buffer) {
-    gst_text_overlay_blit_yuv420 (overlay, &overlay->bitmap,
-        GST_BUFFER_DATA (video_frame), xpos, ypos);
+  /* blit text on video image */
+  if (overlay->text_image) {
+    gst_text_overlay_blit_1 (overlay,
+        y + (ypos / 1) * I420_Y_ROWSTRIDE (overlay->width), xpos, ypos,
+        overlay->text_image, I420_Y_ROWSTRIDE (overlay->width));
+    gst_text_overlay_blit_sub2x2cbcr (overlay,
+        u + (ypos / 2) * I420_U_ROWSTRIDE (overlay->width),
+        v + (ypos / 2) * I420_V_ROWSTRIDE (overlay->width), xpos, ypos,
+        overlay->text_image, I420_U_ROWSTRIDE (overlay->width),
+        I420_V_ROWSTRIDE (overlay->width));
   }
 
   return gst_pad_push (overlay->srcpad, video_frame);
Index: ext/pango/gsttextoverlay.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ext/pango/gsttextoverlay.h,v
retrieving revision 1.12
diff -u -r1.12 gsttextoverlay.h
--- ext/pango/gsttextoverlay.h	7 Mar 2006 15:08:15 -0000	1.12
+++ ext/pango/gsttextoverlay.h	13 May 2006 13:08:07 -0000
@@ -2,7 +2,7 @@
 #define __GST_TEXT_OVERLAY_H__
 
 #include <gst/gst.h>
-#include <pango/pangoft2.h>
+#include <pango/pangocairo.h>
 
 G_BEGIN_DECLS
 
@@ -102,8 +102,10 @@
     gboolean                 want_shading;
 
     PangoLayout             *layout;
-    FT_Bitmap                bitmap;
-    gint                     bitmap_buffer_size;
+    gint                     font_size;
+    guchar                  *text_image;
+    gint                     image_width;
+    gint                     image_height;
     gint                     baseline_y;
 
     gboolean                 need_render;
Index: ext/pango/gsttextrender.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ext/pango/gsttextrender.c,v
retrieving revision 1.8
diff -u -r1.8 gsttextrender.c
--- ext/pango/gsttextrender.c	28 Apr 2006 19:46:35 -0000	1.8
+++ ext/pango/gsttextrender.c	13 May 2006 13:08:07 -0000
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
  * Copyright (C) <2003> David Schleef <ds@schleef.org>
+ * Copyright (C) <2006> Young-Ho Cha <ganadist@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -50,6 +51,7 @@
 #include <gst/video/video.h>
 
 #include "gsttextrender.h"
+#include <string.h>
 
 GST_DEBUG_CATEGORY_EXTERN (pango_debug);
 #define GST_CAT_DEFAULT pango_debug
@@ -105,6 +107,7 @@
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
+  PangoFontMap *fontmap;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
@@ -114,57 +117,79 @@
   gobject_class->finalize = gst_text_render_finalize;
   gobject_class->set_property = gst_text_render_set_property;
 
-  klass->pango_context = pango_ft2_get_context (72, 72);
+  fontmap = pango_cairo_font_map_get_default ();
+  klass->pango_context =
+      pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FONT_DESC,
       g_param_spec_string ("font-desc", "font description",
-          "Pango font description of font "
-          "to be used for rendering. "
-          "See documentation of "
-          "pango_font_description_from_string"
+          "Pango font description of font " "to be used for rendering. "
+          "See documentation of " "pango_font_description_from_string"
           " for syntax.", "", G_PARAM_WRITABLE));
 }
 
 
 static void
-resize_bitmap (GstTextRender * render, gint width, gint height)
-{
-  FT_Bitmap *bitmap = &render->bitmap;
-  gint pitch = (width | 3) + 1;
-  gint size = pitch * height;
-
-  /* no need to keep reallocating; just keep the maximum size so far */
-  if (size <= render->bitmap_buffer_size) {
-    bitmap->rows = height;
-    bitmap->width = width;
-    bitmap->pitch = pitch;
-    memset (bitmap->buffer, 0, render->bitmap_buffer_size);
-    return;
-  }
-  if (!bitmap->buffer) {
-    /* initialize */
-    bitmap->pixel_mode = ft_pixel_mode_grays;
-    bitmap->num_grays = 256;
-  }
-  if (bitmap->buffer)
-    bitmap->buffer = g_realloc (bitmap->buffer, size);
-  else
-    bitmap->buffer = g_malloc (size);
-  bitmap->rows = height;
-  bitmap->width = width;
-  bitmap->pitch = pitch;
-  memset (bitmap->buffer, 0, size);
-  render->bitmap_buffer_size = size;
-}
-
-static void
-gst_text_render_render_text (GstTextRender * render)
+gst_text_render_render_pangocairo (GstTextRender * render)
 {
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  cairo_t *cr_shadow;
+  cairo_surface_t *surface_shadow;
+  gint width, height;
   PangoRectangle ink_rect, logical_rect;
 
   pango_layout_get_pixel_extents (render->layout, &ink_rect, &logical_rect);
-  resize_bitmap (render, ink_rect.width, ink_rect.height + ink_rect.y);
-  pango_ft2_render_layout (&render->bitmap, render->layout, -ink_rect.x, 0);
-  render->baseline_y = ink_rect.y;
+
+  width = ink_rect.width;
+  height = ink_rect.height + ink_rect.y;
+
+  /* add some space */
+  width += 10;
+
+  surface_shadow = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+  cr_shadow = cairo_create (surface_shadow);
+
+  /* clear shadow surface */
+  cairo_set_source_rgba (cr_shadow, 0.0, 0.0, 0.0, 0.0);
+  cairo_set_operator (cr_shadow, CAIRO_OPERATOR_CLEAR);
+  cairo_paint (cr_shadow);
+  cairo_set_operator (cr_shadow, CAIRO_OPERATOR_OVER);
+  cairo_save (cr_shadow);
+
+  /* set shadow color */
+  cairo_set_source_rgb (cr_shadow, 0.0, 0.0, 0.0);
+
+  /* draw text shadow */
+  pango_cairo_update_layout (cr_shadow, render->layout);
+  pango_cairo_show_layout (cr_shadow, render->layout);
+  cairo_restore (cr_shadow);
+  cairo_destroy (cr_shadow);
+
+  render->text_image = g_realloc (render->text_image, 4 * width * height);
+  memset (render->text_image, 0, 4 * width * height);
+
+  surface = cairo_image_surface_create_for_data (render->text_image,
+      CAIRO_FORMAT_ARGB32, width, height, width * 4);
+  cr = cairo_create (surface);
+
+  /* set default color */
+  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+  pango_cairo_update_layout (cr, render->layout);
+
+  /* draw text */
+  pango_cairo_show_layout (cr, render->layout);
+
+  /* composite shadow with offset */
+  cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
+  cairo_set_source_surface (cr, surface_shadow, render->font_size / 20.0,
+      render->font_size / 20.0);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+  cairo_surface_destroy (surface_shadow);
+  cairo_surface_destroy (surface);
+  render->image_width = width;
+  render->image_height = height;
 }
 
 static gboolean
@@ -181,7 +206,7 @@
 
   GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps);
 
-  if (width >= render->bitmap.width && height >= render->bitmap.rows) {
+  if (width >= render->image_width && height >= render->image_height) {
     render->width = width;
     render->height = height;
     ret = TRUE;
@@ -198,44 +223,48 @@
   GstStructure *s = gst_caps_get_structure (caps, 0);
 
   GST_DEBUG ("Fixating caps %" GST_PTR_FORMAT, caps);
-  gst_structure_fixate_field_nearest_int (s, "width", render->bitmap.width);
-  gst_structure_fixate_field_nearest_int (s, "height", render->bitmap.rows);
+  gst_structure_fixate_field_nearest_int (s, "width", render->image_width);
+  gst_structure_fixate_field_nearest_int (s, "height", render->image_height);
   GST_DEBUG ("Fixated to    %" GST_PTR_FORMAT, caps);
 
   gst_object_unref (render);
 }
 
 static void
-gst_text_renderer_bitmap_to_ayuv (GstTextRender * render, FT_Bitmap * bitmap,
-    guchar * pixbuf)
+gst_text_renderer_argb_to_ayuv (GstTextRender * render, guchar * pixbuf)
 {
   int y;                        /* text bitmap coordinates */
-  int rowinc, bit_rowinc;
+  int row_inc;
   guchar *p, *bitp;
-  guchar v;
-
-  rowinc = render->width - bitmap->width;
-  bit_rowinc = bitmap->pitch - bitmap->width;
+  guchar a, r, g, b;
+  int width, height;
 
-  bitp = bitmap->buffer;
+  width = render->image_width;
+  height = render->image_height;
+  bitp = render->text_image;
   p = pixbuf;
 
-  for (y = 0; y < bitmap->rows; y++) {
+  row_inc = render->width - width;
+  if (row_inc < 0)
+    row_inc = 0;
+
+  for (y = 0; y < height; y++) {
     int n;
 
-    for (n = bitmap->width; n > 0; --n) {
-      v = *bitp;
-      if (v) {
-        p[0] = v;
-        p[1] = 255;
-        p[2] = 0x80;
-        p[3] = 0x80;
-      }
-      p += 4;
-      bitp++;
+    for (n = 0; n < width; n++) {
+      b = *bitp++;
+      g = *bitp++;
+      r = *bitp++;
+      a = *bitp++;
+
+      *p++ = a;
+      *p++ = CLAMP ((int) (((19595 * r) >> 16) + ((38470 * g) >> 16) +
+              ((7471 * b) >> 16)), 0, 255);
+      *p++ = CLAMP ((int) (-((11059 * r) >> 16) - ((21709 * g) >> 16) +
+              ((32768 * b) >> 16) + 128), 0, 255);
+      *p++ = CLAMP ((int) (((32768 * r) >> 16) - ((27439 * g) >> 16) -
+              ((5329 * b) >> 16) + 128), 0, 255);
     }
-    p += rowinc * 4;
-    bitp += bit_rowinc;
   }
 }
 
@@ -249,7 +278,6 @@
   GstCaps *caps = NULL;
   guint8 *data = GST_BUFFER_DATA (inbuf);
   guint size = GST_BUFFER_SIZE (inbuf);
-  gint n;
 
   render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
 
@@ -260,14 +288,19 @@
     size--;
   }
 
+  if (size == 0) {
+    size = 1;
+    data = (guint8 *) " ";
+  }
+
   /* render text */
   GST_DEBUG ("rendering '%*s'", size, data);
   pango_layout_set_markup (render->layout, (gchar *) data, size);
-  gst_text_render_render_text (render);
+  gst_text_render_render_pangocairo (render);
 
   caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC,
       GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), "width", G_TYPE_INT,
-      render->bitmap.width, "height", G_TYPE_INT, render->bitmap.rows,
+      render->image_width, "height", G_TYPE_INT, render->image_height,
       "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
 
   if (!gst_pad_set_caps (render->srcpad, caps)) {
@@ -289,14 +322,8 @@
   gst_buffer_stamp (outbuf, inbuf);
   data = GST_BUFFER_DATA (outbuf);
 
-  for (n = 0; n < render->width * render->height; n++) {
-    data[n * 4] = 0;
-    data[n * 4 + 1] = 0;
-    data[n * 4 + 2] = data[n * 4 + 3] = 128;
-  }
-
-  if (render->bitmap.buffer) {
-    gst_text_renderer_bitmap_to_ayuv (render, &render->bitmap, data);
+  if (render->text_image) {
+    gst_text_renderer_argb_to_ayuv (render, data);
   }
 
   ret = gst_pad_push (render->srcpad, outbuf);
@@ -314,7 +341,10 @@
 {
   GstTextRender *render = GST_TEXT_RENDER (object);
 
-  g_free (render->bitmap.buffer);
+  if (render->text_image) {
+    g_free (render->text_image);
+    render->text_image = NULL;
+  }
 
   if (render->layout)
     g_object_unref (render->layout);
@@ -347,7 +377,8 @@
 
   render->layout =
       pango_layout_new (GST_TEXT_RENDER_GET_CLASS (render)->pango_context);
-  memset (&render->bitmap, 0, sizeof (render->bitmap));
+  pango_layout_set_width (render->layout, -1);
+  pango_layout_set_alignment (render->layout, PANGO_ALIGN_CENTER);
 }
 
 static void
@@ -366,8 +397,10 @@
         GST_LOG ("font description set: %s", g_value_get_string (value));
         GST_OBJECT_LOCK (render);
         pango_layout_set_font_description (render->layout, desc);
+        render->font_size =
+            pango_font_description_get_size (desc) / PANGO_SCALE;
         pango_font_description_free (desc);
-        gst_text_render_render_text (render);
+        gst_text_render_render_pangocairo (render);
         GST_OBJECT_UNLOCK (render);
       } else {
         GST_WARNING ("font description parse failed: %s",
Index: ext/pango/gsttextrender.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ext/pango/gsttextrender.h,v
retrieving revision 1.4
diff -u -r1.4 gsttextrender.h
--- ext/pango/gsttextrender.h	8 Apr 2006 18:09:17 -0000	1.4
+++ ext/pango/gsttextrender.h	13 May 2006 13:08:07 -0000
@@ -2,7 +2,7 @@
 #define __GST_TEXT_RENDER_H__
 
 #include <gst/gst.h>
-#include <pango/pangoft2.h>
+#include <pango/pangocairo.h>
 
 G_BEGIN_DECLS
 
@@ -33,8 +33,10 @@
     gint                  width;
     gint                  height;
     PangoLayout          *layout;
-    FT_Bitmap             bitmap;
-    gint                  bitmap_buffer_size;
+    guint                 font_size;
+    guchar               *text_image;
+    gint                  image_width;
+    gint                  image_height;
     gint                  baseline_y;
 };
 
