#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)
protected:
+
+virtual QRectF boundingRect() const
+{
+ return QRectF(0, 0, m_img.width(), m_img.height());
+}
+
virtual void paint( QPainter *painter,
const QStyleOptionGraphicsItem * /*option*/,
QWidget* )
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 );
}
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() )
{
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
}
}
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;
// 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" ));
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 );
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 );
}