void QgsComposerLegend::drawPolygonSymbol( QPainter* p, QgsSymbol* s, double currentYCoord, double& currentXPosition, int opacity ) const { if ( !s ) { return; } if ( p ) { //scale brush and set transparencies QBrush symbolBrush = s->brush(); QColor brushColor = symbolBrush.color(); brushColor.setAlpha( opacity ); symbolBrush.setColor( brushColor ); QPaintDevice* paintDevice = p->device(); if ( paintDevice ) { double rasterScaleFactor = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4; QgsRenderer::scaleBrush( symbolBrush, rasterScaleFactor ); } p->setBrush( symbolBrush ); QPen symbolPen = s->pen(); QColor penColor = symbolPen.color(); penColor.setAlpha( opacity ); symbolPen.setColor( penColor ); p->setPen( symbolPen ); p->drawRect( QRectF( currentXPosition, currentYCoord, mSymbolWidth, mSymbolHeight ) ); } currentXPosition += mSymbolWidth; }
void QgsComposerArrow::drawLine( QPainter *painter ) { if ( ! mLineSymbol || ! mComposition ) { return; } QPaintDevice* thePaintDevice = painter->device(); painter->save(); //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = thePaintDevice->logicalDpiX() / 25.4; painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); //scale painter from mm to dots //setup render context QgsMapSettings ms = mComposition->mapSettings(); //context units should be in dots ms.setOutputDpi( painter->device()->logicalDpiX() ); QgsRenderContext context = QgsRenderContext::fromMapSettings( ms ); context.setForceVectorOutput( true ); context.setPainter( painter ); QgsExpressionContext expressionContext = createExpressionContext(); context.setExpressionContext( expressionContext ); //line scaled to dots QPolygonF line; line << QPointF( mStartPoint.x() - pos().x(), mStartPoint.y() - pos().y() ) * dotsPerMM << QPointF( mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y() ) * dotsPerMM; mLineSymbol->startRender( context ); mLineSymbol->renderPolyline( line, nullptr, context ); mLineSymbol->stopRender( context ); painter->restore(); }
void QgsMapRendererCustomPainterJob::start() { if ( isActive() ) return; mRenderingStart.start(); mActive = true; mErrors.clear(); QgsDebugMsg( "QPAINTER run!" ); QgsDebugMsg( "Preparing list of layer jobs for rendering" ); QTime prepareTime; prepareTime.start(); // clear the background mPainter->fillRect( 0, 0, mSettings.outputSize().width(), mSettings.outputSize().height(), mSettings.backgroundColor() ); mPainter->setRenderHint( QPainter::Antialiasing, mSettings.testFlag( QgsMapSettings::Antialiasing ) ); QPaintDevice* thePaintDevice = mPainter->device(); QString errMsg = QString( "pre-set DPI not equal to painter's DPI (%1 vs %2)" ).arg( thePaintDevice->logicalDpiX() ).arg( mSettings.outputDpi() ); Q_ASSERT_X( thePaintDevice->logicalDpiX() == mSettings.outputDpi(), "Job::startRender()", errMsg.toAscii().data() ); delete mLabelingEngine; mLabelingEngine = 0; if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) ) { mLabelingEngine = new QgsPalLabeling; mLabelingEngine->loadEngineSettings(); mLabelingEngine->init( mSettings ); } mLayerJobs = prepareJobs( mPainter, mLabelingEngine ); QgsDebugMsg( "Rendering prepared in (seconds): " + QString( "%1" ).arg( prepareTime.elapsed() / 1000.0 ) ); // now we are ready to start rendering! if ( !mLayerJobs.isEmpty() ) { connect( &mFutureWatcher, SIGNAL( finished() ), SLOT( futureFinished() ) ); mFuture = QtConcurrent::run( staticRender, this ); mFutureWatcher.setFuture( mFuture ); } else { // just make sure we will clean up and emit finished() signal QTimer::singleShot( 0, this, SLOT( futureFinished() ) ); } }
void QgsMapRendererCustomPainterJob::start() { if ( isActive() ) return; mRenderingStart.start(); mActive = true; mErrors.clear(); QgsDebugMsg( "QPAINTER run!" ); QgsDebugMsg( "Preparing list of layer jobs for rendering" ); QTime prepareTime; prepareTime.start(); // clear the background mPainter->fillRect( 0, 0, mSettings.outputSize().width(), mSettings.outputSize().height(), mSettings.backgroundColor() ); mPainter->setRenderHint( QPainter::Antialiasing, mSettings.testFlag( QgsMapSettings::Antialiasing ) ); #ifndef QT_NO_DEBUG QPaintDevice* thePaintDevice = mPainter->device(); QString errMsg = QStringLiteral( "pre-set DPI not equal to painter's DPI (%1 vs %2)" ).arg( thePaintDevice->logicalDpiX() ).arg( mSettings.outputDpi() ); Q_ASSERT_X( qgsDoubleNear( thePaintDevice->logicalDpiX(), mSettings.outputDpi() ), "Job::startRender()", errMsg.toLatin1().data() ); #endif delete mLabelingEngineV2; mLabelingEngineV2 = nullptr; if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) ) { mLabelingEngineV2 = new QgsLabelingEngine(); mLabelingEngineV2->readSettingsFromProject(); mLabelingEngineV2->setMapSettings( mSettings ); } mLayerJobs = prepareJobs( mPainter, mLabelingEngineV2 ); QgsDebugMsg( "Rendering prepared in (seconds): " + QString( "%1" ).arg( prepareTime.elapsed() / 1000.0 ) ); if ( mRenderSynchronously ) { // do the rendering right now! doRender(); return; } // now we are ready to start rendering! connect( &mFutureWatcher, SIGNAL( finished() ), SLOT( futureFinished() ) ); mFuture = QtConcurrent::run( staticRender, this ); mFutureWatcher.setFuture( mFuture ); }
void printerStream::printPixmap(const QPixmap &pm, bool newLine) { #if 0 QPaintDevice *dev = pr.device(); if (fwbdebug) { qDebug("printPixmap: width=%d height=%d", pm.width(), pm.height()); qDebug("printPixmap: printer->resolution()=%d", printer->resolution()); if (dev) { qDebug("printPixmap: device parameters:"); qDebug(" height=%d width=%d", dev->height(), dev->width()); qDebug(" logicalDpiY=%d logicalDpiX=%d", dev->logicalDpiY(), dev->logicalDpiX()); qDebug(" physicalDpiY=%d physicalDpiX=%d", dev->physicalDpiY(), dev->physicalDpiX()); } } #endif int target_w = (int)(pm.width() * pixmap_scaling_ratio); int target_h = (int)(pm.height() * pixmap_scaling_ratio); int pmYOffset = 0; while ( getYSpace()<(pm.height()-pmYOffset) ) { int yFrag = pageBody.height() - yPos; if (pageNo>=fromPage && pageNo<=toPage) { if (fwbdebug) qDebug("Print pixmap 1: yPos=%d pmYOffset=%d " "yFrag=%d target_w=%d target_h=%d", yPos, pmYOffset, yFrag, target_w, target_h); pr.drawPixmap(xmargin, yPos, target_w, target_h, pm, 0, pmYOffset, -1, yFrag); } pmYOffset = pmYOffset + yFrag; flushPage(); beginPage(); // resets yPos } if (pageNo>=fromPage && pageNo<=toPage) { if (fwbdebug) qDebug("Print pixmap 2: yPos=%d pmYOffset=%d target_w=%d target_h=%d", yPos, pmYOffset, target_w, target_h); pr.drawPixmap(xmargin, yPos, target_w, target_h, pm, 0, pmYOffset, -1, -1); } if (newLine) yPos = yPos + (target_h - pmYOffset); }
int Global::dpi() { if (m_dpi > 0) return m_dpi; QImage texImage(100, 100, QImage::Format_ARGB32); QPainter p(&texImage); QPaintDevice *pd = p.device(); m_dpi = pd->logicalDpiX(); return m_dpi; }
/// <summary> /// Start rendering. /// </summary> /// <param name="painter">The painter.</param> /// <param name="forceWidthScale">Force a specific scale factor for line widths and marker sizes.</param> void GRRenderer::render( QPainter* painter, double *forceWidthScale /*= 0 */ ) { QMutexLocker renderLock( &mRenderMutex ); qDebug() << "=====Rendering========="; QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { qDebug() << "already rendering!"; QCoreApplication::processEvents(); } if ( mDrawing ) { qDebug() << "still rendering - skipping"; return; } mDrawing = true; GRCoordinateTransform* ct; if ( mOverview ) { // mRenderContext.setDrawEditingInformation(!mOverview); } mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); mRenderContext.setRenderingStopped( false ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == GRRenderer::Millimeters ) { if ( forceWidthScale ) { scaleFactor = *forceWidthScale; } else { scaleFactor = sceneDpi / 25.4; } } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; // need to finish................. }
int QgsDiagramRendererV2::dpiPaintDevice( const QPainter* painter ) { if ( painter ) { QPaintDevice* device = painter->device(); if ( device ) { return device->logicalDpiX(); } } return -1; }
void QgsComposerLegend::drawPointSymbol( QPainter* p, QgsSymbol* s, double currentYCoord, double& currentXPosition, double& symbolHeight, int opacity ) const { if ( !s ) { return; } QImage pointImage; double rasterScaleFactor = 1.0; if ( p ) { QPaintDevice* paintDevice = p->device(); if ( !paintDevice ) { return; } rasterScaleFactor = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4; } //width scale is 1.0 pointImage = s->getPointSymbolAsImage( 1.0, false, Qt::yellow, 1.0, 0.0, rasterScaleFactor, opacity / 255.0 ); if ( p ) { p->save(); p->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); QPointF imageTopLeft( currentXPosition * rasterScaleFactor, currentYCoord * rasterScaleFactor ); p->drawImage( imageTopLeft, pointImage ); p->restore(); } currentXPosition += s->pointSize(); //pointImage.width() / rasterScaleFactor; symbolHeight = s->pointSize(); //pointImage.height() / rasterScaleFactor; }
void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) { //Lock render method for concurrent threads (e.g. from globe) QMutexLocker renderLock( &mRenderMutex ); //flag to see if the render context has changed //since the last time we rendered. If it hasnt changed we can //take some shortcuts with rendering bool mySameAsLastFlag = true; QgsDebugMsg( "========== Rendering ==========" ); if ( mExtent.isEmpty() ) { QgsDebugMsg( "empty extent... not rendering" ); return; } if ( mSize.width() == 1 && mSize.height() == 1 ) { QgsDebugMsg( "size 1x1... not rendering" ); return; } QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { QgsDebugMsg( "already rendering" ); QCoreApplication::processEvents(); } if ( mDrawing ) { QgsDebugMsg( "still rendering - skipping" ); return; } mDrawing = true; const QgsCoordinateTransform *ct; #ifdef QGISDEBUG QgsDebugMsg( "Starting to render layer stack." ); QTime renderTime; renderTime.start(); #endif if ( mOverview ) mRenderContext.setDrawEditingInformation( !mOverview ); mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); //this flag is only for stopping during the current rendering progress, //so must be false at every new render operation mRenderContext.setRenderingStopped( false ); // set selection color QgsProject* prj = QgsProject::instance(); int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 ); int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 ); int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 ); int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 ); mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == QgsMapRenderer::Millimeters ) { if ( forceWidthScale ) { scaleFactor = *forceWidthScale; } else { scaleFactor = sceneDpi / 25.4; } } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) { mRenderContext.setRasterScaleFactor( rasterScaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); mySameAsLastFlag = false; } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; mySameAsLastFlag = false; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( this ); // know we know if this render is just a repeat of the last time, we // can clear caches if it has changed if ( !mySameAsLastFlag ) { //clear the cache pixmap if we changed resolution / extent QSettings mySettings; if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { QgsMapLayerRegistry::instance()->clearAllLayerCaches(); } } // render all layers in the stack, starting at the base QListIterator<QString> li( mLayerSet ); li.toBack(); QgsRectangle r1, r2; while ( li.hasPrevious() ) { if ( mRenderContext.renderingStopped() ) { break; } // Store the painter in case we need to swap it out for the // cache painter QPainter * mypContextPainter = mRenderContext.painter(); // Flattened image for drawing when a blending mode is set QImage * mypFlattenedImage = 0; QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); // This call is supposed to cause the progress bar to // advance. However, it seems that updating the progress bar is // incompatible with having a QPainter active (the one that is // passed into this function), as Qt produces a number of errors // when try to do so. I'm (Gavin) not sure how to fix this, but // added these comments and debug statement to help others... QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" ); //emit drawingProgress(myRenderCounter++, mLayerSet.size()); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { QgsDebugMsg( "Layer not found in registry!" ); continue; } QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" ) .arg( ml->name() ) .arg( ml->minimumScale() ) .arg( ml->maximumScale() ) .arg( ml->hasScaleBasedVisibility() ) .arg( ml->extent().toString() ) .arg( ml->blendMode() ) ); if ( mRenderContext.useAdvancedEffects() ) { // Set the QPainter composition mode so that this layer is rendered using // the desired blending mode mypContextPainter->setCompositionMode( ml->blendMode() ); } if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview ) { connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); // // Now do the call to the layer that actually does // the rendering work! // bool split = false; if ( hasCrsTransformEnabled() ) { r1 = mExtent; split = splitLayersExtent( ml, r1, r2 ); ct = transformation( ml ); mRenderContext.setExtent( r1 ); QgsDebugMsg( " extent 1: " + r1.toString() ); QgsDebugMsg( " extent 2: " + r2.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer { continue; } } else { ct = NULL; } mRenderContext.setCoordinateTransform( ct ); //decide if we have to scale the raster //this is necessary in case QGraphicsScene is used bool scaleRaster = false; QgsMapToPixel rasterMapToPixel; QgsMapToPixel bk_mapToPixel; if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 ) { scaleRaster = true; } // Force render of layers that are being edited // or if there's a labeling engine that needs the layer to register features if ( ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->isEditable() || ( mRenderContext.labelingEngine() && mRenderContext.labelingEngine()->willUseLayer( vl ) ) ) { ml->setCacheImage( 0 ); } } QSettings mySettings; bool useRenderCaching = false; if ( ! split )//render caching does not yet cater for split extents { if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { useRenderCaching = true; if ( !mySameAsLastFlag || ml->cacheImage() == 0 ) { QgsDebugMsg( "Caching enabled but layer redraw forced by extent change or empty cache" ); QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); if ( mypImage->isNull() ) { QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) ); emit drawError( ml ); painter->end(); // drawError is not caught by anyone, so we end painting to notify caller return; } mypImage->fill( 0 ); ml->setCacheImage( mypImage ); //no need to delete the old one, maplayer does it for you QPainter * mypPainter = new QPainter( ml->cacheImage() ); // Changed to enable anti aliasing by default in QGIS 1.7 if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mRenderContext.setPainter( mypPainter ); } else if ( mySameAsLastFlag ) { //draw from cached image QgsDebugMsg( "Caching enabled --- drawing layer from cached image" ); mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); //short circuit as there is nothing else to do... continue; } } } // If we are drawing with an alternative blending mode then we need to render to a separate image // before compositing this on the map. This effectively flattens the layer and prevents // blending occuring between objects on the layer // (this is not required for raster layers or when layer caching is enabled, since that has the same effect) bool flattenedLayer = false; if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if (( !useRenderCaching ) && (( vl->blendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->layerTransparency() != 0 ) ) ) { flattenedLayer = true; mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); if ( mypFlattenedImage->isNull() ) { QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) ); emit drawError( ml ); painter->end(); // drawError is not caught by anyone, so we end painting to notify caller return; } mypFlattenedImage->fill( 0 ); QPainter * mypPainter = new QPainter( mypFlattenedImage ); if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mypPainter->scale( rasterScaleFactor, rasterScaleFactor ); mRenderContext.setPainter( mypPainter ); } } // Per feature blending mode if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) { // set the painter to the feature blend mode, so that features drawn // on this layer will interact and blend with each other mRenderContext.painter()->setCompositionMode( vl->featureBlendMode() ); } } if ( scaleRaster ) { bk_mapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor ); rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor ); mRenderContext.setMapToPixel( rasterMapToPixel ); mRenderContext.painter()->save(); mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); } if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } else { QgsDebugMsg( "Layer rendered without issues" ); } if ( split ) { mRenderContext.setExtent( r2 ); if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } } if ( scaleRaster ) { mRenderContext.setMapToPixel( bk_mapToPixel ); mRenderContext.painter()->restore(); } //apply layer transparency for vector layers if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->layerTransparency() != 0 ) { // a layer transparency has been set, so update the alpha for the flattened layer // by combining it with the layer transparency QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) ); // use destination in composition mode to merge source's alpha with destination mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn ); mRenderContext.painter()->fillRect( 0, 0, mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), transparentFillColor ); } } if ( useRenderCaching ) { // composite the cached image into our view and then clean up from caching // by reinstating the painter as it was swapped out for caching renders delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); //draw from cached image that we created further up if ( ml->cacheImage() ) mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); } else if ( flattenedLayer ) { // If we flattened this layer for alternate blend modes, composite it now delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); mypContextPainter->save(); mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) ); mypContextPainter->restore(); delete mypFlattenedImage; mypFlattenedImage = 0; } disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); }
void QgsMapRenderer::render( QPainter* painter ) { //flag to see if the render context has changed //since the last time we rendered. If it hasnt changed we can //take some shortcuts with rendering bool mySameAsLastFlag = true; QgsDebugMsg( "========== Rendering ==========" ); if ( mExtent.isEmpty() ) { QgsDebugMsg( "empty extent... not rendering" ); return; } if ( mSize.width() == 1 && mSize.height() == 1 ) { QgsDebugMsg( "size 1x1... not rendering" ); return; } QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { QgsDebugMsg( "already rendering" ); QCoreApplication::processEvents(); } if ( mDrawing ) { QgsDebugMsg( "still rendering - skipping" ); return; } mDrawing = true; QgsCoordinateTransform* ct; #ifdef QGISDEBUG QgsDebugMsg( "Starting to render layer stack." ); QTime renderTime; renderTime.start(); #endif if ( mOverview ) mRenderContext.setDrawEditingInformation( !mOverview ); mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); //this flag is only for stopping during the current rendering progress, //so must be false at every new render operation mRenderContext.setRenderingStopped( false ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == QgsMapRenderer::Millimeters ) { scaleFactor = sceneDpi / 25.4; } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) { mRenderContext.setRasterScaleFactor( rasterScaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); mySameAsLastFlag = false; } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; mySameAsLastFlag = false; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( this ); // know we know if this render is just a repeat of the last time, we // can clear caches if it has changed if ( !mySameAsLastFlag ) { //clear the cache pixmap if we changed resolution / extent QSettings mySettings; if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { QgsMapLayerRegistry::instance()->clearAllLayerCaches(); } } QgsOverlayObjectPositionManager* overlayManager = overlayManagerFromSettings(); QList<QgsVectorOverlay*> allOverlayList; //list of all overlays, used to draw them after layers have been rendered // render all layers in the stack, starting at the base QListIterator<QString> li( mLayerSet ); li.toBack(); QgsRectangle r1, r2; while ( li.hasPrevious() ) { if ( mRenderContext.renderingStopped() ) { break; } // Store the painter in case we need to swap it out for the // cache painter QPainter * mypContextPainter = mRenderContext.painter(); QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); // This call is supposed to cause the progress bar to // advance. However, it seems that updating the progress bar is // incompatible with having a QPainter active (the one that is // passed into this function), as Qt produces a number of errors // when try to do so. I'm (Gavin) not sure how to fix this, but // added these comments and debug statement to help others... QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" ); //emit drawingProgress(myRenderCounter++, mLayerSet.size()); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { QgsDebugMsg( "Layer not found in registry!" ); continue; } QgsDebugMsg( "Rendering layer " + ml->name() ); QgsDebugMsg( " Layer minscale " + QString( "%1" ).arg( ml->minimumScale() ) ); QgsDebugMsg( " Layer maxscale " + QString( "%1" ).arg( ml->maximumScale() ) ); QgsDebugMsg( " Scale dep. visibility enabled? " + QString( "%1" ).arg( ml->hasScaleBasedVisibility() ) ); QgsDebugMsg( " Input extent: " + ml->extent().toString() ); if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) || mOverview ) { connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); // // Now do the call to the layer that actually does // the rendering work! // bool split = false; if ( hasCrsTransformEnabled() ) { r1 = mExtent; split = splitLayersExtent( ml, r1, r2 ); ct = new QgsCoordinateTransform( ml->crs(), *mDestCRS ); mRenderContext.setExtent( r1 ); QgsDebugMsg( " extent 1: " + r1.toString() ); QgsDebugMsg( " extent 2: " + r2.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer { continue; } } else { ct = NULL; } mRenderContext.setCoordinateTransform( ct ); //decide if we have to scale the raster //this is necessary in case QGraphicsScene is used bool scaleRaster = false; QgsMapToPixel rasterMapToPixel; QgsMapToPixel bk_mapToPixel; if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 ) { scaleRaster = true; } //create overlay objects for features within the view extent if ( ml->type() == QgsMapLayer::VectorLayer && overlayManager ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl ) { QList<QgsVectorOverlay*> thisLayerOverlayList; vl->vectorOverlays( thisLayerOverlayList ); QList<QgsVectorOverlay*>::iterator overlayIt = thisLayerOverlayList.begin(); for ( ; overlayIt != thisLayerOverlayList.end(); ++overlayIt ) { if (( *overlayIt )->displayFlag() ) { ( *overlayIt )->createOverlayObjects( mRenderContext ); allOverlayList.push_back( *overlayIt ); } } overlayManager->addLayer( vl, thisLayerOverlayList ); } } // Force render of layers that are being edited // or if there's a labeling engine that needs the layer to register features if ( ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->isEditable() || ( mRenderContext.labelingEngine() && mRenderContext.labelingEngine()->willUseLayer( vl ) ) ) { ml->setCacheImage( 0 ); } } QSettings mySettings; if ( ! split )//render caching does not yet cater for split extents { if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { if ( !mySameAsLastFlag || ml->cacheImage() == 0 ) { QgsDebugMsg( "\n\n\nCaching enabled but layer redraw forced by extent change or empty cache\n\n\n" ); QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); mypImage->fill( 0 ); ml->setCacheImage( mypImage ); //no need to delete the old one, maplayer does it for you QPainter * mypPainter = new QPainter( ml->cacheImage() ); // Changed to enable anti aliasing by default in QGIS 1.7 if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mRenderContext.setPainter( mypPainter ); } else if ( mySameAsLastFlag ) { //draw from cached image QgsDebugMsg( "\n\n\nCaching enabled --- drawing layer from cached image\n\n\n" ); mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); //short circuit as there is nothing else to do... continue; } } } if ( scaleRaster ) { bk_mapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor ); rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor ); mRenderContext.setMapToPixel( rasterMapToPixel ); mRenderContext.painter()->save(); mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); } if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } else { QgsDebugMsg( "Layer rendered without issues" ); } if ( split ) { mRenderContext.setExtent( r2 ); if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } } if ( scaleRaster ) { mRenderContext.setMapToPixel( bk_mapToPixel ); mRenderContext.painter()->restore(); } if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { if ( !split ) { // composite the cached image into our view and then clean up from caching // by reinstating the painter as it was swapped out for caching renders delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); //draw from cached image that we created further up mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); } } disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); } else // layer not visible due to scale {
void QgsComposerLegend::drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight, int layerOpacity ) const { if ( !p || !s ) { return; } double rasterScaleFactor = 1.0; if ( p ) { QPaintDevice* paintDevice = p->device(); if ( !paintDevice ) { return; } rasterScaleFactor = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4; } //consider relation to composer map for symbol sizes in mm bool sizeInMapUnits = s->outputUnit() == QgsSymbolV2::MapUnit; double mmPerMapUnit = 1; if ( mComposerMap ) { mmPerMapUnit = mComposerMap->mapUnitsToMM(); } QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ); //Consider symbol size for point markers double height = mSymbolHeight; double width = mSymbolWidth; double size = 0; //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( markerSymbol ) { size = markerSymbol->size(); height = size; width = size; if ( mComposerMap && sizeInMapUnits ) { height *= mmPerMapUnit; width *= mmPerMapUnit; markerSymbol->setSize( width ); } if ( width < mSymbolWidth ) { widthOffset = ( mSymbolWidth - width ) / 2.0; } if ( height < mSymbolHeight ) { heightOffset = ( mSymbolHeight - height ) / 2.0; } } p->save(); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); if ( markerSymbol && sizeInMapUnits ) { s->setOutputUnit( QgsSymbolV2::MM ); } s->drawPreviewIcon( p, QSize( width * rasterScaleFactor, height * rasterScaleFactor ) ); if ( markerSymbol && sizeInMapUnits ) { s->setOutputUnit( QgsSymbolV2::MapUnit ); markerSymbol->setSize( size ); } p->restore(); currentXPosition += width; currentXPosition += 2 * widthOffset; symbolHeight = height + 2 * heightOffset; }
MainPage::MainPage(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { ui.setupUi(this); this->LoadQSS(); m_mousePressed = false; QObject::connect(ui.toolButtonHardware, SIGNAL(clicked()), this, SLOT(HardwareInforClicked())); QObject::connect(ui.toolButtonTempManagement, SIGNAL(clicked()), this, SLOT(TemperatureClicked())); QObject::connect(ui.toolButtonTestItem, SIGNAL(clicked()), this, SLOT(TestItemClicked())); QObject::connect(ui.pushButtonMin, SIGNAL(clicked()), this, SLOT(MinButtonClicked())); QObject::connect(ui.pushButtonClose, SIGNAL(clicked()), this, SLOT(CloseButtonClicked())); QObject::connect(ui.pushButtonUpdate, SIGNAL(clicked()), this, SLOT(UpdateButtonClicked())); QObject::connect(&m_checkNewTimer, SIGNAL(timeout()), this, SLOT(CheckNewTimerTimeout())); QObject::connect(&m_downloadNewTimer, SIGNAL(timeout()), this, SLOT(DownloadNewTimerTimeout())); // 隐藏默认窗口边框和标题栏 this->setWindowFlags(Qt::Window|Qt::FramelessWindowHint|Qt::WindowSystemMenuHint |Qt::WindowMinimizeButtonHint|Qt::WindowMaximizeButtonHint); this->setWindowIcon(QIcon(":/ControlImage/Main.png")); QString title = MAIN_TITLE; title += LAppParam::GetAppVersion(); this->ui.labelTitle->setText(title); this->ui.pushButtonUpdate->setVisible(false); // 获取当前系统DPI, 当前系统DPI除以设计时DPI值, 则得到UI放大系数 const float DESIGN_DPI = 96.0f; // 设计时DPI QPainter painter(this); QPaintDevice* pDevice = painter.device(); PrintLogW(L"System DPI X: %d, Y: %d", pDevice->logicalDpiX(), pDevice->logicalDpiY()); float ratioX = pDevice->logicalDpiX()/DESIGN_DPI; float ratioY = pDevice->logicalDpiY()/DESIGN_DPI; m_uiRatio = ratioX > ratioY ? ratioX : ratioY; if (m_uiRatio < 1.0f) m_uiRatio = 1.0f; PrintLogW(L"UI Ratio: %f", m_uiRatio); // 根据比例重新调整主UI大小, 并居中显示 int width = this->geometry().width() * m_uiRatio; int height = this->geometry().height() * m_uiRatio; this->setFixedSize(width, height); QDesktopWidget* pDesk = QApplication::desktop(); this->move((pDesk->width() - width) / 2, (pDesk->height() - height) / 2); // 显示启动画面 QPixmap originalImage(".\\Image\\Background\\splash.png"); QSize imageSize(originalImage.width() * m_uiRatio, originalImage.height() * m_uiRatio); QPixmap scaledImage = originalImage.scaled(imageSize, Qt::KeepAspectRatio); QFont splashFont("Microsoft YaHei UI", 10); m_splashScreen.setFont(splashFont); m_splashScreen.setPixmap(scaledImage); m_splashScreen.show(); width = ui.stackedWidget->width() * m_uiRatio; height = ui.stackedWidget->height() * m_uiRatio; m_splashScreen.showMessage(QObject::tr("Creating Hardware Page..."), Qt::AlignLeft | Qt::AlignTop, Qt::red); m_pHardwareInforPage = new HardwareInforPage(m_uiRatio); m_pHardwareInforPage->SetSplashScreen(&m_splashScreen); m_pHardwareInforPage->setFixedSize(width, height); m_pHardwareInforPage->InitHardwareInfor(); ui.stackedWidget->addWidget(m_pHardwareInforPage); m_splashScreen.showMessage(QObject::tr("Creating Temperature Page..."), Qt::AlignLeft | Qt::AlignTop, Qt::red); m_pTempManagementPage = new TempManagementPage(); m_pTempManagementPage->setFixedSize(width, height); ui.stackedWidget->addWidget(m_pTempManagementPage); m_splashScreen.showMessage(QObject::tr("Creating Test Item Page..."), Qt::AlignLeft | Qt::AlignTop, Qt::red); m_pTestItemPage = new TestItemPage(m_uiRatio); m_pTestItemPage->setFixedSize(width, height); ui.stackedWidget->addWidget(m_pTestItemPage); if (APP_NORMAL == LAppParam::GetStartMode()) ui.stackedWidget->setCurrentWidget(m_pHardwareInforPage); else if (APP_RESTARTAGING == LAppParam::GetStartMode()) ui.stackedWidget->setCurrentWidget(m_pTestItemPage); else ui.stackedWidget->setCurrentWidget(m_pTestItemPage); }
void QgsMapRendererCustomPainterJob::start() { if ( isActive() ) return; mRenderingStart.start(); mActive = true; mErrors.clear(); QgsDebugMsg( "QPAINTER run!" ); QgsDebugMsg( "Preparing list of layer jobs for rendering" ); QTime prepareTime; prepareTime.start(); // clear the background mPainter->fillRect( 0, 0, mSettings.outputSize().width(), mSettings.outputSize().height(), mSettings.backgroundColor() ); mPainter->setRenderHint( QPainter::Antialiasing, mSettings.testFlag( QgsMapSettings::Antialiasing ) ); #ifndef QT_NO_DEBUG QPaintDevice* thePaintDevice = mPainter->device(); QString errMsg = QString( "pre-set DPI not equal to painter's DPI (%1 vs %2)" ).arg( thePaintDevice->logicalDpiX() ).arg( mSettings.outputDpi() ); Q_ASSERT_X( qgsDoubleNear( thePaintDevice->logicalDpiX(), mSettings.outputDpi() ), "Job::startRender()", errMsg.toAscii().data() ); #endif delete mLabelingEngine; mLabelingEngine = nullptr; delete mLabelingEngineV2; mLabelingEngineV2 = nullptr; if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) ) { #ifdef LABELING_V2 mLabelingEngineV2 = new QgsLabelingEngineV2(); mLabelingEngineV2->readSettingsFromProject(); mLabelingEngineV2->setMapSettings( mSettings ); #else mLabelingEngine = new QgsPalLabeling; mLabelingEngine->loadEngineSettings(); mLabelingEngine->init( mSettings ); #endif } mLayerJobs = prepareJobs( mPainter, mLabelingEngine, mLabelingEngineV2 ); // prepareJobs calls mapLayer->createMapRenderer may involve cloning a RasterDataProvider, // whose constructor may need to download some data (i.e. WMS, AMS) and doing so runs a // QEventLoop waiting for the network request to complete. If unluckily someone calls // mapCanvas->refresh() while this is happening, QgsMapRendererCustomPainterJob::cancel is // called, deleting the QgsMapRendererCustomPainterJob while this function is running. // Hence we need to check whether the job is still active before proceeding if ( !isActive() ) return; QgsDebugMsg( "Rendering prepared in (seconds): " + QString( "%1" ).arg( prepareTime.elapsed() / 1000.0 ) ); if ( mRenderSynchronously ) { // do the rendering right now! doRender(); return; } // now we are ready to start rendering! connect( &mFutureWatcher, SIGNAL( finished() ), SLOT( futureFinished() ) ); mFuture = QtConcurrent::run( staticRender, this ); mFutureWatcher.setFuture( mFuture ); }