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; }
static ComPtr<ID2D1PathGeometry1> vectorPathToID2D1PathGeometry(const QVectorPath &path, bool alias) { ComPtr<ID2D1PathGeometry1> pathGeometry; HRESULT hr = factory()->CreatePathGeometry(pathGeometry.GetAddressOf()); if (FAILED(hr)) { qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr); return NULL; } if (path.isEmpty()) return pathGeometry; ComPtr<ID2D1GeometrySink> sink; hr = pathGeometry->Open(sink.GetAddressOf()); if (FAILED(hr)) { qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr); return NULL; } sink->SetFillMode(path.hasWindingFill() ? D2D1_FILL_MODE_WINDING : D2D1_FILL_MODE_ALTERNATE); bool inFigure = false; const QPainterPath::ElementType *types = path.elements(); const int count = path.elementCount(); const qreal *points = 0; QScopedArrayPointer<qreal> rounded_points; if (alias) { // Aliased painting, round to whole numbers rounded_points.reset(new qreal[count * 2]); points = rounded_points.data(); for (int i = 0; i < (count * 2); i++) rounded_points[i] = qRound(path.points()[i]); } else { // Antialiased painting, keep original numbers points = path.points(); } Q_ASSERT(points); if (types) { qreal x, y; for (int i = 0; i < count; i++) { x = points[i * 2]; y = points[i * 2 + 1]; switch (types[i]) { case QPainterPath::MoveToElement: if (inFigure) sink->EndFigure(D2D1_FIGURE_END_OPEN); sink->BeginFigure(D2D1::Point2F(x, y), D2D1_FIGURE_BEGIN_FILLED); inFigure = true; break; case QPainterPath::LineToElement: sink->AddLine(D2D1::Point2F(x, y)); break; case QPainterPath::CurveToElement: { Q_ASSERT((i + 2) < count); Q_ASSERT(types[i+1] == QPainterPath::CurveToDataElement); Q_ASSERT(types[i+2] == QPainterPath::CurveToDataElement); i++; const qreal x2 = points[i * 2]; const qreal y2 = points[i * 2 + 1]; i++; const qreal x3 = points[i * 2]; const qreal y3 = points[i * 2 + 1]; D2D1_BEZIER_SEGMENT segment = { D2D1::Point2F(x, y), D2D1::Point2F(x2, y2), D2D1::Point2F(x3, y3) }; sink->AddBezier(segment); } break; case QPainterPath::CurveToDataElement: qWarning("%s: Unhandled Curve Data Element", __FUNCTION__); break; } } } else { sink->BeginFigure(D2D1::Point2F(points[0], points[1]), D2D1_FIGURE_BEGIN_FILLED); inFigure = true; for (int i = 1; i < count; i++) sink->AddLine(D2D1::Point2F(points[i * 2], points[i * 2 + 1])); } if (inFigure) { if (path.hasImplicitClose()) sink->AddLine(D2D1::Point2F(points[0], points[1])); sink->EndFigure(D2D1_FIGURE_END_OPEN); } sink->Close(); return pathGeometry; }