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

provide support for line-dasharray theme style #47

Merged
merged 2 commits into from
Jul 15, 2022
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
12 changes: 10 additions & 2 deletions lib/src/features/line_renderer.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import '../../vector_tile_renderer.dart';
import '../context.dart';
import '../path/path_transform.dart';
import '../path/ring_number_provider.dart';
import '../themes/expression/expression.dart';
import '../themes/style.dart';
import 'feature_renderer.dart';
Expand Down Expand Up @@ -47,13 +49,19 @@ class LineRenderer extends FeatureRenderer {
effectivePaint.strokeWidth =
context.tileSpaceMapper.widthFromPixelToTile(strokeWidth);

final lines = feature.paths;
final dashLengths = effectivePaint.strokeDashPattern
?.map((e) => context.tileSpaceMapper.widthFromPixelToTile(e))
.toList(growable: false);

for (final line in lines) {
final lines = feature.paths;
for (var line in lines) {
if (!context.optimizations.skipInBoundsChecks &&
!context.tileSpaceMapper.isPathWithinTileClip(line)) {
continue;
}
if (dashLengths != null) {
line = line.dashPath(RingNumberProvider(dashLengths));
}
context.canvas.drawPath(line, effectivePaint);
}
}
Expand Down
25 changes: 25 additions & 0 deletions lib/src/path/path_transform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'dart:ui';

import 'ring_number_provider.dart';

extension DashPath on Path {
// creates a new dashed path with the given intervals
Path dashPath(RingNumberProvider dashArray) {
final Path dest = Path();
for (final PathMetric metric in computeMetrics()) {
double distance = .0;
bool draw = true;
while (distance < metric.length) {
final double len = dashArray.next;
if (draw) {
dest.addPath(
metric.extractPath(distance, distance + len), Offset.zero);
}
distance += len;
draw = !draw;
}
}

return dest;
}
}
13 changes: 13 additions & 0 deletions lib/src/path/ring_number_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class RingNumberProvider {
RingNumberProvider(this._vals);

final List<double> _vals;
int _idx = 0;

double get next {
if (_idx >= _vals.length) {
_idx = 0;
}
return _vals[_idx++];
}
}
34 changes: 27 additions & 7 deletions lib/src/themes/paint_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import 'expression/expression.dart';
import 'expression/literal_expression.dart';
import 'expression/numeric_expression.dart';

class PaintExpression extends Expression<Paint> {
class PaintExpression extends Expression<PaintModel> {
final PaintStyle _delegate;

PaintExpression(this._delegate)
: super(_cacheKey(_delegate), _properties(_delegate));

@override
Paint? evaluate(EvaluationContext context) => _delegate.paint(context);
PaintModel? evaluate(EvaluationContext context) => _delegate.paint(context);

@override
bool get isConstant => false;
Expand All @@ -28,21 +28,27 @@ class PaintExpression extends Expression<Paint> {
};
}

class PaintModel extends Paint {
List<double>? strokeDashPattern;
}

class PaintStyle {
final String id;
final PaintingStyle paintingStyle;
final Expression<double> opacity;
final Expression<double> strokeWidth;
final Expression<Color> color;
final List<double>? strokeDashPattern;

PaintStyle(
{required this.id,
required this.paintingStyle,
required this.opacity,
required this.strokeWidth,
required this.color});
required this.color,
required this.strokeDashPattern});

Paint? paint(EvaluationContext context) {
PaintModel? paint(EvaluationContext context) {
final opacity = this.opacity.evaluate(context);
if (opacity != null && opacity <= 0) {
return null;
Expand All @@ -51,7 +57,9 @@ class PaintStyle {
if (color == null) {
return null;
}
final paint = Paint()..style = paintingStyle;
final paint = PaintModel()
..style = paintingStyle
..strokeDashPattern = strokeDashPattern;
if (opacity != null && opacity < 1.0) {
paint.color = color.withOpacity(opacity);
} else {
Expand All @@ -73,7 +81,7 @@ class PaintFactory {
final ExpressionParser expressionParser;
PaintFactory(this.logger) : expressionParser = ExpressionParser(logger);

Expression<Paint>? create(
Expression<PaintModel>? create(
String id, PaintingStyle style, String prefix, paint,
{double? defaultStrokeWidth = 1.0}) {
if (paint == null) {
Expand All @@ -87,11 +95,23 @@ class PaintFactory {
whenNull: () => LiteralExpression(1.0));
final strokeWidth = expressionParser.parse(paint['$prefix-width'],
whenNull: () => LiteralExpression(defaultStrokeWidth));

List<double>? dashArray;
final dashJson = paint['$prefix-dasharray'];
if (dashJson != null && dashJson is List<num> && dashJson.length >= 2) {
if (dashJson.any((element) => element < .0)) {
logger.warn(() => '$prefix-dasharray contains value < 0');
} else {
dashArray = dashJson.map((e) => e.toDouble()).toList(growable: false);
}
}

return PaintExpression(PaintStyle(
id: id,
paintingStyle: style,
opacity: opacity.asDoubleExpression(),
strokeWidth: strokeWidth.asDoubleExpression(),
color: color.asColorExpression()));
color: color.asColorExpression(),
strokeDashPattern: dashArray));
}
}
9 changes: 5 additions & 4 deletions lib/src/themes/style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:math';
import 'dart:ui';

import 'package:flutter/widgets.dart';
import 'package:vector_tile_renderer/src/themes/paint_factory.dart';
import 'expression/expression.dart';

import '../extensions.dart';
Expand All @@ -12,14 +13,14 @@ typedef ColorZoomFunction = Color? Function(double zoom);
typedef TextTransformFunction = String? Function(String? text);

class Style {
final Expression<Paint>? fillPaint;
final Expression<PaintModel>? fillPaint;
final Extrusion? fillExtrusion;
final Expression<Paint>? linePaint;
final Expression<PaintModel>? linePaint;
final LineLayout? lineLayout;
final Expression<Paint>? textPaint;
final Expression<PaintModel>? textPaint;
final TextLayout? textLayout;
final Expression<List<Shadow>>? textHalo;
final Expression<Paint>? outlinePaint;
final Expression<PaintModel>? outlinePaint;

Style(
{this.fillPaint,
Expand Down