2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <dali-toolkit-test-suite-utils.h>
22 #include <dali-toolkit/dali-toolkit.h>
23 #include <dali-toolkit/internal/text/bidirectional-support.h>
24 #include <dali-toolkit/internal/text/character-set-conversion.h>
25 #include <dali-toolkit/internal/text/text-run-container.h>
26 #include <dali/devel-api/text-abstraction/bidirectional-support.h>
27 #include <toolkit-text-utils.h>
30 using namespace Toolkit;
33 // Tests the following functions.
35 // void SetBidirectionalInfo( const Vector<Character>& text,
36 // const Vector<ScriptRun>& scripts,
37 // const Vector<LineBreakInfo>& lineBreakInfo,
38 // CharacterIndex startIndex,
39 // Length numberOfCharacters,
40 // Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo )
41 // bool GetMirroredText( const Vector<Character>& text,
42 // Vector<CharacterDirection>& directions,
43 // const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
44 // CharacterIndex startIndex,
45 // Length numberOfCharacters,
46 // Vector<Character>& mirroredText )
47 // void GetCharactersDirection( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
48 // Length totalNumberOfCharacters,
49 // CharacterIndex startIndex,
50 // Length numberOfCharacters,
51 // Vector<CharacterDirection>& directions )
53 //////////////////////////////////////////////////////////
57 struct SetBidirectionalInfoData
59 std::string description; ///< Description of the test.
60 std::string text; ///< Input text.
61 unsigned int startIndex; ///< The index from where the model is updated.
62 unsigned int numberOfCharacters; ///< The number of characters to update.
63 unsigned int numberOfParagraphs; ///< The expected number of bidirectional paragraphs.
64 unsigned int* indices; ///< The expected indices to the first character of each paragraph.
65 unsigned int* numberOfParagraphCharacters; ///< The expected number of characters of each paragraph.
66 bool* directions; ///< The expected direction of each paragraph.
71 unsigned int characterIndex;
72 unsigned int numberOfCharacters;
73 unsigned int* visualToLogical;
76 struct GetMirroredTextData
78 std::string description; ///< Description of the test.
79 std::string text; ///< Input text.
80 unsigned int startIndex; ///< The index from where the model is updated.
81 unsigned int numberOfCharacters; ///< The number of the characters.
82 std::string mirroredText; ///< The expected result.
85 struct GetCharactersDirectionData
87 std::string description; ///< Description of the test.
88 std::string text; ///< Input text.
89 unsigned int startIndex; ///< The index from where the model is updated.
90 unsigned int numberOfCharacters; ///< The number of characters.
91 bool* directions; ///< The expected directions.
92 bool markupProcessorEnabled; ///< Enable markup processor to use markup text.
95 bool SetBidirectionalInfoTest(const SetBidirectionalInfoData& data)
97 // 1) Create the model.
100 Size textArea(100.f, 60.f);
104 const Vector<FontDescriptionRun> fontDescriptions;
105 const LayoutOptions options;
106 CreateTextModel(data.text,
116 Toolkit::DevelText::EllipsisPosition::END,
118 0.0f // characterSpacing
121 LogicalModelPtr logicalModel = textModel->mLogicalModel;
122 VisualModelPtr visualModel = textModel->mVisualModel;
124 // 2) Clear the bidirectional paragraph info data.
125 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
126 if(0u != data.numberOfCharacters)
128 ClearCharacterRuns(data.startIndex,
129 data.startIndex + data.numberOfCharacters - 1u,
133 // 3) Call the SetBidirectionalInfo() function.
134 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
136 SetBidirectionalInfo(bidirectionalSupport,
138 logicalModel->mScriptRuns,
139 logicalModel->mLineBreakInfo,
141 data.numberOfCharacters,
144 // 4) Compare with the expected results.
145 if(data.numberOfParagraphs != bidirectionalInfo.Count())
147 // Different number of expected bidirectional paragraphs.
148 std::cout << " Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
152 for(unsigned int index = 0u; index < data.numberOfParagraphs; ++index)
154 const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
156 const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection(run.bidirectionalInfoIndex);
157 if(direction != data.directions[index])
159 std::cout << " Different direction" << std::endl;
160 std::cout << " paragraph : " << index << std::endl;
161 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
162 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
166 if(run.characterRun.characterIndex != data.indices[index])
168 std::cout << " Different index" << std::endl;
169 std::cout << " paragraph : " << index << std::endl;
170 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
171 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
174 if(run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index])
176 std::cout << " Different number of characters" << std::endl;
177 std::cout << " paragraph : " << index << std::endl;
178 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
179 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
187 bool GetMirroredTextTest(const GetMirroredTextData& data)
189 // 1) Create the model.
192 Size textArea(100.f, 60.f);
196 const Vector<FontDescriptionRun> fontDescriptions;
197 const LayoutOptions options;
198 CreateTextModel(data.text,
208 Toolkit::DevelText::EllipsisPosition::END,
210 0.0f // characterSpacing
213 LogicalModelPtr logicalModel = textModel->mLogicalModel;
214 VisualModelPtr visualModel = textModel->mVisualModel;
216 // 2) Call the GetMirroredText() function for the whole text
217 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
219 Vector<Character> mirroredText;
220 bool mirrored = false;
221 mirrored = GetMirroredText(bidirectionalSupport,
223 logicalModel->mCharacterDirections,
224 logicalModel->mBidirectionalParagraphInfo,
226 logicalModel->mText.Count(),
229 // 3) Call the GetMirroredText() function for the given index + number of characters
230 mirrored = GetMirroredText(bidirectionalSupport,
232 logicalModel->mCharacterDirections,
233 logicalModel->mBidirectionalParagraphInfo,
235 data.numberOfCharacters,
238 // 4) Compare the results.
241 std::string mirroredString;
242 Utf32ToUtf8(mirroredText.Begin(),
243 mirroredText.Count(),
246 if(!mirrored && (mirroredString != data.text))
248 std::cout << " No mirrored text and mirroredString != data.text." << std::endl;
249 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
250 std::cout << " text : [" << data.text << "]" << std::endl;
254 if(mirrored && (mirroredString == data.text))
256 std::cout << " Mirrored text and mirroredString == data.text." << std::endl;
257 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
258 std::cout << " text : [" << data.text << "]" << std::endl;
262 if(mirrored && (mirroredString != data.mirroredText))
264 std::cout << " Mirrored text and mirroredString != data.mirroredText." << std::endl;
265 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
266 std::cout << " text : [" << data.mirroredText << "]" << std::endl;
273 bool GetCharactersDirectionTest(const GetCharactersDirectionData& data)
275 // 1) Create the model.
278 Size textArea(100.f, 60.f);
282 const Vector<FontDescriptionRun> fontDescriptions;
283 const LayoutOptions options;
284 CreateTextModel(data.text,
291 data.markupProcessorEnabled,
294 Toolkit::DevelText::EllipsisPosition::END,
296 0.0f // characterSpacing
299 LogicalModelPtr logicalModel = textModel->mLogicalModel;
300 VisualModelPtr visualModel = textModel->mVisualModel;
302 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
304 // 2) Clear the direction info data.
305 Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
307 if(directions.Count() >= data.startIndex + data.numberOfCharacters)
309 directions.Erase(directions.Begin() + data.startIndex,
310 directions.Begin() + data.startIndex + data.numberOfCharacters);
313 // 3) Call GetCharactersDirection() function.
314 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
316 GetCharactersDirection(bidirectionalSupport,
318 logicalModel->mText.Count(),
320 data.numberOfCharacters,
323 for(unsigned int index = 0u; index < logicalModel->mText.Count(); ++index)
325 if(data.directions[index] != directions[index])
336 //////////////////////////////////////////////////////////
338 int UtcDaliSetBidirectionalInfo(void)
340 tet_infoline(" UtcDaliSetBidirectionalInfo");
342 unsigned int indices01[] = {};
343 unsigned int numberOfCharacters01[] = {};
344 bool direction01[] = {};
345 unsigned int indices02[] = {};
346 unsigned int numberOfCharacters02[] = {};
347 bool direction02[] = {};
348 unsigned int indices03[] = {17u, 48u};
349 unsigned int numberOfCharacters03[] = {14u, 14u};
350 bool direction03[] = {true, true};
351 unsigned int indices04[] = {17u, 31u, 79u};
352 unsigned int numberOfCharacters04[] = {14u, 48u, 31u};
353 bool direction04[] = {true, false, true};
354 unsigned int indices05[] = {17u, 41u, 117u};
355 unsigned int numberOfCharacters05[] = {24u, 76u, 49u};
356 bool direction05[] = {true, false, true};
357 unsigned int indices06[] = {17u, 48u};
358 unsigned int numberOfCharacters06[] = {14u, 14u};
359 bool direction06[] = {true, true};
360 unsigned int indices07[] = {17u, 31u, 79u};
361 unsigned int numberOfCharacters07[] = {14u, 48u, 31u};
362 bool direction07[] = {true, false, true};
363 unsigned int indices08[] = {17u, 41u, 117u};
364 unsigned int numberOfCharacters08[] = {24u, 76u, 49u};
365 bool direction08[] = {true, false, true};
367 struct SetBidirectionalInfoData data[] =
375 numberOfCharacters01,
378 {"Some left to right paragraphs",
379 "Hello world\ndemo\n\n",
384 numberOfCharacters02,
387 {"A mix of left to right and right to left paragraphs.",
388 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
393 numberOfCharacters03,
396 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
397 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
402 numberOfCharacters04,
405 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts.",
406 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
411 numberOfCharacters05,
414 {"A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
415 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
420 numberOfCharacters06,
423 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
424 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
429 numberOfCharacters07,
432 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts. Updates initial paragraphs.",
433 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
438 numberOfCharacters08,
441 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts. Updates mid paragraphs.",
442 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
447 numberOfCharacters08,
450 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text and a mix of right to left scripts. Updates from character 85",
451 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
456 numberOfCharacters08,
459 const unsigned int numberOfTests = 10u;
461 for(unsigned int index = 0u; index < numberOfTests; ++index)
463 ToolkitTestApplication application;
464 if(!SetBidirectionalInfoTest(data[index]))
466 tet_result(TET_FAIL);
470 tet_result(TET_PASS);
474 int UtcDaliGetMirroredText(void)
476 tet_infoline(" UtcDaliGetMirroredText");
478 struct GetMirroredTextData data[] =
486 {"Left to right characters only.",
487 "Hello world\nhello world demo.",
490 "Hello world\nhello world demo."},
492 {"Right to left characters but with no characters to mirror.",
493 "שלום עולם\nمرحبا بالعالم",
496 "שלום עולם\nمرحبا بالعالم"},
498 {"Right to left characters with some characters to mirror.",
499 "שלום עולם\n(مرحبا بالعالم)",
502 "שלום עולם\n)مرحبا بالعالم("},
504 {"Right to left characters with some characters to mirror. Update last paragraph.",
505 "שלום עולם\n(مرحبا بالعالم)",
508 "שלום עולם\n)مرحبا بالعالم("},
510 {"Mix of bidirectional text. With more paragraphs.",
511 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
512 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
515 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
516 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום )hello( world demo )עולם(\nשלום )مرحبا بالعالم עולם( )hello("},
518 {"Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
519 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
520 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
523 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
524 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"},
526 {"Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
527 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
528 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
531 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
532 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"},
534 const unsigned int numberOfTests = 8u;
536 for(unsigned int index = 0u; index < numberOfTests; ++index)
538 ToolkitTestApplication application;
539 if(!GetMirroredTextTest(data[index]))
541 tet_result(TET_FAIL);
545 tet_result(TET_PASS);
549 int UtcDaliGetCharactersDirection(void)
551 tet_infoline(" UtcDaliGetCharactersDirection");
553 bool directions01[] = {};
554 bool directions02[] = {
555 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
556 bool directions03[] = {
557 true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true};
558 bool directions04[] = {
559 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false};
560 bool directions05[] = {
561 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false};
563 bool directions06[] = {
564 true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
566 struct GetCharactersDirectionData data[] =
575 {"Left to right characters only",
576 "Hello world\nhello world demo",
582 {"Right to left characters only",
583 "שלום עולם\nשלום עולם",
589 {"Mix of bidirectional text",
590 "Hello world\nhello world שלום עולם\nשלום עולם hello world",
596 {"Mix of bidirectional text. With more paragraphs.",
597 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
598 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
604 {"Mix of bidirectional text. With more paragraphs. Update first paragraph.",
605 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
606 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
612 {"Mix of bidirectional text. With more paragraphs. Update from character 29",
613 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
614 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
620 {"Mix of bidirectional text. With more paragraphs. Update from character 163",
621 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
622 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
628 {"Mix of bidirectional text. With brackets and LRM",
629 "שלום עולם ‎(hello)[world]‎",
635 const unsigned int numberOfTests = 9u;
637 for(unsigned int index = 0u; index < numberOfTests; ++index)
639 ToolkitTestApplication application;
640 if(!GetCharactersDirectionTest(data[index]))
642 tet_result(TET_FAIL);
646 tet_result(TET_PASS);