2 * Copyright (c) 2018 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,
116 LogicalModelPtr logicalModel = textModel->mLogicalModel;
117 VisualModelPtr visualModel = textModel->mVisualModel;
119 // 2) Clear the bidirectional paragraph info data.
120 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
121 if( 0u != data.numberOfCharacters )
123 ClearCharacterRuns( data.startIndex,
124 data.startIndex + data.numberOfCharacters - 1u,
128 // 3) Call the SetBidirectionalInfo() function.
129 SetBidirectionalInfo( logicalModel->mText,
130 logicalModel->mScriptRuns,
131 logicalModel->mLineBreakInfo,
133 data.numberOfCharacters,
136 // 4) Compare with the expected results.
137 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
139 if( data.numberOfParagraphs != bidirectionalInfo.Count() )
141 // Different number of expected bidirectional paragraphs.
142 std::cout << " Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
146 for( unsigned int index = 0u; index < data.numberOfParagraphs; ++index )
148 const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
150 const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( run.bidirectionalInfoIndex );
151 if( direction != data.directions[index] )
153 std::cout << " Different direction" << std::endl;
154 std::cout << " paragraph : " << index << std::endl;
155 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
156 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
160 if( run.characterRun.characterIndex != data.indices[index] )
162 std::cout << " Different index" << std::endl;
163 std::cout << " paragraph : " << index << std::endl;
164 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
165 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
168 if( run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index] )
170 std::cout << " Different number of characters" << std::endl;
171 std::cout << " paragraph : " << index << std::endl;
172 std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
173 std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
181 bool GetMirroredTextTest( const GetMirroredTextData& data )
183 // 1) Create the model.
186 Size textArea(100.f, 60.f);
190 const Vector<FontDescriptionRun> fontDescriptions;
191 const LayoutOptions options;
192 CreateTextModel( data.text,
201 LogicalModelPtr logicalModel = textModel->mLogicalModel;
202 VisualModelPtr visualModel = textModel->mVisualModel;
204 // 2) Call the GetMirroredText() function for the whole text
205 Vector<Character> mirroredText;
206 bool mirrored = false;
207 mirrored = GetMirroredText( logicalModel->mText,
208 logicalModel->mCharacterDirections,
209 logicalModel->mBidirectionalParagraphInfo,
211 logicalModel->mText.Count(),
214 // 3) Call the GetMirroredText() function for the given index + number of characters
215 mirrored = GetMirroredText( logicalModel->mText,
216 logicalModel->mCharacterDirections,
217 logicalModel->mBidirectionalParagraphInfo,
219 data.numberOfCharacters,
222 // 4) Compare the results.
225 std::string mirroredString;
226 Utf32ToUtf8( mirroredText.Begin(),
227 mirroredText.Count(),
230 if( !mirrored && ( mirroredString != data.text ) )
232 std::cout << " No mirrored text and mirroredString != data.text." << std::endl;
233 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
234 std::cout << " text : [" << data.text << "]" << std::endl;
238 if( mirrored && ( mirroredString == data.text ) )
240 std::cout << " 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.mirroredText ) )
248 std::cout << " Mirrored text and mirroredString != data.mirroredText." << std::endl;
249 std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
250 std::cout << " text : [" << data.mirroredText << "]" << std::endl;
257 bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
259 // 1) Create the model.
262 Size textArea(100.f, 60.f);
266 const Vector<FontDescriptionRun> fontDescriptions;
267 const LayoutOptions options;
268 CreateTextModel( data.text,
275 data.markupProcessorEnabled );
277 LogicalModelPtr logicalModel = textModel->mLogicalModel;
278 VisualModelPtr visualModel = textModel->mVisualModel;
280 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
282 // 2) Clear the direction info data.
283 Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
285 if( directions.Count() >= data.startIndex + data.numberOfCharacters )
287 directions.Erase( directions.Begin() + data.startIndex,
288 directions.Begin() + data.startIndex + data.numberOfCharacters );
291 // 3) Call GetCharactersDirection() function.
293 GetCharactersDirection( bidirectionalInfo,
294 logicalModel->mText.Count(),
296 data.numberOfCharacters,
299 for( unsigned int index = 0u; index < logicalModel->mText.Count(); ++index )
301 if( data.directions[index] != directions[index] )
312 //////////////////////////////////////////////////////////
314 int UtcDaliSetBidirectionalInfo(void)
316 tet_infoline(" UtcDaliSetBidirectionalInfo");
318 unsigned int indices01[] = {};
319 unsigned int numberOfCharacters01[] = {};
320 bool direction01[] = {};
321 unsigned int indices02[] = {};
322 unsigned int numberOfCharacters02[] = {};
323 bool direction02[] = {};
324 unsigned int indices03[] = { 17u, 48u };
325 unsigned int numberOfCharacters03[] = { 14u, 14u };
326 bool direction03[] = { true, true };
327 unsigned int indices04[] = { 17u, 31u, 79u };
328 unsigned int numberOfCharacters04[] = { 14u, 48u, 31u };
329 bool direction04[] = { true, false, true };
330 unsigned int indices05[] = { 17u, 41u, 117u };
331 unsigned int numberOfCharacters05[] = { 24u, 76u, 49u };
332 bool direction05[] = { true, false, true };
333 unsigned int indices06[] = { 17u, 48u };
334 unsigned int numberOfCharacters06[] = { 14u, 14u };
335 bool direction06[] = { true, true };
336 unsigned int indices07[] = { 17u, 31u, 79u };
337 unsigned int numberOfCharacters07[] = { 14u, 48u, 31u };
338 bool direction07[] = { true, false, true };
339 unsigned int indices08[] = { 17u, 41u, 117u };
340 unsigned int numberOfCharacters08[] = { 24u, 76u, 49u };
341 bool direction08[] = { true, false, true };
343 struct SetBidirectionalInfoData data[] =
352 numberOfCharacters01,
356 "Some left to right paragraphs",
357 "Hello world\ndemo\n\n",
362 numberOfCharacters02,
366 "A mix of left to right and right to left paragraphs.",
367 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
372 numberOfCharacters03,
376 "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
377 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
382 numberOfCharacters04,
386 "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.",
387 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
392 numberOfCharacters05,
396 "A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
397 "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
402 numberOfCharacters06,
406 "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
407 "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
412 numberOfCharacters07,
416 "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.",
417 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
422 numberOfCharacters08,
426 "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.",
427 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
432 numberOfCharacters08,
436 "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",
437 "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
442 numberOfCharacters08,
446 const unsigned int numberOfTests = 10u;
448 for( unsigned int index = 0u; index < numberOfTests; ++index )
450 ToolkitTestApplication application;
451 if( !SetBidirectionalInfoTest( data[index] ) )
453 tet_result(TET_FAIL);
457 tet_result(TET_PASS);
461 int UtcDaliGetMirroredText(void)
463 tet_infoline(" UtcDaliGetMirroredText");
465 struct GetMirroredTextData data[] =
475 "Left to right characters only.",
476 "Hello world\nhello world demo.",
479 "Hello world\nhello world demo."
482 "Right to left characters but with no characters to mirror.",
483 "שלום עולם\nمرحبا بالعالم",
486 "שלום עולם\nمرحبا بالعالم"
489 "Right to left characters with some characters to mirror.",
490 "שלום עולם\n(مرحبا بالعالم)",
493 "שלום עולם\n)مرحبا بالعالم("
496 "Right to left characters with some characters to mirror. Update last paragraph.",
497 "שלום עולם\n(مرحبا بالعالم)",
500 "שלום עולם\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("
512 "Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
513 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
514 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
517 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
518 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
521 "Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
522 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
523 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
526 "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
527 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
530 const unsigned int numberOfTests = 8u;
532 for( unsigned int index = 0u; index < numberOfTests; ++index )
534 ToolkitTestApplication application;
535 if( !GetMirroredTextTest( data[index] ) )
537 tet_result(TET_FAIL);
541 tet_result(TET_PASS);
545 int UtcDaliGetCharactersDirection(void)
547 tet_infoline(" UtcDaliGetCharactersDirection");
549 bool directions01[] = {};
550 bool directions02[] = {
551 false, false, false, false, false, false, false, false, false, false,
552 false, false, false, false, false, false, false, false, false, false,
553 false, false, false, false, false, false, false, false };
554 bool directions03[] = {
555 true, true, true, true, true, true, true, true, true, true,
556 true, true, true, true, true, true, true, true, true };
557 bool directions04[] = {
558 false, false, false, false, false, false, false, false, false, false,
559 false, false, false, false, false, false, false, false, false, false,
560 false, false, false, false, true, true, true, true, true, true,
561 true, true, true, false, true, true, true, true, true, true,
562 true, true, true, true, false, false, false, false, false, false,
563 false, false, false, false, false };
564 bool directions05[] = {
565 false, false, false, false, false, false, false, false, false, false,
566 false, false, false, false, false, false, false, false, false, false,
567 false, false, false, false, false, false, false, false, false, false,
568 false, false, false, false, false, false, false, false, false, false,
569 false, true, true, true, true, true, true, true, true, true,
570 true, true, true, true, true, true, true, true, true, true,
571 true, true, true, true, false, true, true, true, true, true,
572 true, true, true, true, true, true, true, true, true, true,
573 true, true, true, true, true, true, true, true, true, false,
574 false, false, false, false, true, true, true, true, true, true,
575 true, true, true, true, true, true, true, true, true, false,
576 false, false, false, false, true, true, true, true, true, true,
577 true, true, true, true, true, true, true, true, true, true,
578 true, true, true, true, true, true, true, true, true, 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, false, true, true, true, true, true, true, true, true,
582 true, true, true, true, true, true, 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, true, true, true, true,
586 true, true, true, true, true, true, true, true, true, true,
587 true, true, false, false, false, false, false };
589 bool directions06[] = {
590 true, true, true, true, true, true, true, true, true, true,
591 false, false, false, false, false, false, false, false, false, false,
592 false, false, false, false, false, false };
594 struct GetCharactersDirectionData data[] =
605 "Left to right characters only",
606 "Hello world\nhello world demo",
613 "Right to left characters only",
614 "שלום עולם\nשלום עולם",
621 "Mix of bidirectional text",
622 "Hello world\nhello world שלום עולם\nשלום עולם hello world",
629 "Mix of bidirectional text. With more paragraphs.",
630 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
631 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
638 "Mix of bidirectional text. With more paragraphs. Update first paragraph.",
639 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
640 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
647 "Mix of bidirectional text. With more paragraphs. Update from character 29",
648 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
649 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
656 "Mix of bidirectional text. With more paragraphs. Update from character 163",
657 "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
658 " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
665 "Mix of bidirectional text. With brackets and LRM",
666 "שלום עולם ‎(hello)[world]‎",
673 const unsigned int numberOfTests = 9u;
675 for( unsigned int index = 0u; index < numberOfTests; ++index )
677 ToolkitTestApplication application;
678 if( !GetCharactersDirectionTest( data[index] ) )
680 tet_result(TET_FAIL);
684 tet_result(TET_PASS);