mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
Refactor ColorFilter to have a native wrapper (#9668)
This commit is contained in:
@@ -332,6 +332,8 @@ FILE: ../../../flutter/lib/ui/painting/canvas.cc
|
||||
FILE: ../../../flutter/lib/ui/painting/canvas.h
|
||||
FILE: ../../../flutter/lib/ui/painting/codec.cc
|
||||
FILE: ../../../flutter/lib/ui/painting/codec.h
|
||||
FILE: ../../../flutter/lib/ui/painting/color_filter.cc
|
||||
FILE: ../../../flutter/lib/ui/painting/color_filter.h
|
||||
FILE: ../../../flutter/lib/ui/painting/engine_layer.cc
|
||||
FILE: ../../../flutter/lib/ui/painting/engine_layer.h
|
||||
FILE: ../../../flutter/lib/ui/painting/frame_info.cc
|
||||
|
||||
@@ -24,6 +24,8 @@ source_set("ui") {
|
||||
"painting/canvas.h",
|
||||
"painting/codec.cc",
|
||||
"painting/codec.h",
|
||||
"painting/color_filter.cc",
|
||||
"painting/color_filter.h",
|
||||
"painting/engine_layer.cc",
|
||||
"painting/engine_layer.h",
|
||||
"painting/frame_info.cc",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h"
|
||||
#include "flutter/lib/ui/painting/canvas.h"
|
||||
#include "flutter/lib/ui/painting/codec.h"
|
||||
#include "flutter/lib/ui/painting/color_filter.h"
|
||||
#include "flutter/lib/ui/painting/engine_layer.h"
|
||||
#include "flutter/lib/ui/painting/frame_info.h"
|
||||
#include "flutter/lib/ui/painting/gradient.h"
|
||||
@@ -75,6 +76,7 @@ void DartUI::InitForGlobal() {
|
||||
CanvasPath::RegisterNatives(g_natives);
|
||||
CanvasPathMeasure::RegisterNatives(g_natives);
|
||||
Codec::RegisterNatives(g_natives);
|
||||
ColorFilter::RegisterNatives(g_natives);
|
||||
DartRuntimeHooks::RegisterNatives(g_natives);
|
||||
EngineLayer::RegisterNatives(g_natives);
|
||||
FontCollection::RegisterNatives(g_natives);
|
||||
|
||||
+81
-48
@@ -1056,13 +1056,10 @@ class Paint {
|
||||
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 _kMaskFilterIndex = 12;
|
||||
static const int _kMaskFilterBlurStyleIndex = 13;
|
||||
static const int _kMaskFilterSigmaIndex = 14;
|
||||
static const int _kInvertColorIndex = 15;
|
||||
static const int _kMaskFilterIndex = 9;
|
||||
static const int _kMaskFilterBlurStyleIndex = 10;
|
||||
static const int _kMaskFilterSigmaIndex = 11;
|
||||
static const int _kInvertColorIndex = 12;
|
||||
|
||||
static const int _kIsAntiAliasOffset = _kIsAntiAliasIndex << 2;
|
||||
static const int _kColorOffset = _kColorIndex << 2;
|
||||
@@ -1073,20 +1070,17 @@ class Paint {
|
||||
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;
|
||||
static const int _kMaskFilterOffset = _kMaskFilterIndex << 2;
|
||||
static const int _kMaskFilterBlurStyleOffset = _kMaskFilterBlurStyleIndex << 2;
|
||||
static const int _kMaskFilterSigmaOffset = _kMaskFilterSigmaIndex << 2;
|
||||
static const int _kInvertColorOffset = _kInvertColorIndex << 2;
|
||||
// If you add more fields, remember to update _kDataByteCount.
|
||||
static const int _kDataByteCount = 75;
|
||||
static const int _kDataByteCount = 52;
|
||||
|
||||
// Binary format must match the deserialization code in paint.cc.
|
||||
List<dynamic> _objects;
|
||||
static const int _kShaderIndex = 0;
|
||||
static const int _kColorFilterMatrixIndex = 1;
|
||||
static const int _kColorFilterIndex = 1;
|
||||
static const int _kImageFilterIndex = 2;
|
||||
static const int _kObjectCount = 3; // Must be one larger than the largest index.
|
||||
|
||||
@@ -1342,48 +1336,23 @@ class Paint {
|
||||
///
|
||||
/// When a shape is being drawn, [colorFilter] overrides [color] and [shader].
|
||||
ColorFilter get colorFilter {
|
||||
switch (_data.getInt32(_kColorFilterOffset, _kFakeHostEndian)) {
|
||||
case ColorFilter._TypeNone:
|
||||
return null;
|
||||
case ColorFilter._TypeMode:
|
||||
return ColorFilter.mode(
|
||||
Color(_data.getInt32(_kColorFilterColorOffset, _kFakeHostEndian)),
|
||||
BlendMode.values[_data.getInt32(_kColorFilterBlendModeOffset, _kFakeHostEndian)],
|
||||
);
|
||||
case ColorFilter._TypeMatrix:
|
||||
return ColorFilter.matrix(_objects[_kColorFilterMatrixIndex]);
|
||||
case ColorFilter._TypeLinearToSrgbGamma:
|
||||
return const ColorFilter.linearToSrgbGamma();
|
||||
case ColorFilter._TypeSrgbToLinearGamma:
|
||||
return const ColorFilter.srgbToLinearGamma();
|
||||
if (_objects == null || _objects[_kColorFilterIndex] == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return _objects[_kColorFilterIndex].creator;
|
||||
}
|
||||
|
||||
set colorFilter(ColorFilter value) {
|
||||
if (value == null) {
|
||||
_data.setInt32(_kColorFilterOffset, ColorFilter._TypeNone, _kFakeHostEndian);
|
||||
_data.setInt32(_kColorFilterColorOffset, 0, _kFakeHostEndian);
|
||||
_data.setInt32(_kColorFilterBlendModeOffset, 0, _kFakeHostEndian);
|
||||
|
||||
if (_objects != null) {
|
||||
_objects[_kColorFilterMatrixIndex] = null;
|
||||
_objects[_kColorFilterIndex] = null;
|
||||
}
|
||||
} else {
|
||||
_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 ??= List<dynamic>(_kObjectCount);
|
||||
_objects[_kColorFilterMatrixIndex] = Float32List.fromList(value._matrix);
|
||||
if (_objects == null) {
|
||||
_objects = List<dynamic>(_kObjectCount);
|
||||
_objects[_kColorFilterIndex] = value._toNativeColorFilter();
|
||||
} else if (_objects[_kColorFilterIndex]?.creator != value) {
|
||||
_objects[_kColorFilterIndex] = value._toNativeColorFilter();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2520,7 +2489,9 @@ 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,
|
||||
: assert(color != null),
|
||||
assert(blendMode != null),
|
||||
_color = color,
|
||||
_blendMode = blendMode,
|
||||
_matrix = null,
|
||||
_type = _TypeMode;
|
||||
@@ -2529,7 +2500,9 @@ class ColorFilter {
|
||||
/// 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,
|
||||
: assert(matrix != null),
|
||||
assert(matrix.length == 20),
|
||||
_color = null,
|
||||
_blendMode = null,
|
||||
_matrix = matrix,
|
||||
_type = _TypeMatrix;
|
||||
@@ -2580,6 +2553,21 @@ class ColorFilter {
|
||||
return _color == typedOther._color && _blendMode == typedOther._blendMode;
|
||||
}
|
||||
|
||||
_ColorFilter _toNativeColorFilter() {
|
||||
switch (_type) {
|
||||
case _TypeMode:
|
||||
return _ColorFilter.mode(this);
|
||||
case _TypeMatrix:
|
||||
return _ColorFilter.matrix(this);
|
||||
case _TypeLinearToSrgbGamma:
|
||||
return _ColorFilter.linearToSrgbGamma(this);
|
||||
case _TypeSrgbToLinearGamma:
|
||||
return _ColorFilter.srgbToLinearGamma(this);
|
||||
default:
|
||||
throw StateError('Unknown mode $_type for ColorFilter.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(_color, _blendMode, hashList(_matrix), _type);
|
||||
|
||||
@@ -2600,6 +2588,51 @@ class ColorFilter {
|
||||
}
|
||||
}
|
||||
|
||||
/// A [ColorFilter] that is backed by a native SkColorFilter.
|
||||
///
|
||||
/// This is a private class, rather than being the implementation of the public
|
||||
/// ColorFilter, because we want ColorFilter to be const constructible and
|
||||
/// efficiently comparable, so that widgets can check for ColorFilter equality to
|
||||
// avoid repainting.
|
||||
class _ColorFilter extends NativeFieldWrapperClass2 {
|
||||
_ColorFilter.mode(this.creator)
|
||||
: assert(creator != null),
|
||||
assert(creator._type == ColorFilter._TypeMode) {
|
||||
_constructor();
|
||||
_initMode(creator._color.value, creator._blendMode.index);
|
||||
}
|
||||
|
||||
_ColorFilter.matrix(this.creator)
|
||||
: assert(creator != null),
|
||||
assert(creator._type == ColorFilter._TypeMatrix) {
|
||||
_constructor();
|
||||
_initMatrix(Float32List.fromList(creator._matrix));
|
||||
}
|
||||
_ColorFilter.linearToSrgbGamma(this.creator)
|
||||
: assert(creator != null),
|
||||
assert(creator._type == ColorFilter._TypeLinearToSrgbGamma) {
|
||||
_constructor();
|
||||
_initLinearToSrgbGamma();
|
||||
}
|
||||
|
||||
_ColorFilter.srgbToLinearGamma(this.creator)
|
||||
: assert(creator != null),
|
||||
assert(creator._type == ColorFilter._TypeSrgbToLinearGamma) {
|
||||
_constructor();
|
||||
_initSrgbToLinearGamma();
|
||||
}
|
||||
|
||||
/// The original Dart object that created the native wrapper, which retains
|
||||
/// the values used for the filter.
|
||||
final ColorFilter creator;
|
||||
|
||||
void _constructor() native 'ColorFilter_constructor';
|
||||
void _initMode(int color, int blendMode) native 'ColorFilter_initMode';
|
||||
void _initMatrix(Float32List matrix) native 'ColorFilter_initMatrix';
|
||||
void _initLinearToSrgbGamma() native 'ColorFilter_initLinearToSrgbGamma';
|
||||
void _initSrgbToLinearGamma() native 'ColorFilter_initSrgbToLinearGamma';
|
||||
}
|
||||
|
||||
/// A filter operation to apply to a raster image.
|
||||
///
|
||||
/// See also:
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/lib/ui/painting/color_filter.h"
|
||||
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/dart_args.h"
|
||||
#include "third_party/tonic/dart_binding_macros.h"
|
||||
#include "third_party/tonic/dart_library_natives.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
static void ColorFilter_constructor(Dart_NativeArguments args) {
|
||||
DartCallConstructor(&ColorFilter::Create, args);
|
||||
}
|
||||
|
||||
IMPLEMENT_WRAPPERTYPEINFO(ui, ColorFilter);
|
||||
|
||||
#define FOR_EACH_BINDING(V) \
|
||||
V(ColorFilter, initMode) \
|
||||
V(ColorFilter, initMatrix) \
|
||||
V(ColorFilter, initSrgbToLinearGamma) \
|
||||
V(ColorFilter, initLinearToSrgbGamma)
|
||||
|
||||
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
|
||||
|
||||
void ColorFilter::RegisterNatives(tonic::DartLibraryNatives* natives) {
|
||||
natives->Register(
|
||||
{{"ColorFilter_constructor", ColorFilter_constructor, 1, true},
|
||||
FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
|
||||
}
|
||||
|
||||
fml::RefPtr<ColorFilter> ColorFilter::Create() {
|
||||
return fml::MakeRefCounted<ColorFilter>();
|
||||
}
|
||||
|
||||
void ColorFilter::initMode(int color, int blend_mode) {
|
||||
filter_ = SkColorFilters::Blend(static_cast<SkColor>(color),
|
||||
static_cast<SkBlendMode>(blend_mode));
|
||||
}
|
||||
|
||||
sk_sp<SkColorFilter> ColorFilter::MakeColorMatrixFilter255(
|
||||
const float array[20]) {
|
||||
float tmp[20];
|
||||
memcpy(tmp, array, sizeof(tmp));
|
||||
tmp[4] *= 1.0f / 255;
|
||||
tmp[9] *= 1.0f / 255;
|
||||
tmp[14] *= 1.0f / 255;
|
||||
tmp[19] *= 1.0f / 255;
|
||||
return SkColorFilters::Matrix(tmp);
|
||||
}
|
||||
|
||||
void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) {
|
||||
FML_CHECK(color_matrix.num_elements() == 20);
|
||||
|
||||
filter_ = MakeColorMatrixFilter255(color_matrix.data());
|
||||
}
|
||||
|
||||
void ColorFilter::initLinearToSrgbGamma() {
|
||||
filter_ = SkColorFilters::LinearToSRGBGamma();
|
||||
}
|
||||
|
||||
void ColorFilter::initSrgbToLinearGamma() {
|
||||
filter_ = SkColorFilters::SRGBToLinearGamma();
|
||||
}
|
||||
|
||||
ColorFilter::~ColorFilter() = default;
|
||||
|
||||
} // namespace flutter
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_LIB_UI_COLOR_FILTER_H_
|
||||
#define FLUTTER_LIB_UI_COLOR_FILTER_H_
|
||||
|
||||
#include "flutter/lib/ui/dart_wrapper.h"
|
||||
#include "third_party/skia/include/core/SkColorFilter.h"
|
||||
#include "third_party/tonic/typed_data/typed_list.h"
|
||||
|
||||
using tonic::DartPersistentValue;
|
||||
|
||||
namespace tonic {
|
||||
class DartLibraryNatives;
|
||||
} // namespace tonic
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A handle to an SkCodec object.
|
||||
//
|
||||
// Doesn't mirror SkCodec's API but provides a simple sequential access API.
|
||||
class ColorFilter : public RefCountedDartWrappable<ColorFilter> {
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
FML_FRIEND_MAKE_REF_COUNTED(ColorFilter);
|
||||
|
||||
public:
|
||||
static fml::RefPtr<ColorFilter> Create();
|
||||
|
||||
// Flutter still defines the matrix to be biased by 255 in the last column
|
||||
// (translate). skia is normalized, treating the last column as 0...1, so we
|
||||
// post-scale here before calling the skia factory.
|
||||
static sk_sp<SkColorFilter> MakeColorMatrixFilter255(const float array[20]);
|
||||
|
||||
void initMode(int color, int blend_mode);
|
||||
void initMatrix(const tonic::Float32List& color_matrix);
|
||||
void initSrgbToLinearGamma();
|
||||
void initLinearToSrgbGamma();
|
||||
|
||||
~ColorFilter() override;
|
||||
|
||||
sk_sp<SkColorFilter> filter() const { return filter_; }
|
||||
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
private:
|
||||
sk_sp<SkColorFilter> filter_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_LIB_UI_COLOR_FILTER_H_
|
||||
+21
-80
@@ -5,6 +5,7 @@
|
||||
#include "flutter/lib/ui/painting/paint.h"
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "flutter/lib/ui/painting/color_filter.h"
|
||||
#include "flutter/lib/ui/painting/image_filter.h"
|
||||
#include "flutter/lib/ui/painting/shader.h"
|
||||
#include "third_party/skia/include/core/SkColorFilter.h"
|
||||
@@ -27,18 +28,15 @@ constexpr int kStrokeCapIndex = 5;
|
||||
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 int kMaskFilterIndex = 12;
|
||||
constexpr int kMaskFilterBlurStyleIndex = 13;
|
||||
constexpr int kMaskFilterSigmaIndex = 14;
|
||||
constexpr int kInvertColorIndex = 15;
|
||||
constexpr size_t kDataByteCount = 75; // 4 * (last index + 1)
|
||||
constexpr int kMaskFilterIndex = 9;
|
||||
constexpr int kMaskFilterBlurStyleIndex = 10;
|
||||
constexpr int kMaskFilterSigmaIndex = 11;
|
||||
constexpr int kInvertColorIndex = 12;
|
||||
constexpr size_t kDataByteCount = 52; // 4 * (last index + 1)
|
||||
|
||||
// Indices for objects.
|
||||
constexpr int kShaderIndex = 0;
|
||||
constexpr int kColorFilterMatrixIndex = 1;
|
||||
constexpr int kColorFilterIndex = 1;
|
||||
constexpr int kImageFilterIndex = 2;
|
||||
constexpr int kObjectCount = 3; // One larger than largest object index.
|
||||
|
||||
@@ -66,64 +64,6 @@ constexpr float 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
|
||||
};
|
||||
|
||||
// Flutter still defines the matrix to be biased by 255 in the last column
|
||||
// (translate). skia is normalized, treating the last column as 0...1, so we
|
||||
// post-scale here before calling the skia factory.
|
||||
static sk_sp<SkColorFilter> MakeColorMatrixFilter255(const float array[20]) {
|
||||
float tmp[20];
|
||||
memcpy(tmp, array, sizeof(tmp));
|
||||
tmp[4] *= 1.0f / 255;
|
||||
tmp[9] *= 1.0f / 255;
|
||||
tmp[14] *= 1.0f / 255;
|
||||
tmp[19] *= 1.0f / 255;
|
||||
return SkColorFilters::Matrix(tmp);
|
||||
}
|
||||
|
||||
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 SkColorFilters::Blend(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 MakeColorMatrixFilter255(decoded.data());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
case LinearToSRGBGamma: {
|
||||
return SkColorFilters::LinearToSRGBGamma();
|
||||
}
|
||||
case SRGBToLinearGamma: {
|
||||
return SkColorFilters::SRGBToLinearGamma();
|
||||
}
|
||||
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_)
|
||||
@@ -145,6 +85,13 @@ Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) {
|
||||
paint_.setShader(decoded->shader());
|
||||
}
|
||||
|
||||
Dart_Handle color_filter = values[kColorFilterIndex];
|
||||
if (!Dart_IsNull(color_filter)) {
|
||||
ColorFilter* decoded_color_filter =
|
||||
tonic::DartConverter<ColorFilter*>::FromDart(color_filter);
|
||||
paint_.setColorFilter(decoded_color_filter->filter());
|
||||
}
|
||||
|
||||
Dart_Handle image_filter = values[kImageFilterIndex];
|
||||
if (!Dart_IsNull(image_filter)) {
|
||||
ImageFilter* decoded =
|
||||
@@ -197,20 +144,14 @@ Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) {
|
||||
if (filter_quality)
|
||||
paint_.setFilterQuality(static_cast<SkFilterQuality>(filter_quality));
|
||||
|
||||
if (uint_data[kColorFilterIndex] && uint_data[kInvertColorIndex]) {
|
||||
sk_sp<SkColorFilter> color_filter = ExtractColorFilter(uint_data, values);
|
||||
if (color_filter) {
|
||||
sk_sp<SkColorFilter> invert_filter =
|
||||
MakeColorMatrixFilter255(invert_colors);
|
||||
paint_.setColorFilter(invert_filter->makeComposed(color_filter));
|
||||
}
|
||||
} else if (uint_data[kInvertColorIndex]) {
|
||||
paint_.setColorFilter(MakeColorMatrixFilter255(invert_colors));
|
||||
} else if (uint_data[kColorFilterIndex]) {
|
||||
sk_sp<SkColorFilter> color_filter = ExtractColorFilter(uint_data, values);
|
||||
if (color_filter) {
|
||||
paint_.setColorFilter(color_filter);
|
||||
if (uint_data[kInvertColorIndex]) {
|
||||
sk_sp<SkColorFilter> invert_filter =
|
||||
ColorFilter::MakeColorMatrixFilter255(invert_colors);
|
||||
sk_sp<SkColorFilter> current_filter = paint_.refColorFilter();
|
||||
if (current_filter) {
|
||||
invert_filter = invert_filter->makeComposed(current_filter);
|
||||
}
|
||||
paint_.setColorFilter(invert_filter);
|
||||
}
|
||||
|
||||
switch (uint_data[kMaskFilterIndex]) {
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
const Color red = Color(0xFFAA0000);
|
||||
const Color green = Color(0xFF00AA00);
|
||||
|
||||
const int greenRedColorBlend = 0xFF3131DB;
|
||||
const int greenRedColorBlendInverted = 0xFFCECE24;
|
||||
const int greenGreyscaled = 0xFF7A7A7A;
|
||||
const int greenInvertedGreyscaled = 0xFF858585;
|
||||
|
||||
const int greenLinearToSrgbGamma = 0xFF00D500;
|
||||
const int greenLinearToSrgbGammaInverted = 0xFFFF2AFF;
|
||||
|
||||
const int greenSrgbToLinearGamma = 0xFF006700;
|
||||
const int greenSrgbToLinearGammaInverted = 0xFFFF98FF;
|
||||
|
||||
const List<double> greyscaleColorMatrix = <double>[
|
||||
0.2126, 0.7152, 0.0722, 0, 0, //
|
||||
0.2126, 0.7152, 0.0722, 0, 0, //
|
||||
0.2126, 0.7152, 0.0722, 0, 0, //
|
||||
0, 0, 0, 1, 0, //
|
||||
];
|
||||
|
||||
void main() {
|
||||
Future<Uint32List> getBytesForPaint(Paint paint, {int width = 1, int height = 1}) async {
|
||||
final PictureRecorder recorder = PictureRecorder();
|
||||
final Canvas recorderCanvas = Canvas(recorder);
|
||||
recorderCanvas.drawPaint(paint);
|
||||
final Picture picture = recorder.endRecording();
|
||||
final Image image = await picture.toImage(width, height);
|
||||
final ByteData bytes = await image.toByteData();
|
||||
|
||||
expect(bytes.lengthInBytes, width * height * 4);
|
||||
return bytes.buffer.asUint32List();
|
||||
}
|
||||
|
||||
test('ColorFilter - mode', () async {
|
||||
final Paint paint = Paint()
|
||||
..color = green
|
||||
..colorFilter = ColorFilter.mode(red, BlendMode.color);
|
||||
|
||||
Uint32List bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenRedColorBlend);
|
||||
|
||||
paint.invertColors = true;
|
||||
bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenRedColorBlendInverted);
|
||||
});
|
||||
|
||||
test('ColorFilter - matrix', () async {
|
||||
final Paint paint = Paint()
|
||||
..color = green
|
||||
..colorFilter = ColorFilter.matrix(greyscaleColorMatrix);
|
||||
|
||||
Uint32List bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenGreyscaled);
|
||||
|
||||
paint.invertColors = true;
|
||||
bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenInvertedGreyscaled);
|
||||
});
|
||||
|
||||
test('ColorFilter - linearToSrgbGamma', () async {
|
||||
final Paint paint = Paint()
|
||||
..color = green
|
||||
..colorFilter = ColorFilter.linearToSrgbGamma();
|
||||
|
||||
Uint32List bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenLinearToSrgbGamma);
|
||||
|
||||
paint.invertColors = true;
|
||||
bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenLinearToSrgbGammaInverted);
|
||||
});
|
||||
|
||||
test('ColorFilter - srgbToLinearGamma', () async {
|
||||
final Paint paint = Paint()
|
||||
..color = green
|
||||
..colorFilter = ColorFilter.srgbToLinearGamma();
|
||||
|
||||
Uint32List bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenSrgbToLinearGamma);
|
||||
|
||||
paint.invertColors = true;
|
||||
bytes = await getBytesForPaint(paint);
|
||||
expect(bytes[0], greenSrgbToLinearGammaInverted);
|
||||
});
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user