mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
Enable line join styles and miter limit. (#3777)
* Add support for join types and miter limits. * Fix miter limit data type. * Adding some clearer documentation to painting.dart * Clarifying more documentation. * Code review changes * Fixed debug printing of stroke width and miter limit * Adding missing periods at the ends of sentences.
This commit is contained in:
committed by
Ian Hickson
parent
80f039ff32
commit
5403f65bca
+78
-9
@@ -286,6 +286,25 @@ enum StrokeCap {
|
||||
square,
|
||||
}
|
||||
|
||||
/// Styles to use for line joins.
|
||||
///
|
||||
/// This only affects line joins for polygons drawn by [Canvas.drawPath] and
|
||||
/// rectangles, not points drawn as lines with [Canvas.drawPoints].
|
||||
///
|
||||
/// See [Paint.strokeJoin].
|
||||
// These enum values must be kept in sync with SkPaint::Join.
|
||||
enum StrokeJoin {
|
||||
/// Joins between line segments form sharp corners.
|
||||
miter,
|
||||
|
||||
/// Joins between line segments are semi-circular.
|
||||
round,
|
||||
|
||||
/// Joins between line segments connect the corners of the butt ends of the
|
||||
/// line segments to give a beveled appearance.
|
||||
bevel,
|
||||
}
|
||||
|
||||
/// Strategies for painting shapes and paths on a canvas.
|
||||
///
|
||||
/// See [Paint.style].
|
||||
@@ -321,7 +340,7 @@ class Paint {
|
||||
// * _data is binary data in four-byte fields, each of which is either a
|
||||
// uint32_t or a float. The default value for each field is encoded as
|
||||
// zero to make initialization trivial. Most values already have a default
|
||||
// value of zero, but some, such a color, have a non-zero default value.
|
||||
// value of zero, but some, such as color, have a non-zero default value.
|
||||
// To encode or decode these values, XOR the value with the default value.
|
||||
//
|
||||
// * _objects is a list of unencodable objects, typically wrappers for native
|
||||
@@ -337,10 +356,12 @@ class Paint {
|
||||
static const int _kStyleIndex = 3;
|
||||
static const int _kStrokeWidthIndex = 4;
|
||||
static const int _kStrokeCapIndex = 5;
|
||||
static const int _kFilterQualityIndex = 6;
|
||||
static const int _kColorFilterIndex = 7;
|
||||
static const int _kColorFilterColorIndex = 8;
|
||||
static const int _kColorFilterBlendModeIndex = 9;
|
||||
static const int _kStrokeJoinIndex = 6;
|
||||
static const int _kStrokeMiterLimitIndex = 7;
|
||||
static const int _kFilterQualityIndex = 8;
|
||||
static const int _kColorFilterIndex = 9;
|
||||
static const int _kColorFilterColorIndex = 10;
|
||||
static const int _kColorFilterBlendModeIndex = 11;
|
||||
|
||||
static const int _kIsAntiAliasOffset = _kIsAntiAliasIndex << 2;
|
||||
static const int _kColorOffset = _kColorIndex << 2;
|
||||
@@ -348,12 +369,14 @@ class Paint {
|
||||
static const int _kStyleOffset = _kStyleIndex << 2;
|
||||
static const int _kStrokeWidthOffset = _kStrokeWidthIndex << 2;
|
||||
static const int _kStrokeCapOffset = _kStrokeCapIndex << 2;
|
||||
static const int _kStrokeJoinOffset = _kStrokeJoinIndex << 2;
|
||||
static const int _kStrokeMiterLimitOffset = _kStrokeMiterLimitIndex << 2;
|
||||
static const int _kFilterQualityOffset = _kFilterQualityIndex << 2;
|
||||
static const int _kColorFilterOffset = _kColorFilterIndex << 2;
|
||||
static const int _kColorFilterColorOffset = _kColorFilterColorIndex << 2;
|
||||
static const int _kColorFilterBlendModeOffset = _kColorFilterBlendModeIndex << 2;
|
||||
// If you add more fields, remember to update _kDataByteCount.
|
||||
static const int _kDataByteCount = 40;
|
||||
static const int _kDataByteCount = 48;
|
||||
|
||||
// Binary format must match the deserialization code in paint.cc.
|
||||
List<dynamic> _objects;
|
||||
@@ -375,6 +398,7 @@ class Paint {
|
||||
_data.setInt32(_kIsAntiAliasOffset, encoded, _kFakeHostEndian);
|
||||
}
|
||||
|
||||
// Must be kept in sync with the default in paint.cc.
|
||||
static const int _kColorDefault = 0xFF000000;
|
||||
|
||||
/// The color to use when stroking or filling a shape.
|
||||
@@ -399,6 +423,7 @@ class Paint {
|
||||
_data.setInt32(_kColorOffset, encoded, _kFakeHostEndian);
|
||||
}
|
||||
|
||||
// Must be kept in sync with the default in paint.cc.
|
||||
static final int _kBlendModeDefault = BlendMode.srcOver.index;
|
||||
|
||||
/// A blend mode to apply when a shape is drawn or a layer is composited.
|
||||
@@ -461,6 +486,44 @@ class Paint {
|
||||
_data.setInt32(_kStrokeCapOffset, encoded, _kFakeHostEndian);
|
||||
}
|
||||
|
||||
/// The kind of finish to place on the joins between segments.
|
||||
///
|
||||
/// This applies to paths drawn when [style] is set to [PaintingStyle.stroke],
|
||||
/// It does not apply to points drawn as lines with [Canvas.drawPoints].
|
||||
///
|
||||
/// Defaults to [StrokeJoin.miter], i.e. sharp corners. See also
|
||||
/// [strokeMiterLimit] to control when miters are replaced by bevels.
|
||||
StrokeJoin get strokeJoin {
|
||||
return StrokeJoin.values[_data.getInt32(_kStrokeJoinOffset, _kFakeHostEndian)];
|
||||
}
|
||||
set strokeJoin(StrokeJoin value) {
|
||||
assert(value != null);
|
||||
final int encoded = value.index;
|
||||
_data.setInt32(_kStrokeJoinOffset, encoded, _kFakeHostEndian);
|
||||
}
|
||||
|
||||
// Must be kept in sync with the default in paint.cc.
|
||||
static final double _kStrokeMiterLimitDefault = 4.0;
|
||||
|
||||
/// The limit for miters to be drawn on segments when the join is set to
|
||||
/// [StrokeJoin.miter] and the [style] is set to [PaintingStyle.stroke]. If
|
||||
/// this limit is exceeded, then a [StrokeJoin.bevel] join will be drawn
|
||||
/// instead. This may cause some 'popping' of the corners of a path if the
|
||||
/// angle between line segments is animated.
|
||||
///
|
||||
/// This limit is expressed as a limit on the length of the miter.
|
||||
///
|
||||
/// Defaults to 4.0. Using zero as a limit will cause a [StrokeJoin.bevel]
|
||||
/// join to be used all the time.
|
||||
double get strokeMiterLimit {
|
||||
return _data.getFloat32(_kStrokeMiterLimitOffset, _kFakeHostEndian);
|
||||
}
|
||||
set strokeMiterLimit(double value) {
|
||||
assert(value != null);
|
||||
final double encoded = value - _kStrokeMiterLimitDefault;
|
||||
_data.setFloat32(_kStrokeMiterLimitOffset, encoded, _kFakeHostEndian);
|
||||
}
|
||||
|
||||
/// A mask filter (for example, a blur) to apply to a shape after it has been
|
||||
/// drawn but before it has been composited into the image.
|
||||
///
|
||||
@@ -547,25 +610,31 @@ class Paint {
|
||||
if (style == PaintingStyle.stroke) {
|
||||
result.write('$style');
|
||||
if (strokeWidth != 0.0)
|
||||
result.write(' $strokeWidth');
|
||||
result.write(' ${strokeWidth.toStringAsFixed(1)}');
|
||||
else
|
||||
result.write(' hairline');
|
||||
if (strokeCap != StrokeCap.butt)
|
||||
result.write(' $strokeCap');
|
||||
if (strokeJoin == StrokeJoin.miter) {
|
||||
if (strokeMiterLimit != _kStrokeMiterLimitDefault)
|
||||
result.write(' $strokeJoin up to ${strokeMiterLimit.toStringAsFixed(1)}');
|
||||
} else {
|
||||
result.write(' $strokeJoin');
|
||||
}
|
||||
semicolon = '; ';
|
||||
}
|
||||
if (isAntiAlias != true) {
|
||||
result.write('${semicolon}antialias off');
|
||||
semicolon = '; ';
|
||||
}
|
||||
if (color != const Color(0xFF000000)) {
|
||||
if (color != const Color(_kColorDefault)) {
|
||||
if (color != null)
|
||||
result.write('$semicolon$color');
|
||||
else
|
||||
result.write('${semicolon}no color');
|
||||
semicolon = '; ';
|
||||
}
|
||||
if (blendMode != BlendMode.srcOver) {
|
||||
if (blendMode.index != _kBlendModeDefault) {
|
||||
result.write('$semicolon$blendMode');
|
||||
semicolon = '; ';
|
||||
}
|
||||
|
||||
@@ -23,16 +23,29 @@ constexpr int kBlendModeIndex = 2;
|
||||
constexpr int kStyleIndex = 3;
|
||||
constexpr int kStrokeWidthIndex = 4;
|
||||
constexpr int kStrokeCapIndex = 5;
|
||||
constexpr int kFilterQualityIndex = 6;
|
||||
constexpr int kColorFilterIndex = 7;
|
||||
constexpr int kColorFilterColorIndex = 8;
|
||||
constexpr int kColorFilterBlendModeIndex = 9;
|
||||
constexpr size_t kDataByteCount = 40;
|
||||
constexpr int kStrokeJoinIndex = 6;
|
||||
constexpr int kStrokeMiterLimitIndex = 7;
|
||||
constexpr int kFilterQualityIndex = 8;
|
||||
constexpr int kColorFilterIndex = 9;
|
||||
constexpr int kColorFilterColorIndex = 10;
|
||||
constexpr int kColorFilterBlendModeIndex = 11;
|
||||
constexpr size_t kDataByteCount = 48;
|
||||
|
||||
constexpr int kMaskFilterIndex = 0;
|
||||
constexpr int kShaderIndex = 1;
|
||||
constexpr int kObjectCount = 2; // Must be one larger than the largest index
|
||||
|
||||
// Must be kept in sync with the default in painting.dart.
|
||||
constexpr uint32_t kColorDefault = 0xFF000000;
|
||||
|
||||
// Must be kept in sync with the default in painting.dart.
|
||||
constexpr uint32_t kBlendModeDefault =
|
||||
static_cast<uint32_t>(SkBlendMode::kSrcOver);
|
||||
|
||||
// Must be kept in sync with the default in painting.dart, and also with the
|
||||
// default SkPaintDefaults_MiterLimit in Skia (which is not in a public header).
|
||||
constexpr double kStrokeMiterLimitDefault = 4.0;
|
||||
|
||||
Paint DartConverter<Paint>::FromArguments(Dart_NativeArguments args,
|
||||
int index,
|
||||
Dart_Handle& exception) {
|
||||
@@ -78,14 +91,14 @@ Paint DartConverter<Paint>::FromArguments(Dart_NativeArguments args,
|
||||
|
||||
uint32_t encoded_color = uint_data[kColorIndex];
|
||||
if (encoded_color) {
|
||||
SkColor color = encoded_color ^ 0xFF000000;
|
||||
SkColor color = encoded_color ^ kColorDefault;
|
||||
paint.setColor(color);
|
||||
}
|
||||
|
||||
uint32_t encoded_blend_mode = uint_data[kBlendModeIndex];
|
||||
if (encoded_blend_mode) {
|
||||
uint32_t blend_mode =
|
||||
encoded_blend_mode ^ static_cast<uint32_t>(SkBlendMode::kSrcOver);
|
||||
encoded_blend_mode ^ kBlendModeDefault;
|
||||
paint.setBlendMode(static_cast<SkBlendMode>(blend_mode));
|
||||
}
|
||||
|
||||
@@ -101,6 +114,14 @@ Paint DartConverter<Paint>::FromArguments(Dart_NativeArguments args,
|
||||
if (stroke_cap)
|
||||
paint.setStrokeCap(static_cast<SkPaint::Cap>(stroke_cap));
|
||||
|
||||
uint32_t stroke_join = uint_data[kStrokeJoinIndex];
|
||||
if (stroke_join)
|
||||
paint.setStrokeJoin(static_cast<SkPaint::Join>(stroke_join));
|
||||
|
||||
float stroke_miter_limit = float_data[kStrokeMiterLimitIndex];
|
||||
if (stroke_miter_limit != 0.0)
|
||||
paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
|
||||
|
||||
uint32_t filter_quality = uint_data[kFilterQualityIndex];
|
||||
if (filter_quality)
|
||||
paint.setFilterQuality(static_cast<SkFilterQuality>(filter_quality));
|
||||
|
||||
Reference in New Issue
Block a user