Ejemplo n.º 1
0
void tst_QPainterPath::angleAtPercent()
{
    for (int angle = 0; angle < 360; ++angle) {
        QLineF line = QLineF::fromPolar(100, angle);
        QPainterPath path;
        path.moveTo(line.p1());
        path.lineTo(line.p2());

        QCOMPARE(path.angleAtPercent(0.5), line.angle());
    }
}
Ejemplo n.º 2
0
void PrimitivePainter::drawLabel(QPainterPath* R, QPainter* thePainter, qreal PixelPerM, QString str, QString strBg) const
{
    if (!DrawLabel)
        return;

    if (str.isEmpty() && strBg.isEmpty())
        return;

    thePainter->save();
    if (getLabelArea()) {
        QPointF C(R->boundingRect().center());
        drawPointLabel(C, str, strBg, thePainter, PixelPerM);
        thePainter->restore();
        return;
    }

    LineParameters lp = labelBoundary();
    qreal WW = PixelPerM*lp.Proportional+lp.Fixed;
    if (WW < 10) return;
    //qreal WWR = qMax(PixelPerM*R->widthOf()*BackgroundScale+BackgroundOffset, PixelPerM*R->widthOf()*ForegroundScale+ForegroundOffset);

    QPainterPath textPath;
    QPainterPath tranformedRoadPath = *R;
    QFont font = getLabelFont();

    if (!str.isEmpty()) {
        QRegion rg = thePainter->clipRegion();
        font.setPixelSize(int(WW));
        QFontMetrics metrics(font);

        if (font.pixelSize() >= 5 && tranformedRoadPath.length() > metrics.width(str)) {
            thePainter->setFont(font);

            int repeat = int((tranformedRoadPath.length() / ((metrics.width(str) * LABEL_PATH_DISTANCE))) - 0.5);
            int numSegment = repeat+1;
            qreal lenSegment = tranformedRoadPath.length() / numSegment;
            qreal startSegment = 0;
            QPainterPath textPath;
            do {
                QRegion rg = thePainter->clipRegion();

                qreal curLen = startSegment + ((lenSegment - metrics.width(str)) / 2);
                int modIncrement = 1;
                qreal modAngle = 0;
                int modY = 0;
                if (cos(angToRad(tranformedRoadPath.angleAtPercent((startSegment+(lenSegment/2))/tranformedRoadPath.length()))) < 0) {
                    modIncrement = -1;
                    modAngle = 180.0;
                    curLen += metrics.width(str);
                }
                for (int i = 0; i < str.length(); ++i) {
                    qreal t = tranformedRoadPath.percentAtLength(curLen);
                    QPointF pt = tranformedRoadPath.pointAtPercent(t);
                    qreal angle = tranformedRoadPath.angleAtPercent(t);
                    modY = (metrics.ascent()/2)-3;

                    QMatrix m;
                    m.translate(pt.x(), pt.y());
                    m.rotate(-angle+modAngle);

                    QPainterPath charPath;
                    charPath.addText(0, modY, font, str.mid(i, 1));
                    charPath = charPath * m;

                    textPath.addPath(charPath);

                    qreal incremenet = metrics.width(str[i]);
                    curLen += (incremenet * modIncrement);
                }
                startSegment += lenSegment;
            } while (--repeat >= 0);

            if (getLabelHalo()) {
                thePainter->setPen(QPen(Qt::white, font.pixelSize()/6));
                thePainter->drawPath(textPath);
            }
            thePainter->setPen(Qt::NoPen);
            thePainter->setBrush(LabelColor);
            thePainter->drawPath(textPath);
            thePainter->setClipRegion(rg);
        }
    }
    if (DrawLabelBackground && !strBg.isEmpty()) {
        QRegion rg = thePainter->clipRegion();
        font.setPixelSize(int(WW));
        QFontMetrics metrics(font);

        int repeat = int((tranformedRoadPath.length() / (metrics.width(strBg) * LABEL_STRAIGHT_DISTANCE)) - 0.5);
        int numSegment = repeat+1;
        qreal lenSegment = tranformedRoadPath.length() / numSegment;
        qreal startSegment = 0;
        do {

            int modX = 0;
            int modY = 0;

            qreal curLen = startSegment + (lenSegment / 2);
            qreal t = tranformedRoadPath.percentAtLength(curLen);
            QPointF pt = tranformedRoadPath.pointAtPercent(t);

            modX = - (metrics.width(strBg)/2);
            //modX = WW;
            modY = (metrics.ascent()/2);

            QPainterPath textPath, bgPath;
            textPath.addText(modX, modY, font, strBg);
            bgPath.addRect(textPath.boundingRect().adjusted(-BG_SPACING, -BG_SPACING, BG_SPACING, BG_SPACING));

            bool rgContains = false;
            for (int i=0; i<rg.rects().size(); i++) {
                if (rg.rects()[i].contains(bgPath.boundingRect().toRect().translated(pt.toPoint()))) {
                    rgContains = true;
                    break;
                }
            }
            if (rgContains) {
                thePainter->translate(pt);

                thePainter->setPen(QPen(LabelColor, BG_PEN_SZ));
                thePainter->setBrush(LabelBackgroundColor);
                thePainter->drawPath(bgPath);

                if (getLabelHalo()) {
                    thePainter->setPen(QPen(Qt::white, font.pixelSize()/5));
                    thePainter->drawPath(textPath);
                }
                thePainter->setPen(Qt::NoPen);
                thePainter->setBrush(LabelColor);
                thePainter->drawPath(textPath);

                rg -= bgPath.boundingRect().toRect().translated(pt.toPoint());
            }

            startSegment += lenSegment;
        } while (--repeat >= 0);

        thePainter->setClipRegion(rg);
    }
    thePainter->restore();
}
Ejemplo n.º 3
0
qreal Geometry::tangentLineAt(QPainterPath const &path, QPointF const &point)
{
	qreal const percentage = percentageAt(path, point);
	return path.angleAtPercent(percentage);
}
Ejemplo n.º 4
0
void PageItem_PathText::DrawObj_Item(ScPainter *p, QRectF cullingArea)
{
	itemText.invalidateAll();
	firstChar = 0;
	MaxChars = 0;
	int a;
	double chs;
	QString chstr, chstr2, chstr3;
	ScText *hl;
	double dx;
	FPoint point = FPoint(0, 0);
	FPoint tangent = FPoint(0, 0);
	uint seg = 0;
	double segLen = 0;
	QColor tmp;
	CurX = Extra;
	QString cachedStroke = "";
	QString cachedFill = "";
	double cachedFillShade = -1;
	double cachedStrokeShade = -1;
	QString actStroke = "";
	QString actFill = "";
	double actFillShade = -1;
	double actStrokeShade = -1;
	QColor cachedFillQ;
	QColor cachedStrokeQ;
	if (!m_Doc->layerOutline(LayerID))
	{
		if (PoShow)
		{
			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();
					}
				}
			}
		}
	}
	double totalTextLen = 0.0;
	double totalCurveLen = 0.0;
	double extraOffset = 0.0;
	if (itemText.length() != 0)
	{
		CurX += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
		totalTextLen += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
	}
	segLen = PoLine.lenPathSeg(seg);
	for (a = firstChar; a < itemText.length(); ++a)
	{
		hl = itemText.item(a);
		chstr = hl->ch;
		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
			|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
			continue;
		if (a < itemText.length()-1)
			chstr += itemText.text(a+1, 1);
		hl->glyph.yadvance = 0;
		layoutGlyphs(itemText.charStyle(a), chstr, hl->glyph);
		hl->glyph.shrink();
		if (hl->ch == SpecialChars::OBJECT)
			totalTextLen += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH;
		else
			totalTextLen += hl->glyph.wide()+hl->fontSize() * hl->tracking() / 10000.0;
	}
	for (uint segs = 0; segs < PoLine.size()-3; segs += 4)
	{
		totalCurveLen += PoLine.lenPathSeg(segs);
	}
	if ((itemText.defaultStyle().alignment() != 0) && (totalCurveLen >= totalTextLen + Extra))
	{
		if (itemText.defaultStyle().alignment() == 2)
		{
			CurX = totalCurveLen  - totalTextLen;
			CurX -= Extra;
		}
		if (itemText.defaultStyle().alignment() == 1)
			CurX = (totalCurveLen - totalTextLen) / 2.0;
		if ((itemText.defaultStyle().alignment() == 3) || (itemText.defaultStyle().alignment() == 4))
			extraOffset = (totalCurveLen - Extra  - totalTextLen) / static_cast<double>(itemText.length());
	}
#ifndef NLS_PROTO
	QPainterPath guidePath = PoLine.toQPainterPath(false);
	QList<QPainterPath> pathList = decomposePath(guidePath);
	QPainterPath currPath = pathList[0];
	int currPathIndex = 0;
	for (a = firstChar; a < itemText.length(); ++a)
	{
		CurY = 0;
		hl = itemText.item(a);
		chstr = hl->ch;
		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
			|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
			continue;
		chs = hl->fontSize();
		if (a < itemText.length()-1)
			chstr += itemText.text(a+1, 1);
		hl->glyph.yadvance = 0;
		layoutGlyphs(itemText.charStyle(a), chstr, hl->glyph);
		hl->glyph.shrink();                                                           // HACK
		if (hl->ch == SpecialChars::OBJECT)
			dx = (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH / 2.0;
		else
			dx = hl->glyph.wide() / 2.0;
		CurX += dx;

		double currPerc = currPath.percentAtLength(CurX);
		if (currPerc >= 0.9999999)
		{
			currPathIndex++;
			if (currPathIndex == pathList.count())
			{
				MaxChars = a;
				break;
			}
			currPath = pathList[currPathIndex];
			CurX = dx;
			currPerc = currPath.percentAtLength(CurX);
		}
		double currAngle = currPath.angleAtPercent(currPerc);
#if QT_VERSION  >= 0x040400
		if (currAngle <= 180.0)
			currAngle *= -1.0;
		else
			currAngle = 360.0 - currAngle;
#endif
		QPointF currPoint = currPath.pointAtPercent(currPerc);
		tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0));
		point = FPoint(currPoint.x(), currPoint.y());
		hl->glyph.xoffset = 0;
		hl->PtransX = point.x();
		hl->PtransY = point.y();
		hl->PRot    = currAngle * M_PI / 180.0;
		hl->PDx     = dx;
		QTransform trafo = QTransform( 1, 0, 0, -1, -dx, 0 );
		if (textPathFlipped)
			trafo *= QTransform(1, 0, 0, -1, 0, 0);
		if (textPathType == 0)
			trafo *= QTransform( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x(), point.y() ); // ID's Rainbow mode
		else if (textPathType == 1)
			trafo *= QTransform( 1, 0, 0, -1, point.x(), point.y() ); // ID's Stair Step mode
		else if (textPathType == 2)
		{
			double a = 1;
			if (tangent.x() < 0)
				a = -1;
			if (fabs(tangent.x()) > 0.1)
				trafo *= QTransform( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x(), point.y() ); // ID's Skew mode
			else
				trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() );
		}
		QTransform sca = p->worldMatrix();
		trafo *= sca;
		p->save();
		QTransform savWM = p->worldMatrix();
		p->setWorldMatrix(trafo);
		if (!m_Doc->RePos)
		{
			actFill = itemText.charStyle(a).fillColor();
			actFillShade = itemText.charStyle(a).fillShade();
			if (actFill != CommonStrings::None)
			{
				p->setFillMode(ScPainter::Solid);
				if ((cachedFillShade != actFillShade) || (cachedFill != actFill))
				{
					SetQColor(&tmp, actFill, actFillShade);
					p->setBrush(tmp);
					cachedFillQ = tmp;
					cachedFill = actFill;
					cachedFillShade = actFillShade;
				}
				else
					p->setBrush(cachedFillQ);
			}
			else
				p->setFillMode(ScPainter::None);
			actStroke = itemText.charStyle(a).strokeColor();
			actStrokeShade = itemText.charStyle(a).strokeShade();
			if (actStroke != CommonStrings::None)
			{
				if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke))
				{
					SetQColor(&tmp, actStroke, actStrokeShade);
					p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
					cachedStrokeQ = tmp;
					cachedStroke = actStroke;
					cachedStrokeShade = actStrokeShade;
				}
				else
					p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
			}
			p->translate(0.0, BaseOffs);
			if (hl->ch == SpecialChars::OBJECT)
				DrawObj_Embedded(p, cullingArea, itemText.charStyle(a), hl->embedded.getItem());
			else
				drawGlyphs(p, itemText.charStyle(a), hl->glyph);
		}
		p->setWorldMatrix(savWM);
		p->restore();
		MaxChars = a+1;
		CurX -= dx;
		if (hl->ch == SpecialChars::OBJECT)
			CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH;
		else
			CurX += hl->glyph.wide()+hl->fontSize() * hl->tracking() / 10000.0 + extraOffset;
	}
#endif
}
Ejemplo n.º 5
0
//!
//! Updates the path end points according to the positions of start and end
//! nodes.
//!
void ConnectionGraphicsItem::updatePath ()
{
    prepareGeometryChange();

    // calculate positions of the end points
    QPointF startPoint = m_startPoint;
    QPointF endPoint = m_endPoint;
    if (m_startNodeItem)
        startPoint += m_startNodeItem->pos();
    if (m_endNodeItem)
        endPoint += m_endNodeItem->pos();

    // calculate the rectangles to help calculating the positions of the node's anchor points
    const qreal offset = 10;
    QRectF baseAnchorRect = QRectF(-offset, -offset, 2 * offset, 2 * offset);
    QRectF startAnchorRect = baseAnchorRect.translated(startPoint);
    QRectF endAnchorRect = baseAnchorRect.translated(endPoint);
    if (m_startNodeItem)
        startAnchorRect = m_startNodeItem->rect().adjusted(-offset, -offset, offset, offset).translated(m_startNodeItem->pos());
    if (m_endNodeItem)
        endAnchorRect = m_endNodeItem->rect().adjusted(-offset, -offset, offset, offset).translated(m_endNodeItem->pos());

    //
    // Diagram of anchor points for start and end nodes:
    //
    //    x        x      sU2, sU1     eU1, eU2      x        x
    //      ,----,                                     ,----,
    //      |    |                                     |    |
    //      |    |                                     |    |
    //      |   x| x      sP, sO         eO, eP      x |x   |
    //      '----'                                     '----'
    //    x        x      sL2, sL1     eL1, eL2      x        x
    //

    QPointF sP = startPoint;
    QPointF sO = QPointF(startAnchorRect.right(), startPoint.y());
    QPointF sU1 = startAnchorRect.topRight();
    QPointF sU2 = startAnchorRect.topLeft();
    QPointF sL1 = startAnchorRect.bottomRight();
    QPointF sL2 = startAnchorRect.bottomLeft();

    QPointF eP = endPoint;
    QPointF eO = QPointF(endAnchorRect.left(), endPoint.y());
    QPointF eU1 = endAnchorRect.topLeft();
    QPointF eU2 = endAnchorRect.topRight();
    QPointF eL1 = endAnchorRect.bottomLeft();
    QPointF eL2 = endAnchorRect.bottomRight();

    // declare path segments
    QList<QPointF> startPoints;
    QPainterPath cubicPath;
    QList<QPointF> endPoints;

    // construct the path segments
    if (eO.x() < sO.x() && eU2.x() > sL2.x() && eU2.y() < sL2.y() && eL2.y() > sU2.y()) {
        //> case 1V: elements very close to each other
        startPoints << sP << sO;

        QPointF offsetVector = QPointF(0, 0.75 * (eO.y() - sO.y()));
        cubicPath.moveTo(sO);
        cubicPath.cubicTo(sO + offsetVector, eO - offsetVector, eO);

        endPoints << eO << eP;
    } else if (eO.x() >= sO.x()) {
        //> case 1H: end node is right of start node
        startPoints << sP << sO;

        QPointF offsetVector = QPointF(0.75 * (eO.x() - sO.x()), 0);
        cubicPath.moveTo(sO);
        cubicPath.cubicTo(sO + offsetVector, eO - offsetVector, eO);

        endPoints << eO << eP;
    } else if (eU1.y() >= sL1.y()) {
        //> case 2LV
        startPoints << sP << sO << sL1;

        QPointF offsetVector = QPointF(0, 0.75 * (eU1.y() - sL1.y()));
        cubicPath.moveTo(sL1);
        cubicPath.cubicTo(sL1 + offsetVector, eU1 - offsetVector, eU1);

        endPoints << eU1 << eO << eP;
    } else if (eL1.y() <= sU1.y()) {
        //> case 2UV
        startPoints << sP << sO << sU1;

        QPointF offsetVector = QPointF(0, 0.75 * (eL1.y() - sU1.y()));
        cubicPath.moveTo(sU1);
        cubicPath.cubicTo(sU1 + offsetVector, eL1 - offsetVector, eL1);

        endPoints << eL1 << eO << eP;
    } else if (eP.y() >= sP.y()) {
        //> case 3L
        startPoints << sP << sO << sL1 << sL2;

        QPointF offsetVector = QPointF(0.75 * (eU2.x() - sL2.x()), 0);
        cubicPath.moveTo(sL2);
        cubicPath.cubicTo(sL2 + offsetVector, eU2 - offsetVector, eU2);

        endPoints << eU2 << eU1 << eO << eP;
    } else {
        //> case 3U
        startPoints << sP << sO << sU1 << sU2;

        QPointF offsetVector = QPointF(0.75 * (eL2.x() - sU2.x()), 0);
        cubicPath.moveTo(sU2);
        cubicPath.cubicTo(sU2 + offsetVector, eL2 - offsetVector, eL2);

        endPoints << eL2 << eL1 << eO << eP;
    }

    // build the main path from the path segments
    m_mainPath = QPainterPath();
    for (int i = 0; i < startPoints.size(); ++i)
        if (i == 0)
            m_mainPath.moveTo(startPoints[0]);
        else
            m_mainPath.lineTo(startPoints[i]);
    m_mainPath.addPath(cubicPath);
    for (int i = 0; i < endPoints.size(); ++i)
        if (i == 0)
            m_mainPath.moveTo(endPoints[0]);
        else
            m_mainPath.lineTo(endPoints[i]);

    // create the shadow path as a copy of the main path
    m_shadowPath = QPainterPath(m_mainPath);
    // move the path elements of the shadow path one pixel down and to the right
    for (int i = 1; i < m_shadowPath.elementCount(); ++i) {
        QPainterPath::Element element = m_shadowPath.elementAt(i);
        m_shadowPath.setElementPositionAt(i, element.x + 1, element.y + 1);
    }

    // get the center point for the arrow and the angle at that point
    static const qreal t = 0.5;
    QPointF arrowPoint = cubicPath.pointAtPercent(t);
    qreal angle = cubicPath.angleAtPercent(t) * Pi / 180;

    // calculate the polygon for the arrow head
    qreal pathLengthFraction = m_mainPath.length() / 10;
    static const qreal maxArrowSize = 10;
    qreal arrowSize = pathLengthFraction < maxArrowSize ? pathLengthFraction : maxArrowSize;
    QPointF arrowPoint1 = arrowPoint - QPointF(arrowSize * sin(angle - Pi / 2), arrowSize * cos(angle - Pi / 2));
    QPointF arrowPoint2 = arrowPoint - QPointF(arrowSize * sin(angle + Pi / 3), arrowSize * cos(angle + Pi / 3));
    QPointF arrowPoint3 = arrowPoint - QPointF(arrowSize * sin(angle + Pi - Pi / 3), arrowSize * cos(angle + Pi - Pi / 3));
    m_arrowHeadPolygon.clear();
    m_arrowHeadPolygon << arrowPoint1 << arrowPoint2 << arrowPoint3;

    // repaint the graphics item
    update();
}
Ejemplo n.º 6
0
void SCgAlphabet::paintPair(QPainter *painter, SCgPair *pair)
{
    Q_ASSERT(pair != 0);

    QVector<QPointF> points = pair->points();

    Q_ASSERT(points.size() > 1);

    static float arrowLength = 10.f;
    static float arrowWidth = LINE_FAT_WIDTH;

    if (pair->isOrient())
    {

        static const QPointF arrowPoints[3] = {QPointF(-arrowWidth / 2.f, 0.f),
                                               QPointF(arrowWidth / 2.f, 0.f),
                                               QPointF(0.f, arrowLength)};

        // draw arrow for orient pairs
        QLineF line(points[points.size() - 2], points.last());
        double angle = ::atan2(line.dx(), line.dy());

        painter->save();
        painter->translate(line.p2());
        painter->rotate(-angle * 180.f / M_PI);
        painter->translate(0.f, -arrowLength);

        painter->setBrush(QBrush(pair->color(), Qt::SolidPattern));
        painter->setPen(Qt::NoPen);
        painter->drawConvexPolygon(arrowPoints, 3);

        painter->restore();

        // correct last point
        points.last() -= QPointF((arrowLength) * ::sin(angle), (arrowLength) * ::cos(angle));
    }

    // get type data
    SCgPosType posType = pair->posType();
    SCgConstType constType = pair->constType();
    SCgPermType permType = pair->permType();

    painter->setBrush(Qt::NoBrush);

    QPen pen(pair->color());
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::RoundJoin);

    // draw all cases
    if (pair->isAccessory())
    {       
        pen.setWidthF(LINE_THIN_WIDTH);
        QPen markPen = pen;

        if (constType == ConstUnknown && posType == PosUnknown)
        {
            painter->setPen(pen);
            painter->drawPolyline(&(points[0]), points.size());

            markPen.setWidthF(LINE_COM_ACCESS_MARK_WIDTH);
            markPen.setDashPattern(msCommonAccessoryDashPattern);

            painter->setPen(markPen);
            painter->drawPolyline(&(points[0]), points.size());
        }else
        {

            if (permType == Permanent && constType == Var)
                pen.setDashPattern(msPermVarAccesDashPattern);

            if (permType == Temporary)
            {
                if (constType == Const)
                    pen.setDashPattern(msTempConstAccesDashPattern);
                else
                    pen.setDashPattern(msTempVarAccesDashPattern);
            }

            painter->setPen(pen);
            painter->drawPolyline(&(points[0]), points.size());

            // draw negative lines
            if (posType == Negative)
            {
                painter->setPen(markPen);

                QPainterPath path = pair->shapeNormal();
                float length = path.length() - arrowLength - 3;
                int i = 0;

                qreal mult = 28.f;
                qreal offset = 22.f;
                qreal l = offset;

                while (l < length)
                {
                    qreal perc = path.percentAtLength(l);

                    painter->save();
                    painter->translate(path.pointAtPercent(perc));
                    painter->rotate(-path.angleAtPercent(perc));
                    painter->drawLine(0.f, -LINE_MARK_NEG_LENGTH, 0.f, LINE_MARK_NEG_LENGTH);
                    painter->restore();

                    l = (++i) * mult + offset;
                }

            }else   // draw fuzzy lines
                if (posType == Fuzzy)
                {
                    painter->setPen(markPen);

                    QPainterPath path = pair->shapeNormal();
                    float length = path.length() - arrowLength - 3;
                    int i = 0;

                    qreal mult = 28.f;
                    qreal offset = 22.f;
                    qreal l = offset;

                    while (l < length)
                    {
                        qreal perc = path.percentAtLength(l);

                        painter->save();
                        painter->translate(path.pointAtPercent(perc));
                        painter->rotate(-path.angleAtPercent(perc));

                        if (i % 2 == 0)
                            painter->drawLine(0.f, -LINE_MARK_FUZ_LENGTH, 0.f, 0.f);
                        else
                            painter->drawLine(0.f, LINE_MARK_FUZ_LENGTH, 0.f, 0.f);
                        painter->restore();

                        l = (++i) * mult + offset;
                    }
                }
        }
    }else // draw binary pairs
    {
        pen.setWidthF(LINE_FAT_WIDTH);
        painter->setPen(pen);
        painter->drawPolyline(&(points[0]), points.size());

        if (constType == Var)
        {
            pen.setWidthF(LINE_FATIN_WIDTH);
            pen.setDashPattern(msPermVarNoAccesDashPattern);
            pen.setDashOffset(20);
            pen.setColor(QColor(255, 255, 255));
            painter->setPen(pen);
            painter->drawPolyline(&(points[0]), points.size());
        }else
        {
            pen.setWidthF(LINE_FATIN_WIDTH);
            pen.setColor(Qt::white);
            painter->setPen(pen);
            painter->drawPolyline(&(points[0]), points.size());

            if (constType == ConstUnknown)
            {
                pen.setWidthF(LINE_THIN_WIDTH);
                pen.setDashPattern(msPermVarAccesDashPattern);
                pen.setColor(pair->color());

                painter->setPen(pen);
                painter->drawPolyline(&(points[0]), points.size());
            }
        }
    }
}
Ejemplo n.º 7
0
void PageItem_PathText::DrawObj_Item(ScPainter *p, QRectF cullingArea)
{
	itemText.invalidateAll();
	firstChar = 0;
	MaxChars = 0;
	int a;
	QString chstr, chstr2, chstr3;
	double dx;
	FPoint point = FPoint(0, 0);
	FPoint tangent = FPoint(0, 0);
	QColor tmp;
	CurX = m_textDistanceMargins.left();
	QString cachedStroke = "";
	QString cachedFill = "";
	double cachedFillShade = -1;
	double cachedStrokeShade = -1;
	QString actStroke = "";
	QString actFill = "";
	double actFillShade = -1;
	double actStrokeShade = -1;
	QColor cachedFillQ;
	QColor cachedStrokeQ;
	if (!m_Doc->layerOutline(LayerID))
	{
		if (PoShow)
		{
			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();
					}
				}
			}
		}
	}
	double totalTextLen = 0.0;
	double totalCurveLen = 0.0;
	double extraOffset = 0.0;
	if (itemText.length() != 0)
	{
		CurX += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
		totalTextLen += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
	}
	itemRenderText.clear();
	itemRenderText.setDoc(m_Doc);
	itemRenderText.setDefaultStyle(itemText.defaultStyle());
	for (a = firstChar; a < itemText.length(); ++a)
	{
		CharStyle nstyle = itemText.charStyle(a);
		ParagraphStyle pstyle = itemText.paragraphStyle(a);
		chstr = itemText.text(a, 1);
		if ((chstr[0] == SpecialChars::OBJECT) && (itemText.hasObject(a)))
		{
			int pot = itemRenderText.length();
			itemRenderText.insertObject(pot, itemText.object(a)->inlineCharID);
		}
		else
		{
			if (!(chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK))
				chstr = ExpandToken(a);
			for (int cc = 0; cc < chstr.count(); cc++)
			{
				int pot = itemRenderText.length();
				itemRenderText.insertChars(pot, chstr.mid(cc, 1));
				itemRenderText.applyStyle(pot, pstyle);
				itemRenderText.applyCharStyle(pot, 1, nstyle);
			}
		}
		chstr.clear();
	}
	textLayout.setStory(&itemRenderText);
	int spaceCount = 0;
	double wordExtra = 0;
	for (a = firstChar; a < itemRenderText.length(); ++a)
	{
		GlyphLayout* glyphs = itemRenderText.getGlyphs(a);
		chstr = itemRenderText.text(a, 1);
		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
			|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
			continue;
		if (chstr[0] == SpecialChars::BLANK)
			spaceCount++;
		if (a < itemRenderText.length()-1)
			chstr += itemRenderText.text(a+1, 1);
		glyphs->yadvance = 0;
		layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a), *glyphs);
		glyphs->shrink();
		if (itemRenderText.hasObject(a))
			totalTextLen += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH;
		else
			totalTextLen += glyphs->wide()+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0;
	}
	for (int segs = 0; segs < PoLine.size()-3; segs += 4)
	{
		totalCurveLen += PoLine.lenPathSeg(segs);
	}
	if ((itemRenderText.paragraphStyle(0).alignment() != 0) && (totalCurveLen >= totalTextLen + m_textDistanceMargins.left()))
	{
		if (itemRenderText.paragraphStyle(0).alignment() == 2)
		{
			CurX = totalCurveLen  - totalTextLen;
			CurX -= m_textDistanceMargins.left();
		}
		if (itemRenderText.paragraphStyle(0).alignment() == 1)
			CurX = (totalCurveLen - totalTextLen) / 2.0;
		if (itemRenderText.paragraphStyle(0).alignment() == 3)
		{
			if (spaceCount != 0)
			{
				extraOffset = 0;
				wordExtra = (totalCurveLen - m_textDistanceMargins.left()  - totalTextLen) / static_cast<double>(spaceCount);
			}
			else
			{
				extraOffset = (totalCurveLen - m_textDistanceMargins.left()  - totalTextLen) / static_cast<double>(itemRenderText.length());
				wordExtra = 0;
			}
		}
		if (itemRenderText.paragraphStyle(0).alignment() == 4)
			extraOffset = (totalCurveLen - m_textDistanceMargins.left() - totalTextLen) / static_cast<double>(itemRenderText.length());
	}
	QPainterPath guidePath = PoLine.toQPainterPath(false);
	QList<QPainterPath> pathList = decomposePath(guidePath);
	QPainterPath currPath = pathList[0];
	int currPathIndex = 0;
	for (a = firstChar; a < itemRenderText.length(); ++a)
	{
		CurY = 0;
		GlyphLayout* glyphs = itemRenderText.getGlyphs(a);
		PathData* pdata = & (textLayout.point(a));
		chstr = itemRenderText.text(a,1);
		if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
			|| chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
			continue;
		if (a < itemRenderText.length()-1)
			chstr += itemRenderText.text(a+1, 1);
		glyphs->yadvance = 0;
		layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a), *glyphs);
		glyphs->shrink();                                                           // HACK
		if (itemRenderText.hasObject(a))
			dx = (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH / 2.0;
		else
			dx = glyphs->wide() / 2.0;
		CurX += dx;

		double currPerc = currPath.percentAtLength(CurX);
		if (currPerc >= 0.9999999)
		{
			currPathIndex++;
			if (currPathIndex == pathList.count())
			{
				MaxChars = a;
				break;
			}
			currPath = pathList[currPathIndex];
			CurX = dx;
			currPerc = currPath.percentAtLength(CurX);
		}
		double currAngle = currPath.angleAtPercent(currPerc);
		if (currAngle <= 180.0)
			currAngle *= -1.0;
		else
			currAngle = 360.0 - currAngle;
		QPointF currPoint = currPath.pointAtPercent(currPerc);
		tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0));
		point = FPoint(currPoint.x(), currPoint.y());
		glyphs->xoffset = 0;
		pdata->PtransX = point.x();
		pdata->PtransY = point.y();
		pdata->PRot    = currAngle * M_PI / 180.0;
		pdata->PDx     = dx;
		QTransform trafo = QTransform( 1, 0, 0, -1, -dx, 0 );
		if (textPathFlipped)
			trafo *= QTransform(1, 0, 0, -1, 0, 0);
		if (textPathType == 0)
			trafo *= QTransform( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x(), point.y() ); // ID's Rainbow mode
		else if (textPathType == 1)
			trafo *= QTransform( 1, 0, 0, -1, point.x(), point.y() ); // ID's Stair Step mode
		else if (textPathType == 2)
		{
			double a = 1;
			if (tangent.x() < 0)
				a = -1;
			if (fabs(tangent.x()) > 0.1)
				trafo *= QTransform( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x(), point.y() ); // ID's Skew mode
			else
				trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() );
		}
		QTransform sca = p->worldMatrix();
		trafo *= sca;
		p->save();
		QTransform savWM = p->worldMatrix();
		p->setWorldMatrix(trafo);
		if (!m_Doc->RePos)
		{
			actFill = itemRenderText.charStyle(a).fillColor();
			actFillShade = itemRenderText.charStyle(a).fillShade();
			if (actFill != CommonStrings::None)
			{
				p->setFillMode(ScPainter::Solid);
				if ((cachedFillShade != actFillShade) || (cachedFill != actFill))
				{
					SetQColor(&tmp, actFill, actFillShade);
					p->setBrush(tmp);
					cachedFillQ = tmp;
					cachedFill = actFill;
					cachedFillShade = actFillShade;
				}
				else
					p->setBrush(cachedFillQ);
			}
			else
				p->setFillMode(ScPainter::None);
			actStroke = itemRenderText.charStyle(a).strokeColor();
			actStrokeShade = itemRenderText.charStyle(a).strokeShade();
			if (actStroke != CommonStrings::None)
			{
				if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke))
				{
					SetQColor(&tmp, actStroke, actStrokeShade);
					p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
					cachedStrokeQ = tmp;
					cachedStroke = actStroke;
					cachedStrokeShade = actStrokeShade;
				}
				else
					p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
			}
			p->translate(0.0, BaseOffs);
			if (itemRenderText.hasObject(a))
				DrawObj_Embedded(p, cullingArea, itemRenderText.charStyle(a), itemRenderText.object(a));
			else
				drawGlyphs(p, itemRenderText.charStyle(a), itemRenderText.flags(a), *glyphs);
		}
		p->setWorldMatrix(savWM);
		p->restore();
		MaxChars = a+1;
		CurX -= dx;
		if (itemRenderText.hasObject(a))
			CurX += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs->scaleH + extraOffset;
		else if (chstr[0] == SpecialChars::BLANK)
			CurX += glyphs->wide()+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0 + wordExtra + extraOffset;
		else
			CurX += glyphs->wide()+itemRenderText.charStyle(a).fontSize() *itemRenderText.charStyle(a).tracking() / 10000.0 + extraOffset;
	}
}
Ejemplo n.º 8
0
void LabelScheme::Draw(MapTranslator *renderer, Feature *feature, QPainter *painter)
{
    if(p_label_paint_func) {
        if(p_label_paint_func(painter, renderer, feature, this))
            return;
    }
    if(!p_fieldName.isEmpty()) {
        QString name = feature->GetFieldValue(p_fieldName);
        if(p_position == QSimpleSpatial::FollowPath && feature->getScheme()->getShapeType() == QSimpleSpatial::PolyLine)
        {
            PolylineFeature *pf = static_cast<PolylineFeature *>(feature);
            if(pf) {
                const QVector<Points *> *array = pf->getPointsArray();
                QPainterPath path;
                QPointF pathpoint;
                for(int i = 0;i < array->count();i ++) {
                    Points *points = array->at(i);
                    if(i > 0 && renderer->Coord2ScreenPoint(points->x[0],points->y[0]) != pathpoint)
                        break;
                    pathpoint = renderer->Coord2ScreenPoint(points->x[0],points->y[0]);
                    path.moveTo(pathpoint);
                    for(int j = 1;j < points->count;j ++) {
                        pathpoint = renderer->Coord2ScreenPoint(points->x[j],points->y[j]);
                        path.lineTo(pathpoint);
                    }
                }
                painter->setPen(p_pen);
                painter->setFont(p_font);
                qreal pathLength = path.length();
                qreal textLength = painter->fontMetrics().boundingRect(name).width() * 1.5;
                if(pathLength > textLength) {
                    qreal length = (pathLength - textLength) / 2;
                    for ( int i = 0; i < name.size(); i++ ) {
                        qreal currentPos = length / pathLength;
                        QPointF point = path.pointAtPercent(currentPos);
                        QRect charRect = painter->fontMetrics().boundingRect(name[i]);
                        charRect.translate(point.x(),point.y());
                        renderer->addLabelRect(charRect.marginsAdded(QMargins(5,5,5,5)));
                        qreal angle = path.angleAtPercent(currentPos);
                        angle = 360 - angle;
                        painter->save();
                        painter->translate(point);
                        painter->rotate(angle);
                        painter->drawText(QPoint(p_offset.X, p_offset.Y),QString(name[i]));
                        painter->restore();
                        length += charRect.width();
                        length += p_font.pointSize() / 2;
                    }
                }
            }
        }
        else
        {
            QSimpleSpatial::SimplePoint labelPosition = feature->getLabelPosition(p_position);
            QSimpleSpatial::SimplePoint point = renderer->Coord2Screen(labelPosition);
            QRect rect = painter->fontMetrics().boundingRect(name);
            rect.moveTo(point.X - rect.width() / 2 + p_offset.X,point.Y - rect.height() / 2 + p_offset.Y);
            if(p_allowOverlap || !renderer->isLabelIntersects(rect)) {
                painter->setPen(p_pen);
                painter->setFont(p_font);
                painter->drawText(rect,Qt::AlignVCenter,name);
                if(!p_allowOverlap)
                    renderer->addLabelRect(rect);
            }
        }
    }
}