• 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 #include <cstddef>
16 
17 #include "gtest/gtest.h"
18 #include "font_collection.h"
19 #include "modules/skparagraph/src/ParagraphImpl.h"
20 #include "ohos/init_data.h"
21 #include "paragraph_builder.h"
22 #include "paragraph_impl.h"
23 #include "paragraph_style.h"
24 #include "text_style.h"
25 
26 using namespace testing;
27 using namespace testing::ext;
28 using namespace OHOS::Rosen;
29 using namespace OHOS::Rosen::Drawing;
30 using namespace OHOS::Rosen::SPText;
31 
32 namespace txt {
33 namespace skt = skia::textlayout;
34 class ParagraphTest : public testing::Test {
35 public:
36     void SetUp() override;
37     void TearDown() override;
38 
39     static bool AnimationFunc(const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig);
40     static skia::textlayout::ParagraphImpl* GetParagraphSkiaImpl(const std::shared_ptr<Paragraph>& paragraph);
41     static ParagraphImpl* GetParagraphImpl(const std::shared_ptr<Paragraph>& paragraph);
42     void PrepareMiddleEllipsis(size_t& maxLines, const std::u16string& str, const std::u16string& text);
43 
44 protected:
45     std::shared_ptr<Paragraph> paragraph_;
46     std::shared_ptr<Paragraph> paragraphMiddleEllipsis_;
47     int layoutWidth_ = 50;
48     std::u16string text_ = u"text";
49 };
50 
SetUp()51 void ParagraphTest::SetUp()
52 {
53     SetHwIcuDirectory();
54     ParagraphStyle paragraphStyle;
55     std::shared_ptr<FontCollection> fontCollection = std::make_shared<FontCollection>();
56     ASSERT_NE(fontCollection, nullptr);
57     fontCollection->SetupDefaultFontManager();
58     std::shared_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
59     ASSERT_NE(paragraphBuilder, nullptr);
60     paragraphBuilder->AddText(text_);
61     // 50 just for test
62     PlaceholderRun placeholderRun(50, 50, PlaceholderAlignment::BASELINE, SPText::TextBaseline::ALPHABETIC, 0.0);
63     paragraphBuilder->AddPlaceholder(placeholderRun);
64     paragraph_ = paragraphBuilder->Build();
65     ASSERT_NE(paragraph_, nullptr);
66     // 50 just for test
67     paragraph_->Layout(layoutWidth_);
68     paragraph_->MeasureText();
69 }
70 
TearDown()71 void ParagraphTest::TearDown()
72 {
73     paragraph_.reset();
74 }
75 
GetParagraphImpl(const std::shared_ptr<Paragraph> & paragraph)76 ParagraphImpl* ParagraphTest::GetParagraphImpl(const std::shared_ptr<Paragraph>& paragraph)
77 {
78     return static_cast<ParagraphImpl*>(paragraph.get());
79 }
80 
GetParagraphSkiaImpl(const std::shared_ptr<Paragraph> & paragraph)81 skia::textlayout::ParagraphImpl* ParagraphTest::GetParagraphSkiaImpl(const std::shared_ptr<Paragraph>& paragraph)
82 {
83     return static_cast<skia::textlayout::ParagraphImpl*>(GetParagraphImpl(paragraph)->paragraph_.get());
84 }
85 
AnimationFunc(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)86 bool ParagraphTest::AnimationFunc(const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
87 {
88     return true;
89 }
90 
91 /*
92  * @tc.name: ParagraphTest001
93  * @tc.desc: test for GetMaxWidth
94  * @tc.type: FUNC
95  */
96 HWTEST_F(ParagraphTest, ParagraphTest001, TestSize.Level0)
97 {
98     EXPECT_EQ(paragraph_->GetMaxWidth(), layoutWidth_);
99     EXPECT_EQ(paragraph_->GetHeight(), 19);
100     EXPECT_EQ(static_cast<int>(paragraph_->GetLongestLine()), 44);
101     EXPECT_EQ(static_cast<int>(paragraph_->GetMinIntrinsicWidth()), 78);
102     EXPECT_EQ(static_cast<int>(paragraph_->GetMaxIntrinsicWidth()), 78);
103     EXPECT_EQ(static_cast<int>(paragraph_->GetAlphabeticBaseline()), 14);
104     EXPECT_EQ(static_cast<int>(paragraph_->GetIdeographicBaseline()), 18);
105     EXPECT_EQ(paragraph_->GetGlyphsBoundsTop(), -11);
106     EXPECT_EQ(paragraph_->GetGlyphsBoundsBottom(), 1);
107     EXPECT_EQ(paragraph_->GetGlyphsBoundsLeft(), 0);
108     EXPECT_EQ(static_cast<int>(paragraph_->GetGlyphsBoundsRight()), 36);
109     EXPECT_TRUE(paragraph_->DidExceedMaxLines());
110     EXPECT_EQ(paragraph_->GetLineCount(), 1);
111     EXPECT_EQ(paragraph_->GetUnresolvedGlyphsCount(), 0);
112     EXPECT_EQ(paragraph_->GetRectsForRange(0, text_.size(), RectHeightStyle::MAX, RectWidthStyle::TIGHT).size(), 1);
113     EXPECT_EQ(paragraph_->GetRectsForPlaceholders().size(), 0);
114     EXPECT_EQ(paragraph_->GetGlyphPositionAtCoordinate(0.0, 0.0).affinity, OHOS::Rosen::SPText::Affinity::DOWNSTREAM);
115     EXPECT_EQ(paragraph_->GetGlyphPositionAtCoordinate(0.0, 0.0).position, 0.0);
116     EXPECT_EQ(paragraph_->GetWordBoundary(0).start, 0);
117     EXPECT_EQ(paragraph_->GetActualTextRange(0, false).start, 0);
118     EXPECT_EQ(paragraph_->GetActualTextRange(-1, false).start, 0);
119     EXPECT_EQ(paragraph_->GetActualTextRange(paragraph_->GetLineCount(), false).start, 0);
120     EXPECT_EQ(paragraph_->GetActualTextRange(paragraph_->GetLineCount(), false).end, 0);
121     EXPECT_EQ(paragraph_->GetLineMetrics().size(), 1);
122     EXPECT_EQ(static_cast<int>(paragraph_->GetLongestLineWithIndent()), 44);
123 }
124 
125 /*
126  * @tc.name: ParagraphTest002
127  * @tc.desc: test for SetIndents
128  * @tc.type: FUNC
129  */
130 HWTEST_F(ParagraphTest, ParagraphTest002, TestSize.Level0)
131 {
132     // 0.5 just for test
133     std::vector<float> indents = { 0.5, 1 };
134     paragraph_->SetIndents(indents);
135     EXPECT_EQ(paragraph_->DetectIndents(0), 0.5);
136     EXPECT_EQ(paragraph_->DetectIndents(indents.size()), 1);
137 }
138 
139 /*
140  * @tc.name: ParagraphTest003
141  * @tc.desc: test for MarkDirty
142  * @tc.type: FUNC
143  */
144 HWTEST_F(ParagraphTest, ParagraphTest003, TestSize.Level0)
145 {
146     paragraph_->MarkDirty();
147     auto paragraphImpl = GetParagraphSkiaImpl(paragraph_);
148     EXPECT_EQ(paragraphImpl->fState, skia::textlayout::kIndexed);
149 }
150 
151 /*
152  * @tc.name: ParagraphTest004
153  * @tc.desc: test for UpdateFontSize
154  * @tc.type: FUNC
155  */
156 HWTEST_F(ParagraphTest, ParagraphTest004, TestSize.Level0)
157 {
158     // 2 24.0 just for test
159     paragraph_->UpdateFontSize(0, text_.size(), 24.0);
160     auto paragraphImpl = GetParagraphSkiaImpl(paragraph_);
161     ASSERT_GT(paragraphImpl->fTextStyles.size(), 0);
162     EXPECT_EQ(paragraphImpl->fTextStyles.at(0).fStyle.getFontSize(), 24);
163 }
164 
165 /*
166  * @tc.name: ParagraphTest005
167  * @tc.desc: test for Paint
168  * @tc.type: FUNC
169  */
170 HWTEST_F(ParagraphTest, ParagraphTest005, TestSize.Level0)
171 {
172     SkCanvas skCanvas;
173     // redundancy because it has been checked in setup
174     ASSERT_NE(paragraph_, nullptr);
175     paragraph_->Paint(&skCanvas, 0.0, 0.0);
176     Canvas canvas;
177     paragraph_->Paint(&canvas, 0.0, 0.0);
178     Path path;
179     paragraph_->Paint(&canvas, &path, 0.0, 0.0);
180 }
181 
182 /*
183  * @tc.name: ParagraphTest006
184  * @tc.desc: test for GetLineMetricsAt
185  * @tc.type: FUNC
186  */
187 HWTEST_F(ParagraphTest, ParagraphTest006, TestSize.Level0)
188 {
189     skia::textlayout::LineMetrics lineMetrics;
190     auto metrics = paragraph_->MeasureText();
191     ASSERT_TRUE(paragraph_->GetLineMetricsAt(0, &lineMetrics));
192     EXPECT_EQ(lineMetrics.fAscent, -metrics.fAscent);
193     EXPECT_EQ(lineMetrics.fDescent, metrics.fDescent);
194 }
195 
196 /*
197  * @tc.name: ParagraphTest007
198  * @tc.desc: test for SetAnimation
199  * @tc.type: FUNC
200  */
201 HWTEST_F(ParagraphTest, ParagraphTest007, TestSize.Level0)
202 {
203     std::function<bool(const std::shared_ptr<TextEngine::SymbolAnimationConfig>&)> animationFunc =
204         ParagraphTest::AnimationFunc;
205     paragraph_->SetAnimation(animationFunc);
206     auto paragraphImpl = GetParagraphImpl(paragraph_);
207     EXPECT_TRUE(paragraphImpl->animationFunc_(nullptr));
208 }
209 
210 /*
211  * @tc.name: ParagraphTest008
212  * @tc.desc: test for SetParagraghId
213  * @tc.type: FUNC
214  */
215 HWTEST_F(ParagraphTest, ParagraphTest008, TestSize.Level0)
216 {
217     paragraph_->SetParagraghId(1);
218     auto paragraphImpl = GetParagraphImpl(paragraph_);
219     EXPECT_EQ(paragraphImpl->id_, 1);
220 }
221 
222 /*
223  * @tc.name: ParagraphTest009
224  * @tc.desc: test for GetFontMetricsResult
225  * @tc.type: FUNC
226  */
227 HWTEST_F(ParagraphTest, ParagraphTest009, TestSize.Level0)
228 {
229     SPText::TextStyle textStyle;
230     auto fontMetrics = paragraph_->GetFontMetricsResult(textStyle);
231     EXPECT_EQ(static_cast<int>(fontMetrics.fTop), -14);
232 }
233 
234 /*
235  * @tc.name: ParagraphTest010
236  * @tc.desc: test for GetLineFontMetrics
237  * @tc.type: FUNC
238  */
239 HWTEST_F(ParagraphTest, ParagraphTest010, TestSize.Level0)
240 {
241     size_t charNumber = 1;
242     std::vector<Drawing::FontMetrics> fontMetrics;
243     ASSERT_TRUE(paragraph_->GetLineFontMetrics(1, charNumber, fontMetrics));
244     ASSERT_GT(fontMetrics.size(), 0);
245     auto metrics = paragraph_->MeasureText();
246     EXPECT_EQ(metrics.fAscent, fontMetrics.at(0).fAscent);
247     EXPECT_EQ(metrics.fDescent, fontMetrics.at(0).fDescent);
248 }
249 
250 /*
251  * @tc.name: ParagraphTest011
252  * @tc.desc: test for CloneSelf
253  * @tc.type: FUNC
254  */
255 HWTEST_F(ParagraphTest, ParagraphTest011, TestSize.Level0)
256 {
257     auto paragraphClone = paragraph_->CloneSelf();
258     EXPECT_EQ(paragraphClone->GetHeight(), paragraph_->GetHeight());
259     EXPECT_EQ(paragraphClone->GetMaxWidth(), paragraph_->GetMaxWidth());
260     EXPECT_EQ(paragraphClone->GetMinIntrinsicWidth(), paragraph_->GetMinIntrinsicWidth());
261     EXPECT_EQ(paragraphClone->GetGlyphsBoundsBottom(), paragraph_->GetGlyphsBoundsBottom());
262     EXPECT_EQ(paragraphClone->GetGlyphsBoundsLeft(), paragraph_->GetGlyphsBoundsLeft());
263     EXPECT_EQ(paragraphClone->GetLongestLine(), paragraph_->GetLongestLine());
264     EXPECT_EQ(paragraphClone->GetLongestLineWithIndent(), paragraph_->GetLongestLineWithIndent());
265 }
266 
267 /*
268  * @tc.name: ParagraphTest012
269  * @tc.desc: test for SkStyleToTextStyle
270  * @tc.type: FUNC
271  */
272 HWTEST_F(ParagraphTest, ParagraphTest012, TestSize.Level0)
273 {
274     skt::TextStyle skStyle;
275     skStyle.setBackgroundPaintID(-1);
276     skStyle.addShadow(skia::textlayout::TextShadow());
277     skStyle.setColor(0xFF0000FF);           // used for testing. Set the color to blue.
278     skStyle.setDecorationColor(0xFF000000); // used for testing. Set the color to black.
279     skStyle.setDecorationThicknessMultiplier(2.0f);
280     skStyle.setFontFamilies({ SkString("sans-serif") });
281     skStyle.setFontSize(12.0f);
282     skStyle.setHeight(1.5f);
283     SPText::TextStyle txt = paragraph_->SkStyleToTextStyle(skStyle);
284     EXPECT_EQ(txt.color, skStyle.getColor());
285     EXPECT_EQ(txt.decorationColor, skStyle.fDecoration.fColor);
286     EXPECT_EQ(txt.decorationThicknessMultiplier, skStyle.fDecoration.fThicknessMultiplier);
287     EXPECT_EQ(txt.fontSize, skStyle.getFontSize());
288     EXPECT_EQ(txt.height, skStyle.getHeight());
289     ASSERT_GT(txt.fontFamilies.size(), 0);
290     EXPECT_EQ(txt.fontFamilies.back(), std::string(skStyle.fFontFamilies.back().c_str()));
291 }
292 
293 /*
294  * @tc.name: ParagraphTest013
295  * @tc.desc: test for UpdateColor
296  * @tc.type: FUNC
297  */
298 HWTEST_F(ParagraphTest, ParagraphTest013, TestSize.Level0)
299 {
300     RSColor color(255, 0, 0, 255);
301     std::u16string text = u"text";
302     paragraph_->UpdateColor(0, text.length(), color);
303     auto paragraphImpl = GetParagraphImpl(paragraph_);
304     for (auto p: paragraphImpl->paints_) {
305         EXPECT_EQ(p.color, color);
306     }
307 }
308 
309 /*
310  * @tc.name: ParagraphTest014
311  * @tc.desc: test for SkStyleToTextStyle
312  * @tc.type: FUNC
313  */
314 HWTEST_F(ParagraphTest, ParagraphTest014, TestSize.Level0)
315 {
316     auto metrics = paragraph_->GetLineMetrics();
317     for (auto skLineMetrics : metrics) {
318         for (const auto& [index, styleMetrics] : skLineMetrics.fLineMetrics) {
319             OHOS::Rosen::SPText::TextStyle spTextStyle = paragraph_->SkStyleToTextStyle(*styleMetrics.text_style);
320             EXPECT_EQ(spTextStyle.color, styleMetrics.text_style->fColor);
321             EXPECT_EQ(spTextStyle.decorationColor, styleMetrics.text_style->fDecoration.fColor);
322         }
323     }
324 }
325 
326 /*
327  * @tc.name: ParagraphHyphenTest001
328  * @tc.desc: test for text break work with hyphen strategy in en-gb env.
329  * @tc.type: FUNC
330  */
331 HWTEST_F(ParagraphTest, ParagraphHyphenTest001, TestSize.Level0)
332 {
333     OHOS::Rosen::SPText::TextStyle style;
334     style.fontSize = 50;
335     ParagraphStyle paragraphStyle;
336     paragraphStyle.maxLines = 10;
337     paragraphStyle.locale = "en-gb";
338     paragraphStyle.wordBreakType = OHOS::Rosen::SPText::WordBreakType::BREAK_HYPHEN;
339     std::shared_ptr<FontCollection> fontCollection = std::make_shared<FontCollection>();
340     ASSERT_NE(fontCollection, nullptr);
341     fontCollection->SetupDefaultFontManager();
342     std::shared_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
343     ASSERT_NE(paragraphBuilder, nullptr);
344     std::u16string text = u"British English is the official language of the United Kingdom. It has some differences in "
345                           u"spelling, pronunciation, and vocabulary compared to American English.";
346     paragraphBuilder->PushStyle(style);
347     paragraphBuilder->AddText(text);
348     std::shared_ptr<Paragraph> paragraph = paragraphBuilder->Build();
349     ASSERT_NE(paragraph, nullptr);
350     paragraph->Layout(687);
351     std::vector<std::unique_ptr<SPText::TextLineBase>> textLines = paragraph->GetTextLines();
352     ASSERT_EQ(textLines.size(), 6);
353     //expect lines 2,3,4 to have hyphenation breakpoints,
354     //and the last charater of each line to have a hyphen glyphid of 800
355     size_t breakArr[3] = {2, 3, 4};
356     for (std::size_t i = 0; i < 3; i++) {
357         ASSERT_NE(textLines.at(breakArr[i]), nullptr);
358         std::vector<std::unique_ptr<SPText::Run>> runs = textLines.at(breakArr[i])->GetGlyphRuns();
359         ASSERT_NE(runs.back(), nullptr);
360         std::vector<uint16_t> glyphs = runs.back()->GetGlyphs();
361         EXPECT_EQ(glyphs.back(), 800);
362     }
363 }
364 
365 /*
366  * @tc.name: ParagraphHyphenTest002
367  * @tc.desc: test for text break work with hyphen strategy in en-gb env, and text word ends with special chars.
368  * @tc.type: FUNC
369  */
370 HWTEST_F(ParagraphTest, ParagraphHyphenTest002, TestSize.Level0)
371 {
372     ParagraphStyle paragraphStyle;
373     paragraphStyle.maxLines = 10;
374     paragraphStyle.fontSize = 72;
375     paragraphStyle.locale = "en-gb";
376     paragraphStyle.breakStrategy = OHOS::Rosen::SPText::BreakStrategy::HIGH_QUALITY;
377     paragraphStyle.wordBreakType = OHOS::Rosen::SPText::WordBreakType::BREAK_HYPHEN;
378     std::shared_ptr<FontCollection> fontCollection = std::make_shared<FontCollection>();
379     ASSERT_NE(fontCollection, nullptr);
380     fontCollection->SetupDefaultFontManager();
381     std::shared_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
382     ASSERT_NE(paragraphBuilder, nullptr);
383     std::u16string text = u"Special character =========== Special character a---------- Special character ab,,,,,,,,,,";
384     paragraphBuilder->AddText(text);
385     std::shared_ptr<Paragraph> paragraph = paragraphBuilder->Build();
386     ASSERT_NE(paragraph, nullptr);
387     paragraph->Layout(560);
388     std::vector<std::unique_ptr<SPText::TextLineBase>> textLines = paragraph->GetTextLines();
389     EXPECT_EQ(textLines.size(), 7);
390     //expect lines 0,2,4 to have hyphenation breakpoints,
391     //and the last charater of each line to have a hyphen glyphid of 800
392     size_t breakArr[3] = {0, 2, 4};
393     for (size_t i = 0; i < 3; i++) {
394         ASSERT_NE(textLines.at(breakArr[i]), nullptr);
395         std::vector<std::unique_ptr<SPText::Run>> runs = textLines.at(breakArr[i])->GetGlyphRuns();
396         ASSERT_NE(runs.back(), nullptr);
397         std::vector<uint16_t> glyphs = runs.back()->GetGlyphs();
398         EXPECT_EQ(glyphs.back(), 800);
399     }
400 }
401 
402 /*
403  * @tc.name: ParagraphTest016
404  * @tc.desc: test for combin follow liga
405  * @tc.type: FUNC
406  */
407 HWTEST_F(ParagraphTest, ParagraphTest016, TestSize.Level0)
408 {
409     OHOS::Rosen::SPText::TextStyle style;
410     style.fontSize = 30;
411     ParagraphStyle paragraphStyle;
412     paragraphStyle.spTextStyle = style;
413     std::shared_ptr<FontCollection> fontCollection = std::make_shared<FontCollection>();
414     ASSERT_NE(fontCollection, nullptr);
415     fontCollection->SetupDefaultFontManager();
416     std::shared_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
417     ASSERT_NE(paragraphBuilder, nullptr);
418     std::u16string text = u"brt゙゙";
419     paragraphBuilder->PushStyle(style);
420     paragraphBuilder->AddText(text);
421     std::shared_ptr<Paragraph> paragraph = paragraphBuilder->Build();
422     ASSERT_NE(paragraph, nullptr);
423     paragraph->Layout(100);
424     std::vector<std::unique_ptr<SPText::TextLineBase>> textLines = paragraph->GetTextLines();
425     ASSERT_EQ(textLines.size(), 1);
426     std::unique_ptr<SPText::TextLineBase>& textLine = textLines.at(0);
427     std::vector<std::unique_ptr<SPText::Run>> runs = textLine->GetGlyphRuns();
428     ASSERT_EQ(runs.size(), 2);
429     // 'a' will hit HM Sans
430     std::vector<uint16_t> glyphs1 = runs.at(0)->GetGlyphs();
431     ASSERT_EQ(glyphs1.size(), 1);
432     EXPECT_EQ(glyphs1.at(0), 217);
433     // 'rt゙゙' will hit cjk
434     std::vector<uint16_t> glyphs2 = runs.at(1)->GetGlyphs();
435     ASSERT_EQ(glyphs2.size(), 4);
436     EXPECT_EQ(glyphs2.at(0), 83);
437     EXPECT_EQ(glyphs2.at(1), 85);
438     EXPECT_EQ(glyphs2.at(2), 1546);
439     EXPECT_EQ(glyphs2.at(3), 1546);
440 }
441 
PrepareMiddleEllipsis(size_t & maxLines,const std::u16string & str,const std::u16string & text)442 void ParagraphTest::PrepareMiddleEllipsis(size_t& maxLines, const std::u16string& str, const std::u16string& text)
443 {
444     ParagraphStyle paragraphStyle;
445     paragraphStyle.maxLines = maxLines;
446     paragraphStyle.ellipsis = str;
447     paragraphStyle.ellipsisModal = OHOS::Rosen::SPText::EllipsisModal::MIDDLE;
448     std::shared_ptr<FontCollection> fontCollection = std::make_shared<FontCollection>();
449     ASSERT_NE(fontCollection, nullptr);
450     fontCollection->SetupDefaultFontManager();
451     std::shared_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
452     ASSERT_NE(paragraphBuilder, nullptr);
453     OHOS::Rosen::SPText::TextStyle style;
454     style.fontSize = 30; // 30 default fontsize
455     paragraphBuilder->PushStyle(style);
456     paragraphBuilder->AddText(text);
457     paragraphMiddleEllipsis_ = paragraphBuilder->Build();
458     ASSERT_NE(paragraphMiddleEllipsis_, nullptr);
459 }
460 
461 /*
462  * @tc.name: ParagraphTestMiddleEllipsis001
463  * @tc.desc: test for Middle Ellipsis 001, English word
464  * @tc.type: FUNC
465  */
466 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis001, TestSize.Level0)
467 {
468     size_t maxLines = 1;
469     PrepareMiddleEllipsis(maxLines, u"...", u"Hello World");
470     paragraphMiddleEllipsis_->Layout(100);
471     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
472     EXPECT_EQ(range.start, 2);
473     EXPECT_EQ(range.end, 8);
474     EXPECT_FALSE(paragraphMiddleEllipsis_->CanPaintAllText());
475     paragraphMiddleEllipsis_->Layout(500);
476 
477     OHOS::Rosen::SPText::ParagraphImpl* paragraphImpl = GetParagraphImpl(paragraphMiddleEllipsis_);
478     ASSERT_NE(paragraphImpl, nullptr);
479     std::unique_ptr<skt::Paragraph> temp = nullptr;
480     paragraphImpl->paragraph_.swap(temp);
481     EXPECT_FALSE(paragraphImpl->CanPaintAllText());
482     paragraphImpl->paragraph_.swap(temp);
483     EXPECT_TRUE(paragraphMiddleEllipsis_->CanPaintAllText());
484 }
485 
486 /*
487  * @tc.name: ParagraphTestMiddleEllipsis002
488  * @tc.desc: test for Middle Ellipsis 002,Burmese combin
489  * @tc.type: FUNC
490  */
491 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis002, TestSize.Level0)
492 {
493     size_t maxLines = 1;
494     PrepareMiddleEllipsis(maxLines, u"...", u"ျမင့္ေသာ ႏွလုံးခုန္ႏႈန္း သတ္မွတ္ခ်က္");
495     paragraphMiddleEllipsis_->Layout(200);
496     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
497     EXPECT_EQ(range.start, 5);
498     EXPECT_EQ(range.end, 30);
499 }
500 
501 /*
502  * @tc.name: ParagraphTestMiddleEllipsis003
503  * @tc.desc: test for Middle Ellipsis 003,emoji
504  * @tc.type: FUNC
505  */
506 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis003, TestSize.Level0)
507 {
508     size_t maxLines = 1;
509     PrepareMiddleEllipsis(maxLines, u"...", u"���� MM abc 中文 123");
510     paragraphMiddleEllipsis_->Layout(200);
511     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
512     EXPECT_EQ(range.start, 5);
513     EXPECT_EQ(range.end, 13);
514 }
515 
516 /*
517  * @tc.name: ParagraphTestMiddleEllipsis004
518  * @tc.desc: test for Middle Ellipsis 004,chinese & number & English
519  * @tc.type: FUNC
520  */
521 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis004, TestSize.Level0)
522 {
523     size_t maxLines = 1;
524     PrepareMiddleEllipsis(maxLines, u"...", u"你好       123    Hello ");
525     paragraphMiddleEllipsis_->Layout(200);
526     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
527     EXPECT_EQ(range.start, 5);
528     EXPECT_EQ(range.end, 15);
529 }
530 
531 /*
532  * @tc.name: ParagraphTestMiddleEllipsis005
533  * @tc.desc: test for Middle Ellipsis 005,Tibetan
534  * @tc.type: FUNC
535  */
536 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis005, TestSize.Level0)
537 {
538     size_t maxLines = 1;
539     PrepareMiddleEllipsis(maxLines, u"...", u"བོད་སྐད་ནི་སྒྲ་གཉིས་ཀྱི་བྱུས་དང་སྤྱི་ཚད་ཁུར་སྒྲ་སེམས་བཞིན་ཡོད།");
540     paragraphMiddleEllipsis_->Layout(200);
541     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
542     EXPECT_EQ(range.start, 11);
543     EXPECT_EQ(range.end, 53);
544 }
545 
546 /*
547  * @tc.name: ParagraphTestMiddleEllipsis006
548  * @tc.desc: test for Middle Ellipsis 006,Empty ellipsis,Empty String
549  * @tc.type: FUNC
550  */
551 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis006, TestSize.Level0)
552 {
553     size_t maxLines = 1;
554     PrepareMiddleEllipsis(maxLines, u"", u"");
555     paragraphMiddleEllipsis_->Layout(200);
556     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
557     EXPECT_EQ(range.start, std::numeric_limits<size_t>::max());
558     EXPECT_EQ(range.end, std::numeric_limits<size_t>::max());
559 }
560 
561 /*
562  * @tc.name: ParagraphTestMiddleEllipsis007
563  * @tc.desc: test for Middle Ellipsis 007,maxLines != 1
564  * @tc.type: FUNC
565  */
566 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis007, TestSize.Level0)
567 {
568     size_t maxLines = 2;
569     PrepareMiddleEllipsis(maxLines, u"...", u"Hello World");
570     paragraphMiddleEllipsis_->Layout(100);
571     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
572     EXPECT_EQ(range.start, std::numeric_limits<size_t>::max());
573     EXPECT_EQ(range.end, std::numeric_limits<size_t>::max());
574     EXPECT_TRUE(paragraphMiddleEllipsis_->CanPaintAllText());
575     ParagraphStyle paragraphStyle;
576     paragraphStyle.wordBreakType = OHOS::Rosen::SPText::WordBreakType::BREAK_WORD;
577     paragraphStyle.relayoutChangeBitmap.set(static_cast<size_t>(RelayoutParagraphStyleAttribute::WORD_BREAKTYPE));
578     std::vector<OHOS::Rosen::SPText::TextStyle> relayoutTextStyles;
579     OHOS::Rosen::SPText::TextStyle textStyle;
580     relayoutTextStyles.push_back(textStyle);
581     paragraphMiddleEllipsis_->Relayout(50, paragraphStyle, relayoutTextStyles);
582     EXPECT_FALSE(paragraphMiddleEllipsis_->CanPaintAllText());
583 }
584 
585 /*
586  * @tc.name: ParagraphTestMiddleEllipsis008
587  * @tc.desc: test for Middle Ellipsis 008, uygurqa
588  * @tc.type: FUNC
589  */
590 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis008, TestSize.Level0)
591 {
592     size_t maxLines = 1;
593     PrepareMiddleEllipsis(maxLines, u"...", u"ياخشىمۇ سىز؟ ھەركىمگە قۇتلۇق كۈنىمىز بولسۇن!");
594     paragraphMiddleEllipsis_->Layout(100);
595     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
596     EXPECT_EQ(range.start, 3);
597     EXPECT_EQ(range.end, 41);
598 }
599 
600 /*
601  * @tc.name: ParagraphTestMiddleEllipsis009
602  * @tc.desc: test for Middle Ellipsis 009, long tail space
603  * @tc.type: FUNC
604  */
605 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis009, TestSize.Level0)
606 {
607     size_t maxLines = 1;
608     PrepareMiddleEllipsis(maxLines, u"...", u"Hello Wolrd                ");
609     paragraphMiddleEllipsis_->Layout(100);
610     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
611     EXPECT_EQ(range.start, 2);
612     EXPECT_EQ(range.end, 23);
613 }
614 
615 /*
616  * @tc.name: ParagraphTestMiddleEllipsis010
617  * @tc.desc: test for Middle Ellipsis 010, empty text
618  * @tc.type: FUNC
619  */
620 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis010, TestSize.Level0)
621 {
622     size_t maxLines = 1;
623     PrepareMiddleEllipsis(maxLines, u"...", u"");
624     paragraphMiddleEllipsis_->Layout(1);
625     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
626     EXPECT_EQ(range.start, std::numeric_limits<size_t>::max());
627     EXPECT_EQ(range.end, std::numeric_limits<size_t>::max());
628 }
629 
630 /*
631  * @tc.name: ParagraphTestMiddleEllipsis011
632  * @tc.desc: test for Middle Ellipsis 011, empty ellipsis
633  * @tc.type: FUNC
634  */
635 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis011, TestSize.Level0)
636 {
637     size_t maxLines = 1;
638     PrepareMiddleEllipsis(maxLines, u"", u"Hello World");
639     paragraphMiddleEllipsis_->Layout(1);
640     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
641     EXPECT_EQ(range.start, std::numeric_limits<size_t>::max());
642     EXPECT_EQ(range.end, std::numeric_limits<size_t>::max());
643 }
644 
645 /*
646  * @tc.name: ParagraphTestMiddleEllipsis012
647  * @tc.desc: test for Middle Ellipsis 012, add placeholder
648  * @tc.type: FUNC
649  */
650 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis012, TestSize.Level0)
651 {
652     size_t maxLines = 1;
653     ParagraphStyle paragraphStyle;
654     paragraphStyle.maxLines = maxLines;
655     paragraphStyle.ellipsis = u"...";
656     paragraphStyle.ellipsisModal = OHOS::Rosen::SPText::EllipsisModal::MIDDLE;
657     std::shared_ptr<FontCollection> fontCollection = std::make_shared<FontCollection>();
658     ASSERT_NE(fontCollection, nullptr);
659     fontCollection->SetupDefaultFontManager();
660     std::shared_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
661     ASSERT_NE(paragraphBuilder, nullptr);
662     OHOS::Rosen::SPText::TextStyle style;
663     style.fontSize = 30; // 30 default fontsize
664     PlaceholderRun placeholderRun(50, 50, PlaceholderAlignment::BASELINE, SPText::TextBaseline::ALPHABETIC, 0.0);
665     paragraphBuilder->AddPlaceholder(placeholderRun);
666     paragraphBuilder->PushStyle(style);
667     paragraphBuilder->AddText(u"Hello World");
668     PlaceholderRun placeholderRun2(150, 150, PlaceholderAlignment::BASELINE, SPText::TextBaseline::ALPHABETIC, 0.0);
669     paragraphBuilder->AddPlaceholder(placeholderRun2);
670     paragraphMiddleEllipsis_ = paragraphBuilder->Build();
671     ASSERT_NE(paragraphMiddleEllipsis_, nullptr);
672     paragraphMiddleEllipsis_->Layout(100);
673     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
674     EXPECT_EQ(range.start, 1);
675     EXPECT_EQ(range.end, 13);
676 }
677 
678 /*
679  * @tc.name: ParagraphTestMiddleEllipsis013
680  * @tc.desc: test for Middle Ellipsis 013, \n
681  * @tc.type: FUNC
682  */
683 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis013, TestSize.Level0)
684 {
685     size_t maxLines = 1;
686     PrepareMiddleEllipsis(maxLines, u"...", u"A\nB");
687     paragraphMiddleEllipsis_->Layout(1);
688     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
689     EXPECT_EQ(range.start, 0);
690     EXPECT_EQ(range.end, 2);
691 }
692 
693 /*
694  * @tc.name: ParagraphTestMiddleEllipsis014
695  * @tc.desc: test for Middle Ellipsis 014, \n
696  * @tc.type: FUNC
697  */
698 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis014, TestSize.Level0)
699 {
700     size_t maxLines = 1;
701     PrepareMiddleEllipsis(maxLines, u"...", u"\nB");
702     paragraphMiddleEllipsis_->Layout(1);
703     OHOS::Rosen::SPText::Range<size_t> range = paragraphMiddleEllipsis_->GetEllipsisTextRange();
704     EXPECT_EQ(range.start, std::numeric_limits<size_t>::max());
705     EXPECT_EQ(range.end, std::numeric_limits<size_t>::max());
706 }
707 
708 /*
709  * @tc.name: ParagraphTestMiddleEllipsis015
710  * @tc.desc: test for Middle Ellipsis 015, get glyph position
711  * @tc.type: FUNC
712  */
713 HWTEST_F(ParagraphTest, ParagraphTestMiddleEllipsis015, TestSize.Level0)
714 {
715     size_t maxLines = 1;
716     PrepareMiddleEllipsis(maxLines, u"...", u"你好世界 Hello World");
717     paragraphMiddleEllipsis_->Layout(280);
718     EXPECT_EQ(paragraphMiddleEllipsis_->GetGlyphPositionAtCoordinate(50, 0.0).position, 2.0);
719     EXPECT_EQ(paragraphMiddleEllipsis_->GetGlyphPositionAtCoordinate(150, 0.0).position, 7.0);
720     EXPECT_EQ(paragraphMiddleEllipsis_->GetGlyphPositionAtCoordinate(270, 0.0).position, 16.0);
721 }
722 
ProcessRelayout(std::shared_ptr<Paragraph> paragraph,std::optional<RSBrush> brush)723 OHOS::Rosen::SPText::ParagraphImpl* ProcessRelayout(std::shared_ptr<Paragraph> paragraph, std::optional<RSBrush> brush)
724 {
725     std::vector<OHOS::Rosen::SPText::TextStyle> textStyles;
726     ParagraphStyle paragraphStyle;
727     OHOS::Rosen::SPText::TextStyle changeTextStyle;
728     changeTextStyle.foreground = SPText::PaintRecord(brush, Drawing::Pen());
729     changeTextStyle.relayoutChangeBitmap.set(static_cast<size_t>(RelayoutTextStyleAttribute::FOREGROUND_BRUSH));
730     textStyles.push_back(changeTextStyle);
731     paragraph->Relayout(200, paragraphStyle, textStyles);
732     return ParagraphTest::GetParagraphImpl(paragraph);
733 }
734 
735 /*
736  * @tc.name: ParagraphTestRelayoutBrush001
737  * @tc.desc: test for relayout foreground brush with multiple textstyle
738  * @tc.type: FUNC
739  */
740 HWTEST_F(ParagraphTest, ParagraphTestRelayoutBrush001, TestSize.Level0)
741 {
742     ParagraphStyle paragraphStyle;
743     auto fontCollection = std::make_shared<FontCollection>();
744     ASSERT_NE(fontCollection, nullptr);
745     fontCollection->SetupDefaultFontManager();
746     std::unique_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
747     ASSERT_NE(paragraphBuilder, nullptr);
748 
749     OHOS::Rosen::SPText::TextStyle style;
750     style.foreground = SPText::PaintRecord(Drawing::Brush(Drawing::Color::COLOR_DKGRAY), Drawing::Pen());
751     paragraphBuilder->PushStyle(style);
752     paragraphBuilder->AddText(text_);
753     OHOS::Rosen::SPText::TextStyle style1;
754     paragraphBuilder->PushStyle(style1);
755     paragraphBuilder->AddText(text_);
756     std::shared_ptr<Paragraph> paragraph = paragraphBuilder->Build();
757     ASSERT_NE(paragraph, nullptr);
758     paragraph->Layout(200);
759 
760     Drawing::Brush brush(Drawing::Color::COLOR_MAGENTA);
761     OHOS::Rosen::SPText::ParagraphImpl* paragraphImpl = ProcessRelayout(paragraph, brush);
762     EXPECT_EQ(paragraphImpl->paints_.size(), 3);
763     EXPECT_EQ(paragraphImpl->paints_[1].brush.value().GetColor(), Drawing::Color::COLOR_MAGENTA);
764     EXPECT_EQ(paragraphImpl->paints_[2].brush.value().GetColor(), Drawing::Color::COLOR_MAGENTA);
765     EXPECT_EQ(paragraphImpl->paints_[2].pen.has_value(), false);
766 
767     auto skiaTextStyles = paragraphImpl->paragraph_->exportTextStyles();
768     EXPECT_EQ(skiaTextStyles.size(), 2);
769     EXPECT_EQ(skiaTextStyles[0].fStyle.hasForeground(), true);
770     EXPECT_EQ(skiaTextStyles[1].fStyle.hasForeground(), true);
771     EXPECT_EQ(std::get<int>(skiaTextStyles[1].fStyle.getForegroundPaintOrID()), 2);
772 }
773 
774 /*
775  * @tc.name: ParagraphTestRelayoutBrush002
776  * @tc.desc: test for relayout foreground brush with symbol textstyle
777  * @tc.type: FUNC
778  */
779 HWTEST_F(ParagraphTest, ParagraphTestRelayoutBrush002, TestSize.Level0)
780 {
781     ParagraphStyle paragraphStyle;
782     auto fontCollection = std::make_shared<FontCollection>();
783     ASSERT_NE(fontCollection, nullptr);
784     fontCollection->SetupDefaultFontManager();
785     std::unique_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
786     ASSERT_NE(paragraphBuilder, nullptr);
787 
788     OHOS::Rosen::SPText::TextStyle style;
789     style.foreground = SPText::PaintRecord(Drawing::Brush(Drawing::Color::COLOR_DKGRAY), Drawing::Pen());
790     paragraphBuilder->PushStyle(style);
791     paragraphBuilder->AddText(text_);
792     OHOS::Rosen::SPText::TextStyle style1;
793     style1.isSymbolGlyph = true;
794     RSSColor symbolColor = {1.0, 0, 0, 0};
795     style1.symbol.SetRenderColor(symbolColor);
796     paragraphBuilder->PushStyle(style1);
797     paragraphBuilder->AddText(text_);
798     std::shared_ptr<Paragraph> paragraph = paragraphBuilder->Build();
799     ASSERT_NE(paragraph, nullptr);
800     paragraph->Layout(200);
801 
802     Drawing::Brush brush(Drawing::Color::COLOR_MAGENTA);
803     OHOS::Rosen::SPText::ParagraphImpl* paragraphImpl = ProcessRelayout(paragraph, brush);
804     EXPECT_EQ(paragraphImpl->paints_.size(), 3);
805     EXPECT_EQ(paragraphImpl->paints_[1].brush.value().GetColor(), Drawing::Color::COLOR_MAGENTA);
806     EXPECT_EQ(paragraphImpl->paints_[2].brush.has_value(), false);
807 }
808 
809 /*
810  * @tc.name: ParagraphTestRelayoutBrush003
811  * @tc.desc: test for relayout foreground with nullopt
812  * @tc.type: FUNC
813  */
814 HWTEST_F(ParagraphTest, ParagraphTestRelayoutBrush003, TestSize.Level0)
815 {
816     ParagraphStyle paragraphStyle;
817     auto fontCollection = std::make_shared<FontCollection>();
818     ASSERT_NE(fontCollection, nullptr);
819     fontCollection->SetupDefaultFontManager();
820     std::unique_ptr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::Create(paragraphStyle, fontCollection);
821     ASSERT_NE(paragraphBuilder, nullptr);
822 
823     OHOS::Rosen::SPText::TextStyle style;
824     style.foreground = SPText::PaintRecord(Drawing::Brush(Drawing::Color::COLOR_DKGRAY), Drawing::Pen());
825     paragraphBuilder->PushStyle(style);
826     paragraphBuilder->AddText(text_);
827     OHOS::Rosen::SPText::TextStyle style1;
828     paragraphBuilder->PushStyle(style1);
829     paragraphBuilder->AddText(text_);
830     std::shared_ptr<Paragraph> paragraph = paragraphBuilder->Build();
831     ASSERT_NE(paragraph, nullptr);
832     paragraph->Layout(200);
833 
834     OHOS::Rosen::SPText::ParagraphImpl* paragraphImpl = ProcessRelayout(paragraph, std::nullopt);
835 
836     EXPECT_EQ(paragraphImpl->paints_.size(), 3);
837     EXPECT_EQ(paragraphImpl->paints_[0].brush.has_value(), false);
838     EXPECT_EQ(paragraphImpl->paints_[1].brush.has_value(), false);
839 }
840 
841 /*
842  * @tc.name: ParagraphTestTextEffect001
843  * @tc.desc: test for text effect state
844  * @tc.type: FUNC
845  */
846 HWTEST_F(ParagraphTest, ParagraphTestTextEffect001, TestSize.Level0)
847 {
848     Canvas canvas;
849     paragraph_->Paint(&canvas, 0.0, 0.0);
850     OHOS::Rosen::SPText::ParagraphImpl* paragraphImpl = GetParagraphImpl(paragraph_);
851     ASSERT_NE(paragraphImpl, nullptr);
852     std::unique_ptr<skt::Paragraph> temp = nullptr;
853     paragraphImpl->paragraph_.swap(temp);
854     EXPECT_EQ(paragraphImpl->GetTextBlobRecordInfo().size(), 0);
855     paragraphImpl->SetSkipTextBlobDrawing(true);
856     EXPECT_FALSE(paragraphImpl->HasSkipTextBlobDrawing());
857 
858     paragraphImpl->paragraph_.swap(temp);
859     EXPECT_NE(paragraphImpl->GetTextBlobRecordInfo().size(), 0);
860     paragraphImpl->SetSkipTextBlobDrawing(true);
861     EXPECT_TRUE(paragraphImpl->HasSkipTextBlobDrawing());
862 }
863 } // namespace txt