• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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/text_adapt_font_sizer.h"
17 
18 namespace OHOS::Ace::NG {
AdaptMaxFontSize(TextStyle & textStyle,const std::u16string & content,const Dimension & stepUnit,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)19 bool TextAdaptFontSizer::AdaptMaxFontSize(TextStyle& textStyle, const std::u16string& content,
20     const Dimension& stepUnit, const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
21 {
22     double maxFontSize = 0.0;
23     double minFontSize = 0.0;
24     GetAdaptMaxMinFontSize(textStyle, maxFontSize, minFontSize, contentConstraint);
25     if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) {
26         // minFontSize or maxFontSize is invalid
27         return CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper, false);
28     }
29     double stepSize = 0.0;
30     GetAdaptFontSizeStep(textStyle, stepSize, stepUnit, contentConstraint);
31     auto maxSize = GetMaxMeasureSize(contentConstraint);
32     GetSuitableSize(maxSize, layoutWrapper);
33     // Use the minFontSize to layout the paragraph. While using the minFontSize, if the paragraph could be layout in 1
34     // line, then increase the font size and try to layout using the maximum available fontsize.
35     textStyle.SetFontSize(Dimension(minFontSize));
36     CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper);
37     if (IsAdaptExceedLimit(maxSize)) {
38         return true;
39     }
40     auto tag = static_cast<int32_t>((maxFontSize - minFontSize) / stepSize);
41     auto length = tag + 1 + (GreatNotEqual(maxFontSize, minFontSize + stepSize * tag) ? 1 : 0);
42     int32_t left = 0;
43     int32_t right = length - 1;
44     float fontSize = 0.0f;
45     while (left <= right) {
46         int32_t mid = left + (right - left) / 2;
47         fontSize = static_cast<float>((mid == length - 1) ? (maxFontSize) : (minFontSize + stepSize * mid));
48         textStyle.SetFontSize(Dimension(fontSize));
49         if (!CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper)) {
50             return false;
51         }
52         if (!IsAdaptExceedLimit(maxSize)) {
53             left = mid + 1;
54         } else {
55             right = mid - 1;
56         }
57     }
58     fontSize = static_cast<float>((left - 1 == length - 1) ? (maxFontSize) : (minFontSize + stepSize * (left - 1)));
59     fontSize = LessNotEqual(fontSize, minFontSize) ? minFontSize : fontSize;
60     fontSize = GreatNotEqual(fontSize, maxFontSize) ? maxFontSize : fontSize;
61     textStyle.SetFontSize(Dimension(fontSize));
62     return CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper);
63 }
64 
AdaptMinFontSize(TextStyle & textStyle,const std::u16string & content,const Dimension & stepUnit,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)65 bool TextAdaptFontSizer::AdaptMinFontSize(TextStyle& textStyle, const std::u16string& content,
66     const Dimension& stepUnit, const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
67 {
68     double maxFontSize = 0.0;
69     double minFontSize = 0.0;
70     GetAdaptMaxMinFontSize(textStyle, maxFontSize, minFontSize, contentConstraint);
71     if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) {
72         return CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper, false);
73     }
74     double stepSize = 0.0;
75     GetAdaptFontSizeStep(textStyle, stepSize, stepUnit, contentConstraint);
76     auto maxSize = GetMaxMeasureSize(contentConstraint);
77     GetSuitableSize(maxSize, layoutWrapper);
78     while (GreatOrEqual(maxFontSize, minFontSize)) {
79         textStyle.SetFontSize(Dimension(maxFontSize));
80         if (!CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper)) {
81             return false;
82         }
83         if (!DidExceedMaxLines(maxSize)) {
84             break;
85         }
86         maxFontSize -= stepSize;
87     }
88     return true;
89 }
90 
GetAdaptMaxMinFontSize(const TextStyle & textStyle,double & maxFontSize,double & minFontSize,const LayoutConstraintF & contentConstraint)91 void TextAdaptFontSizer::GetAdaptMaxMinFontSize(const TextStyle& textStyle, double& maxFontSize, double& minFontSize,
92     const LayoutConstraintF& contentConstraint)
93 {
94     maxFontSize = textStyle.GetAdaptMaxFontSize().ConvertToPxDistribute(
95         textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
96     minFontSize = textStyle.GetAdaptMinFontSize().ConvertToPxDistribute(
97         textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
98 }
99 
GetAdaptFontSizeStep(const TextStyle & textStyle,double & stepSize,const Dimension & stepUnit,const LayoutConstraintF & contentConstraint)100 void TextAdaptFontSizer::GetAdaptFontSizeStep(const TextStyle& textStyle, double& stepSize, const Dimension& stepUnit,
101     const LayoutConstraintF& contentConstraint)
102 {
103     Dimension step = stepUnit;
104     if (GreatNotEqual(textStyle.GetAdaptFontSizeStep().Value(), 0.0)) {
105         step = textStyle.GetAdaptFontSizeStep();
106     }
107     stepSize =
108         step.ConvertToPxDistribute(textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
109 }
110 
GetMaxMeasureSize(const LayoutConstraintF & contentConstraint)111 SizeF TextAdaptFontSizer::GetMaxMeasureSize(const LayoutConstraintF& contentConstraint)
112 {
113     auto maxSize = contentConstraint.selfIdealSize;
114     maxSize.UpdateIllegalSizeWithCheck(contentConstraint.maxSize);
115     return maxSize.ConvertToSizeT();
116 }
117 
DidExceedMaxLines(const SizeF & maxSize)118 bool TextAdaptFontSizer::DidExceedMaxLines(const SizeF& maxSize)
119 {
120     auto paragraph = GetParagraph();
121     CHECK_NULL_RETURN(paragraph, false);
122     bool didExceedMaxLines = paragraph->DidExceedMaxLines();
123     didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph->GetHeight(), maxSize.Height());
124     didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph->GetLongestLine(), maxSize.Width());
125     return didExceedMaxLines;
126 }
127 
IsAdaptExceedLimit(const SizeF & maxSize)128 bool TextAdaptFontSizer::IsAdaptExceedLimit(const SizeF& maxSize)
129 {
130     auto paragraph = GetParagraph();
131     CHECK_NULL_RETURN(paragraph, false);
132     return (paragraph->GetLineCount() > 1) || paragraph->DidExceedMaxLines() ||
133         GreatNotEqual(paragraph->GetLongestLine(), maxSize.Width());
134 }
135 
IsNeedAdaptFontSize(const double & maxFontSize,const double & minFontSize)136 bool TextAdaptFontSizer::IsNeedAdaptFontSize(const double& maxFontSize, const double& minFontSize)
137 {
138     if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) {
139         return false;
140     }
141     return true;
142 }
143 
IsNeedAdaptFontSize(const TextStyle & textStyle,const LayoutConstraintF & contentConstraint)144 bool TextAdaptFontSizer::IsNeedAdaptFontSize(const TextStyle& textStyle, const LayoutConstraintF& contentConstraint)
145 {
146     double maxFontSize = 0.0;
147     double minFontSize = 0.0;
148     GetAdaptMaxMinFontSize(textStyle, maxFontSize, minFontSize, contentConstraint);
149     return IsNeedAdaptFontSize(maxFontSize, minFontSize);
150 }
151 
SetAdaptFontSizeLineHeight(const Dimension & lineHeight,const TextStyle & textStyle)152 void TextAdaptFontSizer::SetAdaptFontSizeLineHeight(const Dimension& lineHeight, const TextStyle& textStyle)
153 {
154     lineHeight_ = lineHeight.ConvertToPxDistribute(
155         textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
156 }
157 
IsAdaptFontSizeExceedLineHeight(const RefPtr<Paragraph> & paragraph)158 bool TextAdaptFontSizer::IsAdaptFontSizeExceedLineHeight(const RefPtr<Paragraph>& paragraph)
159 {
160     if (LessOrEqual(lineHeight_, 0.0)) {
161         return false;
162     }
163     auto lineMetrics = paragraph->GetLineMetrics(0);
164     return GreatNotEqual(lineMetrics.height, lineHeight_);
165 }
166 } // namespace OHOS::Ace::NG
167