Skip to content

Commit

Permalink
Add some more options to control how a preview pixmap for a color ram…
Browse files Browse the repository at this point in the history
…p is generated
  • Loading branch information
nyalldawson committed Dec 7, 2020
1 parent e11f64e commit 928b00a
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 17 deletions.
Expand Up @@ -286,13 +286,19 @@ Returns an icon preview for a color ramp.
.. seealso:: :py:func:`colorRampPreviewPixmap`
%End

static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0 );
static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0, Qt::Orientation direction = Qt::Horizontal,
bool flipDirection = false, bool drawTransparentBackground = true );
%Docstring
Returns a pixmap preview for a color ramp.

:param ramp: color ramp
:param size: target pixmap size
:param padding: space between icon edge and color ramp
:param direction: direction to render pixmap (since QGIS 3.18)
:param flipDirection: set to ``True`` to flip the direction of the ramp. For horizontal ``directions``, ramps will be
rendered left to right by default. For vertical ``directions``, ramps will be rendered top to bottom by default. Setting
this flag to ``True`` will reverse these default directions.
:param drawTransparentBackground: set to ``False`` to disable the checkerboard effect drawn below transparent colors in the ramp

.. seealso:: :py:func:`colorRampPreviewIcon`
%End
Expand Down
34 changes: 28 additions & 6 deletions src/core/symbology/qgssymbollayerutils.cpp
Expand Up @@ -874,7 +874,7 @@ QIcon QgsSymbolLayerUtils::colorRampPreviewIcon( QgsColorRamp *ramp, QSize size,
return QIcon( colorRampPreviewPixmap( ramp, size, padding ) );
}

QPixmap QgsSymbolLayerUtils::colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding )
QPixmap QgsSymbolLayerUtils::colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding, Qt::Orientation direction, bool flipDirection, bool drawTransparentBackground )
{
QPixmap pixmap( size );
pixmap.fill( Qt::transparent );
Expand All @@ -883,16 +883,38 @@ QPixmap QgsSymbolLayerUtils::colorRampPreviewPixmap( QgsColorRamp *ramp, QSize s
painter.begin( &pixmap );

//draw stippled background, for transparent images
drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
if ( drawTransparentBackground )
drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );

// antialiasing makes the colors duller, and no point in antialiasing a color ramp
// painter.setRenderHint( QPainter::Antialiasing );
for ( int i = 0; i < size.width(); i++ )
switch ( direction )
{
QPen pen( ramp->color( static_cast< double >( i ) / size.width() ) );
painter.setPen( pen );
painter.drawLine( i, 0 + padding, i, size.height() - 1 - padding );
case Qt::Horizontal:
{
for ( int i = 0; i < size.width(); i++ )
{
QPen pen( ramp->color( static_cast< double >( i ) / size.width() ) );
painter.setPen( pen );
const int x = flipDirection ? size.width() - i - 1 : i;
painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
}
break;
}

case Qt::Vertical:
{
for ( int i = 0; i < size.height(); i++ )
{
QPen pen( ramp->color( static_cast< double >( i ) / size.height() ) );
painter.setPen( pen );
const int y = flipDirection ? size.height() - i - 1 : i;
painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
}
break;
}
}

painter.end();
return pixmap;
}
Expand Down
8 changes: 7 additions & 1 deletion src/core/symbology/qgssymbollayerutils.h
Expand Up @@ -273,9 +273,15 @@ class CORE_EXPORT QgsSymbolLayerUtils
* \param ramp color ramp
* \param size target pixmap size
* \param padding space between icon edge and color ramp
* \param direction direction to render pixmap (since QGIS 3.18)
* \param flipDirection set to TRUE to flip the direction of the ramp. For horizontal \a directions, ramps will be
* rendered left to right by default. For vertical \a directions, ramps will be rendered top to bottom by default. Setting
* this flag to TRUE will reverse these default directions.
* \param drawTransparentBackground set to FALSE to disable the checkerboard effect drawn below transparent colors in the ramp
* \see colorRampPreviewIcon()
*/
static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0 );
static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0, Qt::Orientation direction = Qt::Horizontal,
bool flipDirection = false, bool drawTransparentBackground = true );

static void drawStippledBackground( QPainter *painter, QRect rect );

Expand Down
83 changes: 74 additions & 9 deletions tests/src/python/test_qgssymbollayerutils.py
Expand Up @@ -11,20 +11,26 @@
__copyright__ = 'Copyright 2016, The QGIS Project'

import qgis # NOQA

from qgis.core import (QgsSymbolLayerUtils,
QgsMarkerSymbol,
QgsArrowSymbolLayer,
QgsUnitTypes)
from qgis.PyQt.QtCore import (
QSizeF,
QPointF,
QMimeData,
QDir,
QSize,
Qt
)
from qgis.PyQt.QtGui import (
QColor,
QPolygonF,
QImage
)
from qgis.PyQt.QtCore import (
QSizeF,
QPointF,
QMimeData
from qgis.core import (
QgsSymbolLayerUtils,
QgsMarkerSymbol,
QgsArrowSymbolLayer,
QgsUnitTypes,
QgsRenderChecker,
QgsGradientColorRamp
)
from qgis.testing import unittest, start_app

Expand All @@ -33,6 +39,16 @@

class PyQgsSymbolLayerUtils(unittest.TestCase):

@classmethod
def setUpClass(cls):
cls.report = "<h1>Python QgsPointCloudRgbRenderer Tests</h1>\n"

@classmethod
def tearDownClass(cls):
report_file_path = "%s/qgistest.html" % QDir.tempPath()
with open(report_file_path, 'a') as report_file:
report_file.write(cls.report)

def testEncodeDecodeSize(self):
s = QSizeF()
string = QgsSymbolLayerUtils.encodeSize(s)
Expand Down Expand Up @@ -408,6 +424,55 @@ def testColorFromMimeData(self):
color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data)
self.assertFalse(color.isValid())

def testPreviewColorRampHorizontal(self):
r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255))

pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100))
img = QImage(pix)
self.assertTrue(self.imageCheck('color_ramp_horizontal', 'color_ramp_horizontal', img))

def testPreviewColorRampHorizontalNoCheckboard(self):
r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255))

pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100), drawTransparentBackground=False)
img = QImage(pix)
self.assertTrue(self.imageCheck('color_ramp_no_check', 'color_ramp_no_check', img))

def testPreviewColorRampHorizontalFlipped(self):
r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255))

pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100), flipDirection=True)
img = QImage(pix)
self.assertTrue(self.imageCheck('color_ramp_horizontal_flipped', 'color_ramp_horizontal_flipped', img))

def testPreviewColorRampVertical(self):
r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255))

pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(100, 200), direction=Qt.Vertical)
img = QImage(pix)
self.assertTrue(self.imageCheck('color_ramp_vertical', 'color_ramp_vertical', img))

def testPreviewColorRampVerticalFlipped(self):
r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255))

pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(100, 200), direction=Qt.Vertical, flipDirection=True)
img = QImage(pix)
self.assertTrue(self.imageCheck('color_ramp_vertical_flipped', 'color_ramp_vertical_flipped', img))

def imageCheck(self, name, reference_image, image):
self.report += "<h2>Render {}</h2>\n".format(name)
temp_dir = QDir.tempPath() + '/'
file_name = temp_dir + name + ".png"
image.save(file_name, "PNG")
checker = QgsRenderChecker()
checker.setControlPathPrefix("symbol_layer_utils")
checker.setControlName("expected_" + reference_image)
checker.setRenderedImage(file_name)
checker.setColorTolerance(2)
result = checker.compareImages(name, 20)
PyQgsSymbolLayerUtils.report += checker.report()
return result


if __name__ == '__main__':
unittest.main()
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 928b00a

Please sign in to comment.