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_text_clock_ffi.h"
17 
18 #include "cj_lambda.h"
19 #include "base/utils/string_utils.h"
20 #include "core/common/ace_application_info.h"
21 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_view_abstract_ffi.h"
22 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
23 #include "bridge/common/utils/utils.h"
24 #include "core/components/common/properties/text_style_parser.h"
25 
26 
27 using namespace OHOS::Ace;
28 using namespace OHOS::FFI;
29 using namespace OHOS::Ace::Framework;
30 
31 namespace OHOS::Ace::Framework {
32 
33 namespace {
34 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
35 const std::string DEFAULT_FORMAT_API_ELEVEN = "aa hh:mm:ss";
36 const std::string DEFAULT_FORMAT_API_TEN = "hms";
37 } // namespace
38 
NativeTextClockController()39 NativeTextClockController::NativeTextClockController() : FFIData()
40 {
41     LOGI("Native TextAreaController constructed: %{public}" PRId64, GetID());
42 }
43 
Start()44 void NativeTextClockController::Start()
45 {
46     if (controller_) {
47         controller_->Start();
48     }
49 }
50 
Stop()51 void NativeTextClockController::Stop()
52 {
53     if (controller_) {
54         controller_->Stop();
55     }
56 }
57 
58 namespace {
59 constexpr int32_t TWENTY_FOUR_HOUR_BASE = 24;
60 constexpr int32_t HOURS_WEST_LOWER_LIMIT = -14;
61 constexpr int32_t HOURS_WEST_UPPER_LIMIT = 12;
62 constexpr int32_t HOURS_WEST_GEOGRAPHICAL_LOWER_LIMIT = -12;
63 
HoursWestIsValid_(int32_t hoursWest)64 bool HoursWestIsValid_(int32_t hoursWest)
65 {
66     if (hoursWest < HOURS_WEST_LOWER_LIMIT || hoursWest > HOURS_WEST_UPPER_LIMIT) {
67         return false;
68     }
69     if (hoursWest < HOURS_WEST_GEOGRAPHICAL_LOWER_LIMIT) {
70         hoursWest += TWENTY_FOUR_HOUR_BASE;
71     }
72     return true;
73 }
74 } // namespace
75 
76 } // namespace OHOS::Ace::Framework
77 
78 extern "C" {
FFICJCreateVectorNativeTextShadow(int64_t size)79 VectorNativeTextShadow FFICJCreateVectorNativeTextShadow(int64_t size)
80 {
81     LOGI("Create NativeTextShadow Vector");
82     return new std::vector<NativeTextShadow>(size);
83 }
84 
FFICJVectorNativeTextShadowSetElement(VectorNativeTextShadow vec,int64_t index,NativeTextShadow textShadow)85 void FFICJVectorNativeTextShadowSetElement(
86     VectorNativeTextShadow vec, int64_t index, NativeTextShadow textShadow)
87 {
88     LOGI("NativeTextShadow Vector Set Element");
89     auto actualVec = reinterpret_cast<std::vector<NativeTextShadow>*>(vec);
90     (*actualVec)[index] = textShadow;
91     LOGI("NativeTextShadow Vector Set Element Success");
92 }
93 
FFICJVectorNativeTextShadowDelete(VectorNativeTextShadow vec)94 void FFICJVectorNativeTextShadowDelete(VectorNativeTextShadow vec)
95 {
96     auto actualVec = reinterpret_cast<std::vector<NativeTextShadow>*>(vec);
97     delete actualVec;
98 }
99 
FfiOHOSAceFrameworkTextClockCreateDefault(int64_t controllerId)100 void FfiOHOSAceFrameworkTextClockCreateDefault(int64_t controllerId)
101 {
102     auto textClock = TextClockModel::GetInstance()->Create();
103     TextClockModel::GetInstance()->SetHoursWest(NAN);
104 
105     auto controller = FFIData::GetData<NativeTextClockController>(controllerId);
106     if (controller != nullptr) {
107         controller->SetController(textClock);
108     } else {
109         LOGE("textClockControllerId is invalid ");
110     }
111 }
112 
FfiOHOSAceFrameworkTextClockCreate(int32_t timeZoneOffset,int64_t controllerId)113 void FfiOHOSAceFrameworkTextClockCreate(int32_t timeZoneOffset, int64_t controllerId)
114 {
115     auto textClock = TextClockModel::GetInstance()->Create();
116     if (HoursWestIsValid_(timeZoneOffset)) {
117         TextClockModel::GetInstance()->SetHoursWest(timeZoneOffset);
118     } else {
119         LOGE("timeZoneOffset is invalid");
120     }
121 
122     auto controller = FFIData::GetData<NativeTextClockController>(controllerId);
123     if (controller != nullptr) {
124         controller->SetController(textClock);
125     } else {
126         LOGE("textClockControllerId is invalid ");
127     }
128 }
129 
FfiOHOSAceFrameworkTextClockFormat(const char * value)130 void FfiOHOSAceFrameworkTextClockFormat(const char* value)
131 {
132     std::string format = static_cast<std::string>(value);
133     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
134         if (format.length() == 0) {
135             TextClockModel::GetInstance()->SetFormat(DEFAULT_FORMAT_API_ELEVEN);
136             return;
137         }
138     } else {
139         std::regex pattern(
140             R"(^([Yy]*[_|\W\s]*[M]*[_|\W\s]*[d]*[_|\W\s]*[D]*[_|\W\s]*[Hh]*[_|\W\s]*[m]*[_|\W\s]*[s]*[_|\W\s]*[S]*)$)");
141         if (format.length() == 0 || !StringUtils::IsAscii(format) || !std::regex_match(format, pattern)) {
142             TextClockModel::GetInstance()->SetFormat(DEFAULT_FORMAT_API_TEN);
143             return;
144         }
145     }
146 
147     TextClockModel::GetInstance()->SetFormat(format);
148 }
149 
FfiOHOSAceFrameworkTextClockOnChange(void (* callback)(int64_t timeStamp))150 void FfiOHOSAceFrameworkTextClockOnChange(void (*callback)(int64_t timeStamp))
151 {
152     auto lambda = [lambda = CJLambda::Create(callback)](
153                       const std::string& value) -> void { lambda(std::atol(value.c_str())); };
154     TextClockModel::GetInstance()->SetOnDateChange(lambda);
155 }
156 
FfiOHOSAceFrameworkTextClockTextColor(uint32_t color)157 void FfiOHOSAceFrameworkTextClockTextColor(uint32_t color)
158 {
159     TextClockModel::GetInstance()->SetTextColor(Color(color));
160 }
161 
FfiOHOSAceFrameworkTextClockFontSize(double size,int32_t unit)162 void FfiOHOSAceFrameworkTextClockFontSize(double size, int32_t unit)
163 {
164     CalcDimension fontSize = CalcDimension(size, DimensionUnit(unit));
165     TextClockModel::GetInstance()->SetFontSize(fontSize);
166 }
167 
FfiOHOSAceFrameworkTextClockFontWeight(const char * fontWeight)168 void FfiOHOSAceFrameworkTextClockFontWeight(const char* fontWeight)
169 {
170     TextClockModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(fontWeight));
171 }
172 
FfiOHOSAceFrameworkTextClockFontStyle(int32_t fontStyle)173 void FfiOHOSAceFrameworkTextClockFontStyle(int32_t fontStyle)
174 {
175     if (!Utils::CheckParamsValid(fontStyle, FONT_STYLES.size())) {
176         LOGE("invalid value for font style");
177         return;
178     }
179     TextClockModel::GetInstance()->SetItalicFontStyle(FONT_STYLES[fontStyle]);
180 }
181 
FfiOHOSAceFrameworkTextClockFontFamily(const char * fontFamily)182 void FfiOHOSAceFrameworkTextClockFontFamily(const char* fontFamily)
183 {
184     std::vector<std::string> fontFamilies;
185     fontFamilies = ConvertStrToFontFamilies(fontFamily);
186     TextClockModel::GetInstance()->SetFontFamily(fontFamilies);
187 }
188 
FfiOHOSAceFrameworkTextClockTextShadow(VectorStringPtr vecContent)189 void FfiOHOSAceFrameworkTextClockTextShadow(VectorStringPtr vecContent)
190 {
191     auto nativeTextShadowVec = *reinterpret_cast<std::vector<NativeTextShadow>*>(vecContent);
192 
193     std::vector<Shadow> shadows(nativeTextShadowVec.size());
194     for (size_t i = 0; i < nativeTextShadowVec.size(); i++) {
195         Dimension dOffsetX(nativeTextShadowVec[i].offsetX, DimensionUnit::VP);
196         Dimension dOffsetY(nativeTextShadowVec[i].offsetY, DimensionUnit::VP);
197 
198         shadows[i].SetBlurRadius(nativeTextShadowVec[i].radius);
199         shadows[i].SetOffsetX(dOffsetX.Value());
200         shadows[i].SetOffsetY(dOffsetY.Value());
201         shadows[i].SetColor(Color(nativeTextShadowVec[i].color));
202     }
203 
204     TextClockModel::GetInstance()->SetTextShadow(shadows);
205 }
206 
FfiOHOSAceFrameworkTextClockFontFeature(const char * fontFeature)207 void FfiOHOSAceFrameworkTextClockFontFeature(const char* fontFeature)
208 {
209     std::string fontFeatureSettings = fontFeature;
210     TextClockModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
211 }
212 
FfiOHOSAceFrameworkTextClockControllerCtor()213 int64_t FfiOHOSAceFrameworkTextClockControllerCtor()
214 {
215     auto controller = FFIData::Create<NativeTextClockController>();
216     if (controller == nullptr) {
217         return FFI_ERROR_CODE;
218     }
219     return controller->GetID();
220 }
221 
FfiOHOSAceFrameworkTextClockControllerStart(int64_t selfID)222 void FfiOHOSAceFrameworkTextClockControllerStart(int64_t selfID)
223 {
224     auto self = FFIData::GetData<NativeTextClockController>(selfID);
225     if (self != nullptr) {
226         self->Start();
227     } else {
228         LOGE("FfiTextArea: invalid textClockController");
229     }
230 }
231 
FfiOHOSAceFrameworkTextClockControllerStop(int64_t selfID)232 void FfiOHOSAceFrameworkTextClockControllerStop(int64_t selfID)
233 {
234     auto self = FFIData::GetData<NativeTextClockController>(selfID);
235     if (self != nullptr) {
236         self->Stop();
237     } else {
238         LOGE("FfiTextArea: invalid textClockController");
239     }
240 }
241 }
242