Exemple #1
0
void QPainterFilterContext::drawImage(const QRectF &target, const QImage &image, const QRectF &source, Qt::ImageConversionFlags flags)
{
    if (!prepare())
        return;
    if (source.isNull())
        painter->drawImage(target, image, QRectF(0, 0, image.width(), image.height()), flags);
    else
        painter->drawImage(target, image, source, flags);
    painter->restore();
}
Exemple #2
0
void BlurItem::reload(const QPixmap &pixmap)
{
  const QRectF r = rect();
  if (r.isNull() && !r.isValid())
    return;

  QTransform t = sceneTransform();
  t.translate(qAbs(scene()->sceneRect().left()), qAbs(scene()->sceneRect().top()));
  m_item->setPixmap(pixmap.copy(t.mapRect(r).toRect()));
}
Exemple #3
0
void QPainterFilterContext::drawPlainText(const QRectF &rect, int flags, const QString &text)
{
    if (!prepare())
        return;
    if (rect.isNull())
        painter->drawText(rect.topLeft(), text);
    else
        painter->drawText(rect, flags, text);
    painter->restore();
}
void OrthogonalRenderer::drawTileLayer(QPainter *painter,
                                       const TileLayer *layer,
                                       const QRectF &exposed) const
{
    const QTransform savedTransform = painter->transform();

    const int tileWidth = map()->tileWidth();
    const int tileHeight = map()->tileHeight();
    const QPointF layerPos(layer->x() * tileWidth,
                           layer->y() * tileHeight);

    painter->translate(layerPos);

    int startX = 0;
    int startY = 0;
    int endX = layer->width();
    int endY = layer->height();

    if (!exposed.isNull()) {
        QMargins drawMargins = layer->drawMargins();
        drawMargins.setTop(drawMargins.top() - tileHeight);
        drawMargins.setRight(drawMargins.right() - tileWidth);

        QRectF rect = exposed.adjusted(-drawMargins.right(),
                                       -drawMargins.bottom(),
                                       drawMargins.left(),
                                       drawMargins.top());

        rect.translate(-layerPos);

        startX = qMax((int) rect.x() / tileWidth, 0);
        startY = qMax((int) rect.y() / tileHeight, 0);
        endX = qMin((int) std::ceil(rect.right()) / tileWidth + 1, endX);
        endY = qMin((int) std::ceil(rect.bottom()) / tileHeight + 1, endY);
    }

    CellRenderer renderer(painter);

    for (int y = startY; y < endY; ++y) {
        for (int x = startX; x < endX; ++x) {
            const Cell &cell = layer->cellAt(x, y);
            if (cell.isEmpty())
                continue;

            renderer.render(cell,
                            QPointF(x * tileWidth, (y + 1) * tileHeight),
                            CellRenderer::BottomLeft);
        }
    }

    renderer.flush();

    painter->setTransform(savedTransform);
}
QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const
{
    const QRectF bounds = object->bounds();
    const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                      tileToPixelCoords(bounds.bottomRight()));

    QRectF boundingRect;

    if (!object->cell().isEmpty()) {
        const QPointF bottomLeft = rect.topLeft();
        const Tile *tile = object->cell().tile;
        const QSize imgSize = tile->image().size();
        const QPoint tileOffset = tile->tileset()->tileOffset();
        boundingRect = QRectF(bottomLeft.x() + tileOffset.x(),
                              bottomLeft.y() + tileOffset.y() - imgSize.height(),
                              imgSize.width(),
                              imgSize.height()).adjusted(-1, -1, 1, 1);
    } else {
        const qreal extraSpace = qMax(objectLineWidth() / 2, qreal(1));

        switch (object->shape()) {
        case MapObject::Ellipse:
        case MapObject::Rectangle:
            if (rect.isNull()) {
                boundingRect = rect.adjusted(-10 - extraSpace,
                                             -10 - extraSpace,
                                             10 + extraSpace + 1,
                                             10 + extraSpace + 1);
            } else {
                const int nameHeight = object->name().isEmpty() ? 0 : 15;
                boundingRect = rect.adjusted(-extraSpace,
                                             -nameHeight - extraSpace,
                                             extraSpace + 1,
                                             extraSpace + 1);
            }
            break;

        case MapObject::Polygon:
        case MapObject::Polyline: {
            const QPointF &pos = object->position();
            const QPolygonF polygon = object->polygon().translated(pos);
            QPolygonF screenPolygon = tileToPixelCoords(polygon);
            boundingRect = screenPolygon.boundingRect().adjusted(-extraSpace,
                                                                 -extraSpace,
                                                                 extraSpace + 1,
                                                                 extraSpace + 1);
            break;
        }
        }
    }

    return boundingRect;
}
QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const
{
    const QRectF bounds = object->bounds();
    const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                      tileToPixelCoords(bounds.bottomRight()));

    // The -2 and +3 are to account for the pen width and shadow
    if (rect.isNull())
        return rect.adjusted(-15 - 2, -25 - 2, 10 + 3, 10 + 3);
    else
        return rect.adjusted(-2, -15 - 2, 3, 3);
}
Exemple #7
0
qreal PathView::contentsScale() const
{
	QRectF br = _tr | _rr | _wr;

	if (br.isNull())
		return mapScale(ZOOM_MAX);

	QPointF sc(br.width() / (viewport()->width() - MARGIN/2),
	  br.height() / (viewport()->height() - MARGIN/2));

	return qMax(sc.x(), sc.y());
}
Exemple #8
0
QRectF PathView::contentsSceneRect() const
{
	qreal scale = mapScale(_zoom);
	QRectF br = scaled(_tr | _rr | _wr, 1.0/scale);

	if (br.isNull())
		return QRectF(QPointF(_wp.x() / scale - Tile::size()/2,
		  _wp.y() /scale - Tile::size()/2), QSizeF(Tile::size(), Tile::size()));
	else
		return br.adjusted(-Tile::size(), -Tile::size(), Tile::size(),
		  Tile::size());
}
bool
BubbleAnimation::nextFrame(
	QColor const& head_color, QColor const& tail_color,
	QPaintDevice* pd, QRectF rect)
{
	if (rect.isNull()) {
		rect = QRectF(0.0, 0.0, pd->width(), pd->height());
	}
	
	QPainter painter(pd);
	return nextFrame(head_color, tail_color, &painter, rect);
}
void QVGPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
{
    if (src.isNull())
        return;

    if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
        // The pixmap data is not an instance of QVGPixmapData, so fall
        // back to the default blur filter implementation.
        QPixmapBlurFilter::draw(painter, dest, src, srcRect);
        return;
    }

    QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());

    VGImage srcImage = pd->toVGImage();
    if (srcImage == VG_INVALID_HANDLE)
        return;

    QSize size = pd->size();
    VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
        (VG_sARGB_8888_PRE, size.width(), size.height(),
         VG_IMAGE_QUALITY_FASTER, pd);
    if (dstImage == VG_INVALID_HANDLE)
        return;

    // Clamp the radius range.  We divide by 2 because the OpenVG blur
    // is "too blurry" compared to the default raster implementation.
    VGfloat maxRadius = VGfloat(vgGeti(VG_MAX_GAUSSIAN_STD_DEVIATION));
    VGfloat radiusF = VGfloat(radius()) / 2.0f;
    if (radiusF < 0.001f)
        radiusF = 0.001f;
    else if (radiusF > maxRadius)
        radiusF = maxRadius;

    vgGaussianBlur(dstImage, srcImage, radiusF, radiusF, VG_TILE_PAD);

    VGImage child = VG_INVALID_HANDLE;

    if (srcRect.isNull() ||
        (srcRect.topLeft().isNull() && srcRect.size() == size)) {
        child = dstImage;
    } else {
        QRect src = srcRect.toRect();
        child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
    }

    qt_vg_drawVGImage(painter, dest, child);

    if(child != dstImage)
        vgDestroyImage(child);
    QVGImagePool::instance()->releaseImage(0, dstImage);
}
bool OLSAdaptiveNodeTextAreaVisualizer::tryPerformAdaptableVisualization(OLSOntologyGraphNodeItem *nodeToVisualize,
            OLSOntologyGraphNodeItem *nodeWithVisualizeInfo, QPainter *)
{
    if (nodeToVisualize == nullptr)
        return false;
    QRectF rect = enlargeRect(nodeToVisualize->textRect(), getParameterValueOrDefaultDouble(m_offsetStr, nodeWithVisualizeInfo, m_offset));
    if (!rect.isNull())
        nodeToVisualize->setRect(rect);
    else
        nodeToVisualize->setRect(nodeToVisualize->textRect());
    qDebug() << "OLSAdaptiveNodeTextAreaVisualizer";
    return true;
}
QPainterPath OrthogonalRenderer::shape(const MapObject *object) const
{
    const QRectF bounds = object->bounds();
    const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                      tileToPixelCoords(bounds.bottomRight()));

    QPainterPath path;
    if (rect.isNull())
        path.addEllipse(rect.topLeft(), 20, 20);
    else
        path.addRoundedRect(rect, 10, 10);
    return path;
}
Exemple #13
0
void PrintBedView::drawGrid(QPainter *painter, const QRectF &rect)
{
	double gridDensity = 10;
	int thickLineWidth = 3;

	double thickLineSceneWidth = thickLineWidth / transform().m11();
	QRectF toDraw = m_gridRect.intersected(rect.adjusted(-thickLineSceneWidth, -thickLineSceneWidth,
										   thickLineSceneWidth, thickLineSceneWidth));

	if (toDraw.isNull()) {
		return;
	}

	QPen defaultPen = painter->pen();
	QPen thickPen = defaultPen;
	thickPen.setWidth(thickLineWidth);
	thickPen.setCosmetic(true);

	int lineNo = static_cast<int>(toDraw.left() / gridDensity);
	if (toDraw.left() > 0) {
		++lineNo;
	}

	for (double x = lineNo * gridDensity; x <= toDraw.right(); x += gridDensity, ++lineNo) {
		if (lineNo % 5 == 0) {
			painter->setPen(thickPen);
			painter->drawLine(QPointF(x, toDraw.top()), QPointF(x, toDraw.bottom()));
			painter->setPen(defaultPen);
		} else {
			painter->drawLine(QPointF(x, toDraw.top()), QPointF(x, toDraw.bottom()));
		}
	}

	lineNo = static_cast<int>(toDraw.top() / gridDensity);
	if (toDraw.top() > 0) {
		++lineNo;
	}

	for (double y = lineNo * gridDensity; y <= toDraw.bottom(); y += gridDensity, ++lineNo) {
		if (lineNo % 5 == 0) {
			painter->setPen(thickPen);
			painter->drawLine(QPointF(toDraw.left(), y), QPointF(toDraw.right(), y));
			painter->setPen(defaultPen);
		} else {
			painter->drawLine(QPointF(toDraw.left(), y), QPointF(toDraw.right(), y));
		}
	}

}
Exemple #14
0
QRectF boundsOfChildren( QGraphicsItem const * qgi )
{
    typedef QList<QGraphicsItem*> QGIL;
    QGIL ch( qboard::childItems(qgi) );
    QRectF r;
    for( QGIL::const_iterator it = ch.begin();
	 ch.end() != it; ++it )
    {
	QGraphicsItem const * x = *it;
	QRectF r2( x->mapToParent(x->pos()), x->boundingRect().size() );
	r = r.unite( r2 );
    }
    if(1  && ! r.isNull() ) qDebug() << "bounds of children ="<<r;
    return r;
}
void BoxTextGraphicsItem::updateRect(const QRectF &rect)
{
    QRectF r = rect;
    if (!r.isNull() && r.isValid()) {
        if (r.height() < m_gi->boundingRect().height()+18) {
            r.setHeight(m_gi->boundingRect().height()+18);
        }
        if (r.width() < MINTEXTWIDTH) {
            r.setWidth(MINTEXTWIDTH);
        }
        m_gi->show();
        adaptTextItemWidth(r);
        setRect(r);
        updateHandlesPosition();
    }
}
Exemple #16
0
static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, QRectF gradientRect = QRectF())//copy from QPlainTextEditor from 4.8.1
{
    p->save();
    if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
        if (!gradientRect.isNull()) {
            QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
            m.scale(gradientRect.width(), gradientRect.height());
            brush.setTransform(m);
            const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode);
        }
    } else {
        p->setBrushOrigin(rect.topLeft());
    }
    p->fillRect(rect, brush);
    p->restore();
}
void SymbolDataEditor::setSymbolData(const QPointF _inPoint, const QPointF _outPoint, const QRectF _limits)
{
    if (scene->items().isEmpty())
        return;

    QRectF symbolRect = scene->items(Qt::AscendingOrder).at(Item::SymbolItem)->boundingRect();
    symbolRect.moveTopLeft(scene->items(Qt::AscendingOrder).at(Item::SymbolItem)->pos());
    symbolRect.adjust(symbolRect.width() / 4, symbolRect.height() / 4,
                      -symbolRect.width() / 4, -symbolRect.height() / 4);

    //try to set data automatically if they're not set
    if (_inPoint.isNull())
    {
        if (setupPoints)
            inPoint = getBeginPoint();
        else
        {
            inPoint = symbolRect.topLeft();
            inPoint.ry() += symbolRect.height() / 2;
        }
    }
    else
        inPoint = fromStored(_inPoint);

    if (_outPoint.isNull())
    {
        if (setupPoints)
            outPoint = getEndPoint();
        else
        {
            outPoint = symbolRect.topRight();
            outPoint.ry() += symbolRect.height() / 2;
        }
    }
    else
        outPoint = fromStored(_outPoint);

    if (_limits.isNull())
        limits = symbolRect;
    else
        limits = QRectF(fromStored(_limits.topLeft()),
                        fromStored(_limits.bottomRight()));

    correctLimits();
    addDataItems();
}
Exemple #18
0
void DemoItem::setPosUsingSheepDog(const QPointF &dest, const QRectF &sceneFence)
{
    this->setPos(dest);
    if (sceneFence.isNull())
        return;

    // I agree. This is not the optimal way of doing it.
    // But don't want for use time on it now....
    float itemWidth = this->boundingRect().width();
    float itemHeight = this->boundingRect().height();
    float fenceRight = sceneFence.x() + sceneFence.width();
    float fenceBottom = sceneFence.y() + sceneFence.height();

    if (this->scenePos().x() < sceneFence.x()) this->moveBy(this->mapFromScene(QPointF(sceneFence.x(), 0)).x(), 0);
    if (this->scenePos().x() > fenceRight - itemWidth) this->moveBy(this->mapFromScene(QPointF(fenceRight - itemWidth, 0)).x(), 0);
    if (this->scenePos().y() < sceneFence.y()) this->moveBy(0, this->mapFromScene(QPointF(0, sceneFence.y())).y());
    if (this->scenePos().y() > fenceBottom - itemHeight) this->moveBy(0, this->mapFromScene(QPointF(0, fenceBottom - itemHeight)).y());
}
void OrthogonalRenderer::drawTileLayer(QPainter *painter,
                                       const TileLayer *layer,
                                       const QRectF &exposed) const
{
    const int tileWidth = map()->tileWidth();
    const int tileHeight = map()->tileHeight();
    const QPointF layerPos(layer->x() * tileWidth,
                           layer->y() * tileHeight);

    painter->translate(layerPos);

    int startX = 0;
    int startY = 0;
    int endX = layer->width();
    int endY = layer->height();

    if (!exposed.isNull()) {
        const QSize maxTileSize = layer->maxTileSize();
        const int extraWidth = maxTileSize.width() - tileWidth;
        const int extraHeight = maxTileSize.height() - tileHeight;
        QRectF rect = exposed.adjusted(-extraWidth, 0, 0, extraHeight);
        rect.translate(-layerPos);

        startX = qMax((int) rect.x() / tileWidth, 0);
        startY = qMax((int) rect.y() / tileHeight, 0);
        endX = qMin((int) std::ceil(rect.right()) / tileWidth + 1, endX);
        endY = qMin((int) std::ceil(rect.bottom()) / tileHeight + 1, endY);
    }

    for (int y = startY; y < endY; ++y) {
        for (int x = startX; x < endX; ++x) {
            const Tile *tile = layer->tileAt(x, y);
            if (!tile)
                continue;

            const QPixmap &img = tile->image();
            painter->drawPixmap(x * tileWidth,
                                (y + 1) * tileHeight - img.height(),
                                img);
        }
    }

    painter->translate(-layerPos);
}
QPainterPath OrthogonalRenderer::shape(const MapObject *object) const
{
    QPainterPath path;

    if (object->tile()) {
        path.addRect(boundingRect(object));
    } else {
        switch (object->shape()) {
        case MapObject::Rectangle: {
            const QRectF bounds = object->bounds();
            const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                              tileToPixelCoords(bounds.bottomRight()));

            if (rect.isNull()) {
                path.addEllipse(rect.topLeft(), 20, 20);
            } else {
                path.addRoundedRect(rect, 10, 10);
            }
            break;
        }
        case MapObject::Polygon:
        case MapObject::Polyline: {
            const QPointF &pos = object->position();
            const QPolygonF polygon = object->polygon().translated(pos);
            const QPolygonF screenPolygon = tileToPixelCoords(polygon);
            if (object->shape() == MapObject::Polygon) {
                path.addPolygon(screenPolygon);
            } else {
                for (int i = 1; i < screenPolygon.size(); ++i) {
                    path.addPolygon(lineToPolygon(screenPolygon[i - 1],
                                                  screenPolygon[i]));
                }
                path.setFillRule(Qt::WindingFill);
            }
            break;
        }
        }
    }

    return path;
}
Exemple #21
0
QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const
{
    const QRectF bounds = object->bounds();
    const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                      tileToPixelCoords(bounds.bottomRight()));

    QRectF boundingRect;

    if (object->tile()) {
        const QPointF bottomLeft = rect.topLeft();
        const QPixmap &img = object->tile()->image();
        boundingRect = QRectF(bottomLeft.x(),
                              bottomLeft.y() - img.height(),
                              img.width(),
                              img.height()).adjusted(-1, -1, 1, 1);
    } else {
        // The -2 and +3 are to account for the pen width and shadow
        switch (object->shape()) {
        case MapObject::Ellipse:
        case MapObject::Rectangle:
            if (rect.isNull()) {
                boundingRect = rect.adjusted(-10 - 2, -10 - 2, 10 + 3, 10 + 3);
            } else {
                const int nameHeight = object->name().isEmpty() ? 0 : 15;
                boundingRect = rect.adjusted(-2, -nameHeight - 2, 3, 3);
            }
            break;

        case MapObject::Polygon:
        case MapObject::Polyline: {
            const QPointF &pos = object->position();
            const QPolygonF polygon = object->polygon().translated(pos);
            QPolygonF screenPolygon = tileToPixelCoords(polygon);
            boundingRect = screenPolygon.boundingRect().adjusted(-2, -2, 3, 3);
            break;
        }
        }
    }

    return boundingRect;
}
Exemple #22
0
static inline QPainterPath headerPath( const QRectF& r, int roundness,
                                       int headerHeight = 10 )
{
    QPainterPath path;
    int xRnd = roundness;
    int yRnd = roundness;
    if( r.width() > r.height() )
    {
        xRnd = int ( roundness * r.height() / r.width() );
    }
    else
    {
        yRnd = int ( roundness * r.width() / r.height() );
    }

    if( xRnd >= 100 )                        // fix ranges
    {
        xRnd = 99;
    }
    if( yRnd >= 100 )
    {
        yRnd = 99;
    }
    if( xRnd <= 0 || yRnd <= 0 )             // add normal rectangle
    {
        path.addRect( r );
        return path;
    }

    QRectF rect = r.normalized();

    if( rect.isNull() )
    {
        return path;
    }

    qreal x = rect.x();
    qreal y = rect.y();
    qreal w = rect.width();
    qreal h = rect.height();
    qreal rxx = w * xRnd / 200;
    qreal ryy = h * yRnd / 200;
    // were there overflows?
    if( rxx < 0 )
    {
        rxx = w / 200 * xRnd;
    }
    if( ryy < 0 )
    {
        ryy = h / 200 * yRnd;
    }
    qreal rxx2 = 2 * rxx;
    qreal ryy2 = 2 * ryy;

    path.arcMoveTo( x, y, rxx2, ryy2, 90 );
    path.arcTo( x, y, rxx2, ryy2, 90, 90 );
    QPointF pt = path.currentPosition();
    path.lineTo( x, pt.y() + headerHeight );
    path.lineTo( x + w, pt.y() + headerHeight );
    path.lineTo( x + w, pt.y() );
    path.arcTo( x + w - rxx2, y, rxx2, ryy2, 0, 90 );
    path.closeSubpath();

    return path;
}
void OrthogonalRenderer::drawTileLayer(QPainter *painter,
                                       const TileLayer *layer,
                                       const QRectF &exposed) const
{
    QTransform savedTransform = painter->transform();

    const int tileWidth = map()->tileWidth();
    const int tileHeight = map()->tileHeight();
    const QPointF layerPos(layer->x() * tileWidth,
                           layer->y() * tileHeight);

    painter->translate(layerPos);

    int startX = 0;
    int startY = 0;
    int endX = layer->width();
    int endY = layer->height();

    if (!exposed.isNull()) {
        QMargins drawMargins = layer->drawMargins();
        drawMargins.setTop(drawMargins.top() - tileHeight);
        drawMargins.setRight(drawMargins.right() - tileWidth);

        QRectF rect = exposed.adjusted(-drawMargins.right(),
                                       -drawMargins.bottom(),
                                       drawMargins.left(),
                                       drawMargins.top());

        rect.translate(-layerPos);

        startX = qMax((int) rect.x() / tileWidth, 0);
        startY = qMax((int) rect.y() / tileHeight, 0);
        endX = qMin((int) std::ceil(rect.right()) / tileWidth + 1, endX);
        endY = qMin((int) std::ceil(rect.bottom()) / tileHeight + 1, endY);
    }

    QTransform baseTransform = painter->transform();

    for (int y = startY; y < endY; ++y) {
        for (int x = startX; x < endX; ++x) {
            const Cell &cell = layer->cellAt(x, y);
            if (cell.isEmpty())
                continue;

            const QPixmap &img = cell.tile->image();
            const QPoint offset = cell.tile->tileset()->tileOffset();

            qreal m11 = 1;      // Horizontal scaling factor
            qreal m12 = 0;      // Vertical shearing factor
            qreal m21 = 0;      // Horizontal shearing factor
            qreal m22 = 1;      // Vertical scaling factor
            qreal dx = offset.x() + x * tileWidth;
            qreal dy = offset.y() + (y + 1) * tileHeight - img.height();

            if (cell.flippedAntiDiagonally) {
                // Use shearing to swap the X/Y axis
                m11 = 0;
                m12 = 1;
                m21 = 1;
                m22 = 0;

                // Compensate for the swap of image dimensions
                dy += img.height() - img.width();
            }
            if (cell.flippedHorizontally) {
                m11 = -m11;
                m21 = -m21;    
                dx += cell.flippedAntiDiagonally ? img.height() : img.width();
            }
            if (cell.flippedVertically) {
                m12 = -m12;
                m22 = -m22;
                dy += cell.flippedAntiDiagonally ? img.width() : img.height();
            }

            const QTransform transform(m11, m12, m21, m22, dx, dy);
            painter->setTransform(transform * baseTransform);

            painter->drawPixmap(0, 0, img);
        }
    }

    painter->setTransform(savedTransform);
}
Exemple #24
0
void drawTexture(const QRectF &target, const QSizeF &viewport, GLuint texture, qreal alpha, const QRectF &source)
{
    static QOpenGLShaderProgram *program = 0;
    static int vertexAttr;
    static int texCoordAttr;
    static int opacityUniform;

    if (program == 0) {
        program = generateShaderProgram(0, drawTextureVertexSrc, drawTextureFragmentSrc);
        vertexAttr = program->attributeLocation("vertexAttr");
        texCoordAttr = program->attributeLocation("texCoordAttr");
        opacityUniform = program->uniformLocation("alpha");
    }

    qreal xmin = -1 + 2 * (target.left() / viewport.width());
    qreal xmax = -1 + 2 * (target.right() / viewport.width());
    qreal ymin = -1 + 2 * (viewport.height() - target.top()) / viewport.height();
    qreal ymax = -1 + 2 * (viewport.height() - target.bottom()) / viewport.height();

    QVector2D va(xmin, ymin);
    QVector2D vb(xmax, ymin);
    QVector2D vc(xmax, ymax);
    QVector2D vd(xmin, ymax);

    QVector2D vertexCoords[] =
    {
        va, vb, vd, vd, vb, vc
    };

    QVector2D ta, tb, tc, td;

    QRectF s = source;
    if (s.isNull()) {
        s = QRectF(0, 0, 1, 1);
        ta = QVector2D(s.left(), s.top());
        tb = QVector2D(s.right(), s.top());
        tc = QVector2D(s.right(), s.bottom());
        td = QVector2D(s.left(), s.bottom());
    } else {
        ta = QVector2D(s.left(), s.top());
        tb = QVector2D(s.right(), s.top());
        tc = QVector2D(s.right(), s.bottom());
        td = QVector2D(s.left(), s.bottom());
    }

    QVector2D texCoords[] =
    {
        ta, tb, td, td, tb, tc
    };

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    program->bind();
    program->setUniformValue(opacityUniform, GLfloat(alpha));

    program->enableAttributeArray(vertexAttr);
    program->setAttributeArray(vertexAttr, vertexCoords);
    program->enableAttributeArray(texCoordAttr);
    program->setAttributeArray(texCoordAttr, texCoords);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    program->disableAttributeArray(vertexAttr);
    program->disableAttributeArray(texCoordAttr);
}
void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int height, double position, int force_refresh )
{
  	// 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 );
	
	// Check if user wants us to reload the image
	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 );
	}
	
	if (self->current_image == NULL) {
		// restore QGraphicsScene
		QGraphicsScene *scene = static_cast<QGraphicsScene *> (mlt_properties_get_data( producer_props, "qscene", NULL ));

		if ( force_refresh == 1 && scene )
		{
			scene = NULL;
			mlt_properties_set_data( producer_props, "qscene", NULL, 0, NULL, NULL );
		}

		if ( scene == NULL )
		{
			int argc = 1;
			char* argv[1];
			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>( "QTextCursor" );
			}
			scene = new QGraphicsScene();
			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, width, 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( 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 );
}
void QQuickTextNodeEngine::processCurrentLine()
{
    // No glyphs, do nothing
    if (m_currentLineTree.isEmpty())
        return;

    // 1. Go through current line and get correct decoration position for each node based on
    // neighbouring decorations. Add decoration to global list
    // 2. Create clip nodes for all selected text. Try to merge as many as possible within
    // the line.
    // 3. Add QRects to a list of selection rects.
    // 4. Add all nodes to a global processed list
    QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
    BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);

    Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());

    SelectionState currentSelectionState = Unselected;
    QRectF currentRect;

    QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration;
    qreal underlineOffset = 0.0;
    qreal underlineThickness = 0.0;

    qreal overlineOffset = 0.0;
    qreal overlineThickness = 0.0;

    qreal strikeOutOffset = 0.0;
    qreal strikeOutThickness = 0.0;

    QRectF decorationRect = currentRect;

    QColor lastColor;
    QColor lastBackgroundColor;

    QVarLengthArray<TextDecoration> pendingUnderlines;
    QVarLengthArray<TextDecoration> pendingOverlines;
    QVarLengthArray<TextDecoration> pendingStrikeOuts;
    if (!sortedIndexes.isEmpty()) {
        QQuickDefaultClipNode *currentClipNode = m_hasSelection ? new QQuickDefaultClipNode(QRectF()) : 0;
        bool currentClipNodeUsed = false;
        for (int i=0; i<=sortedIndexes.size(); ++i) {
            BinaryTreeNode *node = 0;
            if (i < sortedIndexes.size()) {
                int sortedIndex = sortedIndexes.at(i);
                Q_ASSERT(sortedIndex < m_currentLineTree.size());

                node = m_currentLineTree.data() + sortedIndex;
            }

            if (i == 0)
                currentSelectionState = node->selectionState;

            // Update decorations
            if (currentDecorations != QQuickTextNode::NoDecoration) {
                decorationRect.setY(m_position.y() + m_currentLine.y());
                decorationRect.setHeight(m_currentLine.height());

                if (node != 0)
                    decorationRect.setRight(node->boundingRect.left());

                TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
                if (currentDecorations & QQuickTextNode::Underline)
                    pendingUnderlines.append(textDecoration);

                if (currentDecorations & QQuickTextNode::Overline)
                    pendingOverlines.append(textDecoration);

                if (currentDecorations & QQuickTextNode::StrikeOut)
                    pendingStrikeOuts.append(textDecoration);

                if (currentDecorations & QQuickTextNode::Background)
                    m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor));
            }

            // If we've reached an unselected node from a selected node, we add the
            // selection rect to the graph, and we add decoration every time the
            // selection state changes, because that means the text color changes
            if (node == 0 || node->selectionState != currentSelectionState) {
                currentRect.setY(m_position.y() + m_currentLine.y());
                currentRect.setHeight(m_currentLine.height());

                if (currentSelectionState == Selected)
                    m_selectionRects.append(currentRect);

                if (currentClipNode != 0) {
                    if (!currentClipNodeUsed) {
                        delete currentClipNode;
                    } else {
                        currentClipNode->setIsRectangular(true);
                        currentClipNode->setRect(currentRect);
                        currentClipNode->update();
                    }
                }

                if (node != 0 && m_hasSelection)
                    currentClipNode = new QQuickDefaultClipNode(QRectF());
                else
                    currentClipNode = 0;
                currentClipNodeUsed = false;

                if (node != 0) {
                    currentSelectionState = node->selectionState;
                    currentRect = node->boundingRect;

                    // Make sure currentRect is valid, otherwise the unite won't work
                    if (currentRect.isNull())
                        currentRect.setSize(QSizeF(1, 1));
                }
            } else {
                if (currentRect.isNull())
                    currentRect = node->boundingRect;
                else
                    currentRect = currentRect.united(node->boundingRect);
            }

            if (node != 0) {
                if (node->selectionState == Selected) {
                    node->clipNode = currentClipNode;
                    currentClipNodeUsed = true;
                }

                decorationRect = node->boundingRect;

                // If previous item(s) had underline and current does not, then we add the
                // pending lines to the lists and likewise for overlines and strikeouts
                if (!pendingUnderlines.isEmpty()
                        && !(node->decorations & QQuickTextNode::Underline)) {
                    addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);

                    pendingUnderlines.clear();

                    underlineOffset = 0.0;
                    underlineThickness = 0.0;
                }

                // ### Add pending when overlineOffset/thickness changes to minimize number of
                // nodes
                if (!pendingOverlines.isEmpty()) {
                    addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);

                    pendingOverlines.clear();

                    overlineOffset = 0.0;
                    overlineThickness = 0.0;
                }

                // ### Add pending when overlineOffset/thickness changes to minimize number of
                // nodes
                if (!pendingStrikeOuts.isEmpty()) {
                    addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);

                    pendingStrikeOuts.clear();

                    strikeOutOffset = 0.0;
                    strikeOutThickness = 0.0;
                }

                // Merge current values with previous. Prefer greatest thickness
                QRawFont rawFont = node->glyphRun.rawFont();
                if (node->decorations & QQuickTextNode::Underline) {
                    if (rawFont.lineThickness() > underlineThickness) {
                        underlineThickness = rawFont.lineThickness();
                        underlineOffset = rawFont.underlinePosition();
                    }
                }

                if (node->decorations & QQuickTextNode::Overline) {
                    overlineOffset = -rawFont.ascent();
                    overlineThickness = rawFont.lineThickness();
                }

                if (node->decorations & QQuickTextNode::StrikeOut) {
                    strikeOutThickness = rawFont.lineThickness();
                    strikeOutOffset = rawFont.ascent() / -3.0;
                }

                currentDecorations = node->decorations;
                lastColor = node->color;
                lastBackgroundColor = node->backgroundColor;
                m_processedNodes.append(*node);
            }
        }

        if (!pendingUnderlines.isEmpty())
            addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);

        if (!pendingOverlines.isEmpty())
            addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);

        if (!pendingStrikeOuts.isEmpty())
            addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
    }

    m_currentLineTree.clear();
    m_currentLine = QTextLine();
    m_hasSelection = false;
}
Exemple #27
0
static void qtmDrawRoundedRect(QPainter *p, const QRectF &rect, qreal xRadius, qreal yRadius,
                               Qt::SizeMode mode)
{
  QRectF r = rect.normalized();
  
  if (r.isNull())
    return;
  
  if (mode == Qt::AbsoluteSize) {
    qreal w = r.width() / 2;
    qreal h = r.height() / 2;
    
    xRadius = 100 * qMin(xRadius, w) / w;
    yRadius = 100 * qMin(yRadius, h) / h;
  } else {
    if (xRadius > 100)                          // fix ranges
      xRadius = 100;
    
    if (yRadius > 100)
      yRadius = 100;
  }
  
  QPainterPath path;
  
  if (xRadius <= 0 || yRadius <= 0) {             // add normal rectangle
    path.addRect(r);
  } else {
    qreal x = r.x();
    qreal y = r.y();
    qreal w = r.width();
    qreal h = r.height();
    qreal rxx2 = w*xRadius/100;
    qreal ryy2 = h*yRadius/100;
    
#ifdef Q_WS_X11
    // There is a bug (probably in arcTo) for small sizes.
    // We use a rough linear approx.
    rxx2 /= 4;
    ryy2 /= 4;
    path.moveTo(x+rxx2,y);
    path.lineTo(x+w-rxx2, y);
    path.lineTo(x+w, y+ryy2);
    path.lineTo(x+w, y+h-ryy2);    
    path.lineTo(x+w-rxx2, y+h);    
    path.lineTo(x+rxx2, y+h);    
    path.lineTo(x, y+h-ryy2);    
    path.lineTo(x, y+ryy2);    
    path.closeSubpath();
#else
    path.moveTo(x+rxx2,y);
    path.arcMoveTo(x, y, rxx2, ryy2, 90);
    path.arcTo(x, y, rxx2, ryy2, 90, 90);
    path.arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90);
    path.arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 3*90, 90);
    path.arcTo(x+w-rxx2, y, rxx2, ryy2, 0, 90);
    path.closeSubpath();
#endif
  }
  
  p->drawPath(path);
}
void OrthogonalRenderer::drawMapObject(QPainter *painter,
                                       const MapObject *object,
                                       const QColor &color) const
{
    painter->save();

    QColor brushColor = color;
    brushColor.setAlpha(50);
    QBrush brush(brushColor);

    QPen pen(Qt::black);
    pen.setWidth(3);
    pen.setJoinStyle(Qt::RoundJoin);

    // Make sure the line aligns nicely on the pixels
    if (pen.width() % 2)
        painter->translate(0.5, 0.5);

    painter->setPen(pen);
    painter->setRenderHint(QPainter::Antialiasing);
    const QFontMetrics fm = painter->fontMetrics();

    const QRectF bounds = object->bounds();
    const QRectF rect(tileToPixelCoords(bounds.topLeft()),
                      tileToPixelCoords(bounds.bottomRight()));
    painter->translate(rect.topLeft());

    if (rect.isNull())
    {
        QString name = fm.elidedText(object->name(), Qt::ElideRight, 30);

        // Draw the shadow
        painter->drawEllipse(QRect(- 10 + 1, - 10 + 1, 20, 20));
        painter->drawText(QPoint(-15 + 1, -15 + 1), name);

        pen.setColor(color);
        painter->setPen(pen);
        painter->setBrush(brush);
        painter->drawEllipse(QRect(-10, -10, 20, 20));
        painter->drawText(QPoint(-15, -15), name);
    }
    else
    {
        QString name = fm.elidedText(object->name(), Qt::ElideRight,
                                     rect.width() + 2);

        // Draw the shadow
        painter->drawRoundedRect(QRectF(QPointF(1, 1), rect.size()),
                                 10.0, 10.0);
        painter->drawText(QPoint(1, -5 + 1), name);

        pen.setColor(color);
        painter->setPen(pen);
        painter->setBrush(brush);
        painter->drawRoundedRect(QRectF(QPointF(0, 0), rect.size()),
                                 10.0, 10.0);
        painter->drawText(QPoint(0, -5), name);
    }

    painter->restore();
}
void QVGPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
{
    if (src.isNull())
        return;

    if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
        // The pixmap data is not an instance of QVGPixmapData, so fall
        // back to the default colorize filter implementation.
        QPixmapColorizeFilter::draw(painter, dest, src, srcRect);
        return;
    }

    QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());

    VGImage srcImage = pd->toVGImage();
    if (srcImage == VG_INVALID_HANDLE)
        return;

    QSize size = pd->size();
    VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
        (VG_sARGB_8888_PRE, size.width(), size.height(),
         VG_IMAGE_QUALITY_FASTER, pd);
    if (dstImage == VG_INVALID_HANDLE)
        return;

    // Determine the weights for the matrix from the color and strength.
    QColor c = color();
    VGfloat strength = this->strength();
    VGfloat weights[3];
    VGfloat invweights[3];
    VGfloat alpha = c.alphaF();
    weights[0] = c.redF() * alpha;
    weights[1] = c.greenF() * alpha;
    weights[2] = c.blueF() * alpha;
    invweights[0] = (1.0f - weights[0]) * strength;
    invweights[1] = (1.0f - weights[1]) * strength;
    invweights[2] = (1.0f - weights[2]) * strength;

    // Grayscale weights.
    static const VGfloat redGray = 11.0f / 32.0f;
    static const VGfloat greenGray = 16.0f / 32.0f;
    static const VGfloat blueGray = 1.0f - (redGray + greenGray);

    VGfloat matrix[5][4];
    matrix[0][0] = redGray * invweights[0] + (1.0f - strength);
    matrix[0][1] = redGray * invweights[1];
    matrix[0][2] = redGray * invweights[2];
    matrix[0][3] = 0.0f;
    matrix[1][0] = greenGray * invweights[0];
    matrix[1][1] = greenGray * invweights[1] + (1.0f - strength);
    matrix[1][2] = greenGray * invweights[2];
    matrix[1][3] = 0.0f;
    matrix[2][0] = blueGray * invweights[0];
    matrix[2][1] = blueGray * invweights[1];
    matrix[2][2] = blueGray * invweights[2] + (1.0f - strength);
    matrix[2][3] = 0.0f;
    matrix[3][0] = 0.0f;
    matrix[3][1] = 0.0f;
    matrix[3][2] = 0.0f;
    matrix[3][3] = 1.0f;
    matrix[4][0] = weights[0] * strength;
    matrix[4][1] = weights[1] * strength;
    matrix[4][2] = weights[2] * strength;
    matrix[4][3] = 0.0f;

    vgColorMatrix(dstImage, srcImage, matrix[0]);

    VGImage child = VG_INVALID_HANDLE;

    if (srcRect.isNull() ||
        (srcRect.topLeft().isNull() && srcRect.size() == size)) {
        child = dstImage;
    } else {
        QRect src = srcRect.toRect();
        child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
    }

    qt_vg_drawVGImage(painter, dest, child);

    if(child != dstImage)
        vgDestroyImage(child);
    QVGImagePool::instance()->releaseImage(0, dstImage);
}
void QVGPixmapConvolutionFilter::draw
        (QPainter *painter, const QPointF &dest,
         const QPixmap &src, const QRectF &srcRect) const
{
    if (src.isNull())
        return;

    if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
        // The pixmap data is not an instance of QVGPixmapData, so fall
        // back to the default convolution filter implementation.
        QPixmapConvolutionFilter::draw(painter, dest, src, srcRect);
        return;
    }

    QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());

    VGImage srcImage = pd->toVGImage();
    if (srcImage == VG_INVALID_HANDLE)
        return;

    QSize size = pd->size();
    VGImage dstImage = QVGImagePool::instance()->createTemporaryImage
        (VG_sARGB_8888_PRE, size.width(), size.height(),
         VG_IMAGE_QUALITY_FASTER, pd);
    if (dstImage == VG_INVALID_HANDLE)
        return;

    int kernelWidth = rows();
    int kernelHeight = columns();
    const qreal *kern = convolutionKernel();
    QVarLengthArray<VGshort> kernel;
    for (int i = 0; i < kernelWidth; ++i) {
        for (int j = 0; j < kernelHeight; ++j) {
            kernel.append((VGshort)(kern[j * kernelWidth + i] * 1024.0f));
        }
    }

    VGfloat values[4];
    values[0] = 0.0f;
    values[1] = 0.0f;
    values[2] = 0.0f;
    values[3] = 0.0f;
    vgSetfv(VG_TILE_FILL_COLOR, 4, values);

    vgConvolve(dstImage, srcImage,
               kernelWidth, kernelHeight, 0, 0,
               kernel.constData(), 1.0f / 1024.0f, 0.0f,
               VG_TILE_FILL);

    VGImage child = VG_INVALID_HANDLE;

    if (srcRect.isNull() ||
        (srcRect.topLeft().isNull() && srcRect.size() == size)) {
        child = dstImage;
    } else {
        QRect src = srcRect.toRect();
        child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
    }

    qt_vg_drawVGImage(painter, dest, child);

    if(child != dstImage)
        vgDestroyImage(child);
    QVGImagePool::instance()->releaseImage(0, dstImage);
}