2 * Copyright (c) 2022 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 SetBidirectionalInfo(logicalModel->mText,
135 logicalModel->mScriptRuns,
136 logicalModel->mLineBreakInfo,
138 data.numberOfCharacters,
141 // 4) Compare with the expected results.
142 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
144 if(data.numberOfParagraphs != bidirectionalInfo.Count())
146 // Different number of expected bidirectional paragraphs.
147 std::cout << " Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
151 for(unsigned int index = 0u; index < data.numberOfParagraphs; ++index)
153 const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
155 const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection(run.bidirectionalInfoIndex);
156 if(direction != data.directions[index])
158 std::cout << " Different direction" << std::endl;
159 std::cout << " paragraph : " << index << std::endl;
160 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
161 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
165 if(run.characterRun.characterIndex != data.indices[index])
167 std::cout << " Different index" << std::endl;
168 std::cout << " paragraph : " << index << std::endl;
169 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
170 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
173 if(run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index])
175 std::cout << " Different number of characters" << std::endl;
176 std::cout << " paragraph : " << index << std::endl;
177 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
178 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
186 bool GetMirroredTextTest(const GetMirroredTextData& data)
188 // 1) Create the model.
191 Size textArea(100.f, 60.f);
195 const Vector<FontDescriptionRun> fontDescriptions;
196 const LayoutOptions options;
197 CreateTextModel(data.text,
207 Toolkit::DevelText::EllipsisPosition::END,
209 0.0f // characterSpacing
212 LogicalModelPtr logicalModel = textModel->mLogicalModel;
213 VisualModelPtr visualModel = textModel->mVisualModel;
215 // 2) Call the GetMirroredText() function for the whole text
216 Vector<Character> mirroredText;
217 bool mirrored = false;
218 mirrored = GetMirroredText(logicalModel->mText,
219 logicalModel->mCharacterDirections,
220 logicalModel->mBidirectionalParagraphInfo,
222 logicalModel->mText.Count(),
225 // 3) Call the GetMirroredText() function for the given index + number of characters
226 mirrored = GetMirroredText(logicalModel->mText,
227 logicalModel->mCharacterDirections,
228 logicalModel->mBidirectionalParagraphInfo,
230 data.numberOfCharacters,
233 // 4) Compare the results.
236 std::string mirroredString;
237 Utf32ToUtf8(mirroredText.Begin(),
238 mirroredText.Count(),
241 if(!mirrored && (mirroredString != data.text))
243 std::cout << " No mirrored text and mirroredString != data.text." << std::endl;
244 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
245 std::cout << " text : [" << data.text << "]" << std::endl;
249 if(mirrored && (mirroredString == data.text))
251 std::cout << " Mirrored text and mirroredString == data.text." << std::endl;
252 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
253 std::cout << " text : [" << data.text << "]" << std::endl;
257 if(mirrored && (mirroredString != data.mirroredText))
259 std::cout << " Mirrored text and mirroredString != data.mirroredText." << std::endl;
260 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
261 std::cout << " text : [" << data.mirroredText << "]" << std::endl;
268 bool GetCharactersDirectionTest(const GetCharactersDirectionData& data)
270 // 1) Create the model.
273 Size textArea(100.f, 60.f);
277 const Vector<FontDescriptionRun> fontDescriptions;
278 const LayoutOptions options;
279 CreateTextModel(data.text,
286 data.markupProcessorEnabled,
289 Toolkit::DevelText::EllipsisPosition::END,
291 0.0f // characterSpacing
294 LogicalModelPtr logicalModel = textModel->mLogicalModel;
295 VisualModelPtr visualModel = textModel->mVisualModel;
297 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
299 // 2) Clear the direction info data.
300 Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
302 if(directions.Count() >= data.startIndex + data.numberOfCharacters)
304 directions.Erase(directions.Begin() + data.startIndex,
305 directions.Begin() + data.startIndex + data.numberOfCharacters);
308 // 3) Call GetCharactersDirection() function.
310 GetCharactersDirection(bidirectionalInfo,
311 logicalModel->mText.Count(),
313 data.numberOfCharacters,
316 for(unsigned int index = 0u; index < logicalModel->mText.Count(); ++index)
318 if(data.directions[index] != directions[index])
329 //////////////////////////////////////////////////////////
331 int UtcDaliSetBidirectionalInfo(void)
333 tet_infoline(" UtcDaliSetBidirectionalInfo");
335 unsigned int indices01[] = {};
336 unsigned int numberOfCharacters01[] = {};
337 bool direction01[] = {};
338 unsigned int indices02[] = {};
339 unsigned int numberOfCharacters02[] = {};
340 bool direction02[] = {};
341 unsigned int indices03[] = {17u, 48u};
342 unsigned int numberOfCharacters03[] = {14u, 14u};
343 bool direction03[] = {true, true};
344 unsigned int indices04[] = {17u, 31u, 79u};
345 unsigned int numberOfCharacters04[] = {14u, 48u, 31u};
346 bool direction04[] = {true, false, true};
347 unsigned int indices05[] = {17u, 41u, 117u};
348 unsigned int numberOfCharacters05[] = {24u, 76u, 49u};
349 bool direction05[] = {true, false, true};
350 unsigned int indices06[] = {17u, 48u};
351 unsigned int numberOfCharacters06[] = {14u, 14u};
352 bool direction06[] = {true, true};
353 unsigned int indices07[] = {17u, 31u, 79u};
354 unsigned int numberOfCharacters07[] = {14u, 48u, 31u};
355 bool direction07[] = {true, false, true};
356 unsigned int indices08[] = {17u, 41u, 117u};
357 unsigned int numberOfCharacters08[] = {24u, 76u, 49u};
358 bool direction08[] = {true, false, true};
360 struct SetBidirectionalInfoData data[] =
368 numberOfCharacters01,
371 {"Some left to right paragraphs",
372 "Hello world\ndemo\n\n",
377 numberOfCharacters02,
380 {"A mix of left to right and right to left paragraphs.",
381 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
386 numberOfCharacters03,
389 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
390 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
395 numberOfCharacters04,
398 {"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.",
399 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
404 numberOfCharacters05,
407 {"A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
408 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
413 numberOfCharacters06,
416 {"A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
417 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
422 numberOfCharacters07,
425 {"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.",
426 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
431 numberOfCharacters08,
434 {"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.",
435 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
440 numberOfCharacters08,
443 {"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",
444 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
449 numberOfCharacters08,
452 const unsigned int numberOfTests = 10u;
454 for(unsigned int index = 0u; index < numberOfTests; ++index)
456 ToolkitTestApplication application;
457 if(!SetBidirectionalInfoTest(data[index]))
459 tet_result(TET_FAIL);
463 tet_result(TET_PASS);
467 int UtcDaliGetMirroredText(void)
469 tet_infoline(" UtcDaliGetMirroredText");
471 struct GetMirroredTextData data[] =
479 {"Left to right characters only.",
480 "Hello world\nhello world demo.",
483 "Hello world\nhello world demo."},
485 {"Right to left characters but with no characters to mirror.",
486 "שלום עולם\nمرحبا بالعالم",
489 "שלום עולם\nمرحبا بالعالم"},
491 {"Right to left characters with some characters to mirror.",
492 "שלום עולם\n(مرحبا بالعالم)",
495 "שלום עולם\n)مرحبا بالعالم("},
497 {"Right to left characters with some characters to mirror. Update last paragraph.",
498 "שלום עולם\n(مرحبا بالعالم)",
501 "שלום עולם\n)مرحبا بالعالم("},
503 {"Mix of bidirectional text. With more paragraphs.",
504 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
505 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
508 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
509 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום )hello) world demo )עולם(\nשלום )مرحبا بالعالم עולם( )hello("},
511 {"Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
512 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
513 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
516 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
517 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"},
519 {"Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
520 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
521 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
524 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
525 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"},
527 const unsigned int numberOfTests = 8u;
529 for(unsigned int index = 0u; index < numberOfTests; ++index)
531 ToolkitTestApplication application;
532 if(!GetMirroredTextTest(data[index]))
534 tet_result(TET_FAIL);
538 tet_result(TET_PASS);
542 int UtcDaliGetCharactersDirection(void)
544 tet_infoline(" UtcDaliGetCharactersDirection");
546 bool directions01[] = {};
547 bool directions02[] = {
548 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};
549 bool directions03[] = {
550 true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true};
551 bool directions04[] = {
552 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};
553 bool directions05[] = {
554 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};
556 bool directions06[] = {
557 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};
559 struct GetCharactersDirectionData data[] =
568 {"Left to right characters only",
569 "Hello world\nhello world demo",
575 {"Right to left characters only",
576 "שלום עולם\nשלום עולם",
582 {"Mix of bidirectional text",
583 "Hello world\nhello world שלום עולם\nשלום עולם hello world",
589 {"Mix of bidirectional text. With more paragraphs.",
590 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
591 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
597 {"Mix of bidirectional text. With more paragraphs. Update first paragraph.",
598 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
599 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
605 {"Mix of bidirectional text. With more paragraphs. Update from character 29",
606 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
607 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
613 {"Mix of bidirectional text. With more paragraphs. Update from character 163",
614 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
615 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
621 {"Mix of bidirectional text. With brackets and LRM",
622 "שלום עולם ‎(hello)[world]‎",
628 const unsigned int numberOfTests = 9u;
630 for(unsigned int index = 0u; index < numberOfTests; ++index)
632 ToolkitTestApplication application;
633 if(!GetCharactersDirectionTest(data[index]))
635 tet_result(TET_FAIL);
639 tet_result(TET_PASS);