#include "kdenlivetitle_wrapper.h"
-#include <QtGui/QImage>
-#include <QtGui/QPainter>
-#include <QtCore/QDebug>
-#include <QtGui/QApplication>
-#include <QtCore/QMutex>
-#include <QtGui/QGraphicsScene>
-#include <QtGui/QGraphicsTextItem>
-#include <QtSvg/QGraphicsSvgItem>
-#include <QtSvg/QSvgRenderer>
-#include <QtGui/QTextCursor>
-#include <QtGui/QTextDocument>
-#include <QtGui/QStyleOptionGraphicsItem>
-
-#include <QtCore/QString>
-
-#include <QtXml/QDomElement>
-#include <QtCore/QRectF>
-#include <QtGui/QColor>
-#include <QtGui/QWidget>
+#include <QImage>
+#include <QPainter>
+#include <QDebug>
+#include <QApplication>
+#include <QMutex>
+#include <QGraphicsScene>
+#include <QGraphicsTextItem>
+#include <QGraphicsSvgItem>
+#include <QSvgRenderer>
+#include <QTextCursor>
+#include <QTextDocument>
+#include <QStyleOptionGraphicsItem>
+
+#include <QString>
+
+#include <QDomElement>
+#include <QRectF>
+#include <QColor>
+#include <QWidget>
#include <framework/mlt_log.h>
#if QT_VERSION >= 0x040600
-#include <QtGui/QGraphicsEffect>
-#include <QtGui/QGraphicsBlurEffect>
-#include <QtGui/QGraphicsDropShadowEffect>
+#include <QGraphicsEffect>
+#include <QGraphicsBlurEffect>
+#include <QGraphicsDropShadowEffect>
#endif
static QApplication *app = NULL;
+Q_DECLARE_METATYPE(QTextCursor);
class ImageItem: public QGraphicsItem
{
};
-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 )
{
QString replacementText = QString::fromUtf8(templateText);
doc.setContent(data);
QDomElement title = doc.documentElement();
-
+
// 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") ) {
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++ )
{
QGraphicsItem *gitem = NULL;
- int zValue = items.item( i ).attributes().namedItem( "z-index" ).nodeValue().toInt();
+ node = items.item( i );
+ QDomNamedNodeMap nodeAttributes = node.attributes();
+ int zValue = nodeAttributes.namedItem( "z-index" ).nodeValue().toInt();
if ( zValue > -1000 )
{
- if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsTextItem" )
+ if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsTextItem" )
{
- QDomNamedNodeMap txtProperties = items.item( i ).namedItem( "content" ).attributes();
+ QDomNamedNodeMap txtProperties = node.namedItem( "content" ).attributes();
QFont font( txtProperties.namedItem( "font" ).nodeValue() );
- QDomNode node = txtProperties.namedItem( "font-bold" );
- if ( !node.isNull() )
+ QDomNode propsNode = txtProperties.namedItem( "font-bold" );
+ if ( !propsNode.isNull() )
{
- // Old: Bold/Not bold.
- font.setBold( node.nodeValue().toInt() );
+ // 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.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() )
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();
+ 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){
- QTextCursor cursor(txt->document());
+ 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(
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 )
}
gitem = txt;
}
- else if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsRectItem" )
+ else if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsRectItem" )
{
- 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();
+ 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 ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsPixmapItem" )
+ else if ( nodeAttributes.namedItem( "type" ).nodeValue() == "QGraphicsPixmapItem" )
{
- const QString url = items.item( i ).namedItem( "content" ).attributes().namedItem( "url" ).nodeValue();
+ 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.toAscii()));
+ img.loadFromData(QByteArray::fromBase64(base64.toLatin1()));
}
ImageItem *rec = new ImageItem(img);
scene->addItem( rec );
gitem = rec;
}
- else if ( items.item( i ).attributes().namedItem( "type" ).nodeValue() == "QGraphicsSvgItem" )
+ 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();
rec = new QGraphicsSvgItem(url);
}else{
rec = new QGraphicsSvgItem();
- QSvgRenderer *renderer= new QSvgRenderer(QByteArray::fromBase64(base64.toAscii()), rec );
+ QSvgRenderer *renderer= new QSvgRenderer(QByteArray::fromBase64(base64.toLatin1()), rec );
rec->setSharedRenderer(renderer);
}
if (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() );
+ QPointF p( node.namedItem( "position" ).attributes().namedItem( "x" ).nodeValue().toDouble(),
+ node.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->setTransform( stringToTransform( node.namedItem( "position" ).firstChild().firstChild().nodeValue() ) );
+ int zValue = nodeAttributes.namedItem( "z-index" ).nodeValue().toInt();
gitem->setZValue( zValue );
#if QT_VERSION >= 0x040600
{
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 );
+ const char *localename = mlt_properties_get_lcnumeric( MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) ) );
+ QLocale::setDefault( QLocale( localename ) );
}
+ qRegisterMetaType<QTextCursor>( "QTextCursor" );
}
scene = new QGraphicsScene();
scene->setItemIndexMethod( QGraphicsScene::NoIndex );
scene->setSceneRect(0, 0, mlt_properties_get_int( properties, "width" ), mlt_properties_get_int( properties, "height" ));
- loadFromXml( producer, scene, mlt_properties_get( producer_props, "xmldata" ), mlt_properties_get( producer_props, "templatetext" ) );
+ 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 );
}
// 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() );
- 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 );
+ 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() );
}
}
}
scene->render( &p1, source, end, Qt::IgnoreAspectRatio );
}
else {
- double percentage = position / anim_out;
+ 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 );