1 /*
2 * Copyright (c) 2023 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 "frameworks/bridge/declarative_frontend/jsview/js_image_span.h"
17 #include "frameworks/bridge/declarative_frontend/jsview/js_container_span.h"
18
19 #if !defined(PREVIEW)
20 #include <dlfcn.h>
21 #endif
22
23 #include "base/log/ace_scoring_log.h"
24 #include "core/components/common/layout/constants.h"
25 #include "core/components_ng/pattern/image/image_model.h"
26 #include "core/components_ng/pattern/text/image_span_view.h"
27 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
28 #include "frameworks/bridge/declarative_frontend/jsview/js_image.h"
29
30 namespace OHOS::Ace::Framework {
31 const std::vector<float> DEFAULT_COLORFILTER_MATRIX = {
32 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
33 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f
34 };
35
Create(const JSCallbackInfo & info)36 void JSImageSpan::Create(const JSCallbackInfo& info)
37 {
38 if (!Container::IsCurrentUseNewPipeline()) {
39 return;
40 }
41 if (info.Length() != 1) {
42 return;
43 }
44 JSImage::CreateImage(info, true);
45 NG::ImageSpanView::Create();
46 }
47
SetAlt(const JSCallbackInfo & info)48 void JSImageSpan::SetAlt(const JSCallbackInfo& info)
49 {
50 if (!Container::IsCurrentUseNewPipeline()) {
51 return;
52 }
53 if (info.Length() < 1) {
54 return;
55 }
56 JSImage::SetAlt(info);
57 }
58
SetObjectFit(const JSCallbackInfo & info)59 void JSImageSpan::SetObjectFit(const JSCallbackInfo& info)
60 {
61 if (info.Length() != 1) {
62 return;
63 }
64
65 JSRef<JSVal> args = info[0];
66 if (args->IsNumber()) {
67 auto fit = static_cast<ImageFit>(args->ToNumber<int32_t>());
68 if (fit < ImageFit::FILL || fit > ImageFit::BOTTOM_END) {
69 fit = ImageFit::COVER;
70 }
71 ImageModel::GetInstance()->SetImageFit(fit);
72 } else {
73 ImageModel::GetInstance()->SetImageFit(ImageFit::COVER);
74 }
75 }
76
SetVerticalAlign(int32_t verticalAlign)77 void JSImageSpan::SetVerticalAlign(int32_t verticalAlign)
78 {
79 auto align = static_cast<VerticalAlign>(verticalAlign);
80 if (align < VerticalAlign::TOP || align > VerticalAlign::NONE) {
81 align = VerticalAlign::BOTTOM;
82 }
83 NG::ImageSpanView::SetVerticalAlign(align);
84 }
85
SetTextBackgroundStyle(const JSCallbackInfo & info)86 void JSImageSpan::SetTextBackgroundStyle(const JSCallbackInfo& info)
87 {
88 auto textBackgroundStyle = JSContainerSpan::ParseTextBackgroundStyle(info);
89 NG::ImageSpanView::SetPlaceHolderStyle(textBackgroundStyle);
90 }
91
OnComplete(const JSCallbackInfo & args)92 void JSImageSpan::OnComplete(const JSCallbackInfo& args)
93 {
94 JSRef<JSVal> arg = args[0];
95 if (arg->IsFunction()) {
96 auto jsLoadSuccFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageSuccessEvent, 1>>(
97 JSRef<JSFunc>::Cast(arg), LoadImageSuccEventToJSValue);
98
99 auto onComplete = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadSuccFunc)](
100 const LoadImageSuccessEvent& info) {
101 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
102 ACE_SCORING_EVENT("ImageSpan.onComplete");
103 func->Execute(info);
104 };
105 ImageModel::GetInstance()->SetOnComplete(std::move(onComplete));
106 }
107 }
108
OnError(const JSCallbackInfo & args)109 void JSImageSpan::OnError(const JSCallbackInfo& args)
110 {
111 JSRef<JSVal> arg = args[0];
112 if (arg->IsFunction()) {
113 auto jsLoadFailFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageFailEvent, 1>>(
114 JSRef<JSFunc>::Cast(arg), LoadImageFailEventToJSValue);
115 auto onError = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadFailFunc)](
116 const LoadImageFailEvent& info) {
117 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
118 ACE_SCORING_EVENT("ImageSpan.onError");
119 func->Execute(info);
120 };
121 ImageModel::GetInstance()->SetOnError(onError);
122 }
123 }
124
SetBaselineOffset(const JSCallbackInfo & info)125 void JSImageSpan::SetBaselineOffset(const JSCallbackInfo& info)
126 {
127 if (info.Length() < 1) {
128 return;
129 }
130 NG::CalcLength value;
131 if (ConvertFromJSValueNG(info[0], value) &&
132 value.GetDimensionContainsNegative().Unit() != DimensionUnit::PERCENT) {
133 NG::ImageSpanView::SetBaselineOffset(value.GetDimensionContainsNegative());
134 return;
135 }
136 value.Reset();
137 NG::ImageSpanView::SetBaselineOffset(value.GetDimensionContainsNegative());
138 }
139
SetColorFilter(const JSCallbackInfo & info)140 void JSImageSpan::SetColorFilter(const JSCallbackInfo& info)
141 {
142 if (info.Length() != 1) {
143 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
144 return;
145 }
146 auto tmpInfo = info[0];
147 if (!tmpInfo->IsArray() && !tmpInfo->IsObject()) {
148 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
149 return;
150 }
151 if (tmpInfo->IsObject() && !tmpInfo->IsArray()) {
152 auto drawingColorFilter = CreateDrawingColorFilter(tmpInfo);
153 if (drawingColorFilter) {
154 ImageModel::GetInstance()->SetDrawingColorFilter(drawingColorFilter);
155 return;
156 }
157 JSColorFilter* colorFilter;
158 if (!tmpInfo->IsUndefined() && !tmpInfo->IsNull()) {
159 colorFilter = JSRef<JSObject>::Cast(tmpInfo)->Unwrap<JSColorFilter>();
160 } else {
161 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
162 return;
163 }
164 if (colorFilter && colorFilter->GetColorFilterMatrix().size() == COLOR_FILTER_MATRIX_SIZE) {
165 ImageModel::GetInstance()->SetColorFilterMatrix(colorFilter->GetColorFilterMatrix());
166 return;
167 }
168 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
169 return;
170 }
171 JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
172 if (array->Length() != COLOR_FILTER_MATRIX_SIZE) {
173 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
174 return;
175 }
176 std::vector<float> colorfilter;
177 for (size_t i = 0; i < array->Length(); i++) {
178 JSRef<JSVal> value = array->GetValueAt(i);
179 if (value->IsNumber()) {
180 colorfilter.emplace_back(value->ToNumber<float>());
181 } else {
182 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
183 return;
184 }
185 }
186 ImageModel::GetInstance()->SetColorFilterMatrix(colorfilter);
187 }
188
JSBind(BindingTarget globalObj)189 void JSImageSpan::JSBind(BindingTarget globalObj)
190 {
191 JSClass<JSImageSpan>::Declare("ImageSpan");
192 MethodOptions opt = MethodOptions::NONE;
193 JSClass<JSImageSpan>::StaticMethod("create", &JSImageSpan::Create, opt);
194 JSClass<JSImageSpan>::StaticMethod("alt", &JSImageSpan::SetAlt, opt);
195 JSClass<JSImageSpan>::StaticMethod("objectFit", &JSImageSpan::SetObjectFit);
196 JSClass<JSImageSpan>::StaticMethod("verticalAlign", &JSImageSpan::SetVerticalAlign);
197 JSClass<JSImageSpan>::StaticMethod("textBackgroundStyle", &JSImageSpan::SetTextBackgroundStyle);
198 JSClass<JSImageSpan>::StaticMethod("onComplete", &JSImageSpan::OnComplete);
199 JSClass<JSImageSpan>::StaticMethod("onError", &JSImageSpan::OnError);
200 JSClass<JSImageSpan>::StaticMethod("border", &JSImage::JsBorder);
201 JSClass<JSImageSpan>::StaticMethod("borderRadius", &JSImage::JsBorderRadius);
202 JSClass<JSImageSpan>::StaticMethod("colorFilter", &JSImageSpan::SetColorFilter, opt);
203 JSClass<JSImageSpan>::StaticMethod("baselineOffset", &JSImageSpan::SetBaselineOffset);
204 JSClass<JSImageSpan>::InheritAndBind<JSViewAbstract>(globalObj);
205 }
206 } // namespace OHOS::Ace::Framework
207