Skip to content

Commit

Permalink
Fix distorted line pattern fill when line offset is large compared
Browse files Browse the repository at this point in the history
with pattern distance
  • Loading branch information
nyalldawson committed Oct 12, 2018
1 parent 5b4ed16 commit e277b91
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/core/symbology/qgsfillsymbollayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ void QgsShapeburstFillSymbolLayer::renderPolygon( const QPolygonF &points, QList
if ( !useWholeShape && !qgsDoubleNear( maxDistance, 0.0 ) )
{
//convert max distance to pixels
outputPixelMaxDist = context.renderContext().convertToPainterUnits( maxDistance, mDistanceUnit, mDistanceMapUnitScale );
outputPixelMaxDist = static_cast< int >( std::round( context.renderContext().convertToPainterUnits( maxDistance, mDistanceUnit, mDistanceMapUnitScale ) ) );
}

//if we are using the two color mode, create a gradient ramp
Expand Down Expand Up @@ -2506,6 +2506,15 @@ void QgsLinePatternFillSymbolLayer::applyPattern( const QgsSymbolRenderContext &
double outputPixelDist = ctx.convertToPainterUnits( distance, mDistanceUnit, mDistanceMapUnitScale );
double outputPixelOffset = ctx.convertToPainterUnits( mOffset, mOffsetUnit, mOffsetMapUnitScale );

// NOTE: this may need to be modified if we ever change from a forced rasterized/brush approach,
// because potentially we may want to allow vector based line pattern fills where the first line
// is offset by a large distance

// fix truncated pattern with larger offsets
outputPixelOffset = std::fmod( outputPixelOffset, outputPixelDist );
if ( outputPixelOffset > outputPixelDist / 2.0 )
outputPixelOffset -= outputPixelDist;

// To get all patterns into image, we have to consider symbols size (estimateMaxBleed()).
// For marker lines we have to get markers interval.
double outputPixelBleed = 0;
Expand Down Expand Up @@ -2590,7 +2599,7 @@ void QgsLinePatternFillSymbolLayer::applyPattern( const QgsSymbolRenderContext &

// Add buffer based on bleed but keep precisely the height/width ratio (angle)
// thus we add integer multiplications of width and height covering the bleed
int bufferMulti = std::max( std::ceil( outputPixelBleed / width ), std::ceil( outputPixelBleed / width ) );
int bufferMulti = static_cast< int >( std::max( std::ceil( outputPixelBleed / width ), std::ceil( outputPixelBleed / width ) ) );

// Always buffer at least once so that center of line marker in upper right corner
// does not fall outside due to representation error
Expand Down
12 changes: 12 additions & 0 deletions tests/src/core/testqgslinefillsymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class TestQgsLineFillSymbol : public QObject

void lineFillSymbol();
void lineFillSymbolOffset();
void lineFillLargeOffset();

void dataDefinedSubSymbol();

Expand Down Expand Up @@ -153,6 +154,17 @@ void TestQgsLineFillSymbol::lineFillSymbolOffset()
mLineFill->setOffset( 0 );
}

void TestQgsLineFillSymbol::lineFillLargeOffset()
{
// test line fill with large offset compared to line distance
mLineFill->setOffset( 8 );
QVERIFY( imageCheck( QStringLiteral( "symbol_linefill_large_posoffset" ) ) );

mLineFill->setOffset( -8 );
QVERIFY( imageCheck( QStringLiteral( "symbol_linefill_large_negoffset" ) ) );
mLineFill->setOffset( 0 );
}

void TestQgsLineFillSymbol::dataDefinedSubSymbol()
{
mReport += QLatin1String( "<h2>Line fill symbol data defined sub symbol test</h2>\n" );
Expand Down

0 comments on commit e277b91

Please sign in to comment.