miracle part 1
[melted] / mlt / src / modules / gtk2 / producer_pango.c
index 85b7b39..c1bf1d3 100644 (file)
 #include <pango/pangoft2.h>
 #include <freetype/freetype.h>
 
+struct producer_pango_s
+{
+       struct mlt_producer_s parent;
+       int width;
+       int height;
+       uint8_t *image;
+       uint8_t *alpha;
+       int   fgcolor;
+       int   bgcolor;
+       int   align;
+       int   pad;
+       char *markup;
+       char *text;
+       char *font;
+};
+
 // special color type used by internal pango routines
 typedef struct
 {
@@ -36,7 +52,8 @@ typedef struct
 static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
 static void producer_close( mlt_producer parent );
 static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg );
-static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align );
+static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font,
+       rgba_color fg, rgba_color bg, int pad, int align );
 
 mlt_producer producer_pango_init( const char *markup )
 {
@@ -48,10 +65,27 @@ mlt_producer producer_pango_init( const char *markup )
                producer->get_frame = producer_get_frame;
                producer->close = producer_close;
 
-               this->markup = strdup( markup );
-               this->is_pal = 1;
+               // This is required to initialise gdk-pixbuf
                g_type_init();
 
+               // Get the properties interface
+               mlt_properties properties = mlt_producer_properties( &this->parent );
+
+               // Set the default properties
+               mlt_properties_set_int( properties, "video_standard", mlt_video_standard_pal );
+               mlt_properties_set_int( properties, "fgcolor", 0xffffffff );
+               mlt_properties_set_int( properties, "bgcolor", 0x00000000 );
+               mlt_properties_set_int( properties, "align", pango_align_left );
+               mlt_properties_set_int( properties, "pad", 0 );
+               mlt_properties_set( properties, "markup", ( char * ) ( markup == NULL ? "" : markup ) );
+               mlt_properties_set( properties, "text", "" );
+               mlt_properties_set( properties, "font", "Sans 48" );
+               mlt_properties_set_int( properties, "x", 0 );
+               mlt_properties_set_int( properties, "y", 0 );
+               mlt_properties_set_double( properties, "mix", 1.0 );
+
+               mlt_properties_set( properties, "resource", "pango" );
+
                return producer;
        }
        free( this );
@@ -110,44 +144,78 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        // Generate a frame
        *frame = mlt_frame_init( );
 
-       // Obtain properties of frame
+       // Obtain properties of frame and producer
        mlt_properties properties = mlt_frame_properties( *frame );
-
-    // optimization for subsequent iterations on single picture
-       if ( this->image != NULL )
+       mlt_properties producer_props = mlt_producer_properties( producer );
+       
+       // Get producer properties
+       int fg = mlt_properties_get_int( producer_props, "fgcolor" );
+       int bg = mlt_properties_get_int( producer_props, "bgcolor" );
+       int align = mlt_properties_get_int( producer_props, "align" );
+       int pad = mlt_properties_get_int( producer_props, "pad" );
+       char *markup = mlt_properties_get( producer_props, "markup" );
+       char *text = mlt_properties_get( producer_props, "text" );
+       char *font = mlt_properties_get( producer_props, "font" );
+
+       // See if any properties changed
+       int property_changed = ( fg != this->fgcolor );
+       property_changed = property_changed || ( bg != this->bgcolor );
+       property_changed = property_changed || ( align != this->align );
+       property_changed = property_changed || ( pad != this->pad );
+       property_changed = property_changed || ( markup && this->markup && strcmp( markup, this->markup ) );
+       property_changed = property_changed || ( text && this->text && strcmp( text, this->text ) );
+       property_changed = property_changed || ( font && this->font && strcmp( font, this->font ) );
+
+       // Save the properties for next comparison
+       this->fgcolor = fg;
+       this->bgcolor = bg;
+       this->align = align;
+       this->pad = pad;
+       if ( markup != NULL )
        {
-               // Set width/height
-               mlt_properties_set_int( properties, "width", this->width );
-               mlt_properties_set_int( properties, "height", this->height );
-
-               // if picture sequence pass the image and alpha data without destructor
-               mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL );
-               mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL );
-
-               // Set alpha mask call back
-        ( *frame )->get_alpha_mask = producer_get_alpha_mask;
-
-               // Stack the get image callback
-               mlt_frame_push_get_image( *frame, producer_get_image );
-
+               if ( this->markup != NULL )
+                       free( this->markup );
+               this->markup = strdup( markup );
        }
-       else
+       if ( text != NULL )
        {
-               // the following four will be replaced by properties
-               rgba_color fg = { 0xff, 0xff, 0xff, 0xff };
-               rgba_color bg = { 0, 0, 0, 0x7f };
-               int pad = 8;
-               int align = 0; /* left */
-               
+               if ( this->text != NULL )
+                       free( this->text );
+               this->text = strdup( text );
+       }
+       if ( font != NULL )
+       {
+               if ( this->font != NULL )
+                       free( this->font );
+               this->font = strdup( font );
+       }
+
+       if ( property_changed )
+       {
+               rgba_color fgcolor =
+               {
+                       ( fg & 0xff000000 ) >> 24,
+                       ( fg & 0x00ff0000 ) >> 16,
+                       ( fg & 0x0000ff00 ) >> 8,
+                       ( fg & 0x000000ff )
+               };
+               rgba_color bgcolor =
+               {
+                       ( bg & 0xff000000 ) >> 24,
+                       ( bg & 0x00ff0000 ) >> 16,
+                       ( bg & 0x0000ff00 ) >> 8,
+                       ( bg & 0x000000ff )
+               };
+
                // Render the title
-               pixbuf = pango_get_pixbuf( this->markup, fg, bg, pad, align );
+               pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align );
        }
 
        // If we have a pixbuf
        if ( pixbuf )
        {
                // Scale to adjust for sample aspect ratio
-               if ( this->is_pal )
+               if ( mlt_properties_get_int( properties, "video_standard" ) == mlt_video_standard_pal )
                {
                        GdkPixbuf *temp = pixbuf;
                        GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
@@ -197,23 +265,36 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
                // Finished with pixbuf now
                g_object_unref( pixbuf );
+               
+               // if single picture, reference the image and alpha in the producer
+               if ( this->image != NULL )
+                       free( this->image );
+               this->image = image;
+               if ( this->alpha != NULL )
+                       free( this->alpha );
+               this->alpha = alpha;
 
-               // Set width/height of frame
+       }
+
+       if ( this->image != NULL )
+       {
+               // Set width/height
                mlt_properties_set_int( properties, "width", this->width );
                mlt_properties_set_int( properties, "height", this->height );
 
-               // if single picture, reference the image and alpha in the producer
-               this->image = image;
-               this->alpha = alpha;
+               // Set the compositing properties
+               mlt_properties_set_int( properties, "x", mlt_properties_get_int( producer_props, "x" ) );
+               mlt_properties_set_int( properties, "y", mlt_properties_get_int( producer_props, "y" ) );
+               mlt_properties_set_double( properties, "mix",  mlt_properties_get_double( producer_props, "mix" ) );
 
-               // pass the image and alpha data without destructor
-               mlt_properties_set_data( properties, "image", image, 0, NULL, NULL );
-               mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL );
+               // if picture sequence pass the image and alpha data without destructor
+               mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL );
+               mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL );
 
-               // Set alpha call back
+               // Set alpha mask call back
                ( *frame )->get_alpha_mask = producer_get_alpha_mask;
 
-               // Push the get_image method
+               // Stack the get image callback
                mlt_frame_push_get_image( *frame, producer_get_image );
        }
 
@@ -229,12 +310,16 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 static void producer_close( mlt_producer parent )
 {
        producer_pango this = parent->child;
-       if ( this->markup )
-               free( this->markup );
-       if ( this->image )
+       if ( this->image != NULL )
                free( this->image );
-       if ( this->alpha )
+       if ( this->alpha != NULL )
                free( this->alpha );
+       if ( this->markup != NULL )
+               free( this->markup );
+       if ( this->text != NULL )
+               free( this->text );
+       if ( this->font != NULL )
+               free( this->font );
        parent->close = NULL;
        mlt_producer_close( parent );
        free( this );
@@ -259,12 +344,11 @@ static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg )
        }
 }
 
-static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align )
+static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, rgba_color fg, rgba_color bg, int pad, int align )
 {
        PangoFT2FontMap *fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new();
        PangoContext *context = pango_ft2_font_map_create_context( fontmap );
        PangoLayout *layout = pango_layout_new( context );
-//     PangoFontDescription *font;
        int w, h, x;
        int i, j;
        GdkPixbuf *pixbuf = NULL;
@@ -275,10 +359,15 @@ static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_colo
 
        pango_ft2_font_map_set_resolution( fontmap, 72, 72 );
        pango_layout_set_width( layout, -1 ); // set wrapping constraints
-//     pango_layout_set_font_description( layout, "Sans 48" );
+       pango_layout_set_font_description( layout, pango_font_description_from_string( font ) );
 //     pango_layout_set_spacing( layout, space );
        pango_layout_set_alignment( layout, ( PangoAlignment ) align  );
-       pango_layout_set_markup( layout, markup, (markup == NULL ? 0 : strlen( markup ) ) );
+       if ( markup != NULL && strcmp( markup, "" ) != 0 )
+               pango_layout_set_markup( layout, markup, strlen( markup ) );
+       else if ( text != NULL && strcmp( text, "" ) != 0 )
+               pango_layout_set_text( layout, text, strlen( text ) );
+       else
+               return NULL;
        pango_layout_get_pixel_size( layout, &w, &h );
 
        pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE /* has alpha */, 8, w + 2 * pad, h + 2 * pad );