1 /*
2  * Copyright (c) 2022 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 "core/components_ng/render/render_property.h"
17 
18 #include "core/pipeline_ng/pipeline_context.h"
19 
20 namespace OHOS::Ace::NG {
21 namespace {
ImageRepeatToString(ImageRepeat type)22 std::string ImageRepeatToString(ImageRepeat type)
23 {
24     static const LinearEnumMapNode<ImageRepeat, std::string> toStringMap[] = {
25         { ImageRepeat::NO_REPEAT, "ImageRepeat.NoRepeat" },
26         { ImageRepeat::REPEAT_X, "ImageRepeat.X" },
27         { ImageRepeat::REPEAT_Y, "ImageRepeat.Y" },
28         { ImageRepeat::REPEAT, "ImageRepeat.XY" },
29     };
30     auto idx = BinarySearchFindIndex(toStringMap, ArraySize(toStringMap), type);
31     if (idx >= 0) {
32         return toStringMap[idx].value;
33     }
34     return "ImageRepeat.NoRepeat";
35 }
36 
BasicShapeTypeToString(BasicShapeType type)37 std::string BasicShapeTypeToString(BasicShapeType type)
38 {
39     static const LinearEnumMapNode<BasicShapeType, std::string> toStringMap[] = {
40         { BasicShapeType::NONE, "None" },
41         { BasicShapeType::INSET, "Inset" },
42         { BasicShapeType::CIRCLE, "Circle" },
43         { BasicShapeType::ELLIPSE, "Ellipse" },
44         { BasicShapeType::POLYGON, "Polygon" },
45         { BasicShapeType::PATH, "Path" },
46         { BasicShapeType::RECT, "Rect" },
47     };
48     auto idx = BinarySearchFindIndex(toStringMap, ArraySize(toStringMap), type);
49     if (idx >= 0) {
50         return toStringMap[idx].value;
51     }
52     return "";
53 }
54 
LinearGradientBlurDirection(GradientDirection direction)55 std::string LinearGradientBlurDirection(GradientDirection direction)
56 {
57         static const LinearEnumMapNode<GradientDirection, std::string> toStringMap[] = {
58         { GradientDirection::LEFT, "LEFT" },
59         { GradientDirection::TOP, "LEFT" },
60         { GradientDirection::RIGHT, "RIGHT" },
61         { GradientDirection::BOTTOM, "BOTTOM" },
62         { GradientDirection::LEFT_TOP, "LEFT_TOP" },
63         { GradientDirection::LEFT_BOTTOM, "LEFT_BOTTOM" },
64         { GradientDirection::RIGHT_TOP, "RIGHT_TOP" },
65         { GradientDirection::RIGHT_BOTTOM, "RIGHT_BOTTOM" },
66         { GradientDirection::NONE, "NONE" },
67         { GradientDirection::START_TO_END, "START_TO_END" },
68         { GradientDirection::END_TO_START, "END_TO_START" },
69     };
70     auto idx = BinarySearchFindIndex(toStringMap, ArraySize(toStringMap), direction);
71     if (idx >= 0) {
72         return toStringMap[idx].value;
73     }
74     return "";
75 }
76 } // namespace
77 
78 #define ACE_OFFSET_API_NINE_TO_JSON(name)                            \
79     auto json##name = JsonUtil::Create(true);                        \
80     if (prop##name.has_value()) {                                    \
81         json##name->Put("x", prop##name->GetX().ToString().c_str()); \
82         json##name->Put("y", prop##name->GetY().ToString().c_str()); \
83     } else {                                                         \
84         json##name->Put("x", "0.0px");                               \
85         json##name->Put("y", "0.0px");                               \
86     }
87 
88 #define ACE_OFFSET_API_TEN_TO_JSON(name)                             \
89     auto json##name = JsonUtil::Create(true);                        \
90     if (prop##name.has_value()) {                                    \
91         json##name->Put("x", prop##name->GetX().ToString().c_str()); \
92         json##name->Put("y", prop##name->GetY().ToString().c_str()); \
93     } else {                                                         \
94         json##name->Put("x", "");                                    \
95         json##name->Put("y", "");                                    \
96     }
97 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const98 void RenderPositionProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
99 {
100     /* no fixed attr below, just return */
101     if (filter.IsFastFilter()) {
102         return;
103     }
104     ACE_OFFSET_API_TEN_TO_JSON(Position);
105     json->PutExtAttr("position", jsonPosition, filter);
106 
107     auto context = PipelineContext::GetCurrentContext();
108     // add version protection, null as default start from API 10 or higher
109     if (context && context->GetMinPlatformVersion() > static_cast<int32_t>(PlatformVersion::VERSION_NINE)) {
110         ACE_OFFSET_API_TEN_TO_JSON(Offset);
111         json->PutExtAttr("offset", jsonOffset, filter);
112 
113         ACE_OFFSET_API_TEN_TO_JSON(Anchor);
114         json->PutExtAttr("markAnchor", jsonAnchor, filter);
115     } else {
116         ACE_OFFSET_API_NINE_TO_JSON(Offset);
117         json->PutExtAttr("offset", jsonOffset, filter);
118 
119         ACE_OFFSET_API_NINE_TO_JSON(Anchor);
120         json->PutExtAttr("markAnchor", jsonAnchor, filter);
121     }
122 }
123 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const124 void GraphicsProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
125 {
126     /* no fixed attr below, just return */
127     if (filter.IsFastFilter()) {
128         return;
129     }
130     json->PutExtAttr("grayscale", propFrontGrayScale.has_value() ? propFrontGrayScale->Value() : 0.0, filter);
131     json->PutExtAttr("brightness", propFrontBrightness.has_value() ? propFrontBrightness->Value() : 1.0, filter);
132     json->PutExtAttr("saturate", propFrontSaturate.has_value() ? propFrontSaturate->Value() : 1.0, filter);
133     json->PutExtAttr("contrast", propFrontContrast.has_value() ? propFrontContrast->Value() : 1.0, filter);
134     json->PutExtAttr("sepia", propFrontSepia.has_value() ? propFrontSepia->Value() : 0.0, filter);
135     json->PutExtAttr("hueRotate", propFrontHueRotate.has_value() ? propFrontHueRotate.value() : 0.0, filter);
136     json->PutExtAttr("colorBlend",
137         propFrontColorBlend.has_value() ? propFrontColorBlend->ColorToString().c_str() : "", filter);
138     json->PutExtAttr("blendMode",
139         propBackBlendMode.has_value() ? static_cast<uint16_t>(propBackBlendMode.value()) : 0, filter);
140     json->PutExtAttr("dynamicDimming", propDynamicDimDegree.has_value() ?
141         static_cast<float_t>(propDynamicDimDegree.value()) : 1.0f, filter);
142     auto jsonBgBrightness = JsonUtil::Create(true);
143     jsonBgBrightness->Put(
144         "dynamicLightUpRate", propDynamicLightUpRate.has_value() ? propDynamicLightUpRate.value() : 0.0);
145     jsonBgBrightness->Put(
146         "dynamicLightUpDegree", propDynamicLightUpDegree.has_value() ? propDynamicLightUpDegree.value() : 0.0);
147     json->PutExtAttr("BackgroundBrightness", jsonBgBrightness, filter);
148     auto jsonShadow = JsonUtil::Create(true);
149     auto shadow = propBackShadow.value_or(Shadow());
150     if (shadow.GetStyle() == ShadowStyle::OuterDefaultXS) {
151         json->PutExtAttr("shadow", "ShadowStyle.OuterDefaultXS", filter);
152     } else if (shadow.GetStyle() == ShadowStyle::OuterDefaultSM) {
153         json->PutExtAttr("shadow", "ShadowStyle.OuterDefaultSM", filter);
154     } else if (shadow.GetStyle() == ShadowStyle::OuterDefaultMD) {
155         json->PutExtAttr("shadow", "ShadowStyle.OuterDefaultMD", filter);
156     } else if (shadow.GetStyle() == ShadowStyle::OuterDefaultLG) {
157         json->PutExtAttr("shadow", "ShadowStyle.OuterDefaultLG", filter);
158     } else if (shadow.GetStyle() == ShadowStyle::OuterFloatingSM) {
159         json->PutExtAttr("shadow", "ShadowStyle.OuterFloatingSM", filter);
160     } else if (shadow.GetStyle() == ShadowStyle::OuterFloatingMD) {
161         json->PutExtAttr("shadow", "ShadowStyle.OuterFloatingMD", filter);
162     } else {
163         jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
164         if (shadow.GetShadowColorStrategy() == ShadowColorStrategy::AVERAGE) {
165             jsonShadow->Put("color", "ColoringStrategy.AVERAGE");
166         } else if (shadow.GetShadowColorStrategy() == ShadowColorStrategy::PRIMARY) {
167             jsonShadow->Put("color", "ColoringStrategy.PRIMARY");
168         } else {
169             jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
170         }
171         jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
172         jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
173         jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
174         jsonShadow->Put("fill", std::to_string(shadow.GetIsFilled()).c_str());
175         json->PutExtAttr("shadow", jsonShadow, filter);
176     }
177     if (propFrontInvert.has_value()) {
178         if (propFrontInvert->index() == 0) {
179             json->PutExtAttr("invert", std::get<float>(propFrontInvert.value()), filter);
180         } else {
181             InvertOption option = std::get<InvertOption>(propFrontInvert.value());
182             auto jsonInvert = JsonUtil::Create(true);
183             jsonInvert->Put("low", option.low_);
184             jsonInvert->Put("high", option.high_);
185             jsonInvert->Put("threshold", option.threshold_);
186             jsonInvert->Put("thresholdRange", option.thresholdRange_);
187             json->PutExtAttr("invert", jsonInvert, filter);
188         }
189     }
190     if (propLinearGradientBlur.has_value()) {
191         auto jsonLinearGradientBlur = JsonUtil::Create(true);
192         std::string value = propLinearGradientBlur->blurRadius_.ToString();
193         jsonLinearGradientBlur->Put("value", value.c_str());
194         auto options = JsonUtil::Create(true);
195         std::string direction = LinearGradientBlurDirection(propLinearGradientBlur->direction_);
196         options->Put("direction", direction.c_str());
197         auto fractionStops = JsonUtil::CreateArray(true);
198         int size = static_cast<int>(propLinearGradientBlur->fractionStops_.size());
199         for (auto i = 0; i < size; i++) {
200             auto fraction = propLinearGradientBlur->fractionStops_[i];
201             std::string stop = std::to_string(fraction.first) + "," + std::to_string(fraction.second);
202             fractionStops->Put(std::to_string(i).c_str(), stop.c_str());
203         }
204         options->Put("fractionStops", fractionStops);
205         jsonLinearGradientBlur->Put("options", options);
206         json->Put("linearGradientBlur", jsonLinearGradientBlur);
207     }
208 }
209 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const210 void BackgroundProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
211 {
212     /* no fixed attr below, just return */
213     if (filter.IsFastFilter()) {
214         return;
215     }
216     std::string backgroundImage = "NONE";
217     if (propBackgroundImage.has_value()) {
218         backgroundImage = propBackgroundImage->GetSrc() + ", " +
219                           ImageRepeatToString(propBackgroundImageRepeat.value_or(ImageRepeat::NO_REPEAT));
220     }
221     json->PutExtAttr("backgroundImage", backgroundImage.c_str(), filter);
222 
223     json->PutExtAttr("backgroundImageSize", !propBackgroundImageSize.has_value() ?
224         "ImageSize.Auto" : propBackgroundImageSize->ToString().c_str(), filter);
225 
226     if (propBackgroundImagePosition.has_value()) {
227         json->PutExtAttr("backgroundImagePosition", propBackgroundImagePosition->ToString().c_str(), filter);
228     } else {
229         auto jsonValue = JsonUtil::Create(true);
230         jsonValue->Put("x", 0.0);
231         jsonValue->Put("y", 0.0);
232         json->PutExtAttr("backgroundImagePosition", jsonValue, filter);
233     }
234     json->PutExtAttr("backdropBlur", (propBlurRadius.value_or(Dimension(0))).ConvertToPx(), filter);
235     json->PutExtAttr("backgroundImageResizable",
236         propBackgroundImageResizableSlice.value_or(ImageResizableSlice()).ToString().c_str(), filter);
237 }
238 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const239 void CustomBackgroundProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
240 {
241     /* no fixed attr below, just return */
242     if (filter.IsFastFilter()) {
243         return;
244     }
245     std::string backgroundPixelMap = "NONE";
246     if (propBackgroundPixelMap.has_value()) {
247         backgroundPixelMap = std::to_string(propBackgroundPixelMap.value()->GetWidth()) + ", " +
248                              std::to_string(propBackgroundPixelMap.value()->GetHeight());
249     }
250     json->PutExtAttr("backgroundPixelMap", backgroundPixelMap.c_str(), filter);
251     json->PutExtAttr("backgroundAlign", propBackgroundAlign.value().ToString().c_str(), filter);
252 }
253 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const254 void ForegroundProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
255 {
256     /* no fixed attr below, just return */
257     if (filter.IsFastFilter()) {
258         return;
259     }
260     json->PutExtAttr("blur", (propBlurRadius.value_or(Dimension(0))).ConvertToPx(), filter);
261     auto jsonOption = JsonUtil::Create(true);
262     jsonOption->Put("radius", std::to_string(propForegroundEffect.value_or(0.0f)).c_str());
263     json->PutExtAttr("foregroundEffect", jsonOption, filter);
264     if (propMotionBlur.has_value()) {
265         auto motionBlur = JsonUtil::Create(true);
266         motionBlur->Put("radius", propMotionBlur->radius);
267         auto motionBlurAnchor = JsonUtil::Create(true);
268         motionBlurAnchor->Put("x", propMotionBlur->anchor.x);
269         motionBlurAnchor->Put("y", propMotionBlur->anchor.y);
270         motionBlur->Put("anchor", motionBlurAnchor);
271         json->Put("motionBlur", motionBlur);
272     }
273 }
274 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const275 void ClipProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
276 {
277     /* no fixed attr below, just return */
278     if (filter.IsFastFilter()) {
279         return;
280     }
281     if (propClipShape.has_value()) {
282         auto jsonClip = JsonUtil::Create(true);
283         auto shape = propClipShape.value();
284         auto shapeType = BasicShapeTypeToString(shape->GetBasicShapeType());
285         if (!shapeType.empty()) {
286             jsonClip->Put("shape", shapeType.c_str());
287         }
288         json->PutExtAttr("clip", jsonClip->ToString().c_str(), filter);
289     } else {
290         json->PutExtAttr("clip", propClipEdge.value_or(false) ? "true" : "false", filter);
291     }
292 
293     auto jsonMask = JsonUtil::Create(true);
294     if (propClipMask.has_value()) {
295         auto shape = propClipMask.value();
296         auto shapeType = BasicShapeTypeToString(shape->GetBasicShapeType());
297         if (!shapeType.empty()) {
298             jsonMask->Put("shape", shapeType.c_str());
299         }
300     }
301     json->PutExtAttr("mask", jsonMask, filter);
302 }
303 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const304 void GradientProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
305 {
306     /* no fixed attr below, just return */
307     if (filter.IsFastFilter()) {
308         return;
309     }
310     if (propLinearGradient.has_value()) {
311         json->PutExtAttr("linearGradient", propLinearGradient->LinearGradientToJson(), filter);
312     } else {
313         json->PutExtAttr("linearGradient", JsonUtil::Create(true), filter);
314     }
315 
316     if (propSweepGradient.has_value()) {
317         json->PutExtAttr("sweepGradient", propSweepGradient->SweepGradientToJson(), filter);
318     } else {
319         json->PutExtAttr("sweepGradient", JsonUtil::Create(true), filter);
320     }
321 
322     if (propRadialGradient.has_value()) {
323         json->PutExtAttr("radialGradient", propRadialGradient->RadialGradientToJson(), filter);
324     } else {
325         json->PutExtAttr("radialGradient", JsonUtil::Create(true), filter);
326     }
327 }
328 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const329 void TransformProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
330 {
331     const double halfDimension = 50.0;
332     auto center = propTransformCenter.value_or(DimensionOffset(
333         Dimension(halfDimension, DimensionUnit::PERCENT), Dimension(halfDimension, DimensionUnit::PERCENT)));
334     /* no fixed attr below, just return */
335     if (filter.IsFastFilter()) {
336         return;
337     }
338     if (propTransformRotate.has_value()) {
339         auto jsonValue = JsonUtil::Create(true);
340         jsonValue->Put("x", std::to_string(propTransformRotate->x).c_str());
341         jsonValue->Put("y", std::to_string(propTransformRotate->y).c_str());
342         jsonValue->Put("z", std::to_string(propTransformRotate->z).c_str());
343         jsonValue->Put("angle", std::to_string(propTransformRotate->w).c_str());
344         jsonValue->Put("perspective", std::to_string(propTransformRotate->v).c_str());
345         jsonValue->Put("centerX", center.GetX().ToString().c_str());
346         jsonValue->Put("centerY", center.GetY().ToString().c_str());
347         if (center.GetZ().has_value()) {
348             jsonValue->Put("centerZ", center.GetZ().value().ToString().c_str());
349         } else {
350             json->PutExtAttr("centerZ", JsonUtil::Create(true), filter);
351         }
352         json->PutExtAttr("rotate", jsonValue, filter);
353     } else {
354         json->PutExtAttr("rotate", JsonUtil::Create(true), filter);
355     }
356 
357     if (propTransformScale.has_value()) {
358         auto jsonValue = JsonUtil::Create(true);
359         jsonValue->Put("x", std::to_string(propTransformScale->x).c_str());
360         jsonValue->Put("y", std::to_string(propTransformScale->y).c_str());
361         jsonValue->Put("centerX", center.GetX().ToString().c_str());
362         jsonValue->Put("centerY", center.GetY().ToString().c_str());
363         json->PutExtAttr("scale", jsonValue, filter);
364     } else {
365         json->PutExtAttr("scale", JsonUtil::Create(true), filter);
366     }
367 
368     if (propTransformTranslate.has_value()) {
369         auto jsonValue = JsonUtil::Create(true);
370         jsonValue->Put("x", propTransformTranslate->x.ToString().c_str());
371         jsonValue->Put("y", propTransformTranslate->y.ToString().c_str());
372         jsonValue->Put("z", propTransformTranslate->z.ToString().c_str());
373         json->PutExtAttr("translate", jsonValue, filter);
374     } else {
375         json->PutExtAttr("translate", JsonUtil::Create(true), filter);
376     }
377 }
378 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const379 void BorderProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
380 {
381     /* no fixed attr below, just return */
382     if (filter.IsFastFilter()) {
383         return;
384     }
385     auto jsonBorder = JsonUtil::Create(true);
386     propBorderStyle.value_or(BorderStyleProperty()).ToJsonValue(json, jsonBorder, filter);
387     propBorderColor.value_or(BorderColorProperty()).ToJsonValue(json, jsonBorder, filter);
388     propBorderWidth.value_or(BorderWidthProperty()).ToJsonValue(json, jsonBorder, filter);
389     propBorderRadius.value_or(BorderRadiusProperty()).ToJsonValue(json, jsonBorder, filter);
390     propDashGap.value_or(BorderWidthProperty()).ToDashJsonValue(json, jsonBorder, filter, "dashGap");
391     propDashWidth.value_or(BorderWidthProperty()).ToDashJsonValue(json, jsonBorder, filter, "dashWidth");
392 
393     json->PutExtAttr("border", jsonBorder->ToString().c_str(), filter);
394 }
395 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const396 void OuterBorderProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
397 {
398     /* no fixed attr below, just return */
399     if (filter.IsFastFilter()) {
400         return;
401     }
402     auto jsonOutline = JsonUtil::Create(true);
403     propOuterBorderStyle.value_or(BorderStyleProperty()).ToJsonValue(json, jsonOutline, filter, true);
404     propOuterBorderColor.value_or(BorderColorProperty()).ToJsonValue(json, jsonOutline, filter, true);
405     propOuterBorderWidth.value_or(BorderWidthProperty()).ToJsonValue(json, jsonOutline, filter, true);
406     propOuterBorderRadius.value_or(BorderRadiusProperty()).ToJsonValue(json, jsonOutline, filter, true);
407     json->PutExtAttr("outline", jsonOutline->ToString().c_str(), filter);
408 }
409 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const410 void PointLightProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
411 {
412     /* no fixed attr below, just return */
413     if (filter.IsFastFilter()) {
414         return;
415     }
416     auto jsonLightIntensity = JsonUtil::Create(true);
417     jsonLightIntensity->Put("lightIntensity", propLightIntensity.has_value() ? propLightIntensity.value() : 0.0);
418     json->PutExtAttr("pointLight", jsonLightIntensity, filter);
419 
420     if (propLightPosition.has_value()) {
421         auto jsonLightPosition = JsonUtil::Create(true);
422         jsonLightPosition->Put("x", propLightPosition->x.ToString().c_str());
423         jsonLightPosition->Put("y", propLightPosition->y.ToString().c_str());
424         jsonLightPosition->Put("z", propLightPosition->z.ToString().c_str());
425         json->PutExtAttr("LightPosition", jsonLightPosition, filter);
426     } else {
427         json->PutExtAttr("LightPosition", JsonUtil::Create(true), filter);
428     }
429 }
430 } // namespace OHOS::Ace::NG
431