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 Toolkit::DevelText::EllipsisPosition::END,
120 LogicalModelPtr logicalModel = textModel->mLogicalModel;
121 VisualModelPtr visualModel = textModel->mVisualModel;
123 // 2) Clear the bidirectional paragraph info data.
124 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
125 if( 0u != data.numberOfCharacters )
127 ClearCharacterRuns( data.startIndex,
128 data.startIndex + data.numberOfCharacters - 1u,
132 // 3) Call the SetBidirectionalInfo() function.
133 SetBidirectionalInfo( logicalModel->mText,
134 logicalModel->mScriptRuns,
135 logicalModel->mLineBreakInfo,
137 data.numberOfCharacters,
140 // 4) Compare with the expected results.
141 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
143 if( data.numberOfParagraphs != bidirectionalInfo.Count() )
145 // Different number of expected bidirectional paragraphs.
146 std::cout << " Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
150 for( unsigned int index = 0u; index < data.numberOfParagraphs; ++index )
152 const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
154 const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( run.bidirectionalInfoIndex );
155 if( direction != data.directions[index] )
157 std::cout << " Different direction" << std::endl;
158 std::cout << " paragraph : " << index << std::endl;
159 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
160 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
164 if( run.characterRun.characterIndex != data.indices[index] )
166 std::cout << " Different index" << std::endl;
167 std::cout << " paragraph : " << index << std::endl;
168 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
169 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
172 if( run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index] )
174 std::cout << " Different number of characters" << std::endl;
175 std::cout << " paragraph : " << index << std::endl;
176 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
177 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
185 bool GetMirroredTextTest( const GetMirroredTextData& data )
187 // 1) Create the model.
190 Size textArea(100.f, 60.f);
194 const Vector<FontDescriptionRun> fontDescriptions;
195 const LayoutOptions options;
196 CreateTextModel( data.text,
206 Toolkit::DevelText::EllipsisPosition::END,
209 LogicalModelPtr logicalModel = textModel->mLogicalModel;
210 VisualModelPtr visualModel = textModel->mVisualModel;
212 // 2) Call the GetMirroredText() function for the whole text
213 Vector<Character> mirroredText;
214 bool mirrored = false;
215 mirrored = GetMirroredText( logicalModel->mText,
216 logicalModel->mCharacterDirections,
217 logicalModel->mBidirectionalParagraphInfo,
219 logicalModel->mText.Count(),
222 // 3) Call the GetMirroredText() function for the given index + number of characters
223 mirrored = GetMirroredText( logicalModel->mText,
224 logicalModel->mCharacterDirections,
225 logicalModel->mBidirectionalParagraphInfo,
227 data.numberOfCharacters,
230 // 4) Compare the results.
233 std::string mirroredString;
234 Utf32ToUtf8( mirroredText.Begin(),
235 mirroredText.Count(),
238 if( !mirrored && ( mirroredString != data.text ) )
240 std::cout << " No mirrored text and mirroredString != data.text." << std::endl;
241 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
242 std::cout << " text : [" << data.text << "]" << std::endl;
246 if( mirrored && ( mirroredString == data.text ) )
248 std::cout << " 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.mirroredText ) )
256 std::cout << " Mirrored text and mirroredString != data.mirroredText." << std::endl;
257 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
258 std::cout << " text : [" << data.mirroredText << "]" << std::endl;
265 bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
267 // 1) Create the model.
270 Size textArea(100.f, 60.f);
274 const Vector<FontDescriptionRun> fontDescriptions;
275 const LayoutOptions options;
276 CreateTextModel( data.text,
283 data.markupProcessorEnabled,
286 Toolkit::DevelText::EllipsisPosition::END,
289 LogicalModelPtr logicalModel = textModel->mLogicalModel;
290 VisualModelPtr visualModel = textModel->mVisualModel;
292 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
294 // 2) Clear the direction info data.
295 Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
297 if( directions.Count() >= data.startIndex + data.numberOfCharacters )
299 directions.Erase( directions.Begin() + data.startIndex,
300 directions.Begin() + data.startIndex + data.numberOfCharacters );
303 // 3) Call GetCharactersDirection() function.
305 GetCharactersDirection( bidirectionalInfo,
306 logicalModel->mText.Count(),
308 data.numberOfCharacters,
311 for( unsigned int index = 0u; index < logicalModel->mText.Count(); ++index )
313 if( data.directions[index] != directions[index] )
324 //////////////////////////////////////////////////////////
326 int UtcDaliSetBidirectionalInfo(void)
328 tet_infoline(" UtcDaliSetBidirectionalInfo");
330 unsigned int indices01[] = {};
331 unsigned int numberOfCharacters01[] = {};
332 bool direction01[] = {};
333 unsigned int indices02[] = {};
334 unsigned int numberOfCharacters02[] = {};
335 bool direction02[] = {};
336 unsigned int indices03[] = { 17u, 48u };
337 unsigned int numberOfCharacters03[] = { 14u, 14u };
338 bool direction03[] = { true, true };
339 unsigned int indices04[] = { 17u, 31u, 79u };
340 unsigned int numberOfCharacters04[] = { 14u, 48u, 31u };
341 bool direction04[] = { true, false, true };
342 unsigned int indices05[] = { 17u, 41u, 117u };
343 unsigned int numberOfCharacters05[] = { 24u, 76u, 49u };
344 bool direction05[] = { true, false, true };
345 unsigned int indices06[] = { 17u, 48u };
346 unsigned int numberOfCharacters06[] = { 14u, 14u };
347 bool direction06[] = { true, true };
348 unsigned int indices07[] = { 17u, 31u, 79u };
349 unsigned int numberOfCharacters07[] = { 14u, 48u, 31u };
350 bool direction07[] = { true, false, true };
351 unsigned int indices08[] = { 17u, 41u, 117u };
352 unsigned int numberOfCharacters08[] = { 24u, 76u, 49u };
353 bool direction08[] = { true, false, true };
355 struct SetBidirectionalInfoData data[] =
364 numberOfCharacters01,
368 "Some left to right paragraphs",
369 "Hello world\ndemo\n\n",
374 numberOfCharacters02,
378 "A mix of left to right and right to left paragraphs.",
379 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
384 numberOfCharacters03,
388 "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
389 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
394 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,
408 "A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
409 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
414 numberOfCharacters06,
418 "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
419 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
424 numberOfCharacters07,
428 "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.",
429 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
434 numberOfCharacters08,
438 "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.",
439 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
444 numberOfCharacters08,
448 "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",
449 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
454 numberOfCharacters08,
458 const unsigned int numberOfTests = 10u;
460 for( unsigned int index = 0u; index < numberOfTests; ++index )
462 ToolkitTestApplication application;
463 if( !SetBidirectionalInfoTest( data[index] ) )
465 tet_result(TET_FAIL);
469 tet_result(TET_PASS);
473 int UtcDaliGetMirroredText(void)
475 tet_infoline(" UtcDaliGetMirroredText");
477 struct GetMirroredTextData data[] =
487 "Left to right characters only.",
488 "Hello world\nhello world demo.",
491 "Hello world\nhello world demo."
494 "Right to left characters but with no characters to mirror.",
495 "שלום עולם\nمرحبا بالعالم",
498 "שלום עולם\nمرحبا بالعالم"
501 "Right to left characters with some characters to mirror.",
502 "שלום עולם\n(مرحبا بالعالم)",
505 "שלום עולם\n)مرحبا بالعالم("
508 "Right to left characters with some characters to mirror. Update last paragraph.",
509 "שלום עולם\n(مرحبا بالعالم)",
512 "שלום עולם\n)مرحبا بالعالم("
515 "Mix of bidirectional text. With more 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.",
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 "Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
534 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
535 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
538 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
539 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
542 const unsigned int numberOfTests = 8u;
544 for( unsigned int index = 0u; index < numberOfTests; ++index )
546 ToolkitTestApplication application;
547 if( !GetMirroredTextTest( data[index] ) )
549 tet_result(TET_FAIL);
553 tet_result(TET_PASS);
557 int UtcDaliGetCharactersDirection(void)
559 tet_infoline(" UtcDaliGetCharactersDirection");
561 bool directions01[] = {};
562 bool directions02[] = {
563 false, false, false, false, false, false, false, false, false, false,
564 false, false, false, false, false, false, false, false, false, false,
565 false, false, false, false, false, false, false, false };
566 bool directions03[] = {
567 true, true, true, true, true, true, true, true, true, true,
568 true, true, true, true, true, true, true, true, true };
569 bool directions04[] = {
570 false, false, false, false, false, false, false, false, false, false,
571 false, false, false, false, false, false, false, false, false, false,
572 false, false, false, false, true, true, true, true, true, true,
573 true, true, true, false, true, true, true, true, true, true,
574 true, true, true, true, false, false, false, false, false, false,
575 false, false, false, false, false };
576 bool directions05[] = {
577 false, false, false, false, false, false, false, false, false, false,
578 false, false, false, false, false, false, false, false, false, false,
579 false, false, false, false, false, false, false, false, false, false,
580 false, false, false, false, false, false, false, false, false, false,
581 false, true, true, true, true, true, true, true, true, true,
582 true, true, true, true, true, true, true, true, true, true,
583 true, true, true, true, false, true, true, true, true, true,
584 true, true, true, true, true, true, true, true, true, true,
585 true, true, true, true, true, true, true, true, true, false,
586 false, false, false, false, true, true, true, true, true, true,
587 true, true, true, true, true, true, true, true, true, false,
588 false, false, false, false, true, true, true, true, true, true,
589 true, true, true, true, true, true, true, true, true, true,
590 true, true, true, true, true, true, true, true, true, false,
591 false, false, false, false, false, false, false, false, false, false,
592 false, false, false, false, false, false, false, false, false, false,
593 false, false, true, true, true, true, true, true, true, true,
594 true, true, true, true, true, true, false, false, false, false,
595 false, false, false, false, false, false, false, false, false, false,
596 false, false, true, true, true, true, true, true, true, true,
597 true, true, true, true, true, true, true, true, true, true,
598 true, true, true, true, true, true, true, true, true, true,
599 true, true, false, false, false, false, false };
601 bool directions06[] = {
602 true, true, true, true, true, true, true, true, true, true,
603 false, false, false, false, false, false, false, false, false, false,
604 false, false, false, false, false, false };
606 struct GetCharactersDirectionData data[] =
617 "Left to right characters only",
618 "Hello world\nhello world demo",
625 "Right to left characters only",
626 "שלום עולם\nשלום עולם",
633 "Mix of bidirectional text",
634 "Hello world\nhello world שלום עולם\nשלום עולם hello world",
641 "Mix of bidirectional text. With more paragraphs.",
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 first paragraph.",
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 29",
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 more paragraphs. Update from character 163",
669 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
670 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
677 "Mix of bidirectional text. With brackets and LRM",
678 "שלום עולם ‎(hello)[world]‎",
685 const unsigned int numberOfTests = 9u;
687 for( unsigned int index = 0u; index < numberOfTests; ++index )
689 ToolkitTestApplication application;
690 if( !GetCharactersDirectionTest( data[index] ) )
692 tet_result(TET_FAIL);
696 tet_result(TET_PASS);