2 * Copyright (c) 2021 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/devel-api/text-abstraction/bidirectional-support.h>
22 #include <dali-toolkit/internal/text/bidirectional-support.h>
23 #include <dali-toolkit/internal/text/character-set-conversion.h>
24 #include <dali-toolkit/internal/text/text-run-container.h>
25 #include <dali-toolkit-test-suite-utils.h>
26 #include <dali-toolkit/dali-toolkit.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 //////////////////////////////////////////////////////////
58 struct SetBidirectionalInfoData
60 std::string description; ///< Description of the test.
61 std::string text; ///< Input text.
62 unsigned int startIndex; ///< The index from where the model is updated.
63 unsigned int numberOfCharacters; ///< The number of characters to update.
64 unsigned int numberOfParagraphs; ///< The expected number of bidirectional paragraphs.
65 unsigned int* indices; ///< The expected indices to the first character of each paragraph.
66 unsigned int* numberOfParagraphCharacters; ///< The expected number of characters of each paragraph.
67 bool* directions; ///< The expected direction of each paragraph.
72 unsigned int characterIndex;
73 unsigned int numberOfCharacters;
74 unsigned int* visualToLogical;
77 struct GetMirroredTextData
79 std::string description; ///< Description of the test.
80 std::string text; ///< Input text.
81 unsigned int startIndex; ///< The index from where the model is updated.
82 unsigned int numberOfCharacters; ///< The number of the characters.
83 std::string mirroredText; ///< The expected result.
86 struct GetCharactersDirectionData
88 std::string description; ///< Description of the test.
89 std::string text; ///< Input text.
90 unsigned int startIndex; ///< The index from where the model is updated.
91 unsigned int numberOfCharacters; ///< The number of characters.
92 bool* directions; ///< The expected directions.
93 bool markupProcessorEnabled; ///< Enable markup processor to use markup text.
96 bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
98 // 1) Create the model.
101 Size textArea(100.f, 60.f);
105 const Vector<FontDescriptionRun> fontDescriptions;
106 const LayoutOptions options;
107 CreateTextModel( data.text,
117 LogicalModelPtr logicalModel = textModel->mLogicalModel;
118 VisualModelPtr visualModel = textModel->mVisualModel;
120 // 2) Clear the bidirectional paragraph info data.
121 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
122 if( 0u != data.numberOfCharacters )
124 ClearCharacterRuns( data.startIndex,
125 data.startIndex + data.numberOfCharacters - 1u,
129 // 3) Call the SetBidirectionalInfo() function.
130 SetBidirectionalInfo( logicalModel->mText,
131 logicalModel->mScriptRuns,
132 logicalModel->mLineBreakInfo,
134 data.numberOfCharacters,
137 // 4) Compare with the expected results.
138 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
140 if( data.numberOfParagraphs != bidirectionalInfo.Count() )
142 // Different number of expected bidirectional paragraphs.
143 std::cout << " Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
147 for( unsigned int index = 0u; index < data.numberOfParagraphs; ++index )
149 const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
151 const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( run.bidirectionalInfoIndex );
152 if( direction != data.directions[index] )
154 std::cout << " Different direction" << std::endl;
155 std::cout << " paragraph : " << index << std::endl;
156 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
157 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
161 if( run.characterRun.characterIndex != data.indices[index] )
163 std::cout << " Different index" << std::endl;
164 std::cout << " paragraph : " << index << std::endl;
165 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
166 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
169 if( run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index] )
171 std::cout << " Different number of characters" << std::endl;
172 std::cout << " paragraph : " << index << std::endl;
173 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
174 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
182 bool GetMirroredTextTest( const GetMirroredTextData& data )
184 // 1) Create the model.
187 Size textArea(100.f, 60.f);
191 const Vector<FontDescriptionRun> fontDescriptions;
192 const LayoutOptions options;
193 CreateTextModel( data.text,
203 LogicalModelPtr logicalModel = textModel->mLogicalModel;
204 VisualModelPtr visualModel = textModel->mVisualModel;
206 // 2) Call the GetMirroredText() function for the whole text
207 Vector<Character> mirroredText;
208 bool mirrored = false;
209 mirrored = GetMirroredText( logicalModel->mText,
210 logicalModel->mCharacterDirections,
211 logicalModel->mBidirectionalParagraphInfo,
213 logicalModel->mText.Count(),
216 // 3) Call the GetMirroredText() function for the given index + number of characters
217 mirrored = GetMirroredText( logicalModel->mText,
218 logicalModel->mCharacterDirections,
219 logicalModel->mBidirectionalParagraphInfo,
221 data.numberOfCharacters,
224 // 4) Compare the results.
227 std::string mirroredString;
228 Utf32ToUtf8( mirroredText.Begin(),
229 mirroredText.Count(),
232 if( !mirrored && ( mirroredString != data.text ) )
234 std::cout << " No mirrored text and mirroredString != data.text." << std::endl;
235 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
236 std::cout << " text : [" << data.text << "]" << std::endl;
240 if( mirrored && ( mirroredString == data.text ) )
242 std::cout << " Mirrored text and mirroredString == data.text." << std::endl;
243 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
244 std::cout << " text : [" << data.text << "]" << std::endl;
248 if( mirrored && ( mirroredString != data.mirroredText ) )
250 std::cout << " Mirrored text and mirroredString != data.mirroredText." << std::endl;
251 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
252 std::cout << " text : [" << data.mirroredText << "]" << std::endl;
259 bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
261 // 1) Create the model.
264 Size textArea(100.f, 60.f);
268 const Vector<FontDescriptionRun> fontDescriptions;
269 const LayoutOptions options;
270 CreateTextModel( data.text,
277 data.markupProcessorEnabled,
280 LogicalModelPtr logicalModel = textModel->mLogicalModel;
281 VisualModelPtr visualModel = textModel->mVisualModel;
283 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
285 // 2) Clear the direction info data.
286 Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
288 if( directions.Count() >= data.startIndex + data.numberOfCharacters )
290 directions.Erase( directions.Begin() + data.startIndex,
291 directions.Begin() + data.startIndex + data.numberOfCharacters );
294 // 3) Call GetCharactersDirection() function.
296 GetCharactersDirection( bidirectionalInfo,
297 logicalModel->mText.Count(),
299 data.numberOfCharacters,
302 for( unsigned int index = 0u; index < logicalModel->mText.Count(); ++index )
304 if( data.directions[index] != directions[index] )
315 //////////////////////////////////////////////////////////
317 int UtcDaliSetBidirectionalInfo(void)
319 tet_infoline(" UtcDaliSetBidirectionalInfo");
321 unsigned int indices01[] = {};
322 unsigned int numberOfCharacters01[] = {};
323 bool direction01[] = {};
324 unsigned int indices02[] = {};
325 unsigned int numberOfCharacters02[] = {};
326 bool direction02[] = {};
327 unsigned int indices03[] = { 17u, 48u };
328 unsigned int numberOfCharacters03[] = { 14u, 14u };
329 bool direction03[] = { true, true };
330 unsigned int indices04[] = { 17u, 31u, 79u };
331 unsigned int numberOfCharacters04[] = { 14u, 48u, 31u };
332 bool direction04[] = { true, false, true };
333 unsigned int indices05[] = { 17u, 41u, 117u };
334 unsigned int numberOfCharacters05[] = { 24u, 76u, 49u };
335 bool direction05[] = { true, false, true };
336 unsigned int indices06[] = { 17u, 48u };
337 unsigned int numberOfCharacters06[] = { 14u, 14u };
338 bool direction06[] = { true, true };
339 unsigned int indices07[] = { 17u, 31u, 79u };
340 unsigned int numberOfCharacters07[] = { 14u, 48u, 31u };
341 bool direction07[] = { true, false, true };
342 unsigned int indices08[] = { 17u, 41u, 117u };
343 unsigned int numberOfCharacters08[] = { 24u, 76u, 49u };
344 bool direction08[] = { true, false, true };
346 struct SetBidirectionalInfoData data[] =
355 numberOfCharacters01,
359 "Some left to right paragraphs",
360 "Hello world\ndemo\n\n",
365 numberOfCharacters02,
369 "A mix of left to right and right to left paragraphs.",
370 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
375 numberOfCharacters03,
379 "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
380 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
385 numberOfCharacters04,
389 "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.",
390 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
395 numberOfCharacters05,
399 "A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
400 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
405 numberOfCharacters06,
409 "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
410 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
415 numberOfCharacters07,
419 "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.",
420 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
425 numberOfCharacters08,
429 "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.",
430 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
435 numberOfCharacters08,
439 "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",
440 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
445 numberOfCharacters08,
449 const unsigned int numberOfTests = 10u;
451 for( unsigned int index = 0u; index < numberOfTests; ++index )
453 ToolkitTestApplication application;
454 if( !SetBidirectionalInfoTest( data[index] ) )
456 tet_result(TET_FAIL);
460 tet_result(TET_PASS);
464 int UtcDaliGetMirroredText(void)
466 tet_infoline(" UtcDaliGetMirroredText");
468 struct GetMirroredTextData data[] =
478 "Left to right characters only.",
479 "Hello world\nhello world demo.",
482 "Hello world\nhello world demo."
485 "Right to left characters but with no characters to mirror.",
486 "שלום עולם\nمرحبا بالعالم",
489 "שלום עולם\nمرحبا بالعالم"
492 "Right to left characters with some characters to mirror.",
493 "שלום עולם\n(مرحبا بالعالم)",
496 "שלום עולם\n)مرحبا بالعالم("
499 "Right to left characters with some characters to mirror. Update last paragraph.",
500 "שלום עולם\n(مرحبا بالعالم)",
503 "שלום עולם\n)مرحبا بالعالم("
506 "Mix of bidirectional text. With more paragraphs.",
507 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
508 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
511 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
512 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום )hello) world demo )עולם(\nשלום )مرحبا بالعالم עולם( )hello("
515 "Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
516 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
517 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
520 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
521 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
524 "Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
525 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
526 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
529 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
530 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
533 const unsigned int numberOfTests = 8u;
535 for( unsigned int index = 0u; index < numberOfTests; ++index )
537 ToolkitTestApplication application;
538 if( !GetMirroredTextTest( data[index] ) )
540 tet_result(TET_FAIL);
544 tet_result(TET_PASS);
548 int UtcDaliGetCharactersDirection(void)
550 tet_infoline(" UtcDaliGetCharactersDirection");
552 bool directions01[] = {};
553 bool directions02[] = {
554 false, false, false, false, false, false, false, false, false, false,
555 false, false, false, false, false, false, false, false, false, false,
556 false, false, false, false, false, false, false, false };
557 bool directions03[] = {
558 true, true, true, true, true, true, true, true, true, true,
559 true, true, true, true, true, true, true, true, true };
560 bool directions04[] = {
561 false, false, false, false, false, false, false, false, false, false,
562 false, false, false, false, false, false, false, false, false, false,
563 false, false, false, false, true, true, true, true, true, true,
564 true, true, true, false, true, true, true, true, true, true,
565 true, true, true, true, false, false, false, false, false, false,
566 false, false, false, false, false };
567 bool directions05[] = {
568 false, false, false, false, false, false, false, false, false, false,
569 false, false, false, false, false, false, false, false, false, false,
570 false, false, false, false, false, false, false, false, false, false,
571 false, false, false, false, false, false, false, false, false, false,
572 false, true, true, true, true, true, true, true, true, true,
573 true, true, true, true, true, true, true, true, true, true,
574 true, true, true, true, false, true, true, true, true, true,
575 true, true, true, true, true, true, true, true, true, true,
576 true, true, true, true, true, true, true, true, true, false,
577 false, false, false, false, true, true, true, true, true, true,
578 true, true, true, true, true, true, true, true, true, false,
579 false, false, false, false, true, true, true, true, true, true,
580 true, true, true, true, true, true, true, true, true, true,
581 true, true, true, true, true, true, true, true, true, false,
582 false, false, false, false, false, false, false, false, false, false,
583 false, false, false, false, false, false, false, false, false, false,
584 false, false, true, true, true, true, true, true, true, true,
585 true, true, true, true, true, true, false, false, false, false,
586 false, false, false, false, false, false, false, false, false, false,
587 false, false, true, true, true, true, true, true, true, true,
588 true, true, true, true, true, true, true, true, true, true,
589 true, true, true, true, true, true, true, true, true, true,
590 true, true, false, false, false, false, false };
592 bool directions06[] = {
593 true, true, true, true, true, true, true, true, true, true,
594 false, false, false, false, false, false, false, false, false, false,
595 false, false, false, false, false, false };
597 struct GetCharactersDirectionData data[] =
608 "Left to right characters only",
609 "Hello world\nhello world demo",
616 "Right to left characters only",
617 "שלום עולם\nשלום עולם",
624 "Mix of bidirectional text",
625 "Hello world\nhello world שלום עולם\nשלום עולם hello world",
632 "Mix of bidirectional text. With more paragraphs.",
633 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
634 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
641 "Mix of bidirectional text. With more paragraphs. Update first paragraph.",
642 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
643 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
650 "Mix of bidirectional text. With more paragraphs. Update from character 29",
651 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
652 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
659 "Mix of bidirectional text. With more paragraphs. Update from character 163",
660 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
661 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
668 "Mix of bidirectional text. With brackets and LRM",
669 "שלום עולם ‎(hello)[world]‎",
676 const unsigned int numberOfTests = 9u;
678 for( unsigned int index = 0u; index < numberOfTests; ++index )
680 ToolkitTestApplication application;
681 if( !GetCharactersDirectionTest( data[index] ) )
683 tet_result(TET_FAIL);
687 tet_result(TET_PASS);