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

fix: correct display of StrokePattern.solid at high zoom levels #1871

Merged
merged 1 commit into from
May 6, 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
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
Loading