void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { if ( mSvgViewBox.isNull() ) { return; } delete mSvgPattern; mSvgPattern = 0; double size = context.outputPixelSize( mPatternWidth ); //don't render pattern if symbol size is below one or above 10,000 pixels if (( int )size < 1.0 || 10000.0 < size ) { mSvgPattern = new QImage(); mBrush.setTextureImage( *mSvgPattern ); } else { bool fitsInCache = true; const QImage& patternImage = QgsSvgCache::instance()->svgAsImage( mSvgFilePath, size, mSvgFillColor, mSvgOutlineColor, mSvgOutlineWidth, context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache ); if ( !fitsInCache ) { const QPicture& patternPict = QgsSvgCache::instance()->svgAsPicture( mSvgFilePath, size, mSvgFillColor, mSvgOutlineColor, mSvgOutlineWidth, context.renderContext().scaleFactor(), 1.0 ); double hwRatio = 1.0; if ( patternPict.width() > 0 ) { hwRatio = ( double )patternPict.height() / ( double )patternPict.width(); } mSvgPattern = new QImage(( int )size, ( int )( size * hwRatio ), QImage::Format_ARGB32_Premultiplied ); mSvgPattern->fill( 0 ); // transparent background QPainter p( mSvgPattern ); p.drawPicture( QPointF( size / 2, size * hwRatio / 2 ), patternPict ); } QTransform brushTransform; brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); if ( !doubleNear( context.alpha(), 1.0 ) ) { QImage transparentImage = fitsInCache ? patternImage.copy() : mSvgPattern->copy(); QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); mBrush.setTextureImage( transparentImage ); } else { mBrush.setTextureImage( fitsInCache ? patternImage : *mSvgPattern ); } mBrush.setTransform( brushTransform ); } if ( mOutline ) { mOutline->startRender( context.renderContext() ); } }
void QgsSimpleMarkerSymbolLayerV2::prepareCache( QgsSymbolV2RenderContext& context ) { double scaledSize = context.outputPixelSize( mSize ); // calculate necessary image size for the cache double pw = (( mPen.widthF() == 0 ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen int imageSize = (( int ) scaledSize + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width double center = (( double ) imageSize / 2 ) + 0.5; // add 1/2 pixel for proper rounding when the figure's coordinates are added mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied ); mCache.fill( 0 ); QPainter p; p.begin( &mCache ); p.setRenderHint( QPainter::Antialiasing ); p.setBrush( mBrush ); p.setPen( mPen ); p.translate( QPointF( center, center ) ); drawMarker( &p, context ); p.end(); // Construct the selected version of the Cache QColor selColor = context.selectionColor(); mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied ); mSelCache.fill( 0 ); p.begin( &mSelCache ); p.setRenderHint( QPainter::Antialiasing ); p.setBrush( mSelBrush ); p.setPen( mSelPen ); p.translate( QPointF( center, center ) ); drawMarker( &p, context ); p.end(); // Check that the selected version is different. If not, then re-render, // filling the background with the selection color and using the normal // colors for the symbol .. could be ugly! if ( mSelCache == mCache ) { p.begin( &mSelCache ); p.setRenderHint( QPainter::Antialiasing ); p.fillRect( 0, 0, imageSize, imageSize, selColor ); p.setBrush( mBrush ); p.setPen( mPen ); p.translate( QPointF( center, center ) ); drawMarker( &p, context ); p.end(); } }
void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { double outlinePixelWidth = context.outputPixelSize( mLineWidth ); double outputPixelDist = context.outputPixelSize( mDistance ); double outputPixelOffset = context.outputPixelSize( mOffset ); //create image int height, width; if ( doubleNear( mLineAngle, 0 ) || doubleNear( mLineAngle, 360 ) || doubleNear( mLineAngle, 90 ) || doubleNear( mLineAngle, 180 ) || doubleNear( mLineAngle, 270 ) ) { height = outputPixelDist; width = height; //width can be set to arbitrary value } else { height = qAbs( outputPixelDist / cos( mLineAngle * M_PI / 180 ) ); //keep perpendicular distance between lines constant width = qAbs( height / tan( mLineAngle * M_PI / 180 ) ); } //depending on the angle, we might need to render into a larger image and use a subset of it int dx = 0; int dy = 0; QImage patternImage( width, height, QImage::Format_ARGB32 ); patternImage.fill( 0 ); QPainter p( &patternImage ); p.setRenderHint( QPainter::Antialiasing, true ); QPen pen( mColor ); pen.setWidthF( outlinePixelWidth ); pen.setCapStyle( Qt::FlatCap ); p.setPen( pen ); QPoint p1, p2, p3, p4, p5, p6; if ( doubleNear( mLineAngle, 0.0 ) || doubleNear( mLineAngle, 360.0 ) || doubleNear( mLineAngle, 180.0 ) ) { p1 = QPoint( 0, height ); p2 = QPoint( width, height ); p3 = QPoint( 0, 0 ); p4 = QPoint( width, 0 ); p5 = QPoint( 0, 2 * height ); p6 = QPoint( width, 2 * height ); } else if ( doubleNear( mLineAngle, 90.0 ) || doubleNear( mLineAngle, 270.0 ) ) { p1 = QPoint( 0, height ); p2 = QPoint( 0, 0 ); p3 = QPoint( width, height ); p4 = QPoint( width, 0 ); p5 = QPoint( -width, height ); p6 = QPoint( -width, 0 ); } else if (( mLineAngle > 0 && mLineAngle < 90 ) || ( mLineAngle > 180 && mLineAngle < 270 ) ) { dx = outputPixelDist * cos(( 90 - mLineAngle ) * M_PI / 180.0 ); dy = outputPixelDist * sin(( 90 - mLineAngle ) * M_PI / 180.0 ); p1 = QPoint( 0, height ); p2 = QPoint( width, 0 ); p3 = QPoint( -dx, height - dy ); p4 = QPoint( width - dx, -dy ); //p4 = QPoint( p3.x() + width, p3.y() - height ); p5 = QPoint( dx, height + dy ); p6 = QPoint( width + dx, dy ); //p6 = QPoint( p5.x() + width, p5.y() - height ); } else if (( mLineAngle < 180 ) || ( mLineAngle > 270 && mLineAngle < 360 ) ) { dy = outputPixelDist * cos(( 180 - mLineAngle ) * M_PI / 180 ); dx = outputPixelDist * sin(( 180 - mLineAngle ) * M_PI / 180 ); p1 = QPoint( width, height ); p2 = QPoint( 0, 0 ); p5 = QPoint( width + dx, height - dy ); p6 = QPoint( p5.x() - width, p5.y() - height ); //p6 = QPoint( dx, -dy ); p3 = QPoint( width - dx, height + dy ); p4 = QPoint( p3.x() - width, p3.y() - height ); //p4 = QPoint( -dx, dy ); } if ( !doubleNear( mOffset, 0.0 ) ) //shift everything { QPointF tempPt; tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p3, outputPixelDist + outputPixelOffset ); p3 = QPoint( tempPt.x(), tempPt.y() ); tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p4, outputPixelDist + outputPixelOffset ); p4 = QPoint( tempPt.x(), tempPt.y() ); tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p5, outputPixelDist - outputPixelOffset ); p5 = QPoint( tempPt.x(), tempPt.y() ); tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p6, outputPixelDist - outputPixelOffset ); p6 = QPoint( tempPt.x(), tempPt.y() ); //update p1, p2 last tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p3, outputPixelOffset ).toPoint(); p1 = QPoint( tempPt.x(), tempPt.y() ); tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p4, outputPixelOffset ).toPoint(); p2 = QPoint( tempPt.x(), tempPt.y() );; } p.drawLine( p1, p2 ); p.drawLine( p3, p4 ); p.drawLine( p5, p6 ); p.end(); //set image to mBrush if ( !doubleNear( context.alpha(), 1.0 ) ) { QImage transparentImage = patternImage.copy(); QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); mBrush.setTextureImage( transparentImage ); } else { mBrush.setTextureImage( patternImage ); } QTransform brushTransform; brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); mBrush.setTransform( brushTransform ); if ( mOutline ) { mOutline->startRender( context.renderContext() ); } }
void QgsPointPatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) { //render 3 rows and columns in one go to easily incorporate displacement double width = context.outputPixelSize( mDistanceX ) * 2.0; double height = context.outputPixelSize( mDistanceY ) * 2.0; QImage patternImage( width, height, QImage::Format_ARGB32 ); patternImage.fill( 0 ); if ( mMarkerSymbol ) { QPainter p( &patternImage ); //marker rendering needs context for drawing on patternImage QgsRenderContext pointRenderContext; pointRenderContext.setPainter( &p ); pointRenderContext.setRasterScaleFactor( 1.0 ); pointRenderContext.setScaleFactor( context.renderContext().scaleFactor() * context.renderContext().rasterScaleFactor() ); QgsMapToPixel mtp( context.renderContext().mapToPixel().mapUnitsPerPixel() / context.renderContext().rasterScaleFactor() ); pointRenderContext.setMapToPixel( mtp ); pointRenderContext.setForceVectorOutput( false ); mMarkerSymbol->setOutputUnit( context.outputUnit() ); mMarkerSymbol->startRender( pointRenderContext ); //render corner points mMarkerSymbol->renderPoint( QPointF( 0, 0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width, 0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( 0, height ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width, height ), context.feature(), pointRenderContext ); //render displaced points double displacementPixelX = context.outputPixelSize( mDisplacementX ); double displacementPixelY = context.outputPixelSize( mDisplacementY ); mMarkerSymbol->renderPoint( QPointF( width / 2.0, -displacementPixelY ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width / 2.0 + displacementPixelX, height / 2.0 - displacementPixelY ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width + displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext ); mMarkerSymbol->renderPoint( QPointF( width / 2.0, height - displacementPixelY ), context.feature(), pointRenderContext ); mMarkerSymbol->stopRender( pointRenderContext ); } if ( !doubleNear( context.alpha(), 1.0 ) ) { QImage transparentImage = patternImage.copy(); QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); mBrush.setTextureImage( transparentImage ); } else { mBrush.setTextureImage( patternImage ); } QTransform brushTransform; brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); mBrush.setTransform( brushTransform ); if ( mOutline ) { mOutline->startRender( context.renderContext() ); } }