• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <gmock/gmock.h>
17 #include <gtest/gtest.h>
18 
19 #include "draw/canvas.h"
20 #include "text_flip_effect.h"
21 #include "typography_mock.h"
22 #include "typography.h"
23 #include "typography_create.h"
24 #include "font_collection.h"
25 
26 using namespace testing;
27 using namespace testing::ext;
28 using namespace OHOS::Rosen;
29 
30 class MockCanvas : public Drawing::Canvas {
31 public:
32     MOCK_METHOD(void, DrawTextBlob, (const Drawing::TextBlob* blob, const float x, const float y), (override));
33 };
34 
35 class TextFlipEffectTest : public testing::Test {
36 public:
SetUp()37     void SetUp() override
38     {
39         auto textEffect = TextEffectFactoryCreator::GetInstance().CreateTextEffect(TextEffectStrategy::FLIP);
40         effect_ = std::static_pointer_cast<TextFlipEffect>(textEffect);
41         ASSERT_NE(effect_, nullptr);
42         EXPECT_EQ(effect_->strategy_, TextEffectStrategy::FLIP);
43         mockTypography_ = std::make_shared<MockTypography>();
44         mockCanvas_ = std::make_unique<MockCanvas>();
45     }
46 
TearDown()47     void TearDown() override
48     {
49         effect_.reset();
50         mockTypography_.reset();
51         mockCanvas_.reset();
52     }
53 
54 protected:
55     std::shared_ptr<TextFlipEffect> effect_{nullptr};
56     std::shared_ptr<MockTypography> mockTypography_{nullptr};
57     std::unique_ptr<MockCanvas> mockCanvas_{nullptr};
58 
CreateConfig()59     TypographyConfig CreateConfig()
60     {
61         return { mockTypography_, {0, 10} };
62     }
63 };
64 
65 /*
66  * @tc.name: TextFlipEffectTest001
67  * @tc.desc: Test for UpdateEffectConfig action
68  * @tc.type: FUNC
69  */
70 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest001, TestSize.Level0)
71 {
72     std::unordered_map<TextEffectAttribute, std::string> config1 = {
73         {TextEffectAttribute::FLIP_DIRECTION, "up"},
74         {TextEffectAttribute::BLUR_ENABLE, "false"},
75     };
76 
77     std::unordered_map<TextEffectAttribute, std::string> config2 = {
78         {TextEffectAttribute::FLIP_DIRECTION, "down"},
79         {TextEffectAttribute::BLUR_ENABLE, "true"},
80     };
81 
82     EXPECT_EQ(effect_->UpdateEffectConfig(config1), TEXT_EFFECT_SUCCESS);
83     EXPECT_EQ(effect_->UpdateEffectConfig(config2), TEXT_EFFECT_SUCCESS);
84     EXPECT_EQ(effect_->direction_, TextEffectFlipDirection::DOWN);
85     EXPECT_TRUE(effect_->blurEnable_);
86 
87     std::unordered_map<TextEffectAttribute, std::string> invalidConfig = {
88         {TextEffectAttribute::FLIP_DIRECTION, "invalid"},
89         {TextEffectAttribute::BLUR_ENABLE, "invalid"}
90     };
91     EXPECT_EQ(effect_->UpdateEffectConfig(invalidConfig), TEXT_EFFECT_INVALID_INPUT);
92     EXPECT_EQ(effect_->direction_, TextEffectFlipDirection::DOWN);
93     EXPECT_TRUE(effect_->blurEnable_);
94 
95     std::unordered_map<TextEffectAttribute, std::string> configEmpty;
96     EXPECT_EQ(effect_->UpdateEffectConfig(configEmpty), TEXT_EFFECT_SUCCESS);
97 }
98 
99 /*
100  * @tc.name: TextFlipEffectTest002
101  * @tc.desc: Test for AppendTypography action
102  * @tc.type: FUNC
103  */
104 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest002, TestSize.Level0)
105 {
106     TypographyConfig config = CreateConfig();
107     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(1);
108     EXPECT_EQ(effect_->AppendTypography({config}), TEXT_EFFECT_SUCCESS);
109     EXPECT_EQ(effect_->typographyConfig_.typography, mockTypography_);
110 
111     auto anotherTypography = std::make_shared<MockTypography>();
112     TypographyConfig anotherConfig = { anotherTypography, {5, 15} };
113     EXPECT_EQ(effect_->AppendTypography({anotherConfig}), TEXT_EFFECT_UNKNOWN);
114 
115     EXPECT_EQ(effect_->AppendTypography({}), TEXT_EFFECT_INVALID_INPUT);
116     TypographyConfig nullptrConfig = { nullptr, {0, 0} };
117     EXPECT_EQ(effect_->AppendTypography({nullptrConfig}), TEXT_EFFECT_INVALID_INPUT);
118 }
119 
120 /*
121  * @tc.name: TextFlipEffectTest003
122  * @tc.desc: Test for UpdateTypography action
123  * @tc.type: FUNC
124  */
125 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest003, TestSize.Level0)
126 {
127     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(2);
128     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(false)).Times(1);
129     effect_->AppendTypography({CreateConfig()});
130     TypographyConfig newConfig = { mockTypography_, {5, 15} };
131     std::vector<std::pair<TypographyConfig, TypographyConfig>> update = {
132         {CreateConfig(), newConfig}
133     };
134 
135     EXPECT_EQ(effect_->UpdateTypography(update), TEXT_EFFECT_SUCCESS);
136     EXPECT_EQ(effect_->typographyConfig_.rawTextRange.first, 5);
137     EXPECT_EQ(effect_->typographyConfig_.rawTextRange.second, 15);
138 
139     TypographyConfig configNull = { nullptr, {5, 15} };
140     std::vector<std::pair<TypographyConfig, TypographyConfig>> updateNull = {
141         {CreateConfig(), configNull}
142     };
143     EXPECT_EQ(effect_->UpdateTypography(updateNull), TEXT_EFFECT_INVALID_INPUT);
144 
145     std::vector<std::pair<TypographyConfig, TypographyConfig>> emptyUpdate;
146     EXPECT_EQ(effect_->UpdateTypography(emptyUpdate), TEXT_EFFECT_INVALID_INPUT);
147 
148     auto anotherTypography = std::make_shared<MockTypography>();
149     TypographyConfig anotherConfig = { anotherTypography, {5, 15} };
150     std::vector<std::pair<TypographyConfig, TypographyConfig>> mismatchedUpdate = {
151         {anotherConfig, anotherConfig}
152     };
153     EXPECT_EQ(effect_->UpdateTypography(mismatchedUpdate), TEXT_EFFECT_INVALID_INPUT);
154     effect_->typographyConfig_.typography = nullptr;
155     TypographyConfig invalidConfig = { nullptr, {5, 15} };
156     std::vector<std::pair<TypographyConfig, TypographyConfig>> invalidUpdate = {
157         {invalidConfig, anotherConfig}
158     };
159     EXPECT_EQ(effect_->UpdateTypography(invalidUpdate), TEXT_EFFECT_UNKNOWN);
160 }
161 
162 /*
163  * @tc.name: TextFlipEffectTest004
164  * @tc.desc: Test for RemoveTypography action
165  * @tc.type: FUNC
166  */
167 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest004, TestSize.Level0)
168 {
169     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(false)).Times(2);
170     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(2);
171     TypographyConfig config = CreateConfig();
172     effect_->AppendTypography({config});
173     effect_->RemoveTypography({config});
174 
175     EXPECT_EQ(effect_->typographyConfig_.typography, nullptr);
176     EXPECT_EQ(effect_->typographyConfig_.rawTextRange.first, 0);
177     EXPECT_EQ(effect_->typographyConfig_.rawTextRange.second, 0);
178 
179     effect_->AppendTypography({CreateConfig()});
180     auto anotherTypography = std::make_shared<MockTypography>();
181     TypographyConfig anotherConfig = { anotherTypography, {5, 15} };
182     effect_->RemoveTypography({anotherConfig});
183     EXPECT_NE(effect_->typographyConfig_.typography, nullptr);
184     effect_->RemoveTypography({});
185     EXPECT_EQ(effect_->typographyConfig_.typography, nullptr);
186 }
187 
188 /*
189  * @tc.name: TextFlipEffectTest005
190  * @tc.desc: Test for StartEffect and StopEffect action
191  * @tc.type: FUNC
192  */
193 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest005, TestSize.Level0)
194 {
195     OHOS::Rosen::TypographyStyle typographyStyle0;
196     typographyStyle0.enableAutoSpace = false;
197     std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection0 =
198         OHOS::Rosen::FontCollection::From(std::make_shared<txt::FontCollection>());
199     std::unique_ptr<OHOS::Rosen::TypographyCreate> typographyCreate =
200         OHOS::Rosen::TypographyCreate::Create(typographyStyle0, fontCollection0);
201     std::u16string text = u"88";
202     typographyCreate->AppendText(text);
203     std::unique_ptr<OHOS::Rosen::Typography> typography0 = typographyCreate->CreateTypography();
204     double maxWidth = 1500;
205     typography0->Layout(maxWidth);
206 
207     std::shared_ptr<Typography> typography(typography0.release());
208     TypographyConfig config = { typography, {0, text.length()} };
209     effect_->AppendTypography({config});
210     effect_->StartEffect(mockCanvas_.get(), 100.0, 200.0);
211     effect_->StopEffect();
212     TypographyConfig config1 = { typography, {0, text.length()} };
213     effect_->AppendTypography({config1});
214     typography->SetSkipTextBlobDrawing(true);
215     typography->Paint(mockCanvas_.get(), 100.0, 200.0);
216     effect_->StartEffect(mockCanvas_.get(), 100.0, 200.0);
217     EXPECT_FALSE(effect_->lastAllBlobGlyphIds_.empty());
218 
219     typography->SetSkipTextBlobDrawing(false);
220     effect_->StopEffect();
221     EXPECT_TRUE(effect_->lastAllBlobGlyphIds_.empty());
222 }
223 
224 /*
225  * @tc.name: TextFlipEffectTest006
226  * @tc.desc: Test for DrawTextFlip action
227  * @tc.type: FUNC
228  */
229 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest006, TestSize.Level0)
230 {
231     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(1);
232     EXPECT_CALL(*mockTypography_, GetAnimation()).Times(1);
233     TypographyConfig config = CreateConfig();
234     effect_->AppendTypography({config});
235     std::vector<TextBlobRecordInfo> records;
236     TextBlobRecordInfo record1 = {nullptr, {0.0f, 0.0f}, Drawing::Color::COLOR_BLACK};
237     std::string info = "88";
238     OHOS::Rosen::Drawing::Font font;
239     font.SetSize(24);
240     std::shared_ptr<Drawing::TextBlob> blob = Drawing::TextBlob::MakeFromString(info.c_str(), font);
241     TextBlobRecordInfo record2 = {blob, {0.0f, 0.0f}, Drawing::Color::COLOR_BLACK};
242     records.emplace_back(record1);
243     records.emplace_back(record2);
244     double x = 0.0;
245     double y = 0.0;
246     effect_->DrawTextFlip(records, mockCanvas_.get(), x, y);
247     EXPECT_TRUE(effect_->lastAllBlobGlyphIds_.empty());
248 }
249 
250 /*
251  * @tc.name: TextFlipEffectTest007
252  * @tc.desc: Test for DrawResidualText action
253  * @tc.type: FUNC
254  */
255 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest007, TestSize.Level0)
256 {
257     OHOS::Rosen::TypographyStyle typographyStyle0;
258     typographyStyle0.enableAutoSpace = false;
259     std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection0 =
260         OHOS::Rosen::FontCollection::From(std::make_shared<txt::FontCollection>());
261     std::unique_ptr<OHOS::Rosen::TypographyCreate> typographyCreate =
262         OHOS::Rosen::TypographyCreate::Create(typographyStyle0, fontCollection0);
263     std::u16string text = u"88";
264     typographyCreate->AppendText(text);
265     std::unique_ptr<OHOS::Rosen::Typography> typography0 = typographyCreate->CreateTypography();
266     double maxWidth = 1500;
267     typography0->Layout(maxWidth);
268     std::shared_ptr<Typography> typography(typography0.release());
269     TypographyConfig config = { typography, {0, text.length()} };
270     effect_->AppendTypography({config});
271     typography->SetSkipTextBlobDrawing(true);
272     typography->Paint(mockCanvas_.get(), 100.0, 200.0);
273     std::vector<TextBlobRecordInfo> records = typography->GetTextBlobRecordInfo();
274     EXPECT_FALSE(records.empty());
275     double height = records[0].blob->Bounds()->GetHeight();
276     std::function<bool(const std::shared_ptr<TextEngine::SymbolAnimationConfig>&)> animationFunc =
277         typography->GetAnimation();
278     effect_->currentGlyphIndex_ = 0;
279     effect_->lastAllBlobGlyphIds_.clear();
280     effect_->lastAllBlobGlyphIds_.emplace_back(10);
281     effect_->lastAllBlobGlyphIds_.emplace_back(20);
282     effect_->DrawResidualText(mockCanvas_.get(), height, animationFunc);
283     EXPECT_FALSE(effect_->lastAllBlobGlyphIds_.empty());
284     effect_->currentGlyphIndex_ = 2;
285     effect_->lastAllBlobGlyphIds_.clear();
286     effect_->DrawResidualText(mockCanvas_.get(), height, animationFunc);
287     EXPECT_NE(effect_->currentGlyphIndex_, 0);
288 }
289 
290 /*
291  * @tc.name: TextFlipEffectTest008
292  * @tc.desc: Test for DrawTextFlipElements action
293  * @tc.type: FUNC
294  */
295 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest008, TestSize.Level0)
296 {
297     OHOS::Rosen::TypographyStyle typographyStyle0;
298     typographyStyle0.enableAutoSpace = false;
299     std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection0 =
300         OHOS::Rosen::FontCollection::From(std::make_shared<txt::FontCollection>());
301     std::unique_ptr<OHOS::Rosen::TypographyCreate> typographyCreate =
302         OHOS::Rosen::TypographyCreate::Create(typographyStyle0, fontCollection0);
303     std::u16string text = u"88";
304     typographyCreate->AppendText(text);
305     std::unique_ptr<OHOS::Rosen::Typography> typography0 = typographyCreate->CreateTypography();
306     double maxWidth = 1500;
307     typography0->Layout(maxWidth);
308     std::shared_ptr<Typography> typography(typography0.release());
309     TypographyConfig config = { typography, {0, text.length()} };
310     effect_->AppendTypography({config});
311     typography->SetSkipTextBlobDrawing(true);
312     typography->Paint(mockCanvas_.get(), 100.0, 200.0);
313     std::vector<TextBlobRecordInfo> records = typography->GetTextBlobRecordInfo();
314     EXPECT_FALSE(records.empty());
315     double height = records[0].blob->Bounds()->GetHeight();
316     std::function<bool(const std::shared_ptr<TextEngine::SymbolAnimationConfig>&)> animationFunc =
317         typography->GetAnimation();
318     std::vector<std::vector<TextEngine::TextEffectElement>> effectElements;
319     std::vector<TextEngine::TextEffectElement> unEffectElements;
320     std::vector<TextEngine::TextEffectElement> inEffectElements;
321     effectElements.emplace_back(unEffectElements);
322     effectElements.emplace_back(inEffectElements);
323     effect_->DrawTextFlipElements(mockCanvas_.get(), height, Drawing::Color::COLOR_BLACK,
324         animationFunc, effectElements);
325     EXPECT_EQ(effect_->currentGlyphIndex_, 0);
326 }
327 
328 /*
329  * @tc.name: TextFlipEffectTest009
330  * @tc.desc: Test for ClearTypography action
331  * @tc.type: FUNC
332  */
333 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest009, TestSize.Level0)
334 {
335     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(2);
336     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(false)).Times(1);
337     TypographyConfig config = CreateConfig();
338     effect_->AppendTypography({config});
339     effect_->ClearTypography();
340     EXPECT_EQ(effect_->typographyConfig_.typography, nullptr);
341     effect_->AppendTypography({config});
342     effect_->typographyConfig_.typography = nullptr;
343     effect_->ClearTypography();
344     EXPECT_EQ(effect_->typographyConfig_.rawTextRange.second, 10);
345 }
346 
347 /*
348  * @tc.name: TextFlipEffectTest010
349  * @tc.desc: Test for GenerateChangeElements action
350  * @tc.type: FUNC
351  */
352 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest010, TestSize.Level0)
353 {
354     OHOS::Rosen::TypographyStyle typographyStyle0;
355     typographyStyle0.enableAutoSpace = false;
356     std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection0 =
357         OHOS::Rosen::FontCollection::From(std::make_shared<txt::FontCollection>());
358     std::unique_ptr<OHOS::Rosen::TypographyCreate> typographyCreate0 =
359         OHOS::Rosen::TypographyCreate::Create(typographyStyle0, fontCollection0);
360     std::u16string text = u"88";
361     typographyCreate0->AppendText(text);
362     std::unique_ptr<OHOS::Rosen::Typography> typography0 = typographyCreate0->CreateTypography();
363     double maxWidth = 1500;
364     typography0->Layout(maxWidth);
365     std::shared_ptr<Typography> typographySharePtr0(typography0.release());
366     TypographyConfig config0 = { typographySharePtr0, {0, text.length()} };
367     effect_->AppendTypography({config0});
368     double x = 100.0;
369     double y = 200.0;
370     effect_->StartEffect(mockCanvas_.get(), x, y);
371 
372     OHOS::Rosen::TypographyStyle typographyStyle1;
373     typographyStyle1.enableAutoSpace = false;
374     std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection1 =
375         OHOS::Rosen::FontCollection::From(std::make_shared<txt::FontCollection>());
376     std::unique_ptr<OHOS::Rosen::TypographyCreate> typographyCreate1 =
377         OHOS::Rosen::TypographyCreate::Create(typographyStyle1, fontCollection1);
378     text = u"89";
379     typographyCreate1->AppendText(text);
380     std::unique_ptr<OHOS::Rosen::Typography> typography1 = typographyCreate1->CreateTypography();
381     typography1->Layout(maxWidth);
382     std::shared_ptr<Typography> typographySharePtr1(typography1.release());
383     TypographyConfig config1 = { typographySharePtr1, {0, text.length()} };
384     std::vector<std::pair<TypographyConfig, TypographyConfig>> typographyConfigs;
385     std::pair<TypographyConfig, TypographyConfig> typographyConfig(config0, config1);
386     typographyConfigs.emplace_back(typographyConfig);
387     effect_->UpdateTypography(typographyConfigs);
388     typographySharePtr1->SetSkipTextBlobDrawing(true);
389     typographySharePtr1->Paint(mockCanvas_.get(), x, y);
390     std::vector<TextBlobRecordInfo> records = typographySharePtr1->GetTextBlobRecordInfo();
391     EXPECT_FALSE(records.empty());
392     std::vector<std::vector<TextEngine::TextEffectElement>> effectElements;
393     for (auto& info : records) {
394         effectElements = effect_->GenerateChangeElements(info.blob,
395             x + info.offset.fX, y + info.offset.fY);
396     }
397     EXPECT_FALSE(effectElements.empty());
398 }
399 
400 /*
401  * @tc.name: TextFlipEffectTest011
402  * @tc.desc: Test for GenerateFlipConfig action
403  * @tc.type: FUNC
404  */
405 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest011, TestSize.Level0)
406 {
407     effect_->blurEnable_ = true;
408     EXPECT_EQ(effect_->GenerateFlipConfig(15.0).size(), 2);
409 }
410 
411 /*
412  * @tc.name: TextFlipEffectTest012
413  * @tc.desc: Test for NoEffect action
414  * @tc.type: FUNC
415  */
416 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest012, TestSize.Level0)
417 {
418     double x = 100.0;
419     double y = 200.0;
420     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(1);
421     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(false)).Times(1);
422     EXPECT_CALL(*mockTypography_, HasSkipTextBlobDrawing()).Times(1);
423     EXPECT_CALL(*mockTypography_, SetSkipTextBlobDrawing(false)).Times(2);
424     EXPECT_CALL(*mockTypography_, Paint(mockCanvas_.get(), x, y)).Times(1);
425 
426     TypographyConfig config = CreateConfig();
427     effect_->AppendTypography({config});
428     effect_->NoEffect(mockCanvas_.get(), x, y);
429     EXPECT_TRUE(effect_->lastAllBlobGlyphIds_.empty());
430 
431     effect_->RemoveTypography({config});
432     effect_->NoEffect(mockCanvas_.get(), x, y);
433     EXPECT_EQ(effect_->typographyConfig_.typography, nullptr);
434 }
435 
436 /*
437  * @tc.name: TextFlipEffectTest013
438  * @tc.desc: Test for no path ttf
439  * @tc.type: FUNC
440  */
441 HWTEST_F(TextFlipEffectTest, TextFlipEffectTest013, TestSize.Level0)
442 {
443     double x = 100.0;
444     double y = 100.0;
445     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(true)).Times(1);
446     EXPECT_CALL(*mockTypography_, SetTextEffectAssociation(false)).Times(1);
447     EXPECT_CALL(*mockTypography_, GetAnimation()).Times(1);
448 
449     const char* text = "\uffff";
450     OHOS::Rosen::Drawing::Font font;
451     std::shared_ptr<Drawing::TextBlob> blob = Drawing::TextBlob::MakeFromString(text, font);
452     TypographyConfig config = CreateConfig();
453     effect_->AppendTypography({config});
454     EXPECT_CALL(*mockCanvas_, DrawTextBlob(blob.get(), x, y)).Times(1);
455     TextBlobRecordInfo blobInfo;
456     blobInfo.blob = blob;
457     std::vector<TextBlobRecordInfo> infos;
458     infos.emplace_back(blobInfo);
459     effect_->DrawTextFlip(infos, mockCanvas_.get(), x, y);
460     EXPECT_TRUE(effect_->lastAllBlobGlyphIds_.empty());
461     effect_->DrawTextFlip(infos, nullptr, x, y);
462     effect_->RemoveTypography({config});
463     EXPECT_EQ(effect_->typographyConfig_.typography, nullptr);
464 }