Skip to content

Commit

Permalink
fix: correct display of StrokePattern.solid at high zoom levels (fl…
Browse files Browse the repository at this point in the history
…eaflet#1871)

fix: 1864 - correct display of solid style in high zoom levels

Impacted files:
* `polygon_layer/painter.dart`: now using the new `SolidPixelHiker` for solid style display
* `polyline_layer/painter.dart`: now using the new `SolidPixelHiker` for solid style display
* `pixel_hiker.dart`: new `SolidPixelHiker` class
  • Loading branch information
monsieurtanuki authored May 6, 2024
1 parent 930e8b6 commit 3e8cd97
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 15 deletions.
51 changes: 50 additions & 1 deletion lib/src/layer/misc/line_patterns/pixel_hiker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,45 @@ class DashedPixelHiker extends _PixelHiker {
}
}

/// Pixel hiker that lists the visible solid segments to display on the way.
@internal
class SolidPixelHiker extends _PixelHiker {
/// Standard Solid Pixel Hiker constructor.
SolidPixelHiker({
required super.offsets,
required super.closePath,
required super.canvasSize,
}) : super(
segmentValues: [],
patternFit: PatternFit.none,
);

/// Returns all visible segments.
List<VisibleSegment> getAllVisibleSegments() {
final List<VisibleSegment> result = [];

if (offsets.length < 2) {
return result;
}

for (int i = 0; i < offsets.length - 1 + (closePath ? 1 : 0); i++) {
final VisibleSegment? visibleSegment = VisibleSegment.getVisibleSegment(
offsets[i],
offsets[(i + 1) % offsets.length],
canvasSize,
);
if (visibleSegment != null) {
result.add(visibleSegment);
}
}

return result;
}

@override
double getFactor() => 1;
}

/// Pixel hiker that lists the visible items on the way.
sealed class _PixelHiker {
_PixelHiker({
Expand All @@ -253,6 +292,13 @@ sealed class _PixelHiker {

final List<Offset> offsets;
final bool closePath;

/// List of segments' lengths.
///
/// Expected number of items:
/// * empty for "solid"
/// * > 0 and even for "dashed": (dash size _ space size) * n
/// * only 1 item for "dotted": the size of the space
final List<double> segmentValues;
final Size canvasSize;
final PatternFit patternFit;
Expand Down Expand Up @@ -290,6 +336,9 @@ sealed class _PixelHiker {

@protected
void nextSegment() {
if (segmentValues.isEmpty) {
return;
}
_segmentIndex = (_segmentIndex + 1) % segmentValues.length;
_remaining = segmentValues[_segmentIndex];
}
Expand All @@ -305,7 +354,7 @@ sealed class _PixelHiker {
@protected
Offset getIntermediateOffset(final Offset offsetA, final Offset offsetB) {
final segmentDistance = getDistance(offsetA, offsetB);
if (_remaining >= segmentDistance) {
if (segmentValues.isEmpty || _remaining >= segmentDistance) {
_used = segmentDistance;
return offsetB;
}
Expand Down
19 changes: 12 additions & 7 deletions lib/src/layer/polygon_layer/painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,20 @@ class _PolygonPainter<R extends Object> extends CustomPainter {
Canvas canvas,
Paint paint,
) {
final isSolid = polygon.pattern == const StrokePattern.solid();
final isDashed = polygon.pattern.segments != null;
final isDotted = polygon.pattern.spacingFactor != null;
if (isDotted) {
if (isSolid) {
final SolidPixelHiker hiker = SolidPixelHiker(
offsets: offsets,
closePath: true,
canvasSize: canvasSize,
);
for (final visibleSegment in hiker.getAllVisibleSegments()) {
path.moveTo(visibleSegment.begin.dx, visibleSegment.begin.dy);
path.lineTo(visibleSegment.end.dx, visibleSegment.end.dy);
}
} else if (isDotted) {
final DottedPixelHiker hiker = DottedPixelHiker(
offsets: offsets,
stepLength: polygon.borderStrokeWidth * polygon.pattern.spacingFactor!,
Expand All @@ -341,8 +352,6 @@ class _PolygonPainter<R extends Object> extends CustomPainter {
path.moveTo(visibleSegment.begin.dx, visibleSegment.begin.dy);
path.lineTo(visibleSegment.end.dx, visibleSegment.end.dy);
}
} else {
_addLineToPath(path, offsets);
}
}

Expand All @@ -366,10 +375,6 @@ class _PolygonPainter<R extends Object> extends CustomPainter {
}
}

void _addLineToPath(Path path, List<Offset> offsets) {
path.addPolygon(offsets, true);
}

({Offset min, Offset max}) _getBounds(Offset origin, Polygon polygon) {
final bBox = polygon.boundingBox;
return (
Expand Down
21 changes: 14 additions & 7 deletions lib/src/layer/polyline_layer/painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class _PolylinePainter<R extends Object> extends CustomPainter {
strokeWidth = polyline.strokeWidth;
}

final isSolid = polyline.pattern == const StrokePattern.solid();
final isDashed = polyline.pattern.segments != null;
final isDotted = polyline.pattern.spacingFactor != null;

Expand Down Expand Up @@ -207,7 +208,19 @@ class _PolylinePainter<R extends Object> extends CustomPainter {
paths.add(filterPath);
}
paths.add(path);
if (isDotted) {
if (isSolid) {
final SolidPixelHiker hiker = SolidPixelHiker(
offsets: offsets,
closePath: false,
canvasSize: size,
);
for (final visibleSegment in hiker.getAllVisibleSegments()) {
for (final path in paths) {
path.moveTo(visibleSegment.begin.dx, visibleSegment.begin.dy);
path.lineTo(visibleSegment.end.dx, visibleSegment.end.dy);
}
}
} else if (isDotted) {
final DottedPixelHiker hiker = DottedPixelHiker(
offsets: offsets,
stepLength: strokeWidth * polyline.pattern.spacingFactor!,
Expand Down Expand Up @@ -244,12 +257,6 @@ class _PolylinePainter<R extends Object> extends CustomPainter {
path.lineTo(visibleSegment.end.dx, visibleSegment.end.dy);
}
}
} else {
if (offsets.isNotEmpty) {
for (final path in paths) {
path.addPolygon(offsets, false);
}
}
}
}

Expand Down

0 comments on commit 3e8cd97

Please sign in to comment.