• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/components_ng/pattern/rating/rating_modifier.h"
17 
18 #include "base/geometry/ng/offset_t.h"
19 #include "core/components/rating/rating_theme.h"
20 #include "core/components_ng/render/drawing_prop_convertor.h"
21 #include "core/components_ng/render/image_painter.h"
22 
23 namespace OHOS::Ace::NG {
RatingModifier()24 RatingModifier::RatingModifier()
25     : needDraw_(AceType::MakeRefPtr<PropertyBool>(false)),
26       starNum_(AceType::MakeRefPtr<PropertyInt>(0)),
27       touchStar_(AceType::MakeRefPtr<PropertyInt>(0)),
28       drawScore_(AceType::MakeRefPtr<PropertyFloat>(.0f)),
29       stepSize_(AceType::MakeRefPtr<PropertyFloat>(.0f)),
30       contentOffset_(AceType::MakeRefPtr<PropertyOffsetF>(OffsetF())),
31       contentSize_(AceType::MakeRefPtr<PropertySizeF>(SizeF())),
32       boardColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::TRANSPARENT)))
33 {
34     AttachProperty(needDraw_);
35     AttachProperty(starNum_);
36     AttachProperty(touchStar_);
37     AttachProperty(drawScore_);
38     AttachProperty(stepSize_);
39     AttachProperty(contentOffset_);
40     AttachProperty(contentSize_);
41     AttachProperty(boardColor_);
42 }
43 
onDraw(DrawingContext & context)44 void RatingModifier::onDraw(DrawingContext& context)
45 {
46     CHECK_NULL_VOID(foregroundImageCanvas_);
47     CHECK_NULL_VOID(secondaryImageCanvas_);
48     CHECK_NULL_VOID(backgroundImageCanvas_);
49     // step1: check if touch down any stars.
50     PaintBoard(context);
51     PaintStar(context);
52     SetNeedDraw(false);
53 }
54 
PaintBoard(DrawingContext & context)55 void RatingModifier::PaintBoard(DrawingContext& context)
56 {
57     auto pipeline = PipelineBase::GetCurrentContext();
58     CHECK_NULL_VOID(pipeline);
59     auto ratingTheme = pipeline->GetTheme<RatingTheme>();
60     CHECK_NULL_VOID(ratingTheme);
61     // animate color
62     LinearColor bgColor = boardColor_->Get();
63     auto pressBorderRadius = ratingTheme->GetFocusBorderRadius();
64     auto& canvas = context.canvas;
65 
66     auto singleStarImagePaintConfig = foregroundImageCanvas_->GetPaintConfig();
67     const float singleStarWidth = contentSize_->Get().Width() / static_cast<float>(starNum_->Get());
68     const float singleStarHeight = contentSize_->Get().Height();
69     auto offset = contentOffset_->Get();
70     auto touchStar = touchStar_->Get();
71     auto starNum = starNum_->Get();
72     if (touchStar >= 0 && touchStar < starNum) {
73         RSBrush rsBrush(ToRSColor(bgColor));
74         rsBrush.SetAntiAlias(true);
75         const RSRect rsRect(offset.GetX() + singleStarWidth * static_cast<float>(touchStar), offset.GetY(),
76             offset.GetX() + singleStarWidth * static_cast<float>((touchStar + 1)), offset.GetY() + singleStarHeight);
77         const RSRoundRect rsRoundRect(rsRect, static_cast<float>(pressBorderRadius.ConvertToPx()),
78             static_cast<float>(pressBorderRadius.ConvertToPx()));
79         canvas.Save();
80         canvas.ClipRoundRect(rsRoundRect, RSClipOp::INTERSECT);
81         canvas.DrawBackground(rsBrush);
82         canvas.Restore();
83     }
84 }
85 
PaintStar(DrawingContext & context)86 void RatingModifier::PaintStar(DrawingContext& context)
87 {
88     const ImagePainter foregroundImagePainter(foregroundImageCanvas_);
89     const ImagePainter secondaryImagePainter(secondaryImageCanvas_);
90     const ImagePainter backgroundPainter(backgroundImageCanvas_);
91 
92     auto& canvas = context.canvas;
93     auto offset = contentOffset_->Get();
94     auto starNum = starNum_->Get();
95     auto drawScore = drawScore_->Get();
96     auto config = foregroundImageCanvas_->GetPaintConfig();
97     const float singleStarWidth = contentSize_->Get().Width() / static_cast<float>(starNum_->Get());
98     const float singleStarHeight = contentSize_->Get().Height();
99     // step2: calculate 3 images repeat times.
100     const int32_t foregroundImageRepeatNum = ceil(drawScore);
101     const float secondaryImageRepeatNum = foregroundImageRepeatNum - drawScore;
102     const int32_t backgroundImageRepeatNum = starNum - foregroundImageRepeatNum;
103     // step3: draw the foreground images.
104     canvas.Save();
105     auto offsetTemp = offset;
106     auto contentSize = SizeF(singleStarWidth, singleStarHeight);
107     // step2.1: calculate the clip area in order to display the secondary image.
108     auto clipRect1 = RSRect(offset.GetX(), offsetTemp.GetY(),
109         static_cast<float>(offset.GetX() + singleStarWidth * drawScore), offset.GetY() + singleStarHeight);
110     canvas.ClipRect(clipRect1, RSClipOp::INTERSECT);
111     for (int32_t i = 0; i < foregroundImageRepeatNum; i++) {
112         foregroundImagePainter.DrawImage(canvas, offsetTemp, contentSize);
113         offsetTemp.SetX(static_cast<float>(offsetTemp.GetX() + singleStarWidth));
114     }
115     canvas.Restore();
116 
117     // step3: if drawScore is a decimal, it needs to draw the secondary image.
118     if (secondaryImageRepeatNum != 0) {
119         canvas.Save();
120         auto clipRect2 = RSRect(static_cast<float>(offset.GetX() + singleStarWidth * drawScore), offsetTemp.GetY(),
121             static_cast<float>(offset.GetX() + singleStarWidth * static_cast<float>(foregroundImageRepeatNum)),
122             offset.GetY() + singleStarHeight);
123         // step3.1: calculate the clip area which already occupied by the foreground image.
124         canvas.ClipRect(clipRect2, RSClipOp::INTERSECT);
125         offsetTemp.SetX(static_cast<float>(offsetTemp.GetX() - singleStarWidth));
126         secondaryImagePainter.DrawImage(canvas, offsetTemp, contentSize);
127         offsetTemp.SetX(offsetTemp.GetX() + singleStarWidth);
128         canvas.Restore();
129     }
130 
131     // step4: draw background image.
132     for (int32_t i = 0; i < backgroundImageRepeatNum; i++) {
133         backgroundPainter.DrawImage(canvas, offsetTemp, contentSize);
134         if (i < backgroundImageRepeatNum - 1) {
135             offsetTemp.SetX(offsetTemp.GetX() + singleStarWidth);
136         }
137     }
138 }
139 } // namespace OHOS::Ace::NG
140