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