Skip to content
Permalink
Browse files
Default to a dark gray instead of black for symbol outlines
Avoiding the very high constrast pure black results in cartographically
more pleasing styles, so it's nice to do this by default.

This should result in nicer looking maps being created in QGIS
when users don't do any manual style tweaks.
  • Loading branch information
nyalldawson committed Feb 2, 2018
1 parent 5b9be7a commit 16e98f2
Show file tree
Hide file tree
Showing 27 changed files with 69 additions and 31 deletions.
@@ -29,7 +29,7 @@

QgsEllipseSymbolLayer::QgsEllipseSymbolLayer()
: mSymbolName( QStringLiteral( "circle" ) )
, mStrokeColor( Qt::black )
, mStrokeColor( QColor( 70, 70, 70 ) )
{
mColor = Qt::white;
mPen.setColor( mStrokeColor );
@@ -1712,7 +1712,7 @@ QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString &svgFilePath, double
mStrokeWidth = 0.3;
mAngle = angle;
mColor = QColor( 255, 255, 255 );
mSvgStrokeColor = QColor( 0, 0, 0 );
mSvgStrokeColor = QColor( 70, 70, 70 );
mSvgStrokeWidth = 0.2;
setDefaultSvgParams();
mSvgPattern = nullptr;
@@ -1729,7 +1729,7 @@ QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray &svgData, double
mStrokeWidth = 0.3;
mAngle = angle;
mColor = QColor( 255, 255, 255 );
mSvgStrokeColor = QColor( 0, 0, 0 );
mSvgStrokeColor = QColor( 70, 70, 70 );
mSvgStrokeWidth = 0.2;
setSubSymbol( new QgsLineSymbol() );
setDefaultSvgParams();
@@ -22,7 +22,7 @@

#define DEFAULT_SIMPLEFILL_COLOR QColor(0,0,255)
#define DEFAULT_SIMPLEFILL_STYLE Qt::SolidPattern
#define DEFAULT_SIMPLEFILL_BORDERCOLOR QColor(0,0,0)
#define DEFAULT_SIMPLEFILL_BORDERCOLOR QColor( 70, 70, 70 )
#define DEFAULT_SIMPLEFILL_BORDERSTYLE Qt::SolidLine
#define DEFAULT_SIMPLEFILL_BORDERWIDTH DEFAULT_LINE_WIDTH
#define DEFAULT_SIMPLEFILL_JOINSTYLE Qt::BevelJoin
@@ -25,7 +25,7 @@

class QgsExpression;

#define DEFAULT_SIMPLELINE_COLOR QColor(0,0,0)
#define DEFAULT_SIMPLELINE_COLOR QColor(70,70,70)
#define DEFAULT_SIMPLELINE_WIDTH DEFAULT_LINE_WIDTH
#define DEFAULT_SIMPLELINE_PENSTYLE Qt::SolidLine
#define DEFAULT_SIMPLELINE_JOINSTYLE Qt::BevelJoin
@@ -1698,8 +1698,8 @@ QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double si
mScaleMethod = scaleMethod;
mStrokeWidth = 0.2;
mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
mColor = QColor( Qt::black );
mStrokeColor = QColor( Qt::black );
mColor = QColor( 70, 70, 70 );
mStrokeColor = QColor( 70, 70, 70 );
updateDefaultAspectRatio();
}

@@ -23,7 +23,7 @@

#define DEFAULT_SIMPLEMARKER_NAME "circle"
#define DEFAULT_SIMPLEMARKER_COLOR QColor(255,0,0)
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR QColor(0,0,0)
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR QColor( 70, 70, 70 )
#define DEFAULT_SIMPLEMARKER_JOINSTYLE Qt::BevelJoin
#define DEFAULT_SIMPLEMARKER_SIZE DEFAULT_POINT_SIZE
#define DEFAULT_SIMPLEMARKER_ANGLE 0
@@ -650,7 +650,7 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer
#define DEFAULT_FONTMARKER_FONT "Dingbats"
#define DEFAULT_FONTMARKER_CHR QChar('A')
#define DEFAULT_FONTMARKER_SIZE POINT2MM(12)
#define DEFAULT_FONTMARKER_COLOR QColor(Qt::black)
#define DEFAULT_FONTMARKER_COLOR QColor( 70, 70, 70 )
#define DEFAULT_FONTMARKER_BORDERCOLOR QColor(Qt::white)
#define DEFAULT_FONTMARKER_JOINSTYLE Qt::MiterJoin
#define DEFAULT_FONTMARKER_ANGLE 0
@@ -30,6 +30,7 @@
#include <qgssymbol.h>
#include <qgssinglesymbolrenderer.h>
#include <qgsfillsymbollayer.h>
#include "qgsmarkersymbollayer.h"

//qgis test includes
#include "qgsrenderchecker.h"
@@ -94,6 +95,7 @@ void TestQgsCentroidFillSymbol::initTestCase()

//setup gradient fill
mCentroidFill = new QgsCentroidFillSymbolLayer();
static_cast< QgsSimpleMarkerSymbolLayer * >( mCentroidFill->subSymbol()->symbolLayer( 0 ) )->setStrokeColor( Qt::black );
mFillSymbol = new QgsFillSymbol();
mFillSymbol->changeSymbolLayer( 0, mCentroidFill );
mSymbolRenderer = new QgsSingleSymbolRenderer( mFillSymbol );
@@ -381,6 +381,7 @@ void TestQgsLayerTree::testLegendSymbolCategorized()
renderer->setSourceSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "#ff0000" ) );
props.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#000000" ) );
renderer->addCategory( QgsRendererCategory( "a", QgsMarkerSymbol::createSimple( props ), QStringLiteral( "a" ) ) );
props.insert( QStringLiteral( "color" ), QStringLiteral( "#00ff00" ) );
renderer->addCategory( QgsRendererCategory( "b", QgsMarkerSymbol::createSimple( props ), QStringLiteral( "b" ) ) );
@@ -397,6 +398,7 @@ void TestQgsLayerTree::testLegendSymbolGraduated()
renderer->setSourceSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "#ff0000" ) );
props.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#000000" ) );
renderer->addClass( QgsRendererRange( 1, 2, QgsMarkerSymbol::createSimple( props ), QStringLiteral( "a" ) ) );
props.insert( QStringLiteral( "color" ), QStringLiteral( "#00ff00" ) );
renderer->addClass( QgsRendererRange( 2, 3, QgsMarkerSymbol::createSimple( props ), QStringLiteral( "b" ) ) );
@@ -411,6 +413,7 @@ void TestQgsLayerTree::testLegendSymbolRuleBased()
QgsRuleBasedRenderer::Rule *root = new QgsRuleBasedRenderer::Rule( nullptr );
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "#ff0000" ) );
props.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#000000" ) );
root->appendChild( new QgsRuleBasedRenderer::Rule( QgsMarkerSymbol::createSimple( props ), 0, 0, QStringLiteral( "\"col1\"=1" ) ) );
props.insert( QStringLiteral( "color" ), QStringLiteral( "#00ff00" ) );
root->appendChild( new QgsRuleBasedRenderer::Rule( QgsMarkerSymbol::createSimple( props ), 0, 0, QStringLiteral( "\"col1\"=2" ) ) );
@@ -509,6 +512,7 @@ void TestQgsLayerTree::testRendererLegend( QgsFeatureRenderer *renderer )
//another test - check directly setting symbol at renderer
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "#00ffff" ) );
props.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#000000" ) );
renderer->setLegendSymbolItem( symbolList.at( 2 ).ruleKey(), QgsMarkerSymbol::createSimple( props ) );
m->refreshLayerLegend( n );
symbolNode = dynamic_cast< QgsSymbolLegendNode * >( m->findLegendNode( vl->id(), symbolList.at( 2 ).ruleKey() ) );
@@ -130,6 +130,7 @@ void TestQgsLayoutAtlas::init()
// fix the renderer, fill with green
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "0,127,0" ) );
props.insert( QStringLiteral( "outline_color" ), QStringLiteral( "0,0,0" ) );
QgsFillSymbol *fillSymbol = QgsFillSymbol::createSimple( props );
QgsSingleSymbolRenderer *renderer = new QgsSingleSymbolRenderer( fillSymbol );
mVectorLayer->setRenderer( renderer );
@@ -157,6 +158,7 @@ void TestQgsLayoutAtlas::init()
// set the fill symbol of the overview map
QgsStringMap props2;
props2.insert( QStringLiteral( "color" ), QStringLiteral( "127,0,0,127" ) );
props2.insert( QStringLiteral( "outline_color" ), QStringLiteral( "0,0,0" ) );
QgsFillSymbol *fillSymbol2 = QgsFillSymbol::createSimple( props2 );
mOverview->overview()->setFrameSymbol( fillSymbol2 );

@@ -1877,6 +1877,7 @@ void TestQgsLayoutItem::blendMode()
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( Qt::black );
mComposerRect1->setSymbol( fillSymbol );
delete fillSymbol;

@@ -1889,6 +1890,7 @@ void TestQgsLayoutItem::blendMode()
QgsFillSymbol *fillSymbol2 = new QgsFillSymbol();
fillSymbol2->changeSymbolLayer( 0, simpleFill2 );
simpleFill2->setColor( QColor( 0, 100, 150 ) );
simpleFill2->setStrokeColor( Qt::black );
mComposerRect2->setSymbol( fillSymbol2 );
delete fillSymbol2;

@@ -1926,6 +1928,7 @@ void TestQgsLayoutItem::opacity()
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( Qt::black );
mComposerRect1->setSymbol( fillSymbol );
delete fillSymbol;

@@ -1938,6 +1941,7 @@ void TestQgsLayoutItem::opacity()
QgsFillSymbol *fillSymbol2 = new QgsFillSymbol();
fillSymbol2->changeSymbolLayer( 0, simpleFill2 );
simpleFill2->setColor( QColor( 0, 100, 150 ) );
simpleFill2->setStrokeColor( Qt::black );
mComposerRect2->setSymbol( fillSymbol2 );
delete fillSymbol2;

@@ -20,6 +20,7 @@
#include "qgsmultirenderchecker.h"
#include "qgslayoutitemmap.h"
#include "qgslayoutitemmapgrid.h"
#include "qgsmarkersymbollayer.h"
#include "qgsfontutils.h"
#include "qgsproject.h"
#include <QObject>
@@ -233,6 +234,7 @@ void TestQgsLayoutMapGrid::markerGrid()
map->grid()->setIntervalY( 2000 );
map->grid()->setGridLineWidth( 0.5 );
map->grid()->setGridLineColor( QColor( 0, 0, 0 ) );
static_cast< QgsSimpleMarkerSymbolLayer * >( map->grid()->markerSymbol()->symbolLayer( 0 ) )->setStrokeColor( Qt::black );
map->updateBoundingRect();
l.addLayoutItem( map );

@@ -24,6 +24,7 @@
#include "qgssinglesymbolrenderer.h"
#include "qgsfillsymbollayer.h"
#include "qgslinesymbollayer.h"
#include "qgsmarkersymbollayer.h"
#include "qgsmultirenderchecker.h"
#include "qgslayoutpagecollection.h"
#include <QObject>
@@ -234,6 +235,7 @@ void TestQgsLayoutPage::markerLinePaper()
l.pageCollection()->addPage( page.release() );

QgsMarkerLineSymbolLayer *markerLine = new QgsMarkerLineSymbolLayer();
static_cast< QgsSimpleMarkerSymbolLayer * >( markerLine->subSymbol()->symbolLayer( 0 ) )->setStrokeColor( Qt::black );
std::unique_ptr< QgsFillSymbol > markerLineSymbol = qgis::make_unique< QgsFillSymbol >();
markerLineSymbol->changeSymbolLayer( 0, markerLine );
l.pageCollection()->setPageStyleSymbol( markerLineSymbol.get() );
@@ -303,6 +303,7 @@ void TestQgsLayoutShapes::shapeRotation()
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
simpleFill->setStrokeColor( Qt::black );
//simpleFill->setStrokeColor( Qt::yellow );
//simpleFill->setStrokeWidth( 6 );
shape->setSymbol( fillSymbol );
@@ -133,6 +133,7 @@ void TestQgsPointPatternFillSymbol::pointPatternFillSymbol()

QgsStringMap properties;
properties.insert( QStringLiteral( "color" ), QStringLiteral( "0,0,0,255" ) );
properties.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#000000" ) );
properties.insert( QStringLiteral( "name" ), QStringLiteral( "circle" ) );
properties.insert( QStringLiteral( "size" ), QStringLiteral( "5.0" ) );
QgsMarkerSymbol *pointSymbol = QgsMarkerSymbol::createSimple( properties );
@@ -147,6 +148,7 @@ void TestQgsPointPatternFillSymbol::dataDefinedSubSymbol()

QgsStringMap properties;
properties.insert( QStringLiteral( "color" ), QStringLiteral( "0,0,0,255" ) );
properties.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#000000" ) );
properties.insert( QStringLiteral( "name" ), QStringLiteral( "circle" ) );
properties.insert( QStringLiteral( "size" ), QStringLiteral( "5.0" ) );
QgsMarkerSymbol *pointSymbol = QgsMarkerSymbol::createSimple( properties );
@@ -30,6 +30,7 @@
#include "qgslinesymbollayer.h"
#include "qgsfillsymbollayer.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsmarkersymbollayer.h"

#include "qgsstyle.h"

@@ -177,6 +178,7 @@ void TestQgsSymbol::testCanvasClip()

QgsMarkerLineSymbolLayer *markerLine = new QgsMarkerLineSymbolLayer();
markerLine->setPlacement( QgsMarkerLineSymbolLayer:: CentralPoint );
static_cast< QgsSimpleMarkerSymbolLayer *>( markerLine->subSymbol()->symbolLayer( 0 ) )->setStrokeColor( Qt::black );
QgsLineSymbol *lineSymbol = new QgsLineSymbol();
lineSymbol->changeSymbolLayer( 0, markerLine );
QgsSingleSymbolRenderer *renderer = new QgsSingleSymbolRenderer( lineSymbol );
@@ -196,6 +198,7 @@ void TestQgsSymbol::testCanvasClip()
ms.setLayers( QList<QgsMapLayer *>() << mpPolysLayer );

QgsCentroidFillSymbolLayer *centroidFill = new QgsCentroidFillSymbolLayer();
static_cast< QgsSimpleMarkerSymbolLayer * >( centroidFill->subSymbol()->symbolLayer( 0 ) )->setStrokeColor( Qt::black );
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, centroidFill );
renderer = new QgsSingleSymbolRenderer( fillSymbol );
@@ -55,6 +55,8 @@ def tearDown(self):
def testTextAnnotation(self):
""" test rendering a text annotation"""
a = QgsTextAnnotation()
a.fillSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.markerSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.setFrameSize(QSizeF(300, 200))
a.setFrameOffsetFromReferencePoint(QPointF(40, 50))
doc = QTextDocument()
@@ -71,6 +73,8 @@ def testTextAnnotation(self):
def testSvgAnnotation(self):
""" test rendering a svg annotation"""
a = QgsSvgAnnotation()
a.fillSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.markerSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.setFrameSize(QSizeF(300, 200))
a.setFrameOffsetFromReferencePoint(QPointF(40, 50))
svg = TEST_DATA_DIR + "/sample_svg.svg"
@@ -86,6 +90,8 @@ def testSvgAnnotation(self):
def testHtmlAnnotation(self):
""" test rendering a html annotation"""
a = QgsHtmlAnnotation()
a.fillSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.markerSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.setFrameSize(QSizeF(400, 250))
a.setFrameOffsetFromReferencePoint(QPointF(70, 90))
html = TEST_DATA_DIR + "/test_html.html"
@@ -104,6 +110,8 @@ def testHtmlAnnotationWithFeature(self):
'test', "memory")

a = QgsHtmlAnnotation()
a.fillSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.markerSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.setFrameSize(QSizeF(400, 250))
a.setFrameOffsetFromReferencePoint(QPointF(70, 90))
a.setMapLayer(layer)
@@ -121,6 +129,7 @@ def testHtmlAnnotationWithFeature(self):
def testRelativePosition(self):
""" test rendering an annotation without map point"""
a = QgsHtmlAnnotation()
a.fillSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.setFrameSize(QSizeF(400, 250))
a.setHasFixedMapPosition(False)
html = TEST_DATA_DIR + "/test_html.html"
@@ -131,6 +140,7 @@ def testRelativePosition(self):
def testMargins(self):
""" test rendering an annotation with margins"""
a = QgsHtmlAnnotation()
a.fillSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
a.setFrameSize(QSizeF(400, 250))
a.setHasFixedMapPosition(False)
a.setContentsMargin(QgsMargins(15, 10, 30, 20))
@@ -144,7 +154,7 @@ def testFillSymbol(self):
a = QgsTextAnnotation()
a.setFrameSize(QSizeF(400, 250))
a.setHasFixedMapPosition(False)
a.setFillSymbol(QgsFillSymbol.createSimple({'color': 'blue', 'width_border': '5'}))
a.setFillSymbol(QgsFillSymbol.createSimple({'color': 'blue', 'width_border': '5', 'outline_color': 'black'}))
im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('annotation_fillstyle', 'annotation_fillstyle', im))

@@ -58,6 +58,7 @@ def testSimpleLineWithOffset(self):
""" test that rendering a polygon with simple line symbol with offset results in closed line"""
layer = QgsSimpleLineSymbolLayer()
layer.setOffset(-1)
layer.setColor(QColor(0, 0, 0))

symbol = QgsFillSymbol()
symbol.changeSymbolLayer(0, layer)
@@ -28,7 +28,7 @@
import os

from qgis.PyQt.QtCore import QSize

from qgis.PyQt.QtGui import QColor
from qgis.core import (
QgsVectorLayer,
QgsSingleSymbolRenderer,
@@ -68,9 +68,9 @@ def setUp(self):
QgsProject.instance().addMapLayer(self.points_layer)

# Create style
sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f'})
sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'})
sym2 = QgsLineSymbol.createSimple({'color': '#fdbf6f'})
sym3 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f'})
sym3 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'})

self.polys_layer.setRenderer(QgsSingleSymbolRenderer(sym1))
self.lines_layer.setRenderer(QgsSingleSymbolRenderer(sym2))
@@ -88,6 +88,7 @@ def test_marker(self):
sym = self.polys_layer.renderer().symbol()
sym_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'centroid($geometry)'})
sym_layer.setSymbolType(QgsSymbol.Marker)
sym_layer.subSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
sym.changeSymbolLayer(0, sym_layer)

rendered_layers = [self.polys_layer]
@@ -101,12 +102,14 @@ def test_marker(self):
def test_mixed(self):
sym = self.polys_layer.renderer().symbol()

buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, "value"/15)'})
buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, "value"/15)', 'outline_color': 'black'})
buffer_layer.setSymbolType(QgsSymbol.Fill)
buffer_layer.subSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
self.assertIsNotNone(buffer_layer.subSymbol())
sym.appendSymbolLayer(buffer_layer)
marker_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'centroid($geometry)'})
marker_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'centroid($geometry)', 'outline_color': 'black'})
marker_layer.setSymbolType(QgsSymbol.Marker)
marker_layer.subSymbol().symbolLayer(0).setStrokeColor(QColor(0, 0, 0))
sym.appendSymbolLayer(marker_layer)

rendered_layers = [self.polys_layer]
@@ -120,7 +123,7 @@ def test_mixed(self):
def test_buffer_lines(self):
sym = self.lines_layer.renderer().symbol()

buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, "value"/15)'})
buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, "value"/15)', 'outline_color': 'black'})
buffer_layer.setSymbolType(QgsSymbol.Fill)
self.assertIsNotNone(buffer_layer.subSymbol())
sym.appendSymbolLayer(buffer_layer)
@@ -136,7 +139,7 @@ def test_buffer_lines(self):
def test_buffer_points(self):
sym = self.points_layer.renderer().symbol()

buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, "staff"/15)'})
buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, "staff"/15)', 'outline_color': 'black'})
buffer_layer.setSymbolType(QgsSymbol.Fill)
self.assertIsNotNone(buffer_layer.subSymbol())
sym.appendSymbolLayer(buffer_layer)

0 comments on commit 16e98f2

Please sign in to comment.