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
14namespace flutter {
15
16typedef CanvasGradient
17 Gradient; // Because the C++ name doesn't match the Dart name.
18
19static void Gradient_constructor(Dart_NativeArguments args) {
20 UIDartState::ThrowIfUIOperationsProhibited();
21 DartCallConstructor(&CanvasGradient::Create, args);
22}
23
24IMPLEMENT_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
32FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
33
34void CanvasGradient::RegisterNatives(tonic::DartLibraryNatives* natives) {
35 natives->Register({{"Gradient_constructor", Gradient_constructor, 1, true},
36 FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
37}
38
39fml::RefPtr<CanvasGradient> CanvasGradient::Create() {
40 return fml::MakeRefCounted<CanvasGradient>();
41}
42
43void 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
69void 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
94void 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
121void 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
150CanvasGradient::CanvasGradient() = default;
151
152CanvasGradient::~CanvasGradient() = default;
153
154} // namespace flutter
155