QList<QgsLabelFeature*> QgsVectorLayerDiagramProvider::labelFeatures( QgsRenderContext &context ) { if ( !mSource ) { // we have created the provider with "own feature loop" == false // so it is assumed that prepare() has been already called followed by registerFeature() calls return mFeatures; } QSet<QString> attributeNames; if ( !prepare( context, attributeNames ) ) return QList<QgsLabelFeature*>(); QgsRectangle layerExtent = context.extent(); if ( mSettings.coordinateTransform().isValid() ) layerExtent = mSettings.coordinateTransform().transformBoundingBox( context.extent(), QgsCoordinateTransform::ReverseTransform ); QgsFeatureRequest request; request.setFilterRect( layerExtent ); request.setSubsetOfAttributes( attributeNames, mFields ); QgsFeatureIterator fit = mSource->getFeatures( request ); QgsFeature fet; while ( fit.nextFeature( fet ) ) { registerFeature( fet, context ); } return mFeatures; }
void QgsPointDisplacementRenderer::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer ) { mRenderer->startRender( context, vlayer ); //create groups with features that have the same position createDisplacementGroups( const_cast<QgsVectorLayer*>( vlayer ), context.extent() ); printInfoDisplacementGroups(); //just for debugging if ( mLabelAttributeName.isEmpty() ) { mLabelIndex = -1; } else { mLabelIndex = vlayer->fieldNameIndex( mLabelAttributeName ); } if ( mMaxLabelScaleDenominator > 0 && context.rendererScale() > mMaxLabelScaleDenominator ) { mDrawLabels = false; } else { mDrawLabels = true; } if ( mCenterSymbol ) { mCenterSymbol->startRender( context, vlayer ); } }
QgsConstWkbPtr QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkbPtr, bool clipToExtent ) { QgsWKBTypes::Type wkbType = wkbPtr.readHeader(); unsigned int nPoints; wkbPtr >> nPoints; const QgsCoordinateTransform* ct = context.coordinateTransform(); const QgsMapToPixel& mtp = context.mapToPixel(); //apply clipping for large lines to achieve a better rendering performance if ( clipToExtent && nPoints > 1 ) { const QgsRectangle& e = context.extent(); double cw = e.width() / 10; double ch = e.height() / 10; QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch ); wkbPtr -= 1 + 2 * sizeof( int ); wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts ); } else { pts.resize( nPoints ); int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double ); Q_ASSERT( skipZM >= 0 ); QPointF *ptr = pts.data(); for ( unsigned int i = 0; i < nPoints; ++i, ++ptr ) { wkbPtr >> ptr->rx() >> ptr->ry(); wkbPtr += skipZM; } } //transform the QPolygonF to screen coordinates if ( ct ) { ct->transformPolygon( pts ); } QPointF *ptr = pts.data(); for ( int i = 0; i < pts.size(); ++i, ++ptr ) { mtp.transformInPlace( ptr->rx(), ptr->ry() ); } return wkbPtr; }
void QgsMapHitTest::runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, QgsRenderContext& context ) { QgsFeatureRendererV2* r = vl->rendererV2(); bool moreSymbolsPerFeature = r->capabilities() & QgsFeatureRendererV2::MoreSymbolsPerFeature; r->startRender( context, vl->fields() ); QgsFeature f; QgsFeatureRequest request( context.extent() ); request.setFlags( QgsFeatureRequest::ExactIntersect ); QgsFeatureIterator fi = vl->getFeatures( request ); while ( fi.nextFeature( f ) ) { context.expressionContext().setFeature( f ); if ( moreSymbolsPerFeature ) { Q_FOREACH ( QgsSymbolV2* s, r->originalSymbolsForFeature( f, context ) ) usedSymbols.insert( s ); } else usedSymbols.insert( r->originalSymbolForFeature( f, context ) ); } r->stopRender( context ); }
void QgsDecorationNorthArrow::render( const QgsMapSettings &mapSettings, QgsRenderContext &context ) { //Large IF statement controlled by enable checkbox if ( enabled() ) { QSize size( 64, 64 ); QSvgRenderer svg; const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( QStringLiteral( ":/images/north_arrows/default.svg" ), size.width(), mColor, mOutlineColor, 1.0, 1.0 ); svg.load( svgContent ); if ( svg.isValid() ) { double centerXDouble = size.width() / 2.0; double centerYDouble = size.width() / 2.0; //save the current canvas rotation context.painter()->save(); // //work out how to shift the image so that it rotates // properly about its center //(x cos a + y sin a - x, -x sin a + y cos a - y) // // could move this call to somewhere else so that it is only // called when the projection or map extent changes if ( mAutomatic ) { mRotationInt = QgsBearingUtils:: bearingTrueNorth( mapSettings.destinationCrs(), context.extent().center() ); mRotationInt += mapSettings.rotation(); } double myRadiansDouble = mRotationInt * M_PI / 180.0; int xShift = static_cast<int>( ( ( centerXDouble * cos( myRadiansDouble ) ) + ( centerYDouble * sin( myRadiansDouble ) ) ) - centerXDouble ); int yShift = static_cast<int>( ( ( -centerXDouble * sin( myRadiansDouble ) ) + ( centerYDouble * cos( myRadiansDouble ) ) ) - centerYDouble ); // need width/height of paint device int myHeight = context.painter()->device()->height(); int myWidth = context.painter()->device()->width(); //QgsDebugMsg("Rendering north arrow at " + mPlacementLabels.at(mPlacementIndex)); // Set margin according to selected units int myXOffset = 0; int myYOffset = 0; switch ( mMarginUnit ) { case QgsUnitTypes::RenderMillimeters: { int myPixelsInchX = context.painter()->device()->logicalDpiX(); int myPixelsInchY = context.painter()->device()->logicalDpiY(); myXOffset = myPixelsInchX * INCHES_TO_MM * mMarginHorizontal; myYOffset = myPixelsInchY * INCHES_TO_MM * mMarginVertical; break; } case QgsUnitTypes::RenderPixels: myXOffset = mMarginHorizontal - 5; // Minus 5 to shift tight into corner myYOffset = mMarginVertical - 5; break; case QgsUnitTypes::RenderPercentage: myXOffset = ( ( myWidth - size.width() ) / 100. ) * mMarginHorizontal; myYOffset = ( ( myHeight - size.width() ) / 100. ) * mMarginVertical; break; default: // Use default of top left break; } //Determine placement of label from form combo box switch ( mPlacement ) { case BottomLeft: context.painter()->translate( myXOffset, myHeight - myYOffset - size.width() ); break; case TopLeft: context.painter()->translate( myXOffset, myYOffset ); break; case TopRight: context.painter()->translate( myWidth - myXOffset - size.width(), myYOffset ); break; case BottomRight: context.painter()->translate( myWidth - myXOffset - size.width(), myHeight - myYOffset - size.width() ); break; default: { //QgsDebugMsg("Unable to determine where to put north arrow so defaulting to top left"); } } //rotate the canvas by the north arrow rotation amount context.painter()->rotate( mRotationInt ); //Now we can actually do the drawing, and draw a smooth north arrow even when rotated context.painter()->translate( xShift, yShift ); svg.render( context.painter(), QRectF( 0, 0, size.width(), size.height() ) ); //unrotate the canvas again context.painter()->restore(); } else { QFont myQFont( QStringLiteral( "time" ), 12, QFont::Bold ); context.painter()->setFont( myQFont ); context.painter()->setPen( Qt::black ); context.painter()->drawText( 10, 20, tr( "North arrow pixmap not found" ) ); } } }
QgsConstWkbPtr QgsSymbolV2::_getPolygon( QPolygonF &pts, QList<QPolygonF> &holes, QgsRenderContext &context, QgsConstWkbPtr wkbPtr, bool clipToExtent ) { QgsWKBTypes::Type wkbType = wkbPtr.readHeader(); QgsDebugMsg( QString( "wkbType=%1" ).arg( wkbType ) ); unsigned int numRings; wkbPtr >> numRings; if ( numRings == 0 ) // sanity check for zero rings in polygon return wkbPtr; holes.clear(); const QgsCoordinateTransform* ct = context.coordinateTransform(); const QgsMapToPixel& mtp = context.mapToPixel(); const QgsRectangle& e = context.extent(); double cw = e.width() / 10; double ch = e.height() / 10; QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch ); int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double ); Q_ASSERT( skipZM >= 0 ); for ( unsigned int idx = 0; idx < numRings; idx++ ) { unsigned int nPoints; wkbPtr >> nPoints; QPolygonF poly( nPoints ); QPointF *ptr = poly.data(); for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr ) { wkbPtr >> ptr->rx() >> ptr->ry(); wkbPtr += skipZM; } if ( nPoints < 1 ) continue; //clip close to view extent, if needed QRectF ptsRect = poly.boundingRect(); if ( clipToExtent && !context.extent().contains( ptsRect ) ) { QgsClipper::trimPolygon( poly, clipRect ); } //transform the QPolygonF to screen coordinates if ( ct ) { ct->transformPolygon( poly ); } ptr = poly.data(); for ( int i = 0; i < poly.size(); ++i, ++ptr ) { mtp.transformInPlace( ptr->rx(), ptr->ry() ); } if ( idx == 0 ) pts = poly; else holes.append( poly ); } return wkbPtr; }
void QgsDecorationNorthArrow::render( const QgsMapSettings &mapSettings, QgsRenderContext &context ) { if ( !enabled() ) return; double maxLength = mSize * mapSettings.outputDpi() / 25.4; QSvgRenderer svg; const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( svgPath(), maxLength, mColor, mOutlineColor, 1.0, 1.0 ); svg.load( svgContent ); if ( svg.isValid() ) { QSize size( maxLength, maxLength ); QRectF viewBox = svg.viewBoxF(); if ( viewBox.height() > viewBox.width() ) { size.setWidth( maxLength * viewBox.width() / viewBox.height() ); } else { size.setHeight( maxLength * viewBox.height() / viewBox.width() ); } double centerXDouble = size.width() / 2.0; double centerYDouble = size.height() / 2.0; //save the current canvas rotation context.painter()->save(); // //work out how to shift the image so that it rotates // properly about its center //(x cos a + y sin a - x, -x sin a + y cos a - y) // // could move this call to somewhere else so that it is only // called when the projection or map extent changes if ( mAutomatic ) { try { mRotationInt = QgsBearingUtils:: bearingTrueNorth( mapSettings.destinationCrs(), mapSettings.transformContext(), context.extent().center() ); } catch ( QgsException & ) { mRotationInt = 0.0; } mRotationInt += mapSettings.rotation(); } double radiansDouble = mRotationInt * M_PI / 180.0; int xShift = static_cast<int>( ( ( centerXDouble * std::cos( radiansDouble ) ) + ( centerYDouble * std::sin( radiansDouble ) ) ) - centerXDouble ); int yShift = static_cast<int>( ( ( -centerXDouble * std::sin( radiansDouble ) ) + ( centerYDouble * std::cos( radiansDouble ) ) ) - centerYDouble ); // need width/height of paint device int deviceHeight = context.painter()->device()->height(); int deviceWidth = context.painter()->device()->width(); // Set margin according to selected units int xOffset = 0; int yOffset = 0; switch ( mMarginUnit ) { case QgsUnitTypes::RenderMillimeters: { int pixelsInchX = context.painter()->device()->logicalDpiX(); int pixelsInchY = context.painter()->device()->logicalDpiY(); xOffset = pixelsInchX * INCHES_TO_MM * mMarginHorizontal; yOffset = pixelsInchY * INCHES_TO_MM * mMarginVertical; break; } case QgsUnitTypes::RenderPixels: xOffset = mMarginHorizontal - 5; // Minus 5 to shift tight into corner yOffset = mMarginVertical - 5; break; case QgsUnitTypes::RenderPercentage: xOffset = ( ( deviceWidth - size.width() ) / 100. ) * mMarginHorizontal; yOffset = ( ( deviceHeight - size.width() ) / 100. ) * mMarginVertical; break; case QgsUnitTypes::RenderMapUnits: case QgsUnitTypes::RenderPoints: case QgsUnitTypes::RenderInches: case QgsUnitTypes::RenderUnknownUnit: case QgsUnitTypes::RenderMetersInMapUnits: break; } //Determine placement of label from form combo box switch ( mPlacement ) { case BottomLeft: context.painter()->translate( xOffset, deviceHeight - yOffset - maxLength + ( maxLength - size.height() ) / 2 ); break; case TopLeft: context.painter()->translate( xOffset, yOffset ); break; case TopRight: context.painter()->translate( deviceWidth - xOffset - maxLength + ( maxLength - size.width() ) / 2, yOffset ); break; case BottomRight: context.painter()->translate( deviceWidth - xOffset - maxLength + ( maxLength - size.width() ) / 2, deviceHeight - yOffset - maxLength + ( maxLength - size.height() ) / 2 ); break; } //rotate the canvas by the north arrow rotation amount context.painter()->rotate( mRotationInt ); //Now we can actually do the drawing, and draw a smooth north arrow even when rotated context.painter()->translate( xShift, yShift ); svg.render( context.painter(), QRectF( 0, 0, size.width(), size.height() ) ); //unrotate the canvas again context.painter()->restore(); } }
QgsRasterLayerRenderer::QgsRasterLayerRenderer( QgsRasterLayer* layer, QgsRenderContext& rendererContext ) : QgsMapLayerRenderer( layer->id() ) , mRasterViewPort( nullptr ) , mPipe( nullptr ) { mPainter = rendererContext.painter(); const QgsMapToPixel& theQgsMapToPixel = rendererContext.mapToPixel(); mMapToPixel = &theQgsMapToPixel; QgsMapToPixel mapToPixel = theQgsMapToPixel; if ( mapToPixel.mapRotation() ) { // unset rotation for the sake of local computations. // Rotation will be handled by QPainter later // TODO: provide a method of QgsMapToPixel to fetch map center // in geographical units QgsPoint center = mapToPixel.toMapCoordinates( mapToPixel.mapWidth() / 2.0, mapToPixel.mapHeight() / 2.0 ); mapToPixel.setMapRotation( 0, center.x(), center.y() ); } QgsRectangle myProjectedViewExtent; QgsRectangle myProjectedLayerExtent; if ( rendererContext.coordinateTransform() ) { QgsDebugMsg( "coordinateTransform set -> project extents." ); try { myProjectedViewExtent = rendererContext.coordinateTransform()->transformBoundingBox( rendererContext.extent() ); } catch ( QgsCsException &cs ) { QgsMessageLog::logMessage( QObject::tr( "Could not reproject view extent: %1" ).arg( cs.what() ), QObject::tr( "Raster" ) ); myProjectedViewExtent.setMinimal(); } try { myProjectedLayerExtent = rendererContext.coordinateTransform()->transformBoundingBox( layer->extent() ); } catch ( QgsCsException &cs ) { QgsMessageLog::logMessage( QObject::tr( "Could not reproject layer extent: %1" ).arg( cs.what() ), QObject::tr( "Raster" ) ); myProjectedLayerExtent.setMinimal(); } } else { QgsDebugMsg( "coordinateTransform not set" ); myProjectedViewExtent = rendererContext.extent(); myProjectedLayerExtent = layer->extent(); } // clip raster extent to view extent QgsRectangle myRasterExtent = myProjectedViewExtent.intersect( &myProjectedLayerExtent ); if ( myRasterExtent.isEmpty() ) { QgsDebugMsg( "draw request outside view extent." ); // nothing to do return; } QgsDebugMsg( "theViewExtent is " + rendererContext.extent().toString() ); QgsDebugMsg( "myProjectedViewExtent is " + myProjectedViewExtent.toString() ); QgsDebugMsg( "myProjectedLayerExtent is " + myProjectedLayerExtent.toString() ); QgsDebugMsg( "myRasterExtent is " + myRasterExtent.toString() ); // // The first thing we do is set up the QgsRasterViewPort. This struct stores all the settings // relating to the size (in pixels and coordinate system units) of the raster part that is // in view in the map window. It also stores the origin. // //this is not a class level member because every time the user pans or zooms //the contents of the rasterViewPort will change mRasterViewPort = new QgsRasterViewPort(); mRasterViewPort->mDrawnExtent = myRasterExtent; if ( rendererContext.coordinateTransform() ) { mRasterViewPort->mSrcCRS = layer->crs(); mRasterViewPort->mDestCRS = rendererContext.coordinateTransform()->destCRS(); mRasterViewPort->mSrcDatumTransform = rendererContext.coordinateTransform()->sourceDatumTransform(); mRasterViewPort->mDestDatumTransform = rendererContext.coordinateTransform()->destinationDatumTransform(); } else { mRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid mRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid mRasterViewPort->mSrcDatumTransform = -1; mRasterViewPort->mDestDatumTransform = -1; } // get dimensions of clipped raster image in device coordinate space (this is the size of the viewport) mRasterViewPort->mTopLeftPoint = mapToPixel.transform( myRasterExtent.xMinimum(), myRasterExtent.yMaximum() ); mRasterViewPort->mBottomRightPoint = mapToPixel.transform( myRasterExtent.xMaximum(), myRasterExtent.yMinimum() ); // align to output device grid, i.e. floor/ceil to integers // TODO: this should only be done if paint device is raster - screen, image // for other devices (pdf) it can have floating point origin // we could use floating point for raster devices as well, but respecting the // output device grid should make it more effective as the resampling is done in // the provider anyway mRasterViewPort->mTopLeftPoint.setX( floor( mRasterViewPort->mTopLeftPoint.x() ) ); mRasterViewPort->mTopLeftPoint.setY( floor( mRasterViewPort->mTopLeftPoint.y() ) ); mRasterViewPort->mBottomRightPoint.setX( ceil( mRasterViewPort->mBottomRightPoint.x() ) ); mRasterViewPort->mBottomRightPoint.setY( ceil( mRasterViewPort->mBottomRightPoint.y() ) ); // recalc myRasterExtent to aligned values myRasterExtent.set( mapToPixel.toMapCoordinatesF( mRasterViewPort->mTopLeftPoint.x(), mRasterViewPort->mBottomRightPoint.y() ), mapToPixel.toMapCoordinatesF( mRasterViewPort->mBottomRightPoint.x(), mRasterViewPort->mTopLeftPoint.y() ) ); //raster viewport top left / bottom right are already rounded to int mRasterViewPort->mWidth = static_cast<int>( mRasterViewPort->mBottomRightPoint.x() - mRasterViewPort->mTopLeftPoint.x() ); mRasterViewPort->mHeight = static_cast<int>( mRasterViewPort->mBottomRightPoint.y() - mRasterViewPort->mTopLeftPoint.y() ); //the drawable area can start to get very very large when you get down displaying 2x2 or smaller, this is becasue //mapToPixel.mapUnitsPerPixel() is less then 1, //so we will just get the pixel data and then render these special cases differently in paintImageToCanvas() QgsDebugMsgLevel( QString( "mapUnitsPerPixel = %1" ).arg( mapToPixel.mapUnitsPerPixel() ), 3 ); QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( layer->width() ), 3 ); QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( layer->height() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.xMinimum() = %1" ).arg( myRasterExtent.xMinimum() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.xMaximum() = %1" ).arg( myRasterExtent.xMaximum() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.yMinimum() = %1" ).arg( myRasterExtent.yMinimum() ), 3 ); QgsDebugMsgLevel( QString( "myRasterExtent.yMaximum() = %1" ).arg( myRasterExtent.yMaximum() ), 3 ); QgsDebugMsgLevel( QString( "mTopLeftPoint.x() = %1" ).arg( mRasterViewPort->mTopLeftPoint.x() ), 3 ); QgsDebugMsgLevel( QString( "mBottomRightPoint.x() = %1" ).arg( mRasterViewPort->mBottomRightPoint.x() ), 3 ); QgsDebugMsgLevel( QString( "mTopLeftPoint.y() = %1" ).arg( mRasterViewPort->mTopLeftPoint.y() ), 3 ); QgsDebugMsgLevel( QString( "mBottomRightPoint.y() = %1" ).arg( mRasterViewPort->mBottomRightPoint.y() ), 3 ); QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( mRasterViewPort->mWidth ), 3 ); QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( mRasterViewPort->mHeight ), 3 ); // /\/\/\ - added to handle zoomed-in rasters // TODO R->mLastViewPort = *mRasterViewPort; // TODO: is it necessary? Probably WMS only? layer->dataProvider()->setDpi( rendererContext.rasterScaleFactor() * 25.4 * rendererContext.scaleFactor() ); // copy the whole raster pipe! mPipe = new QgsRasterPipe( *layer->pipe() ); }
void QgsPalLabeling::drawLabeling( QgsRenderContext& context ) { Q_ASSERT( mMapRenderer != NULL ); QPainter* painter = context.painter(); QgsRectangle extent = context.extent(); if ( mLabelSearchTree ) { mLabelSearchTree->clear(); } QTime t; t.start(); // do the labeling itself double scale = mMapRenderer->scale(); // scale denominator QgsRectangle r = extent; double bbox[] = { r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum() }; std::list<LabelPosition*>* labels; pal::Problem* problem; try { problem = mPal->extractProblem( scale, bbox ); } catch ( std::exception& e ) { Q_UNUSED( e ); QgsDebugMsg( "PAL EXCEPTION :-( " + QString::fromLatin1( e.what() ) ); //mActiveLayers.clear(); // clean up return; } const QgsMapToPixel* xform = mMapRenderer->coordinateTransform(); // draw rectangles with all candidates // this is done before actual solution of the problem // before number of candidates gets reduced mCandidates.clear(); if ( mShowingCandidates && problem ) { painter->setPen( QColor( 0, 0, 0, 64 ) ); painter->setBrush( Qt::NoBrush ); for ( int i = 0; i < problem->getNumFeatures(); i++ ) { for ( int j = 0; j < problem->getFeatureCandidateCount( i ); j++ ) { pal::LabelPosition* lp = problem->getFeatureCandidate( i, j ); drawLabelCandidateRect( lp, painter, xform ); } } } // find the solution labels = mPal->solveProblem( problem, mShowingAllLabels ); QgsDebugMsg( QString( "LABELING work: %1 ms ... labels# %2" ).arg( t.elapsed() ).arg( labels->size() ) ); t.restart(); painter->setRenderHint( QPainter::Antialiasing ); // draw the labels std::list<LabelPosition*>::iterator it = labels->begin(); for ( ; it != labels->end(); ++it ) { QgsPalGeometry* palGeometry = dynamic_cast< QgsPalGeometry* >(( *it )->getFeaturePart()->getUserGeometry() ); if ( !palGeometry ) { continue; } //layer names QString layerNameUtf8 = QString::fromUtf8(( *it )->getLayerName() ); if ( palGeometry->isDiagram() ) { //render diagram QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dit = mActiveDiagramLayers.begin(); for ( dit = mActiveDiagramLayers.begin(); dit != mActiveDiagramLayers.end(); ++dit ) { if ( dit.key() && dit.key()->id().append( "d" ) == layerNameUtf8 ) { QgsPoint outPt = xform->transform(( *it )->getX(), ( *it )->getY() ); dit.value().renderer->renderDiagram( palGeometry->diagramAttributes(), context, QPointF( outPt.x(), outPt.y() ) ); } } //insert into label search tree to manipulate position interactively if ( mLabelSearchTree ) { //for diagrams, remove the additional 'd' at the end of the layer id QString layerId = layerNameUtf8; layerId.chop( 1 ); mLabelSearchTree->insertLabel( *it, QString( palGeometry->strId() ).toInt(), layerId, true ); } continue; } const QgsPalLayerSettings& lyr = layer( layerNameUtf8 ); QFont fontForLabel = lyr.textFont; QColor fontColor = lyr.textColor; double bufferSize = lyr.bufferSize; QColor bufferColor = lyr.bufferColor; //apply data defined settings for the label //font size QVariant dataDefinedSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Size ); if ( dataDefinedSize.isValid() ) { fontForLabel.setPixelSize( lyr.sizeToPixel( dataDefinedSize.toDouble(), context ) ); } //font color QVariant dataDefinedColor = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Color ); if ( dataDefinedColor.isValid() ) { fontColor.setNamedColor( dataDefinedColor.toString() ); if ( !fontColor.isValid() ) { fontColor = lyr.textColor; } } //font bold QVariant dataDefinedBold = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Bold ); if ( dataDefinedBold.isValid() ) { fontForLabel.setBold(( bool )dataDefinedBold.toInt() ); } //font italic QVariant dataDefinedItalic = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Italic ); if ( dataDefinedItalic.isValid() ) { fontForLabel.setItalic(( bool ) dataDefinedItalic.toInt() ); } //font underline QVariant dataDefinedUnderline = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Underline ); if ( dataDefinedUnderline.isValid() ) { fontForLabel.setUnderline(( bool ) dataDefinedUnderline.toInt() ); } //font strikeout QVariant dataDefinedStrikeout = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Strikeout ); if ( dataDefinedStrikeout.isValid() ) { fontForLabel.setStrikeOut(( bool ) dataDefinedStrikeout.toInt() ); } //font family QVariant dataDefinedFontFamily = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Family ); if ( dataDefinedFontFamily.isValid() ) { fontForLabel.setFamily( dataDefinedFontFamily.toString() ); } //buffer size QVariant dataDefinedBufferSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::BufferSize ); if ( dataDefinedBufferSize.isValid() ) { bufferSize = dataDefinedBufferSize.toDouble(); } //buffer color QVariant dataDefinedBufferColor = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::BufferColor ); if ( dataDefinedBufferColor.isValid() ) { bufferColor.setNamedColor( dataDefinedBufferColor.toString() ); if ( !bufferColor.isValid() ) { bufferColor = lyr.bufferColor; } } if ( lyr.bufferSize != 0 ) drawLabel( *it, painter, fontForLabel, fontColor, xform, bufferSize, bufferColor, true ); drawLabel( *it, painter, fontForLabel, fontColor, xform ); if ( mLabelSearchTree ) { mLabelSearchTree->insertLabel( *it, QString( palGeometry->strId() ).toInt(), ( *it )->getLayerName() ); } } QgsDebugMsg( QString( "LABELING draw: %1 ms" ).arg( t.elapsed() ) ); delete problem; delete labels; // delete all allocated geometries for features QHash<QgsVectorLayer*, QgsPalLayerSettings>::iterator lit; for ( lit = mActiveLayers.begin(); lit != mActiveLayers.end(); ++lit ) { QgsPalLayerSettings& lyr = lit.value(); for ( QList<QgsPalGeometry*>::iterator git = lyr.geometries.begin(); git != lyr.geometries.end(); ++git ) delete *git; lyr.geometries.clear(); } //delete all allocated geometries for diagrams QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dIt = mActiveDiagramLayers.begin(); for ( ; dIt != mActiveDiagramLayers.end(); ++dIt ) { QgsDiagramLayerSettings& dls = dIt.value(); for ( QList<QgsPalGeometry*>::iterator git = dls.geometries.begin(); git != dls.geometries.end(); ++git ) { delete *git; } dls.geometries.clear(); } }