Example #1
0
void TransformTest::testEstimateNonIsometric()
{
	// Scaling and translation
	PassPointList passpoints;
	passpoints.resize(3);
	passpoints[0].src_coords  = MapCoordF { 128.0, 0.0 };
	passpoints[0].dest_coords = MapCoordF { 64.0, 64.0 };
	passpoints[1].src_coords  = MapCoordF { 256.0, 0.0 };
	passpoints[1].dest_coords = MapCoordF { 96.0, 64.0 };
	passpoints[2].src_coords  = MapCoordF { 128.0, 128.0 };
	passpoints[2].dest_coords = MapCoordF { 64.0, 96.0 };
	
	QTransform qt;
	QVERIFY(passpoints.estimateNonIsometricSimilarityTransform(&qt));
	QVERIFY(qt.isTranslating());
	QVERIFY(qt.isScaling());
	QCOMPARE(int(qt.type()), int(QTransform::TxScale));
	
	QCOMPARE(qt.map(passpoints[0].src_coords), QPointF{passpoints[0].dest_coords});
	QCOMPARE(qt.map(passpoints[1].src_coords), QPointF{passpoints[1].dest_coords});
	QCOMPARE(qt.map(passpoints[2].src_coords), QPointF{passpoints[2].dest_coords});
	
	auto t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, MapCoord(32,64).nativeX());
	QCOMPARE(t.template_y, MapCoord(32,64).nativeY());
	QCOMPARE(t.template_scale_x, 0.25);
	QCOMPARE(t.template_scale_y, 0.25);
	QVERIFY(qAbs(t.template_rotation) < 0.000001);
	
	// Rotation
	passpoints[0].src_coords  = MapCoordF { 0.0, 0.0 };
	passpoints[0].dest_coords = MapCoordF { 0.0, 0.0 };
	passpoints[1].src_coords  = MapCoordF { 5.0, 0.0 };
	passpoints[1].dest_coords = MapCoordF { 4.0, -3.0 };
	passpoints[2].src_coords  = MapCoordF { 0.0, 5.0 };
	passpoints[2].dest_coords = MapCoordF { 3.0, 4.0 };
	
	QVERIFY(passpoints.estimateNonIsometricSimilarityTransform(&qt));
	QVERIFY(qt.isRotating());
	QCOMPARE(int(qt.type()), int(QTransform::TxRotate));
	
	QCOMPARE(qt.map(passpoints[0].src_coords), QPointF{passpoints[0].dest_coords});
	QCOMPARE(qt.map(passpoints[1].src_coords), QPointF{passpoints[1].dest_coords});
	QCOMPARE(qt.map(passpoints[2].src_coords), QPointF{passpoints[2].dest_coords});
	
	t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, 0);
	QCOMPARE(t.template_y, 0);
	QCOMPARE(t.template_scale_x, 1.0);
	QCOMPARE(t.template_scale_y, 1.0);
	QCOMPARE(t.template_rotation, qAcos(passpoints[1].dest_coords.x() / passpoints[1].src_coords.x()));
}
Example #2
0
bool PictureShape::saveSvg(SvgSavingContext &context)
{
    KoImageData *imageData = qobject_cast<KoImageData*>(userData());
    if (!imageData) {
        qWarning() << "Picture has no image data. Omitting.";
        return false;
    }

    context.shapeWriter().startElement("image");
    context.shapeWriter().addAttribute("id", context.getID(this));

    QTransform m = transformation();
    if (m.type() == QTransform::TxTranslate) {
        const QPointF pos = position();
        context.shapeWriter().addAttributePt("x", pos.x());
        context.shapeWriter().addAttributePt("y", pos.y());
    } else {
        context.shapeWriter().addAttribute("transform", SvgUtil::transformToString(m));
    }

    const QSizeF s = size();
    context.shapeWriter().addAttributePt("width", s.width());
    context.shapeWriter().addAttributePt("height", s.height());
    context.shapeWriter().addAttribute("xlink:href", context.saveImage(imageData));
    context.shapeWriter().endElement();

    return true;
}
Example #3
0
void TransformTest::testTransformCombined()
{
	QFETCH(int, type);
	QFETCH(double, rotation);
	
	qint32 dx = -3000;
	qint32 dy = 16000;
	qreal scale_x = 4.5;
	qreal scale_y = 2.5;
	
	QTransform qt;
	// Template::applyTemplateTransform order: translate, rotate, scale
	qt.translate(dx / 1000.0, dy / 1000.0);
	qt.rotate(qreal(rotation));
	qt.scale(scale_x, scale_y);
	QVERIFY(qt.isScaling());
	QCOMPARE(int(qt.type()), type);
	
	auto t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, dx);
	QCOMPARE(t.template_y, dy);
	QCOMPARE(t.template_scale_x, scale_x);
	QCOMPARE(t.template_scale_y, scale_y);
	if (rotation <= 180.0)
		QCOMPARE(t.template_rotation, -qDegreesToRadians(qreal(rotation)));
	else
		QCOMPARE(t.template_rotation, -qDegreesToRadians(qreal(rotation - 360.0)));
}
Example #4
0
QT_BEGIN_NAMESPACE

static inline bool qtransform_equals_no_translate(const QTransform &a, const QTransform &b)
{
    if (a.type() <= QTransform::TxTranslate && b.type() <= QTransform::TxTranslate) {
        return true;
    } else {
        // We always use paths for perspective text anyway, so no
        // point in checking the full matrix...
        Q_ASSERT(a.type() < QTransform::TxProject);
        Q_ASSERT(b.type() < QTransform::TxProject);

        return a.m11() == b.m11()
            && a.m12() == b.m12()
            && a.m21() == b.m21()
            && a.m22() == b.m22();
    }
}
QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
                                         Qt::TransformationMode mode) const
{
    QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
#ifdef QT_NO_DIRECTFB_SUBSURFACE
    if (lockFlags())
        that->unlockSurface();
#endif

    if (!dfbSurface || transform.type() != QTransform::TxScale
        || mode != Qt::FastTransformation)
    {
        const QImage *image = that->buffer();
        Q_ASSERT(image);
        const QImage transformed = image->transformed(transform, mode);
        QDirectFBPixmapData *data = new QDirectFBPixmapData(screen, QPixmapData::PixmapType);
        data->fromImage(transformed, Qt::AutoColor);
        return QPixmap(data);
    }

    const QSize size = transform.mapRect(QRect(0, 0, w, h)).size();
    if (size.isEmpty())
        return QPixmap();

    QDirectFBPixmapData *data = new QDirectFBPixmapData(screen, QPixmapData::PixmapType);
    data->setSerialNumber(++global_ser_no);
    DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
    data->alpha = alpha;
    if (alpha) {
        flags = DSBLIT_BLEND_ALPHACHANNEL;
    }
    data->dfbSurface = screen->createDFBSurface(size,
                                                imageFormat,
                                                QDirectFBScreen::TrackSurface);
    if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
        data->dfbSurface->Clear(data->dfbSurface, 0, 0, 0, 0);
    }
    data->dfbSurface->SetBlittingFlags(data->dfbSurface, flags);

    const DFBRectangle destRect = { 0, 0, size.width(), size.height() };
    data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect);
    data->w = size.width();
    data->h = size.height();
    data->is_null = (data->w <= 0 || data->h <= 0);

#if (Q_DIRECTFB_VERSION >= 0x010000)
    data->dfbSurface->ReleaseSource(data->dfbSurface);
#endif
    return QPixmap(data);
}
Example #6
0
void TransformTest::testTransformTranslate()
{
	MapCoord offset { 100.0, 100.0 };
	QTransform qt;
	qt.translate(offset.x(), offset.y());
	QVERIFY(qt.isTranslating());
	QCOMPARE(int(qt.type()), int(QTransform::TxTranslate));
	
	auto t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, offset.nativeX());
	QCOMPARE(t.template_y, offset.nativeY());
	QCOMPARE(t.template_scale_x, 1.0);
	QCOMPARE(t.template_scale_y, 1.0);
	QCOMPARE(t.template_rotation, 0.0);
}
Example #7
0
void TransformTest::testTransformProject()
{
	qreal scale_x = 4.5;
	qreal scale_y = 2.5;
	QTransform qt;
	qt.scale(scale_x, scale_y);
	QVERIFY(qt.isScaling());
	QCOMPARE(int(qt.type()), int(QTransform::TxScale));
	
	auto t = TemplateTransform::fromQTransform(qt);

	QCOMPARE(t.template_x, 0);
	QCOMPARE(t.template_y, 0);
	QCOMPARE(t.template_scale_x, scale_x);
	QCOMPARE(t.template_scale_y, scale_y);
	QCOMPARE(t.template_rotation, 0.0);
}
Example #8
0
void TransformTest::testTransformRotate()
{
	QFETCH(int, type);
	QFETCH(double, rotation);
	
	QTransform qt;
	qt.rotate(qreal(rotation), Qt::ZAxis);
	QCOMPARE(int(qt.type()), type);
	
	auto t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, 0);
	QCOMPARE(t.template_y, 0);
	QCOMPARE(t.template_scale_x, 1.0);
	QCOMPARE(t.template_scale_y, 1.0);
	if (rotation <= 180.0)
		QCOMPARE(t.template_rotation, -qDegreesToRadians(qreal(rotation)));
	else
		QCOMPARE(t.template_rotation, -qDegreesToRadians(qreal(rotation - 360.0)));
}
static QTransform preciselyInverted( const QTransform& transform )
{
    QTransform inverted;

    switch ( transform.type() ) {
        case QTransform::TxNone:
            break;

        case QTransform::TxTranslate:
            inverted.translate( -transform.dx(), -transform.dy() );
            break;

        case QTransform::TxScale:
            inverted.scale( 1.0 / transform.m11(), 1.0 / transform.m22() );
            inverted.translate( -transform.dx(), -transform.dy() );
            break;

        default:
            inverted = transform.inverted();
    }

    return inverted;
}
Example #10
0
QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
                                         Qt::TransformationMode mode) const
{
    if (!surface || transform.type() != QTransform::TxScale
        || mode != Qt::FastTransformation)
    {
        QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
        const QImage *image = that->buffer();
        if (image) { // avoid deep copy
            const QImage transformed = image->transformed(transform, mode);
            that->unlockDirectFB();
            QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType());
            data->fromImage(transformed, Qt::AutoColor);
            return QPixmap(data);
        }
        return QPixmapData::transformed(transform, mode);
    }

    int w, h;
    surface->GetSize(surface, &w, &h);

    const QSize size = transform.mapRect(QRect(0, 0, w, h)).size();
    if (size.isEmpty())
        return QPixmap();

    QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType());
    data->resize(size.width(), size.height());

    IDirectFBSurface *dest = data->surface;
    dest->SetBlittingFlags(dest, DSBLIT_NOFX);

    const DFBRectangle srcRect = { 0, 0, w, h };
    const DFBRectangle destRect = { 0, 0, size.width(), size.height() };
    dest->StretchBlit(dest, surface, &srcRect, &destRect);

    return QPixmap(data);
}
Example #11
0
void TransformTest::testTransformIdentity()
{
	// Default QTransform: identity
	QTransform qt;
	QVERIFY(qt.isIdentity());
	QCOMPARE(int(qt.type()), int(QTransform::TxNone));
	
	// Default TemplateTransform: identity
	TemplateTransform t;
	
	// TemplateTransform list initialization, and assignment
	t = { 12, -3, 0.1, 2.0, 3.0 };
	QCOMPARE(t.template_x, 12);
	QCOMPARE(t.template_y, -3);
	QCOMPARE(t.template_scale_x, 2.0);
	QCOMPARE(t.template_scale_y, 3.0);
	QCOMPARE(t.template_rotation, 0.1);
	
	// Now transfer the identity QTransform to the TemplateTransform
	t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, 0);
	QCOMPARE(t.template_y, 0);
	QCOMPARE(t.template_scale_x, 1.0);
	QCOMPARE(t.template_scale_y, 1.0);
	QCOMPARE(t.template_rotation, 0.0);
	
	// Put something different in the QTransform
	qt.translate(4, 8);
	qt.rotate(1);
	qt.scale(2.0, 1.5);
	QVERIFY(qt.isAffine());
	QVERIFY(!qt.isIdentity());
	QVERIFY(qt.isTranslating());
	QVERIFY(qt.isRotating());
	QVERIFY(qt.isScaling());
}
Example #12
0
/*!
    \internal
*/
void QDeclarativePaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
    Q_D(QDeclarativePaintedItem);
    const QRect content = boundingRect().toRect();
    if (content.width() <= 0 || content.height() <= 0)
        return;

    ++inpaint;

    const QTransform &x = p->deviceTransform();
    QTransform xinv = x.inverted();
    QRegion effectiveClip;
    QRegion sysClip = p->paintEngine()->systemClip();
    if (xinv.type() <= QTransform::TxScale && sysClip.numRects() < 5) {
        // simple transform, region gets no more complicated...
        effectiveClip = xinv.map(sysClip);
    } else {
        // do not make complicated regions...
        effectiveClip = xinv.mapRect(sysClip.boundingRect());
    }

    QRegion topaint = p->clipRegion();
    if (topaint.isEmpty()) {
        if (effectiveClip.isEmpty())
            topaint = QRect(0,0,p->device()->width(),p->device()->height());
        else
            topaint = effectiveClip;
    } else if (!effectiveClip.isEmpty()) {
        topaint &= effectiveClip;
    }

    topaint &= content;
    QRegion uncached(content);
    p->setRenderHints(QPainter::SmoothPixmapTransform, d->smooth);

    int cachesize=0;
    for (int i=0; i<d->imagecache.count(); ++i) {
        QRect area = d->imagecache[i]->area;
        if (topaint.contains(area)) {
            QRectF target(area.x(), area.y(), area.width(), area.height());
            if (!d->cachefrozen) {
                if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) {
#ifdef Q_WS_MAC
                    bool oldSmooth = qt_applefontsmoothing_enabled;
                    qt_applefontsmoothing_enabled = false;
#endif
                    QPainter qp(&d->imagecache[i]->image);
#ifdef Q_WS_MAC
                    qt_applefontsmoothing_enabled = oldSmooth;
#endif
                    qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);
                    qp.translate(-area.x(), -area.y());
                    qp.scale(d->contentsScale,d->contentsScale);
                    QRect clip = d->imagecache[i]->dirty;
                    QRect sclip(qFloor(clip.x()/d->contentsScale),
                            qFloor(clip.y()/d->contentsScale),
                            qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)),
                            qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale)));
                    qp.setClipRect(sclip);
                    if (d->fillColor.isValid()){
                        if(d->fillColor.alpha() < 255){
                            // ### Might not work outside of raster paintengine
                            QPainter::CompositionMode prev = qp.compositionMode();
                            qp.setCompositionMode(QPainter::CompositionMode_Source);
                            qp.fillRect(sclip,d->fillColor);
                            qp.setCompositionMode(prev);
                        }else{
                            qp.fillRect(sclip,d->fillColor);
                        }
                    }
                    drawContents(&qp, sclip);
                    d->imagecache[i]->dirty = QRect();
                }
            }
            p->drawPixmap(target.toRect(), d->imagecache[i]->image);
            topaint -= area;
            d->imagecache[i]->age=0;
        } else {
            d->imagecache[i]->age++;
        }
        cachesize += area.width()*area.height();
        uncached -= area;
    }

    if (!topaint.isEmpty()) {
        if (!d->cachefrozen) {
            // Find a sensible larger area, otherwise will paint lots of tiny images.
            QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
            cachesize += biggerrect.width() * biggerrect.height();
            while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
                int oldest=-1;
                int age=-1;
                for (int i=0; i<d->imagecache.count(); ++i) {
                    int a = d->imagecache[i]->age;
                    if (a > age) {
                        oldest = i;
                        age = a;
                    }
                }
                cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
                uncached += d->imagecache[oldest]->area;
                delete d->imagecache.takeAt(oldest);
            }
            const QRegion bigger = QRegion(biggerrect) & uncached;
            const QVector<QRect> rects = bigger.rects();
            for (int i = 0; i < rects.count(); ++i) {
                const QRect &r = rects.at(i);
                QPixmap img(r.size());
                if (d->fillColor.isValid())
                    img.fill(d->fillColor);
                {
#ifdef Q_WS_MAC
                    bool oldSmooth = qt_applefontsmoothing_enabled;
                    qt_applefontsmoothing_enabled = false;
#endif
                    QPainter qp(&img);
#ifdef Q_WS_MAC
                    qt_applefontsmoothing_enabled = oldSmooth;
#endif
                    qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);

                    qp.translate(-r.x(),-r.y());
                    qp.scale(d->contentsScale,d->contentsScale);
                    QRect sclip(qFloor(r.x()/d->contentsScale),
                            qFloor(r.y()/d->contentsScale),
                            qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)),
                            qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale)));
                    drawContents(&qp, sclip);
                }
                QDeclarativePaintedItemPrivate::ImageCacheItem *newitem = new QDeclarativePaintedItemPrivate::ImageCacheItem;
                newitem->area = r;
                newitem->image = img;
                d->imagecache.append(newitem);
                p->drawPixmap(r, newitem->image);
            }
        } else {
            const QVector<QRect> rects = uncached.rects();
            for (int i = 0; i < rects.count(); ++i)
                p->fillRect(rects.at(i), Qt::lightGray);
        }
    }

    if (inpaint_clearcache) {
        clearCache();
        inpaint_clearcache = 0;
    }

    --inpaint;
}