31 : QPaintEngine( QPaintEngine::AllFeatures )
32 , mUsePathStroker( usePathStroker )
38 mStrokedPathsSegments = segments;
43 mSimplifyTolerance = tolerance;
58 return QPaintEngine::User;
63 if ( mUsePathStroker && state.state().testFlag( QPaintEngine::DirtyFlag::DirtyPen ) )
88 if ( transform.isIdentity() )
90 for (
int i = 0; i < lineCount; ++i, ++lines )
93 QVector<double> {
static_cast< double >( lines->x1() ),
static_cast< double >( lines->x2() ) },
94 QVector<double> {
static_cast< double >( lines->y1() ),
static_cast< double >( lines->y2() ) } )
100 for (
int i = 0; i < lineCount; ++i, ++lines )
102 double x1 = lines->x1();
103 double x2 = lines->x2();
104 double y1 = lines->y1();
105 double y2 = lines->y2();
107 double tx1, tx2, ty1, ty2;
108 transform.map( x1, y1, &tx1, &ty1 );
109 transform.map( x2, y2, &tx2, &ty2 );
112 QVector<double> { tx1, tx2 },
113 QVector<double> { ty1, ty2 } )
121 if ( mUsePathStroker )
124 QPaintEngine::drawLines( lines, lineCount );
128 const QTransform transform = painter()->combinedTransform();
135 if ( mUsePathStroker )
138 QPaintEngine::drawLines( lines, lineCount );
142 const QTransform transform = painter()->combinedTransform();
151 if ( transform.isIdentity() )
153 for (
int i = 0; i < pointCount; ++i, ++points )
156 static_cast< double >( points->y() ) ) );
161 for (
int i = 0; i < pointCount; ++i, ++points )
163 double x = points->x();
164 double y = points->y();
167 transform.map( x, y, &tx, &ty );
176 const QTransform transform = painter()->combinedTransform();
182 const QTransform transform = painter()->combinedTransform();
190 if ( transform.isIdentity() )
192 for (
int i = 0; i < rectCount; ++i, ++rects )
195 QVector<double> {
static_cast< double >( rects->left() ),
196 static_cast< double >( rects->right() ),
197 static_cast< double >( rects->right() ),
198 static_cast< double >( rects->left() ),
199 static_cast< double>( rects->left() )
201 QVector<double> {
static_cast< double >( rects->bottom() ),
202 static_cast< double >( rects->bottom() ),
203 static_cast< double >( rects->top() ),
204 static_cast< double >( rects->top() ),
205 static_cast< double >( rects->bottom() )
212 for (
int i = 0; i < rectCount; ++i, ++rects )
214 const double left = rects->left();
215 const double right = rects->right();
216 const double top = rects->top();
217 const double bottom = rects->bottom();
219 double bottomLeftX, bottomLeftY, bottomRightX, bottomRightY, topLeftX, topLeftY, topRightX, topRightY;
220 transform.map( left, bottom, &bottomLeftX, &bottomLeftY );
221 transform.map( right, bottom, &bottomRightX, &bottomRightY );
222 transform.map( left, top, &topLeftX, &topLeftY );
223 transform.map( right, top, &topRightX, &topRightY );
226 QVector<double> { bottomLeftX, bottomRightX, topRightX, topLeftX, bottomLeftX },
227 QVector<double> { bottomLeftY, bottomRightY, topRightY, topLeftY, bottomLeftY } );
235 const QTransform transform = painter()->combinedTransform();
241 const QTransform transform = painter()->combinedTransform();
250 x.resize( pointCount );
251 y.resize( pointCount );
252 double *xData = x.data();
253 double *yData = y.data();
255 if ( transform.isIdentity() )
257 for (
int i = 0; i < pointCount; ++i, ++points )
259 *xData++ = points->x();
260 *yData++ = points->y();
265 for (
int i = 0; i < pointCount; ++i, ++points )
267 const double x = points->x();
268 const double y = points->y();
270 transform.map( x, y, &tx, &ty );
279 case QPaintEngine::PolylineMode:
280 if ( simplifyTolerance > 0 )
286 case QPaintEngine::OddEvenMode:
287 case QPaintEngine::WindingMode:
288 case QPaintEngine::ConvexMode:
289 if ( simplifyTolerance > 0 )
299 if ( mUsePathStroker && mode == PolygonDrawMode::PolylineMode )
302 if ( pointCount > 0 )
305 path.moveTo( *points++ );
306 for (
int i = 1; i < pointCount; ++i )
308 path.lineTo( *points++ );
315 const QTransform transform = painter()->combinedTransform();
316 drawPolygonImp( transform, mGeometry, points, pointCount, mode, mSimplifyTolerance );
322 if ( mUsePathStroker )
325 if ( pointCount > 0 )
328 path.moveTo( *points++ );
329 for (
int i = 1; i < pointCount; ++i )
331 path.lineTo( *points++ );
338 const QTransform transform = painter()->combinedTransform();
339 drawPolygonImp( transform, mGeometry, points, pointCount, mode, mSimplifyTolerance );
345 std::unique_ptr< QgsAbstractGeometry > buffered;
346 if ( mSimplifyTolerance > 0 )
353 const double preBufferedSimplificationFactor = mSimplifyTolerance * 0.75;
354 std::unique_ptr< QgsLineString > simplified( line->
simplifyByDistance( preBufferedSimplificationFactor ) );
356 buffered.reset(
geos.buffer( penWidth / 2, mStrokedPathsSegments, endCapStyle, joinStyle, miterLimit ) );
361 buffered.reset(
geos.buffer( penWidth / 2, mStrokedPathsSegments, endCapStyle, joinStyle, miterLimit ) );
368 buffered->transform( *matrix );
370 if (
QgsGeometryCollection *bufferedCollection = qgsgeometry_cast< QgsGeometryCollection * >( buffered.get() ) )
372 if ( mSimplifyTolerance > 0 )
374 for (
auto it = bufferedCollection->const_parts_begin(); it != bufferedCollection->const_parts_end(); ++it )
376 mGeometry.
addGeometry( ( *it )->simplifyByDistance( mSimplifyTolerance ) );
381 mGeometry.
addGeometries( bufferedCollection->takeGeometries() );
386 if ( mSimplifyTolerance > 0 )
388 mGeometry.
addGeometry( buffered->simplifyByDistance( mSimplifyTolerance ) );
397Qgis::EndCapStyle QgsGeometryPaintEngine::penStyleToCapStyle( Qt::PenCapStyle style )
407 case Qt::MPenCapStyle:
415Qgis::JoinStyle QgsGeometryPaintEngine::penStyleToJoinStyle( Qt::PenJoinStyle style )
420 case Qt::SvgMiterJoin:
426 case Qt::MPenJoinStyle:
434void QgsGeometryPaintEngine::addSubpathGeometries(
const QPainterPath &path,
const QTransform &matrix )
436 if ( path.isEmpty() )
439 const bool transformIsIdentity = matrix.isIdentity();
442 const Qgis::JoinStyle joinStyle = penStyleToJoinStyle( mPen.joinStyle() );
443 const double penWidth = mPen.widthF() <= 0 ? 1 : mPen.widthF();
444 const double miterLimit = mPen.miterLimit();
446 QVector< double > currentX;
447 QVector< double > currentY;
448 const int count = path.elementCount();
451 std::vector< std::unique_ptr< QgsPolygon > > queuedPolygons;
453 for (
int i = 0; i < count; ++i )
455 const QPainterPath::Element &e = path.elementAt( i );
458 case QPainterPath::MoveToElement:
460 if ( currentX.size() > 1 )
462 std::unique_ptr< QgsLineString > line = std::make_unique< QgsLineString >( currentX, currentY );
463 if ( mUsePathStroker )
465 addStrokedLine( line.get(), penWidth, endCapStyle, joinStyle, miterLimit, transformIsIdentity ?
nullptr : &matrix );
467 else if ( line->isClosed() )
469 if ( !transformIsIdentity )
470 line->transform( matrix );
472 if ( mSimplifyTolerance > 0 )
474 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line->simplifyByDistance( mSimplifyTolerance ) ) );
479 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line.release() ) );
484 if ( !transformIsIdentity )
485 line->transform( matrix );
486 if ( mSimplifyTolerance > 0 )
488 mGeometry.
addGeometry( line->simplifyByDistance( mSimplifyTolerance ) );
497 currentX.resize( 0 );
498 currentY.resize( 0 );
500 currentX.reserve( 16 );
501 currentY.reserve( 16 );
507 case QPainterPath::LineToElement:
514 case QPainterPath::CurveToElement:
516 Q_ASSERT( path.elementAt( i + 1 ).type == QPainterPath::CurveToDataElement );
517 Q_ASSERT( path.elementAt( i + 2 ).type == QPainterPath::CurveToDataElement );
519 const double x1 = path.elementAt( i - 1 ).x;
520 const double y1 = path.elementAt( i - 1 ).y;
522 const double x3 = path.elementAt( i + 1 ).x;
523 const double y3 = path.elementAt( i + 1 ).y;
525 const double x4 = path.elementAt( i + 2 ).x;
526 const double y4 = path.elementAt( i + 2 ).y;
535 currentX << bezier->xVector();
536 currentY << bezier->yVector();
541 case QPainterPath::CurveToDataElement:
542 Q_ASSERT( !
"addSubpathGeometries(), bad element type" );
547 if ( currentX.size() > 1 )
549 std::unique_ptr< QgsLineString > line = std::make_unique< QgsLineString >( currentX, currentY );
550 if ( mUsePathStroker )
552 addStrokedLine( line.get(), penWidth, endCapStyle, joinStyle, miterLimit, transformIsIdentity ?
nullptr : &matrix );
554 else if ( line->isClosed() )
556 if ( !transformIsIdentity )
557 line->transform( matrix );
558 if ( mSimplifyTolerance > 0 )
560 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line->simplifyByDistance( mSimplifyTolerance ) ) );
565 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line.release() ) );
570 if ( !transformIsIdentity )
571 line->transform( matrix );
572 if ( mSimplifyTolerance > 0 )
574 mGeometry.
addGeometry( line->simplifyByDistance( mSimplifyTolerance ) );
584 if ( queuedPolygons.empty() )
590 tempMultiPolygon.
reserve(
static_cast< int >( queuedPolygons.size() ) );
591 for (
auto &part : queuedPolygons )
597 QgsGeos geosCollection( &tempMultiPolygon );
602 for (
auto it = g->const_parts_begin(); it != g->const_parts_end(); ++it )
610 const QTransform transform = painter()->combinedTransform();
611 addSubpathGeometries( path, transform );
621 mPaintEngine = std::make_unique<QgsGeometryPaintEngine>( usePathStroker );
627 mPaintEngine->setStrokedPathSegments( segments );
633 mPaintEngine->setSimplificationTolerance( tolerance );
638 return mPaintEngine.get();
649 val =
static_cast< int >( mPaintEngine->geometry().boundingBox().width() );
652 val =
static_cast< int >( mPaintEngine->geometry().boundingBox().height() );
655 val =
static_cast< int >( 25.4 /
qt_defaultDpiX() * mPaintEngine->geometry().boundingBox().width() );
658 val =
static_cast< int >( 25.4 /
qt_defaultDpiY() * mPaintEngine->geometry().boundingBox().height() );
661 case PdmPhysicalDpiX:
665 case PdmPhysicalDpiY:
674 case PdmDevicePixelRatio:
677 case PdmDevicePixelRatioScaled:
678 val =
static_cast< int >( 1 * QPaintDevice::devicePixelRatioFScale() );
682 qWarning(
"QPicture::metric: Invalid metric command" );
689 return mPaintEngine->geometry();
695 QPainter painter( &device );
696 painter.drawPath( path );
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
Abstract base class for all geometries.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
void reserve(int size)
Attempts to allocate memory for at least size geometries.
virtual bool addGeometries(const QVector< QgsAbstractGeometry * > &geometries)
Adds a list of geometries to the collection, transferring ownership to the collection.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int numGeometries() const
Returns the number of geometries within the collection.
A paint device which converts everything renderer to a QgsGeometry representation of the rendered sha...
QgsGeometryPaintDevice(bool usePathStroker=false)
Constructor for QgsGeometryPaintDevice.
void setStrokedPathSegments(int segments)
Sets the number of segments to use when drawing stroked paths with a rounded pen.
int metric(PaintDeviceMetric metric) const override
void setSimplificationTolerance(double tolerance)
Sets a simplification tolerance (in painter units) to use for on-the-fly simplification of geometries...
QPaintEngine * paintEngine() const override
static QgsGeometry painterPathToGeometry(const QPainterPath &path)
Converts a painter path to a QgsGeometry.
const QgsAbstractGeometry & geometry() const
Returns the rendered geometry.
void setSimplificationTolerance(double tolerance)
Sets a simplification tolerance (in painter units) to use for on-the-fly simplification of geometries...
void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags=Qt::AutoColor) final
void drawRects(const QRectF *rects, int rectCount) final
void drawPolygon(const QPointF *points, int pointCount, QPaintEngine::PolygonDrawMode mode) final
void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) final
void drawPoints(const QPointF *points, int pointCount) final
bool begin(QPaintDevice *) final
QgsGeometryPaintEngine(bool usePathStroker=false)
Constructor for QgsGeometryPaintEngine.
void drawLines(const QLineF *lines, int lineCount) final
QPaintEngine::Type type() const final
void drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p) final
void updateState(const QPaintEngineState &) final
void drawPath(const QPainterPath &path) final
void setStrokedPathSegments(int segments)
Sets the number of segments to use when drawing stroked paths with a rounded pen.
A geometry is the spatial representation of a feature.
Does vector analysis using the geos library and handles import, export, exception handling*.
Line string geometry type, with support for z-dimension and m-values.
QgsLineString * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
static QgsLineString * fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
Multi polygon geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Point geometry type, with support for z-dimension and m-values.
Contains geos related utilities and functions.
void drawPointsImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *points, int pointCount)
Q_GUI_EXPORT int qt_defaultDpiX()
void drawRectsImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *rects, int rectCount)
Q_GUI_EXPORT int qt_defaultDpiY()
void drawLinesImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *lines, int lineCount)
void drawPolygonImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *points, int pointCount, QPaintEngine::PolygonDrawMode mode, double simplifyTolerance)
Q_GUI_EXPORT int qt_defaultDpiX()
Q_GUI_EXPORT int qt_defaultDpiY()