예제 #1
0
static QPainterPath getPathStroke(const QPainterPath &path, const RenderObject* object, const RenderStyle* style)
{ 
    QPainterPathStroker s;
    s.setWidth(KSVGPainterFactory::cssPrimitiveToLength(object, style->svgStyle()->strokeWidth(), 1.0));

    if (style->svgStyle()->capStyle() == ButtCap)
        s.setCapStyle(Qt::FlatCap);
    else if (style->svgStyle()->capStyle() == RoundCap)
        s.setCapStyle(Qt::RoundCap);

    if (style->svgStyle()->joinStyle() == MiterJoin) {
        s.setJoinStyle(Qt::MiterJoin);
        s.setMiterLimit((qreal) style->svgStyle()->strokeMiterLimit());
    } else if(style->svgStyle()->joinStyle() == RoundJoin)
        s.setJoinStyle(Qt::RoundJoin);

    const KCDashArray& dashes = KSVGPainterFactory::dashArrayFromRenderingStyle(style);
    double dashOffset = KSVGPainterFactory::cssPrimitiveToLength(object, style->svgStyle()->strokeDashOffset(), 0.0);

    unsigned int dashLength = !dashes.isEmpty() ? dashes.size() : 0;
    if(dashLength) {
        QVector<qreal> pattern;
        unsigned int count = (dashLength % 2) == 0 ? dashLength : dashLength * 2;

        for(unsigned int i = 0; i < count; i++)
            pattern.append(dashes[i % dashLength] / (float)s.width());

        s.setDashPattern(pattern);
    
        Q_UNUSED(dashOffset);
        // TODO: dash-offset, does/will qt4 API allow it? (Rob)
    }

    return s.createStroke(path);
}
예제 #2
0
void LineObject::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* /*widget*/)
{
    QGraphicsScene* objScene = scene();
    if(!objScene) return;

    QPen paintPen = pen();
    painter->setPen(paintPen);
    updateRubber(painter);
    if(option->state & QStyle::State_Selected)  { paintPen.setStyle(Qt::DashLine); }
    if(objScene->property(ENABLE_LWT).toBool()) { paintPen = lineWeightPen(); }
    painter->setPen(paintPen);

    if(objectRubberMode() != OBJ_RUBBER_LINE) painter->drawLine(line());

    //TODO: This is the initial concept for what realistic rendering be like. It's somewhat decent but needs improvement.
    if(objScene->property(ENABLE_LWT).toBool() && objScene->property(ENABLE_REAL).toBool())
    {
        painter->setPen(objectColor().darker(150)); //TODO: Improve this for black and dark colors
        QPainterPathStroker stroker;
        stroker.setWidth(0.35);
        stroker.setCapStyle(Qt::RoundCap);
        stroker.setJoinStyle(Qt::RoundJoin);
        QPainterPath realPath = stroker.createStroke(path());
        painter->drawPath(realPath);

        QLinearGradient grad(mapFromScene(objectMidPoint()), mapFromScene(objectEndPoint1()));
        grad.setColorAt(0, objectColor());
        grad.setColorAt(1, objectColor().darker(150)); //TODO: Improve this for black and dark colors
        grad.setSpread(QGradient::ReflectSpread);

        painter->fillPath(realPath, QBrush(grad));
    }
}
/**
 * @return The shape of the AssociationLine.
 */
QPainterPath AssociationLine::shape() const
{
    QPainterPathStroker stroker;
    stroker.setWidth(qMax<qreal>(2*SelectedPointDiameter, pen().widthF()) + 2.0);  // allow delta region
    stroker.setCapStyle(Qt::FlatCap);
    return stroker.createStroke(path());
}
예제 #4
0
static QRectF qwtStrokedPathRect( 
    const QPainter *painter, const QPainterPath &path )
{
    QPainterPathStroker stroker;
    stroker.setWidth( painter->pen().widthF() );
    stroker.setCapStyle( painter->pen().capStyle() );
    stroker.setJoinStyle( painter->pen().joinStyle() );
    stroker.setMiterLimit( painter->pen().miterLimit() );

    QRectF rect;
    if ( qwtHasScalablePen( painter ) )
    {
        QPainterPath stroke = stroker.createStroke(path);
        rect = painter->transform().map(stroke).boundingRect();
    }
    else
    {
        QPainterPath mappedPath = painter->transform().map(path);
        mappedPath = stroker.createStroke( mappedPath );

        rect = mappedPath.boundingRect();
    }

    return rect;
}
예제 #5
0
QPainterPath GraphicsUtils::shapeFromPath(const QPainterPath &path, const QPen &pen, double shapeStrokeWidth, bool includeOriginalPath)
{
	// this function mostly copied from QGraphicsItem::qt_graphicsItem_shapeFromPath


    // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
    // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
    static const double penWidthZero = double(0.00000001);

    if (path == QPainterPath())
        return path;
    QPainterPathStroker ps;
    ps.setCapStyle(pen.capStyle());
    //ps.setCapStyle(Qt::FlatCap);
    if (shapeStrokeWidth <= 0.0)
        ps.setWidth(penWidthZero);
    else
        ps.setWidth(shapeStrokeWidth);

    ps.setJoinStyle(pen.joinStyle());
    ps.setMiterLimit(pen.miterLimit());
    QPainterPath p = ps.createStroke(path);
	if (includeOriginalPath) {
		p.addPath(path);
	}
    return p;
}
예제 #6
0
void LayoutBreak::draw(QPainter* painter) const
      {
      if (score()->printing() || !score()->showUnprintable())
            return;

      QPainterPathStroker stroker;
      stroker.setWidth(lw/2);
      stroker.setJoinStyle(Qt::MiterJoin);
      stroker.setCapStyle(Qt::SquareCap);

      QVector<qreal> dashes ;
      dashes.append(1);
      dashes.append(3);
      stroker.setDashPattern(dashes);
      QPainterPath stroke = stroker.createStroke(path);

      painter->fillPath(stroke, selected() ? MScore::selectColor[0] : MScore::layoutBreakColor);


      painter->setPen(QPen(selected() ? MScore::selectColor[0] : MScore::layoutBreakColor,
         lw, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
      painter->setBrush(Qt::NoBrush);
      painter->drawPath(path2);

      }
예제 #7
0
QRectF QAlphaPaintEnginePrivate::addPenWidth(const QPainterPath &path)
{
    Q_Q(QAlphaPaintEngine);

    QPainterPath tmp = path;

    if (m_pen.style() == Qt::NoPen)
        return (path.controlPointRect() * m_transform).boundingRect();
    bool cosmetic = qt_pen_is_cosmetic(m_pen, q->state->renderHints());
    if (cosmetic)
        tmp = path * m_transform;

    QPainterPathStroker stroker;
    if (m_pen.widthF() == 0.0f)
        stroker.setWidth(1.0);
    else
        stroker.setWidth(m_pen.widthF());
    stroker.setJoinStyle(m_pen.joinStyle());
    stroker.setCapStyle(m_pen.capStyle());
    tmp = stroker.createStroke(tmp);
    if (cosmetic)
        return tmp.controlPointRect();

    return (tmp.controlPointRect() * m_transform).boundingRect();
}
예제 #8
0
QPainterPath GraphicsItemEdge::shape() const
{
    QPainterPathStroker stroker;
    stroker.setWidth(g_settings->edgeWidth);
    stroker.setCapStyle(Qt::RoundCap);
    stroker.setJoinStyle(Qt::RoundJoin);
    return stroker.createStroke(path());
}
예제 #9
0
QPainterPath LatexArrow::contour(qreal width) const
{
    QPainterPathStroker stroker;
    stroker.setJoinStyle(Qt::RoundJoin);
    stroker.setCapStyle(Qt::RoundCap);
    stroker.setWidth(width);

    return stroker.createStroke(path());
}
예제 #10
0
QPainterPath GraphicsItemNode::shape() const
{
    //If there is only one segment and it is shorter than half its
    //width, then the arrow head will not be made with 45 degree
    //angles, but rather whatever angle is made by going from the
    //end to the back corners (the final node will be a triangle).
    if (m_hasArrow
            && m_linePoints.size() == 2
            && distance(getLast(), getSecondLast()) < m_width / 2.0)
    {
        QLineF backline = QLineF(getSecondLast(), getLast()).normalVector();
        backline.setLength(m_width / 2.0);
        QPointF backVector = backline.p2() - backline.p1();
        QPainterPath trianglePath;
        trianglePath.moveTo(getLast());
        trianglePath.lineTo(getSecondLast() + backVector);
        trianglePath.lineTo(getSecondLast() - backVector);
        trianglePath.lineTo(getLast());
        return trianglePath;
    }

    //Create a path that outlines the main node shape.
    QPainterPathStroker stroker;
    stroker.setWidth(m_width);
    stroker.setCapStyle(Qt::FlatCap);
    stroker.setJoinStyle(Qt::RoundJoin);
    QPainterPath mainNodePath = stroker.createStroke(path());

    if (!m_hasArrow)
        return mainNodePath;

    //If the node has an arrow head, subtract the part of its
    //final segment to give it a pointy end.
    //NOTE: THIS APPROACH CAN LEAD TO WEIRD EFFECTS WHEN THE NODE'S
    //POINTY END OVERLAPS WITH ANOTHER PART OF THE NODE.  PERHAPS THERE
    //IS A BETTER WAY TO MAKE ARROWHEADS?
    QLineF frontline = QLineF(getLast(), getSecondLast()).normalVector();
    frontline.setLength(m_width / 2.0);
    QPointF frontVector = frontline.p2() - frontline.p1();
    QLineF arrowheadLine(getLast(), getSecondLast());
    arrowheadLine.setLength(1.42 * (m_width / 2.0));
    arrowheadLine.setAngle(arrowheadLine.angle() + 45.0);
    QPointF arrow1 = arrowheadLine.p2();
    arrowheadLine.setAngle(arrowheadLine.angle() - 90.0);
    QPointF arrow2 = arrowheadLine.p2();
    QLineF lastSegmentLine(getSecondLast(), getLast());
    lastSegmentLine.setLength(0.01);
    QPointF additionalForwardBit = lastSegmentLine.p2() - lastSegmentLine.p1();
    QPainterPath subtractionPath;
    subtractionPath.moveTo(getLast());
    subtractionPath.lineTo(arrow1);
    subtractionPath.lineTo(getLast() + frontVector + additionalForwardBit);
    subtractionPath.lineTo(getLast() - frontVector + additionalForwardBit);
    subtractionPath.lineTo(arrow2);
    subtractionPath.lineTo(getLast());
    return mainNodePath.subtracted(subtractionPath);
}
예제 #11
0
QPainterPath QGVEdge::shape() const
{
    QPainterPathStroker ps;
    ps.setCapStyle(_pen.capStyle());
    ps.setWidth(_pen.widthF() + 10);
    ps.setJoinStyle(_pen.joinStyle());
    ps.setMiterLimit(_pen.miterLimit());
    return ps.createStroke(_path);
}
예제 #12
0
void PainterBezier::updatePath()
{
    QPainterPath bezierPath;
    bezierPath.moveTo(m_p1);
    bezierPath.cubicTo( m_p2, m_p3, m_p4 );
    QPainterPathStroker outliner;
    outliner.setWidth(m_FillWidth);
    outliner.setCapStyle( Qt::FlatCap );
    m_Path = outliner.createStroke(bezierPath);
}
예제 #13
0
파일: line.cpp 프로젝트: genuser/freesch
QPainterPath Line::shape() const
{
	QPainterPath path;
	path.moveTo(line().p1());
	path.lineTo(line().p2());
	QPainterPathStroker stroker;
	stroker.setWidth(100);
	stroker.setCapStyle(Qt::FlatCap);
	return stroker.createStroke(path);
}
예제 #14
0
파일: pin.cpp 프로젝트: genuser/freesch
// The default shape() is really thin and hard to select in the symbol editor. Build a more appropriate one.
void Pin::rebuildShape()
{
	if (hidden) {
		cachedShape = QPainterPath();
	} else {
		QPainterPath path;
		path.moveTo(-((clock ? clock_width : 0) + pen().width()), 0);
		path.lineTo(qMax(_length, grid()) + pen().width(), 0);
		QPainterPathStroker stroker;
		stroker.setWidth(80);
		stroker.setCapStyle(Qt::FlatCap);
		cachedShape = stroker.createStroke(path);
	}
}
예제 #15
0
QPainterPath AbstractArrow::contour(qreal width) const
{
    QPainterPath arrowPath = path();

    // if path is empty, return immediately
    if (arrowPath.isEmpty()) {
        return QPainterPath();
    }

    QPainterPathStroker stroker;
    stroker.setJoinStyle(Qt::RoundJoin);
    stroker.setCapStyle(Qt::RoundCap);
    stroker.setWidth(width + style()->penWidth().toPoint());

    return stroker.createStroke(arrowPath);
}
예제 #16
0
FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
{
    GraphicsContext* gc = scratchContext();
    QPainterPathStroker stroke;
    if (applier) {
        applier->strokeStyle(gc);

        QPen pen = gc->pen();
        stroke.setWidth(pen.widthF());
        stroke.setCapStyle(pen.capStyle());
        stroke.setJoinStyle(pen.joinStyle());
        stroke.setMiterLimit(pen.miterLimit());
        stroke.setDashPattern(pen.dashPattern());
        stroke.setDashOffset(pen.dashOffset());
    }
    return stroke.createStroke(m_path).boundingRect();
}
예제 #17
0
void SGI_NetLine::updateCacheAndRepaint() noexcept
{
    prepareGeometryChange();
    mLineF.setP1(mNetLine.getStartPoint().getPosition().toPxQPointF());
    mLineF.setP2(mNetLine.getEndPoint().getPosition().toPxQPointF());
    mBoundingRect = QRectF(mLineF.p1(), mLineF.p2()).normalized();
    mBoundingRect.adjust(-mNetLine.getWidth().toPx()/2, -mNetLine.getWidth().toPx()/2,
                         mNetLine.getWidth().toPx()/2, mNetLine.getWidth().toPx()/2);
    mShape = QPainterPath();
    mShape.moveTo(mNetLine.getStartPoint().getPosition().toPxQPointF());
    mShape.lineTo(mNetLine.getEndPoint().getPosition().toPxQPointF());
    QPainterPathStroker ps;
    ps.setCapStyle(Qt::RoundCap);
    Length width = (mNetLine.getWidth() > Length(1270000) ? mNetLine.getWidth() : Length(1270000));
    ps.setWidth(width.toPx());
    mShape = ps.createStroke(mShape);
    update();
}
예제 #18
0
bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
{
    ASSERT(applier);

    QPainterPathStroker stroke;
    GraphicsContext* gc = scratchContext();
    applier->strokeStyle(gc);

    QPen pen = gc->pen();
    stroke.setWidth(pen.widthF());
    stroke.setCapStyle(pen.capStyle());
    stroke.setJoinStyle(pen.joinStyle());
    stroke.setMiterLimit(pen.miterLimit());
    stroke.setDashPattern(pen.dashPattern());
    stroke.setDashOffset(pen.dashOffset());

    return stroke.createStroke(m_path).contains(point);
}
void CVisSystemCanvasConnectionItem::updateConnection()
{
    if(!d->connection)
        return;

    if(!d->senderNodeItem)
    {
        d->senderNodeItem = d->canvas->nodeItem(d->connection->senderNode());
        d->senderNodeItem->registerConnectionItem(this);
    }
    if(!d->receiverNodeItem)
    {
        d->receiverNodeItem = d->canvas->nodeItem(d->connection->receiverNode());
        d->receiverNodeItem->registerConnectionItem(this);
    }

    if(!d->senderNodeItem || !d->receiverNodeItem)
        return;

    QRectF senderRect = d->senderNodeItem->pathRect(senderPathIndex());
    QRectF receiverRect = d->receiverNodeItem->pathRect(receiverPathIndex());
	QPointF p1, p2;
    senderRect = d->senderNodeItem->mapToScene(senderRect).boundingRect();
    receiverRect = d->receiverNodeItem->mapToScene(receiverRect).boundingRect();
	p1 = senderRect.center();
	p2 = receiverRect.center();

    QPainterPath path;
    QPointF inputCP = p1 + QPointF(0.0f, 25.0f);
    QPointF outputCP = p2 - QPointF(0.0f, 25.0f);
    if(inputCP.x() - outputCP.x() < 25.0f)
        inputCP.setX(inputCP.x()+25.0f);
    path.moveTo(p1);
    path.cubicTo(inputCP, outputCP, p2);

	prepareGeometryChange();
	d->drawShape = path;

	QPainterPathStroker stroker;
	stroker.setWidth(5);
	stroker.setCapStyle(Qt::FlatCap);
	d->itemShape = stroker.createStroke(path);
	d->boundingRect = d->itemShape.boundingRect();
}
예제 #20
0
void dtkComposerSceneEdge::adjust(const QPointF& start, const QPointF& end)
{
    this->prepareGeometryChange();

    QPointF midPoint = (start + end) / 2;

    qreal halfMid = (midPoint.x() - start.x())/2;

    QPainterPath path;
    path.moveTo(start);
    path.cubicTo(QPointF(end.x() - halfMid, start.y()), QPointF(start.x() + halfMid, end.y()), end);

    QPainterPathStroker stroker;
    stroker.setWidth(3);
    stroker.setCapStyle(Qt::RoundCap);
    d->path = stroker.createStroke(path);

    this->update();
}
예제 #21
0
파일: UbLink.cpp 프로젝트: pholz/UberCode
	void UbLink::updatePath()
	{
		if ( m_StartNode && m_EndNode )
		{
			QPointF startPos = m_StartNode->scenePos();
			QPointF endPos	 = m_EndNode->scenePos();

			QPainterPath bezierPath;
			bezierPath.moveTo( startPos );
			qreal dist   = endPos.x() - startPos.x();
			qreal offset = 0.5f*dist; 
			QPointF cpA  = startPos + QPointF( offset, 0 );
			QPointF cpB  = endPos   - QPointF( offset, 0 );
			bezierPath.cubicTo( cpA, cpB, endPos );
			QPainterPathStroker outliner;
			outliner.setWidth(4.f);
			outliner.setCapStyle( Qt::RoundCap );
			setPath( outliner.createStroke(bezierPath) );
		}
	}
예제 #22
0
void tst_QPainterPath::testStroker()
{
    QFETCH(QPainterPath, path);
    QFETCH(QPen, pen);
    QFETCH(QPainterPath, stroke);

    QPainterPathStroker stroker;
    stroker.setWidth(pen.widthF());
    stroker.setCapStyle(pen.capStyle());
    stroker.setJoinStyle(pen.joinStyle());
    stroker.setMiterLimit(pen.miterLimit());
    stroker.setDashPattern(pen.style());
    stroker.setDashOffset(pen.dashOffset());

    QPainterPath result = stroker.createStroke(path);

    // check if stroke == result
    QVERIFY(result.subtracted(stroke).isEmpty());
    QVERIFY(stroke.subtracted(result).isEmpty());
}
FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
{
    // FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer
    // on each call.
    OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1));
    GraphicsContext* gc = scratchImage->context();
    QPainterPathStroker stroke;
    if (applier) {
        applier->strokeStyle(gc);

        QPen pen = gc->pen();
        stroke.setWidth(pen.widthF());
        stroke.setCapStyle(pen.capStyle());
        stroke.setJoinStyle(pen.joinStyle());
        stroke.setMiterLimit(pen.miterLimit());
        stroke.setDashPattern(pen.dashPattern());
        stroke.setDashOffset(pen.dashOffset());
    }
    return stroke.createStroke(m_path).boundingRect();
}
bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
{
    ASSERT(applier);

    // FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer
    // on each call.
    OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1));
    GraphicsContext* gc = scratchImage->context();
    QPainterPathStroker stroke;
    applier->strokeStyle(gc);

    QPen pen = gc->pen();
    stroke.setWidth(pen.widthF());
    stroke.setCapStyle(pen.capStyle());
    stroke.setJoinStyle(pen.joinStyle());
    stroke.setMiterLimit(pen.miterLimit());
    stroke.setDashPattern(pen.dashPattern());
    stroke.setDashOffset(pen.dashOffset());

    return stroke.createStroke(m_path).contains(point);
}
예제 #25
0
QPainterPath ArrowItem::shape() const
{
    QPainterPath path;
    path.setFillRule(Qt::WindingFill);
    if (m_shaftItem &&m_shaftItem->path() != QPainterPath()) {
        QPainterPathStroker ps;
        QPen pen = m_shaftItem->pen();
        ps.setCapStyle(pen.capStyle());
        ps.setJoinStyle(pen.joinStyle());
        ps.setMiterLimit(pen.miterLimit());
        // overwrite pen width to make selection more lazy
        ps.setWidth(16.0);
        QPainterPath p = ps.createStroke(m_shaftItem->path());
        path.addPath(p);
    }
    if (m_startHeadItem)
        path.addRect(mapRectFromItem(m_startHeadItem, m_startHeadItem->boundingRect()));
    if (m_endHeadItem)
        path.addRect(mapRectFromItem(m_endHeadItem, m_endHeadItem->boundingRect()));
    return path;
}
예제 #26
0
QPainterPath Toolbox::shapeFromPath(const QPainterPath& path, const QPen& pen,
                                    const QBrush&         brush,
                                    const UnsignedLength& minWidth) noexcept {
  // http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/graphicsview/qgraphicsitem.cpp
  // Function: qt_graphicsItem_shapeFromPath()

  if (path == QPainterPath() || pen == Qt::NoPen) {
    return path;
  } else {
    QPainterPathStroker ps;
    ps.setCapStyle(pen.capStyle());
    ps.setWidth(qMax(qMax(pen.widthF(), qreal(0.00000001)), minWidth->toPx()));
    ps.setJoinStyle(pen.joinStyle());
    ps.setMiterLimit(pen.miterLimit());
    QPainterPath p = ps.createStroke(path);
    if (brush != Qt::NoBrush) {
      p.addPath(path);
    }
    return p;
  }
}
예제 #27
0
QRectF QAlphaPaintEnginePrivate::addPenWidth(const QPainterPath &path)
{
    QPainterPath tmp = path;

    if (m_pen.style() == Qt::NoPen)
        return (path.controlPointRect() * m_transform).boundingRect();
    if (m_pen.isCosmetic())
        tmp = path * m_transform;

    QPainterPathStroker stroker;
    if (m_pen.widthF() == 0.0f)
        stroker.setWidth(1.0);
    else
        stroker.setWidth(m_pen.widthF());
    stroker.setJoinStyle(m_pen.joinStyle());
    stroker.setCapStyle(m_pen.capStyle());
    tmp = stroker.createStroke(tmp);
    if (m_pen.isCosmetic())
        return tmp.controlPointRect();

    return (tmp.controlPointRect() * m_transform).boundingRect();
}
예제 #28
0
void Box::draw(QPainter* painter) const
      {
      if (score() && score()->printing())
            return;
      if (selected() || editMode || dropTarget() || score()->showFrames()) {
            qreal w = spatium() * .15;
            QPainterPathStroker stroker;
            stroker.setWidth(w);
            stroker.setJoinStyle(Qt::MiterJoin);
            stroker.setCapStyle(Qt::SquareCap);

            QVector<qreal> dashes ;
            dashes.append(1);
            dashes.append(3);
            stroker.setDashPattern(dashes);
            QPainterPath path;
            w *= .5;
            path.addRect(bbox().adjusted(w, w, -w, -w));
            QPainterPath stroke = stroker.createStroke(path);
            painter->setBrush(Qt::NoBrush);
            painter->fillPath(stroke, (selected() || editMode || dropTarget()) ? MScore::selectColor[0] : MScore::frameMarginColor);
            }
      }
예제 #29
0
void PainterBezier::paint(QPainter * painter)
{
    painter->setBrush(Qt::transparent);
    QRectF rect = calculateBoundingBox();
    setX(rect.topLeft().x() - 10);
    setY( rect.topLeft().y() - 10);
    setWidth( rect.width() + 20);
    setHeight( rect.height() + 20);
    QPen pen;
    pen.setWidthF(m_OutlineWidth);
    pen.setBrush(m_OutlineColor);
    painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    painter->setPen(pen);
    painter->setBrush(m_FillColor);
    QPainterPath bezierPath;
    QPointF pos(x(),y());
    bezierPath.moveTo(m_p1 - pos);
    bezierPath.cubicTo( m_p2 - pos, m_p3 - pos, m_p4 - pos );
    QPainterPathStroker outliner;
    outliner.setWidth(m_FillWidth);
    outliner.setCapStyle( Qt::FlatCap );
    m_Path = outliner.createStroke(bezierPath);
    painter->drawPath(m_Path);
}
void PathStrokeRenderer::paint(QPainter *painter)
{
    if (m_points.isEmpty())
        initializePoints();

    painter->setRenderHint(QPainter::Antialiasing);

    QPalette pal = palette();
    painter->setPen(Qt::NoPen);

    // Construct the path
    QPainterPath path;
    path.moveTo(m_points.at(0));

    if (m_pathMode == LineMode) {
        for (int i=1; i<m_points.size(); ++i)
            path.lineTo(m_points.at(i));
    } else {
        int i=1;
        while (i + 2 < m_points.size()) {
            path.cubicTo(m_points.at(i), m_points.at(i+1), m_points.at(i+2));
            i += 3;
        }
        while (i < m_points.size()) {
            path.lineTo(m_points.at(i));
            ++i;
        }
    }

    // Draw the path
    {
        QColor lg = Qt::red;

        // The "custom" pen
        if (m_penStyle == Qt::NoPen) {
            QPainterPathStroker stroker;
            stroker.setWidth(m_penWidth);
            stroker.setJoinStyle(m_joinStyle);
            stroker.setCapStyle(m_capStyle);

            QVector<qreal> dashes;
            qreal space = 4;
            dashes << 1 << space
                   << 3 << space
                   << 9 << space
                   << 27 << space
                   << 9 << space
                   << 3 << space;
            stroker.setDashPattern(dashes);
            QPainterPath stroke = stroker.createStroke(path);
            painter->fillPath(stroke, lg);

        } else {
            QPen pen(lg, m_penWidth, m_penStyle, m_capStyle, m_joinStyle);
            painter->strokePath(path, pen);
        }
    }

    if (1) {
        // Draw the control points
        painter->setPen(QColor(50, 100, 120, 200));
        painter->setBrush(QColor(200, 200, 210, 120));
        for (int i=0; i<m_points.size(); ++i) {
            QPointF pos = m_points.at(i);
            painter->drawEllipse(QRectF(pos.x() - m_pointSize,
                                       pos.y() - m_pointSize,
                                       m_pointSize*2, m_pointSize*2));
        }
        painter->setPen(QPen(Qt::lightGray, 0, Qt::SolidLine));
        painter->setBrush(Qt::NoBrush);
        painter->drawPolyline(m_points);
    }

}