• 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 #include <cstdint>
17 #include <iostream>
18 #include <ostream>
19 #include <vector>
20 
21 #include "test/mock/core/common/mock_theme_manager.h"
22 #include "test/mock/core/pipeline/mock_pipeline_context.h"
23 #include "test/mock/core/render/mock_paragraph.h"
24 
25 #include "base/geometry/dimension.h"
26 #include "base/geometry/size.h"
27 #include "base/memory/ace_type.h"
28 #include "base/memory/referenced.h"
29 #include "core/components/common/properties/color.h"
30 #include "core/components/common/properties/text_style.h"
31 #include "core/components/text/text_theme.h"
32 #include "html_to_span.h"
33 #include "span_to_html.h"
34 #include "core/components_ng/pattern/text/span/mutable_span_string.h"
35 #include "core/components_ng/pattern/text/span/span_object.h"
36 #include "core/components_ng/pattern/text/span/span_string.h"
37 #include "core/components_ng/pattern/text/span_node.h"
38 #include "core/components_ng/pattern/text/text_pattern.h"
39 #include "core/components_ng/pattern/text/text_styles.h"
40 #include "core/components_ng/property/measure_property.h"
41 
42 #undef private
43 #undef protected
44 
45 using namespace testing;
46 using namespace testing::ext;
47 namespace OHOS::Ace::NG {
48 class HtmlConvertTestNg : public testing::Test {
49 public:
50     static void SetUpTestSuite();
51     static void TearDownTestSuite();
52     void SetUp() override;
53     void TearDown() override;
54     bool IsSpanItemSame(std::list<RefPtr<NG::SpanItem>> src, std::list<RefPtr<NG::SpanItem>> other);
55     SpanParagraphStyle GetDefaultParagraphStyle();
56     ImageSpanOptions GetImageOption(const std::string& src);
57 };
58 
SetUpTestSuite()59 void HtmlConvertTestNg::SetUpTestSuite()
60 {
61     MockPipelineContext::SetUp();
62 }
63 
TearDownTestSuite()64 void HtmlConvertTestNg::TearDownTestSuite()
65 {
66     MockPipelineContext::TearDown();
67 }
68 
SetUp()69 void HtmlConvertTestNg::SetUp() {}
70 
TearDown()71 void HtmlConvertTestNg::TearDown() {}
72 
73 std::string test_str[] = { "hello", "world", "this", "find", "gank", "pink", "that", "when", "how", "cpp" };
74 Font testFont1 { OHOS::Ace::FontWeight::BOLD, Dimension(29.0, DimensionUnit::PX), OHOS::Ace::FontStyle::ITALIC,
75     std::vector<std::string>(test_str, test_str + 10), OHOS::Ace::Color::BLUE };
76 Font testFont2 { OHOS::Ace::FontWeight::LIGHTER, Dimension(19.0, DimensionUnit::PX), OHOS::Ace::FontStyle::ITALIC,
77     std::vector<std::string>(test_str, test_str + 10), OHOS::Ace::Color::GRAY };
78 Font testEmptyFont {};
GetImageOption(const std::string & src)79 ImageSpanOptions HtmlConvertTestNg::GetImageOption(const std::string& src)
80 {
81     ImageSpanSize size { .width = 50.0_vp, .height = 50.0_vp };
82     BorderRadiusProperty borderRadius;
83     borderRadius.SetRadius(2.0_vp);
84     MarginProperty margins;
85     // margins len 10.0
86     margins.SetEdges(CalcLength(10.0));
87     PaddingProperty paddings;
88     // paddings len 5.0
89     paddings.SetEdges(CalcLength(5.0));
90     ImageSpanAttribute attr { .size = size,
91         .paddingProp = paddings,
92         .marginProp = margins,
93         .borderRadius = borderRadius,
94         .objectFit = ImageFit::COVER,
95         .verticalAlign = VerticalAlign::BOTTOM };
96     ImageSpanOptions option { .image = src, .imageAttribute = attr };
97     return option;
98 }
99 
GetDefaultParagraphStyle()100 SpanParagraphStyle HtmlConvertTestNg::GetDefaultParagraphStyle()
101 {
102     SpanParagraphStyle spanParagraphStyle;
103     spanParagraphStyle.align = TextAlign::END;
104     // default max lines 4
105     spanParagraphStyle.maxLines = 4;
106     spanParagraphStyle.wordBreak = WordBreak::BREAK_ALL;
107     spanParagraphStyle.textOverflow = TextOverflow::ELLIPSIS;
108     // defalut textIndent 23
109     spanParagraphStyle.textIndent = Dimension(23.0_vp);
110     spanParagraphStyle.leadingMargin = LeadingMargin();
111     // default width 25.0 height 26.0
112     spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(25.0_vp), Dimension(26.0));
113     return spanParagraphStyle;
114 }
115 
IsSpanItemSame(std::list<RefPtr<NG::SpanItem>> src,std::list<RefPtr<NG::SpanItem>> other)116 bool HtmlConvertTestNg::IsSpanItemSame(std::list<RefPtr<NG::SpanItem>> src, std::list<RefPtr<NG::SpanItem>> other)
117 {
118     if (src.size() != other.size()) {
119         return false;
120     }
121 
122     while (src.size() != 0) {
123         auto it = src.front();
124         auto otherIt = other.front();
125         if (it->interval.first != otherIt->interval.first || it->interval.second != otherIt->interval.second ||
126             it->content != otherIt->content) {
127             return false;
128         }
129         src.pop_front();
130         other.pop_front();
131     }
132     return true;
133 }
134 
135 HWTEST_F(HtmlConvertTestNg, HtmlConvert000, TestSize.Level1)
136 {
137     auto imageOption = GetImageOption("src/icon-1.png");
138     auto mutableStr = AceType::MakeRefPtr<MutableSpanString>(imageOption);
139     auto spanString3 = AceType::MakeRefPtr<SpanString>("012345678\n9");
140     spanString3->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3));
141     spanString3->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5));
142     spanString3->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8));
143 
144     spanString3->AddSpan(AceType::MakeRefPtr<BaselineOffsetSpan>(Dimension(4), 0, 2));
145     spanString3->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(5), 5, 8));
146     spanString3->AddSpan(AceType::MakeRefPtr<DecorationSpan>(
147         TextDecoration::LINE_THROUGH, Color::BLUE, TextDecorationStyle::WAVY, 0, 1));
148 
149     auto spanParagraphStyle = GetDefaultParagraphStyle();
150     auto paraSpan = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 2, 5);
151 
152     spanString3->AddSpan(paraSpan);
153     Shadow textShadow;
154     textShadow.SetBlurRadius(0.0);
155     textShadow.SetColor(Color::BLUE);
156     textShadow.SetOffsetX(5.0);
157     textShadow.SetOffsetY(5.0);
158 
159     Shadow textShadow1;
160     textShadow1.SetBlurRadius(1.0);
161     textShadow1.SetColor(Color::BLUE);
162     textShadow1.SetOffsetX(10.0);
163     textShadow1.SetOffsetY(10.0);
164 
165     vector<Shadow> textShadows { textShadow, textShadow1 };
166     spanString3->AddSpan(AceType::MakeRefPtr<TextShadowSpan>(textShadows, 3, 6));
167     mutableStr->InsertSpanString(1, spanString3);
168 
169     auto spanString2 = AceType::MakeRefPtr<SpanString>("测试一下中文,\n看看是什么情况");
170     spanString2->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 5));
171     spanString2->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 6, 10));
172     spanString2->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(10), 12, 14));
173 
174     mutableStr->InsertSpanString(5, spanString2);
175     SpanToHtml convert;
176     auto out = convert.ToHtml(*mutableStr);
177     HtmlToSpan toSpan;
178     auto dstSpan = toSpan.ToSpanString(out);
179     EXPECT_NE(dstSpan, nullptr);
180     auto items = dstSpan->GetSpanItems();
181     EXPECT_EQ(items.size(), 17);
182 }
183 
184 HWTEST_F(HtmlConvertTestNg, HtmlConvert001, TestSize.Level1)
185 {
186     auto spanString = AceType::MakeRefPtr<SpanString>("0123456789");
187     spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3));
188     spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5));
189     spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8));
190 
191     std::vector<uint8_t> buffer;
192     spanString->EncodeTlv(buffer);
193     SpanToHtml convert;
194     auto u8ToHtml = convert.ToHtml(buffer);
195     EXPECT_NE(u8ToHtml.empty(), true);
196 
197     auto out = convert.ToHtml(*spanString);
198     EXPECT_NE(out.empty(), true);
199     EXPECT_EQ(out, u8ToHtml);
200 
201     HtmlToSpan toSpan;
202     auto dstSpan = toSpan.ToSpanString(out);
203     EXPECT_NE(dstSpan, nullptr);
204     auto items = dstSpan->GetSpanItems();
205     EXPECT_EQ(items.size(), 4);
206 
207     EXPECT_EQ(items.size(), spanString->GetSpanItems().size());
208 }
209 
210 HWTEST_F(HtmlConvertTestNg, HtmlConvert002, TestSize.Level1)
211 {
212     auto imageOption = GetImageOption("src/icon-1.png");
213     auto imageSpan = AceType::MakeRefPtr<MutableSpanString>("123456");
214 
215     std::vector<uint8_t> buffer;
216     imageSpan->EncodeTlv(buffer);
217 
218     SpanToHtml convert;
219     auto u8ToHtml = convert.ToHtml(buffer);
220     EXPECT_NE(u8ToHtml.empty(), true);
221 
222     auto out = convert.ToHtml(*imageSpan);
223     EXPECT_NE(out.empty(), true);
224     EXPECT_EQ(out, u8ToHtml);
225 
226     HtmlToSpan toSpan;
227     auto dstSpan = toSpan.ToSpanString(out);
228     EXPECT_NE(dstSpan, nullptr);
229 
230     auto dstHtml = convert.ToHtml(*dstSpan);
231     EXPECT_EQ(out, dstHtml);
232 
233     // image is invalid,to html discart image the first char is not black space
234     EXPECT_EQ(dstSpan->GetString(), "123456");
235     auto spans = dstSpan->GetSpans(0, 6);
236     EXPECT_EQ(spans.size(), 1);
237 }
238 
239 HWTEST_F(HtmlConvertTestNg, HtmlConvert003, TestSize.Level1)
240 {
241     const std::string fontHtml = "<!DOCTYPE html>"
242                                  "<html>"
243                                  "<body>"
244                                  "<p>我是正常的</p>"
245                                  "<p style=\"COLOR:red;\">我是红色的</p>"
246                                  "<p style=\"font-family: 'Times New Roman', serif; font-size: 14px; font-weight: "
247                                  "normal; color: red; color: blue;\">我是蓝色的<strong style=\"color:blue; "
248                                  "font-size:100px;\">这段文字很重要!</strong><del>蓝色</del></p>"
249                                  "<p style=\"font-size:50px;\">我是50的</p>"
250                                  "</body>"
251                                  "</html>";
252     HtmlToSpan toSpan;
253     auto dstSpan = toSpan.ToSpanString(fontHtml);
254     EXPECT_NE(dstSpan, nullptr);
255 
256     SpanToHtml convert;
257     auto dstHtml = convert.ToHtml(*dstSpan);
258     HtmlToSpan toSpan1;
259     auto dstSpan1 = toSpan1.ToSpanString(dstHtml);
260     EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), dstSpan1->GetSpanItems()), true);
261     auto secondHtml = convert.ToHtml(*dstSpan1);
262     EXPECT_EQ(secondHtml, dstHtml);
263 }
264 
265 HWTEST_F(HtmlConvertTestNg, SpanString004, TestSize.Level1)
266 {
267     auto spanString = AceType::MakeRefPtr<SpanString>("01234中文56789");
268     std::vector<uint8_t> buff;
269     spanString->EncodeTlv(buff);
270     EXPECT_EQ(buff.size() > 0, true);
271     SpanToHtml toHtml;
272     auto htmlFromU8 = toHtml.ToHtml(buff);
273     auto htmlFromSpan = toHtml.ToHtml(*spanString);
274     EXPECT_EQ(htmlFromU8, htmlFromSpan);
275 
276     HtmlToSpan toSpan;
277     auto spanFromHtml = toSpan.ToSpanString(htmlFromU8);
278     EXPECT_EQ(IsSpanItemSame(spanFromHtml->GetSpanItems(), spanString->GetSpanItems()), true);
279 
280     SpanToHtml toHtml1;
281     auto hmtlString = toHtml1.ToHtml(*spanFromHtml);
282     EXPECT_EQ(hmtlString, htmlFromSpan);
283 }
284 
285 HWTEST_F(HtmlConvertTestNg, HtmlConvert005, TestSize.Level1)
286 {
287     auto spanString = AceType::MakeRefPtr<SpanString>("0123456789");
288     spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3));
289     spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5));
290     spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8));
291     spanString->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(5), 5, 8));
292     spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>(
293         TextDecoration::LINE_THROUGH, Color::BLUE, TextDecorationStyle::WAVY, 0, 1));
294 
295     SpanToHtml convert;
296     auto out = convert.ToHtml(*spanString);
297     HtmlToSpan toSpan;
298     auto dstSpan = toSpan.ToSpanString(out);
299     EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), spanString->GetSpanItems()), true);
300 }
301 HWTEST_F(HtmlConvertTestNg, HtmlConvert006, TestSize.Level1)
302 {
303     const std::string multiHtml = "<html>"
304                                   "<body>"
305                                   "<p style=\"color:red;\">dddd当地经的123456</p>"
306                                   "</body>"
307                                   "</html>";
308     HtmlToSpan toSpan;
309     auto dstSpan = toSpan.ToSpanString(multiHtml);
310     std::list<RefPtr<NG::SpanItem>> spans = dstSpan->GetSpanItems();
311     EXPECT_EQ(spans.size(), 1);
312     auto it = spans.begin();
313     EXPECT_EQ((*it)->fontStyle->GetTextColor().value(), OHOS::Ace::Color::RED);
314 }
315 
316 HWTEST_F(HtmlConvertTestNg, HtmlConvert007, TestSize.Level1)
317 {
318     const std::string multiHtml = "<html>"
319                                   "<body>"
320                                   "<p style=\"font-size:50px\">dddd当地经的123456</p>"
321                                   "</body>"
322                                   "</html>";
323     HtmlToSpan toSpan;
324     auto dstSpan = toSpan.ToSpanString(multiHtml);
325     std::list<RefPtr<NG::SpanItem>> spans = dstSpan->GetSpanItems();
326     EXPECT_EQ(spans.size(), 1);
327     auto it = spans.begin();
328     EXPECT_EQ((*it)->fontStyle->GetFontSize().value(), Dimension(50, DimensionUnit::VP));
329 }
330 
331 HWTEST_F(HtmlConvertTestNg, HtmlConvert008, TestSize.Level1)
332 {
333     auto spanString = AceType::MakeRefPtr<SpanString>("段落标题\n正文第一段开始");
334     SpanParagraphStyle spanParagraphStyle;
335     spanParagraphStyle.align = TextAlign::CENTER;
336     // default max lines 4
337     spanParagraphStyle.maxLines = 4;
338     spanParagraphStyle.wordBreak = WordBreak::BREAK_ALL;
339     spanParagraphStyle.textOverflow = TextOverflow::ELLIPSIS;
340     // defalut textIndent 23
341     spanParagraphStyle.textIndent = Dimension(23.0_vp);
342     spanParagraphStyle.leadingMargin = LeadingMargin();
343     // default width 25.0 height 26.0
344     spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(25.0_vp), Dimension(26.0));
345     auto paragraphStyle = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 0, 5);
346     spanString->AddSpan(paragraphStyle);
347 
348     SpanToHtml convert;
349     auto out = convert.ToHtml(*spanString);
350     std::string result =
351         "<div ><p style=\"text-align: center;text-indent: 23.00px;word-break: break_all;text-overflow: ellipsis;\">"
352         "<span style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: #000000FF;font-family: "
353         "HarmonyOS Sans;\">段落标题</span></p><span style=\"font-size: 16.00px;font-style: normal;font-weight: "
354         "normal;color: #000000FF;font-family: HarmonyOS Sans;\">正文第一段开始</span></div>";
355     EXPECT_EQ(out, result);
356 }
357 
358 HWTEST_F(HtmlConvertTestNg, HtmlConvert009, TestSize.Level1)
359 {
360     auto spanString = AceType::MakeRefPtr<SpanString>("向上到顶适中向下到底");
361     spanString->AddSpan(AceType::MakeRefPtr<BaselineOffsetSpan>(Dimension(20.0_vp), 0, 4));
362     spanString->AddSpan(AceType::MakeRefPtr<BaselineOffsetSpan>(Dimension(10.0_vp), 4, 6));
363 
364     SpanToHtml convert;
365     auto out = convert.ToHtml(*spanString);
366     std::string result =
367         "<div ><span style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: #000000FF;font-family: "
368         "HarmonyOS Sans;vertical-align: 20.00px;\">向上到顶</span><span style=\"font-size: 16.00px;font-style: "
369         "normal;font-weight: normal;color: #000000FF;font-family: HarmonyOS Sans;vertical-align: "
370         "10.00px;\">适中</span><span style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: "
371         "#000000FF;font-family: HarmonyOS Sans;\">向下到底</span></div>";
372     EXPECT_EQ(out, result);
373 }
374 
375 HWTEST_F(HtmlConvertTestNg, HtmlConvert010, TestSize.Level1)
376 {
377     const std::string multiHtml =
378         "<html>"
379         "<body>"
380         "<p style=\"font-size:50px\"><span style=\"font-size:100px\">100fontsize</span>dddd当地经的123456<span "
381         "style=\"font-size:30px\">30fontsize</span>1232132</p>"
382         "</body>"
383         "</html>";
384     HtmlToSpan toSpan;
385     auto dstSpan = toSpan.ToSpanString(multiHtml);
386     std::list<RefPtr<NG::SpanItem>> spans = dstSpan->GetSpanItems();
387     EXPECT_EQ(spans.size(), 4);
388 
389     SpanToHtml convert;
390     auto dstHtml = convert.ToHtml(*dstSpan);
391     HtmlToSpan toSpan1;
392     auto dstSpan1 = toSpan1.ToSpanString(dstHtml);
393     EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), dstSpan1->GetSpanItems()), true);
394     auto secondHtml = convert.ToHtml(*dstSpan1);
395     EXPECT_EQ(secondHtml, dstHtml);
396 }
397 
398 HWTEST_F(HtmlConvertTestNg, HtmlConvert011, TestSize.Level1)
399 {
400     const std::string multiHtml =
401         "<html>"
402         "<head>"
403         "</head>"
404         "<body>"
405         "<p style=\"font-size:50px;text-shadow: 0 0 3px red, green 0 0;\">"
406         "<span style=\"font-size:100px\">100fontsize</span>dddd当地经的123456<span "
407         "style=\"font-size:30px\">30fontsize</span>1232132</p>"
408         "</body>"
409         "</html>";
410     HtmlToSpan toSpan;
411     auto dstSpan = toSpan.ToSpanString(multiHtml);
412     std::list<RefPtr<NG::SpanItem>> spans = dstSpan->GetSpanItems();
413     EXPECT_EQ(spans.size(), 4);
414     auto it = spans.begin();
415     EXPECT_EQ((*it)->fontStyle->GetTextShadow().value()[0].GetColor(), OHOS::Ace::Color::RED);
416     EXPECT_EQ((*it)->fontStyle->GetTextShadow().value()[1].GetColor(), OHOS::Ace::Color::GREEN);
417 }
418 } // namespace OHOS::Ace::NG