]> git.sesse.net Git - mlt/blobdiff - src/modules/qimage/kdenlivetitle_wrapper.cpp
Add an offset start param to typewriter effect
[mlt] / src / modules / qimage / kdenlivetitle_wrapper.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 8a7e2bb..9792d47
@@ -29,6 +29,7 @@
 #include <QtGui/QGraphicsTextItem>
 #include <QtSvg/QGraphicsSvgItem>
 #include <QtGui/QTextCursor>
+#include <QtGui/QTextDocument>
 #include <QtGui/QStyleOptionGraphicsItem>
 
 #include <QtCore/QString>
 #include <QtGui/QWidget>
 #include <framework/mlt_log.h>
 
+#if QT_VERSION >= 0x040600
+#include <QtGui/QGraphicsEffect>
+#include <QtGui/QGraphicsBlurEffect>
+#include <QtGui/QGraphicsDropShadowEffect>
+#endif
+
 static QApplication *app = NULL;
 
-class ImageItem: public QGraphicsRectItem
+class ImageItem: public QGraphicsItem
 {
 public:
     ImageItem(QImage img)
@@ -52,6 +59,12 @@ public:
 
 
 protected:
+
+virtual QRectF boundingRect() const
+{
+    return QRectF(0, 0, m_img.width(), m_img.height());
+}
+
 virtual void paint( QPainter *painter,
                        const QStyleOptionGraphicsItem * /*option*/,
                        QWidget* )
@@ -143,6 +156,13 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
             originalWidth = scene->sceneRect().width();
             originalHeight = scene->sceneRect().height();
         }
+        if ( title.hasAttribute( "out" ) ) {
+            mlt_properties_set_position( producer_props, "_animation_out", title.attribute( "out" ).toDouble() );
+        }
+        else {
+            mlt_properties_set_position( producer_props, "_animation_out", mlt_producer_get_out( producer ) );
+        }
+        
        mlt_properties_set_int( producer_props, "_original_width", originalWidth );
        mlt_properties_set_int( producer_props, "_original_height", originalHeight );
 
@@ -187,17 +207,21 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
                                }
                                QGraphicsTextItem *txt = scene->addText(text, font);
                                txt->setDefaultTextColor( col );
+                               
+                               // Effects
+                               if (!txtProperties.namedItem( "typewriter" ).isNull()) {
+                                       // typewriter effect
+                                       mlt_properties_set_int( producer_props, "_animated", 1 );
+                                       QStringList effetData = QStringList() << "typewriter" << text << txtProperties.namedItem( "typewriter" ).nodeValue();
+                                       txt->setData(0, effetData);
+                               }
+                               
                                if ( txtProperties.namedItem( "alignment" ).isNull() == false )
                                {
                                        txt->setTextWidth( txt->boundingRect().width() );
-                                       QTextCursor cur = txt->textCursor();
-                                       QTextBlockFormat format = cur.blockFormat();
-                                       format.setAlignment(( Qt::Alignment ) txtProperties.namedItem( "alignment" ).nodeValue().toInt() );
-                                       cur.select( QTextCursor::Document );
-                                       cur.setBlockFormat( format );
-                                       txt->setTextCursor( cur );
-                                       cur.clearSelection();
-                                       txt->setTextCursor( cur );
+                                       QTextOption opt = txt->document()->defaultTextOption ();
+                                       opt.setAlignment(( Qt::Alignment ) txtProperties.namedItem( "alignment" ).nodeValue().toInt() );
+                                       txt->document()->setDefaultTextOption (opt);
                                }
                                        if ( !txtProperties.namedItem( "kdenlive-axis-x-inverted" ).isNull() )
                                {
@@ -243,6 +267,25 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
                        gitem->setTransform( stringToTransform( items.item( i ).namedItem( "position" ).firstChild().firstChild().nodeValue() ) );
                        int zValue = items.item( i ).attributes().namedItem( "z-index" ).nodeValue().toInt();
                        gitem->setZValue( zValue );
+
+#if QT_VERSION >= 0x040600
+                       // effects
+                       QDomNode eff = items.item(i).namedItem("effect");
+                       if (!eff.isNull()) {
+                               QDomElement e = eff.toElement();
+                               if (e.attribute("type") == "blur") {
+                                       QGraphicsBlurEffect *blur = new QGraphicsBlurEffect();
+                                       blur->setBlurRadius(e.attribute("blurradius").toInt());
+                                       gitem->setGraphicsEffect(blur);
+                               }
+                               else if (e.attribute("type") == "shadow") {
+                                       QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect();
+                                       shadow->setBlurRadius(e.attribute("blurradius").toInt());
+                                       shadow->setOffset(e.attribute("xoffset").toInt(), e.attribute("yoffset").toInt());
+                                       gitem->setGraphicsEffect(shadow);
+                               }
+                       }
+#endif
                }
        }
 
@@ -290,7 +333,7 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
         pthread_mutex_lock( &self->mutex );
        
        // Check if user wants us to reload the image
-       if ( force_refresh == 1 || width != self->current_width || height != self->current_height || mlt_properties_get( producer_props, "_endrect" ) != NULL )
+       if ( mlt_properties_get( producer_props, "_animated" ) != NULL || force_refresh == 1 || width != self->current_width || height != self->current_height || mlt_properties_get( producer_props, "_endrect" ) != NULL )
        {
                //mlt_cache_item_close( self->image_cache );
                self->current_image = NULL;
@@ -317,22 +360,24 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                        // Warning: all Qt graphic objects (QRect, ...) must be initialized AFTER 
                        // the QApplication is created, otherwise their will be NULL
                        
-                       if (qApp) {
-                               app = qApp;
-                       }
-                       else {
-#ifdef linux
-                               if ( getenv("DISPLAY") == 0 )
-                               {
-                                       mlt_log_panic( MLT_PRODUCER_SERVICE( producer ), "Error, cannot render titles without an X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
-                                       pthread_mutex_unlock( &self->mutex );
-                                       exit(1);
-                                       return;
+                       if ( app == NULL ) {
+                               if ( qApp ) {
+                                       app = qApp;
                                }
+                               else {
+#ifdef linux
+                                       if ( getenv("DISPLAY") == 0 )
+                                       {
+                                               mlt_log_panic( MLT_PRODUCER_SERVICE( producer ), "Error, cannot render titles without an X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
+                                               pthread_mutex_unlock( &self->mutex );
+                                               exit(1);
+                                               return;
+                                       }
 #endif
-                               app = new QApplication( argc, argv );
-                //fix to let the decimal point for every locale be: "."
-                setlocale(LC_NUMERIC,"POSIX");
+                                       app = new QApplication( argc, argv );
+                                       //fix to let the decimal point for every locale be: "."
+                                       setlocale(LC_NUMERIC,"POSIX");
+                               }
                        }
                        scene = new QGraphicsScene();
                         scene->setSceneRect(0, 0, mlt_properties_get_int( properties, "width" ), mlt_properties_get_int( properties, "height" ));
@@ -349,7 +394,28 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                if (start.isNull()) {
                    start = QRectF( 0, 0, originalWidth, originalHeight );
                }
-       
+
+               // Effects
+               QList <QGraphicsItem *> items = scene->items();
+               QGraphicsTextItem *titem = NULL;
+               for (int i = 0; i < items.count(); i++) {
+                   titem = static_cast <QGraphicsTextItem*> ( items.at( i ) );
+                   if (titem && !titem->data( 0 ).isNull()) {
+                           QStringList params = titem->data( 0 ).toStringList();
+                           if (params.at( 0 ) == "typewriter" ) {
+                                   // typewriter effect has 2 param values:
+                                   // the keystroke delay and a start offset, both in frames
+                                   QStringList values = params.at( 2 ).split( ";" );
+                                   int interval = qMax( 0, ( ( int ) position) / values.at( 0 ).toInt() - values.at( 1 ).toInt() );
+                                   QTextDocument *td = new QTextDocument( params.at( 1 ).left( interval ) );
+                                   td->setDefaultFont( titem->font() );
+                                   td->setDefaultTextOption( titem->document()->defaultTextOption() );
+                                   td->setTextWidth( titem->document()->textWidth() );
+                                   titem->setDocument( td );
+                           }
+                   }
+               }
+
                //must be extracted from kdenlive title
                QImage img( width, height, QImage::Format_ARGB32 );
                img.fill( 0 );
@@ -357,14 +423,19 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                p1.begin( &img );
                p1.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing );
                //| QPainter::SmoothPixmapTransform );
+                mlt_position anim_out = mlt_properties_get_position( producer_props, "_animation_out" );
+
                if (end.isNull())
                {
                        scene->render( &p1, source, start, Qt::IgnoreAspectRatio );
                }
-               else
-               {
-                       QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * position;
-                       QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * position;
+               else if ( position > anim_out ) {
+                        scene->render( &p1, source, end, Qt::IgnoreAspectRatio );
+                }
+               else {
+                        double percentage = position / anim_out;
+                       QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * percentage;
+                       QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * percentage;
                        const QRectF r1( topleft, bottomRight );
                        scene->render( &p1, source, r1, Qt::IgnoreAspectRatio );
                }