X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fqimage%2Fkdenlivetitle_wrapper.cpp;h=2d5bc4d6bf0df243cebfbc52348a552213771f4a;hb=51b566869164b53f76f915959e9298b5dcb31bb3;hp=9166a32d7dc77207fbcad932273643329c1fda8c;hpb=0d6a1d9c37142be087085810f1d71e5441d34bfa;p=mlt diff --git a/src/modules/qimage/kdenlivetitle_wrapper.cpp b/src/modules/qimage/kdenlivetitle_wrapper.cpp old mode 100644 new mode 100755 index 9166a32d..2d5bc4d6 --- a/src/modules/qimage/kdenlivetitle_wrapper.cpp +++ b/src/modules/qimage/kdenlivetitle_wrapper.cpp @@ -20,27 +20,37 @@ #include "kdenlivetitle_wrapper.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#if QT_VERSION >= 0x040600 +#include +#include +#include +#endif static QApplication *app = NULL; +Q_DECLARE_METATYPE(QTextCursor); -class ImageItem: public QGraphicsRectItem +class ImageItem: public QGraphicsItem { public: ImageItem(QImage img) @@ -51,6 +61,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* ) @@ -61,26 +77,6 @@ virtual void paint( QPainter *painter, }; -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 ) -{ - QString ret = "%1,%2,%3,%4"; - ret = ret.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() ); - return ret; -} - -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; -} - QRectF stringToRect( const QString & s ) { @@ -113,12 +109,12 @@ QTransform stringToTransform( const QString& s ) static void qscene_delete( void *data ) { QGraphicsScene *scene = ( QGraphicsScene * )data; - delete scene; + if (scene) delete scene; scene = NULL; } -void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *templateXml, const char *templateText, int width, int height ) +void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *templateXml, const char *templateText ) { scene->clear(); mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); @@ -126,148 +122,219 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp QString data = QString::fromUtf8(templateXml); QString replacementText = QString::fromUtf8(templateText); doc.setContent(data); - QDomNodeList titles = doc.elementsByTagName( "kdenlivetitle" ); - QTransform transform; - if ( doc.documentElement().hasAttribute("width") ) { - int originalWidth = doc.documentElement().attribute("width").toInt(); - mlt_properties_set_int( producer_props, "_original_width", originalWidth ); - int originalHeight = doc.documentElement().attribute("height").toInt(); - mlt_properties_set_int( producer_props, "_original_height", originalHeight ); - } + QDomElement title = doc.documentElement(); - if ( titles.size() ) + // Check for invalid title + if ( title.isNull() || title.tagName() != "kdenlivetitle" ) return; + + // Check title locale + if ( title.hasAttribute( "LC_NUMERIC" ) ) { + QString locale = title.attribute( "LC_NUMERIC" ); + QLocale::setDefault( locale ); + } + + int originalWidth; + int originalHeight; + if ( title.hasAttribute("width") ) { + originalWidth = title.attribute("width").toInt(); + originalHeight = title.attribute("height").toInt(); + scene->setSceneRect(0, 0, originalWidth, originalHeight); + } + else { + 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 ); + + QDomNode node; + QDomNodeList items = title.elementsByTagName("item"); + for ( int i = 0; i < items.count(); i++ ) { - - QDomNodeList items = titles.item( 0 ).childNodes(); - for ( int i = 0; i < items.count(); i++ ) + QGraphicsItem *gitem = NULL; + node = items.item( i ); + QDomNamedNodeMap nodeAttributes = node.attributes(); + int zValue = nodeAttributes.namedItem( "z-index" ).nodeValue().toInt(); + if ( zValue > -1000 ) { - QGraphicsItem *gitem = NULL; - int zValue = items.item( i ).attributes().namedItem( "z-index" ).nodeValue().toInt(); - if ( zValue > -1000 ) + if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsTextItem" ) { - if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsTextItem" ) + QDomNamedNodeMap txtProperties = node.namedItem( "content" ).attributes(); + QFont font( txtProperties.namedItem( "font" ).nodeValue() ); + QDomNode propsNode = txtProperties.namedItem( "font-bold" ); + if ( !propsNode.isNull() ) { - QDomNamedNodeMap txtProperties = items.item( i ).namedItem( "content" ).attributes(); - QFont font( txtProperties.namedItem( "font" ).nodeValue() ); - - QDomNode node = txtProperties.namedItem( "font-bold" ); - if ( !node.isNull() ) - { - // Old: Bold/Not bold. - font.setBold( node.nodeValue().toInt() ); - } - else - { - // New: Font weight (QFont::) - font.setWeight( txtProperties.namedItem( "font-weight" ).nodeValue().toInt() ); - } - - //font.setBold(txtProperties.namedItem("font-bold").nodeValue().toInt()); - font.setItalic( txtProperties.namedItem( "font-italic" ).nodeValue().toInt() ); - font.setUnderline( txtProperties.namedItem( "font-underline" ).nodeValue().toInt() ); - // Older Kdenlive version did not store pixel size but point size - if ( txtProperties.namedItem( "font-pixel-size" ).isNull() ) - { - QFont f2; - f2.setPointSize( txtProperties.namedItem( "font-size" ).nodeValue().toInt() ); - font.setPixelSize( QFontInfo( f2 ).pixelSize() ); - } - else - font.setPixelSize( txtProperties.namedItem( "font-pixel-size" ).nodeValue().toInt() ); - QColor col( stringToColor( txtProperties.namedItem( "font-color" ).nodeValue() ) ); - QString text = items.item( i ).namedItem( "content" ).firstChild().nodeValue(); - if ( !replacementText.isEmpty() ) - { - text = text.replace( "%s", replacementText ); - } - QGraphicsTextItem *txt = scene->addText(text, font); + // Old: Bold/Not bold. + font.setBold( propsNode.nodeValue().toInt() ); + } + else + { + // New: Font weight (QFont::) + font.setWeight( txtProperties.namedItem( "font-weight" ).nodeValue().toInt() ); + } + font.setItalic( txtProperties.namedItem( "font-italic" ).nodeValue().toInt() ); + font.setUnderline( txtProperties.namedItem( "font-underline" ).nodeValue().toInt() ); + // Older Kdenlive version did not store pixel size but point size + if ( txtProperties.namedItem( "font-pixel-size" ).isNull() ) + { + QFont f2; + f2.setPointSize( txtProperties.namedItem( "font-size" ).nodeValue().toInt() ); + font.setPixelSize( QFontInfo( f2 ).pixelSize() ); + } + else + font.setPixelSize( txtProperties.namedItem( "font-pixel-size" ).nodeValue().toInt() ); + QColor col( stringToColor( txtProperties.namedItem( "font-color" ).nodeValue() ) ); + QString text = node.namedItem( "content" ).firstChild().nodeValue(); + if ( !replacementText.isEmpty() ) + { + text = text.replace( "%s", replacementText ); + } + QGraphicsTextItem *txt = scene->addText(text, font); + if (txtProperties.namedItem("font-outline").nodeValue().toDouble()>0.0){ + QTextDocument *doc = txt->document(); + // Make sure some that the text item does not request refresh by itself + doc->blockSignals(true); + QTextCursor cursor(doc); + cursor.select(QTextCursor::Document); + QTextCharFormat format; + format.setTextOutline( + QPen(QColor( stringToColor( txtProperties.namedItem( "font-outline-color" ).nodeValue() ) ), + txtProperties.namedItem("font-outline").nodeValue().toDouble(), + Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin) + ); + format.setForeground(QBrush(col)); + + cursor.mergeCharFormat(format); + } else { txt->setDefaultTextColor( col ); - 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 ); - } - - if ( !txtProperties.namedItem( "kdenlive-axis-x-inverted" ).isNull() ) - { - //txt->setData(OriginXLeft, txtProperties.namedItem("kdenlive-axis-x-inverted").nodeValue().toInt()); - } - if ( !txtProperties.namedItem( "kdenlive-axis-y-inverted" ).isNull() ) - { - //txt->setData(OriginYTop, txtProperties.namedItem("kdenlive-axis-y-inverted").nodeValue().toInt()); - } - - gitem = txt; } - else if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsRectItem" ) + + // 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( "textwidth" ).isNull() ) + txt->setData( 1, txtProperties.namedItem( "textwidth" ).nodeValue() ); + } + + if ( txtProperties.namedItem( "alignment" ).isNull() == false ) { - QString rect = items.item( i ).namedItem( "content" ).attributes().namedItem( "rect" ).nodeValue(); - QString br_str = items.item( i ).namedItem( "content" ).attributes().namedItem( "brushcolor" ).nodeValue(); - QString pen_str = items.item( i ).namedItem( "content" ).attributes().namedItem( "pencolor" ).nodeValue(); - double penwidth = items.item( i ).namedItem( "content" ).attributes().namedItem( "penwidth" ).nodeValue().toDouble(); - QGraphicsRectItem *rec = scene->addRect( stringToRect( rect ), QPen( QBrush( stringToColor( pen_str ) ), penwidth ), QBrush( stringToColor( br_str ) ) ); - gitem = rec; + txt->setTextWidth( txt->boundingRect().width() ); + QTextOption opt = txt->document()->defaultTextOption (); + opt.setAlignment(( Qt::Alignment ) txtProperties.namedItem( "alignment" ).nodeValue().toInt() ); + txt->document()->setDefaultTextOption (opt); } - else if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsPixmapItem" ) + if ( !txtProperties.namedItem( "kdenlive-axis-x-inverted" ).isNull() ) { - const QString url = items.item( i ).namedItem( "content" ).attributes().namedItem( "url" ).nodeValue(); - QImage img( url ); - ImageItem *rec = new ImageItem(img); - scene->addItem( rec ); - gitem = rec; + //txt->setData(OriginXLeft, txtProperties.namedItem("kdenlive-axis-x-inverted").nodeValue().toInt()); } - else if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsSvgItem" ) + if ( !txtProperties.namedItem( "kdenlive-axis-y-inverted" ).isNull() ) { - const QString url = items.item( i ).namedItem( "content" ).attributes().namedItem( "url" ).nodeValue(); - QGraphicsSvgItem *rec = new QGraphicsSvgItem(url); + //txt->setData(OriginYTop, txtProperties.namedItem("kdenlive-axis-y-inverted").nodeValue().toInt()); + } + gitem = txt; + } + else if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsRectItem" ) + { + QString rect = node.namedItem( "content" ).attributes().namedItem( "rect" ).nodeValue(); + QString br_str = node.namedItem( "content" ).attributes().namedItem( "brushcolor" ).nodeValue(); + QString pen_str = node.namedItem( "content" ).attributes().namedItem( "pencolor" ).nodeValue(); + double penwidth = node.namedItem( "content" ).attributes().namedItem( "penwidth") .nodeValue().toDouble(); + QGraphicsRectItem *rec = scene->addRect( stringToRect( rect ), QPen( QBrush( stringToColor( pen_str ) ), penwidth, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin ), QBrush( stringToColor( br_str ) ) ); + gitem = rec; + } + else if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsPixmapItem" ) + { + const QString url = node.namedItem( "content" ).attributes().namedItem( "url" ).nodeValue(); + const QString base64 = items.item(i).namedItem("content").attributes().namedItem("base64").nodeValue(); + QImage img; + if (base64.isEmpty()){ + img.load(url); + }else{ + img.loadFromData(QByteArray::fromBase64(base64.toLatin1())); + } + ImageItem *rec = new ImageItem(img); + scene->addItem( rec ); + gitem = rec; + } + else if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsSvgItem" ) + { + QString url = items.item(i).namedItem("content").attributes().namedItem("url").nodeValue(); + QString base64 = items.item(i).namedItem("content").attributes().namedItem("base64").nodeValue(); + QGraphicsSvgItem *rec = NULL; + if (base64.isEmpty()){ + rec = new QGraphicsSvgItem(url); + }else{ + rec = new QGraphicsSvgItem(); + QSvgRenderer *renderer= new QSvgRenderer(QByteArray::fromBase64(base64.toLatin1()), rec ); + rec->setSharedRenderer(renderer); + } + if (rec){ scene->addItem(rec); gitem = rec; } } - //pos and transform - if ( gitem ) - { - QPointF p( items.item( i ).namedItem( "position" ).attributes().namedItem( "x" ).nodeValue().toDouble(), - items.item( i ).namedItem( "position" ).attributes().namedItem( "y" ).nodeValue().toDouble() ); - gitem->setPos( p ); - 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 ); + } + //pos and transform + if ( gitem ) + { + QPointF p( node.namedItem( "position" ).attributes().namedItem( "x" ).nodeValue().toDouble(), + node.namedItem( "position" ).attributes().namedItem( "y" ).nodeValue().toDouble() ); + gitem->setPos( p ); + gitem->setTransform( stringToTransform( node.namedItem( "position" ).firstChild().firstChild().nodeValue() ) ); + int zValue = nodeAttributes.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 } } - QDomNode n = doc.documentElement().firstChildElement("background"); + + QDomNode n = title.firstChildElement("background"); if (!n.isNull()) { - QColor color = QColor( stringToColor( n.attributes().namedItem( "color" ).nodeValue() ) ); - //color.setAlpha(items.item(i).attributes().namedItem("alpha").nodeValue().toInt()); - QList items = scene->items(); - for ( int i = 0; i < items.size(); i++ ) - { - if ( items.at( i )->zValue() == -1100 ) - { - (( QGraphicsRectItem * )items.at( i ) )->setBrush( QBrush( color ) ); - break; - } - } + QColor color = QColor( stringToColor( n.attributes().namedItem( "color" ).nodeValue() ) ); + if (color.alpha() > 0) { + QGraphicsRectItem *rec = scene->addRect(0, 0, scene->width(), scene->height() , QPen( Qt::NoPen ), QBrush( color ) ); + rec->setZValue(-1100); + } } QString startRect; - QString endRect; - n = doc.documentElement().firstChildElement( "startviewport" ); - if (!n.isNull()) + n = title.firstChildElement( "startviewport" ); + // Check if node exists, if it has an x attribute, it is an old version title, don't use viewport + if (!n.isNull() && !n.toElement().hasAttribute("x")) { startRect = n.attributes().namedItem( "rect" ).nodeValue(); } - n = doc.documentElement().firstChildElement( "endviewport" ); - if (!n.isNull()) + n = title.firstChildElement( "endviewport" ); + // Check if node exists, if it has an x attribute, it is an old version title, don't use viewport + if (!n.isNull() && !n.toElement().hasAttribute("x")) { QString rect = n.attributes().namedItem( "rect" ).nodeValue(); if (startRect != rect) @@ -276,7 +343,6 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp if (!startRect.isEmpty()) { mlt_properties_set( producer_props, "_startrect", startRect.toUtf8().data() ); } - return; } @@ -285,21 +351,18 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he { // Obtain the producer mlt_producer producer = &self->parent; + mlt_profile profile = mlt_service_profile ( MLT_PRODUCER_SERVICE( producer ) ) ; mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); - - pthread_mutex_lock( &self->mutex ); - - QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "_startrect" ) ) ); - QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "_endrect" ) ) ); + + 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 || !end.isNull()) + 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; mlt_properties_set_data( producer_props, "cached_image", NULL, 0, NULL, NULL ); mlt_properties_set_int( producer_props, "force_reload", 0 ); @@ -314,40 +377,94 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he 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 ); + argv[0] = (char*) "xxx"; + + // Warning: all Qt graphic objects (QRect, ...) must be initialized AFTER + // the QApplication is created, otherwise their will be NULL + + 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 ); + return; + } +#endif + app = new QApplication( argc, argv ); + const char *localename = mlt_properties_get_lcnumeric( MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) ) ); + QLocale::setDefault( QLocale( localename ) ); + } + qRegisterMetaType( "QTextCursor" ); } scene = new QGraphicsScene(); - loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ), width, height ); + scene->setItemIndexMethod( QGraphicsScene::NoIndex ); + scene->setSceneRect(0, 0, mlt_properties_get_int( properties, "width" ), mlt_properties_get_int( properties, "height" )); + if ( mlt_properties_get( producer_props, "resource" ) && mlt_properties_get( producer_props, "resource" )[0] != '\0' ) + { + // The title has a resource property, so we read all properties from the resource. + // Do not serialize the xmldata + loadFromXml( producer, scene, mlt_properties_get( producer_props, "_xmldata" ), mlt_properties_get( producer_props, "templatetext" ) ); + } + else + { + // The title has no resource, all data should be serialized + loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ) ); + + } mlt_properties_set_data( producer_props, "qscene", scene, 0, ( mlt_destructor )qscene_delete, NULL ); } + + QRectF start = stringToRect( QString( mlt_properties_get( producer_props, "_startrect" ) ) ); + QRectF end = stringToRect( QString( mlt_properties_get( producer_props, "_endrect" ) ) ); int originalWidth = mlt_properties_get_int( producer_props, "_original_width" ); int originalHeight= mlt_properties_get_int( producer_props, "_original_height" ); - const QRectF source( 0, 0, originalWidth, originalHeight ); - if (start.isNull()) start = source; - - if (originalWidth != width || originalHeight != height) - { - QTransform transform; -#if QT_VERSION < 0x40500 - transform = QTransform().scale( (double) width / originalWidth, (double) height / originalHeight ); -#else - transform = QTransform::fromScale ( (double) width / originalWidth, (double) height / originalHeight); -#endif - start = transform.mapRect(start); - if (!end.isNull()) end = transform.mapRect(end); + const QRectF source( 0, 0, width, height ); + if (start.isNull()) { + start = QRectF( 0, 0, originalWidth, originalHeight ); } - + + // Effects + QList items = scene->items(); + QGraphicsTextItem *titem = NULL; + for (int i = 0; i < items.count(); i++) { + titem = static_cast ( 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( 1 ).toInt()) / values.at( 0 ).toInt() ); + QTextCursor cursor = titem->textCursor(); + cursor.movePosition(QTextCursor::EndOfBlock); + // get the font format + QTextCharFormat format = cursor.charFormat(); + cursor.select(QTextCursor::Document); + QString txt = params.at( 1 ).left( interval ); + // If the string to insert is empty, insert a space / linebreak so that we don't loose + // formatting infos for the next iterations + int lines = params.at( 1 ).count( '\n' ); + QString empty = " "; + for (int i = 0; i < lines; i++) + empty.append( "\n " ); + cursor.insertText( txt.isEmpty() ? empty : txt, format ); + if ( !titem->data( 1 ).isNull() ) + titem->setTextWidth( titem->data( 1 ).toDouble() ); + } + } + } + //must be extracted from kdenlive title QImage img( width, height, QImage::Format_ARGB32 ); img.fill( 0 ); @@ -355,17 +472,42 @@ 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, start, source ); + 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 = 0; + if ( position && anim_out ) + 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, r1, source ); + scene->render( &p1, source, r1, Qt::IgnoreAspectRatio ); + if ( profile && !profile->progressive ){ + int line=0; + double percentage_next_filed = ( position + 0.5 ) / anim_out; + QPointF topleft_next_field = start.topLeft() + ( end.topLeft() - start.topLeft() ) * percentage_next_filed; + QPointF bottomRight_next_field = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * percentage_next_filed; + const QRectF r2( topleft_next_field, bottomRight_next_field ); + QImage img1( width, height, QImage::Format_ARGB32 ); + img1.fill( 0 ); + QPainter p2; + p2.begin(&img1); + p2.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); + scene->render(&p2,source,r2, Qt::IgnoreAspectRatio ); + p2.end(); + int next_field_line = ( mlt_properties_get_int( producer_props, "top_field_first" ) ? 1 : 0 ); + for (line = next_field_line ;line