Example #1
0
void AbstractDiagram::Private::addLabel(
    LabelPaintCache* cache,
    const QModelIndex& index,
    const CartesianDiagramDataCompressor::CachePosition* position,
    const PositionPoints& points,
    const Position& autoPositionPositive, const Position& autoPositionNegative,
    const qreal value, qreal favoriteAngle /* = 0.0 */ )
{
    CartesianDiagramDataCompressor::AggregatedDataValueAttributes allAttrs(
        aggregatedAttrs( index, position ) );

    QMap<QModelIndex, DataValueAttributes>::const_iterator it;
    for ( it = allAttrs.constBegin(); it != allAttrs.constEnd(); ++it ) {
        DataValueAttributes dva = it.value();
        if ( !dva.isVisible() ) {
            continue;
        }

        const bool isPositive = ( value >= 0.0 );

        RelativePosition relPos( dva.position( isPositive ) );
        relPos.setReferencePoints( points );
        if ( relPos.referencePosition().isUnknown() ) {
            relPos.setReferencePosition( isPositive ? autoPositionPositive : autoPositionNegative );
        }

        // Rotate the label position (not the label itself) if the diagram is rotated so that the defaults still work
        if ( isTransposed() ) {
            KChartEnums::PositionValue posValue = relPos.referencePosition().value();
            if ( posValue >= KChartEnums::PositionNorthWest && posValue <= KChartEnums::PositionWest ) {
                // rotate 90 degrees clockwise
                posValue = static_cast< KChartEnums::PositionValue >( posValue + 2 );
                if ( posValue > KChartEnums::PositionWest ) {
                    // wraparound
                    posValue = static_cast< KChartEnums::PositionValue >( posValue -
                                ( KChartEnums::PositionWest - KChartEnums::PositionNorthWest ) );
                }
                relPos.setReferencePosition( Position( posValue ) );
            }
        }

        const QPointF referencePoint = relPos.referencePoint();
        if ( !diagram->coordinatePlane()->isVisiblePoint( referencePoint ) ) {
            continue;
        }

        const qreal fontHeight = cachedFontMetrics( dva.textAttributes().
                calculatedFont( plane, KChartEnums::MeasureOrientationMinimum ), diagram )->height();

        // Note: When printing data value texts and padding's Measure is using automatic reference area
        //       detection, the font height is used as reference size for both horizontal and vertical
        //       padding.
        QSizeF relativeMeasureSize( fontHeight, fontHeight );

        if ( !dva.textAttributes().hasRotation() ) {
            TextAttributes ta = dva.textAttributes();
            ta.setRotation( favoriteAngle );
            dva.setTextAttributes( ta );
        }

        // get the size of the label text using a subset of the information going into the final layout
        const QString text = formatDataValueText( dva, index, value );
        QTextDocument doc;
        doc.setDocumentMargin( 0 );
        if ( Qt::mightBeRichText( text ) ) {
            doc.setHtml( text );
        } else {
            doc.setPlainText( text );
        }
        const QFont calculatedFont( dva.textAttributes()
                                    .calculatedFont( plane, KChartEnums::MeasureOrientationMinimum ) );
        doc.setDefaultFont( calculatedFont );

        const QRectF plainRect = doc.documentLayout()->frameBoundingRect( doc.rootFrame() );

        /**
        * A few hints on how the positioning of the text frame is done:
        *
        * Let's assume we have a bar chart, a text for a positive value
        * to be drawn, and "North" as attrs.positivePosition().
        *
        * The reference point (pos) is then set to the top center point
        * of a bar. The offset now depends on the alignment:
        *
        *    Top: text is centered horizontally to the bar, bottom of
        *         text frame starts at top of bar
        *
        *    Bottom: text is centered horizontally to the bar, top of
        *            text frame starts at top of bar
        *
        *    Center: text is centered horizontally to the bar, center
        *            line of text frame is same as top of bar
        *
        *    TopLeft: right edge of text frame is horizontal center of
        *             bar, bottom of text frame is top of bar.
        *
        *    ...
        *
        * Positive and negative value labels are treated equally, "North"
        * also refers to the top of a negative bar, and *not* to the bottom.
        *
        *
        * "NorthEast" likewise refers to the top right edge of the bar,
        * "NorthWest" to the top left edge of the bar, and so on.
        *
        * In other words, attrs.positivePosition() always refers to a
        * position of the *bar*, and relPos.alignment() always refers
        * to an alignment of the text frame relative to this position.
        */

        QTransform transform;
        {
            // move to the general area where the label should be
            QPointF calcPoint = relPos.calculatedPoint( relativeMeasureSize );
            transform.translate( calcPoint.x(), calcPoint.y() );
            // align the text rect; find out by how many half-widths / half-heights to move.
            int dx = -1;
            if ( relPos.alignment() & Qt::AlignLeft ) {
                dx -= 1;
            } else if ( relPos.alignment() & Qt::AlignRight ) {
                 dx += 1;
            }

            int dy = -1;
            if ( relPos.alignment() & Qt::AlignTop ) {
                dy -= 1;
            } else if ( relPos.alignment() & Qt::AlignBottom ) {
                dy += 1;
            }
            transform.translate( qreal( dx ) * plainRect.width() * 0.5,
                                 qreal( dy ) * plainRect.height() * 0.5 );

            // rotate the text rect around its center
            transform.translate( plainRect.center().x(), plainRect.center().y() );
            int rotation = dva.textAttributes().rotation();
            if ( !isPositive && dva.mirrorNegativeValueTextRotation() ) {
                rotation *= -1;
            }
            transform.rotate( rotation );
            transform.translate( -plainRect.center().x(), -plainRect.center().y() );
        }

        QPainterPath labelArea;
        //labelArea.addPolygon( transform.mapToPolygon( plainRect.toRect() ) );
        //labelArea.closeSubpath();
        // Not doing that because QTransform has a special case for 180° that gives a different than
        // usual ordering of the points in the polygon returned by mapToPolygon( const QRect & ).
        // We expect a particular ordering in paintDataValueTextsAndMarkers() by using elementAt( 0 ),
        // and similar things might happen elsewhere.
        labelArea.addPolygon( transform.map( QPolygon( plainRect.toRect(), true ) ) );

        // store the label geometry and auxiliary data
        cache->paintReplay.append( LabelPaintInfo( it.key(), dva, labelArea,
                                                   referencePoint, value >= 0.0, text ) );
    }
}
Example #2
0
/**
 * Renders the text data into painter paths.
 */
void RTextRenderer::renderSimple() {
    boundingBox = RBox();
    painterPaths.clear();
    richText = "";

    RVector pos = textData.getAlignmentPoint();
    QString text = textData.getEscapedText();
    double textHeight = textData.getTextHeight();
    RS::VAlign verticalAlignment = textData.getVAlign();
    RS::HAlign horizontalAlignment = textData.getHAlign();
    QString fontName = textData.getFontName();
    bool bold = textData.isBold();
    bool italic = textData.isItalic();
    double angle = textData.getAngle();

    // degree:
    text.replace(QRegExp(RTextRenderer::rxDegree), RTextRenderer::chDegree);
    // plus minus:
    text.replace(QRegExp(RTextRenderer::rxPlusMinus), RTextRenderer::chPlusMinus);
    // diameter:
    text.replace(QRegExp(RTextRenderer::rxDiameter), RTextRenderer::chDiameter);

    bool leadingSpaces = false;
    bool trailingSpaces = false;

    if (!text.isEmpty()) {
        if (text.at(0).isSpace()) {
            leadingSpaces = true;
        }
        if (text.at(text.length()-1).isSpace()) {
            trailingSpaces = true;
        }
    }

    // implicit top level format block:
    QTextCharFormat f;
    f.setForeground(QBrush(QColor()));
    currentFormat.push(f);
    QTextLayout::FormatRange fr;
    fr.start = 0;
    fr.length = text.length();
    fr.format = currentFormat.top();
    QList<QTextLayout::FormatRange> formats;
    formats.append(fr);
    blockHeight.push(textHeight);
    blockFont.push(fontName);
    blockBold.push(bold);
    blockItalic.push(italic);
    useCadFont.push(RFontList::isCadFont(blockFont.top()));
    openTags.push(QStringList());

    double horizontalAdvance = 0.0;
    double horizontalAdvanceNoSpacing = 0.0;
    double ascent = 0.0;
    double descent = 0.0;

    // get painter paths for text at height 1.0:
    painterPaths = getPainterPathsForBlock(
                text, formats,
                horizontalAdvance,
                horizontalAdvanceNoSpacing,
                ascent, descent);

    width = horizontalAdvanceNoSpacing * textHeight;

    // transform to scale text from 1.0 to current text height:
    QTransform sizeTransform;
    sizeTransform.scale(textHeight, textHeight);

    // transform paths of text:
    boundingBox = RBox();
    for (int i=0; i<painterPaths.size(); ++i) {
        painterPaths[i].transform(sizeTransform);
        boundingBox.growToInclude(painterPaths[i].getBoundingBox());
    }

    // feature size of a text is its height
    // determines if text is displayed or only bounding box
    double featureSize = boundingBox.getHeight();

    QPen pen;
    for (int i=0; i<painterPaths.size(); ++i) {
        if (i==0) {
            pen = painterPaths[i].getPen();
            if (pen.style()==Qt::NoPen) {
                pen = QPen(painterPaths[i].getBrush().color());
            }
        }
        painterPaths[i].setFeatureSize(featureSize);
    }

    RPainterPath bbPath;
    bbPath.addBox(boundingBox);
    bbPath.setFeatureSize(-featureSize);
    bbPath.setPen(pen);
    painterPaths.append(bbPath);

    //height = boundingBox.getHeight();

    double topLine = textHeight;
    double baseLine = 0.0;
    double bottomLine = descent * textHeight;

    // at this point, the text is at 0/0 with the base line of the
    // first text line at y==0

    double xOffset = 0.0;
    double yOffset = 0.0;

    switch (verticalAlignment) {
    case RS::VAlignTop:
        yOffset = -topLine;
        break;
    case RS::VAlignMiddle:
        yOffset = -textHeight/2.0;
        break;
    case RS::VAlignBase:
        yOffset = -baseLine;
        break;
    case RS::VAlignBottom:
        yOffset = -bottomLine;
        break;
    }

    switch (horizontalAlignment) {
    default:
    case RS::HAlignAlign:
    case RS::HAlignFit:
    case RS::HAlignLeft:
        if (!leadingSpaces) {
            // move completely to the left (left border is 0.0):
            xOffset = -boundingBox.getMinimum().x;
        }
        else {
            xOffset = 0.0;
        }
        break;
    case RS::HAlignMid:
    case RS::HAlignCenter:
        if (!leadingSpaces && !trailingSpaces) {
            xOffset =  -(boundingBox.getMinimum().x +
                          boundingBox.getMaximum().x)/2.0;
        }
        else {
            xOffset = -horizontalAdvance/2.0*textHeight;
        }
        break;
    case RS::HAlignRight:
        if (!trailingSpaces) {
            xOffset = -boundingBox.getMaximum().x;
        }
        else {
            xOffset = -horizontalAdvance*textHeight;
        }
        break;
    }

    height = boundingBox.getHeight();

    QTransform globalTransform;
    globalTransform.translate(pos.x, pos.y);
    globalTransform.rotate(RMath::rad2deg(angle));
    globalTransform.translate(xOffset, yOffset);

    // apply global transform for position, angle and vertical alignment:
    boundingBox = RBox();
    for (int i=0; i<painterPaths.size(); ++i) {
        painterPaths[i].transform(globalTransform);
        boundingBox.growToInclude(painterPaths[i].getBoundingBox());
    }
}
void PageItem_ImageFrame::handleModeEditKey(QKeyEvent *k, bool& keyRepeat)
{
	double moveBy=1.0;
	Qt::KeyboardModifiers buttonModifiers = k->modifiers();
	bool controlDown=(buttonModifiers & Qt::ControlModifier);
	bool altDown=(buttonModifiers & Qt::AltModifier);
	bool shiftDown=(buttonModifiers & Qt::ShiftModifier);
	bool resizingImage=false;
	if (shiftDown && !controlDown)
		moveBy=10.0;
	else if (shiftDown && controlDown && !altDown)
		moveBy=0.1;
	else if (shiftDown && controlDown && altDown)
		moveBy=0.01;
	else if (!shiftDown && altDown)
		resizingImage=true;
	double dX=0.0,dY=0.0;
	int kk = k->key();
	if (!resizingImage)
	{
		moveBy/=m_Doc->unitRatio();//Lets allow movement by the current doc ratio, not only points
		switch (kk)
		{
			case Qt::Key_Left:
				dX=-moveBy;
				break;
			case Qt::Key_Right:
				dX=moveBy;
				break;
			case Qt::Key_Up:
				dY=-moveBy;
				break;
			case Qt::Key_Down:
				dY=moveBy;
				break;
		}
		if (dX!=0.0 || dY!=0.0)
		{
			moveImageInFrame(dX, dY);
			update();
		}
	}
	else
	{
		switch (kk)
		{
			case Qt::Key_Left:
				dX=-moveBy+100;
				break;
			case Qt::Key_Right:
				dX=moveBy+100;
				break;
			case Qt::Key_Up:
				dY=-moveBy+100;
				break;
			case Qt::Key_Down:
				dY=moveBy+100;
				break;
			default:
				return;
		}		
		if (dX!=0.0)
		{
			double newXScale=dX / 100.0 * m_imageXScale;
			setImageXScale(newXScale);
			if (!controlDown)
			{
				double newYScale=dX / 100.0 * m_imageYScale;
				setImageYScale(newYScale);
			}
		}
		else
		if (dY!=0.0)
		{
			double newYScale=dY / 100.0 * m_imageYScale;
			setImageYScale(newYScale);
			if (!controlDown)
			{
				double newXScale=dY / 100.0 * m_imageYScale;
				setImageXScale(newXScale);
			}
		}
		if (dX!=0.0 || dY!=0.0)
			if (imageClip.size() != 0)
			{
				imageClip = pixm.imgInfo.PDSpathData[pixm.imgInfo.usedPath].copy();
				QTransform cl;
				cl.translate(imageXOffset()*imageXScale(), imageYOffset()*imageYScale());
				cl.rotate(imageRotation());
				cl.scale(imageXScale(), imageYScale());
				imageClip.map(cl);
			}
		update();	
	}
}
void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
    Q_D(QDeclarativeImage);
    if (d->pix.pixmap().isNull() )
        return;

    int drawWidth = width();
    int drawHeight = height();
    bool doClip = false;
    QTransform transform;
    qreal widthScale = width() / qreal(d->pix.width());
    qreal heightScale = height() / qreal(d->pix.height());

    if (width() != d->pix.width() || height() != d->pix.height()) {
        if (d->fillMode >= Tile) {
            if (d->fillMode == TileVertically) {
                transform.scale(widthScale, 1.0);
                drawWidth = d->pix.width();
            } else if (d->fillMode == TileHorizontally) {
                transform.scale(1.0, heightScale);
                drawHeight = d->pix.height();
            }
        } else {
            if (d->fillMode == PreserveAspectFit) {
                if (widthScale <= heightScale) {
                    heightScale = widthScale;
                    transform.translate(0, (height() - heightScale * d->pix.height()) / 2);
                } else if(heightScale < widthScale) {
                    widthScale = heightScale;
                    transform.translate((width() - widthScale * d->pix.width()) / 2, 0);
                }
            } else if (d->fillMode == PreserveAspectCrop) {
                if (widthScale < heightScale) {
                    widthScale = heightScale;
                    transform.translate((width() - widthScale * d->pix.width()) / 2, 0);
                } else if(heightScale < widthScale) {
                    heightScale = widthScale;
                    transform.translate(0, (height() - heightScale * d->pix.height()) / 2);
                }
            }
            transform.scale(widthScale, heightScale);
            drawWidth = d->pix.width();
            drawHeight = d->pix.height();
            doClip = clip();
        }
    }

    QTransform oldTransform;
    bool oldAA = p->testRenderHint(QPainter::Antialiasing);
    bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
    if (d->smooth)
        p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
    if (doClip) {
        p->save();
        p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip);
    }
    if (d->mirror)
        transform.translate(drawWidth, 0).scale(-1.0, 1.0);
    if (!transform.isIdentity()) {
        oldTransform = p->transform();
        p->setWorldTransform(transform * oldTransform);
    }

    if (d->fillMode >= Tile)
        p->drawTiledPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix);
    else
        p->drawPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix, QRectF(0, 0, drawWidth, drawHeight));

    if (d->smooth) {
        p->setRenderHint(QPainter::Antialiasing, oldAA);
        p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
    }
    if (doClip)
        p->restore();
    if (!transform.isIdentity())
        p->setWorldTransform(oldTransform);
}
Example #5
0
bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
{
  //data defined size?
  double size = mSize;

  QgsExpression *sizeExpression = expression( "size" );
  bool hasDataDefinedSize = false;
  if ( context )
  {
    hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;
  }

  //data defined size
  if ( hasDataDefinedSize )
  {
    if ( sizeExpression )
    {
      size = sizeExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
    }
    size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context->renderContext(), mSizeUnit );

    switch ( mScaleMethod )
    {
      case QgsSymbolV2::ScaleArea:
        size = sqrt( size );
        break;
      case QgsSymbolV2::ScaleDiameter:
        break;
    }
  }

  if ( mSizeUnit == QgsSymbolV2::MM )
  {
    size *= mmMapUnitScaleFactor;
  }
  double halfSize = size / 2.0;

  QColor c = mPen.color();
  if ( mPen.style() == Qt::NoPen )
  {
    c = mBrush.color();
  }
  QgsExpression* colorExpression = expression( "color" );
  if ( colorExpression )
  {
    c = QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( *f ).toString() );
  }
  int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() );

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( *context, offsetX, offsetY );
  QPointF off( offsetX, offsetY );

  //angle
  double angle = mAngle;
  QgsExpression* angleExpression = expression( "angle" );
  if ( angleExpression )
  {
    angle = angleExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
  }
  angle = -angle; //rotation in Qt is counterclockwise
  if ( angle )
    off = _rotatedOffset( off, angle );

  if ( mSizeUnit == QgsSymbolV2::MM )
  {
    off *= mmMapUnitScaleFactor;
  }

  QTransform t;
  t.translate( shift.x() + offsetX, shift.y() + offsetY );

  if ( angle != 0 )
    t.rotate( angle );

  //data defined symbol name

  if ( mName == "circle" )
  {
    e.writeGroup( 0, "CIRCLE" );
    e.writeGroup( 8, layerName );

    e.writeGroup( 62, colorIndex );
    e.writeGroup( 10, halfSize + shift.x() );
    e.writeGroup( 20, halfSize + shift.y() );
    e.writeGroup( 30, 0.0 );
    e.writeGroup( 40, halfSize );
  }
  else if ( mName == "square" || mName == "rectangle" )
  {
    QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
    QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
    QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
    QPointF pt4 = t.map( QPointF( halfSize, halfSize ) );
    e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
  }
  else if ( mName == "diamond" )
  {
    QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
    QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
    QPointF pt3 = t.map( QPointF( 0, halfSize ) );
    QPointF pt4 = t.map( QPointF( halfSize, 0 ) );
    e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
  }
  else
  {
    return false;
  }
  return true;
}
Example #6
0
    void GraphAggRenderer::copyToWindow(QPainter *d,
            int x, int y, int w, int h)
    {
        if (NULL == d || m_data->tiles == 0) {
            return;
        }
        QTime time;
        time.start();

        GraphLib::TileManager *tm = m_data->tiles;

        QTransform t;
        t.translate(-1 * x, -1 * y);

        QPainter &painter = *d;
        painter.setTransform(t);

        int i, j;
        for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT)))  {
            for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) {
                GraphLib::Tile *t = tm->get_tile(j, i, true, false);
                if (t == NULL)
                    continue;
                Tile::release(t, false);

                if (1 == needRedraw(QRectF(j, i, 1, 1))) {
                    t = tm->get_tile(j, i, true, true);

                    int tile_x, tile_y;
                    tm->get_tile_coordinates(t, &tile_x, &tile_y);
                    QImage image(t->data, t->ewidth, t->eheight, 
                            QImage::Format_ARGB32_Premultiplied);

                    memset(t->data, 0, t->size);
                    agg::trans_affine mtx;
                    QRectF extent = calculate_extent(m_data->bbox);

                    mtx *= agg::trans_affine_translation(-1*extent.center().x(), -1*extent.center().y());
                    mtx *= agg::trans_affine_translation(tm->width/2, tm->height/2);
                    mtx *= agg::trans_affine_translation(-1 * tile_x, -1 * tile_y);
                    render(&image, QRectF(tile_x, tile_y, w, h), &mtx);
                    Tile::release(t, true);

                    int index = tm->get_tile_num(tile_x, tile_y);
                    m_data->redrawFlags[index] = 0;
                }

                t = tm->get_tile(j, i, true, false);
                int tile_x, tile_y;
                tm->get_tile_coordinates(t, &tile_x, &tile_y);

                QImage image(t->data, t->ewidth, t->eheight, 
                        QImage::Format_ARGB32_Premultiplied);

                int w = t->ewidth;
                int h = t->eheight;

                QRectF targetRect(tile_x, tile_y, w, h);
                QRectF sourceRect(0, 0, w, h);

                painter.drawImage(targetRect, image, sourceRect);
                Tile::release(t, false);


#ifdef TILE_PROFILING
                // 显示tile
                painter.setPen(Qt::red);
                int index = tm->get_tile_num(tile_x, tile_y);
                //image.save(QString("%1.png").arg(index));
                painter.drawText(QRectF(tile_x, tile_y, w, h),
                        Qt::AlignCenter, QString("%1").arg(index));
                painter.drawRect(QRectF(tile_x, tile_y, w, h));
#endif
            } // j循环
        } // i循环
        //qDebug() << "Time elapsed: " << time.elapsed() << " md.";
    }
void ResizeGesture::adjustBounds(QMouseEvent *m)
{
	QTransform rotation;
	FPoint docPoint = m_canvas->globalToCanvas(m->globalPos());
	QPointF oldXY = m_bounds.topLeft();
	// proportional resize
	bool constrainRatio = ((m->modifiers() & Qt::ControlModifier) != Qt::NoModifier);
	
	if (m_mousePressPoint == m->globalPos())
	{
		m_bounds = m_mousePressBounds;
		return;
	}

	// snap to grid	+ snap to guides
	bool isCorner = m_handle == Canvas::NORTHWEST || m_handle == Canvas::NORTHEAST 
		|| m_handle == Canvas::SOUTHWEST || m_handle == Canvas::SOUTHEAST;
	if (m_rotation == 0 || isCorner)
	{
		FPoint snappedPoint = m_doc->ApplyGridF(docPoint);
		double x = snappedPoint.x(), y = snappedPoint.y();
		m_doc->ApplyGuides(&x, &y);
//		if (m_doc->ApplyGuides(&x, &y))
//			qDebug() << "guides applied:" << snappedPoint.x() << snappedPoint.y() << "to" << x << y;
		if (m_handle == Canvas::NORTH || m_handle == Canvas::SOUTH) 
			// only snap on y-axis
			docPoint = FPoint(docPoint.x(), y);
		else if (m_handle == Canvas::EAST || m_handle == Canvas::WEST)
			// only snap on x-axis
			docPoint = FPoint(x, docPoint.y());
		else 
			docPoint = FPoint(x,y);
//		qDebug() << "resize snap grid/guides:" << m->globalPos() << "-->" << m_canvas->canvasToGlobal(docPoint);
	}
	
	// un-rotate point
	if (m_rotation != 0)
	{
		// rotate point around item position
		rotation.translate(m_bounds.x(), m_bounds.y());
		rotation.rotate(m_rotation);
		rotation.translate(-m_bounds.x(), -m_bounds.y());
//		qDebug() << "resize rotated" << m_rotation << "°" << m_bounds << rotation << ":" << point-globalBounds.topLeft() << "-->" << rotation.map(point)-globalBounds.topLeft();
		QPointF qp = QPointF(docPoint.x(), docPoint.y());
		qp = rotation.inverted().map(qp);
		docPoint = FPoint(qp.x(), qp.y());
	}
	
	// adjust bounds vertically
	switch (m_handle)
	{
		case Canvas::NORTHWEST:
		case Canvas::NORTH:
		case Canvas::NORTHEAST:
//			qDebug() << "ResizeGesture: top to" << point.y();
			m_bounds.setTop(docPoint.y());
			break;
		case Canvas::SOUTHWEST:
		case Canvas::SOUTH:
		case Canvas::SOUTHEAST:
//			qDebug() << "ResizeGesture: bottom to" << point.y();
			m_bounds.setBottom(docPoint.y());
			break;
		default:
			break;
	}
	// adjust bounds horizontally
	switch (m_handle)
	{
		case Canvas::NORTHWEST:
		case Canvas::WEST:
		case Canvas::SOUTHWEST:
//			qDebug() << "ResizeGesture: left to" << point.x();
			m_bounds.setLeft(docPoint.x());
			break;
		case Canvas::NORTHEAST:
		case Canvas::EAST:
		case Canvas::SOUTHEAST:
//			qDebug() << "ResizeGesture: right to" << point.x();
			m_bounds.setRight(docPoint.x());
			break;
		default:
			break;
	}

	// constrain ratio
	double newRatio = double(m_bounds.width()) / double(m_bounds.height());
	if (constrainRatio && m_origRatio != newRatio)
	{
//		qDebug() << "constrain ratio:" << m_bounds << newRatio << "to" << m_origRatio; 
		int newWidth = qRound(m_bounds.height() * m_origRatio);
		int newHeight = qRound(m_bounds.width() / m_origRatio);
		switch (m_handle)
		{
			case Canvas::NORTHWEST:
				// axis: topleft + t*[origRatio, 1]    t:= y-top
				//       [x',y] = [left, top] + [(y-top)*origRatio, y-top]
				//              = [left + (y-top)*origRatio, y]
				// x < x'  => mouse is WEST, x > x'  => mouse is NORTH
				// x < left + (y-top)*origratio   <=> x - left < (y - top) * origratio
				
//				qDebug() << "NORTHWEST" << point << m_origBounds.topLeft() << m_origRatio
//				<< (point.x() - m_origBounds.left() < (point.y()-m_origBounds.top()) * m_origRatio);
				
				if (docPoint.x() - m_origBounds.left() < (docPoint.y()-m_origBounds.top()) * m_origRatio)
					m_bounds.setTop(m_bounds.top() - newHeight + m_bounds.height());
				else
					m_bounds.setLeft(m_bounds.left() - newWidth + m_bounds.width());
				break;
			case Canvas::SOUTHWEST:
				// axis: bottomleft + t*[origRatio, -1]    t:= bottom-y
				//       (x',y) = [left, bottom] + [(bottom-y)*origRatio, -bottom+y]
				//              = [left + (bottom-y)*origRatio, y]
				// x < x'  => mouse is WEST, x > x'  => mouse is SOUTH
				// x < left + (bottom-y)*origratio   <=> x - left < (bottom-y) * origratio
				
//				qDebug() << "SOUTHWEST" << point << m_origBounds.bottomLeft()  << m_origRatio
//				<< (point.x() - m_origBounds.left() < (m_origBounds.bottom() - point.y()) * m_origRatio);
				
				if (docPoint.x() - m_origBounds.left() < (m_origBounds.bottom() - docPoint.y()) * m_origRatio)
					m_bounds.setHeight(newHeight);
				else
					m_bounds.setLeft(m_bounds.left() - newWidth + m_bounds.width());
				break;
			case Canvas::NORTHEAST:
				// cf. SOUTHWEST
				if (docPoint.x() - m_origBounds.left() > (m_origBounds.bottom() - docPoint.y()) * m_origRatio)
					m_bounds.setTop(m_bounds.top() - newHeight + m_bounds.height());
				else
					m_bounds.setWidth(newWidth);
				break;
			case Canvas::SOUTHEAST:
				// cf. NORTHWEST
				if (docPoint.x() - m_origBounds.left() > (docPoint.y()-m_origBounds.top()) * m_origRatio)
					m_bounds.setHeight(newHeight);
				else
					m_bounds.setWidth(newWidth);
				break;
			case Canvas::WEST:
			case Canvas::EAST:
				// (origBounds.top + origBounds.bottom) / 2 is the horizontal axis
				// keep that fixed
				m_bounds.setTop(((m_origBounds.top() + m_origBounds.bottom()) / 2) - newHeight / 2);
				m_bounds.setHeight(newHeight);
				break;
			case Canvas::NORTH:
			case Canvas::SOUTH:
				// (origBounds.left + origBounds.right) / 2 is the vertical axis
				// keep that fixed
				m_bounds.setLeft(((m_origBounds.left() + m_origBounds.right()) / 2) - newWidth / 2);
				m_bounds.setWidth(newWidth);
				break;
			default:
				break;
		}
//		qDebug() << "constrained:" << m_bounds << double(m_bounds.width()) / m_bounds.height();
	}

	// re-rotate: if top left has changed, then it needs rotation
	if (m_rotation != 0 && oldXY != m_bounds.topLeft())
	{
		m_bounds.moveTo(rotation.map(m_bounds.topLeft()));
		// fix opposite corner to avoid aggregating rounding errors
		QPointF origFixPoint, newFixPoint;
		switch (m_handle)
		{
			case Canvas::NORTHWEST:
				origFixPoint = m_origBounds.bottomRight();
				newFixPoint = m_bounds.bottomRight();
				break;
			case Canvas::WEST:
				origFixPoint = m_origBounds.topRight() + QPointF(0, m_origBounds.height()/2);
				newFixPoint = m_bounds.topRight() + QPointF(0, m_bounds.height()/2);
				break;
			case Canvas::SOUTHWEST:
				origFixPoint = m_origBounds.topRight();
				newFixPoint = m_bounds.topRight();
				break;
			case Canvas::SOUTH:
				origFixPoint = m_origBounds.topLeft() + QPointF(m_origBounds.width()/2, 0);
				newFixPoint = m_bounds.topLeft() + QPointF(m_bounds.width()/2, 0);
				break;
			case Canvas::SOUTHEAST:
				origFixPoint = m_origBounds.topLeft();
				newFixPoint = m_bounds.topLeft();
				break;
			case Canvas::EAST:
				origFixPoint = m_origBounds.topLeft() + QPointF(0, m_origBounds.height()/2);
				newFixPoint = m_bounds.topLeft() + QPointF(0, m_bounds.height()/2);
				break;
			case Canvas::NORTHEAST:
				origFixPoint = m_origBounds.bottomLeft();
				newFixPoint = m_bounds.bottomLeft();
				break;
			case Canvas::NORTH:
				origFixPoint = m_origBounds.bottomLeft() + QPointF(m_origBounds.width()/2, 0);
				newFixPoint = m_bounds.bottomLeft() + QPointF(m_bounds.width()/2, 0);
				break;
			default:
				origFixPoint = m_origBounds.topLeft();
				newFixPoint = m_bounds.topLeft();
				break;
		}
		origFixPoint = m_origBounds.topLeft() + rotation.map(origFixPoint - m_origBounds.topLeft());
		newFixPoint = m_bounds.topLeft() + rotation.map(newFixPoint - m_bounds.topLeft());
		if (origFixPoint != newFixPoint)
			m_bounds.translate(origFixPoint - newFixPoint);
	}
}
Example #8
0
void PageItem_Line::getBoundingRect(double *x1, double *y1, double *x2, double *y2) const
{
	double minx =  std::numeric_limits<double>::max();
	double miny =  std::numeric_limits<double>::max();
	double maxx = -std::numeric_limits<double>::max();
	double maxy = -std::numeric_limits<double>::max();
	if (m_rotation != 0)
	{
		FPointArray pb;
		pb.resize(0);
		pb.addPoint(FPoint(0,       -m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0));
		pb.addPoint(FPoint(m_width, -m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0));
		pb.addPoint(FPoint(m_width, +m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0));
		pb.addPoint(FPoint(0,       +m_lineWidth / 2.0, m_xPos, m_yPos, m_rotation, 1.0, 1.0));
		for (uint pc = 0; pc < 4; ++pc)
		{
			minx = qMin(minx, pb.point(pc).x());
			miny = qMin(miny, pb.point(pc).y());
			maxx = qMax(maxx, pb.point(pc).x());
			maxy = qMax(maxy, pb.point(pc).y());
		}
		*x1 = minx;
		*y1 = miny;
		*x2 = maxx;
		*y2 = maxy;
	}
	else
	{
		*x1 = m_xPos;
		*y1 = m_yPos - qMax(1.0, m_lineWidth) / 2.0;
		*x2 = m_xPos + m_width;
		*y2 = m_yPos + qMax(1.0, m_lineWidth) / 2.0;
	}

	QRectF totalRect = QRectF(QPointF(*x1, *y1), QPointF(*x2, *y2));
	if (m_startArrowIndex != 0)
	{
		QTransform arrowTrans;
		FPointArray arrow = m_Doc->arrowStyles().at(m_startArrowIndex-1).points.copy();
		arrowTrans.translate(m_xPos, m_yPos);
		arrowTrans.rotate(m_rotation);
		arrowTrans.translate(0, 0);
		arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0);
		if (NamedLStyle.isEmpty())
		{
			if (m_lineWidth != 0.0)
				arrowTrans.scale(m_lineWidth, m_lineWidth);
		}
		else
		{
			multiLine ml = m_Doc->MLineStyles[NamedLStyle];
			if (ml[ml.size()-1].Width != 0.0)
				arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
		}
		arrowTrans.scale(-1,1);
		arrow.map(arrowTrans);
		FPoint minAr = getMinClipF(&arrow);
		FPoint maxAr = getMaxClipF(&arrow);
		totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y())));
	}
	if (m_endArrowIndex != 0)
	{
		QTransform arrowTrans;
		FPointArray arrow = m_Doc->arrowStyles().at(m_endArrowIndex-1).points.copy();
		arrowTrans.translate(m_xPos, m_yPos);
		arrowTrans.rotate(m_rotation);
		arrowTrans.translate(m_width, 0);
		arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0);
		if (NamedLStyle.isEmpty())
		{
			if (m_lineWidth != 0.0)
				arrowTrans.scale(m_lineWidth, m_lineWidth);
		}
		else
		{
			multiLine ml = m_Doc->MLineStyles[NamedLStyle];
			if (ml[ml.size()-1].Width != 0.0)
				arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
		}
		arrow.map(arrowTrans);
		FPoint minAr = getMinClipF(&arrow);
		FPoint maxAr = getMaxClipF(&arrow);
		totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y())));
	}
	totalRect.getCoords(x1, y1, x2, y2);
}
Example #9
0
void PageItem_Line::getVisualBoundingRect(double * x1, double * y1, double * x2, double * y2) const
{
	double minx =  std::numeric_limits<double>::max();
	double miny =  std::numeric_limits<double>::max();
	double maxx = -std::numeric_limits<double>::max();
	double maxy = -std::numeric_limits<double>::max();
	double extraSpace = 0.0;
	if (NamedLStyle.isEmpty())
	{
		if ((lineColor() != CommonStrings::None) || (!patternStrokeVal.isEmpty()) || (GrTypeStroke > 0))
		{
			extraSpace = m_lineWidth / 2.0;
			if ((extraSpace == 0) && m_Doc->view()) // Hairline case
				extraSpace = 0.5 / m_Doc->view()->scale();
		}
		if ((!patternStrokeVal.isEmpty()) && (m_Doc->docPatterns.contains(patternStrokeVal)) && (patternStrokePath))
		{
			ScPattern *pat = &m_Doc->docPatterns[patternStrokeVal];
			QTransform mat;
			mat.rotate(patternStrokeRotation);
			mat.scale(patternStrokeScaleX / 100.0, patternStrokeScaleY / 100.0);
			QRectF p1R = QRectF(0, 0, pat->width / 2.0, pat->height / 2.0);
			QRectF p2R = mat.map(p1R).boundingRect();
			extraSpace = p2R.height();
		}
	}
	else
	{
		multiLine ml = m_Doc->MLineStyles[NamedLStyle];
		const SingleLine& sl = ml.last();
		if (sl.Color != CommonStrings::None)
		{
			extraSpace = sl.Width / 2.0;
			if ((extraSpace == 0) && m_Doc->view()) // Hairline case
				extraSpace = 0.5 / m_Doc->view()->scale();
		}
	}
	if (m_rotation != 0)
	{
		FPointArray pb;
		pb.resize(0);
		pb.addPoint(FPoint(0.0,           -extraSpace, xPos(), yPos(), m_rotation, 1.0, 1.0));
		pb.addPoint(FPoint(visualWidth(), -extraSpace, xPos(), yPos(), m_rotation, 1.0, 1.0));
		pb.addPoint(FPoint(visualWidth(), +extraSpace, xPos(), yPos(), m_rotation, 1.0, 1.0));
		pb.addPoint(FPoint(0.0,           +extraSpace, xPos(), yPos(), m_rotation, 1.0, 1.0));
		for (uint pc = 0; pc < 4; ++pc)
		{
			minx = qMin(minx, pb.point(pc).x());
			miny = qMin(miny, pb.point(pc).y());
			maxx = qMax(maxx, pb.point(pc).x());
			maxy = qMax(maxy, pb.point(pc).y());
		}
		*x1 = minx;
		*y1 = miny;
		*x2 = maxx;
		*y2 = maxy;
	}
	else
	{
		*x1 = m_xPos;
		*y1 = m_yPos - extraSpace;
		*x2 = m_xPos + visualWidth();
		*y2 = m_yPos + extraSpace;
	}

	QRectF totalRect(QPointF(*x1, *y1), QPointF(*x2, *y2));
	if (m_startArrowIndex != 0)
	{
		QTransform arrowTrans;
		FPointArray arrow = m_Doc->arrowStyles().at(m_startArrowIndex-1).points.copy();
		arrowTrans.translate(m_xPos, m_yPos);
		arrowTrans.rotate(m_rotation);
		arrowTrans.translate(0, 0);
		arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0);
		if (NamedLStyle.isEmpty())
		{
			if (m_lineWidth != 0.0)
				arrowTrans.scale(m_lineWidth, m_lineWidth);
		}
		else
		{
			multiLine ml = m_Doc->MLineStyles[NamedLStyle];
			if (ml[ml.size()-1].Width != 0.0)
				arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
		}
		arrowTrans.scale(-1,1);
		arrow.map(arrowTrans);
		FPoint minAr = getMinClipF(&arrow);
		FPoint maxAr = getMaxClipF(&arrow);
		totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y())));
	}
	if (m_endArrowIndex != 0)
	{
		QTransform arrowTrans;
		FPointArray arrow = m_Doc->arrowStyles().at(m_endArrowIndex-1).points.copy();
		arrowTrans.translate(m_xPos, m_yPos);
		arrowTrans.rotate(m_rotation);
		arrowTrans.translate(m_width, 0);
		arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0);
		if (NamedLStyle.isEmpty())
		{
			if (m_lineWidth != 0.0)
				arrowTrans.scale(m_lineWidth, m_lineWidth);
		}
		else
		{
			multiLine ml = m_Doc->MLineStyles[NamedLStyle];
			if (ml[ml.size()-1].Width != 0.0)
				arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
		}
		arrow.map(arrowTrans);
		FPoint minAr = getMinClipF(&arrow);
		FPoint maxAr = getMaxClipF(&arrow);
		totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y())));
	}
	totalRect.getCoords(x1, y1, x2, y2);
}
Example #10
0
void TupGraphicsScene::addTweeningObjects(int photogram)
{
    QList<TupGraphicObject *> tweenList = k->scene->tweeningGraphicObjects();

    for (int i=0; i < tweenList.count(); i++) {

         TupGraphicObject *object = tweenList.at(i);

         if (object->frame()->layer()->isVisible()) {
             int origin = object->frame()->index();

             if (TupItemTweener *tween = object->tween()) {

                 int adjustX = object->item()->boundingRect().width()/2;
                 int adjustY = object->item()->boundingRect().height()/2;

                 if (origin == photogram) {

                     TupTweenerStep *stepItem = tween->stepAt(0);
                     object->item()->setToolTip(tween->tweenType() + ": " + tween->name() + tr("/Step: 0"));

                     if (tween->type() == TupItemTweener::Compound) {
                         object->item()->setTransformOriginPoint(tween->transformOriginPoint());

                         if (stepItem->has(TupTweenerStep::Position)) {
                             // tFatal() << "TupGraphicsScene::addTweeningObjects() - Applying position...";
                             QPointF point = QPoint(-adjustX, -adjustY);
                             object->setLastTweenPos(stepItem->position() + point);
                             object->item()->setPos(tween->transformOriginPoint());
                         }

                         if (stepItem->has(TupTweenerStep::Rotation)) {
                             QRectF rect = object->item()->sceneBoundingRect();
                             object->item()->setTransformOriginPoint(rect.center());
                             double angle = stepItem->rotation();
                             object->item()->setRotation(angle);
                             // tFatal() << "TupGraphicsScene::addTweeningObjects() - Applying rotation - Angle: " << angle;
                         } else {
                             // tFatal() << "TupGraphicsScene::addTweeningObjects() - No rotation parameter!";
                         }
                         
                     } else {

                         if (stepItem->has(TupTweenerStep::Position)) {
                             QPointF point = QPoint(-adjustX, -adjustY);
                             object->setLastTweenPos(stepItem->position() + point);
                             object->item()->setPos(tween->transformOriginPoint());
                         }

                         if (stepItem->has(TupTweenerStep::Rotation)) {
                             double angle = stepItem->rotation();
                             object->item()->setTransformOriginPoint(tween->transformOriginPoint());
                             object->item()->setRotation(angle);
                         }

                         if (stepItem->has(TupTweenerStep::Scale)) {
                             QPointF point = tween->transformOriginPoint();
                             object->item()->setTransformOriginPoint(point);
                             object->item()->setScale(1.0);
                         }

                         if (stepItem->has(TupTweenerStep::Shear)) {
                             QTransform transform;
                             transform.shear(0, 0);
                             object->item()->setTransform(transform);
                         } 

                         if (stepItem->has(TupTweenerStep::Coloring)) {
                             QColor itemColor = stepItem->color();
                             if (TupPathItem *path = qgraphicsitem_cast<TupPathItem *>(object->item())) {
                                 QPen pen = path->pen();
                                 pen.setColor(itemColor);
                                 path->setPen(pen);
                             } else if (TupEllipseItem *ellipse = qgraphicsitem_cast<TupEllipseItem *>(object->item())) {
                                        QPen pen = ellipse->pen();
                                        pen.setColor(itemColor);
                                        ellipse->setPen(pen);
                             } else if (TupLineItem *line = qgraphicsitem_cast<TupLineItem *>(object->item())) {
                                        QPen pen = line->pen();
                                        pen.setColor(itemColor);
                                        line->setPen(pen); 
                             } else if (TupRectItem *rect = qgraphicsitem_cast<TupRectItem *>(object->item())) {
                                        QPen pen = rect->pen();
                                        pen.setColor(itemColor);
                                        rect->setPen(pen);
                            }
                         }

                         if (stepItem->has(TupTweenerStep::Opacity))
                             object->item()->setOpacity(stepItem->opacity());
                     }

                 } else if ((origin < photogram) && (photogram < origin + tween->frames())) {

                            int step = photogram - origin;
                            TupTweenerStep *stepItem = tween->stepAt(step);
                            object->item()->setToolTip(tween->tweenType() + ": " + tween->name() + tr("/Step: ") + QString::number(step));
                            if (tween->type() == TupItemTweener::Compound) {

                                if (stepItem->has(TupTweenerStep::Position)) {
                                    qreal dx = stepItem->position().x() - (object->lastTweenPos().x() + adjustX);
                                    qreal dy = stepItem->position().y() - (object->lastTweenPos().y() + adjustY);
                                    object->item()->moveBy(dx, dy);
                                    QPointF point = QPoint(-adjustX, -adjustY);
                                    object->setLastTweenPos(stepItem->position() + point);
                                }

                                if (stepItem->has(TupTweenerStep::Rotation)) {
                                    double angle = stepItem->rotation();
                                    object->item()->setRotation(angle);
                                    // tFatal() << "TupGraphicsScene::addTweeningObjects() - Applying rotation - Angle: " << angle;
                                }

                                addGraphicObject(object);

                            } else {

                                if (stepItem->has(TupTweenerStep::Position)) {
                                    qreal dx = stepItem->position().x() - (object->lastTweenPos().x() + adjustX);
                                    qreal dy = stepItem->position().y() - (object->lastTweenPos().y() + adjustY);
                                    object->item()->moveBy(dx, dy);
                                    QPointF point = QPoint(-adjustX, -adjustY);
                                    object->setLastTweenPos(stepItem->position() + point);
                                }

                                if (stepItem->has(TupTweenerStep::Rotation)) {
                                    double angle = stepItem->rotation();
                                    object->item()->setRotation(angle);
                                }

                                if (stepItem->has(TupTweenerStep::Scale)) {
                                    QPointF point = tween->transformOriginPoint();

                                    double scaleX = stepItem->horizontalScale();
                                    double scaleY = stepItem->verticalScale();
                                    QTransform transform;
                                    transform.translate(point.x(), point.y());
                                    transform.scale(scaleX, scaleY);
                                    transform.translate(-point.x(), -point.y());

                                    object->item()->setTransform(transform);
                                }

                                if (stepItem->has(TupTweenerStep::Shear)) {
                                    QPointF point = tween->transformOriginPoint();

                                    double shearX = stepItem->horizontalShear();
                                    double shearY = stepItem->verticalShear();
                                    QTransform transform;
                                    transform.translate(point.x(), point.y());
                                    transform.shear(shearX, shearY);
                                    transform.translate(-point.x(), -point.y());

                                    object->item()->setTransform(transform);
                                }

                                if (stepItem->has(TupTweenerStep::Coloring)) {
                                    QColor itemColor = stepItem->color();
                                    if (TupPathItem *path = qgraphicsitem_cast<TupPathItem *>(object->item())) {
                                        QPen pen = path->pen();
                                        pen.setColor(itemColor);
                                        path->setPen(pen);
                                    } else if (TupEllipseItem *ellipse = qgraphicsitem_cast<TupEllipseItem *>(object->item())) {
                                               QPen pen = ellipse->pen();
                                               pen.setColor(itemColor);
                                               ellipse->setPen(pen);
                                    } else if (TupLineItem *line = qgraphicsitem_cast<TupLineItem *>(object->item())) {
                                               QPen pen = line->pen();
                                               pen.setColor(itemColor);
                                               line->setPen(pen);
                                    } else if (TupRectItem *rect = qgraphicsitem_cast<TupRectItem *>(object->item())) {
                                               QPen pen = rect->pen();
                                               pen.setColor(itemColor);
                                               rect->setPen(pen);
                                    }
                                }

                                addGraphicObject(object);

                                if (stepItem->has(TupTweenerStep::Opacity))
                                    object->item()->setOpacity(stepItem->opacity());
                            }    
                 }
             }
        }
    }
}
Example #11
0
void TupGraphicsScene::addSvgTweeningObjects(int photogram)
{
    QList<TupSvgItem *> svgList = k->scene->tweeningSvgObjects();

    for (int i=0; i < svgList.count(); i++) {

         TupSvgItem *object = svgList.at(i);

         if (object->frame()->layer()->isVisible()) {
             int origin = object->frame()->index();

             if (TupItemTweener *tween = object->tween()) {

                 int adjustX = object->boundingRect().width()/2;
                 int adjustY = object->boundingRect().height()/2;

                 if (origin == photogram) {

                     TupTweenerStep *stepItem = tween->stepAt(0);
                     object->setToolTip(tween->tweenType() + ": " + tween->name() + tr("/Step: 0"));

                     if (stepItem->has(TupTweenerStep::Position)) {
                         object->setPos(tween->transformOriginPoint());
                         QPointF offset = QPoint(-adjustX, -adjustY);
                         object->setLastTweenPos(stepItem->position() + offset);
                     }

                     if (stepItem->has(TupTweenerStep::Rotation)) {
                         double angle = stepItem->rotation();
                         object->setTransformOriginPoint(tween->transformOriginPoint());
                         object->setRotation(angle);
                     }

                     if (stepItem->has(TupTweenerStep::Scale)) {
                         QPointF point = tween->transformOriginPoint();
                         object->setTransformOriginPoint(point);
                         object->setScale(1.0);
                     }

                     if (stepItem->has(TupTweenerStep::Shear)) {
                         QTransform transform;
                         transform.shear(0, 0);
                         object->setTransform(transform);
                     }

                     if (stepItem->has(TupTweenerStep::Opacity))
                         object->setOpacity(stepItem->opacity());

                 } else if ((origin < photogram) && (photogram < origin + tween->frames())) {
                             int step = photogram - origin;
                             TupTweenerStep *stepItem = tween->stepAt(step);
                             object->setToolTip(tween->tweenType() + ": " + tween->name() + tr("/Step: ") + QString::number(step));

                             if (stepItem->has(TupTweenerStep::Position)) {
                                 qreal dx = stepItem->position().x() - (object->lastTweenPos().x() + adjustX);
                                 qreal dy = stepItem->position().y() - (object->lastTweenPos().y() + adjustY);
                                 object->moveBy(dx, dy);
                                 QPointF offset = QPoint(-adjustX, -adjustY);
                                 object->setLastTweenPos(stepItem->position() + offset);
                             }

                             if (stepItem->has(TupTweenerStep::Rotation)) {
                                 double angle = stepItem->rotation();
                                 object->setRotation(angle);
                             }

                            if (stepItem->has(TupTweenerStep::Scale)) {
                                QPointF point = tween->transformOriginPoint();

                                double scaleX = stepItem->horizontalScale();
                                double scaleY = stepItem->verticalScale();
                                QTransform transform;
                                transform.translate(point.x(), point.y());
                                transform.scale(scaleX, scaleY);
                                transform.translate(-point.x(), -point.y());

                                object->setTransform(transform);
                            }

                            if (stepItem->has(TupTweenerStep::Shear)) {
                                QPointF point = tween->transformOriginPoint();

                                double shearX = stepItem->horizontalShear();
                                double shearY = stepItem->verticalShear();
                                QTransform transform;
                                transform.translate(point.x(), point.y());
                                transform.shear(shearX, shearY);
                                transform.translate(-point.x(), -point.y());

                                object->setTransform(transform);
                            }

                            addSvgObject(object);

                            if (stepItem->has(TupTweenerStep::Opacity))
                                object->setOpacity(stepItem->opacity());
                 }
             } else {
                 #ifdef K_DEBUG
                        tFatal() << "TupGraphicsScene::addSvgTweeningObjects() - No tween found!";
                 #endif
             }
         }
    }
}
Example #12
0
void PageItem_Spiral::getVisualBoundingRect(double * x1, double * y1, double * x2, double * y2) const
{
	PageItem::getVisualBoundingRect(x1, y1, x2, y2);
	QRectF totalRect(QPointF(*x1, *y1), QPointF(*x2, *y2));
	if (m_startArrowIndex != 0 && !PoLine.empty())
	{
		QTransform arrowTrans;
		FPointArray arrow = m_Doc->arrowStyles().at(m_startArrowIndex-1).points.copy();
		arrowTrans.translate(m_xPos, m_yPos);
		arrowTrans.rotate(m_rotation);
		FPoint Start = PoLine.point(0);
		for (int xx = 1; xx < PoLine.size(); xx += 2)
		{
			FPoint Vector = PoLine.point(xx);
			if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
			{
				arrowTrans.translate(Start.x(), Start.y());
				arrowTrans.rotate(atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI));
				arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0);
				if (NamedLStyle.isEmpty())
				{
					if (m_lineWidth != 0.0)
						arrowTrans.scale(m_lineWidth, m_lineWidth);
				}
				else
				{
					multiLine ml = m_Doc->MLineStyles[NamedLStyle];
					if (ml[ml.size()-1].Width != 0.0)
						arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
				}
				arrow.map(arrowTrans);
				break;
			}
		}
		FPoint minAr = getMinClipF(&arrow);
		FPoint maxAr = getMaxClipF(&arrow);
		totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y())));
	}
	if (m_endArrowIndex != 0 && PoLine.size() >= 2)
	{
		QTransform arrowTrans;
		FPointArray arrow = m_Doc->arrowStyles().at(m_endArrowIndex-1).points.copy();
		arrowTrans.translate(m_xPos, m_yPos);
		arrowTrans.rotate(m_rotation);
		FPoint End = PoLine.point(PoLine.size()-2);
		for (uint xx = PoLine.size()-1; xx > 0; xx -= 2)
		{
			FPoint Vector = PoLine.point(xx);
			if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
			{
				arrowTrans.translate(End.x(), End.y());
				arrowTrans.rotate(atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI));
				arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0);
				if (NamedLStyle.isEmpty())
				{
					if (m_lineWidth != 0.0)
						arrowTrans.scale(m_lineWidth, m_lineWidth);
				}
				else
				{
					multiLine ml = m_Doc->MLineStyles[NamedLStyle];
					if (ml[ml.size()-1].Width != 0.0)
						arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
				}
				arrow.map(arrowTrans);
				break;
			}
		}
		FPoint minAr = getMinClipF(&arrow);
		FPoint maxAr = getMaxClipF(&arrow);
		totalRect = totalRect.united(QRectF(QPointF(minAr.x(), minAr.y()), QPointF(maxAr.x(), maxAr.y())));
	}
	totalRect.getCoords(x1, y1, x2, y2);
}
Example #13
0
void Tie::computeBezier(SlurSegment* ss, QPointF p6o)
      {
      qreal _spatium  = spatium();
      qreal shoulderW;              // height as fraction of slur-length
      qreal shoulderH;

      //
      // pp1      start of slur
      // pp2      end of slur
      // pp3      bezier 1
      // pp4      bezier 2
      // pp5      drag
      // pp6      shoulder
      //
      QPointF pp1 = ss->ups[GRIP_START].p + ss->ups[GRIP_START].off * _spatium;
      QPointF pp2 = ss->ups[GRIP_END].p   + ss->ups[GRIP_END].off   * _spatium;

      QPointF p2 = pp2 - pp1;       // normalize to zero
      if (p2.x() == 0.0) {
            qDebug("zero tie");
            return;
            }

      qreal sinb = atan(p2.y() / p2.x());
      QTransform t;
      t.rotateRadians(-sinb);
      p2  = t.map(p2);
      p6o = t.map(p6o);

      double smallH = 0.38;
      qreal d   = p2.x() / _spatium;
      shoulderH = d * 0.4 * smallH;
      if (shoulderH > 1.3)            // maximum tie shoulder height
            shoulderH = 1.3;
      shoulderH *= _spatium;
      shoulderW = .6;

      shoulderH -= p6o.y();

      if (!up())
            shoulderH = -shoulderH;

      qreal c    = p2.x();
      qreal c1   = (c - c * shoulderW) * .5 + p6o.x();
      qreal c2   = c1 + c * shoulderW       + p6o.x();

      QPointF p5 = QPointF(c * .5, 0.0);

      QPointF p3(c1, -shoulderH);
      QPointF p4(c2, -shoulderH);

      qreal w = (score()->styleS(ST_SlurMidWidth).val() - score()->styleS(ST_SlurEndWidth).val()) * _spatium;
      QPointF th(0.0, w);    // thickness of slur

      QPointF p3o = p6o + t.map(ss->ups[GRIP_BEZIER1].off * _spatium);
      QPointF p4o = p6o + t.map(ss->ups[GRIP_BEZIER2].off * _spatium);

      if(!p6o.isNull()) {
            QPointF p6i = t.inverted().map(p6o) / _spatium;
            ss->ups[GRIP_BEZIER1].off += p6i ;
            ss->ups[GRIP_BEZIER2].off += p6i;
            }

      //-----------------------------------calculate p6
      QPointF pp3  = p3 + p3o;
      QPointF pp4  = p4 + p4o;
      QPointF ppp4 = pp4 - pp3;

      qreal r2 = atan(ppp4.y() / ppp4.x());
      t.reset();
      t.rotateRadians(-r2);
      QPointF p6  = QPointF(t.map(ppp4).x() * .5, 0.0);

      t.rotateRadians(2 * r2);
      p6 = t.map(p6) + pp3 - p6o;
      //-----------------------------------

      ss->path = QPainterPath();
      ss->path.moveTo(QPointF());
      ss->path.cubicTo(p3 + p3o - th, p4 + p4o - th, p2);
      if (lineType() == 0)
            ss->path.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF());

      th = QPointF(0.0, 3.0 * w);
      ss->shapePath = QPainterPath();
      ss->shapePath.moveTo(QPointF());
      ss->shapePath.cubicTo(p3 + p3o - th, p4 + p4o - th, p2);
      ss->shapePath.cubicTo(p4 +p4o + th, p3 + p3o + th, QPointF());

      // translate back
      t.reset();
      t.translate(pp1.x(), pp1.y());
      t.rotateRadians(sinb);
      ss->path                 = t.map(ss->path);
      ss->shapePath            = t.map(ss->shapePath);
      ss->ups[GRIP_BEZIER1].p  = t.map(p3);
      ss->ups[GRIP_BEZIER2].p  = t.map(p4);
      ss->ups[GRIP_END].p      = t.map(p2) - ss->ups[GRIP_END].off * _spatium;
      ss->ups[GRIP_DRAG].p     = t.map(p5);
      ss->ups[GRIP_SHOULDER].p = t.map(p6);
      }
void CanvasMode_Rotate::getNewItemPosition(PageItem* item, FPoint& pos, double& rotation)
{
	double newAngle = xy2Deg(m_canvasCurrCoord.x() - m_rotCenter.x(), m_canvasCurrCoord.y() - m_rotCenter.y());
	if (m_angleConstrained)
	{
		newAngle = constrainAngle(newAngle, m_doc->opToolPrefs().constrain);
		/*double oldAngle = constrainAngle(m_startAngle, m_doc->opToolPrefs.constrain);
		newAngle = m_doc->m_Selection->isMultipleSelection() ? (newAngle - oldAngle) : newAngle;*/
		m_view->oldW = constrainAngle(m_view->oldW, m_doc->opToolPrefs().constrain);
		newAngle = m_doc->m_Selection->isMultipleSelection() ? (newAngle - m_view->oldW) : newAngle;
	}
	else if (m_doc->m_Selection->isMultipleSelection())
		newAngle = (newAngle - m_startAngle);
	else
		newAngle = item->rotation() - (m_startAngle - newAngle);
	if (m_doc->m_Selection->isMultipleSelection())
	{
		QTransform ma;
		ma.translate(m_rotCenter.x(), m_rotCenter.y());
		ma.scale(1, 1);
		ma.rotate(newAngle);
		FPoint n(item->xPos() - m_rotCenter.x(), item->yPos() - m_rotCenter.y());
		pos.setXY(ma.m11() * n.x() + ma.m21() * n.y() + ma.dx(), ma.m22() * n.y() + ma.m12() * n.x() + ma.dy());
		rotation = item->rotation() + newAngle;
	}
	else if (m_rotMode != 0)
	{
		FPoint n(0,0);
		QTransform ma;
		ma.translate(item->xPos(), item->yPos());
		ma.scale(1, 1);
		ma.rotate(item->rotation());
		double ro = newAngle - item->rotation();
		switch (m_rotMode)
		{
		case 2:
			ma.translate(item->width()/2.0, item->height()/2.0);
			n = FPoint(-item->width()/2.0, -item->height()/2.0);
			break;
		case 4:
			ma.translate(item->width(), item->height());
			n = FPoint(-item->width(), -item->height());
			break;
		case 3:
			ma.translate(0, item->height());
			n = FPoint(0, -item->height());
			break;
		case 1:
			ma.translate(item->width(), 0);
			n = FPoint(-item->width(), 0);
			break;
		}
		ma.rotate(ro);
		pos.setXY(ma.m11() * n.x() + ma.m21() * n.y() + ma.dx(), ma.m22() * n.y() + ma.m12() * n.x() + ma.dy());
		rotation = newAngle;
	}
	else
	{
		pos.setXY(item->xPos(), item->yPos());
		rotation = newAngle;
	}
}
void PageItem_PolyLine::DrawObj_Item(ScPainter *p, QRectF /*e*/)
{
	if (!m_Doc->RePos && PoLine.size()>=4)
	{
		if (!m_Doc->layerOutline(LayerID))
		{
			if ((fillColor() != CommonStrings::None) || (GrType != 0))
			{
				FPointArray cli;
				FPoint Start;
				bool firstp = true;
				for (uint n = 0; n < PoLine.size()-3; n += 4)
				{
					if (firstp)
					{
						Start = PoLine.point(n);
						firstp = false;
					}
					if (PoLine.point(n).x() > 900000)
					{
						cli.addPoint(PoLine.point(n-2));
						cli.addPoint(PoLine.point(n-2));
						cli.addPoint(Start);
						cli.addPoint(Start);
						cli.setMarker();
						firstp = true;
						continue;
					}
					cli.addPoint(PoLine.point(n));
					cli.addPoint(PoLine.point(n+1));
					cli.addPoint(PoLine.point(n+2));
					cli.addPoint(PoLine.point(n+3));
				}
				if (cli.size() > 2)
				{
					FPoint l1 = cli.point(cli.size()-2);
					cli.addPoint(l1);
					cli.addPoint(l1);
					cli.addPoint(Start);
					cli.addPoint(Start);
				}
				p->setupPolygon(&cli);
				p->fillPath();
			}
			p->setupPolygon(&PoLine, false);
			if (NamedLStyle.isEmpty())
			{
				if ((!patternStrokeVal.isEmpty()) && (m_Doc->docPatterns.contains(patternStrokeVal)))
				{
					if (patternStrokePath)
					{
						QPainterPath guidePath = PoLine.toQPainterPath(false);
						DrawStrokePattern(p, guidePath);
					}
					else
					{
						p->setPattern(&m_Doc->docPatterns[patternStrokeVal], patternStrokeScaleX, patternStrokeScaleY, patternStrokeOffsetX, patternStrokeOffsetY, patternStrokeRotation, patternStrokeSkewX, patternStrokeSkewY, patternStrokeMirrorX, patternStrokeMirrorY);
						p->setStrokeMode(ScPainter::Pattern);
						p->strokePath();
					}
				}
				else if (GrTypeStroke > 0)
				{
					if ((!gradientStrokeVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientStrokeVal)))
						gradientStrokeVal = "";
					if (!(gradientStrokeVal.isEmpty()) && (m_Doc->docGradients.contains(gradientStrokeVal)))
						stroke_gradient = m_Doc->docGradients[gradientStrokeVal];
					if (stroke_gradient.Stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
					{
						if (lineColor() != CommonStrings::None)
						{
							p->setBrush(strokeQColor);
							p->setStrokeMode(ScPainter::Solid);
						}
						else
							p->setStrokeMode(ScPainter::None);
					}
					else
					{
						p->setStrokeMode(ScPainter::Gradient);
						p->stroke_gradient = stroke_gradient;
						if (GrTypeStroke == 6)
							p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
						else
							p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY), GrStrokeScale, GrStrokeSkew);
					}
					p->strokePath();
				}
				else if (lineColor() != CommonStrings::None)
				{
					p->setStrokeMode(ScPainter::Solid);
					p->strokePath();
				}
			}
			else
			{
				p->setStrokeMode(ScPainter::Solid);
				multiLine ml = m_Doc->MLineStyles[NamedLStyle];
				QColor tmp;
				for (int it = ml.size()-1; it > -1; it--)
				{
					if (ml[it].Color != CommonStrings::None) // && (ml[it].Width != 0))
					{
						SetQColor(&tmp, ml[it].Color, ml[it].Shade);
						p->setPen(tmp, ml[it].Width, static_cast<Qt::PenStyle>(ml[it].Dash), static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
						p->strokePath();
					}
				}
			}
		}
		if (m_startArrowIndex != 0)
		{
			FPoint Start = PoLine.point(0);
			for (uint xx = 1; xx < PoLine.size(); xx += 2)
			{
				FPoint Vector = PoLine.point(xx);
				if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
				{
					double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
					QTransform arrowTrans;
					arrowTrans.translate(Start.x(), Start.y());
					arrowTrans.rotate(r);
					arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0);
					drawArrow(p, arrowTrans, m_startArrowIndex);
					break;
				}
			}
		}
		if (m_endArrowIndex != 0)
		{
			FPoint End = PoLine.point(PoLine.size()-2);
			for (uint xx = PoLine.size()-1; xx > 0; xx -= 2)
			{
				FPoint Vector = PoLine.point(xx);
				if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
				{
					double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
					QTransform arrowTrans;
					arrowTrans.translate(End.x(), End.y());
					arrowTrans.rotate(r);
					arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0);
					drawArrow(p, arrowTrans, m_endArrowIndex);
					break;
				}
			}
		}
	}
}
Example #16
0
void PageItem_Line::DrawObj_Item(ScPainter *p, QRectF /*e*/)
{
	if (m_Doc->RePos)
		return;

	if (m_Doc->layerOutline(m_layerID))
		p->drawLine(FPoint(0, 0), FPoint(m_width, 0));
	else
	{
		if (NamedLStyle.isEmpty())
		{
			ScPattern *strokePattern = m_Doc->checkedPattern(patternStrokeVal);
			if (strokePattern)
			{
				if (patternStrokePath)
				{
					QPainterPath guidePath;
					guidePath.moveTo(0, 0);
					guidePath.lineTo(m_width, 0);
					DrawStrokePattern(p, guidePath);
				}
				else
				{
					p->setPattern(strokePattern, patternStrokeScaleX, patternStrokeScaleY, patternStrokeOffsetX, patternStrokeOffsetY, patternStrokeRotation, patternStrokeSkewX, patternStrokeSkewY, patternStrokeMirrorX, patternStrokeMirrorY);
					p->setStrokeMode(ScPainter::Pattern);
					p->drawLine(FPoint(0, 0), FPoint(m_width, 0));
				}
			}
			else if (GrTypeStroke > 0)
			{
				if ((!gradientStrokeVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientStrokeVal)))
					gradientStrokeVal = "";
				if (!(gradientStrokeVal.isEmpty()) && (m_Doc->docGradients.contains(gradientStrokeVal)))
					stroke_gradient = m_Doc->docGradients[gradientStrokeVal];
				if (stroke_gradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
				{
					if (lineColor() != CommonStrings::None)
					{
						p->setBrush(strokeQColor);
						p->setStrokeMode(ScPainter::Solid);
					}
					else
					{
						no_stroke = true;
						p->setStrokeMode(ScPainter::None);
					}
				}
				else
				{
					p->setStrokeMode(ScPainter::Gradient);
					p->stroke_gradient = stroke_gradient;
					if (GrTypeStroke == 6)
						p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
					else
						p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY), GrStrokeScale, GrStrokeSkew);
				}
				p->drawLine(FPoint(0, 0), FPoint(m_width, 0));
			}
			else if (lineColor() != CommonStrings::None)
			{
				p->setStrokeMode(ScPainter::Solid);
				p->drawLine(FPoint(0, 0), FPoint(m_width, 0));
			}
			else
				no_stroke = true;
		}
		else
		{
			p->setStrokeMode(ScPainter::Solid);
			multiLine ml = m_Doc->MLineStyles[NamedLStyle];
			QColor tmp;
			for (int it = ml.size()-1; it > -1; it--)
			{
				if (ml[it].Color != CommonStrings::None) // && (ml[it].Width != 0))
				{
					SetQColor(&tmp, ml[it].Color, ml[it].Shade);
					p->setPen(tmp, ml[it].Width, static_cast<Qt::PenStyle>(ml[it].Dash), static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
					p->drawLine(FPoint(0, 0), FPoint(m_width, 0));
				}
			}
		}
	}
	if (m_startArrowIndex != 0)
	{
		QTransform arrowTrans;
		arrowTrans.translate(0, 0);
		arrowTrans.scale(-1,1);
		arrowTrans.scale(m_startArrowScale / 100.0, m_startArrowScale / 100.0);
		drawArrow(p, arrowTrans, m_startArrowIndex);
	}
	if (m_endArrowIndex != 0)
	{
		QTransform arrowTrans;
		arrowTrans.translate(m_width, 0);
		arrowTrans.scale(m_endArrowScale / 100.0, m_endArrowScale / 100.0);
		drawArrow(p, arrowTrans, m_endArrowIndex);
	}
}
Example #17
0
void QgsComposerView::mousePressEvent( QMouseEvent* e )
{
  if ( !composition() )
  {
    return;
  }

  QPointF scenePoint = mapToScene( e->pos() );
  QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint );
  mMousePressStartPos = e->pos();

  //lock/unlock position of item with right click
  if ( e->button() == Qt::RightButton )
  {
    QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint );
    if ( selectedItem )
    {
      bool lock = selectedItem->positionLock() ? false : true;
      selectedItem->setPositionLock( lock );
      selectedItem->update();
    }
    return;
  }
  else if ( e->button() == Qt::MidButton )
  {
    //pan composer with middle button
    mPanning = true;
    mMouseLastXY = e->pos();
    if ( composition() )
    {
      //lock cursor to closed hand cursor
      composition()->setPreventCursorChange( true );
    }
    viewport()->setCursor( Qt::ClosedHandCursor );
    return;
  }

  switch ( mCurrentTool )
  {
      //select/deselect items and pass mouse event further
    case Select:
    {
      //check if we are clicking on a selection handle
      if ( composition()->selectionHandles()->isVisible() )
      {
        //selection handles are being shown, get mouse action for current cursor position
        QgsComposerMouseHandles::MouseAction mouseAction = composition()->selectionHandles()->mouseActionForScenePos( scenePoint );

        if ( mouseAction != QgsComposerMouseHandles::MoveItem && mouseAction != QgsComposerMouseHandles::NoAction && mouseAction != QgsComposerMouseHandles::SelectItem )
        {
          //mouse is over a resize handle, so propagate event onward
          QGraphicsView::mousePressEvent( e );
          return;
        }
      }

      QgsComposerItem* selectedItem = 0;
      QgsComposerItem* previousSelectedItem = 0;

      if ( e->modifiers() & Qt::ControlModifier )
      {
        //CTRL modifier, so we are trying to select the next item below the current one
        //first, find currently selected item
        QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems();
        if ( selectedItems.size() > 0 )
        {
          previousSelectedItem = selectedItems.at( 0 );
        }
      }

      if ( previousSelectedItem )
      {
        //select highest item just below previously selected item at position of event
        selectedItem = composition()->composerItemAt( scenePoint, previousSelectedItem );

        //if we didn't find a lower item we'll use the top-most as fall-back
        //this duplicates mapinfo/illustrator/etc behaviour where ctrl-clicks are "cyclic"
        if ( !selectedItem )
        {
          selectedItem = composition()->composerItemAt( scenePoint );
        }
      }
      else
      {
        //select topmost item at position of event
        selectedItem = composition()->composerItemAt( scenePoint );
      }

      if ( !selectedItem )
      {
        //not clicking over an item, so start marquee selection
        startMarqueeSelect( scenePoint );
        break;
      }

      if (( !selectedItem->selected() ) &&        //keep selection if an already selected item pressed
          !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
      {
        composition()->clearSelection();
      }

      if (( e->modifiers() & Qt::ShiftModifier ) && ( selectedItem->selected() ) )
      {
        //SHIFT-clicking a selected item deselects it
        selectedItem->setSelected( false );

        //Check if we have any remaining selected items, and if so, update the item panel
        QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems();
        if ( selectedItems.size() > 0 )
        {
          emit selectedItemChanged( selectedItems.at( 0 ) );
        }
      }
      else
      {
        selectedItem->setSelected( true );
        QGraphicsView::mousePressEvent( e );
        emit selectedItemChanged( selectedItem );
      }
      break;
    }

    case Zoom:
    {
      if ( !( e->modifiers() & Qt::ShiftModifier ) )
      {
        //zoom in action
        startMarqueeZoom( scenePoint );
      }
      else
      {
        //zoom out action, so zoom out and recenter on clicked point
        double scaleFactor = 2;
        //get current visible part of scene
        QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
        QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );

        //transform the mouse pos to scene coordinates
        QPointF scenePoint = mapToScene( e->pos() );

        visibleRect.scale( scaleFactor, scenePoint.x(), scenePoint.y() );
        QRectF boundsRect = visibleRect.toRectF();

        //zoom view to fit desired bounds
        fitInView( boundsRect, Qt::KeepAspectRatio );
      }
      break;
    }

    case Pan:
    {
      //pan action
      mPanning = true;
      mMouseLastXY = e->pos();
      viewport()->setCursor( Qt::ClosedHandCursor );
      break;
    }

    case MoveItemContent:
    {
      //get a list of items at clicked position
      QList<QGraphicsItem *> itemsAtCursorPos = items( e->pos() );
      if ( itemsAtCursorPos.size() == 0 )
      {
        //no items at clicked position
        return;
      }

      //find highest QgsComposerItem at clicked position
      //(other graphics items may be higher, eg selection handles)
      QList<QGraphicsItem*>::iterator itemIter = itemsAtCursorPos.begin();
      for ( ; itemIter != itemsAtCursorPos.end(); ++itemIter )
      {
        QgsComposerItem* item = dynamic_cast<QgsComposerItem *>(( *itemIter ) );
        if ( item )
        {
          //we've found the highest QgsComposerItem
          mMoveContentStartPos = scenePoint;
          mMoveContentItem = item;
          break;
        }
      }

      //no QgsComposerItem at clicked position
      return;
    }

    case AddArrow:
    {
      mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandLineItem = new QGraphicsLineItem( snappedScenePoint.x(), snappedScenePoint.y(), snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandLineItem->setZValue( 1000 );
      scene()->addItem( mRubberBandLineItem );
      scene()->update();
      break;
    }

    //create rubber band for map and ellipse items
    case AddMap:
    case AddRectangle:
    case AddTriangle:
    case AddEllipse:
    case AddHtml:
    {
      QTransform t;
      mRubberBandItem = new QGraphicsRectItem( 0, 0, 0, 0 );
      mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() );
      t.translate( snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandItem->setTransform( t );
      mRubberBandItem->setZValue( 1000 );
      scene()->addItem( mRubberBandItem );
      scene()->update();
    }
    break;

    case AddLabel:
      if ( composition() )
      {
        QgsComposerLabel* newLabelItem = new QgsComposerLabel( composition() );
        newLabelItem->setText( tr( "QGIS" ) );
        newLabelItem->adjustSizeToText();
        newLabelItem->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLabelItem->rect().width(), newLabelItem->rect().height() ) );
        composition()->addComposerLabel( newLabelItem );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newLabelItem, tr( "Label added" ) );
      }
      break;

    case AddScalebar:
      if ( composition() )
      {
        QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( composition() );
        newScaleBar->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 20, 20 ) );
        composition()->addComposerScaleBar( newScaleBar );
        QList<const QgsComposerMap*> mapItemList = composition()->composerMapItems();
        if ( mapItemList.size() > 0 )
        {
          newScaleBar->setComposerMap( mapItemList.at( 0 ) );
        }
        newScaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width
        emit actionFinished();
        composition()->pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) );
      }
      break;

    case AddLegend:
    {
      if ( composition() )
      {
        QgsComposerLegend* newLegend = new QgsComposerLegend( composition() );
        newLegend->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLegend->rect().width(), newLegend->rect().height() ) );
        composition()->addComposerLegend( newLegend );
        newLegend->updateLegend();
        emit actionFinished();
        composition()->pushAddRemoveCommand( newLegend, tr( "Legend added" ) );
      }
      break;
    }
    case AddPicture:
      if ( composition() )
      {
        QgsComposerPicture* newPicture = new QgsComposerPicture( composition() );
        newPicture->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 30, 30 ) );
        composition()->addComposerPicture( newPicture );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newPicture, tr( "Picture added" ) );
      }
      break;
    case AddTable:
      if ( composition() )
      {
        QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( composition() );
        newTable->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 50, 50 ) );
        composition()->addComposerTable( newTable );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newTable, tr( "Table added" ) );
      }
      break;
    default:
      break;
  }
}
Example #18
0
void QgsComposerView::mouseMoveEvent( QMouseEvent* e )
{
  if ( !composition() )
  {
    return;
  }

  updateRulers();
  if ( mHorizontalRuler )
  {
    mHorizontalRuler->updateMarker( e->posF() );
  }
  if ( mVerticalRuler )
  {
    mVerticalRuler->updateMarker( e->posF() );
  }

  if ( e->buttons() == Qt::NoButton )
  {
    if ( mCurrentTool == Select )
    {
      QGraphicsView::mouseMoveEvent( e );
    }
  }
  else
  {
    QPointF scenePoint = mapToScene( e->pos() );

    switch ( mCurrentTool )
    {
      case Select:
        QGraphicsView::mouseMoveEvent( e );
        break;

      case AddArrow:
      {
        if ( mRubberBandLineItem )
        {
          mRubberBandLineItem->setLine( mRubberBandStartPos.x(), mRubberBandStartPos.y(),  scenePoint.x(),  scenePoint.y() );
        }
        break;
      }

      case AddMap:
      case AddRectangle:
      case AddTriangle:
      case AddEllipse:
      case AddHtml:
        //adjust rubber band item
      {
        double x = 0;
        double y = 0;
        double width = 0;
        double height = 0;

        double dx = scenePoint.x() - mRubberBandStartPos.x();
        double dy = scenePoint.y() - mRubberBandStartPos.y();

        if ( dx < 0 )
        {
          x = scenePoint.x();
          width = -dx;
        }
        else
        {
          x = mRubberBandStartPos.x();
          width = dx;
        }

        if ( dy < 0 )
        {
          y = scenePoint.y();
          height = -dy;
        }
        else
        {
          y = mRubberBandStartPos.y();
          height = dy;
        }

        if ( mRubberBandItem )
        {
          mRubberBandItem->setRect( 0, 0, width, height );
          QTransform t;
          t.translate( x, y );
          mRubberBandItem->setTransform( t );
        }
        break;
      }

      case MoveItemContent:
      {
        //update map preview if composer map
        QgsComposerMap* composerMap = dynamic_cast<QgsComposerMap *>( mMoveContentItem );
        if ( composerMap )
        {
          composerMap->setOffset( scenePoint.x() - mMoveContentStartPos.x(), scenePoint.y() - mMoveContentStartPos.y() );
          composerMap->update();
        }
        break;
      }
      default:
        break;
    }
  }
}
int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, int *gStateObject)
{
    int paintType = 2; // Uncolored tiling
    int w = 8;
    int h = 8;

    *specifyColor = true;
    *gStateObject = 0;

    QTransform matrix = m;
    matrix.translate(brushOrigin.x(), brushOrigin.y());
    matrix = matrix * pageMatrix();
    //qDebug() << brushOrigin << matrix;

    Qt::BrushStyle style = brush.style();
    if (style == Qt::LinearGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
#ifdef USE_NATIVE_GRADIENTS
        *specifyColor = false;
        return gradientBrush(b, matrix, gStateObject);
#else
        return 0;
#endif
    }

    if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
        *gStateObject = addConstantAlphaObject(qRound(brush.color().alpha() * opacity),
                                               qRound(pen.color().alpha() * opacity));

    int imageObject = -1;
    QByteArray pattern = QPdf::patternForBrush(brush);
    if (pattern.isEmpty()) {
        if (brush.style() != Qt::TexturePattern)
            return 0;
        QImage image = brush.texture().toImage();
        bool bitmap = true;
        imageObject = addImage(image, &bitmap, qt_pixmap_id(brush.texture()));
        if (imageObject != -1) {
            QImage::Format f = image.format();
            if (f != QImage::Format_MonoLSB && f != QImage::Format_Mono) {
                paintType = 1; // Colored tiling
                *specifyColor = false;
            }
            w = image.width();
            h = image.height();
            QTransform m(w, 0, 0, -h, 0, h);
            QPdf::ByteStream s(&pattern);
            s << QPdf::generateMatrix(m);
            s << "/Im" << imageObject << " Do\n";
        }
    }

    QByteArray str;
    QPdf::ByteStream s(&str);
    s << "<<\n"
        "/Type /Pattern\n"
        "/PatternType 1\n"
        "/PaintType " << paintType << "\n"
        "/TilingType 1\n"
        "/BBox [0 0 " << w << h << "]\n"
        "/XStep " << w << "\n"
        "/YStep " << h << "\n"
        "/Matrix ["
      << matrix.m11()
      << matrix.m12()
      << matrix.m21()
      << matrix.m22()
      << matrix.dx()
      << matrix.dy() << "]\n"
        "/Resources \n<< "; // open resource tree
    if (imageObject > 0) {
        s << "/XObject << /Im" << imageObject << ' ' << imageObject << "0 R >> ";
    }
    s << ">>\n"
        "/Length " << pattern.length() << "\n"
        ">>\n"
        "stream\n"
      << pattern
      << "endstream\n"
        "endobj\n";

    int patternObj = addXrefEntry(-1);
    write(str);
    currentPage->patterns.append(patternObj);
    return patternObj;
}
Example #20
0
void QgsComposerView::mousePressEvent( QMouseEvent* e )
{
  if ( !composition() )
  {
    return;
  }

  QPointF scenePoint = mapToScene( e->pos() );
  QPointF snappedScenePoint = composition()->snapPointToGrid( scenePoint );

  //lock/unlock position of item with right click
  if ( e->button() == Qt::RightButton )
  {
    QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint );
    if ( selectedItem )
    {
      bool lock = selectedItem->positionLock() ? false : true;
      selectedItem->setPositionLock( lock );
      selectedItem->update();
      //make sure the new cursor is correct
      QPointF itemPoint = selectedItem->mapFromScene( scenePoint );
      selectedItem->updateCursor( itemPoint );
    }
    return;
  }

  switch ( mCurrentTool )
  {
      //select/deselect items and pass mouse event further
    case Select:
    {
      if ( !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
      {
        composition()->clearSelection();
      }

      //select topmost item at position of event
      QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint );
      if ( !selectedItem )
      {
        break;
      }

      selectedItem->setSelected( true );
      QGraphicsView::mousePressEvent( e );
      emit selectedItemChanged( selectedItem );
      break;
    }

    case MoveItemContent:
    {
      //store item as member if it is selected and cursor is over item
      QgsComposerItem* item = dynamic_cast<QgsComposerItem *>( itemAt( e->pos() ) );
      if ( item )
      {
        mMoveContentStartPos = scenePoint;
      }
      mMoveContentItem = item;
      break;
    }

    case AddArrow:
    {
      mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandLineItem = new QGraphicsLineItem( snappedScenePoint.x(), snappedScenePoint.y(), snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandLineItem->setZValue( 100 );
      scene()->addItem( mRubberBandLineItem );
      scene()->update();
      break;
    }

    //create rubber band for map and ellipse items
    case AddMap:
    case AddRectangle:
    case AddTriangle:
    case AddEllipse:
    case AddHtml:
    {
      QTransform t;
      mRubberBandItem = new QGraphicsRectItem( 0, 0, 0, 0 );
      mRubberBandStartPos = QPointF( snappedScenePoint.x(), snappedScenePoint.y() );
      t.translate( snappedScenePoint.x(), snappedScenePoint.y() );
      mRubberBandItem->setTransform( t );
      mRubberBandItem->setZValue( 100 );
      scene()->addItem( mRubberBandItem );
      scene()->update();
    }
    break;

    case AddLabel:
      if ( composition() )
      {
        QgsComposerLabel* newLabelItem = new QgsComposerLabel( composition() );
        newLabelItem->setText( tr( "Quantum GIS" ) );
        newLabelItem->adjustSizeToText();
        newLabelItem->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLabelItem->rect().width(), newLabelItem->rect().height() ) );
        composition()->addComposerLabel( newLabelItem );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newLabelItem, tr( "Label added" ) );
      }
      break;

    case AddScalebar:
      if ( composition() )
      {
        QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( composition() );
        newScaleBar->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 20, 20 ) );
        composition()->addComposerScaleBar( newScaleBar );
        QList<const QgsComposerMap*> mapItemList = composition()->composerMapItems();
        if ( mapItemList.size() > 0 )
        {
          newScaleBar->setComposerMap( mapItemList.at( 0 ) );
        }
        newScaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width
        emit actionFinished();
        composition()->pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) );
      }
      break;

    case AddLegend:
    {
      if ( composition() )
      {
        QgsComposerLegend* newLegend = new QgsComposerLegend( composition() );
        newLegend->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), newLegend->rect().width(), newLegend->rect().height() ) );
        composition()->addComposerLegend( newLegend );
        newLegend->updateLegend();
        emit actionFinished();
        composition()->pushAddRemoveCommand( newLegend, tr( "Legend added" ) );
      }
      break;
    }
    case AddPicture:
      if ( composition() )
      {
        QgsComposerPicture* newPicture = new QgsComposerPicture( composition() );
        newPicture->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 30, 30 ) );
        composition()->addComposerPicture( newPicture );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newPicture, tr( "Picture added" ) );
      }
      break;
    case AddTable:
      if ( composition() )
      {
        QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( composition() );
        newTable->setSceneRect( QRectF( snappedScenePoint.x(), snappedScenePoint.y(), 50, 50 ) );
        composition()->addComposerTable( newTable );
        emit actionFinished();
        composition()->pushAddRemoveCommand( newTable, tr( "Table added" ) );
      }
      break;
    default:
      break;
  }
}
Example #21
0
void Path::translate(const FloatSize& size)
{
    QTransform matrix;
    matrix.translate(size.width(), size.height());
    m_path = m_path * matrix;
}
QPainterPath ArtisticTextToolSelection::outline()
{
    if (!hasSelection())
        return QPainterPath();

    CharIndex charPos = m_currentShape->indexOfChar(m_selectionStart);
    if (charPos.first < 0)
        return QPainterPath();

    QPainterPath outline;

    QPolygonF polygon;

    QList<ArtisticTextRange> ranges = m_currentShape->text();
    int globalCharIndex = m_selectionStart;
    int remainingChars = m_selectionCount;
    while (remainingChars) {
        const ArtisticTextRange &currentRange = ranges[charPos.first];

        int currentTextLength = currentRange.text().length();
        while (charPos.second < currentTextLength && remainingChars > 0) {
            const QPointF pos = m_currentShape->charPositionAt(globalCharIndex);
            const qreal angle = m_currentShape->charAngleAt(globalCharIndex);

            QTransform charTransform;
            charTransform.translate( pos.x() - 1, pos.y() );
            charTransform.rotate( 360. - angle );

            QFontMetricsF metrics(currentRange.font());

            polygon.prepend(charTransform.map(QPointF(0.0, -metrics.ascent())));
            polygon.append(charTransform.map(QPointF(0.0, metrics.descent())));

            // advance to next character
            charPos.second++;
            globalCharIndex++;
            remainingChars--;

            // next character has y-offset or we are at the end of this text range
            const bool hasYOffset = currentRange.hasYOffset(charPos.second);
            const bool atRangeEnd = charPos.second == currentTextLength;
            const bool atSelectionEnd = remainingChars == 0;
            if (hasYOffset || atRangeEnd || atSelectionEnd) {
                if (hasYOffset || atRangeEnd) {
                    const QChar c = currentRange.text().at(charPos.second-1);
                    const qreal w = metrics.width(c);
                    polygon.prepend(charTransform.map(QPointF(w, -metrics.ascent())));
                    polygon.append(charTransform.map(QPointF(w, metrics.descent())));
                } else {
                    const QPointF pos = m_currentShape->charPositionAt(globalCharIndex);
                    const qreal angle = m_currentShape->charAngleAt(globalCharIndex);
                    charTransform.reset();
                    charTransform.translate( pos.x() - 1, pos.y() );
                    charTransform.rotate( 360. - angle );
                    polygon.prepend(charTransform.map(QPointF(0.0, -metrics.ascent())));
                    polygon.append(charTransform.map(QPointF(0.0, metrics.descent())));
                }
                QPainterPath p;
                p.addPolygon(polygon);
                outline = outline.united(p);
                polygon.clear();
            }
        }

        // go to first character of next text range
        charPos.first++;
        charPos.second = 0;
    }

    // transform to document coordinates
    return m_currentShape->absoluteTransformation(0).map(outline);
}
void ShapeResizeStrategy::resizeBy( const QPointF &center, qreal zoomX, qreal zoomY )
{
    QTransform matrix;
    matrix.translate(center.x(), center.y()); // translate to 
    matrix.scale(zoomX, zoomY);
    matrix.translate(-center.x(), -center.y()); // and back

    // that is the transformation we want to apply to the shapes
    matrix = m_unwindMatrix * matrix * m_windMatrix;

    // the resizing transformation without the mirroring part
    QTransform resizeMatrix;
    resizeMatrix.translate(center.x(), center.y()); // translate to 
    resizeMatrix.scale( qAbs(zoomX), qAbs(zoomY) );
    resizeMatrix.translate(-center.x(), -center.y()); // and back

    // the mirroring part of the resizing transformation
    QTransform mirrorMatrix;
    mirrorMatrix.translate(center.x(), center.y()); // translate to 
    mirrorMatrix.scale( zoomX < 0 ? -1 : 1, zoomY < 0 ? -1 : 1 );
    mirrorMatrix.translate(-center.x(), -center.y()); // and back

    int i = 0;
    foreach(KoShape *shape, m_selectedShapes)
    {
        shape->update();

        // this uses resize for the zooming part
        shape->applyAbsoluteTransformation( m_unwindMatrix );

        /*
         normally we would just apply the resizeMatrix now and be done with it, but
         we want to resize instead of scale, so we have to separate the scaling part
         of that transformation which can then be used to resize
        */

        // undo the last resize transformation
        shape->applyAbsoluteTransformation( m_transformations[i].inverted() );

        // save the shapes transformation matrix
        QTransform shapeMatrix = shape->absoluteTransformation(0);

        // calculate the matrix we would apply to the local shape matrix
        // that tells us the effective scale values we have to use for the resizing
        QTransform localMatrix = shapeMatrix * resizeMatrix * shapeMatrix.inverted();
        // save the effective scale values
        qreal scaleX = localMatrix.m11();
        qreal scaleY = localMatrix.m22();

        // calculate the scale matrix which is equivalent to our resizing above
        QTransform scaleMatrix = (QTransform().scale( scaleX, scaleY ));
        scaleMatrix =  shapeMatrix.inverted() * scaleMatrix * shapeMatrix;

        // calculate the new size of the shape, using the effective scale values
        QSizeF size( scaleX * m_startSizes[i].width(), scaleY * m_startSizes[i].height() );

        // apply the transformation
        shape->setSize( size );
        // apply the rest of the transformation without the resizing part
        shape->applyAbsoluteTransformation( scaleMatrix.inverted() * resizeMatrix );
        shape->applyAbsoluteTransformation( mirrorMatrix );

        // and remember the applied transformation later for later undoing
        m_transformations[i] = shapeMatrix.inverted() * shape->absoluteTransformation(0);

        shape->applyAbsoluteTransformation( m_windMatrix );

        shape->update();
        i++;
    }
void tst_QPainterPath::testOperatorEquals_fuzzy()
{
    // if operator== returns true for two paths it should
    // also return true when the same transform is applied to both paths
    {
        QRectF a(100, 100, 100, 50);
        QRectF b = a.translated(1e-14, 1e-14);

        QPainterPath pa;
        pa.addRect(a);
        QPainterPath pb;
        pb.addRect(b);

        QVERIFY(pa == pb);

        QTransform transform;
        transform.translate(-100, -100);

        QVERIFY(transform.map(pa) == transform.map(pb));
    }

    // higher tolerance for error when path's bounding rect is big
    {
        QRectF a(1, 1, 1e6, 0.5e6);
        QRectF b = a.translated(1e-7, 1e-7);

        QPainterPath pa;
        pa.addRect(a);
        QPainterPath pb;
        pb.addRect(b);

        QVERIFY(pa == pb);

        QTransform transform;
        transform.translate(-1, -1);

        QVERIFY(transform.map(pa) == transform.map(pb));
    }

    // operator== should return true for a path that has
    // been transformed and then inverse transformed
    {
        QPainterPath a;
        a.addRect(0, 0, 100, 100);

        QTransform transform;
        transform.translate(100, 20);
        transform.scale(1.5, 1.5);

        QPainterPath b = transform.inverted().map(transform.map(a));

        QVERIFY(a == b);
    }

    {
        QPainterPath a;
        a.lineTo(10, 0);
        a.lineTo(10, 10);
        a.lineTo(0, 10);

        QPainterPath b;
        b.lineTo(10, 0);
        b.moveTo(10, 10);
        b.lineTo(0, 10);

        QVERIFY(a != b);
    }
}
Example #25
0
void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *stackBefore)
{
    if (targetParent && target && target->parentItem()) {
        Q_Q(QQuickParentChange);
        bool ok;
        const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
        if (transform.type() >= QTransform::TxShear || !ok) {
            qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under complex transform");
            ok = false;
        }

        qreal scale = 1;
        qreal rotation = 0;
        bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
        if (ok && !isRotate) {
            if (transform.m11() == transform.m22())
                scale = transform.m11();
            else {
                qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
                ok = false;
            }
        } else if (ok && isRotate) {
            if (transform.m11() == transform.m22())
                scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
            else {
                qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
                ok = false;
            }

            if (scale != 0)
                rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
            else {
                qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0");
                ok = false;
            }
        }

        const QPointF &point = transform.map(QPointF(target->x(),target->y()));
        qreal x = point.x();
        qreal y = point.y();

        // setParentItem will update the transformOriginPoint if needed
        target->setParentItem(targetParent);

        if (ok && target->transformOrigin() != QQuickItem::TopLeft) {
            qreal tempxt = target->transformOriginPoint().x();
            qreal tempyt = target->transformOriginPoint().y();
            QTransform t;
            t.translate(-tempxt, -tempyt);
            t.rotate(rotation);
            t.scale(scale, scale);
            t.translate(tempxt, tempyt);
            const QPointF &offset = t.map(QPointF(0,0));
            x += offset.x();
            y += offset.y();
        }

        if (ok) {
            //qDebug() << x << y << rotation << scale;
            target->setPosition(QPointF(x, y));
            target->setRotation(target->rotation() + rotation);
            target->setScale(target->scale() * scale);
        }
    } else if (target) {
        target->setParentItem(targetParent);
    }

    //restore the original stack position.
    //### if stackBefore has also been reparented this won't work
    if (stackBefore)
        target->stackBefore(stackBefore);
}
bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext &context, QPointF shift ) const
{
  //width
  double symbolWidth = mSymbolWidth;

  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
  {
    context.setOriginalValueVariable( mSymbolWidth );
    symbolWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mSymbolWidth ).toDouble();
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
  {
    symbolWidth = mSize;
  }
  if ( mSymbolWidthUnit == QgsSymbolV2::MM )
  {
    symbolWidth *= mmMapUnitScaleFactor;
  }

  //height
  double symbolHeight = mSymbolHeight;
  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
  {
    context.setOriginalValueVariable( mSymbolHeight );
    symbolHeight = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, context, mSymbolHeight ).toDouble();
  }
  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
  {
    symbolHeight = mSize;
  }
  if ( mSymbolHeightUnit == QgsSymbolV2::MM )
  {
    symbolHeight *= mmMapUnitScaleFactor;
  }

  //outline width
  double outlineWidth = mOutlineWidth;

  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) )
  {
    context.setOriginalValueVariable( mOutlineWidth );
    outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, mOutlineWidth ).toDouble();
  }
  if ( mOutlineWidthUnit == QgsSymbolV2::MM )
  {
    outlineWidth *= outlineWidth;
  }

  //fill color
  bool ok;
  QColor fc = mColor;
  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR ) )
  {
    context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mColor ) );
    QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, context, QVariant(), &ok ).toString();
    if ( ok )
      fc = QgsSymbolLayerV2Utils::decodeColor( colorString );
  }

  //outline color
  QColor oc = mOutlineColor;
  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR ) )
  {
    context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mOutlineColor ) );
    QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, context, QVariant(), &ok ).toString();
    if ( ok )
      oc = QgsSymbolLayerV2Utils::decodeColor( colorString );
  }

  //symbol name
  QString symbolName = mSymbolName;
  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME ) )
  {
    context.setOriginalValueVariable( mSymbolName );
    symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context, mSymbolName ).toString();
  }

  //offset
  double offsetX = 0;
  double offsetY = 0;
  markerOffset( context, offsetX, offsetY );
  QPointF off( offsetX, offsetY );

  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
  double rotation = 0.0;
  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION ) )
  {
    context.setOriginalValueVariable( mAngle );
    rotation = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle ).toDouble() + mLineAngle;
  }
  else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
  {
    rotation = mAngle + mLineAngle;
  }
  rotation = -rotation; //rotation in Qt is counterclockwise
  if ( rotation )
    off = _rotatedOffset( off, rotation );

  QTransform t;
  t.translate( shift.x() + offsetX, shift.y() + offsetY );

  if ( !qgsDoubleNear( rotation, 0.0 ) )
    t.rotate( rotation );

  double halfWidth = symbolWidth / 2.0;
  double halfHeight = symbolHeight / 2.0;

  if ( symbolName == "circle" )
  {
    if ( qgsDoubleNear( halfWidth, halfHeight ) )
    {
      QgsPointV2 pt( t.map( QPointF( 0, 0 ) ) );
      e.writeFilledCircle( layerName, oc, pt, halfWidth );
    }
    else
    {
      QgsPointSequenceV2 line;

      double stepsize = 2 * M_PI / 40;
      for ( int i = 0; i < 39; ++i )
      {
        double angle = stepsize * i;
        double x = halfWidth * cos( angle );
        double y = halfHeight * sin( angle );
        line << QgsPointV2( t.map( QPointF( x, y ) ) );
      }
      //close ellipse with first point
      line << line.at( 0 );

      if ( mBrush.style() != Qt::NoBrush )
        e.writePolygon( QgsRingSequenceV2() << line, layerName, "SOLID", fc );
      if ( mPen.style() != Qt::NoPen )
        e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
    }
  }
  else if ( symbolName == "rectangle" )
  {
    QgsPointSequenceV2 p;
    p << QgsPointV2( t.map( QPointF( -halfWidth, -halfHeight ) ) )
    << QgsPointV2( t.map( QPointF( halfWidth, -halfHeight ) ) )
    << QgsPointV2( t.map( QPointF( halfWidth, halfHeight ) ) )
    << QgsPointV2( t.map( QPointF( -halfWidth, halfHeight ) ) );
    p << p[0];

    if ( mBrush.style() != Qt::NoBrush )
      e.writePolygon( QgsRingSequenceV2() << p, layerName, "SOLID", fc );
    if ( mPen.style() != Qt::NoPen )
      e.writePolyline( p, layerName, "CONTINUOUS", oc, outlineWidth );
    return true;
  }
  else if ( symbolName == "cross" && mPen.style() != Qt::NoPen )
  {
    e.writePolyline( QgsPointSequenceV2()
                     << QgsPointV2( t.map( QPointF( -halfWidth, 0 ) ) )
                     << QgsPointV2( t.map( QPointF( halfWidth, 0 ) ) ),
                     layerName, "CONTINUOUS", oc, outlineWidth );
    e.writePolyline( QgsPointSequenceV2()
                     << QgsPointV2( t.map( QPointF( 0, halfHeight ) ) )
                     << QgsPointV2( t.map( QPointF( 0, -halfHeight ) ) ),
                     layerName, "CONTINUOUS", oc, outlineWidth );
    return true;
  }
  else if ( symbolName == "triangle" )
  {
    QgsPointSequenceV2 p;
    p << QgsPointV2( t.map( QPointF( -halfWidth, -halfHeight ) ) )
    << QgsPointV2( t.map( QPointF( halfWidth, -halfHeight ) ) )
    << QgsPointV2( t.map( QPointF( 0, halfHeight ) ) );
    p << p[0];
    if ( mBrush.style() != Qt::NoBrush )
      e.writePolygon( QgsRingSequenceV2() << p, layerName, "SOLID", fc );
    if ( mPen.style() != Qt::NoPen )
      e.writePolyline( p, layerName, "CONTINUOUS", oc, outlineWidth );
    return true;
  }

  return false; //soon...
}
Example #27
0
/**
 * Renders the text data into painter paths.
 */
void RTextRenderer::render() {
    boundingBox = RBox();
    painterPaths.clear();
    richText = "";

    QString text = textData.getEscapedText();
    //RVector position = textData.getPosition();
    RVector position = textData.getAlignmentPoint();
    double textHeight = textData.getTextHeight();
    RS::VAlign verticalAlignment = textData.getVAlign();
    RS::HAlign horizontalAlignment = textData.getHAlign();
    double lineSpacingFactor = textData.getLineSpacingFactor();
    QString fontName = textData.getFontName();
    bool bold = textData.isBold();
    bool italic = textData.isItalic();
    double angle = textData.getAngle();
    //RColor color = textData.getColor(true);

    // split up text where separation is required due to line feed,
    // or any type of height change (\P, \H[0-9]*.?[0-9]+;, \S*/*;)

    // split up text at every formatting change:
    QRegExp regExpAll(rxAll);
    QStringList literals = text.split(regExpAll);

    // collect formatting change information for every literal:
    QStringList formattings;
    int pos = 0;
    while ((pos = regExpAll.indexIn(text, pos)) != -1) {
        formattings << regExpAll.cap(1);
        pos += regExpAll.matchedLength();
    }

    // x position in real units:
    double xCursor = 0.0;
    // y position for next text line:
    double yCursor = 0.0;
    // painter paths for current text line:
    QList<RPainterPath> linePaths;
    // max ascent of current text line:
    double maxAscent = 0.0;
    // max descent of current line:
    double minDescent = 0.0;
    // max descent of _previous_ line:
    double minDescentPrevious = 0.0;
    // true for the first block of the current line:
    bool firstBlockInLine = true;
    // current line has leading spaces:
    bool leadingSpaces = false;
    // current line has trailing spaces:
    bool trailingSpaces = false;
    // text has leading empty lines:
    bool leadingEmptyLines = false;
    // text has trailing empty lines:
    bool trailingEmptyLines = false;
    int lineCounter = 0;
    QString textBlock;
    QList<QTextLayout::FormatRange> formats;

    bool blockChangedHeightOrFont = false;

    // implicit top level format block:
    QTextCharFormat f;
    f.setForeground(QBrush(QColor()));
    currentFormat.push(f);
    QTextLayout::FormatRange fr;
    fr.start = 0;
    fr.length = 0;
    fr.format = currentFormat.top();
    formats.append(fr);
    blockHeight.push(textHeight);
    blockFont.push(fontName);
    blockBold.push(bold);
    blockItalic.push(italic);
    useCadFont.push(RFontList::isCadFont(fontName));
    openTags.push(QStringList());

    width = 0.0;
    height = 0.0;

    // iterate through all text blocks:
    for (int i=0; i<literals.size(); ++i) {

        // the literal text, e.g. "ABC":
        QString literal = literals.at(i);

        // the formatting _after_ the text, e.g. "\C1;"
        QString formatting;
        if (i<formattings.size()) {
            formatting = formattings.at(i);
        }

//        qDebug() << "block: " << i;
//        qDebug() << "  literal: " << literal;
//        qDebug() << "  literal length: " << literal.length();
//        qDebug() << "  formatting: " << formatting;
//        qDebug() << "  font: " << blockFont.top();
//        qDebug() << "  height: " << blockHeight.top();
//        qDebug() << "  cad font: " << useCadFont.top();
//        qDebug() << "  xCursor: " << xCursor;

        // handle literal:
        textBlock.append(literal);

        if (firstBlockInLine) {
            if (!literal.isEmpty()) {
                if (literal.at(0).isSpace()) {
                    leadingSpaces = true;
                }
            }
            else {
                if (formatting=="\\~") {
                    leadingSpaces = true;
                }
            }
            firstBlockInLine = false;
        }

        bool lineFeed = false;
        bool paragraphFeed = false;
        bool heightChange = false;
        bool stackedText = false;
        bool fontChange = false;
        bool colorChange = false;
        bool blockEnd = false;

        // detect formatting that ends the current text block:
        if (!formatting.isEmpty()) {
            fontChange = QRegExp(rxFontChangeTtf).exactMatch(formatting) ||
                QRegExp(rxFontChangeCad).exactMatch(formatting);
            colorChange = QRegExp(rxColorChangeCustom).exactMatch(formatting) ||
                QRegExp(rxColorChangeIndex).exactMatch(formatting);
            heightChange = QRegExp(rxHeightChange).exactMatch(formatting);
            stackedText = QRegExp(rxStackedText).exactMatch(formatting);
            lineFeed = QRegExp(rxLineFeed).exactMatch(formatting);
            paragraphFeed = QRegExp(rxParagraphFeed).exactMatch(formatting);
            blockEnd = QRegExp(rxEndBlock).exactMatch(formatting);
        }

        bool start = (i==0);
        bool end = (i==literals.size()-1);

        // first line is empty:
        if (textBlock.trimmed().isEmpty() && (lineFeed || paragraphFeed || end)) {
            if (start) {
                leadingEmptyLines = true;
            }
            else if (end) {
                trailingEmptyLines = true;
            }
        }

        // reached a new text block that needs to be rendered separately
        // due to line feed, height change, font change, ...:
        if (target==RichText ||
            lineFeed || paragraphFeed || heightChange || stackedText ||
            fontChange || colorChange || end
            || (blockEnd && blockChangedHeightOrFont)) {

            // render block _before_ format change that requires new block:
            if (textBlock!="") {
                // fix format lengths to match up. each format stops where
                // the next one starts. formatting that is carried over is set
                // again for the new format.
                for (int i=0; i<formats.size(); i++) {
                    int nextStart;
                    if (i<formats.size()-1) {
                        nextStart = formats[i+1].start;
                    }
                    else {
                        nextStart = textBlock.length();
                    }
                    formats[i].length = nextStart - formats[i].start;
                }

                if (target==RichText) {
                    richText += getRichTextForBlock(
                                   textBlock, formats);
                }

                if (target==PainterPaths) {
                    double horizontalAdvance = 0.0;
                    double horizontalAdvanceNoSpacing = 0.0;
                    double ascent = 0.0;
                    double descent = 0.0;
                    QList<RPainterPath> paths;

                    // get painter paths for current text block at height 1.0:
                    paths = getPainterPathsForBlock(
                                textBlock, formats,
                                horizontalAdvance,
                                horizontalAdvanceNoSpacing,
                                ascent, descent);

                    // transform to scale text from 1.0 to current text height:
                    QTransform sizeTransform;
                    sizeTransform.scale(blockHeight.top(), blockHeight.top());

                    // transform for current block due to xCursor position:
                    QTransform blockTransform;
                    blockTransform.translate(xCursor, 0);

                    // combine transforms for current text block:
                    QTransform allTransforms = sizeTransform;
                    allTransforms *= blockTransform;

                    maxAscent = qMax(maxAscent, ascent * blockHeight.top());
                    minDescent = qMin(minDescent, descent * blockHeight.top());

                    // transform paths of current block and append to paths
                    // of current text line:
                    for (int i=0; i<paths.size(); ++i) {
                        RPainterPath p = paths.at(i);
                        p.transform(allTransforms);
                        linePaths.append(p);
                    }

                    xCursor += horizontalAdvance * blockHeight.top();
                }
            }

            // empty text, might be line feed, we need ascent, descent anyway:
            else if (lineFeed || paragraphFeed || end) {
                if (target==PainterPaths) {
                    double horizontalAdvance = 0.0;
                    double horizontalAdvanceNoSpacing = 0.0;
                    double ascent = 0.0;
                    double descent = 0.0;

                    // get painter paths for current text block at height 1.0:
                    getPainterPathsForBlock(
                                "A", QList<QTextLayout::FormatRange>(),
                                horizontalAdvance,
                                horizontalAdvanceNoSpacing,
                                ascent, descent);

                    maxAscent = qMax(maxAscent, ascent * blockHeight.top());
                    minDescent = qMin(minDescent, descent * blockHeight.top());
                }
            }

            // handle stacked text:
            if (stackedText) {
                QRegExp reg;
                reg.setPattern(rxStackedText);
                reg.exactMatch(formatting);

                if (target==PainterPaths) {
                    double horizontalAdvance[2];
                    horizontalAdvance[0] = 0.0;
                    horizontalAdvance[1] = 0.0;
                    double horizontalAdvanceNoSpacing[2];
                    horizontalAdvanceNoSpacing[0] = 0.0;
                    horizontalAdvanceNoSpacing[1] = 0.0;
                    double heightFactor = 0.4;

                    // s==0: superscript, s==1: subscript:
                    for (int s=0; s<=1; ++s) {
                        QString script = reg.cap(s+1);

                        QList<RPainterPath> paths;

                        double ascent = 0.0;
                        double descent = 0.0;

                        QList<QTextLayout::FormatRange> localFormats;

                        QTextLayout::FormatRange fr;
                        fr.start = 0;
                        fr.length = script.length();
                        fr.format = currentFormat.top();
                        localFormats.append(fr);

                        // get painter paths for superscript at height 1.0:
                        paths = getPainterPathsForBlock(
                                    script, localFormats,
                                    horizontalAdvance[s],
                                    horizontalAdvanceNoSpacing[s],
                                    ascent, descent);

                        if (s==0) {
                            maxAscent = qMax(maxAscent, ascent * blockHeight.top() * heightFactor + blockHeight.top()*(1.0-heightFactor));
                        }
                        else {
                            minDescent = qMin(minDescent, descent * blockHeight.top() * heightFactor);
                        }

                        // transform to scale text from 1.0 to current text height * 0.4:
                        QTransform sizeTransform;
                        sizeTransform.scale(blockHeight.top()*heightFactor, blockHeight.top()*heightFactor);

                        // move top text more to the right for italic texts:
                        double xOffset = 0.0;
                        if (s==0 && blockItalic.top()==true) {
                            double y = blockHeight.top()*(1.0-heightFactor);
                            // assume italic means roughly 12 degrees:
                            xOffset = tan(RMath::deg2rad(12)) * y;
                        }

                        // transform for current block due to xCursor position
                        // and top or bottom text position:
                        QTransform blockTransform;
                        blockTransform.translate(xCursor + xOffset,
                                                 s==0 ? blockHeight.top()*(1.0-heightFactor) : 0.0);

                        horizontalAdvance[s] += xOffset / (blockHeight.top() * heightFactor);

                        // combine transforms for current text block:
                        QTransform allTransforms = sizeTransform;
                        allTransforms *= blockTransform;

                        // transform paths of current block and append to paths
                        // of current text line:
                        for (int i=0; i<paths.size(); ++i) {
                            RPainterPath p = paths.at(i);
                            p.transform(allTransforms);
                            linePaths.append(p);
                        }
                    }

                    xCursor += qMax(horizontalAdvance[0], horizontalAdvance[1]) * blockHeight.top() * heightFactor;
                }

                if (target==RichText) {
                    QString super = reg.cap(1);
                    QString sub = reg.cap(2);
                    if (!super.isEmpty()) {
                        richText += QString("<span style=\"vertical-align:super;\">%1</span>").arg(super);
                    }
                    if (!sub.isEmpty()) {
                        richText += QString("<span style=\"vertical-align:sub;\">%1</span>").arg(sub);
                    }
                }
            }

            // prepare for next text block:
            if (lineFeed || paragraphFeed || end) {
                if (!textBlock.isEmpty()) {
                    if (textBlock.at(textBlock.length()-1).isSpace()) {
                        trailingSpaces = true;
                    }
                }
//                else {
//                    if (formatting=="\\~") {
//                        trailingSpaces = true;
//                    }
//                }
            }

            textBlock = "";
            formats.clear();
            QTextLayout::FormatRange fr;
            fr.start = 0;
            fr.length = 0;
            fr.format = currentFormat.top();
            formats.append(fr);

            // handle text line.
            // add all painter paths of the current line to result set of
            // painter paths. apply line feed transformations.
            if (lineFeed || paragraphFeed || end) {
//                qDebug() << "lineFeed: adding text line:";
//                qDebug() << "  maxAscent: " << maxAscent;
//                qDebug() << "  minDescent: " << minDescent;
//                qDebug() << "  minDescentPrevious: " << minDescentPrevious;
//                qDebug() << "got line feed or end";
//                qDebug() << "  trailingSpaces: " << trailingSpaces;

                if (target==RichText) {
                    if (lineFeed || paragraphFeed) {
                        richText += "<br/>";
                    }
                }

                if (lineCounter!=0) {
                    yCursor += (minDescentPrevious - maxAscent) * lineSpacingFactor;
                }

                // calculate line bounding box for alignment without spaces at borders:
                RBox lineBoundingBox;
                for (int i=0; i<linePaths.size(); ++i) {
                    RPainterPath p = linePaths.at(i);
                    lineBoundingBox.growToInclude(p.getBoundingBox());
                }

                double featureSize = lineBoundingBox.getHeight();

                QTransform lineTransform;

                switch (horizontalAlignment) {
                case RS::HAlignAlign:
                case RS::HAlignFit:
                case RS::HAlignLeft:
                    if (!leadingSpaces) {
                        // move completely to the left (left border is 0.0):
                        lineTransform.translate(
                                    -lineBoundingBox.getMinimum().x,
                                    yCursor);
                    }
                    else {
                        lineTransform.translate(0, yCursor);
                    }
                    break;
                case RS::HAlignMid:
                case RS::HAlignCenter:
                    if (!leadingSpaces && !trailingSpaces) {
                        lineTransform.translate(
                                    -(lineBoundingBox.getMinimum().x +
                                      lineBoundingBox.getMaximum().x)/2.0,
                                    yCursor);
                    }
                    else {
                        lineTransform.translate(-xCursor/2.0, yCursor);
                    }
                    break;
                case RS::HAlignRight:
                    if (!trailingSpaces) {
                        lineTransform.translate(-lineBoundingBox.getMaximum().x, yCursor);
                    }
                    else {
                        lineTransform.translate(-xCursor, yCursor);
                    }
                    break;
                }

                width = qMax(width, lineBoundingBox.getMaximum().x - qMin(0.0, lineBoundingBox.getMinimum().x));

                // add current text line to result set:
                QPen pen;
                for (int i=0; i<linePaths.size(); ++i) {
                    RPainterPath p = linePaths[i];
                    if (i==0) {
                        pen = p.getPen();
                        if (pen.style()==Qt::NoPen) {
                           pen = QPen(p.getBrush().color());
                        }
                    }
                    p.transform(lineTransform);
                    p.setFeatureSize(featureSize);
                    painterPaths.append(p);
                    boundingBox.growToInclude(p.getBoundingBox());
                }

                RPainterPath bbPath;
                bbPath.addBox(lineBoundingBox);
                bbPath.transform(lineTransform);
                bbPath.setFeatureSize(-featureSize);
                bbPath.setPen(pen);
                painterPaths.append(bbPath);

                lineCounter++;
                xCursor = 0.0;
                maxAscent = 0.0;
                minDescentPrevious = minDescent;
                minDescent = 0.0;
                linePaths.clear();
                firstBlockInLine = true;
                leadingSpaces = false;
                trailingSpaces = false;
            }
        }

        // handle formatting after text block, that applies either
        // to the next text block(s) or the rest of the current text block:
        if (formatting.isEmpty()) {
            continue;
        }

        QRegExp reg;

        // unicode:
        reg.setPattern(rxUnicode);
        if (reg.exactMatch(formatting)) {
            textBlock += QChar(reg.cap(1).toInt(0, 16));
            continue;
        }

        // curly braket open:
        reg.setPattern(rxCurlyOpen);
        if (reg.exactMatch(formatting)) {
            textBlock += "{";
            continue;
        }

        // curly braket close:
        reg.setPattern(rxCurlyClose);
        if (reg.exactMatch(formatting)) {
            textBlock += "}";
            continue;
        }

        // degree:
        reg.setPattern(rxDegree);
        if (reg.exactMatch(formatting)) {
            textBlock += chDegree;
            continue;
        }

        // plus/minus:
        reg.setPattern(rxPlusMinus);
        if (reg.exactMatch(formatting)) {
            textBlock += chPlusMinus;
            continue;
        }

        // diameter:
        reg.setPattern(rxDiameter);
        if (reg.exactMatch(formatting)) {
            textBlock += chDiameter;
            continue;
        }

        // backslash:
        reg.setPattern(rxBackslash);
        if (reg.exactMatch(formatting)) {
            textBlock += "\\";
            continue;
        }

        // non-breaking space:
        reg.setPattern(rxNonBreakingSpace);
        if (reg.exactMatch(formatting)) {
            if (target==PainterPaths) {
                textBlock += QChar(Qt::Key_nobreakspace);
            }
            if (target==RichText) {
                textBlock += "&nbsp;";
            }
            continue;
        }

        // font change (TTF):
        reg.setPattern(rxFontChangeTtf);
        if (reg.exactMatch(formatting)) {
            blockFont.top() = reg.cap(1);
            blockBold.top() = (reg.cap(2).toInt()!=0);
            blockItalic.top() = (reg.cap(3).toInt()!=0);
            useCadFont.top() = false;
            blockChangedHeightOrFont = true;

            if (target==RichText) {
                QString style;
                style += QString("font-family:%1;").arg(blockFont.top());
                style += QString("font-weight:%1;").arg(blockBold.top() ? "bold" : "normal");
                style += QString("font-style:%1;").arg(blockItalic.top() ? "italic" : "normal");
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        // font change (CAD):
        reg.setPattern(rxFontChangeCad);
        if (reg.exactMatch(formatting)) {
            blockFont.top() = reg.cap(1);
            useCadFont.top() = true;
            if (xCursor>RS::PointTolerance) {
                RFont* f = RFontList::get(blockFont.top());
                if (f!=NULL && f->isValid()) {
                    xCursor += f->getLetterSpacing() / 9.0;
                }
            }
            blockChangedHeightOrFont = true;

            if (target==RichText) {
                QString style;
                style += QString("font-family:%1;").arg(blockFont.top());
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        // height change:
        reg.setPattern(rxHeightChange);
        if (reg.exactMatch(formatting)) {
            bool factor = reg.cap(2)=="x";

            if (factor) {
                blockHeight.top() *= reg.cap(1).toDouble();
            }
            else {
                blockHeight.top() = reg.cap(1).toDouble();
            }
            blockChangedHeightOrFont = true;

            if (target==RichText) {
                QString style;
                style += QString("font-size:%1pt;").arg(blockHeight.top() * fontHeightFactor);
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        QTextLayout::FormatRange fr;
        fr.start = textBlock.length();
        fr.length = 0;

        // start format block:
        reg.setPattern(rxBeginBlock);
        if (reg.exactMatch(formatting)) {
            currentFormat.push(currentFormat.top());
            blockFont.push(blockFont.top());
            blockBold.push(blockBold.top());
            blockItalic.push(blockItalic.top());
            blockHeight.push(blockHeight.top());
            useCadFont.push(useCadFont.top());
            if (target==RichText) {
                openTags.push(QStringList());
            }
            blockChangedHeightOrFont = false;
            continue;
        }

        // end format block:
        reg.setPattern(rxEndBlock);
        if (reg.exactMatch(formatting)) {
            currentFormat.pop();
            fr.format = currentFormat.top();
            formats.append(fr);
            blockFont.pop();
            blockBold.pop();
            blockItalic.pop();
            blockHeight.pop();
            useCadFont.pop();
            blockChangedHeightOrFont = false;

            if (target==RichText) {
                // close all tags that were opened in this block:
                for (int i=openTags.top().size()-1; i>=0; --i) {
                    QString tag = openTags.top().at(i);
                    richText += QString("</%1>").arg(tag);
                }
                openTags.pop();
            }

            continue;
        }

        // color change (indexed):
        reg.setPattern(rxColorChangeIndex);
        if (reg.exactMatch(formatting)) {
            RColor blockColor = RColor::createFromCadIndex(reg.cap(1));
            if (blockColor.isByLayer()) {
                currentFormat.top().setForeground(RColor::CompatByLayer);
            } else if (blockColor.isByBlock()) {
                currentFormat.top().setForeground(RColor::CompatByBlock);
            }
            else {
                currentFormat.top().setForeground(blockColor);
            }
            fr.format = currentFormat.top();
            formats.append(fr);

            if (target==RichText) {
                QString style;
                style += QString("color:%1;").arg(blockColor.name());
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }

        // color change (custom):
        reg.setPattern(rxColorChangeCustom);
        if (reg.exactMatch(formatting)) {
            RColor blockColor = RColor::createFromCadCustom(reg.cap(1));
            currentFormat.top().setForeground(blockColor);
            fr.format = currentFormat.top();
            formats.append(fr);

            if (target==RichText) {
                QString style;
                style += QString("color:%1;").arg(blockColor.name());
                richText += QString("<span style=\"%1\">").arg(style);
                openTags.top().append("span");
            }
            continue;
        }
    }

    if (target==PainterPaths) {
        // at this point, the text is at 0/0 with the base line of the
        // first text line at y==0

        // vertical alignment:
        double topLine = qMax(textHeight, boundingBox.getMaximum().y);
        double bottomLine = qMin(0.0, boundingBox.getMinimum().y);

        QTransform globalTransform;
        globalTransform.translate(position.x, position.y);
        globalTransform.rotate(RMath::rad2deg(angle));
        switch (verticalAlignment) {
        case RS::VAlignTop:
            //if (!leadingEmptyLines) {
                globalTransform.translate(0.0, -topLine);
            //}
            break;
        case RS::VAlignMiddle:
            if (leadingEmptyLines || trailingEmptyLines) {
                globalTransform.translate(0.0, -(yCursor+textHeight)/2.0);
            }
            else {
                globalTransform.translate(0.0, -(bottomLine + topLine) / 2.0);
            }
            break;
        case RS::VAlignBottom:
        case RS::VAlignBase:
            if (trailingEmptyLines) {
                globalTransform.translate(0.0, -yCursor);
            }
            else {
                globalTransform.translate(0.0, -bottomLine);
            }
            break;
        }

        height = boundingBox.getHeight();

        // apply global transform for position, angle and vertical alignment:
        boundingBox = RBox();
        for (int i=0; i<painterPaths.size(); ++i) {
            painterPaths[i].transform(globalTransform);
            boundingBox.growToInclude(painterPaths[i].getBoundingBox());
        }
    }

    if (target==RichText) {
        // close all tags that were opened:
        for (int i=openTags.top().size()-1; i>=0; --i) {
            QString tag = openTags.top().at(i);
            richText += QString("</%1>").arg(tag);
        }
    }
}
Example #28
0
void
BigFirehoseDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    painter->save();
    
    QColor bg;
    if (index.data( moose::CumulativeCountRole ).toInt() % 2 != index.row() % 2)
    {
        bg = option.palette.color( QPalette::AlternateBase );
        painter->fillRect( option.rect, bg );
    }
    else
        bg = option.palette.color( QPalette::Base );
    
    QTransform t;
    QPoint p = option.rect.topLeft();
    t.translate( p.x(), p.y() );
    painter->setTransform( t );
    
    const int S = painter->fontMetrics().lineSpacing();

    QColor const primary = Qt::black;
    QColor const secondary = QColor(AGING_MOOSE);

    QPixmap px = index.data( Qt::DecorationRole ).value<QPixmap>();
    const int n = option.rect.height() - 20;
    px = fitInSquare( px, n );
    painter->drawPixmap( 10, 10, px );
    painter->setPen( secondary );
    painter->setBrush( Qt::NoBrush );
    painter->drawRect( 10, 10, n, n );

    // keep text within the rects we drew
    QRect r( 5, 5, option.rect.width() - 10, option.rect.height() - 10 );
    //painter->setClipRect( r );

    painter->drawText( m_metric, 5 + S + 2 + S, index.data( moose::SecondaryDisplayRole ).toString() );

    QFont f = painter->font();
    f.setBold( true );
    painter->setFont( f );
    painter->setPen( primary );
    painter->drawText( m_metric, 5 + S, index.data().toString() );

    QString const small = index.data( moose::SmallDisplayRole ).toString();
    if (small.size())
    {
        int const h = painter->fontMetrics().height();
        int const w_name = painter->fontMetrics().width( index.data().toString() );

        f.setPointSize( 8 );
        f.setBold( false );
        painter->setFont( f );
        int const w = painter->fontMetrics().width( small );

        QRect const r_text_bounds( option.rect.width() - 5 - w, 10, w, h );
        QRect const r_text = r_text_bounds.adjusted( -5, 0, 0, 0 );
        QRect r_g = r_text;
        r_g.translate( -10, 0 );
        r_g.setWidth( 10 );

        if (m_metric + w_name > r_text.left())
        {
            QLinearGradient g( r_g.topLeft(), r_g.topRight() );
            g.setColorAt( 0, Qt::transparent );
            g.setColorAt( 1, bg );
            
            painter->fillRect( r_text, bg );
            painter->fillRect( r_g, g );  
        }
        
        painter->setPen( secondary );
        painter->drawText( r_text_bounds, Qt::AlignVCenter | Qt::AlignRight, small );
    }

    QRect r3( option.rect.right() - 14, 5 + S + 2, 15, 2*S );
    QLinearGradient g( r3.topLeft(), r3.topRight() );
    g.setColorAt( 0, Qt::transparent );
    g.setColorAt( 0.9, bg );
    painter->fillRect( r3, g );

    painter->restore();
}
Example #29
0
// motif arrows look the same whether they are used or not
// is this correct?
static void qDrawMotifArrow(QPainter *p, Qt::ArrowType type, bool down,
                             int x, int y, int w, int h,
                             const QPalette &pal, bool)
{
    QPolygon bFill;                                // fill polygon
    QPolygon bTop;                                // top shadow.
    QPolygon bBot;                                // bottom shadow.
    QPolygon bLeft;                                // left shadow.
    QTransform matrix;                            // xform matrix
    bool vertical = type == Qt::UpArrow || type == Qt::DownArrow;
    bool horizontal = !vertical;
    int         dim = w < h ? w : h;
    int         colspec = 0x0000;                        // color specification array

    if (dim < 2)                                // too small arrow
        return;

    if (dim > 3) {
        if (dim > 6)
            bFill.resize(dim & 1 ? 3 : 4);
        bTop.resize((dim/2)*2);
        bBot.resize(dim & 1 ? dim + 1 : dim);
        bLeft.resize(dim > 4 ? 4 : 2);
        bLeft.putPoints(0, 2, 0,0, 0,dim-1);
        if (dim > 4)
            bLeft.putPoints(2, 2, 1,2, 1,dim-3);
        bTop.putPoints(0, 4, 1,0, 1,1, 2,1, 3,1);
        bBot.putPoints(0, 4, 1,dim-1, 1,dim-2, 2,dim-2, 3,dim-2);

        for(int i=0; i<dim/2-2 ; i++) {
            bTop.putPoints(i*2+4, 2, 2+i*2,2+i, 5+i*2, 2+i);
            bBot.putPoints(i*2+4, 2, 2+i*2,dim-3-i, 5+i*2,dim-3-i);
        }
        if (dim & 1)                                // odd number size: extra line
            bBot.putPoints(dim-1, 2, dim-3,dim/2, dim-1,dim/2);
        if (dim > 6) {                        // dim>6: must fill interior
            bFill.putPoints(0, 2, 1,dim-3, 1,2);
            if (dim & 1)                        // if size is an odd number
                bFill.setPoint(2, dim - 3, dim / 2);
            else
                bFill.putPoints(2, 2, dim-4,dim/2-1, dim-4,dim/2);
        }
    }
    else {
        if (dim == 3) {                        // 3x3 arrow pattern
            bLeft.setPoints(4, 0,0, 0,2, 1,1, 1,1);
            bTop .setPoints(2, 1,0, 1,0);
            bBot .setPoints(2, 1,2, 2,1);
        }
        else {                                        // 2x2 arrow pattern
            bLeft.setPoints(2, 0,0, 0,1);
            bTop .setPoints(2, 1,0, 1,0);
            bBot .setPoints(2, 1,1, 1,1);
        }
    }

    if (type == Qt::UpArrow || type == Qt::LeftArrow) {
        matrix.translate(x, y);
        if (vertical) {
            matrix.translate(0, h - 1);
            matrix.rotate(-90);
        } else {
            matrix.translate(w - 1, h - 1);
            matrix.rotate(180);
        }
        if (down)
            colspec = horizontal ? 0x2334 : 0x2343;
        else
            colspec = horizontal ? 0x1443 : 0x1434;
    }
    else if (type == Qt::DownArrow || type == Qt::RightArrow) {
        matrix.translate(x, y);
        if (vertical) {
            matrix.translate(w-1, 0);
            matrix.rotate(90);
        }
        if (down)
            colspec = horizontal ? 0x2443 : 0x2434;
        else
            colspec = horizontal ? 0x1334 : 0x1343;
    }

    const QColor *cols[5];
    cols[0] = 0;
    cols[1] = &pal.button().color();
    cols[2] = &pal.mid().color();
    cols[3] = &pal.light().color();
    cols[4] = &pal.dark().color();
#define CMID        *cols[(colspec>>12) & 0xf]
#define CLEFT        *cols[(colspec>>8) & 0xf]
#define CTOP        *cols[(colspec>>4) & 0xf]
#define CBOT        *cols[colspec & 0xf]

    QPen     savePen   = p->pen();                // save current pen
    QBrush   saveBrush = p->brush();                // save current brush
    QTransform wxm = p->transform();
    QPen     pen(Qt::NoPen);
    const QBrush &brush = pal.brush(QPalette::Button);

    p->setPen(pen);
    p->setBrush(brush);
    p->setTransform(matrix, true);                // set transformation matrix
    p->drawPolygon(bFill);                        // fill arrow
    p->setBrush(Qt::NoBrush);                        // don't fill

    p->setPen(CLEFT);
    p->drawLines(bLeft);
    p->setPen(CTOP);
    p->drawLines(bTop);
    p->setPen(CBOT);
    p->drawLines(bBot);

    p->setTransform(wxm);
    p->setBrush(saveBrush);                        // restore brush
    p->setPen(savePen);                        // restore pen

#undef CMID
#undef CLEFT
#undef CTOP
#undef CBOT
}
void QgsComposerItem::changeItemRectangle( const QPointF& currentPosition,
    const QPointF& mouseMoveStartPos,
    const QGraphicsRectItem* originalItem,
    double dx, double dy,
    QGraphicsRectItem* changeItem )
{
  Q_UNUSED( dx );
  Q_UNUSED( dy );
  if ( !changeItem || !originalItem || !mComposition )
  {
    return;
  }

  //test if change item is a composer item. If so, prefer call to  setSceneRect() instead of setTransform() and setRect()
  QgsComposerItem* changeComposerItem = dynamic_cast<QgsComposerItem *>( changeItem );

  double mx = 0.0, my = 0.0, rx = 0.0, ry = 0.0;
  QPointF snappedPosition = mComposition->snapPointToGrid( currentPosition );

  //snap to grid and align to other items
  if ( mComposition->alignmentSnap() && mCurrentMouseMoveAction != QgsComposerItem::MoveItem )
  {
    double alignX = 0;
    double alignY = 0;
    snappedPosition = mComposition->alignPos( snappedPosition, dynamic_cast<const QgsComposerItem*>( originalItem ), alignX, alignY );
    if ( alignX != -1 )
    {
      QGraphicsLineItem* item = hAlignSnapItem();
      item->setLine( QLineF( alignX, 0, alignX,  mComposition->paperHeight() ) );
      item->show();
    }
    else
    {
      deleteHAlignSnapItem();
    }

    if ( alignY != -1 )
    {
      QGraphicsLineItem* item = vAlignSnapItem();
      item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
      item->show();
    }
    else
    {
      deleteVAlignSnapItem();
    }
  }

  double diffX = 0;
  double diffY = 0;

  switch ( mCurrentMouseMoveAction )
  {
      //vertical resize
    case QgsComposerItem::ResizeUp:
      diffY = snappedPosition.y() - originalItem->transform().dy();
      mx = 0; my = diffY; rx = 0; ry = -diffY;
      break;

    case QgsComposerItem::ResizeDown:
      diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
      mx = 0; my = 0; rx = 0; ry = diffY;
      break;

      //horizontal resize
    case QgsComposerItem::ResizeLeft:
      diffX = snappedPosition.x() - originalItem->transform().dx();
      mx = diffX, my = 0; rx = -diffX; ry = 0;
      break;

    case QgsComposerItem::ResizeRight:
      diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
      mx = 0; my = 0; rx = diffX, ry = 0;
      break;

      //diagonal resize
    case QgsComposerItem::ResizeLeftUp:
      diffX = snappedPosition.x() - originalItem->transform().dx();
      diffY = snappedPosition.y() - originalItem->transform().dy();
      mx = diffX, my = diffY; rx = -diffX; ry = -diffY;
      break;

    case QgsComposerItem::ResizeRightDown:
      diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
      diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
      mx = 0; my = 0; rx = diffX, ry = diffY;
      break;

    case QgsComposerItem::ResizeRightUp:
      diffX = snappedPosition.x() - ( originalItem->transform().dx() + originalItem->rect().width() );
      diffY = snappedPosition.y() - originalItem->transform().dy();
      mx = 0; my = diffY, rx = diffX, ry = -diffY;
      break;

    case QgsComposerItem::ResizeLeftDown:
      diffX = snappedPosition.x() - originalItem->transform().dx();
      diffY = snappedPosition.y() - ( originalItem->transform().dy() + originalItem->rect().height() );
      mx = diffX, my = 0; rx = -diffX; ry = diffY;
      break;

    case QgsComposerItem::MoveItem:
    {
      //calculate total move difference
      double moveX = currentPosition.x() - mouseMoveStartPos.x();
      double moveY = currentPosition.y() - mouseMoveStartPos.y();

      QPointF upperLeftPoint( originalItem->transform().dx() + moveX, originalItem->transform().dy() + moveY );
      QPointF snappedLeftPoint = mComposition->snapPointToGrid( upperLeftPoint );

      if ( snappedLeftPoint != upperLeftPoint ) //don't do align snap if grid snap has been done
      {
        deleteAlignItems();
      }
      else if ( mComposition->alignmentSnap() ) //align item
      {
        double alignX = 0;
        double alignY = 0;
        snappedLeftPoint = mComposition->alignItem( dynamic_cast<const QgsComposerItem*>( originalItem ), alignX, alignY, moveX, moveY );
        if ( alignX != -1 )
        {
          QGraphicsLineItem* item = hAlignSnapItem();
          int numPages = mComposition->numPages();
          double yLineCoord = 300; //default in case there is no single page
          if ( numPages > 0 )
          {
            yLineCoord = mComposition->paperHeight() * numPages + mComposition->spaceBetweenPages() * ( numPages - 1 );
          }
          item->setLine( QLineF( alignX, 0, alignX,  yLineCoord ) );
          item->show();
        }
        else
        {
          deleteHAlignSnapItem();
        }
        if ( alignY != -1 )
        {
          QGraphicsLineItem* item = vAlignSnapItem();
          item->setLine( QLineF( 0, alignY, mComposition->paperWidth(), alignY ) );
          item->show();
        }
        else
        {
          deleteVAlignSnapItem();
        }
      }
      double moveRectX = snappedLeftPoint.x() - originalItem->transform().dx();
      double moveRectY = snappedLeftPoint.y() - originalItem->transform().dy();

      if ( !changeComposerItem )
      {
        QTransform moveTransform;
        moveTransform.translate( originalItem->transform().dx() + moveRectX, originalItem->transform().dy() + moveRectY );
        changeItem->setTransform( moveTransform );
      }
      else  //for composer items, we prefer setSceneRect as subclasses can implement custom behaviour (e.g. item group)
      {
        changeComposerItem->setSceneRect( QRectF( originalItem->transform().dx() + moveRectX,
                                          originalItem->transform().dy() + moveRectY,
                                          originalItem->rect().width(), originalItem->rect().height() ) );
        changeComposerItem->updateItem();
      }
    }
    return;
    case QgsComposerItem::NoAction:
      break;
  }

  if ( !changeComposerItem )
  {
    QTransform itemTransform;
    itemTransform.translate( originalItem->transform().dx() + mx, originalItem->transform().dy() + my );
    changeItem->setTransform( itemTransform );
    QRectF itemRect( 0, 0, originalItem->rect().width() + rx,  originalItem->rect().height() + ry );
    changeItem->setRect( itemRect );
  }
  else //for composer items, we prefer setSceneRect as subclasses can implement custom behaviour (e.g. item group)
  {
    changeComposerItem->setSceneRect( QRectF( originalItem->transform().dx() + mx, originalItem->transform().dy() + my,
                                      originalItem->rect().width() + rx, originalItem->rect().height() + ry ) );
    changeComposerItem->updateItem();
  }
}