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 );
 
 
  620  mPaintEngine = std::make_unique<QgsGeometryPaintEngine>( usePathStroker );
 
 
  626    mPaintEngine->setStrokedPathSegments( segments );
 
 
  632    mPaintEngine->setSimplificationTolerance( tolerance );
 
 
  637  return mPaintEngine.get();
 
 
  648      val = 
static_cast< int >( mPaintEngine->geometry().boundingBox().width() );
 
  651      val = 
static_cast< int >( mPaintEngine->geometry().boundingBox().height() );
 
  654      val = 
static_cast< int >( 25.4 / 
qt_defaultDpiX() * mPaintEngine->geometry().boundingBox().width() );
 
  657      val = 
static_cast< int >( 25.4 / 
qt_defaultDpiY() * mPaintEngine->geometry().boundingBox().height() );
 
  660    case PdmPhysicalDpiX:
 
  664    case PdmPhysicalDpiY:
 
  673    case PdmDevicePixelRatio:
 
  676    case PdmDevicePixelRatioScaled:
 
  677      val = 
static_cast< int >( 1 * QPaintDevice::devicePixelRatioFScale() );
 
  681      qWarning( 
"QPicture::metric: Invalid metric command" );
 
 
  688  return mPaintEngine->geometry();
 
 
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.
 
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.
 
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
 
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.
 
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()