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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GRADIENT_PROPERTY_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GRADIENT_PROPERTY_H 18 19 #include <array> 20 #include <memory> 21 #include <optional> 22 #include <regex> 23 #include <vector> 24 25 #include "base/geometry/dimension.h" 26 #include "base/geometry/ng/offset_t.h" 27 #include "base/json/json_util.h" 28 #include "base/log/log.h" 29 #include "base/memory/ace_type.h" 30 #include "base/utils/macros.h" 31 #include "base/utils/utils.h" 32 #include "core/components/common/properties/color.h" 33 34 namespace OHOS::Ace::NG { 35 36 constexpr float BOX_END_SIZE = 100.0f; 37 38 enum class GradientDirection { 39 LEFT = 0, 40 TOP, 41 RIGHT, 42 BOTTOM, 43 LEFT_TOP, 44 LEFT_BOTTOM, 45 RIGHT_TOP, 46 RIGHT_BOTTOM, 47 NONE, 48 START_TO_END, 49 END_TO_START, 50 }; 51 52 enum class GradientType { 53 LINEAR, 54 RADIAL, 55 SWEEP, 56 CONIC, 57 }; 58 59 enum class RadialSizeType { 60 CLOSEST_SIDE, 61 CLOSEST_CORNER, 62 FARTHEST_SIDE, 63 FARTHEST_CORNER, 64 NONE, 65 }; 66 67 enum class RadialShapeType { 68 CIRCLE, 69 ELLIPSE, 70 NONE, 71 }; 72 73 enum class SpreadMethod { 74 PAD, 75 REFLECT, 76 REPEAT, 77 }; 78 79 struct LinearGradientInfo { 80 float x1 = 0.0f; 81 float x2 = 0.0f; 82 float y1 = 0.0f; 83 float y2 = 0.0f; 84 bool operator==(const LinearGradientInfo& other) const 85 { 86 return ( 87 NearEqual(x1, other.x1) && NearEqual(x2, other.x2) && NearEqual(y1, other.y1) && NearEqual(y2, other.y2)); 88 } 89 }; 90 91 struct RadialGradientInfo { 92 float r = 0.0f; 93 float cx = 0.0f; 94 float cy = 0.0f; 95 float fx = 0.0f; 96 float fy = 0.0f; 97 bool operator==(const RadialGradientInfo& other) const 98 { 99 return (NearEqual(r, other.r) && NearEqual(cx, other.cx) && NearEqual(cy, other.cy) && 100 NearEqual(fx, other.fx) && NearEqual(fy, other.fy)); 101 } 102 }; 103 104 class GradientColor final { 105 public: 106 GradientColor() = default; 107 ~GradientColor() = default; 108 GradientColor(const Color & color)109 explicit GradientColor(const Color& color) 110 { 111 color_ = color; 112 } 113 114 void SetDimension(double value, DimensionUnit unit = DimensionUnit::PERCENT) 115 { 116 if (value < 0.0) { 117 return; 118 } 119 if (unit == DimensionUnit::PERCENT && value > BOX_END_SIZE) { 120 return; 121 } 122 dimension_ = Dimension(value, unit); 123 } 124 SetDimension(const Dimension & dimension)125 void SetDimension(const Dimension& dimension) 126 { 127 if (dimension.Value() < 0.0) { 128 return; 129 } 130 if (dimension.Unit() == DimensionUnit::PERCENT && dimension.Value() > BOX_END_SIZE) { 131 return; 132 } 133 dimension_ = dimension; 134 } 135 SetHasValue(bool hasValue)136 void SetHasValue(bool hasValue) 137 { 138 hasValue_ = hasValue; 139 } 140 SetColor(const Color & color)141 void SetColor(const Color& color) 142 { 143 color_ = color; 144 } 145 GetColor()146 const Color& GetColor() const 147 { 148 return color_; 149 } 150 SetLinearColor(const LinearColor & linearColor)151 void SetLinearColor(const LinearColor& linearColor) 152 { 153 linearColor_ = linearColor; 154 } 155 GetLinearColor()156 const LinearColor& GetLinearColor() const 157 { 158 return linearColor_; 159 } 160 GetDimension()161 const Dimension& GetDimension() const 162 { 163 return dimension_; 164 } 165 GetHasValue()166 bool GetHasValue() const 167 { 168 return hasValue_; 169 } 170 SetOpacity(double opacity)171 void SetOpacity(double opacity) 172 { 173 opacity_ = opacity; 174 } 175 GetOpacity()176 double GetOpacity() const 177 { 178 return opacity_; 179 } 180 181 bool operator==(const GradientColor& other) const 182 { 183 return (hasValue_ == other.GetHasValue() && color_ == other.GetColor() && dimension_ == other.GetDimension() && 184 opacity_ == other.GetOpacity() && linearColor_ == other.GetLinearColor()); 185 } 186 187 private: 188 bool hasValue_ = true; 189 Color color_ { Color::TRANSPARENT }; 190 LinearColor linearColor_ { LinearColor::TRANSPARENT }; 191 Dimension dimension_ { BOX_END_SIZE, DimensionUnit::PERCENT }; 192 float opacity_ = 1.0f; 193 }; 194 195 struct ACE_EXPORT RadialGradient { 196 // size type 197 std::optional<RadialSizeType> radialSizeType; 198 // shape circle or ellipse 199 std::optional<RadialShapeType> radialShape; 200 // size in x-axis 201 std::optional<Dimension> radialHorizontalSize; 202 // size in y-axis 203 std::optional<Dimension> radialVerticalSize; 204 // center of shape 205 std::optional<Dimension> radialCenterX; 206 std::optional<Dimension> radialCenterY; 207 208 std::optional<Dimension> fRadialCenterX; 209 std::optional<Dimension> fRadialCenterY; 210 211 bool operator==(const RadialGradient& other) const 212 { 213 return (radialSizeType == other.radialSizeType && radialShape == other.radialShape && 214 radialHorizontalSize == other.radialHorizontalSize && radialVerticalSize == other.radialVerticalSize && 215 radialCenterX == other.radialCenterX && radialCenterY == other.radialCenterY && 216 fRadialCenterX == other.fRadialCenterX && fRadialCenterY == other.fRadialCenterY); 217 } 218 }; 219 220 struct ACE_EXPORT LinearGradient { 221 // direction in x-axis 222 std::optional<GradientDirection> linearX; 223 // direction in y-axis 224 std::optional<GradientDirection> linearY; 225 // angle of gradient line in bearing angle 226 std::optional<Dimension> angle; 227 228 std::optional<Dimension> x1; 229 std::optional<Dimension> y1; 230 std::optional<Dimension> x2; 231 std::optional<Dimension> y2; 232 233 // is direction in x-axis IsXAxisLinearGradient234 static bool IsXAxis(GradientDirection direction) 235 { 236 return (direction == GradientDirection::LEFT || direction == GradientDirection::RIGHT || 237 direction == GradientDirection::START_TO_END || direction == GradientDirection::END_TO_START); 238 } 239 240 bool operator==(const LinearGradient& other) const 241 { 242 return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2 && linearX == other.linearX && 243 linearY == other.linearY && angle == other.angle); 244 } 245 }; 246 247 struct ACE_EXPORT SweepGradient { 248 // center of x-axis 249 std::optional<Dimension> centerX; 250 // center of y-axis 251 std::optional<Dimension> centerY; 252 // startAngle in degree 253 std::optional<Dimension> startAngle; 254 // endAngle in degree 255 std::optional<Dimension> endAngle; 256 // rotation in degree 257 std::optional<Dimension> rotation; 258 259 bool operator==(const OHOS::Ace::NG::SweepGradient& other) const 260 { 261 return (centerX == other.centerX && centerY == other.centerY && startAngle == other.startAngle && 262 endAngle == other.endAngle && rotation == other.rotation); 263 } 264 }; 265 266 class ACE_FORCE_EXPORT Gradient final { 267 public: 268 void AddColor(const GradientColor& color); 269 270 void ClearColors(); 271 IsSweepGradientValid()272 bool IsSweepGradientValid() const 273 { 274 if (sweepGradient_->startAngle.has_value() && sweepGradient_->endAngle.has_value()) { 275 return LessOrEqual(sweepGradient_->startAngle.value().Value(), sweepGradient_->endAngle.value().Value()); 276 } 277 if (sweepGradient_->startAngle.has_value() && !sweepGradient_->endAngle.has_value()) { 278 return LessOrEqual(sweepGradient_->startAngle.value().Value(), 0.0); 279 } 280 if (!sweepGradient_->startAngle.has_value() && sweepGradient_->endAngle.has_value()) { 281 return LessOrEqual(0.0, sweepGradient_->endAngle.value().Value()); 282 } 283 return true; 284 } 285 IsValid()286 bool IsValid() const 287 { 288 if (GetType() == GradientType::SWEEP) { 289 return IsSweepGradientValid() && colors_.size() > 1; 290 } 291 return colors_.size() > 1; 292 } 293 SetRepeat(bool repeat)294 void SetRepeat(bool repeat) 295 { 296 repeat_ = repeat; 297 } 298 GetRepeat()299 bool GetRepeat() const 300 { 301 return repeat_; 302 } 303 GetColors()304 const std::vector<GradientColor>& GetColors() const 305 { 306 return colors_; 307 } 308 GetBeginOffset()309 const std::shared_ptr<OffsetF>& GetBeginOffset() const 310 { 311 return beginOffset_; 312 } 313 SetBeginOffset(const OffsetF & beginOffset)314 void SetBeginOffset(const OffsetF& beginOffset) 315 { 316 beginOffset_ = std::make_shared<OffsetF>(beginOffset); 317 } 318 GetEndOffset()319 const std::shared_ptr<OffsetF>& GetEndOffset() const 320 { 321 return endOffset_; 322 } 323 SetEndOffset(const OffsetF & endOffset)324 void SetEndOffset(const OffsetF& endOffset) 325 { 326 endOffset_ = std::make_shared<OffsetF>(endOffset); 327 } 328 GetInnerRadius()329 double GetInnerRadius() const 330 { 331 return innerRadius_; 332 } 333 SetInnerRadius(double innerRadius)334 void SetInnerRadius(double innerRadius) 335 { 336 innerRadius_ = innerRadius; 337 } 338 GetOuterRadius()339 double GetOuterRadius() const 340 { 341 return outerRadius_; 342 } 343 SetOuterRadius(double outerRadius)344 void SetOuterRadius(double outerRadius) 345 { 346 outerRadius_ = outerRadius; 347 } 348 GetType()349 GradientType GetType() const 350 { 351 return type_; 352 } 353 CreateGradientWithType(GradientType type)354 void CreateGradientWithType(GradientType type) 355 { 356 type_ = type; 357 switch (type_) { 358 case GradientType::LINEAR: 359 linearGradient_ = std::make_shared<LinearGradient>(); 360 break; 361 case GradientType::RADIAL: 362 radialGradient_ = std::make_shared<RadialGradient>(); 363 break; 364 case GradientType::SWEEP: 365 sweepGradient_ = std::make_shared<SweepGradient>(); 366 break; 367 default: 368 LOGE("GradientType not supported"); 369 } 370 } 371 ToString()372 std::string ToString() const 373 { 374 return std::string("Gradient (") 375 .append(beginOffset_->ToString()) 376 .append(",") 377 .append(std::to_string(innerRadius_)) 378 .append(" --- ") 379 .append(endOffset_->ToString()) 380 .append(",") 381 .append(std::to_string(outerRadius_)) 382 .append(")"); 383 } 384 GetSweepGradient()385 std::shared_ptr<SweepGradient> GetSweepGradient() 386 { 387 return sweepGradient_; 388 } 389 GetSweepGradient()390 const std::shared_ptr<SweepGradient> GetSweepGradient() const 391 { 392 return sweepGradient_; 393 } 394 SetSweepGradient(const SweepGradient & sweepGradient)395 void SetSweepGradient(const SweepGradient& sweepGradient) 396 { 397 sweepGradient_ = std::make_shared<SweepGradient>(sweepGradient); 398 } 399 GetRadialGradient()400 std::shared_ptr<RadialGradient>& GetRadialGradient() 401 { 402 return radialGradient_; 403 } 404 GetRadialGradient()405 const std::shared_ptr<RadialGradient>& GetRadialGradient() const 406 { 407 return radialGradient_; 408 } 409 SetRadialGradient(const RadialGradient & radialGradient)410 void SetRadialGradient(const RadialGradient& radialGradient) 411 { 412 radialGradient_ = std::make_shared<RadialGradient>(radialGradient); 413 } 414 GetLinearGradient()415 std::shared_ptr<LinearGradient>& GetLinearGradient() 416 { 417 return linearGradient_; 418 } 419 GetLinearGradient()420 const std::shared_ptr<LinearGradient>& GetLinearGradient() const 421 { 422 return linearGradient_; 423 } 424 SetLinearGradient(const LinearGradient & linearGradient)425 void SetLinearGradient(const LinearGradient& linearGradient) 426 { 427 linearGradient_ = std::make_shared<LinearGradient>(linearGradient); 428 } 429 SetDirection(const GradientDirection & direction)430 void SetDirection(const GradientDirection& direction) 431 { 432 if (LinearGradient::IsXAxis(direction)) { 433 linearGradient_->linearX = direction; 434 } else { 435 linearGradient_->linearY = direction; 436 } 437 } 438 SetSpreadMethod(SpreadMethod spreadMethod)439 void SetSpreadMethod(SpreadMethod spreadMethod) 440 { 441 spreadMethod_ = spreadMethod; 442 } 443 SetGradientTransform(const std::string & gradientTransform)444 void SetGradientTransform(const std::string& gradientTransform) 445 { 446 gradientTransform_ = gradientTransform; 447 } 448 GetSpreadMethod()449 SpreadMethod GetSpreadMethod() const 450 { 451 return spreadMethod_; 452 } 453 GetGradientTransform()454 const std::string& GetGradientTransform() const 455 { 456 return gradientTransform_; 457 } 458 GetRadialGradientInfo()459 const std::shared_ptr<RadialGradientInfo>& GetRadialGradientInfo() const 460 { 461 return radialGradientInfo_; 462 } 463 SetRadialGradientInfo(const RadialGradientInfo & radialGradientInfo)464 void SetRadialGradientInfo(const RadialGradientInfo& radialGradientInfo) 465 { 466 radialGradientInfo_ = std::make_shared<RadialGradientInfo>(radialGradientInfo); 467 } 468 GetLinearGradientInfo()469 const std::shared_ptr<LinearGradientInfo> GetLinearGradientInfo() const 470 { 471 return linearGradientInfo_; 472 } 473 SetLinearGradientInfo(const LinearGradientInfo & linearGradientInfo)474 void SetLinearGradientInfo(const LinearGradientInfo& linearGradientInfo) 475 { 476 linearGradientInfo_ = std::make_shared<LinearGradientInfo>(linearGradientInfo); 477 } 478 479 bool operator==(const Gradient& other) const 480 { 481 return (type_ == other.GetType() && repeat_ == other.GetRepeat() && colors_ == other.GetColors() && 482 radialGradient_ == other.GetRadialGradient() && linearGradient_ == other.GetLinearGradient() && 483 sweepGradient_ == other.GetSweepGradient() && beginOffset_ == other.GetBeginOffset() && 484 endOffset_ == other.GetEndOffset() && spreadMethod_ == other.GetSpreadMethod() && 485 gradientTransform_ == other.GetGradientTransform() && 486 linearGradientInfo_ == other.GetLinearGradientInfo() && 487 radialGradientInfo_ == other.GetRadialGradientInfo()); 488 } 489 490 bool operator!=(const Gradient& other) const 491 { 492 return !(*this == other); 493 } 494 495 std::unique_ptr<JsonValue> LinearGradientToJson() const; 496 std::unique_ptr<JsonValue> SweepGradientToJson() const; 497 std::unique_ptr<JsonValue> RadialGradientToJson() const; 498 499 private: 500 GradientType type_ = GradientType::LINEAR; 501 bool repeat_ = false; 502 std::vector<GradientColor> colors_; 503 // for RadialGradient 504 std::shared_ptr<RadialGradient> radialGradient_; 505 // for LinearGradient 506 std::shared_ptr<LinearGradient> linearGradient_; 507 // for SweepGradient 508 std::shared_ptr<SweepGradient> sweepGradient_; 509 // used for CanvasLinearGradient 510 std::shared_ptr<OffsetF> beginOffset_; 511 std::shared_ptr<OffsetF> endOffset_; 512 // used for CanvasRadialGradient 513 float innerRadius_ = 0.0f; 514 float outerRadius_ = 0.0; 515 SpreadMethod spreadMethod_ = SpreadMethod::PAD; 516 std::string gradientTransform_; 517 std::shared_ptr<LinearGradientInfo> linearGradientInfo_; 518 std::shared_ptr<RadialGradientInfo> radialGradientInfo_; 519 }; 520 521 522 class LinearGradientBlurPara final { 523 public: 524 Dimension blurRadius_; 525 std::vector<std::pair<float, float>> fractionStops_; 526 GradientDirection direction_; 527 LinearGradientBlurPara(const Dimension blurRadius,const std::vector<std::pair<float,float>> fractionStops,const GradientDirection direction)528 LinearGradientBlurPara(const Dimension blurRadius, 529 const std::vector<std::pair<float, float>>fractionStops, const GradientDirection direction) 530 : blurRadius_(blurRadius), fractionStops_(fractionStops), direction_(direction) {} 531 bool operator==(const LinearGradientBlurPara& other) const 532 { 533 return NearEqual(blurRadius_, other.blurRadius_) && NearEqual(fractionStops_, other.fractionStops_) && 534 NearEqual(direction_, other.direction_); 535 } 536 537 ~LinearGradientBlurPara() = default; 538 }; 539 540 class MagnifierParams final { 541 public: 542 float factor_ = 0.f; 543 float width_ = 0.f; 544 float height_ = 0.f; 545 float borderWidth_ = 0.f; 546 float cornerRadius_ = 0.f; 547 float offsetX_ = 0.f; 548 float offsetY_ = 0.f; 549 550 float shadowOffsetX_ = 0.f; 551 float shadowOffsetY_ = 0.f; 552 float shadowSize_ = 0.f; 553 float shadowStrength_ = 0.f; 554 555 // rgba 556 uint32_t gradientMaskColor1_ = 0x00000000; 557 uint32_t gradientMaskColor2_ = 0x00000000; 558 uint32_t outerContourColor1_ = 0x00000000; 559 uint32_t outerContourColor2_ = 0x00000000; 560 561 bool operator==(const MagnifierParams& other) const 562 { 563 return NearEqual(factor_, other.factor_) && NearEqual(width_, other.width_) && 564 NearEqual(height_, other.height_) && NearEqual(borderWidth_, other.borderWidth_) && 565 NearEqual(cornerRadius_, other.cornerRadius_) && NearEqual(offsetX_, other.offsetX_) && 566 NearEqual(offsetY_, other.offsetY_) && NearEqual(shadowOffsetX_, other.shadowOffsetX_) && 567 NearEqual(shadowOffsetY_, other.shadowOffsetY_) && NearEqual(shadowSize_, other.shadowSize_) && 568 NearEqual(shadowStrength_, other.shadowStrength_) && 569 NearEqual(gradientMaskColor1_, other.gradientMaskColor1_) && 570 NearEqual(gradientMaskColor2_, other.gradientMaskColor2_) && 571 NearEqual(outerContourColor1_, other.outerContourColor1_) && 572 NearEqual(outerContourColor2_, other.outerContourColor2_); 573 } 574 MagnifierParams() = default; 575 ~MagnifierParams() = default; 576 }; 577 } // namespace OHOS::Ace::NG 578 579 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_GRADIENT_PROPERTY_H