qgis_render_cache_v3.diff
src/app/qgsoptions.cpp (working copy) | ||
---|---|---|
149 | 149 | |
150 | 150 |
//set the state of the checkboxes |
151 | 151 |
chkAntiAliasing->setChecked( settings.value( "/qgis/enable_anti_aliasing", false ).toBool() ); |
152 |
chkUseRenderCaching->setChecked( settings.value( "/qgis/enable_render_caching", false ).toBool() ); |
|
152 | 153 | |
153 | 154 |
// Slightly awkard here at the settings value is true to use QImage, |
154 | 155 |
// but the checkbox is true to use QPixmap |
... | ... | |
365 | 366 |
settings.setValue( "/qgis/addPostgisDC", cbxAddPostgisDC->isChecked() ); |
366 | 367 |
settings.setValue( "/qgis/new_layers_visible", chkAddedVisibility->isChecked() ); |
367 | 368 |
settings.setValue( "/qgis/enable_anti_aliasing", chkAntiAliasing->isChecked() ); |
369 |
settings.setValue( "/qgis/enable_render_caching", chkUseRenderCaching->isChecked() ); |
|
368 | 370 |
settings.setValue( "/qgis/use_qimage_to_render", !( chkUseQPixmap->isChecked() ) ); |
369 | 371 |
settings.setValue( "qgis/capitaliseLayerName", capitaliseCheckBox->isChecked() ); |
370 | 372 |
settings.setValue( "qgis/askToSaveProjectChanges", chbAskToSaveProjectChanges->isChecked() ); |
... | ... | |
530 | 532 |
// used (we we can. but it then doesn't do anti-aliasing, and this |
531 | 533 |
// will confuse people). |
532 | 534 |
if ( chkAntiAliasing->isChecked() ) |
535 |
{ |
|
533 | 536 |
chkUseQPixmap->setChecked( false ); |
537 |
} |
|
534 | 538 | |
535 | 539 |
} |
536 | 540 | |
... | ... | |
540 | 544 |
// used (we we can. but it then doesn't do anti-aliasing, and this |
541 | 545 |
// will confuse people). |
542 | 546 |
if ( chkUseQPixmap->isChecked() ) |
547 |
{ |
|
543 | 548 |
chkAntiAliasing->setChecked( false ); |
549 |
} |
|
544 | 550 | |
545 | 551 |
} |
546 | 552 |
src/app/qgsvectorlayerproperties.cpp (working copy) | ||
---|---|---|
673 | 673 |
// update symbology |
674 | 674 |
emit refreshLegend( layer->getLayerID(), false ); |
675 | 675 | |
676 |
if ( layer->cachePixmap() ) |
|
677 |
{ |
|
678 |
//no need to delete the old one, maplayer will do it if needed |
|
679 |
layer->setCachePixmap( 0 ); |
|
680 |
} |
|
676 | 681 |
layer->triggerRepaint(); |
677 | 682 |
// notify the project we've made a change |
678 | 683 |
QgsProject::instance()->dirty( true ); |
src/core/qgsmaprenderer.h (working copy) | ||
---|---|---|
199 | 199 | |
200 | 200 |
//! current extent to be drawn |
201 | 201 |
QgsRectangle mExtent; |
202 |
// |
|
203 |
/** Last extent to we drew so we know if we can |
|
204 |
used layer render caching or not. Note there are no |
|
205 |
accessors for this as it is intended to internal |
|
206 |
use only. |
|
207 |
@note added in QGIS 1.4 */ |
|
208 |
QgsRectangle mLastExtent; |
|
202 | 209 | |
203 | 210 |
//! indicates whether it's map image for overview |
204 | 211 |
bool mOverview; |
src/core/qgsmaplayer.cpp (working copy) | ||
---|---|---|
75 | 75 |
mMinScale = 0; |
76 | 76 |
mMaxScale = 100000000; |
77 | 77 |
mScaleBasedVisibility = false; |
78 |
mpCachePixmap = 0; |
|
78 | 79 |
} |
79 | 80 | |
80 | 81 | |
... | ... | |
82 | 83 |
QgsMapLayer::~QgsMapLayer() |
83 | 84 |
{ |
84 | 85 |
delete mCRS; |
86 |
if ( mpCachePixmap ) |
|
87 |
{ |
|
88 |
delete mpCachePixmap; |
|
89 |
} |
|
85 | 90 |
} |
86 | 91 | |
87 | 92 |
QgsMapLayer::LayerType QgsMapLayer::type() const |
... | ... | |
729 | 734 |
{ |
730 | 735 |
return &mUndoStack; |
731 | 736 |
} |
737 | ||
738 |
void QgsMapLayer::setCachePixmap( QPixmap * thepPixmap ) |
|
739 |
{ |
|
740 |
QgsDebugMsg( "cache Pixmap set!" ); |
|
741 |
if ( mpCachePixmap ) |
|
742 |
{ |
|
743 |
delete mpCachePixmap; |
|
744 |
} |
|
745 |
mpCachePixmap = thepPixmap; |
|
746 |
} |
src/core/qgsmaprenderer.cpp (working copy) | ||
---|---|---|
80 | 80 | |
81 | 81 |
bool QgsMapRenderer::setExtent( const QgsRectangle& extent ) |
82 | 82 |
{ |
83 |
//remember the previous extent |
|
84 |
mLastExtent = mExtent; |
|
83 | 85 | |
84 | 86 |
// Don't allow zooms where the current extent is so small that it |
85 | 87 |
// can't be accurately represented using a double (which is what |
... | ... | |
207 | 209 | |
208 | 210 |
void QgsMapRenderer::render( QPainter* painter ) |
209 | 211 |
{ |
212 |
//flag to see if the render context has changed |
|
213 |
//since the last time we rendered. If it hasnt changed we can |
|
214 |
//take some shortcuts with rendering |
|
215 |
bool mySameAsLastFlag = true; |
|
216 | ||
210 | 217 |
QgsDebugMsg( "========== Rendering ==========" ); |
211 | 218 | |
212 | 219 |
if ( mExtent.isEmpty() ) |
... | ... | |
216 | 223 |
} |
217 | 224 | |
218 | 225 |
if ( mDrawing ) |
226 |
{ |
|
219 | 227 |
return; |
228 |
} |
|
220 | 229 | |
221 | 230 |
QPaintDevice* thePaintDevice = painter->device(); |
222 | 231 |
if ( !thePaintDevice ) |
... | ... | |
251 | 260 |
scaleFactor = sceneDpi / 25.4; |
252 | 261 |
} |
253 | 262 |
double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; |
254 |
mRenderContext.setScaleFactor( scaleFactor ); |
|
255 |
mRenderContext.setRasterScaleFactor( rasterScaleFactor ); |
|
256 |
mRenderContext.setRendererScale( mScale ); |
|
263 |
if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) |
|
264 |
{ |
|
265 |
mRenderContext.setRasterScaleFactor( rasterScaleFactor ); |
|
266 |
mySameAsLastFlag = false; |
|
267 |
} |
|
268 |
if ( mRenderContext.scaleFactor() != scaleFactor ) |
|
269 |
{ |
|
270 |
mRenderContext.setScaleFactor( scaleFactor ); |
|
271 |
mySameAsLastFlag = false; |
|
272 |
} |
|
273 |
if ( mRenderContext.rendererScale() != mScale ) |
|
274 |
{ |
|
275 |
//add map scale to render context |
|
276 |
mRenderContext.setRendererScale( mScale ); |
|
277 |
mySameAsLastFlag = false; |
|
278 |
} |
|
279 |
if ( mLastExtent != mExtent ) |
|
280 |
{ |
|
281 |
mLastExtent = mExtent; |
|
282 |
mySameAsLastFlag = false; |
|
283 |
} |
|
257 | 284 | |
258 | 285 |
bool placeOverlays = false; |
259 | 286 |
QgsOverlayObjectPositionManager* overlayManager = overlayManagerFromSettings(); |
... | ... | |
263 | 290 |
placeOverlays = true; |
264 | 291 |
} |
265 | 292 | |
266 |
//add map scale to render context |
|
267 |
mRenderContext.setRendererScale( mScale ); |
|
268 | ||
269 | 293 |
// render all layers in the stack, starting at the base |
270 | 294 |
QListIterator<QString> li( mLayerSet ); |
271 | 295 |
li.toBack(); |
... | ... | |
279 | 303 |
break; |
280 | 304 |
} |
281 | 305 | |
306 |
// Store the painter in case we need to swap it out for the |
|
307 |
// cache painter |
|
308 |
QPainter * mypContextPainter = mRenderContext.painter(); |
|
309 | ||
282 | 310 |
QString layerId = li.previous(); |
283 | 311 | |
284 | 312 |
QgsDebugMsg( "Rendering at layer item " + layerId ); |
... | ... | |
377 | 405 |
} |
378 | 406 |
} |
379 | 407 | |
408 |
QSettings mySettings; |
|
409 |
if ( mySettings.value ( "/qgis/enable_render_caching", false ).toBool() ) |
|
410 |
{ |
|
411 |
if ( ( !mySameAsLastFlag || ml->cachePixmap() == 0 ) && !split ) //render caching does not yet cater for split extents |
|
412 |
{ |
|
413 |
QPixmap * mypPixmap = new QPixmap( mRenderContext.painter()->device()->width(), |
|
414 |
mRenderContext.painter()->device()->height() ); |
|
415 |
mypPixmap->fill( QColor( 0,0,0,0 ) ); |
|
416 |
ml->setCachePixmap( mypPixmap ); //no need to delete the oldone, maplayer does it for you |
|
417 |
QPainter * mypPainter = new QPainter( ml->cachePixmap() ); |
|
418 |
if ( mySettings.value( "/qgis/enable_anti_aliasing", false ).toBool() ) |
|
419 |
{ |
|
420 |
mypPainter->setRenderHint( QPainter::Antialiasing ); |
|
421 |
} |
|
422 |
mRenderContext.setPainter( mypPainter ); |
|
423 |
} |
|
424 |
else if ( mySameAsLastFlag && !split ) |
|
425 |
{ |
|
426 |
//always ensure the layers cache pixmap is initialised... |
|
427 |
if ( ! ml->cachePixmap() ) |
|
428 |
{ |
|
429 |
QPixmap * mypPixmap = new QPixmap( mRenderContext.painter()->device()->width(), |
|
430 |
mRenderContext.painter()->device()->height() ); |
|
431 |
mypPixmap->fill( QColor( 0,0,0,0 ) ); |
|
432 |
ml->setCachePixmap( mypPixmap ); |
|
433 |
} |
|
434 |
//draw from cached image |
|
435 |
mypContextPainter->drawPixmap( 0,0, *(ml->cachePixmap()) ); |
|
436 |
disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); |
|
437 |
//short circuit as there is nothing else to do... |
|
438 |
continue; |
|
439 |
} |
|
440 |
} |
|
441 | ||
380 | 442 |
if ( !ml->draw( mRenderContext ) ) |
381 | 443 |
{ |
382 | 444 |
emit drawError( ml ); |
... | ... | |
397 | 459 |
mRenderContext.painter()->restore(); |
398 | 460 |
} |
399 | 461 | |
462 |
//clean up from caching |
|
463 |
if ( mySettings.value ( "/qgis/enable_render_caching", false ).toBool() ) |
|
464 |
{ |
|
465 |
if ( !mySameAsLastFlag && !split ) |
|
466 |
{ |
|
467 |
//draw from cached image that we created further up |
|
468 |
mypContextPainter->drawPixmap( 0,0, *(ml->cachePixmap()) ); |
|
469 |
// reinstate the painter as it was swapped out for caching |
|
470 |
delete mRenderContext.painter(); |
|
471 |
mRenderContext.setPainter( mypContextPainter ); |
|
472 |
} |
|
473 |
} |
|
400 | 474 |
disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); |
401 | 475 |
} |
402 |
else |
|
476 |
else // layer not visible
|
|
403 | 477 |
{ |
478 |
//clear the cache pixmap if we changed resolution / extent |
|
479 |
QSettings mySettings; |
|
480 |
if ( mySettings.value ( "/qgis/enable_render_caching", false ).toBool() ) |
|
481 |
{ |
|
482 |
if ( !mySameAsLastFlag ) |
|
483 |
{ |
|
484 |
delete ml->cachePixmap(); |
|
485 |
ml->setCachePixmap( 0 ); |
|
486 |
} |
|
487 |
} |
|
404 | 488 |
QgsDebugMsg( "Layer not rendered because it is not within the defined " |
405 |
"visibility scale range" );
|
|
489 |
"visibility scale range" ); |
|
406 | 490 |
} |
407 | 491 | |
408 | 492 |
} // while (li.hasPrevious()) |
src/core/qgsmaplayer.h (working copy) | ||
---|---|---|
24 | 24 | |
25 | 25 |
#include <QObject> |
26 | 26 |
#include <QUndoStack> |
27 |
#include <QPixmap> |
|
27 | 28 | |
28 | 29 |
#include "qgsrectangle.h" |
29 | 30 | |
... | ... | |
263 | 264 |
/** Return pointer to layer's undo stack */ |
264 | 265 |
QUndoStack* undoStack(); |
265 | 266 | |
267 |
/** Get the QPixmap used for caching render operations |
|
268 |
* @note This method was added in QGIS 1.4 **/ |
|
269 |
QPixmap * cachePixmap() { return mpCachePixmap; } |
|
270 |
/** Set the QPixmap used for caching render operations |
|
271 |
* @note This method was added in QGIS 1.4 **/ |
|
272 |
void setCachePixmap( QPixmap * thepPixmap ); |
|
273 | ||
266 | 274 |
public slots: |
267 | 275 | |
268 | 276 |
/** Event handler for when a coordinate transform fails due to bad vertex error */ |
... | ... | |
360 | 368 |
/** A flag that tells us whether to use the above vars to restrict layer visibility */ |
361 | 369 |
bool mScaleBasedVisibility; |
362 | 370 | |
371 |
/** Collection of undoable operations for this layer. **/ |
|
363 | 372 |
QUndoStack mUndoStack; |
364 | 373 | |
374 |
/**QPixmap for caching of rendering operations |
|
375 |
* @note This property was added in QGIS 1.4 **/ |
|
376 |
QPixmap * mpCachePixmap; |
|
377 | ||
365 | 378 |
}; |
366 | 379 | |
367 | 380 |
#endif |
src/ui/qgsoptionsbase.ui (working copy) | ||
---|---|---|
13 | 13 |
<string>Options</string> |
14 | 14 |
</property> |
15 | 15 |
<property name="windowIcon" > |
16 |
<iconset> |
|
17 |
<normaloff/> |
|
18 |
</iconset> |
|
16 |
<iconset/> |
|
19 | 17 |
</property> |
20 | 18 |
<property name="sizeGripEnabled" > |
21 | 19 |
<bool>true</bool> |
... | ... | |
195 | 193 |
</widget> |
196 | 194 |
</item> |
197 | 195 |
<item row="1" column="0" colspan="2" > |
198 |
<spacer name="verticalSpacer">
|
|
199 |
<property name="orientation"> |
|
196 |
<spacer> |
|
197 |
<property name="orientation" >
|
|
200 | 198 |
<enum>Qt::Vertical</enum> |
201 | 199 |
</property> |
202 |
<property name="sizeType"> |
|
200 |
<property name="sizeType" >
|
|
203 | 201 |
<enum>QSizePolicy::Fixed</enum> |
204 | 202 |
</property> |
205 |
<property name="sizeHint" stdset="0">
|
|
203 |
<property name="sizeHint" > |
|
206 | 204 |
<size> |
207 | 205 |
<width>20</width> |
208 | 206 |
<height>10</height> |
209 | 207 |
</size> |
210 | 208 |
</property> |
211 | 209 |
</spacer> |
212 |
</item>
|
|
210 |
</item> |
|
213 | 211 |
<item row="2" column="0" colspan="2" > |
214 | 212 |
<widget class="QCheckBox" name="capitaliseCheckBox" > |
215 | 213 |
<property name="text" > |
... | ... | |
321 | 319 |
</property> |
322 | 320 |
</widget> |
323 | 321 |
</item> |
322 |
<item row="3" column="0" colspan="2" > |
|
323 |
<widget class="QCheckBox" name="chkUseRenderCaching" > |
|
324 |
<property name="text" > |
|
325 |
<string>Use render caching where possible to speed up redraws</string> |
|
326 |
</property> |
|
327 |
</widget> |
|
328 |
</item> |
|
324 | 329 |
</layout> |
325 | 330 |
</widget> |
326 | 331 |
</item> |
... | ... | |
369 | 374 |
</property> |
370 | 375 |
<property name="sizeHint" > |
371 | 376 |
<size> |
372 |
<width>20</width>
|
|
373 |
<height>40</height>
|
|
377 |
<width>614</width>
|
|
378 |
<height>111</height>
|
|
374 | 379 |
</size> |
375 | 380 |
</property> |
376 | 381 |
</spacer> |
... | ... | |
1308 | 1313 |
</customwidget> |
1309 | 1314 |
</customwidgets> |
1310 | 1315 |
<tabstops> |
1316 |
<tabstop>tabWidget</tabstop> |
|
1311 | 1317 |
<tabstop>chbAskToSaveProjectChanges</tabstop> |
1312 | 1318 |
<tabstop>chbWarnOldProjectVersion</tabstop> |
1313 | 1319 |
<tabstop>pbnSelectionColour</tabstop> |
1314 | 1320 |
<tabstop>pbnCanvasColor</tabstop> |
1315 | 1321 |
<tabstop>cmbTheme</tabstop> |
1316 | 1322 |
<tabstop>capitaliseCheckBox</tabstop> |
1323 |
<tabstop>cbxLegendClassifiers</tabstop> |
|
1317 | 1324 |
<tabstop>cbxHideSplash</tabstop> |
1325 |
<tabstop>cbxIdentifyResultsDocked</tabstop> |
|
1326 |
<tabstop>cbxAttributeTableDocked</tabstop> |
|
1327 |
<tabstop>cbxAddPostgisDC</tabstop> |
|
1318 | 1328 |
<tabstop>chkAddedVisibility</tabstop> |
1319 | 1329 |
<tabstop>spinBoxUpdateThreshold</tabstop> |
1330 |
<tabstop>chkUseRenderCaching</tabstop> |
|
1320 | 1331 |
<tabstop>chkAntiAliasing</tabstop> |
1321 | 1332 |
<tabstop>chkUseQPixmap</tabstop> |
1333 |
<tabstop>cmbIdentifyMode</tabstop> |
|
1322 | 1334 |
<tabstop>spinBoxIdentifyValue</tabstop> |
1323 | 1335 |
<tabstop>cmbEllipsoid</tabstop> |
1324 | 1336 |
<tabstop>pbnMeasureColour</tabstop> |
1337 |
<tabstop>radMeters</tabstop> |
|
1338 |
<tabstop>radFeet</tabstop> |
|
1325 | 1339 |
<tabstop>cmbWheelAction</tabstop> |
1326 | 1340 |
<tabstop>spinZoomFactor</tabstop> |
1341 |
<tabstop>mOverlayAlgorithmComboBox</tabstop> |
|
1327 | 1342 |
<tabstop>mLineWidthSpinBox</tabstop> |
1328 | 1343 |
<tabstop>mLineColourToolButton</tabstop> |
1329 | 1344 |
<tabstop>mDefaultSnapModeComboBox</tabstop> |
1330 | 1345 |
<tabstop>mDefaultSnappingToleranceSpinBox</tabstop> |
1331 | 1346 |
<tabstop>mSearchRadiusVertexEditSpinBox</tabstop> |
1347 |
<tabstop>mDefaultSnappingToleranceComboBox</tabstop> |
|
1348 |
<tabstop>mSearchRadiusVertexEditComboBox</tabstop> |
|
1349 |
<tabstop>mMarkersOnlyForSelectedCheckBox</tabstop> |
|
1332 | 1350 |
<tabstop>mMarkerStyleComboBox</tabstop> |
1351 |
<tabstop>mMarkerSizeSpinBox</tabstop> |
|
1352 |
<tabstop>chkDisableAttributeValuesDlg</tabstop> |
|
1333 | 1353 |
<tabstop>radPromptForProjection</tabstop> |
1334 | 1354 |
<tabstop>radUseProjectProjection</tabstop> |
1335 | 1355 |
<tabstop>radUseGlobalProjection</tabstop> |
... | ... | |
1337 | 1357 |
<tabstop>pbnSelectProjection</tabstop> |
1338 | 1358 |
<tabstop>grpLocale</tabstop> |
1339 | 1359 |
<tabstop>cboLocale</tabstop> |
1360 |
<tabstop>grpProxy</tabstop> |
|
1361 |
<tabstop>leProxyHost</tabstop> |
|
1362 |
<tabstop>leProxyPort</tabstop> |
|
1363 |
<tabstop>leProxyUser</tabstop> |
|
1364 |
<tabstop>leProxyPassword</tabstop> |
|
1365 |
<tabstop>mProxyTypeComboBox</tabstop> |
|
1366 |
<tabstop>mAddUrlPushButton</tabstop> |
|
1367 |
<tabstop>mRemoveUrlPushButton</tabstop> |
|
1368 |
<tabstop>mExcludeUrlListWidget</tabstop> |
|
1340 | 1369 |
<tabstop>buttonBox</tabstop> |
1341 |
<tabstop>tabWidget</tabstop> |
|
1342 | 1370 |
</tabstops> |
1343 | 1371 |
<resources/> |
1344 | 1372 |
<connections/> |