Exemple #1
0
//FIXME: width and length for arrow
QPolygonF QNEConnection::createArrowPoly(QPainterPath& p, QNEPort* conn) {
    float arrowStartPercentage;
    float arrowEndPercentage;

    if (conn->isOutput()) {
        arrowStartPercentage = p.percentAtLength(p.length() - conn->radius() - arrowSize);
        arrowEndPercentage = p.percentAtLength(p.length() - conn->radius());
    }
    else {
        //assuming is start connector, should throw exception otherwise?
        arrowStartPercentage = p.percentAtLength(conn->radius() + arrowSize);
        arrowEndPercentage = p.percentAtLength(conn->radius());
    }
    QPointF headStartP = p.pointAtPercent(arrowStartPercentage);
    QPointF headEndP = p.pointAtPercent(arrowEndPercentage);
    QLineF arrowMiddleLine(headStartP, headEndP);
    //QLineF normHead = arrowMiddleLine.normalVector();
    arrowMiddleLine.unitVector();
    QPointF normHead(arrowMiddleLine.dy(), -arrowMiddleLine.dx());
    QPointF arrowP1 = headStartP + normHead * 0.4;
    QPointF arrowP2 = headStartP - normHead * 0.4;

    QPolygonF arrowHeadEnd;
    arrowHeadEnd << headEndP << arrowP1 << arrowP2 << headEndP /*<< headEndP*/;
    return arrowHeadEnd;
}
QPolygonF mafNodeConnectionGraphicWidget::createArrowPoly(QPainterPath& p, mafNodeConnectorGraphicWidget* conn) {
	float arrowStartPercentage;
	float arrowEndPercentage;
	
	if (conn == mEndConnector) {
		arrowStartPercentage = p.percentAtLength(p.length() - conn->mRadius - arrowSize);
		arrowEndPercentage = p.percentAtLength(p.length() - conn->mRadius);
	}
	else {
		arrowStartPercentage = p.percentAtLength(conn->mRadius + arrowSize);
		arrowEndPercentage = p.percentAtLength(conn->mRadius);
	}
	QPointF headStartP = p.pointAtPercent(arrowStartPercentage);
	QPointF headEndP = p.pointAtPercent(arrowEndPercentage);
	QLineF arrowMiddleLine(headStartP, headEndP);
	//QLineF normHead = arrowMiddleLine.normalVector();
	arrowMiddleLine.unitVector();
	QPointF normHead(arrowMiddleLine.dy(), -arrowMiddleLine.dx());
	QPointF arrowP1 = headStartP + normHead * 0.4;
	QPointF arrowP2 = headStartP - normHead * 0.4;

	QPolygonF arrowHeadEnd;
	arrowHeadEnd << headEndP << arrowP1 << arrowP2 /*<< headEndP*/;
	return arrowHeadEnd;
}
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();
}
Exemple #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
}
Exemple #5
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());
            }
        }
    }
}
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;
	}
}