1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #define _USE_MATH_DEFINES |
6 | |
7 | #include "flutter/lib/ui/painting/gradient.h" |
8 | |
9 | #include "third_party/tonic/converter/dart_converter.h" |
10 | #include "third_party/tonic/dart_args.h" |
11 | #include "third_party/tonic/dart_binding_macros.h" |
12 | #include "third_party/tonic/dart_library_natives.h" |
13 | |
14 | namespace flutter { |
15 | |
16 | typedef CanvasGradient |
17 | Gradient; // Because the C++ name doesn't match the Dart name. |
18 | |
19 | static void Gradient_constructor(Dart_NativeArguments args) { |
20 | UIDartState::ThrowIfUIOperationsProhibited(); |
21 | DartCallConstructor(&CanvasGradient::Create, args); |
22 | } |
23 | |
24 | IMPLEMENT_WRAPPERTYPEINFO(ui, Gradient); |
25 | |
26 | #define FOR_EACH_BINDING(V) \ |
27 | V(Gradient, initLinear) \ |
28 | V(Gradient, initRadial) \ |
29 | V(Gradient, initSweep) \ |
30 | V(Gradient, initTwoPointConical) |
31 | |
32 | FOR_EACH_BINDING(DART_NATIVE_CALLBACK) |
33 | |
34 | void CanvasGradient::RegisterNatives(tonic::DartLibraryNatives* natives) { |
35 | natives->Register({{"Gradient_constructor" , Gradient_constructor, 1, true}, |
36 | FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); |
37 | } |
38 | |
39 | fml::RefPtr<CanvasGradient> CanvasGradient::Create() { |
40 | return fml::MakeRefCounted<CanvasGradient>(); |
41 | } |
42 | |
43 | void CanvasGradient::initLinear(const tonic::Float32List& end_points, |
44 | const tonic::Int32List& colors, |
45 | const tonic::Float32List& color_stops, |
46 | SkTileMode tile_mode, |
47 | const tonic::Float64List& matrix4) { |
48 | FML_DCHECK(end_points.num_elements() == 4); |
49 | FML_DCHECK(colors.num_elements() == color_stops.num_elements() || |
50 | color_stops.data() == nullptr); |
51 | |
52 | static_assert(sizeof(SkPoint) == sizeof(float) * 2, |
53 | "SkPoint doesn't use floats." ); |
54 | static_assert(sizeof(SkColor) == sizeof(int32_t), |
55 | "SkColor doesn't use int32_t." ); |
56 | |
57 | SkMatrix sk_matrix; |
58 | bool has_matrix = matrix4.data() != nullptr; |
59 | if (has_matrix) { |
60 | sk_matrix = ToSkMatrix(matrix4); |
61 | } |
62 | |
63 | set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeLinear( |
64 | reinterpret_cast<const SkPoint*>(end_points.data()), |
65 | reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(), |
66 | colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr))); |
67 | } |
68 | |
69 | void CanvasGradient::initRadial(double center_x, |
70 | double center_y, |
71 | double radius, |
72 | const tonic::Int32List& colors, |
73 | const tonic::Float32List& color_stops, |
74 | SkTileMode tile_mode, |
75 | const tonic::Float64List& matrix4) { |
76 | FML_DCHECK(colors.num_elements() == color_stops.num_elements() || |
77 | color_stops.data() == nullptr); |
78 | |
79 | static_assert(sizeof(SkColor) == sizeof(int32_t), |
80 | "SkColor doesn't use int32_t." ); |
81 | |
82 | SkMatrix sk_matrix; |
83 | bool has_matrix = matrix4.data() != nullptr; |
84 | if (has_matrix) { |
85 | sk_matrix = ToSkMatrix(matrix4); |
86 | } |
87 | |
88 | set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeRadial( |
89 | SkPoint::Make(center_x, center_y), radius, |
90 | reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(), |
91 | colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr))); |
92 | } |
93 | |
94 | void CanvasGradient::initSweep(double center_x, |
95 | double center_y, |
96 | const tonic::Int32List& colors, |
97 | const tonic::Float32List& color_stops, |
98 | SkTileMode tile_mode, |
99 | double start_angle, |
100 | double end_angle, |
101 | const tonic::Float64List& matrix4) { |
102 | FML_DCHECK(colors.num_elements() == color_stops.num_elements() || |
103 | color_stops.data() == nullptr); |
104 | |
105 | static_assert(sizeof(SkColor) == sizeof(int32_t), |
106 | "SkColor doesn't use int32_t." ); |
107 | |
108 | SkMatrix sk_matrix; |
109 | bool has_matrix = matrix4.data() != nullptr; |
110 | if (has_matrix) { |
111 | sk_matrix = ToSkMatrix(matrix4); |
112 | } |
113 | |
114 | set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeSweep( |
115 | center_x, center_y, reinterpret_cast<const SkColor*>(colors.data()), |
116 | color_stops.data(), colors.num_elements(), tile_mode, |
117 | start_angle * 180.0 / M_PI, end_angle * 180.0 / M_PI, 0, |
118 | has_matrix ? &sk_matrix : nullptr))); |
119 | } |
120 | |
121 | void CanvasGradient::initTwoPointConical(double start_x, |
122 | double start_y, |
123 | double start_radius, |
124 | double end_x, |
125 | double end_y, |
126 | double end_radius, |
127 | const tonic::Int32List& colors, |
128 | const tonic::Float32List& color_stops, |
129 | SkTileMode tile_mode, |
130 | const tonic::Float64List& matrix4) { |
131 | FML_DCHECK(colors.num_elements() == color_stops.num_elements() || |
132 | color_stops.data() == nullptr); |
133 | |
134 | static_assert(sizeof(SkColor) == sizeof(int32_t), |
135 | "SkColor doesn't use int32_t." ); |
136 | |
137 | SkMatrix sk_matrix; |
138 | bool has_matrix = matrix4.data() != nullptr; |
139 | if (has_matrix) { |
140 | sk_matrix = ToSkMatrix(matrix4); |
141 | } |
142 | |
143 | set_shader(UIDartState::CreateGPUObject(SkGradientShader::MakeTwoPointConical( |
144 | SkPoint::Make(start_x, start_y), start_radius, |
145 | SkPoint::Make(end_x, end_y), end_radius, |
146 | reinterpret_cast<const SkColor*>(colors.data()), color_stops.data(), |
147 | colors.num_elements(), tile_mode, 0, has_matrix ? &sk_matrix : nullptr))); |
148 | } |
149 | |
150 | CanvasGradient::CanvasGradient() = default; |
151 | |
152 | CanvasGradient::~CanvasGradient() = default; |
153 | |
154 | } // namespace flutter |
155 | |