VectorPath::VectorPath(const QPainterPath &painterPath)
{
    m_isPainterPath = true;
    nOuter = 1;
    m_painterPath = painterPath;
    m_fillRule = painterPath.fillRule();
}
static QPainterPath qwtTransformPath( const QwtScaleMap &xMap,
        const QwtScaleMap &yMap, const QPainterPath &path, bool doAlign )
{
    QPainterPath shape;
    shape.setFillRule( path.fillRule() );

    for ( int i = 0; i < path.elementCount(); i++ )
    {
        const QPainterPath::Element &element = path.elementAt( i );

        double x = xMap.transform( element.x );
        double y = yMap.transform( element.y );

        switch( element.type )
        {
            case QPainterPath::MoveToElement:
            {
                if ( doAlign )
                {
                    x = qRound( x );
                    y = qRound( y );
                }

                shape.moveTo( x, y );
                break;
            }
            case QPainterPath::LineToElement:
            {
                if ( doAlign )
                {
                    x = qRound( x );
                    y = qRound( y );
                }

                shape.lineTo( x, y );
                break;
            }
            case QPainterPath::CurveToElement:
            {
                const QPainterPath::Element& element1 = path.elementAt( ++i );
                const double x1 = xMap.transform( element1.x );
                const double y1 = yMap.transform( element1.y );

                const QPainterPath::Element& element2 = path.elementAt( ++i );
                const double x2 = xMap.transform( element2.x );
                const double y2 = yMap.transform( element2.y );

                shape.cubicTo( x, y, x1, y1, x2, y2 );
                break;
            }
            case QPainterPath::CurveToDataElement:
            {
                break;
            }
        }
    }

    return shape;
}
/*!
  Draw the shape item

  \param painter Painter
  \param xMap X-Scale Map
  \param yMap Y-Scale Map
  \param canvasRect Contents rect of the plot canvas
*/
void QwtPlotShapeItem::draw( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect ) const
{
    if ( d_data->shape.isEmpty() )
        return;

    if ( d_data->pen.style() == Qt::NoPen 
        && d_data->brush.style() == Qt::NoBrush )
    {
        return;
    }

    const QRectF cRect = QwtScaleMap::invTransform(
        xMap, yMap, canvasRect.toRect() );

    if ( d_data->boundingRect.intersects( cRect ) )
    {
        const bool doAlign = QwtPainter::roundingAlignment( painter );

        QPainterPath path = qwtTransformPath( xMap, yMap, 
            d_data->shape, doAlign );

        if ( testPaintAttribute( QwtPlotShapeItem::ClipPolygons ) )
        {
            qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
            QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );

            QPainterPath clippedPath;
            clippedPath.setFillRule( path.fillRule() );

            const QList<QPolygonF> polygons = path.toSubpathPolygons();
            for ( int i = 0; i < polygons.size(); i++ )
            {
                const QPolygonF p = QwtClipper::clipPolygonF(
                    clipRect, polygons[i], true );

                clippedPath.addPolygon( p );

            }

            path = clippedPath;
        }

        if ( d_data->renderTolerance > 0.0 )
        {
            QwtWeedingCurveFitter fitter( d_data->renderTolerance );

            QPainterPath fittedPath;
            fittedPath.setFillRule( path.fillRule() );

            const QList<QPolygonF> polygons = path.toSubpathPolygons();
            for ( int i = 0; i < polygons.size(); i++ )
                fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) );

            path = fittedPath;
        }

        painter->setPen( d_data->pen );
        painter->setBrush( d_data->brush );

        painter->drawPath( path );
    }
}
/*!
  Draw the shape item

  \param painter Painter
  \param xMap X-Scale Map
  \param yMap Y-Scale Map
  \param canvasRect Contents rect of the plot canvas
*/
void QwtPlotShapeItem::draw( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect ) const
{
    if ( d_data->shape.isEmpty() )
        return;

    if ( d_data->pen.style() == Qt::NoPen
        && d_data->brush.style() == Qt::NoBrush )
    {
        return;
    }

    const QRectF cr = QwtScaleMap::invTransform(
        xMap, yMap, canvasRect.toRect() );

    const QRectF &br = d_data->boundingRect;

    if ( ( br.left() > cr.right() ) || ( br.right() < cr.left() )
        || ( br.top() > cr.bottom() ) || ( br.bottom() < cr.top() ) )
    {
        // outside the visisble area
        return;
    }

    const bool doAlign = QwtPainter::roundingAlignment( painter );

    QPainterPath path = qwtTransformPath( xMap, yMap,
        d_data->shape, doAlign );

    if ( testPaintAttribute( QwtPlotShapeItem::ClipPolygons ) )
    {
        const qreal pw = QwtPainter::effectivePenWidth( painter->pen() );
        const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );

        QPainterPath clippedPath;
        clippedPath.setFillRule( path.fillRule() );

        QList<QPolygonF> polygons = path.toSubpathPolygons();
        for ( int i = 0; i < polygons.size(); i++ )
        {
            QwtClipper::clipPolygonF( clipRect, polygons[i], true );
            clippedPath.addPolygon( polygons[i] );

        }

        path = clippedPath;
    }

    if ( d_data->renderTolerance > 0.0 )
    {
        QwtWeedingCurveFitter fitter( d_data->renderTolerance );

        QPainterPath fittedPath;
        fittedPath.setFillRule( path.fillRule() );

        const QList<QPolygonF> polygons = path.toSubpathPolygons();
        for ( int i = 0; i < polygons.size(); i++ )
            fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) );

        path = fittedPath;
    }

    painter->setPen( d_data->pen );
    painter->setBrush( d_data->brush );

    painter->drawPath( path );
}
static ComPtr<ID2D1PathGeometry1> painterPathToPathGeometry(const QPainterPath &path)
{
    ComPtr<ID2D1PathGeometry1> geometry;
    ComPtr<ID2D1GeometrySink> sink;

    HRESULT hr = factory()->CreatePathGeometry(&geometry);
    if (FAILED(hr)) {
        qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr);
        return NULL;
    }

    hr = geometry->Open(&sink);
    if (FAILED(hr)) {
        qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr);
        return NULL;
    }

    switch (path.fillRule()) {
    case Qt::WindingFill:
        sink->SetFillMode(D2D1_FILL_MODE_WINDING);
        break;
    case Qt::OddEvenFill:
        sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);
        break;
    }

    bool inFigure = false;

    for (int i = 0; i < path.elementCount(); i++) {
        const QPainterPath::Element element = path.elementAt(i);

        switch (element.type) {
        case QPainterPath::MoveToElement:
            if (inFigure)
                sink->EndFigure(D2D1_FIGURE_END_OPEN);

            sink->BeginFigure(to_d2d_point_2f(element), D2D1_FIGURE_BEGIN_FILLED);
            inFigure = true;
            break;

        case QPainterPath::LineToElement:
            sink->AddLine(to_d2d_point_2f(element));
            break;

        case QPainterPath::CurveToElement:
        {
            const QPainterPath::Element data1 = path.elementAt(++i);
            const QPainterPath::Element data2 = path.elementAt(++i);

            Q_ASSERT(i < path.elementCount());

            Q_ASSERT(data1.type == QPainterPath::CurveToDataElement);
            Q_ASSERT(data2.type == QPainterPath::CurveToDataElement);

            D2D1_BEZIER_SEGMENT segment;

            segment.point1 = to_d2d_point_2f(element);
            segment.point2 = to_d2d_point_2f(data1);
            segment.point3 = to_d2d_point_2f(data2);

            sink->AddBezier(segment);
        }
            break;

        case QPainterPath::CurveToDataElement:
            qWarning("%s: Unhandled Curve Data Element", __FUNCTION__);
            break;
        }
    }

    if (inFigure)
        sink->EndFigure(D2D1_FIGURE_END_OPEN);

    sink->Close();

    return geometry;
}
void QCairoPaintEngine::drawPath(const QPainterPath &path)
{
    if (!cr || !surface) {
        qDebug()<<"Cairo Error [QCairoPaintEngine::drawPath]: no cairo or no surface!";
        return;
    }
    if (cbrush.style()==Qt::NoBrush && cpen.style()==Qt::NoPen) {
        qDebug()<<"Cairo Error [QCairoPaintEngine::drawPath]: no pen and no brush set!";
        return;
    }
    //qDebug()<<"drawPath n="<<path;

    bool fill;
    updatePath(path, fill);
    /*cairo_new_path(cr);

    int start = -1, elmCount = path.elementCount();
    for (int index = 0; index < elmCount; index++)
    {
      const QPainterPath::Element elm = path.elementAt(index);
      switch (elm.type)
      {
        case QPainterPath::MoveToElement:
          cairo_move_to(cr, elm.x, elm.y);
          start = index;
          break;

        case QPainterPath::LineToElement:
          cairo_line_to(cr, elm.x, elm.y);
          break;

        case QPainterPath::CurveToElement:
          cairo_curve_to(cr, elm.x, elm.y,
              path.elementAt(index + 1).x, path.elementAt(index + 1).y,
              path.elementAt(index + 2).x, path.elementAt(index + 2).y);
          index += 2;
          break;

        default:
          break;
      }
    }

    bool fill=false;
    if (start != -1 && start != elmCount - 1
          && path.elementAt(start).x == path.elementAt(elmCount - 1).x
            && path.elementAt(start).y == path.elementAt(elmCount - 1).y){
        cairo_close_path(cr);
        //qDebug()<<"closing path";
        fill=cbrush.style()!=Qt::NoBrush;
    }*/
    if (fill) fill=cbrush.style()!=Qt::NoBrush;


    if (fill) {
        switch (path.fillRule()) {
            case Qt::WindingFill:
                cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
                break;
            default:
            case Qt::OddEvenFill:
                cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
                break;
        }


        updateBrush();
        if (cpen.style()!=Qt::NoPen) cairo_fill_preserve(cr);
        else cairo_fill(cr);
    }
    if (cpen.style()!=Qt::NoPen) {
        updatePen();
        cairo_stroke(cr);
    } else {

    }


}