• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 <algorithm>
17 #include <cstddef>
18 #include <optional>
19 #include <utility>
20 
21 #include "base/image/image_source.h"
22 #include "base/image/pixel_map.h"
23 #include "gtest/gtest.h"
24 
25 #define protected public
26 #define private public
27 #include "core/components_ng/pattern/canvas/canvas_event_hub.h"
28 #include "core/components_ng/pattern/canvas/canvas_layout_algorithm.h"
29 #include "core/components_ng/pattern/canvas/canvas_model.h"
30 #include "core/components_ng/pattern/canvas/canvas_model_ng.h"
31 #include "core/components_ng/pattern/canvas/canvas_modifier.h"
32 #include "core/components_ng/pattern/canvas/canvas_paint_method.h"
33 #include "core/components_ng/pattern/canvas/canvas_paint_op.h"
34 #include "core/components_ng/pattern/canvas/canvas_pattern.h"
35 #include "core/components_ng/pattern/canvas/custom_paint_paint_method.h"
36 #include "core/components_ng/pattern/canvas/custom_paint_util.h"
37 #include "core/components_ng/pattern/canvas/offscreen_canvas_paint_method.h"
38 #include "core/components_ng/pattern/canvas/offscreen_canvas_pattern.h"
39 #undef private
40 #undef protected
41 
42 using namespace testing;
43 using namespace testing::ext;
44 
45 namespace OHOS::Ace::NG {
46 
47 class CanvasTestNg : public testing::Test {
48 public:
49     static void SetUpTestCase();
50     static void TearDownTestCase();
51 };
52 
SetUpTestCase()53 void CanvasTestNg::SetUpTestCase() {}
54 
TearDownTestCase()55 void CanvasTestNg::TearDownTestCase() {}
56 
57 /**
58  * @tc.name: CanvasPatternTest001
59  * @tc.desc: Test the function 'IsPercentStr' of the class 'CustomPaintPaintMethod'.
60  * @tc.type: FUNC
61  */
62 HWTEST_F(CanvasTestNg, CanvasPatternTest001, TestSize.Level1)
63 {
64     /**
65      * @tc.steps1: initialize parameters.
66      * @tc.expected: All pointer is non-null.
67      */
68     auto paintMethod = AceType::MakeRefPtr<OffscreenCanvasPaintMethod>();
69     ASSERT_NE(paintMethod, nullptr);
70 
71     /**
72      * @tc.steps2: Call the function IsPercentStr with percent string.
73      * @tc.expected: The return value is true and the '%' of percent string is droped.
74      */
75     const std::string exceptedresult("50");
76 
77     std::string percentStr("50%");
78     EXPECT_TRUE(paintMethod->IsPercentStr(percentStr));
79     EXPECT_STREQ(percentStr.c_str(), exceptedresult.c_str());
80 
81     /**
82      * @tc.steps3: Call the function IsPercentStr with non-percent string.
83      * @tc.expected: The return value is false and the non-percent string is not changed.
84      */
85     std::string nonPercentStr("50");
86     EXPECT_FALSE(paintMethod->IsPercentStr(nonPercentStr));
87     EXPECT_STREQ(nonPercentStr.c_str(), exceptedresult.c_str());
88 }
89 
90 /**
91  * @tc.name: CanvasPatternTest002
92  * @tc.desc: CanvasPattern::OnSizeChanged
93  * @tc.type: FUNC
94  */
95 HWTEST_F(CanvasTestNg, CanvasPatternTest002, TestSize.Level1)
96 {
97     auto* stack = ViewStackProcessor::GetInstance();
98     auto nodeId = stack->ClaimNodeId();
99     auto frameNode = FrameNode::GetOrCreateFrameNode(
__anonef3f1d760102() 100         V2::CANVAS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CanvasPattern>(); });
101     RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
102     geometryNode->SetContentSize(SizeF(100.0f, 100.0f));
103     geometryNode->SetContentOffset(OffsetF(0.0f, 0.0f));
104     auto pattern = frameNode->GetPattern<CanvasPattern>();
105     RefPtr<LayoutAlgorithm> layoutAlgorithm = AceType::MakeRefPtr<LayoutAlgorithm>();
106     auto layoutAlgorithmWrapper = AceType::MakeRefPtr<LayoutAlgorithmWrapper>(layoutAlgorithm, false);
107     auto layoutWrapper = AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, nullptr);
108     layoutWrapper->SetLayoutAlgorithm(layoutAlgorithmWrapper);
109     DirtySwapConfig config;
110     bool needReset;
111 
112     /**
113      * @tc.steps: step1. needReset = false; dirtyPixelGridRoundSize_ = { 0, 0 }
114      */
115     needReset = false;
116     pattern->contentModifier_ = AceType::MakeRefPtr<CanvasModifier>();
117     pattern->dirtyPixelGridRoundSize_ = { -1, -1 };
118     pattern->OnSizeChanged(config, needReset);
119     ASSERT_NE(pattern->contentModifier_, nullptr);
120     auto contentModifier1 = pattern->contentModifier_;
121     EXPECT_FALSE(contentModifier1->needResetSurface_);
122 
123     /**
124      * @tc.steps: step2. needReset = false; dirtyPixelGridRoundSize_ = { 1, 1 };
125      */
126     needReset = false;
127     config.frameSizeChange = false;
128     config.contentSizeChange = false;
129     pattern->contentModifier_ = AceType::MakeRefPtr<CanvasModifier>();
130     pattern->dirtyPixelGridRoundSize_ = { 1, 1 };
131     pattern->OnSizeChanged(config, needReset);
132     ASSERT_NE(pattern->contentModifier_, nullptr);
133     auto contentModifier2 = pattern->contentModifier_;
134     EXPECT_FALSE(contentModifier2->needResetSurface_);
135 
136     /**
137      * @tc.steps: step3. needReset = true; dirtyPixelGridRoundSize_ = { 1, 1 };
138      */
139     needReset = false;
140     config.frameSizeChange = true;
141     config.contentSizeChange = true;
142     pattern->contentModifier_ = AceType::MakeRefPtr<CanvasModifier>();
143     pattern->dirtyPixelGridRoundSize_ = { 1, 1 };
144     pattern->OnSizeChanged(config, needReset);
145     ASSERT_NE(pattern->contentModifier_, nullptr);
146     auto contentModifier3 = pattern->contentModifier_;
147     EXPECT_FALSE(contentModifier3->needResetSurface_);
148 
149     /**
150      * @tc.steps: step4. needReset = true; config.frameSizeChange = false; config.contentSizeChange = false;
151      */
152     needReset = true;
153     config.frameSizeChange = false;
154     config.contentSizeChange = false;
155     pattern->contentModifier_ = AceType::MakeRefPtr<CanvasModifier>();
156     pattern->dirtyPixelGridRoundSize_ = { -1, -1 };
157     pattern->OnSizeChanged(config, needReset);
158     ASSERT_NE(pattern->contentModifier_, nullptr);
159     auto contentModifier4 = pattern->contentModifier_;
160     EXPECT_FALSE(contentModifier4->needResetSurface_);
161 
162     /**
163      * @tc.steps: step5. needReset = true; config.frameSizeChange = true; config.contentSizeChange = false;
164      */
165     needReset = true;
166     config.frameSizeChange = true;
167     config.contentSizeChange = false;
168     pattern->contentModifier_ = AceType::MakeRefPtr<CanvasModifier>();
169     pattern->dirtyPixelGridRoundSize_ = { -1, -1 };
170     pattern->OnSizeChanged(config, needReset);
171     ASSERT_NE(pattern->contentModifier_, nullptr);
172     auto contentModifier5 = pattern->contentModifier_;
173     EXPECT_TRUE(contentModifier5->needResetSurface_);
174 
175     /**
176      * @tc.steps: step6. needReset = true; config.frameSizeChange = false; config.contentSizeChange = true;
177      */
178     needReset = true;
179     config.frameSizeChange = false;
180     config.contentSizeChange = true;
181     pattern->contentModifier_ = AceType::MakeRefPtr<CanvasModifier>();
182     pattern->dirtyPixelGridRoundSize_ = { -1, -1 };
183     pattern->OnSizeChanged(config, needReset);
184     ASSERT_NE(pattern->contentModifier_, nullptr);
185     auto contentModifier6 = pattern->contentModifier_;
186     EXPECT_TRUE(contentModifier6->needResetSurface_);
187 }
188 
189 /**
190  * @tc.name: CanvasPatternTest003
191  * @tc.desc: CanvasPattern::EnableAnalyzer
192  * @tc.type: FUNC
193  */
194 HWTEST_F(CanvasTestNg, CanvasPatternTest003, TestSize.Level1)
195 {
196     auto* stack = ViewStackProcessor::GetInstance();
197     auto nodeId = stack->ClaimNodeId();
198     auto frameNode = FrameNode::GetOrCreateFrameNode(
__anonef3f1d760202() 199         V2::CANVAS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CanvasPattern>(); });
200     RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
201     geometryNode->SetContentSize(SizeF(100.0f, 100.0f));
202     geometryNode->SetContentOffset(OffsetF(0.0f, 0.0f));
203     auto pattern = frameNode->GetPattern<CanvasPattern>();
204 
205     /**
206      * @tc.steps: step1. enable = false;
207      */
208     pattern->EnableAnalyzer(false);
209     EXPECT_FALSE(pattern->imageAnalyzerManager_);
210 
211     /**
212      * @tc.steps: step1. enable = true;
213      */
214     pattern->EnableAnalyzer(true);
215     EXPECT_TRUE(pattern->imageAnalyzerManager_);
216 }
217 
218 /**
219  * @tc.name: CanvasPatternTest004
220  * @tc.desc: CanvasPattern::UpdateTextDefaultDirection
221  * @tc.type: FUNC
222  */
223 HWTEST_F(CanvasTestNg, CanvasPatternTest004, TestSize.Level1)
224 {
225     auto* stack = ViewStackProcessor::GetInstance();
226     auto nodeId = stack->ClaimNodeId();
227     auto frameNode = FrameNode::GetOrCreateFrameNode(
__anonef3f1d760302() 228         V2::CANVAS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CanvasPattern>(); });
229     RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
230     geometryNode->SetContentSize(SizeF(100.0f, 100.0f));
231     geometryNode->SetContentOffset(OffsetF(0.0f, 0.0f));
232     auto pattern = frameNode->GetPattern<CanvasPattern>();
233 
234     /**
235      * @tc.steps: step1. TextDirection::AUTO;
236      */
237     pattern->currentSetTextDirection_ = TextDirection::AUTO;
238     pattern->UpdateTextDefaultDirection();
239     EXPECT_EQ(pattern->currentSetTextDirection_, TextDirection::AUTO);
240 }
241 
242 /**
243  * @tc.name: CanvasPatternTest005
244  * @tc.desc: CanvasLayoutAlgorithm::MeasureContent
245  * @tc.type: FUNC
246  */
247 HWTEST_F(CanvasTestNg, CanvasPatternTest005, TestSize.Level1)
248 {
249     auto* stack = ViewStackProcessor::GetInstance();
250     auto nodeId = stack->ClaimNodeId();
251     auto frameNode = FrameNode::GetOrCreateFrameNode(
__anonef3f1d760402() 252         V2::CANVAS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CanvasPattern>(); });
253     RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
254     geometryNode->SetContentSize(SizeF(100.0f, 100.0f));
255     geometryNode->SetContentOffset(OffsetF(0.0f, 0.0f));
256     auto pattern = frameNode->GetPattern<CanvasPattern>();
257 
258     RefPtr<CanvasLayoutAlgorithm> canvasLayoutAlgorithm = AceType::MakeRefPtr<CanvasLayoutAlgorithm>();
259     LayoutConstraintF layoutConstraint;
260     LayoutWrapperNode layoutWrapper = LayoutWrapperNode(frameNode, geometryNode, frameNode->GetLayoutProperty());
261 
262     /**
263      * @tc.steps: step1. IsValid() == false;
264      */
265     layoutConstraint.maxSize.SetWidth(1000.0f);
266     layoutConstraint.maxSize.SetHeight(1000.0f);
267     canvasLayoutAlgorithm->MeasureContent(layoutConstraint, &layoutWrapper);
268     EXPECT_EQ(pattern->canvasSize_->width_, 1000.0f);
269     EXPECT_EQ(pattern->canvasSize_->height_, 1000.0f);
270 
271     /**
272      * @tc.steps: step1. IsValid() == true;
273      */
274     layoutConstraint.selfIdealSize.SetWidth(960.0f);
275     layoutConstraint.selfIdealSize.SetHeight(960.0f);
276     canvasLayoutAlgorithm->MeasureContent(layoutConstraint, &layoutWrapper);
277     EXPECT_EQ(pattern->canvasSize_->width_, 960.0f);
278     EXPECT_EQ(pattern->canvasSize_->height_, 960.0f);
279 }
280 
281 /**
282  * @tc.name: CanvasPatternTest006
283  * @tc.desc: GetQuality
284  * @tc.type: FUNC
285  */
286 HWTEST_F(CanvasTestNg, CanvasPatternTest006, TestSize.Level1)
287 {
288     double dRet = 0.0;
289     std::string strRet = "";
290 
291     /**
292      * @tc.steps: step1. GetQuality:type != IMAGE_JPEG && type != IMAGE_WEBP, quality > 0.0 || quality < 1.0
293      */
294     dRet = GetQuality("", 0.8);
295     EXPECT_EQ(dRet, DEFAULT_QUALITY * QUALITY_COEFFICIENT);
296 
297     /**
298      * @tc.steps: step2. GetQuality:type != IMAGE_JPEG && type != IMAGE_WEBP, quality > 0.0 || quality < 1.0
299      */
300     dRet = GetQuality(IMAGE_PNG, 0.8);
301     EXPECT_EQ(dRet, DEFAULT_QUALITY * QUALITY_COEFFICIENT);
302 
303     /**
304      * @tc.steps: step4. GetQuality:mimeType == IMAGE_JPEG, quality > 0.0 || quality < 1.0
305      */
306     dRet = GetQuality(IMAGE_JPEG, 0.8);
307     EXPECT_EQ(dRet, 0.8 * QUALITY_COEFFICIENT);
308 
309     /**
310      * @tc.steps: step5. GetQuality:mimeType == IMAGE_WEBP, quality > 0.0 || quality < 1.0
311      */
312     dRet = GetQuality(IMAGE_WEBP, 0.8);
313     EXPECT_EQ(dRet, 0.8 * QUALITY_COEFFICIENT);
314 
315     /**
316      * @tc.steps: step6. mimeType == IMAGE_WEBP, GetQuality:quality > 1.0
317      */
318     dRet = GetQuality(IMAGE_WEBP, 1.1);
319     EXPECT_EQ(dRet, DEFAULT_QUALITY * QUALITY_COEFFICIENT);
320 
321     /**
322      * @tc.steps: step7. mimeType == IMAGE_WEBP, GetQuality:quality < 0.0
323      */
324     dRet = GetQuality(IMAGE_WEBP, -1.1);
325     EXPECT_EQ(dRet, DEFAULT_QUALITY * QUALITY_COEFFICIENT);
326 }
327 
328 /**
329  * @tc.name: CanvasPatternTest007
330  * @tc.desc: OffscreenCanvasPattern::SetTextDirection && UpdateTextDefaultDirection
331  * @tc.type: FUNC
332  */
333 HWTEST_F(CanvasTestNg, CanvasPatternTest007, TestSize.Level1)
334 {
335     auto* stack = ViewStackProcessor::GetInstance();
336     auto nodeId = stack->ClaimNodeId();
337     auto frameNode = FrameNode::GetOrCreateFrameNode(
__anonef3f1d760502() 338         V2::CANVAS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<OffscreenCanvasPattern>(100, 100); });
339     RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
340     geometryNode->SetContentSize(SizeF(100.0f, 100.0f));
341     geometryNode->SetContentOffset(OffsetF(0.0f, 0.0f));
342     auto offPattern = frameNode->GetPattern<OffscreenCanvasPattern>();
343 
344     /**
345      * @tc.steps: step1. SetTextDirection : TextDirection::AUTO;
346      */
347     offPattern->SetTextDirection(TextDirection::AUTO);
348     EXPECT_EQ(offPattern->offscreenPaintMethod_->state_.fillState.textDirection_, TextDirection::AUTO);
349     /**
350      * @tc.steps: step2. SetTextDirection : TextDirection::INHERIT;
351      */
352     offPattern->SetTextDirection(TextDirection::INHERIT);
353     EXPECT_EQ(offPattern->offscreenPaintMethod_->state_.fillState.textDirection_, TextDirection::LTR);
354     /**
355      * @tc.steps: step3. UpdateTextDefaultDirection : TextDirection::INHERIT;
356      */
357     offPattern->currentSetTextDirection_ = TextDirection::AUTO;
358     offPattern->UpdateTextDefaultDirection();
359     EXPECT_EQ(offPattern->offscreenPaintMethod_->state_.fillState.textDirection_, TextDirection::LTR);
360     /**
361      * @tc.steps: step4. UpdateTextDefaultDirection : TextDirection::INHERIT;
362      */
363     offPattern->currentSetTextDirection_ = TextDirection::INHERIT;
364     offPattern->UpdateTextDefaultDirection();
365     EXPECT_EQ(offPattern->offscreenPaintMethod_->state_.fillState.textDirection_, TextDirection::LTR);
366 }
367 
368 /**
369  * @tc.name: CanvasPatternTest008
370  * @tc.desc: CustomPaintPaintMethod::FillText && StrokeText
371  * @tc.type: FUNC
372  */
373 HWTEST_F(CanvasTestNg, CanvasPatternTest008, TestSize.Level1)
374 {
375     auto* stack = ViewStackProcessor::GetInstance();
376     auto nodeId = stack->ClaimNodeId();
377     auto frameNode = FrameNode::GetOrCreateFrameNode(
__anonef3f1d760602() 378         V2::CANVAS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<OffscreenCanvasPattern>(100, 100); });
379     RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
380     geometryNode->SetContentSize(SizeF(100.0f, 100.0f));
381     geometryNode->SetContentOffset(OffsetF(0.0f, 0.0f));
382     auto offPattern = frameNode->GetPattern<OffscreenCanvasPattern>();
383 
384     /**
385      * @tc.steps: step1. FillText : ret == false
386      */
387     offPattern->offscreenPaintMethod_->FillText("test", 0.0, 0.0, 50);
388     EXPECT_FALSE(offPattern->offscreenPaintMethod_->UpdateFillParagraph("test"));
389 
390     /**
391      * @tc.steps: step2. StrokeText : HasShadow() == false
392      */
393     Shadow shadow1 = Shadow(5.0f, Offset(0.0, 0.0), Color(0x32000000), ShadowStyle::OuterDefaultXS);
394     Shadow shadow2 = Shadow(5.0f, Offset(10.0, 10.0), Color(0x32000000), ShadowStyle::OuterDefaultXS);
395     offPattern->offscreenPaintMethod_->state_.shadow = shadow1;
396     EXPECT_FALSE(offPattern->offscreenPaintMethod_->HasShadow());
397     offPattern->offscreenPaintMethod_->StrokeText("test", 0.0, 0.0, 50);
398     /**
399      * @tc.steps: step3. StrokeText : HasShadow() == true
400      */
401     offPattern->offscreenPaintMethod_->state_.shadow = shadow2;
402     EXPECT_TRUE(offPattern->offscreenPaintMethod_->HasShadow());
403     offPattern->offscreenPaintMethod_->FillText("test", 0.0, 0.0, 50);
404 }
405 
406 } // namespace OHOS::Ace::NG
407