• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.. All rights reserved.
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 "paragraph_builder_impl.h"
17 
18 #include <string>
19 
20 #include "common_utils/string_util.h"
21 #include "text_font_utils.h"
22 #include "modules/skparagraph/include/ParagraphStyle.h"
23 #include "modules/skparagraph/include/TextStyle.h"
24 #include "paragraph_impl.h"
25 #include "paragraph_line_fetcher_impl.h"
26 #include "txt/paragraph_style.h"
27 #include "txt/text_bundle_config_parser.h"
28 #include "utils/text_log.h"
29 
30 namespace OHOS {
31 namespace Rosen {
32 namespace SPText {
33 namespace {
DefaultLocale()34 const char* DefaultLocale()
35 {
36     static const char* LOCALE_ZH = "zh-Hans";
37     return LOCALE_ZH;
38 }
39 } // anonymous namespace
40 
ParagraphBuilderImpl(const ParagraphStyle & style,std::shared_ptr<txt::FontCollection> fontCollection)41 ParagraphBuilderImpl::ParagraphBuilderImpl(
42     const ParagraphStyle& style, std::shared_ptr<txt::FontCollection> fontCollection)
43     : baseStyle_(style.ConvertToTextStyle())
44 {
45     threadId_ = pthread_self();
46     builder_ = skt::ParagraphBuilder::make(TextStyleToSkStyle(style), fontCollection->CreateSktFontCollection());
47 }
48 
49 ParagraphBuilderImpl::~ParagraphBuilderImpl() = default;
50 
PushStyle(const TextStyle & style)51 void ParagraphBuilderImpl::PushStyle(const TextStyle& style)
52 {
53     RecordDifferentPthreadCall(__FUNCTION__);
54     builder_->pushStyle(TextStyleToSkStyle(style));
55 }
56 
Pop()57 void ParagraphBuilderImpl::Pop()
58 {
59     RecordDifferentPthreadCall(__FUNCTION__);
60     builder_->pop();
61 }
62 
AddText(const std::u16string & text)63 void ParagraphBuilderImpl::AddText(const std::u16string& text)
64 {
65     RecordDifferentPthreadCall(__FUNCTION__);
66     if (TextBundleConfigParser::GetInstance().IsTargetApiVersion(SINCE_API18_VERSION)) {
67         std::u16string wideText = text;
68         Utf16Utils::HandleIncompleteSurrogatePairs(wideText);
69         builder_->addText(wideText);
70     } else {
71         builder_->addText(text);
72     }
73 }
74 
AddPlaceholder(PlaceholderRun & run)75 void ParagraphBuilderImpl::AddPlaceholder(PlaceholderRun& run)
76 {
77     RecordDifferentPthreadCall(__FUNCTION__);
78     skt::PlaceholderStyle placeholderStyle;
79     placeholderStyle.fHeight = run.height;
80     placeholderStyle.fWidth = run.width;
81     placeholderStyle.fBaseline = static_cast<skt::TextBaseline>(run.baseline);
82     placeholderStyle.fBaselineOffset = run.baselineOffset;
83     placeholderStyle.fAlignment = static_cast<skt::PlaceholderAlignment>(run.alignment);
84 
85     builder_->addPlaceholder(placeholderStyle);
86 }
87 
Build()88 std::unique_ptr<Paragraph> ParagraphBuilderImpl::Build()
89 {
90     RecordDifferentPthreadCall(__FUNCTION__);
91     auto ret = std::make_unique<ParagraphImpl>(builder_->Build(), std::move(paints_));
92     builder_->Reset();
93     return ret;
94 }
95 
BuildLineFetcher()96 std::unique_ptr<ParagraphLineFetcher> ParagraphBuilderImpl::BuildLineFetcher()
97 {
98     if (builder_ == nullptr) {
99         return nullptr;
100     }
101     auto lineFetcher = builder_->buildLineFetcher();
102     if (lineFetcher == nullptr) {
103         return nullptr;
104     }
105     auto fetcherImpl = std::make_unique<ParagraphLineFetcherImpl>(std::move(lineFetcher), std::move(paints_));
106     builder_->Reset();
107     return fetcherImpl;
108 }
109 
AllocPaintID(const PaintRecord & paint)110 skt::ParagraphPainter::PaintID ParagraphBuilderImpl::AllocPaintID(const PaintRecord& paint)
111 {
112     paints_.push_back(paint);
113     return static_cast<int>(paints_.size()) - 1;
114 }
115 
ConvertToSkTextTab(const TextTab & tab)116 skt::TextTabs ConvertToSkTextTab(const TextTab& tab)
117 {
118     return {
119         static_cast<skt::TextAlign>(tab.alignment),
120         tab.location,
121     };
122 }
123 
TextStyleToSKStrutStyle(skt::StrutStyle & strutStyle,const ParagraphStyle & txt)124 void ParagraphBuilderImpl::TextStyleToSKStrutStyle(skt::StrutStyle& strutStyle, const ParagraphStyle& txt)
125 {
126     strutStyle.setFontStyle(TextFontUtils::MakeFontStyle(txt.strutFontWeight, txt.strutFontWidth, txt.strutFontStyle));
127     strutStyle.setFontSize(SkDoubleToScalar(txt.strutFontSize));
128     strutStyle.setHeight(SkDoubleToScalar(txt.strutHeight));
129     strutStyle.setHeightOverride(txt.strutHeightOverride);
130 
131     std::vector<SkString> strutFonts;
132     std::transform(txt.strutFontFamilies.begin(), txt.strutFontFamilies.end(), std::back_inserter(strutFonts),
133         [](const std::string& f) { return SkString(f.c_str()); });
134     strutStyle.setHalfLeading(txt.strutHalfLeading);
135     strutStyle.setFontFamilies(strutFonts);
136     strutStyle.setLeading(txt.strutLeading);
137     strutStyle.setForceStrutHeight(txt.forceStrutHeight);
138     strutStyle.setStrutEnabled(txt.strutEnabled);
139     strutStyle.setWordBreakType(static_cast<skt::WordBreakType>(txt.wordBreakType));
140     strutStyle.setLineBreakStrategy(static_cast<skt::LineBreakStrategy>(txt.breakStrategy));
141 }
142 
TextStyleToSkStyle(const ParagraphStyle & txt)143 skt::ParagraphStyle ParagraphBuilderImpl::TextStyleToSkStyle(const ParagraphStyle& txt)
144 {
145     skt::ParagraphStyle skStyle;
146     skt::TextStyle textStyle;
147 
148     PaintRecord paint;
149     paint.SetColor(textStyle.getColor());
150     if (txt.customSpTextStyle) {
151         textStyle = this->TextStyleToSkStyle(txt.spTextStyle);
152     } else {
153         textStyle.setForegroundPaintID(AllocPaintID(paint));
154         textStyle.setFontStyle(TextFontUtils::MakeFontStyle(txt.fontWeight, txt.fontWidth, txt.fontStyle));
155         textStyle.setFontSize(SkDoubleToScalar(txt.fontSize));
156         textStyle.setHeight(SkDoubleToScalar(txt.height));
157         textStyle.setHeightOverride(txt.heightOverride);
158         textStyle.setFontFamilies({ SkString(txt.fontFamily.c_str()) });
159         textStyle.setLocale(SkString(txt.locale.empty() ? DefaultLocale() : txt.locale.c_str()));
160         textStyle.setTextStyleUid(txt.defaultTextStyleUid);
161         textStyle.setHalfLeading(txt.halfLeading);
162     }
163 
164     skStyle.setTextStyle(textStyle);
165     skStyle.setTextOverflower(txt.textOverflower);
166     skt::StrutStyle strutStyle;
167     TextStyleToSKStrutStyle(strutStyle, txt);
168     skStyle.setStrutStyle(strutStyle);
169 
170     skStyle.setTextAlign(static_cast<skt::TextAlign>(txt.textAlign));
171     skStyle.setTextDirection(static_cast<skt::TextDirection>(txt.textDirection));
172     skStyle.setEllipsisMod(static_cast<skt::EllipsisModal>(txt.ellipsisModal));
173     if (txt.ellipsisModal != EllipsisModal::TAIL) {
174         skStyle.setEllipsis(txt.ellipsis);
175     }
176     skStyle.setMaxLines(txt.maxLines);
177     skStyle.setEllipsis(txt.ellipsis);
178     skStyle.setTextHeightBehavior(static_cast<skt::TextHeightBehavior>(txt.textHeightBehavior));
179     if (!txt.hintingIsOn) {
180         skStyle.turnHintingOff();
181     }
182     skStyle.setReplaceTabCharacters(true);
183     skStyle.setTextSplitRatio(txt.textSplitRatio);
184     skStyle.setTextHeightBehavior(static_cast<skt::TextHeightBehavior>(txt.textHeightBehavior));
185     skStyle.setTextTab(ConvertToSkTextTab(txt.tab));
186     skStyle.setParagraphSpacing(txt.paragraphSpacing);
187     skStyle.setIsEndAddParagraphSpacing(txt.isEndAddParagraphSpacing);
188     skStyle.setTrailingSpaceOptimized(txt.isTrailingSpaceOptimized);
189     skStyle.setEnableAutoSpace(txt.enableAutoSpace);
190     skStyle.setVerticalAlignment(static_cast<skt::TextVerticalAlign>(txt.verticalAlignment));
191 
192     return skStyle;
193 }
194 
TextStyleToSkStyle(const TextStyle & txt)195 skt::TextStyle ParagraphBuilderImpl::TextStyleToSkStyle(const TextStyle& txt)
196 {
197     auto skStyle = ConvertTextStyleToSkStyle(txt);
198     CopyTextStylePaint(txt, skStyle);
199     return skStyle;
200 }
201 
ConvertTextStyleToSkStyle(const TextStyle & txt)202 skt::TextStyle ParagraphBuilderImpl::ConvertTextStyleToSkStyle(const TextStyle& txt)
203 {
204     skt::TextStyle skStyle;
205 
206     skStyle.setColor(txt.color);
207     skStyle.setDecoration(static_cast<skt::TextDecoration>(txt.decoration));
208     skStyle.setDecorationColor(txt.decorationColor);
209     skStyle.setDecorationStyle(static_cast<skt::TextDecorationStyle>(txt.decorationStyle));
210     skStyle.setDecorationThicknessMultiplier(SkDoubleToScalar(txt.decorationThicknessMultiplier));
211     skStyle.setFontStyle(TextFontUtils::MakeFontStyle(txt.fontWeight, txt.fontWidth, txt.fontStyle));
212     skStyle.setTextBaseline(static_cast<skt::TextBaseline>(txt.baseline));
213 
214     std::vector<SkString> fonts;
215     std::transform(txt.fontFamilies.begin(), txt.fontFamilies.end(), std::back_inserter(fonts),
216         [](const std::string& f) { return SkString(f.c_str()); });
217     skStyle.setFontFamilies(fonts);
218 
219     skStyle.setFontSize(SkDoubleToScalar(txt.fontSize));
220     skStyle.setLetterSpacing(SkDoubleToScalar(txt.letterSpacing));
221     skStyle.setWordSpacing(SkDoubleToScalar(txt.wordSpacing));
222     skStyle.setHeight(SkDoubleToScalar(txt.height));
223     skStyle.setHeightOverride(txt.heightOverride);
224     skStyle.setHalfLeading(txt.halfLeading);
225     skStyle.setBaselineShift(txt.baseLineShift);
226 
227     skStyle.setLocale(SkString(txt.locale.empty() ? DefaultLocale() : txt.locale.c_str()));
228     skStyle.setStyleId(txt.styleId);
229     skStyle.setTextStyleUid(txt.textStyleUid);
230     skStyle.setBackgroundRect({ txt.backgroundRect.color, txt.backgroundRect.leftTopRadius,
231         txt.backgroundRect.rightTopRadius, txt.backgroundRect.rightBottomRadius,
232         txt.backgroundRect.leftBottomRadius });
233 
234     skStyle.resetFontFeatures();
235     for (const auto& ff : txt.fontFeatures.GetFontFeatures()) {
236         skStyle.addFontFeature(SkString(ff.first.c_str()), ff.second);
237     }
238 
239     if (!txt.fontVariations.GetAxisValues().empty()) {
240         TextFontUtils::MakeFontArguments(skStyle, txt.fontVariations);
241     }
242 
243     skStyle.resetShadows();
244     for (const TextShadow& txtShadow : txt.textShadows) {
245         skStyle.addShadow(TextFontUtils::MakeTextShadow(txtShadow));
246     }
247 
248     if (txt.isPlaceholder) {
249         skStyle.setPlaceholder();
250     }
251 
252     if (txt.symbol.GetSymbolType() == SymbolType::CUSTOM) {
253         skStyle.setCustomSymbol(true);
254     }
255 
256     skStyle.setTextBadgeType(static_cast<skt::TextBadgeType>(txt.badgeType));
257 
258     return skStyle;
259 }
260 
CopyTextStylePaint(const TextStyle & txt,skia::textlayout::TextStyle & skStyle)261 void ParagraphBuilderImpl::CopyTextStylePaint(const TextStyle& txt, skia::textlayout::TextStyle& skStyle)
262 {
263     if (txt.background.has_value()) {
264         skStyle.setBackgroundPaintID(AllocPaintID(txt.background.value()));
265     }
266     if (txt.foreground.has_value()) {
267         skStyle.setForegroundPaintID(AllocPaintID(txt.foreground.value()));
268     } else {
269         PaintRecord paint;
270         paint.SetColor(txt.color);
271         paint.isSymbolGlyph = txt.isSymbolGlyph;
272         paint.symbol.familyName_ = txt.fontFamilies.empty() ? "" : txt.fontFamilies[0];
273         paint.symbol.SetSymbolColor(txt.symbol.GetSymbolColor());
274         paint.symbol.SetRenderMode(txt.symbol.GetRenderMode());
275         paint.symbol.SetSymbolEffect(txt.symbol.GetEffectStrategy());
276         paint.symbol.SetAnimationMode(txt.symbol.GetAnimationMode());
277         paint.symbol.SetRepeatCount(txt.symbol.GetRepeatCount());
278         paint.symbol.SetAnimationStart(txt.symbol.GetAnimationStart());
279         paint.symbol.SetCommonSubType(txt.symbol.GetCommonSubType());
280         paint.symbol.SetSymbolType(txt.symbol.GetSymbolType());
281         paint.symbol.SetSymbolUid(txt.symbol.GetSymbolUid());
282         paint.symbol.SetSymbolShadow(txt.symbol.GetSymbolShadow());
283         skStyle.setForegroundPaintID(AllocPaintID(paint));
284     }
285 }
286 
RecordDifferentPthreadCall(const char * caller) const287 void ParagraphBuilderImpl::RecordDifferentPthreadCall(const char* caller) const
288 {
289     pthread_t currenetThreadId = pthread_self();
290     if (threadId_ != currenetThreadId) {
291         TEXT_LOGE_LIMIT3_HOUR("New pthread access paragraph builder, old %{public}lu, caller %{public}s",
292             threadId_, caller);
293         threadId_ = currenetThreadId;
294     }
295 }
296 } // namespace SPText
297 } // namespace Rosen
298 } // namespace OHOS
299