#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
{
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 )
+mlt_producer producer_pango_init( const char *filename )
{
producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 );
if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
producer->get_frame = producer_get_frame;
producer->close = producer_close;
- this->markup = strdup( markup );
+ // This is required to initialise gdk-pixbuf
g_type_init();
// Get the properties interface
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, "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 );
+
+ if ( filename == NULL )
+ {
+ mlt_properties_set( properties, "resource", "pango" );
+ mlt_properties_set( properties, "markup", "" );
+ }
+ else
+ {
+ FILE *f = fopen( filename, "r" );
+ if ( f != NULL )
+ {
+ char line[81];
+ char *markup = NULL;
+ size_t size = 0;
+ line[80] = '\0';
+
+ while ( fgets( line, 80, f ) )
+ {
+ size += strlen( line ) + 1;
+ if ( markup )
+ {
+ markup = realloc( markup, size );
+ strcat( markup, line );
+ }
+ else
+ {
+ markup = strdup( line );
+ }
+ }
+ fclose( f );
+ mlt_properties_set( properties, "resource", ( char * ) filename );
+ mlt_properties_set( properties, "markup", ( char * ) ( markup == NULL ? "" : markup ) );
+ if ( markup )
+ free( markup );
+ }
+ else
+ {
+ mlt_properties_set( properties, "resource", "pango" );
+ mlt_properties_set( properties, "markup", "" );
+ }
+ }
return producer;
}
// 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 )
+ {
+ 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 )
{
- // Obtain properties of producer
- mlt_properties props = mlt_producer_properties( producer );
-
- // Get properties
- int fg = mlt_properties_get_int( props, "fgcolor" );
- int bg = mlt_properties_get_int( props, "bgcolor" );
- int align = mlt_properties_get_int( props, "align" );
- int pad = mlt_properties_get_int( props, "pad" );
rgba_color fgcolor =
{
( fg & 0xff000000 ) >> 24,
( bg & 0x0000ff00 ) >> 8,
( bg & 0x000000ff )
};
-
+
// Render the title
- pixbuf = pango_get_pixbuf( this->markup, fgcolor, bgcolor, pad, align );
+ pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align );
}
// If we have a pixbuf
// 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
+ if ( mlt_properties_get( producer_props, "x" ) != NULL )
+ mlt_properties_set_int( properties, "x", mlt_properties_get_int( producer_props, "x" ) );
+ if ( mlt_properties_get( producer_props, "y" ) != NULL )
+ mlt_properties_set_int( properties, "y", mlt_properties_get_int( producer_props, "y" ) );
+ if ( mlt_properties_get( producer_props, "mix" ) != NULL )
+ mlt_properties_set_double( properties, "image.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, this->width * this->height * 2, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, 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 );
}
// Update timecode on the frame we're creating
- mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+ mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Calculate the next timecode
mlt_producer_prepare_next( producer );
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 );
}
}
-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;
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 );