提交 28201577 编写于 作者: R Razvan Lung 提交者: Dan Field

add ColorFilter matrix support (#7459)

* add ColorFilter matrix support
上级 82097a42
......@@ -1082,7 +1082,8 @@ class Paint {
// Binary format must match the deserialization code in paint.cc.
List<dynamic> _objects;
static const int _kShaderIndex = 0;
static const int _kObjectCount = 1; // Must be one larger than the largest index.
static const int _kColorFilterMatrixIndex = 1;
static const int _kObjectCount = 2; // Must be one larger than the largest index.
/// Whether to apply anti-aliasing to lines and images drawn on the
/// canvas.
......@@ -1336,25 +1337,49 @@ class Paint {
///
/// When a shape is being drawn, [colorFilter] overrides [color] and [shader].
ColorFilter get colorFilter {
final bool isNull = _data.getInt32(_kColorFilterOffset, _kFakeHostEndian) == 0;
if (isNull)
return null;
return new ColorFilter.mode(
new Color(_data.getInt32(_kColorFilterColorOffset, _kFakeHostEndian)),
BlendMode.values[_data.getInt32(_kColorFilterBlendModeOffset, _kFakeHostEndian)]
);
switch (_data.getInt32(_kColorFilterOffset, _kFakeHostEndian)) {
case ColorFilter._TypeNone:
return null;
case ColorFilter._TypeMode:
return new ColorFilter.mode(
new Color(_data.getInt32(_kColorFilterColorOffset, _kFakeHostEndian)),
BlendMode.values[_data.getInt32(_kColorFilterBlendModeOffset, _kFakeHostEndian)],
);
case ColorFilter._TypeMatrix:
return new ColorFilter.matrix(_objects[_kColorFilterMatrixIndex]);
case ColorFilter._TypeLinearToSrgbGamma:
return const ColorFilter.linearToSrgbGamma();
case ColorFilter._TypeSrgbToLinearGamma:
return const ColorFilter.srgbToLinearGamma();
}
return null;
}
set colorFilter(ColorFilter value) {
if (value == null) {
_data.setInt32(_kColorFilterOffset, 0, _kFakeHostEndian);
_data.setInt32(_kColorFilterOffset, ColorFilter._TypeNone, _kFakeHostEndian);
_data.setInt32(_kColorFilterColorOffset, 0, _kFakeHostEndian);
_data.setInt32(_kColorFilterBlendModeOffset, 0, _kFakeHostEndian);
if (_objects != null) {
_objects[_kColorFilterMatrixIndex] = null;
}
} else {
assert(value._color != null);
assert(value._blendMode != null);
_data.setInt32(_kColorFilterOffset, 1, _kFakeHostEndian);
_data.setInt32(_kColorFilterColorOffset, value._color.value, _kFakeHostEndian);
_data.setInt32(_kColorFilterBlendModeOffset, value._blendMode.index, _kFakeHostEndian);
_data.setInt32(_kColorFilterOffset, value._type, _kFakeHostEndian);
if (value._type == ColorFilter._TypeMode) {
assert(value._color != null);
assert(value._blendMode != null);
_data.setInt32(_kColorFilterColorOffset, value._color.value, _kFakeHostEndian);
_data.setInt32(_kColorFilterBlendModeOffset, value._blendMode.index, _kFakeHostEndian);
} else if (value._type == ColorFilter._TypeMatrix) {
assert(value._matrix != null);
_objects ??= new List<dynamic>(_kObjectCount);
_objects[_kColorFilterMatrixIndex] = Float32List.fromList(value._matrix);
}
}
}
......@@ -2378,25 +2403,84 @@ class ColorFilter {
/// to the [Paint.blendMode], using the output of this filter as the source
/// and the background as the destination.
const ColorFilter.mode(Color color, BlendMode blendMode)
: _color = color, _blendMode = blendMode;
: _color = color,
_blendMode = blendMode,
_matrix = null,
_type = _TypeMode;
/// Construct a color filter that transforms a color by a 4x5 matrix. The
/// matrix is in row-major order and the translation column is specified in
/// unnormalized, 0...255, space.
const ColorFilter.matrix(List<double> matrix)
: _color = null,
_blendMode = null,
_matrix = matrix,
_type = _TypeMatrix;
/// Construct a color filter that applies the srgb gamma curve to the RGB
/// channels.
const ColorFilter.linearToSrgbGamma()
: _color = null,
_blendMode = null,
_matrix = null,
_type = _TypeLinearToSrgbGamma;
/// Creates a color filter that applies the inverse of the srgb gamma curve
/// to the RGB channels.
const ColorFilter.srgbToLinearGamma()
: _color = null,
_blendMode = null,
_matrix = null,
_type = _TypeSrgbToLinearGamma;
final Color _color;
final BlendMode _blendMode;
final List<double> _matrix;
final int _type;
// The type of SkColorFilter class to create for Skia.
// These constants must be kept in sync with ColorFilterType in paint.cc.
static const int _TypeNone = 0; // null
static const int _TypeMode = 1; // MakeModeFilter
static const int _TypeMatrix = 2; // MakeMatrixFilterRowMajor255
static const int _TypeLinearToSrgbGamma = 3; // MakeLinearToSRGBGamma
static const int _TypeSrgbToLinearGamma = 4; // MakeSRGBToLinearGamma
@override
bool operator ==(dynamic other) {
if (other is! ColorFilter)
if (other is! ColorFilter) {
return false;
}
final ColorFilter typedOther = other;
return _color == typedOther._color &&
_blendMode == typedOther._blendMode;
if (_type != typedOther._type) {
return false;
}
if (!_listEquals<double>(_matrix, typedOther._matrix)) {
return false;
}
return _color == typedOther._color && _blendMode == typedOther._blendMode;
}
@override
int get hashCode => hashValues(_color, _blendMode);
int get hashCode => hashValues(_color, _blendMode, hashList(_matrix), _type);
@override
String toString() => 'ColorFilter($_color, $_blendMode)';
String toString() {
switch (_type) {
case _TypeMode:
return 'ColorFilter.mode($_color, $_blendMode)';
case _TypeMatrix:
return 'ColorFilter.matrix($_matrix)';
case _TypeLinearToSrgbGamma:
return 'ColorFilter.linearToSrgbGamma()';
case _TypeSrgbToLinearGamma:
return 'ColorFilter.srgbToLinearGamma()';
default:
return 'Unknown ColorFilter type. This is an error. If you\'re seeing this, please file an issue at https://github.com/flutter/flutter/issues/new.';
}
}
}
/// A filter operation to apply to a raster image.
......
......@@ -11,6 +11,7 @@
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"
#include "third_party/tonic/typed_data/float32_list.h"
namespace blink {
......@@ -35,7 +36,8 @@ constexpr size_t kDataByteCount = 75; // 4 * (last index + 1)
// Indices for objects.
constexpr int kShaderIndex = 0;
constexpr int kObjectCount = 1; // One larger than largest object index.
constexpr int kColorFilterMatrixIndex = 1;
constexpr int kObjectCount = 2; // One larger than largest object index.
// Must be kept in sync with the default in painting.dart.
constexpr uint32_t kColorDefault = 0xFF000000;
......@@ -61,18 +63,63 @@ constexpr SkScalar invert_colors[20] = {
// Must be kept in sync with the MaskFilter private constants in painting.dart.
enum MaskFilterType { Null, Blur };
// Must be kept in sync with the ColorFilter private constants in painting.dart.
enum ColorFilterType {
None,
Mode,
Matrix,
LinearToSRGBGamma,
SRGBToLinearGamma
};
sk_sp<SkColorFilter> ExtractColorFilter(const uint32_t* uint_data,
Dart_Handle* values) {
switch (uint_data[kColorFilterIndex]) {
case Mode: {
SkColor color = uint_data[kColorFilterColorIndex];
SkBlendMode blend_mode =
static_cast<SkBlendMode>(uint_data[kColorFilterBlendModeIndex]);
return SkColorFilter::MakeModeFilter(color, blend_mode);
}
case Matrix: {
Dart_Handle matrixHandle = values[kColorFilterMatrixIndex];
if (!Dart_IsNull(matrixHandle)) {
FML_DCHECK(Dart_IsList(matrixHandle));
intptr_t length = 0;
Dart_ListLength(matrixHandle, &length);
FML_CHECK(length == 20);
tonic::Float32List decoded(matrixHandle);
return SkColorFilter::MakeMatrixFilterRowMajor255(decoded.data());
}
return nullptr;
}
case LinearToSRGBGamma: {
return SkColorFilter::MakeLinearToSRGBGamma();
}
case SRGBToLinearGamma: {
return SkColorFilter::MakeSRGBToLinearGamma();
}
default:
FML_DLOG(ERROR) << "Out of range value received for kColorFilterIndex.";
return nullptr;
}
}
Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) {
is_null_ = Dart_IsNull(paint_data);
if (is_null_)
return;
Dart_Handle values[kObjectCount];
if (!Dart_IsNull(paint_objects)) {
FML_DCHECK(Dart_IsList(paint_objects));
intptr_t length = 0;
Dart_ListLength(paint_objects, &length);
FML_CHECK(length == kObjectCount);
Dart_Handle values[kObjectCount];
if (Dart_IsError(Dart_ListGetRange(paint_objects, 0, kObjectCount, values)))
return;
......@@ -128,22 +175,20 @@ Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) {
paint_.setFilterQuality(static_cast<SkFilterQuality>(filter_quality));
if (uint_data[kColorFilterIndex] && uint_data[kInvertColorIndex]) {
SkColor color = uint_data[kColorFilterColorIndex];
SkBlendMode blend_mode =
static_cast<SkBlendMode>(uint_data[kColorFilterBlendModeIndex]);
sk_sp<SkColorFilter> color_filter =
SkColorFilter::MakeModeFilter(color, blend_mode);
sk_sp<SkColorFilter> invert_filter =
SkColorFilter::MakeMatrixFilterRowMajor255(invert_colors);
paint_.setColorFilter(invert_filter->makeComposed(color_filter));
sk_sp<SkColorFilter> color_filter = ExtractColorFilter(uint_data, values);
if (color_filter) {
sk_sp<SkColorFilter> invert_filter =
SkColorFilter::MakeMatrixFilterRowMajor255(invert_colors);
paint_.setColorFilter(invert_filter->makeComposed(color_filter));
}
} else if (uint_data[kInvertColorIndex]) {
paint_.setColorFilter(
SkColorFilter::MakeMatrixFilterRowMajor255(invert_colors));
} else if (uint_data[kColorFilterIndex]) {
SkColor color = uint_data[kColorFilterColorIndex];
SkBlendMode blend_mode =
static_cast<SkBlendMode>(uint_data[kColorFilterBlendModeIndex]);
paint_.setColorFilter(SkColorFilter::MakeModeFilter(color, blend_mode));
sk_sp<SkColorFilter> color_filter = ExtractColorFilter(uint_data, values);
if (color_filter) {
paint_.setColorFilter(color_filter);
}
}
switch (uint_data[kMaskFilterIndex]) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册