1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_gauge_ffi.h"
17 
18 #include "cj_lambda.h"
19 #include "base/log/ace_scoring_log.h"
20 #include "base/memory/ace_type.h"
21 #include "core/common/container.h"
22 #include "core/components_ng/base/view_stack_model.h"
23 #include "core/components_ng/pattern/gauge/gauge_model_ng.h"
24 
25 using namespace OHOS::Ace;
26 
27 namespace {
28 const std::string INDICATOR_DEFAULT = "default";
29 const std::string INDICATOR_NULL = "null";
30 }  // namespace
31 extern "C" {
FFICJCreateVectorColorStop(int64_t size)32 VectorColorStops FFICJCreateVectorColorStop(int64_t size)
33 {
34     LOGI("Create ColorStop Vector");
35     return new std::vector<ColorStop>(size);
36 }
37 
FFICJVectorColorStopSetElement(VectorColorStops vec,int64_t index,ColorStop colorStop)38 void FFICJVectorColorStopSetElement(VectorColorStops vec, int64_t index, ColorStop colorStop)
39 {
40     LOGI("ColorStop Vector Set Element");
41     auto actualVec = reinterpret_cast<std::vector<ColorStop>*>(vec);
42     (*actualVec)[index] = colorStop;
43     LOGI("ColorStop Vector Set Element Success");
44 }
45 
FFICJVectorColorStopDelete(VectorColorStops vec)46 void FFICJVectorColorStopDelete(VectorColorStops vec)
47 {
48     auto actualVec = reinterpret_cast<std::vector<ColorStop>*>(vec);
49     delete actualVec;
50 }
51 
FFICJCreateVectorGaugeLinearGradient(int64_t size)52 VecLinearGradientHandle FFICJCreateVectorGaugeLinearGradient(int64_t size)
53 {
54     LOGI("Create VectorGaugeLinearGradient Vector");
55     return new std::vector<VectorColorStops>(size);
56 }
57 
FFICJVectorGaugeLinearGradientSetElement(VecLinearGradientHandle vec,int64_t index,VectorColorStops vectorColorStops)58 void FFICJVectorGaugeLinearGradientSetElement(
59     VecLinearGradientHandle vec, int64_t index, VectorColorStops vectorColorStops)
60 {
61     LOGI("VectorGaugeLinearGradient Vector Set Element");
62     auto actualVec = reinterpret_cast<std::vector<VectorColorStops>*>(vec);
63     (*actualVec)[index] = vectorColorStops;
64     LOGI("VectorGaugeLinearGradient Vector Set Element Success");
65 }
66 
FFICJVectorGaugeLinearGradientDelete(VecLinearGradientHandle vec)67 void FFICJVectorGaugeLinearGradientDelete(VecLinearGradientHandle vec)
68 {
69     auto actualVec = reinterpret_cast<std::vector<VectorColorStops>*>(vec);
70     delete actualVec;
71 }
72 
FfiOHOSAceFrameworkGaugeCreate(double gaugeValue,double gaugeMin,double gaugeMax)73 void FfiOHOSAceFrameworkGaugeCreate(double gaugeValue, double gaugeMin, double gaugeMax)
74 {
75     if (gaugeMin >= gaugeMax) {
76         gaugeMin = NG::DEFAULT_MIN_VALUE;
77         gaugeMax = NG::DEFAULT_MAX_VALUE;
78     }
79     if (gaugeValue < gaugeMin || gaugeValue > gaugeMax) {
80         gaugeValue = gaugeMin;
81     }
82     GaugeModel::GetInstance()->Create(gaugeValue, gaugeMin, gaugeMax);
83     GaugeModel::GetInstance()->SetIsShowLimitValue(true);
84 }
85 
FfiOHOSAceFrameworkGaugeSetValue(double value)86 void FfiOHOSAceFrameworkGaugeSetValue(double value)
87 {
88     GaugeModel::GetInstance()->SetValue(value);
89 }
90 
FfiOHOSAceFrameworkGaugeSetStartAngle(double startAngle)91 void FfiOHOSAceFrameworkGaugeSetStartAngle(double startAngle)
92 {
93     GaugeModel::GetInstance()->SetStartAngle(startAngle);
94 }
95 
FfiOHOSAceFrameworkGaugeSetEndAngle(double endAngle)96 void FfiOHOSAceFrameworkGaugeSetEndAngle(double endAngle)
97 {
98     GaugeModel::GetInstance()->SetEndAngle(endAngle);
99 }
100 
SortColorStopOffset(std::vector<NG::ColorStopArray> & colors)101 void SortColorStopOffset(std::vector<NG::ColorStopArray>& colors)
102 {
103     for (auto& colorStopArray : colors) {
104         std::sort(colorStopArray.begin(), colorStopArray.end(),
105             [](const std::pair<Color, Dimension>& left, const std::pair<Color, Dimension>& right) {
106                 return left.second.Value() < right.second.Value();
107             });
108 
109         auto iter = std::unique(colorStopArray.begin(), colorStopArray.end(),
110             [](const std::pair<Color, Dimension>& left, const std::pair<Color, Dimension>& right) {
111                 return left.second.Value() == right.second.Value();
112             });
113         colorStopArray.erase(iter, colorStopArray.end());
114     }
115 }
116 
FfiOHOSAceFrameworkGaugeSetColors(VectorUInt32Ptr gaugeColors,VectorFloat32Ptr gaugeWeights)117 void FfiOHOSAceFrameworkGaugeSetColors(VectorUInt32Ptr gaugeColors, VectorFloat32Ptr gaugeWeights)
118 {
119     if (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
120         FfiOHOSAceFrameworkGaugeSetColorsV2(gaugeColors, gaugeWeights);
121         return;
122     }
123     const auto& vecColor = *reinterpret_cast<std::vector<uint32_t>*>(gaugeColors);
124     const auto& vecWeight = *reinterpret_cast<std::vector<float>*>(gaugeWeights);
125     if (vecColor.size() != vecWeight.size()) {
126         LOGE("gauge colors not match weights");
127         return;
128     }
129     std::vector<Color> colors;
130     for (size_t i = 0; i < vecColor.size(); ++i) {
131         colors.push_back(Color(vecColor[i]));
132     }
133     GaugeModel::GetInstance()->SetColors(colors, vecWeight);
134 }
135 
FfiOHOSAceFrameworkGaugeSetColorsV2(VectorUInt32Ptr gaugeColors,VectorFloat32Ptr gaugeWeights)136 void FfiOHOSAceFrameworkGaugeSetColorsV2(VectorUInt32Ptr gaugeColors, VectorFloat32Ptr gaugeWeights)
137 {
138     NG::GaugeType type = NG::GaugeType::TYPE_CIRCULAR_MULTI_SEGMENT_GRADIENT;
139     std::vector<NG::ColorStopArray> colors;
140     std::vector<float> weights;
141     const auto& vecColor = *reinterpret_cast<std::vector<uint32_t>*>(gaugeColors);
142     const auto& vecWeight = *reinterpret_cast<std::vector<float>*>(gaugeWeights);
143     if (vecColor.size() != vecWeight.size()) {
144         LOGE("gauge colors not match weights");
145         return;
146     }
147     if (vecColor.size() <= 0) {
148         GaugeModel::GetInstance()->ResetGradientColors();
149         return;
150     }
151     if (vecColor.size() > 1) {
152         for (size_t i = 0; i < vecColor.size(); ++i) {
153             NG::ColorStopArray colorStopArray;
154             colorStopArray.emplace_back(std::make_pair(Color(vecColor[i]), Dimension(vecWeight[i], DimensionUnit::VP)));
155             colors.emplace_back(colorStopArray);
156         }
157         GaugeModel::GetInstance()->SetGradientColors(colors, weights, type);
158         return;
159     }
160     type = NG::GaugeType::TYPE_CIRCULAR_MONOCHROME;
161     NG::ColorStopArray colorStopArray;
162     colorStopArray.emplace_back(std::make_pair(Color(vecColor[0]), Dimension(vecWeight[0], DimensionUnit::VP)));
163     colors.emplace_back(colorStopArray);
164     GaugeModel::GetInstance()->SetGradientColors(colors, weights, type);
165 }
166 
FfiOHOSAceFrameworkGaugeSetLinearGradientColors(VecLinearGradientHandle linearGradients,VectorUInt32Ptr weight)167 void FfiOHOSAceFrameworkGaugeSetLinearGradientColors(VecLinearGradientHandle linearGradients, VectorUInt32Ptr weight)
168 {
169     NG::GaugeType type = NG::GaugeType::TYPE_CIRCULAR_MULTI_SEGMENT_GRADIENT;
170     std::vector<NG::ColorStopArray> colors;
171     std::vector<float> weights;
172     auto vecLinearGradients = *reinterpret_cast<std::vector<VectorColorStops>*>(linearGradients);
173     auto vecWeight = *reinterpret_cast<std::vector<float>*>(weight);
174     if (vecLinearGradients.size() != vecWeight.size()) {
175         LOGE("gauge colors not match weights");
176         return;
177     }
178     if (vecLinearGradients.size() <= 0) {
179         GaugeModel::GetInstance()->ResetGradientColors();
180         return;
181     }
182     if (vecLinearGradients.size() > 1) {
183         for (size_t i = 0; i < vecLinearGradients.size(); i++) {
184             if (vecWeight[i] <= 0) {
185                 continue;
186             }
187             weights.emplace_back(vecWeight[i]);
188             auto vecColorStops = *reinterpret_cast<std::vector<ColorStop>*>(vecLinearGradients[i]);
189             if (vecColorStops.size() <= 1) {
190                 continue;
191             }
192             NG::ColorStopArray colorStopArray;
193             for (size_t j = 0; j < vecColorStops.size(); j++) {
194                 colorStopArray.emplace_back(std::make_pair(
195                     Color(vecColorStops[j].color), Dimension(vecColorStops[j].offset, DimensionUnit::VP)));
196             }
197             colors.emplace_back(colorStopArray);
198         }
199         SortColorStopOffset(colors);
200         GaugeModel::GetInstance()->SetGradientColors(colors, weights, type);
201         return;
202     }
203     type = NG::GaugeType::TYPE_CIRCULAR_SINGLE_SEGMENT_GRADIENT;
204     NG::ColorStopArray colorStopArray;
205     auto vecColorStops = *reinterpret_cast<std::vector<ColorStop>*>(vecLinearGradients[0]);
206     for (size_t i = 0; i < vecColorStops.size(); i++) {
207         colorStopArray.emplace_back(
208             std::make_pair(Color(vecColorStops[i].color), Dimension(vecColorStops[i].offset, DimensionUnit::VP)));
209     }
210     colors.emplace_back(colorStopArray);
211     SortColorStopOffset(colors);
212     GaugeModel::GetInstance()->SetGradientColors(colors, weights, type);
213 }
214 
FfiOHOSAceFrameworkGaugeSetShadowOptions(double radius,double offsetX,double offsetY)215 void FfiOHOSAceFrameworkGaugeSetShadowOptions(double radius, double offsetX, double offsetY)
216 {
217     NG::GaugeShadowOptions shadowOptions;
218     if (radius < 0) {
219         radius = NG::DEFAULT_GAUGE_SHADOW_RADIUS;
220     }
221     if (offsetX < 0) {
222         offsetX = NG::DEFAULT_GAUGE_SHADOW_OFFSETX;
223     }
224     if (offsetY < 0) {
225         offsetY = NG::DEFAULT_GAUGE_SHADOW_OFFSETY;
226     }
227     shadowOptions.radius = radius;
228     shadowOptions.offsetX = offsetX;
229     shadowOptions.offsetY = offsetY;
230 
231     GaugeModel::GetInstance()->SetShadowOptions(shadowOptions);
232 }
233 
FfiOHOSAceFrameworkGaugeSetStrokeWidth(double strokeWidth,int32_t strokeUnit)234 void FfiOHOSAceFrameworkGaugeSetStrokeWidth(double strokeWidth, int32_t strokeUnit)
235 {
236     Dimension strokeDimWidth(strokeWidth, static_cast<DimensionUnit>(strokeUnit));
237     GaugeModel::GetInstance()->SetStrokeWidth(strokeDimWidth);
238 }
239 
FfiOHOSAceFrameworkGaugeSetIndicator(const char * icon,double size)240 void FfiOHOSAceFrameworkGaugeSetIndicator(const char* icon, double size)
241 {
242     std::string iconPath = icon;
243     if (icon == INDICATOR_NULL) {
244         GaugeModel::GetInstance()->SetIsShowIndicator(false);
245         return;
246     }
247     if (icon == INDICATOR_DEFAULT) {
248         GaugeModel::GetInstance()->ResetIndicatorIconPath();
249     } else {
250         std::string bundleName;
251         std::string moduleName;
252         GaugeModel::GetInstance()->SetIndicatorIconPath(iconPath, bundleName, moduleName);
253     }
254 
255     CalcDimension space;
256     if (size < 0) {
257         space = NG::INDICATOR_DISTANCE_TO_TOP;
258     } else {
259         space = CalcDimension(size, DimensionUnit::VP);
260     }
261     GaugeModel::GetInstance()->SetIndicatorSpace(space);
262 }
263 
FfiOHOSAceFrameworkGaugeSetDescription(void (* builder)())264 void FfiOHOSAceFrameworkGaugeSetDescription(void (*builder)())
265 {
266     GaugeModel::GetInstance()->SetIsShowLimitValue(false);
267     GaugeModel::GetInstance()->SetIsShowDescription(true);
268     // parse builder
269     auto buildFunc = CJLambda::Create(builder);
270     RefPtr<AceType> customNode;
271     {
272         ViewStackModel::GetInstance()->NewScope();
273         buildFunc();
274         customNode = ViewStackModel::GetInstance()->Finish();
275     }
276     GaugeModel::GetInstance()->SetDescription(customNode);
277 }
278 }
279