#include <QtGui/QTextCursor>
#include <QtGui/QStyleOptionGraphicsItem>
-static QApplication *app = NULL;
-
-extern "C"
-{
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_cache.h>
+#include <QtCore/QString>
- static QMutex g_mutex;
- void refresh_kdenlivetitle( mlt_producer producer, uint8_t* buffer, int width, int height , double position, int force_refresh )
- {
- drawKdenliveTitle( producer, buffer, width, height, position, force_refresh );
- }
-
- static void qscene_delete( void *data )
- {
- QGraphicsScene *scene = ( QGraphicsScene * )data;
- delete scene;
- scene = NULL;
- }
-}
+#include <QtXml/QDomElement>
+#include <QtCore/QRectF>
+#include <QtGui/QColor>
+#include <QtGui/QWidget>
+static QMutex g_mutex;
+static QApplication *app = NULL;
class ImageItem: public QGraphicsRectItem
{
{
m_img = img;
}
-
QImage m_img;
+
protected:
virtual void paint( QPainter *painter,
- const QStyleOptionGraphicsItem *option,
+ const QStyleOptionGraphicsItem * /*option*/,
QWidget* )
-{
- //todo: clip rect ?
- painter->drawImage(QPointF(), m_img);
- //painter->fillRect(option->exposedRect, QBrush(QColor(0,255,0)));
+{
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
+ painter->drawImage(QPoint(), m_img);
}
-
-
};
-void drawKdenliveTitle( mlt_producer producer, uint8_t * buffer, int width, int height, double position, int force_refresh )
+QString rectTransform( QString s, QTransform t )
{
-
- // restore QGraphicsScene
- g_mutex.lock();
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
- QGraphicsScene *scene = static_cast<QGraphicsScene *> (mlt_properties_get_data( producer_props, "qscene", NULL ));
+ QStringList l = s.split( ',' );
+ return QString::number(l.at(0).toDouble() * t.m11()) + ',' + QString::number(l.at(1).toDouble() * t.m22()) + ',' + QString::number(l.at(2).toDouble() * t.m11()) + ',' + QString::number(l.at(3).toDouble() * t.m22());
+}
- if ( force_refresh == 1 && scene )
- {
- scene = NULL;
- mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
- }
-
- if ( scene == NULL )
- {
- int argc = 1;
- char* argv[1];
- argv[0] = "xxx";
- if (qApp) {
- app = qApp;
- }
- else {
- app=new QApplication( argc,argv );
- }
- scene = new QGraphicsScene( 0, 0, width, height, app );
- loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ), width, height );
- mlt_properties_set_data( producer_props, "qscene", scene, 0, ( mlt_destructor )qscene_delete, NULL );
- }
+QString colorToString( const QColor& c )
+{
+ QString ret = "%1,%2,%3,%4";
+ ret = ret.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() );
+ return ret;
+}
- g_mutex.unlock();
-
- //must be extracted from kdenlive title
- QImage img( width, height, QImage::Format_ARGB32 );
- img.fill( 0 );
- QPainter p1;
- p1.begin( &img );
- p1.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing );
- //| QPainter::SmoothPixmapTransform );
+QString rectFToString( const QRectF& c )
+{
+ QString ret = "%1,%2,%3,%4";
+ ret = ret.arg( c.top() ).arg( c.left() ).arg( c.width() ).arg( c.height() );
+ return ret;
+}
- const QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "startrect" ) ) );
- const QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "endrect" ) ) );
- const QRectF source( 0, 0, width, height );
+QRectF stringToRect( const QString & s )
+{
- if (end.isNull()) {
- if (start.isNull())
- scene->render( &p1, source, source );
- else
- scene->render( &p1, start, source );
- }
- else {
- QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * position;
- QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * position;
- const QRectF r1( topleft, bottomRight );
- scene->render( &p1, r1, source );
- }
- p1.end();
- uint8_t *pointer=img.bits();
- QRgb* src = ( QRgb* ) pointer;
- for ( int i = 0; i < width * height * 4; i += 4 )
- {
- *buffer++=qRed( *src );
- *buffer++=qGreen( *src );
- *buffer++=qBlue( *src );
- *buffer++=qAlpha( *src );
- src++;
- }
+ QStringList l = s.split( ',' );
+ if ( l.size() < 4 )
+ return QRectF();
+ return QRectF( l.at( 0 ).toDouble(), l.at( 1 ).toDouble(), l.at( 2 ).toDouble(), l.at( 3 ).toDouble() ).normalized();
+}
+
+QColor stringToColor( const QString & s )
+{
+ QStringList l = s.split( ',' );
+ if ( l.size() < 4 )
+ return QColor();
+ return QColor( l.at( 0 ).toInt(), l.at( 1 ).toInt(), l.at( 2 ).toInt(), l.at( 3 ).toInt() );
+ ;
+}
+QTransform stringToTransform( const QString& s )
+{
+ QStringList l = s.split( ',' );
+ if ( l.size() < 9 )
+ return QTransform();
+ return QTransform(
+ l.at( 0 ).toDouble(), l.at( 1 ).toDouble(), l.at( 2 ).toDouble(),
+ l.at( 3 ).toDouble(), l.at( 4 ).toDouble(), l.at( 5 ).toDouble(),
+ l.at( 6 ).toDouble(), l.at( 7 ).toDouble(), l.at( 8 ).toDouble()
+ );
}
+static void qscene_delete( void *data )
+{
+ QGraphicsScene *scene = ( QGraphicsScene * )data;
+ delete scene;
+ scene = NULL;
+}
+
+
void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *templateXml, const char *templateText, int width, int height )
{
scene->clear();
else
font.setPixelSize( txtProperties.namedItem( "font-pixel-size" ).nodeValue().toInt() );
QColor col( stringToColor( txtProperties.namedItem( "font-color" ).nodeValue() ) );
- QGraphicsTextItem *txt;
+ QString text = items.item( i ).namedItem( "content" ).firstChild().nodeValue();
if ( !replacementText.isEmpty() )
{
- QString text = items.item( i ).namedItem( "content" ).firstChild().nodeValue();
text = text.replace( "%s", replacementText );
- txt = scene->addText( text, font );
}
- else txt = scene->addText( items.item( i ).namedItem( "content" ).firstChild().nodeValue(), font );
+ QGraphicsTextItem *txt = new QGraphicsTextItem( text );
+ txt->setFont(font);
+ scene->addItem(txt);
txt->setDefaultTextColor( col );
- txt->setTextInteractionFlags( Qt::NoTextInteraction );
if ( txtProperties.namedItem( "alignment" ).isNull() == false )
{
txt->setTextWidth( txt->boundingRect().width() );
if ( transform != QTransform() ) {
rect = rectTransform( rect, transform );
}
- mlt_properties_set( producer_props, "startrect", rect.toUtf8().data() );
+ mlt_properties_set( producer_props, "_startrect", rect.toUtf8().data() );
}
else if ( items.item( i ).nodeName() == "endviewport" )
{
if ( transform != QTransform() ) {
rect = rectTransform( rect, transform );
}
- mlt_properties_set( producer_props, "endrect", rect.toUtf8().data() );
+ mlt_properties_set( producer_props, "_endrect", rect.toUtf8().data() );
}
}
}
- if ( mlt_properties_get( producer_props, "startrect") == mlt_properties_get( producer_props, "endrect") )
- mlt_properties_set( producer_props, "endrect", "" );
+ if ( !strcmp( mlt_properties_get( producer_props, "_startrect" ), mlt_properties_get( producer_props, "_endrect" ) ) )
+ mlt_properties_set( producer_props, "_endrect", "" );
return;
}
-QString rectTransform( QString s, QTransform t )
-{
- QStringList l = s.split( ',' );
- return QString::number(l.at(0).toDouble() * t.m11()) + ',' + QString::number(l.at(1).toDouble() * t.m22()) + ',' + QString::number(l.at(2).toDouble() * t.m11()) + ',' + QString::number(l.at(3).toDouble() * t.m22());
-}
-QString colorToString( const QColor& c )
+void drawKdenliveTitle( producer_ktitle self, uint8_t * buffer, int width, int height, double position, int force_refresh )
{
- QString ret = "%1,%2,%3,%4";
- ret = ret.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() );
- return ret;
-}
+
+ // Obtain the producer
+ mlt_producer producer = &self->parent;
+
+ // restore cached image if any
+ mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-QString rectFToString( const QRectF& c )
-{
- QString ret = "%1,%2,%3,%4";
- ret = ret.arg( c.top() ).arg( c.left() ).arg( c.width() ).arg( c.height() );
- return ret;
-}
+ /*if ( force_refresh == 0 )
+ {
+ uint8_t * cache = ( uint8_t * )mlt_properties_get_data( producer_props, "image", NULL );
+ if (cache) {
+ buffer = cache;
+ return;
+ }
+ }*/
+
+ // restore QGraphicsScene
+ QGraphicsScene *scene = static_cast<QGraphicsScene *> (mlt_properties_get_data( producer_props, "qscene", NULL ));
-QRectF stringToRect( const QString & s )
-{
+ if ( force_refresh == 1 && scene )
+ {
+ scene = NULL;
+ mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
+ }
+
+ if ( scene == NULL )
+ {
+ int argc = 1;
+ char* argv[1];
+ argv[0] = "xxx";
+ if (qApp) {
+ app = qApp;
+ }
+ else {
+ app=new QApplication( argc,argv ); //, QApplication::Tty );
+ }
+ scene = new QGraphicsScene( 0, 0, width, height, app );
+ loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ), width, height );
+ mlt_properties_set_data( producer_props, "qscene", scene, 0, ( mlt_destructor )qscene_delete, NULL );
+ }
- QStringList l = s.split( ',' );
- if ( l.size() < 4 )
- return QRectF();
- return QRectF( l.at( 0 ).toDouble(), l.at( 1 ).toDouble(), l.at( 2 ).toDouble(), l.at( 3 ).toDouble() ).normalized();
-}
-QColor stringToColor( const QString & s )
-{
- QStringList l = s.split( ',' );
- if ( l.size() < 4 )
- return QColor();
- return QColor( l.at( 0 ).toInt(), l.at( 1 ).toInt(), l.at( 2 ).toInt(), l.at( 3 ).toInt() );
- ;
-}
-QTransform stringToTransform( const QString& s )
-{
- QStringList l = s.split( ',' );
- if ( l.size() < 9 )
- return QTransform();
- return QTransform(
- l.at( 0 ).toDouble(), l.at( 1 ).toDouble(), l.at( 2 ).toDouble(),
- l.at( 3 ).toDouble(), l.at( 4 ).toDouble(), l.at( 5 ).toDouble(),
- l.at( 6 ).toDouble(), l.at( 7 ).toDouble(), l.at( 8 ).toDouble()
- );
+ //must be extracted from kdenlive title
+ QImage img( width, height, QImage::Format_ARGB32 );
+ img.fill( 0 );
+ QPainter p1;
+ p1.begin( &img );
+ p1.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing );
+ //| QPainter::SmoothPixmapTransform );
+
+ const QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "_startrect" ) ) );
+ const QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "_endrect" ) ) );
+ const QRectF source( 0, 0, width, height );
+
+ if (end.isNull()) {
+ if (start.isNull())
+ scene->render( &p1, source, source );
+ else
+ scene->render( &p1, start, source );
+ }
+ else {
+ QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * position;
+ QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * position;
+ const QRectF r1( topleft, bottomRight );
+ scene->render( &p1, r1, source );
+ }
+ p1.end();
+ g_mutex.lock();
+ uint8_t *pointer=img.bits();
+ QRgb* src = ( QRgb* ) pointer;
+ int size = width * height * 4;
+ for ( int i = 0; i < width * height * 4; i += 4 )
+ {
+ *buffer++=qRed( *src );
+ *buffer++=qGreen( *src );
+ *buffer++=qBlue( *src );
+ *buffer++=qAlpha( *src );
+ src++;
+ }
+
+ if ( end.isNull() )
+ {
+ // No animation, cache image for further requests
+ self->current_image = (uint8_t *)mlt_pool_alloc( size );
+ self->current_image = buffer;
+ mlt_properties_set_data( producer_props, "image", self->current_image, width * height * 4, NULL, NULL );
+
+ // Clear scene, we don't need it anymore
+ mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
+ }
+ g_mutex.unlock();
}
+
+
+
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "kdenlivetitle_wrapper.h"
+
#include <framework/mlt.h>
#include <stdlib.h>
#include <string.h>
mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
/* Obtain the producer for this frame */
- mlt_producer producer = mlt_properties_get_data( properties, "producer_kdenlivetitle", NULL );
-
+ producer_ktitle this = mlt_properties_get_data( properties, "producer_kdenlivetitle", NULL );
+
/* Obtain properties of producer */
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
+ mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( &this->parent );
*width = mlt_properties_get_int( properties, "width" );
*height = mlt_properties_get_int( properties, "height" );
mlt_properties_set_int( properties, "width", *width );
mlt_properties_set_int( properties, "height", *height );
-
- /* cache later ?? */
-
- if ( 1 )
+
+ if ( this->current_image )
+ {
+ // Clone the image
+ uint8_t *image_copy = mlt_pool_alloc( size );
+ memcpy( image_copy, this->current_image, size );
+ // Now update properties so we free the copy after
+ mlt_properties_set_data( properties, "image", image_copy, size, mlt_pool_release, NULL );
+ // We're going to pass the copy on
+ *buffer = image_copy;
+ }
+ else
{
/* Allocate the image */
*format = mlt_image_rgb24a;
- mlt_position in = mlt_producer_get_in( producer );
- mlt_position out = mlt_producer_get_out( producer );
- mlt_position time = mlt_producer_position( producer );
+ mlt_position in = mlt_producer_get_in( &this->parent );
+ mlt_position out = mlt_producer_get_out( &this->parent );
+ mlt_position time = mlt_producer_position( &this->parent );
double position = ( double )( time - in ) / ( double )( out - in + 1 );
if ( mlt_properties_get_int( producer_props, "force_reload" ) ) {
if (mlt_properties_get_int( producer_props, "force_reload" ) > 1) read_xml(producer_props);
mlt_properties_set_int( producer_props, "force_reload", 0 );
- refresh_kdenlivetitle( producer, *buffer, *width, *height, position, 1);
+ drawKdenliveTitle( this, *buffer, *width, *height, position, 1);
}
- else refresh_kdenlivetitle( producer, *buffer, *width, *height, position, 0);
+ else drawKdenliveTitle( this, *buffer, *width, *height, position, 0);
/* Update the frame */
mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );
- mlt_log_debug( MLT_PRODUCER_SERVICE( producer ), "width:%d height:%d %s\n", *width, *height, mlt_image_format_name( *format ) );
+ mlt_log_debug( MLT_PRODUCER_SERVICE( &this->parent ), "width:%d height:%d %s\n", *width, *height, mlt_image_format_name( *format ) );
}
return 0;
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
{
+ // Get the real structure for this producer
+ producer_ktitle this = producer->child;
/* Generate a frame */
*frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
/* Set the producer on the frame properties */
- mlt_properties_set_data( properties, "producer_kdenlivetitle", producer, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "producer_kdenlivetitle", this, 0, NULL, NULL );
/* Update timecode on the frame we're creating */
mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
{
/* fprintf(stderr, ":::::::::::: CREATE TITLE\n"); */
/* Create a new producer object */
-
- mlt_producer producer = calloc( 1, sizeof( struct mlt_producer_s ) );
- if ( producer != NULL && mlt_producer_init( producer, NULL ) == 0 )
+
+ producer_ktitle this = calloc( sizeof( struct producer_ktitle_s ), 1 );
+ if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
{
+ mlt_producer producer = &this->parent;
+
/* Get the properties interface */
mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
/* Callback registration */
read_xml(properties);
return producer;
}
- free( producer );
+ free( this );
return NULL;
}