• 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/text_field/text_field_content_modifier.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components_ng/base/modifier.h"
20 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
21 #include "core/components_ng/property/calc_length.h"
22 #include "core/components_ng/render/drawing.h"
23 #include "core/components_ng/render/drawing_prop_convertor.h"
24 #include "core/components_ng/render/image_painter.h"
25 #include "core/pipeline_ng/pipeline_context.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 const FontWeight FONT_WEIGHT_CONVERT_MAP[] = {
30     FontWeight::W100,
31     FontWeight::W200,
32     FontWeight::W300,
33     FontWeight::W400,
34     FontWeight::W500,
35     FontWeight::W600,
36     FontWeight::W700,
37     FontWeight::W800,
38     FontWeight::W900,
39     FontWeight::W700,
40     FontWeight::W400,
41     FontWeight::W900,
42     FontWeight::W100,
43     FontWeight::W500,
44     FontWeight::W400,
45 };
46 constexpr Dimension ERROR_TEXT_UNDERLINE_MARGIN = 8.0_vp;
47 constexpr Dimension ERROR_TEXT_CAPSULE_MARGIN = 8.0_vp;
48 
ConvertFontWeight(FontWeight fontWeight)49 inline FontWeight ConvertFontWeight(FontWeight fontWeight)
50 {
51     return FONT_WEIGHT_CONVERT_MAP[(int)fontWeight];
52 }
53 } // namespace
54 
TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::Pattern> & pattern)55 TextFieldContentModifier::TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::Pattern>& pattern) : pattern_(pattern)
56 {
57     SetDefaultAnimatablePropertyValue();
58     SetDefaultPropertyValue();
59 }
60 
onDraw(DrawingContext & context)61 void TextFieldContentModifier::onDraw(DrawingContext& context)
62 {
63     auto& canvas = context.canvas;
64     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
65     CHECK_NULL_VOID(textFieldPattern);
66     auto paragraph = textFieldPattern->GetParagraph();
67     CHECK_NULL_VOID(paragraph);
68     auto contentOffset = contentOffset_->Get();
69     auto contentRect = textFieldPattern->GetContentRect();
70     auto clipRectHeight = 0.0f;
71     auto errorMargin = 0.0f;
72     auto errorViewHeight = 0.0f;
73     auto errorParagraph = textFieldPattern->GetErrorParagraph();
74     auto textFrameRect = textFieldPattern->GetFrameRect();
75     auto frameNode = textFieldPattern->GetHost();
76     CHECK_NULL_VOID(frameNode);
77     auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
78     CHECK_NULL_VOID(layoutProperty);
79     if (layoutProperty->GetShowUnderlineValue(false) && showErrorState_->Get()) {
80         errorMargin = ERROR_TEXT_UNDERLINE_MARGIN.ConvertToPx();
81     } else if (textFieldPattern->NeedShowPasswordIcon() && showErrorState_->Get()) {
82         errorMargin = ERROR_TEXT_CAPSULE_MARGIN.ConvertToPx();
83     } else if (showErrorState_->Get()) {
84         errorMargin = ERROR_TEXT_CAPSULE_MARGIN.ConvertToPx();
85     } else {
86         errorMargin = 0;
87     }
88     ProcessErrorParagraph(context, errorMargin);
89     if (errorParagraph && showErrorState_->Get()) {
90         errorViewHeight = textFrameRect.Bottom() - textFrameRect.Top() + errorMargin;
91     }
92     clipRectHeight = contentRect.GetY() + contentRect.Height() + errorViewHeight;
93     canvas.Save();
94     RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
95         contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
96     canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
97     if (paragraph) {
98         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
99             canvas.Save();
100             RSRect clipRect;
101             std::vector<RSPoint> clipRadius;
102             GetFrameRectClip(clipRect, clipRadius);
103             canvas.ClipRoundRect(clipRect, clipRadius, true);
104             paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
105                 textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
106             canvas.Restore();
107         } else {
108             paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
109                 textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
110         }
111     }
112     canvas.Restore();
113 }
114 
GetFrameRectClip(RSRect & clipRect,std::vector<RSPoint> & clipRadius)115 void TextFieldContentModifier::GetFrameRectClip(RSRect& clipRect, std::vector<RSPoint>& clipRadius)
116 {
117     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
118     CHECK_NULL_VOID(textFieldPattern);
119     auto host = textFieldPattern->GetHost();
120     CHECK_NULL_VOID(host);
121     auto renderContext = host->GetRenderContext();
122     CHECK_NULL_VOID(renderContext);
123     auto textFrameRect = textFieldPattern->GetFrameRect();
124     clipRect = RSRect(0.0f, 0.0f, textFrameRect.Width(), textFrameRect.Height());
125     auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
126     auto radiusTopLeft = RSPoint(static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()),
127         static_cast<float>(radius.radiusTopLeft.value_or(0.0_vp).ConvertToPx()));
128     clipRadius.emplace_back(radiusTopLeft);
129     auto radiusTopRight = RSPoint(static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()),
130         static_cast<float>(radius.radiusTopRight.value_or(0.0_vp).ConvertToPx()));
131     clipRadius.emplace_back(radiusTopRight);
132     auto radiusBottomRight = RSPoint(static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()),
133         static_cast<float>(radius.radiusBottomRight.value_or(0.0_vp).ConvertToPx()));
134     clipRadius.emplace_back(radiusBottomRight);
135     auto radiusBottomLeft = RSPoint(static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()),
136         static_cast<float>(radius.radiusBottomLeft.value_or(0.0_vp).ConvertToPx()));
137     clipRadius.emplace_back(radiusBottomLeft);
138 }
139 
SetDefaultAnimatablePropertyValue()140 void TextFieldContentModifier::SetDefaultAnimatablePropertyValue()
141 {
142     RefPtr<TextTheme> theme;
143     RefPtr<TextFieldLayoutProperty> textFieldLayoutProperty;
144     RefPtr<PipelineContext> pipelineContext;
145     auto textPartten = pattern_.Upgrade();
146     CHECK_NULL_VOID(textPartten);
147     auto frameNode = textPartten->GetHost();
148     CHECK_NULL_VOID(frameNode);
149     pipelineContext = frameNode->GetContext();
150     CHECK_NULL_VOID(pipelineContext);
151     theme = pipelineContext->GetTheme<TextTheme>();
152     textFieldLayoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
153     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
154     CHECK_NULL_VOID(textFieldPattern);
155     TextStyle textStyle;
156     if (!textFieldPattern->GetTextValue().empty()) {
157         textStyle = CreateTextStyleUsingTheme(
158             textFieldLayoutProperty->GetFontStyle(), textFieldLayoutProperty->GetTextLineStyle(), theme);
159     } else {
160         textStyle = CreateTextStyleUsingTheme(textFieldLayoutProperty->GetPlaceholderFontStyle(),
161             textFieldLayoutProperty->GetPlaceholderTextLineStyle(), theme);
162     }
163     SetDefaultFontSize(textStyle);
164     SetDefaultFontWeight(textStyle);
165     SetDefaultTextColor(textStyle);
166     SetDefaultFontStyle(textStyle);
167     SetDefaultTextOverflow(textStyle);
168 }
169 
SetDefaultPropertyValue()170 void TextFieldContentModifier::SetDefaultPropertyValue()
171 {
172     RefPtr<TextFieldTheme> theme;
173     RefPtr<PipelineContext> pipelineContext;
174     auto textPattern = pattern_.Upgrade();
175     CHECK_NULL_VOID(textPattern);
176     auto frameNode = textPattern->GetHost();
177     CHECK_NULL_VOID(frameNode);
178     pipelineContext = frameNode->GetContext();
179     CHECK_NULL_VOID(pipelineContext);
180     theme = pipelineContext->GetTheme<TextFieldTheme>();
181     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
182 
183     textObscured_ = AceType::MakeRefPtr<PropertyBool>(textFieldPattern->GetTextObscured());
184     dragStatus_ = AceType::MakeRefPtr<PropertyBool>(false);
185     contentOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(
186         OffsetF(textFieldPattern->GetTextRect().GetX(), textFieldPattern->GetTextRect().GetY()));
187     contentSize_ = AceType::MakeRefPtr<PropertySizeF>(SizeF());
188     textValue_ = AceType::MakeRefPtr<PropertyString>("");
189     errorTextValue_ = AceType::MakeRefPtr<PropertyString>("");
190     placeholderValue_ = AceType::MakeRefPtr<PropertyString>("");
191     textRectY_ = AceType::MakeRefPtr<PropertyFloat>(textFieldPattern->GetTextRect().GetY());
192     textRectX_ = AceType::MakeRefPtr<PropertyFloat>(textFieldPattern->GetTextRect().GetX());
193     textAlign_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(TextAlign::START));
194     showErrorState_ = AceType::MakeRefPtr<PropertyBool>(false);
195     fontFamilyString_ = AceType::MakeRefPtr<PropertyString>("");
196     fontReady_ = AceType::MakeRefPtr<PropertyBool>(false);
197     contentChange_ = AceType::MakeRefPtr<PropertyBool>(false);
198     AttachProperty(contentOffset_);
199     AttachProperty(contentSize_);
200     AttachProperty(textValue_);
201     AttachProperty(errorTextValue_);
202     AttachProperty(placeholderValue_);
203     AttachProperty(textRectY_);
204     AttachProperty(textObscured_);
205     AttachProperty(dragStatus_);
206     AttachProperty(textRectX_);
207     AttachProperty(textAlign_);
208     AttachProperty(showErrorState_);
209     AttachProperty(showUnderline_);
210     AttachProperty(fontFamilyString_);
211     AttachProperty(fontReady_);
212     AttachProperty(contentChange_);
213 }
214 
SetDefaultFontSize(const TextStyle & textStyle)215 void TextFieldContentModifier::SetDefaultFontSize(const TextStyle& textStyle)
216 {
217     float fontSizeValue;
218     auto pipelineContext = PipelineContext::GetCurrentContext();
219     if (pipelineContext) {
220         fontSizeValue = pipelineContext->NormalizeToPx(textStyle.GetFontSize());
221         if (textStyle.IsAllowScale() || textStyle.GetFontSize().Unit() == DimensionUnit::FP) {
222             fontSizeValue = pipelineContext->NormalizeToPx(textStyle.GetFontSize() * pipelineContext->GetFontScale());
223         }
224     } else {
225         fontSizeValue = textStyle.GetFontSize().ConvertToPx();
226     }
227 
228     fontSizeFloat_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(fontSizeValue);
229     AttachProperty(fontSizeFloat_);
230 }
231 
SetDefaultFontWeight(const TextStyle & textStyle)232 void TextFieldContentModifier::SetDefaultFontWeight(const TextStyle& textStyle)
233 {
234     fontWeightFloat_ =
235         AceType::MakeRefPtr<AnimatablePropertyFloat>(static_cast<float>(ConvertFontWeight(textStyle.GetFontWeight())));
236     AttachProperty(fontWeightFloat_);
237 }
238 
SetDefaultTextColor(const TextStyle & textStyle)239 void TextFieldContentModifier::SetDefaultTextColor(const TextStyle& textStyle)
240 {
241     animatableTextColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(textStyle.GetTextColor()));
242     AttachProperty(animatableTextColor_);
243 }
244 
SetDefaultFontStyle(const TextStyle & textStyle)245 void TextFieldContentModifier::SetDefaultFontStyle(const TextStyle& textStyle)
246 {
247     fontStyle_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(textStyle.GetFontStyle()));
248     AttachProperty(fontStyle_);
249 }
250 
SetDefaultTextOverflow(const TextStyle & textStyle)251 void TextFieldContentModifier::SetDefaultTextOverflow(const TextStyle& textStyle)
252 {
253     textOverflow_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int32_t>(textStyle.GetTextOverflow()));
254     AttachProperty(textOverflow_);
255 }
256 
ModifyTextStyle(TextStyle & textStyle)257 void TextFieldContentModifier::ModifyTextStyle(TextStyle& textStyle)
258 {
259     if (fontSize_.has_value() && fontSizeFloat_) {
260         textStyle.SetFontSize(Dimension(fontSizeFloat_->Get(), DimensionUnit::PX));
261     }
262     if (fontWeight_.has_value() && fontWeightFloat_) {
263         textStyle.SetFontWeight(static_cast<FontWeight>(std::floor(fontWeightFloat_->Get() + 0.5f)));
264     }
265     if (textColor_.has_value() && animatableTextColor_) {
266         textStyle.SetTextColor(Color(animatableTextColor_->Get().GetValue()));
267     }
268 }
269 
SetFontFamilies(const std::vector<std::string> & value)270 void TextFieldContentModifier::SetFontFamilies(const std::vector<std::string>& value)
271 {
272     CHECK_NULL_VOID(fontFamilyString_);
273     fontFamilyString_->Set(V2::ConvertFontFamily(value));
274 }
275 
SetFontSize(const Dimension & value)276 void TextFieldContentModifier::SetFontSize(const Dimension& value)
277 {
278     auto valPx = static_cast<float>(value.ConvertToPx());
279     fontSize_ = Dimension(valPx);
280     CHECK_NULL_VOID(fontSizeFloat_);
281     fontSizeFloat_->Set(valPx);
282 }
283 
SetFontWeight(const FontWeight & value)284 void TextFieldContentModifier::SetFontWeight(const FontWeight& value)
285 {
286     fontWeight_ = ConvertFontWeight(value);
287     CHECK_NULL_VOID(fontWeightFloat_);
288     fontWeightFloat_->Set(static_cast<int>(ConvertFontWeight(value)));
289 }
290 
SetTextColor(const Color & value)291 void TextFieldContentModifier::SetTextColor(const Color& value)
292 {
293     textColor_ = value;
294     CHECK_NULL_VOID(animatableTextColor_);
295     animatableTextColor_->Set(LinearColor(value));
296 }
297 
SetTextOverflow(const TextOverflow value)298 void TextFieldContentModifier::SetTextOverflow(const TextOverflow value)
299 {
300     if (textOverflow_->Get() != static_cast<int32_t>(value)) {
301         textOverflow_->Set(static_cast<int32_t>(value));
302     }
303 }
304 
SetFontStyle(const OHOS::Ace::FontStyle & value)305 void TextFieldContentModifier::SetFontStyle(const OHOS::Ace::FontStyle& value)
306 {
307     if (fontStyle_->Get() != static_cast<int32_t>(value)) {
308         fontStyle_->Set(static_cast<int32_t>(value));
309     }
310 }
311 
SetContentOffset(OffsetF & value)312 void TextFieldContentModifier::SetContentOffset(OffsetF& value)
313 {
314     if (contentOffset_) {
315         contentOffset_->Set(value);
316     }
317 }
318 
GetContentOffsetY()319 float TextFieldContentModifier::GetContentOffsetY()
320 {
321     return contentOffset_->Get().GetY();
322 }
323 
SetContentSize(SizeF & value)324 void TextFieldContentModifier::SetContentSize(SizeF& value)
325 {
326     if (contentSize_) {
327         contentSize_->Set(value);
328     }
329 }
330 
SetTextValue(std::string & value)331 void TextFieldContentModifier::SetTextValue(std::string& value)
332 {
333     if (textValue_->Get() != value) {
334         textValue_->Set(value);
335     }
336 }
337 
SetErrorTextValue(const std::string & value)338 void TextFieldContentModifier::SetErrorTextValue(const std::string& value)
339 {
340     if (errorTextValue_->Get() != value) {
341         errorTextValue_->Set(value);
342     }
343 }
344 
SetPlaceholderValue(std::string && value)345 void TextFieldContentModifier::SetPlaceholderValue(std::string&& value)
346 {
347     if (placeholderValue_->Get() != value) {
348         placeholderValue_->Set(value);
349     }
350 }
351 
SetTextRectY(const float value)352 void TextFieldContentModifier::SetTextRectY(const float value)
353 {
354     if (textRectY_->Get() != value) {
355         textRectY_->Set(value);
356     }
357 }
358 
GetTextRectY()359 float TextFieldContentModifier::GetTextRectY()
360 {
361     return textRectY_->Get();
362 }
363 
SetTextObscured(bool value)364 void TextFieldContentModifier::SetTextObscured(bool value)
365 {
366     if (textObscured_) {
367         textObscured_->Set(value);
368     }
369 }
370 
ChangeDragStatus()371 void TextFieldContentModifier::ChangeDragStatus()
372 {
373     dragStatus_->Set(!dragStatus_->Get());
374 }
375 
SetTextRectX(const float value)376 void TextFieldContentModifier::SetTextRectX(const float value)
377 {
378     if (textRectX_->Get() != value) {
379         textRectX_->Set(value);
380     }
381 }
382 
GetTextRectX()383 float TextFieldContentModifier::GetTextRectX()
384 {
385     return textRectX_->Get();
386 }
387 
SetTextAlign(const TextAlign value)388 void TextFieldContentModifier::SetTextAlign(const TextAlign value)
389 {
390     if (textAlign_->Get() != static_cast<int32_t>(value)) {
391         textAlign_->Set(static_cast<int32_t>(value));
392     }
393 }
394 
SetShowErrorState(bool value)395 void TextFieldContentModifier::SetShowErrorState(bool value)
396 {
397     if (showErrorState_) {
398         showErrorState_->Set(value);
399     }
400 }
401 
SetShowUnderlineState(bool value)402 void TextFieldContentModifier::SetShowUnderlineState(bool value)
403 {
404     if (showUnderline_) {
405         showUnderline_->Set(value);
406     }
407 }
408 
SetFontReady(bool value)409 void TextFieldContentModifier::SetFontReady(bool value)
410 {
411     if (fontReady_) {
412         fontReady_->Set(value);
413     }
414 }
415 
ContentChange()416 void TextFieldContentModifier::ContentChange()
417 {
418     CHECK_NULL_VOID(contentChange_);
419     contentChange_->Set(!contentChange_->Get());
420 }
421 
NeedMeasureUpdate(PropertyChangeFlag & flag)422 bool TextFieldContentModifier::NeedMeasureUpdate(PropertyChangeFlag& flag)
423 {
424     flag = 0;
425     if (fontSize_.has_value() && fontSizeFloat_ && !NearEqual(fontSize_.value().Value(), fontSizeFloat_->Get())) {
426         flag |= PROPERTY_UPDATE_MEASURE;
427     }
428     if (fontWeight_.has_value() && fontWeightFloat_ &&
429         !NearEqual(static_cast<float>(fontWeight_.value()), fontWeightFloat_->Get())) {
430         flag |= PROPERTY_UPDATE_MEASURE;
431     }
432     if (textColor_.has_value() && animatableTextColor_ &&
433         textColor_->GetValue() != animatableTextColor_->Get().GetValue()) {
434         flag |= PROPERTY_UPDATE_MEASURE_SELF;
435     }
436     flag &= (PROPERTY_UPDATE_MEASURE | PROPERTY_UPDATE_MEASURE_SELF | PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
437     return flag;
438 }
439 
ProcessErrorParagraph(DrawingContext & context,float errorMargin)440 void TextFieldContentModifier::ProcessErrorParagraph(DrawingContext& context, float errorMargin)
441 {
442     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
443     CHECK_NULL_VOID(textFieldPattern);
444     auto offset = contentOffset_->Get();
445     auto textFrameRect = textFieldPattern->GetFrameRect();
446     auto errorParagraph = textFieldPattern->GetErrorParagraph();
447     auto errorValue = textFieldPattern->GetErrorTextString();
448     auto frameNode = textFieldPattern->GetHost();
449     auto& canvas = context.canvas;
450     if (showErrorState_->Get() && errorParagraph && !textFieldPattern->IsDisabled() && !errorValue.empty()) {
451         auto property = frameNode->GetLayoutProperty();
452         float padding = 0.0f;
453         if (property && property->GetPaddingProperty()) {
454             const auto& paddingProperty = property->GetPaddingProperty();
455             padding = paddingProperty->left.value_or(CalcLength(0.0)).GetDimension().ConvertToPx() +
456                       paddingProperty->right.value_or(CalcLength(0.0)).GetDimension().ConvertToPx();
457         }
458         errorParagraph->Layout(textFrameRect.Width() - padding);
459         errorParagraph->Paint(canvas, offset.GetX(), textFrameRect.Bottom() - textFrameRect.Top() + errorMargin);
460     }
461 }
462 } // namespace OHOS::Ace::NG
463