+ // 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( 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 );
+ QPainter p1;
+ 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 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, 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<height;line+=2){
+ memcpy(img.scanLine(line),img1.scanLine(line),img.bytesPerLine());
+ }
+
+ }
+ }
+ p1.end();
+
+ int size = width * height * 4;
+ uint8_t *pointer=img.bits();
+ QRgb* src = ( QRgb* ) pointer;
+ self->current_image = ( uint8_t * )mlt_pool_alloc( size );
+ uint8_t *dst = self->current_image;
+
+ for ( int i = 0; i < width * height * 4; i += 4 )
+ {
+ *dst++=qRed( *src );
+ *dst++=qGreen( *src );
+ *dst++=qBlue( *src );
+ *dst++=qAlpha( *src );
+ src++;
+ }
+
+ mlt_properties_set_data( producer_props, "cached_image", self->current_image, size, mlt_pool_release, NULL );
+ self->current_width = width;
+ self->current_height = height;
+ }
+
+ pthread_mutex_unlock( &self->mutex );
+ mlt_properties_set_int( properties, "width", self->current_width );
+ mlt_properties_set_int( properties, "height", self->current_height );