Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-default blend mode should force raster render of layer #58966

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/core/annotations/qgsannotationlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ QgsAnnotationLayerRenderer::QgsAnnotationLayerRenderer( QgsAnnotationLayer *laye
: QgsMapLayerRenderer( layer->id(), &context )
, mFeedback( std::make_unique< QgsFeedback >() )
, mLayerOpacity( layer->opacity() )
, mLayerBlendMode( layer->blendMode() )
{
if ( QgsMapLayer *linkedLayer = layer->linkedVisibilityLayer() )
{
Expand Down Expand Up @@ -123,5 +124,14 @@ bool QgsAnnotationLayerRenderer::render()

bool QgsAnnotationLayerRenderer::forceRasterRender() const
{
return renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) && ( !qgsDoubleNear( mLayerOpacity, 1.0 ) );
if ( !renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) )
return false;

if ( !qgsDoubleNear( mLayerOpacity, 1.0 ) )
return true;

if ( mLayerBlendMode != QPainter::CompositionMode_SourceOver )
return true;

return false;
}
1 change: 1 addition & 0 deletions src/core/annotations/qgsannotationlayerrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class CORE_EXPORT QgsAnnotationLayerRenderer : public QgsMapLayerRenderer
std::vector < std::pair< QString, std::unique_ptr< QgsAnnotationItem > > > mItems;
std::unique_ptr< QgsFeedback > mFeedback;
double mLayerOpacity = 1.0;
QPainter::CompositionMode mLayerBlendMode = QPainter::CompositionMode::CompositionMode_SourceOver;
std::unique_ptr< QgsPaintEffect > mPaintEffect;

};
Expand Down
12 changes: 11 additions & 1 deletion src/core/vectortile/qgsvectortilelayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ QgsVectorTileLayerRenderer::QgsVectorTileLayerRenderer( QgsVectorTileLayer *laye
, mLayerName( layer->name() )
, mDataProvider( qgis::down_cast< const QgsVectorTileDataProvider* >( layer->dataProvider() )->clone() )
, mRenderer( layer->renderer()->clone() )
, mLayerBlendMode( layer->blendMode() )
, mDrawTileBoundaries( layer->isTileBorderRenderingEnabled() )
, mLabelsEnabled( layer->labelsEnabled() )
, mFeedback( new QgsFeedback )
Expand Down Expand Up @@ -237,7 +238,16 @@ bool QgsVectorTileLayerRenderer::render()

bool QgsVectorTileLayerRenderer::forceRasterRender() const
{
return renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) && ( !qgsDoubleNear( mLayerOpacity, 1.0 ) );
if ( !renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) )
return false;

if ( !qgsDoubleNear( mLayerOpacity, 1.0 ) )
return true;

if ( mLayerBlendMode != QPainter::CompositionMode_SourceOver )
return true;

return false;
}

void QgsVectorTileLayerRenderer::decodeAndDrawTile( const QgsVectorTileRawData &rawTile )
Expand Down
2 changes: 2 additions & 0 deletions src/core/vectortile/qgsvectortilelayerrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class QgsVectorTileLayerRenderer : public QgsMapLayerRenderer
//! Tile renderer object to do rendering of individual tiles
std::unique_ptr<QgsVectorTileRenderer> mRenderer;

QPainter::CompositionMode mLayerBlendMode = QPainter::CompositionMode::CompositionMode_SourceOver;

/**
* Label provider that handles registration of labels.
* No need to delete: if exists it is owned by labeling engine.
Expand Down
19 changes: 19 additions & 0 deletions tests/src/python/test_qgsannotationlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,25 @@ def test_render_via_job_with_transform(self):
self.assertTrue(compareWkt(result, expected, tol=1000), "mismatch Expected:\n{}\nGot:\n{}\n".format(expected,
result))

def test_force_raster_render(self):
layer = QgsAnnotationLayer('test', QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext()))
self.assertTrue(layer.isValid())
settings = QgsMapSettings()
rc = QgsRenderContext.fromMapSettings(settings)
renderer = layer.createMapRenderer(rc)
self.assertFalse(renderer.forceRasterRender())

# layer opacity should force raster render
layer.setOpacity(0.5)
renderer = layer.createMapRenderer(rc)
self.assertTrue(renderer.forceRasterRender())
layer.setOpacity(1.0)

# alternate blend mode should force raster render
layer.setBlendMode(QPainter.CompositionMode.CompositionMode_Multiply)
renderer = layer.createMapRenderer(rc)
self.assertTrue(renderer.forceRasterRender())

def testRenderWithDisabledItems(self):
layer = QgsAnnotationLayer('test', QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext()))
self.assertTrue(layer.isValid())
Expand Down
22 changes: 22 additions & 0 deletions tests/src/python/test_qgsvectortile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from pathlib import Path

from qgis.PyQt.QtTest import QSignalSpy
from qgis.PyQt.QtGui import QPainter
from qgis.core import (
Qgis,
QgsDataSourceUri,
Expand All @@ -29,6 +30,8 @@
QgsVectorLayer,
QgsVectorTileLayer,
QgsVectorTileWriter,
QgsMapSettings,
QgsRenderContext
)
import unittest
from qgis.testing import start_app, QgisTestCase
Expand Down Expand Up @@ -294,6 +297,25 @@ def testSelection(self):
self.assertCountEqual({f.geometry().asWkt(-3) for f in layer.selectedFeatures()}, {'Polygon ((-10958000 3835000, -10958000 3796000, -10919000 3835000, -10841000 3874000, -10684000 3992000, -10567000 4031000, -10410000 4031000, -10332000 3992000, -10254000 3914000, -10136000 3914000, -10058000 3874000, -10019000 3796000, -10019000 3757000, -10058000 3718000, -10097000 3718000, -10254000 3796000, -10332000 3796000, -10371000 3757000, -10371000 3718000, -10371000 3679000, -10332000 3640000, -10332000 3561000, -10410000 3483000, -10449000 3405000, -10488000 3366000, -10645000 3327000, -10723000 3366000, -10762000 3405000, -10801000 3444000, -10762000 3483000, -10801000 3522000, -10841000 3561000, -10919000 3561000, -10958000 3600000, -10958000 3640000, -10958000 3679000, -10958000 3718000, -10997000 3796000, -10958000 3835000))'})
self.assertEqual(len(spy), 11)

def test_force_raster_render(self):
layer = QgsVectorTileLayer(f"type=vtpk&url={unitTestDataPath() + '/testvtpk.vtpk'}", 'tiles')
self.assertTrue(layer.isValid())
settings = QgsMapSettings()
rc = QgsRenderContext.fromMapSettings(settings)
renderer = layer.createMapRenderer(rc)
self.assertFalse(renderer.forceRasterRender())

# layer opacity should force raster render
layer.setOpacity(0.5)
renderer = layer.createMapRenderer(rc)
self.assertTrue(renderer.forceRasterRender())
layer.setOpacity(1.0)

# alternate blend mode should force raster render
layer.setBlendMode(QPainter.CompositionMode.CompositionMode_Multiply)
renderer = layer.createMapRenderer(rc)
self.assertTrue(renderer.forceRasterRender())


if __name__ == '__main__':
unittest.main()
Loading