--- /dev/null
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org.
+
+Arev Fonts Copyright
+------------------------------
+
+Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the fonts accompanying this license ("Fonts") and
+associated documentation files (the "Font Software"), to reproduce
+and distribute the modifications to the Bitstream Vera Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be included in all copies of one or more of the Font Software
+typefaces.
+
+The Font Software may be modified, altered, or added to, and in
+particular the designs of glyphs or characters in the Fonts may be
+modified and additional glyphs or characters may be added to the
+Fonts, only if the fonts are renamed to names not containing either
+the words "Tavmjong Bah" or the word "Arev".
+
+This License becomes null and void to the extent applicable to Fonts
+or Font Software that has been modified and is distributed under the
+"Tavmjong Bah Arev" names.
+
+The Font Software may be sold as part of a larger software package but
+no copy of one or more of the Font Software typefaces may be sold by
+itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the name of Tavmjong Bah shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in this Font Software without prior written authorization
+from Tavmjong Bah. For further information, contact: tavmjong @ free
+. fr.
+
+$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
utc-Dali-Text-CharacterSetConversion.cpp
utc-Dali-Text-Segmentation.cpp
utc-Dali-Text-MultiLanguage.cpp
+ utc-Dali-LogicalModel.cpp
+ utc-Dali-BidirectionalSupport.cpp
)
# Append list of test harness files (Won't get parsed for test cases)
../dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-timer.cpp
../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
+ ../dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
../dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp
../dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp
../dali-toolkit/dali-toolkit-test-utils/test-application.cpp
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+
+#include <dali/devel-api/text-abstraction/bidirectional-support.h>
+#include <dali-toolkit/internal/text/bidirectional-support.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-model.h>
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions.
+//
+// void SetBidirectionalInfo( const Vector<Character>& text,
+// const Vector<ScriptRun>& scripts,
+// const Vector<LineBreakInfo>& lineBreakInfo,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
+// Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo )
+// void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
+// Vector<LineRun>& lineRuns,
+// Vector<BidirectionalLineInfoRun>& lineInfoRuns )
+// bool GetMirroredText( const Vector<Character>& text,
+// Vector<CharacterDirection>& directions,
+// const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
+// Vector<Character>& mirroredText )
+// void GetCharactersDirection( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
+// Vector<CharacterDirection>& directions )
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct SetBidirectionalInfoData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The index from where the model is updated.
+ unsigned int numberOfCharacters; ///< The number of characters to update.
+ unsigned int numberOfParagraphs; ///< The expected number of bidirectional paragraphs.
+ unsigned int* indices; ///< The expected indices to the first character of each paragraph.
+ unsigned int* numberOfParagraphCharacters; ///< The expected number of characters of each paragraph.
+ bool* directions; ///< The expected direction of each paragraph.
+};
+
+struct BidiLineData
+{
+ unsigned int characterIndex;
+ unsigned int numberOfCharacters;
+ unsigned int* visualToLogical;
+};
+
+struct ReorderLinesData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The index from where the model is updated.
+ unsigned int numberOfCharacters; ///< The number of characters.
+ unsigned int numberOfLineInfo; ///< The number or reordered lines.
+ BidiLineData* bidiLineData; ///< The bidirectional line info.
+};
+
+struct GetMirroredTextData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The index from where the model is updated.
+ unsigned int numberOfCharacters; ///< The number of the characters.
+ std::string mirroredText; ///< The expected result.
+};
+
+struct GetCharactersDirectionData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The index from where the model is updated.
+ unsigned int numberOfCharacters; ///< The number of characters.
+ bool* directions; ///< The expected directions.
+};
+
+bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ // Create the model.
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Clear the bidirectional paragraph info data.
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
+ if( 0u != data.numberOfCharacters )
+ {
+ ClearCharacterRuns( data.startIndex,
+ data.startIndex + data.numberOfCharacters - 1u,
+ bidirectionalInfo );
+ }
+
+ // 3) Call the SetBidirectionalInfo() function.
+ SetBidirectionalInfo( logicalModel->mText,
+ logicalModel->mScriptRuns,
+ logicalModel->mLineBreakInfo,
+ data.startIndex,
+ data.numberOfCharacters,
+ bidirectionalInfo );
+
+ // 4) Compare with the expected results.
+ TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
+
+ if( data.numberOfParagraphs != bidirectionalInfo.Count() )
+ {
+ // Different number of expected bidirectional paragraphs.
+ std::cout << " Different number of bidi paragraphs : " << bidirectionalInfo.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < data.numberOfParagraphs; ++index )
+ {
+ const BidirectionalParagraphInfoRun& run = bidirectionalInfo[index];
+
+ const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( run.bidirectionalInfoIndex );
+ if( direction != data.directions[index] )
+ {
+ std::cout << " Different direction" << std::endl;
+ std::cout << " paragraph : " << index << std::endl;
+ std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
+ std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
+ return false;
+ }
+
+ if( run.characterRun.characterIndex != data.indices[index] )
+ {
+ std::cout << " Different index" << std::endl;
+ std::cout << " paragraph : " << index << std::endl;
+ std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
+ std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
+ return false;
+ }
+ if( run.characterRun.numberOfCharacters != data.numberOfParagraphCharacters[index] )
+ {
+ std::cout << " Different number of characters" << std::endl;
+ std::cout << " paragraph : " << index << std::endl;
+ std::cout << " index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << ", direction : " << direction << std::endl;
+ std::cout << " expected, index : " << data.indices[index] << ", num chars : " << data.numberOfParagraphCharacters[index] << ", direction : " << data.directions[index] << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * @brief Frees previously allocated bidirectional resources.
+ *
+ * @param[in] bidirectionalLineInfo Bidirectional info per line.
+ * @param[in] startIndex Index to the first line with bidirectional info to be freed.
+ * @param[in] endIndex Index to the last line with bidirectional info to be freed.
+ */
+void FreeBidirectionalLineInfoResources( Vector<BidirectionalLineInfoRun> bidirectionalLineInfo,
+ uint32_t startIndex,
+ uint32_t endIndex )
+{
+ // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+ for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin() + startIndex,
+ endIt = bidirectionalLineInfo.Begin() + endIndex;
+ it != endIt;
+ ++it )
+ {
+ BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+ free( bidiLineInfo.visualToLogicalMap );
+ }
+}
+
+bool ReorderLinesTest( const ReorderLinesData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 300.f);
+ Size layoutSize;
+
+ // Create the model.
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Clear the bidirectional line info data.
+ uint32_t startRemoveIndex = logicalModel->mBidirectionalLineInfo.Count();
+ uint32_t endRemoveIndex = startRemoveIndex;
+ ClearCharacterRuns( data.startIndex,
+ data.startIndex + data.numberOfCharacters - 1u,
+ logicalModel->mBidirectionalLineInfo,
+ startRemoveIndex,
+ endRemoveIndex );
+
+ // Index to the first index to be removed.
+
+ FreeBidirectionalLineInfoResources( logicalModel->mBidirectionalLineInfo, startRemoveIndex, endRemoveIndex );
+ BidirectionalLineInfoRun* bidiLineBuffer = logicalModel->mBidirectionalLineInfo.Begin();
+ logicalModel->mBidirectionalLineInfo.Erase( bidiLineBuffer + startRemoveIndex,
+ bidiLineBuffer + endRemoveIndex );
+
+ // 3) Call the function ReorderLines()
+
+ ReorderLines( logicalModel->mBidirectionalParagraphInfo,
+ data.startIndex,
+ data.numberOfCharacters,
+ visualModel->mLines,
+ logicalModel->mBidirectionalLineInfo );
+
+ // 4) Compare the results.
+
+ if( data.numberOfLineInfo != logicalModel->mBidirectionalLineInfo.Count() )
+ {
+ // Different number of bidirectional lines.
+ std::cout << " different number of bidi lines : " << logicalModel->mBidirectionalLineInfo.Count() << ", expected : " << data.numberOfLineInfo << std::endl;
+ for( unsigned int index = 0u; index < logicalModel->mBidirectionalLineInfo.Count(); ++index )
+ {
+ const BidirectionalLineInfoRun& run = logicalModel->mBidirectionalLineInfo[index];
+ const BidiLineData& bidiLineData = data.bidiLineData[index];
+
+ std::cout << " bidi line : " << index << ", index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << std::endl;
+ std::cout << " expected index : " << bidiLineData.characterIndex << ", num chars : " << bidiLineData.numberOfCharacters << std::endl;
+ }
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < data.numberOfLineInfo; ++index )
+ {
+ const BidirectionalLineInfoRun& run = logicalModel->mBidirectionalLineInfo[index];
+ const BidiLineData& bidiLineData = data.bidiLineData[index];
+
+ if( bidiLineData.characterIndex != run.characterRun.characterIndex )
+ {
+ std::cout << " bidi line : " << index << ", index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << std::endl;
+ std::cout << " expected index : " << bidiLineData.characterIndex << ", num chars : " << bidiLineData.numberOfCharacters << std::endl;
+ return false;
+ }
+ if( bidiLineData.numberOfCharacters != run.characterRun.numberOfCharacters )
+ {
+ std::cout << " bidi line : " << index << ", index : " << run.characterRun.characterIndex << ", num chars : " << run.characterRun.numberOfCharacters << std::endl;
+ std::cout << " expected index : " << bidiLineData.characterIndex << ", num chars : " << bidiLineData.numberOfCharacters << std::endl;
+ return false;
+ }
+
+ for( unsigned int i = 0u; i < run.characterRun.numberOfCharacters; ++i )
+ {
+ if( bidiLineData.visualToLogical[i] != run.visualToLogicalMap[i] )
+ {
+ std::cout << " v2l : ";
+ for( unsigned int i = 0u; i < run.characterRun.numberOfCharacters; ++i )
+ {
+ std::cout << run.visualToLogicalMap[i] << " ";
+ }
+ std::cout << std::endl;
+ std::cout << " expected v2l : ";
+ for( unsigned int i = 0u; i < run.characterRun.numberOfCharacters; ++i )
+ {
+ std::cout << bidiLineData.visualToLogical[i] << " ";
+ }
+ std::cout << std::endl;
+
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool GetMirroredTextTest( const GetMirroredTextData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ // Create the model.
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Call the GetMirroredText() function for the whole text
+ Vector<Character> mirroredText;
+ bool mirrored = false;
+ mirrored = GetMirroredText( logicalModel->mText,
+ logicalModel->mCharacterDirections,
+ logicalModel->mBidirectionalParagraphInfo,
+ 0u,
+ logicalModel->mText.Count(),
+ mirroredText );
+
+ // 3) Call the GetMirroredText() function for the given index + number of characters
+ mirrored = GetMirroredText( logicalModel->mText,
+ logicalModel->mCharacterDirections,
+ logicalModel->mBidirectionalParagraphInfo,
+ data.startIndex,
+ data.numberOfCharacters,
+ mirroredText );
+
+ // 4) Compare the results.
+
+ // Convert to utf8
+ std::string mirroredString;
+ Utf32ToUtf8( mirroredText.Begin(),
+ mirroredText.Count(),
+ mirroredString );
+
+ if( !mirrored && ( mirroredString != data.text ) )
+ {
+ std::cout << " No mirrored text and mirroredString != data.text." << std::endl;
+ std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
+ std::cout << " text : [" << data.text << "]" << std::endl;
+ return false;
+ }
+
+ if( mirrored && ( mirroredString == data.text ) )
+ {
+ std::cout << " Mirrored text and mirroredString == data.text." << std::endl;
+ std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
+ std::cout << " text : [" << data.text << "]" << std::endl;
+ return false;
+ }
+
+ if( mirrored && ( mirroredString != data.mirroredText ) )
+ {
+ std::cout << " Mirrored text and mirroredString != data.mirroredText." << std::endl;
+ std::cout << " mirrored string : [" << mirroredString << "]" << std::endl;
+ std::cout << " text : [" << data.mirroredText << "]" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ // Create the model.
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
+
+ // 2) Clear the direction info data.
+ Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections;
+
+ directions.Erase( directions.Begin() + data.startIndex,
+ directions.Begin() + data.startIndex + data.numberOfCharacters );
+
+ // 3) Call GetCharactersDirection() function.
+
+ GetCharactersDirection( bidirectionalInfo,
+ logicalModel->mText.Count(),
+ data.startIndex,
+ data.numberOfCharacters,
+ directions );
+
+ for( unsigned int index = 0u; index < logicalModel->mText.Count(); ++index )
+ {
+ if( data.directions[index] != directions[index] )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliSetBidirectionalInfo(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliSetBidirectionalInfo");
+
+ unsigned int indices01[] = {};
+ unsigned int numberOfCharacters01[] = {};
+ bool direction01[] = {};
+ unsigned int indices02[] = {};
+ unsigned int numberOfCharacters02[] = {};
+ bool direction02[] = {};
+ unsigned int indices03[] = { 17u, 48u };
+ unsigned int numberOfCharacters03[] = { 14u, 14u };
+ bool direction03[] = { true, true };
+ unsigned int indices04[] = { 17u, 31u, 79u };
+ unsigned int numberOfCharacters04[] = { 14u, 48u, 31u };
+ bool direction04[] = { true, false, true };
+ unsigned int indices05[] = { 17u, 41u, 117u };
+ unsigned int numberOfCharacters05[] = { 24u, 76u, 49u };
+ bool direction05[] = { true, false, true };
+ unsigned int indices06[] = { 17u, 48u };
+ unsigned int numberOfCharacters06[] = { 14u, 14u };
+ bool direction06[] = { true, true };
+ unsigned int indices07[] = { 17u, 31u, 79u };
+ unsigned int numberOfCharacters07[] = { 14u, 48u, 31u };
+ bool direction07[] = { true, false, true };
+ unsigned int indices08[] = { 17u, 41u, 117u };
+ unsigned int numberOfCharacters08[] = { 24u, 76u, 49u };
+ bool direction08[] = { true, false, true };
+
+ struct SetBidirectionalInfoData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ 0u,
+ 0u,
+ 0u,
+ indices01,
+ numberOfCharacters01,
+ direction01
+ },
+ {
+ "Some left to right paragraphs",
+ "Hello world\ndemo\n\n",
+ 0u,
+ 18u,
+ 0u,
+ indices02,
+ numberOfCharacters02,
+ direction02
+ },
+ {
+ "A mix of left to right and right to left paragraphs.",
+ "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
+ 0u,
+ 78u,
+ 2u,
+ indices03,
+ numberOfCharacters03,
+ direction03
+ },
+ {
+ "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
+ "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
+ 0u,
+ 126u,
+ 3u,
+ indices04,
+ numberOfCharacters04,
+ direction04
+ },
+ {
+ "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.",
+ "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
+ 0u,
+ 182u,
+ 3u,
+ indices05,
+ numberOfCharacters05,
+ direction05
+ },
+ {
+ "A mix of left to right and right to left paragraphs. Updates a left to right paragraph.",
+ "Hello world demo\nمرحبا بالعالم\nhello world demo\nمرحبا بالعالم\nhello world demo",
+ 31u,
+ 17u,
+ 2u,
+ indices06,
+ numberOfCharacters06,
+ direction06
+ },
+ {
+ "A mix of left to right and right to left paragraphs. Paragraphs also contain a mix of bidirectional text.",
+ "Hello world demo\nمرحبا بالعالم\nhello world demo مرحبا بالعالم hello world demo\nمرحبا hello world demo بالعالم\nhello world demo",
+ 0u,
+ 126u,
+ 3u,
+ indices07,
+ numberOfCharacters07,
+ direction07
+ },
+ {
+ "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.",
+ "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
+ 0u,
+ 41u,
+ 3u,
+ indices08,
+ numberOfCharacters08,
+ direction08
+ },
+ {
+ "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.",
+ "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
+ 41u,
+ 76u,
+ 3u,
+ indices08,
+ numberOfCharacters08,
+ direction08
+ },
+ {
+ "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",
+ "Hello world demo\nمرحبا שלום עולם بالعالم\nhello world שלום بالعالم עולם demo مرحبا שלום עולם بالعالم hello world demo\nمرحبا hello שלום بالعالم עולם world demo بالعالم\nhello world demo",
+ 117u,
+ 65u,
+ 3u,
+ indices08,
+ numberOfCharacters08,
+ direction08
+ },
+ };
+ const unsigned int numberOfTests = 10u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !SetBidirectionalInfoTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliReorderLines(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliSetBidirectionalInfo");
+
+ unsigned int visualToLogical0301[] = { 0u, 1u, 2u, 3u, 4u, 5u, 9u, 8u, 7u, 6u, 10u };
+ unsigned int visualToLogical0302[] = { 3u, 2u, 1u, 0u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
+ unsigned int visualToLogical0303[] = { 0u, 1u, 2u, 3u, 4u };
+ unsigned int visualToLogical0304[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0305[] = { 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0306[] = { 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0307[] = { 13u, 8u, 9u, 10u, 11u, 12u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0308[] = { 5u, 0u, 1u, 2u, 3u, 4u };
+ unsigned int visualToLogical0309[] = { 0u, 1u, 2u, 3u, 4u, 5u, 9u, 8u, 7u, 6u, 10u };
+ unsigned int visualToLogical0310[] = { 3u, 2u, 1u, 0u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
+ unsigned int visualToLogical0311[] = { 0u, 1u, 2u, 3u, 4u };
+ unsigned int visualToLogical0312[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0313[] = { 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0314[] = { 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0315[] = { 13u, 8u, 9u, 10u, 11u, 12u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical0316[] = { 0u, 1u, 2u, 3u, 4u };
+
+ BidiLineData bidiLine01[] = {};
+ BidiLineData bidiLine02[] = {};
+ BidiLineData bidiLine03[] = {
+ {
+ 17u,
+ 11u,
+ visualToLogical0301
+ },
+ {
+ 28u,
+ 11u,
+ visualToLogical0302
+ },
+ {
+ 39u,
+ 5u,
+ visualToLogical0303
+ },
+ {
+ 44u,
+ 13u,
+ visualToLogical0304
+ },
+ {
+ 57u,
+ 11u,
+ visualToLogical0305
+ },
+ {
+ 68u,
+ 10u,
+ visualToLogical0306
+ },
+ {
+ 78u,
+ 14u,
+ visualToLogical0307
+ },
+ {
+ 92u,
+ 6u,
+ visualToLogical0308
+ },
+ {
+ 115u,
+ 11u,
+ visualToLogical0309
+ },
+ {
+ 126u,
+ 11u,
+ visualToLogical0310
+ },
+ {
+ 137u,
+ 5u,
+ visualToLogical0311
+ },
+ {
+ 142u,
+ 13u,
+ visualToLogical0312
+ },
+ {
+ 155u,
+ 11u,
+ visualToLogical0313
+ },
+ {
+ 166u,
+ 10u,
+ visualToLogical0314
+ },
+ {
+ 176u,
+ 14u,
+ visualToLogical0315
+ },
+ {
+ 190u,
+ 5u,
+ visualToLogical0316
+ },
+ };
+
+ struct ReorderLinesData data[] =
+ {
+ {
+ "Zero characters.",
+ "",
+ 0u,
+ 0u,
+ 0u,
+ bidiLine01
+ },
+ {
+ "Left to right text only.",
+ "Hello world demo\nhello world demo\nhello world demo.",
+ 0u,
+ 51u,
+ 0u,
+ bidiLine02
+ },
+ {
+ "Bidirectional paragraphs.",
+ "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
+ 0u,
+ 195u,
+ 16u,
+ bidiLine03
+ },
+ {
+ "Bidirectional paragraphs. Update initial paragraphs.",
+ "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
+ 0u,
+ 44u,
+ 16u,
+ bidiLine03
+ },
+ {
+ "Bidirectional paragraphs. Update middle paragraphs.",
+ "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
+ 44u,
+ 54u,
+ 16u,
+ bidiLine03
+ },
+ {
+ "Bidirectional paragraphs. Update final paragraphs.",
+ "Hello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world\nHello world demo\nhello שלום עולם world demo\nשלום بالعالم עולם مرحبا שלום עולם بالعالم hello world",
+ 142u,
+ 53u,
+ 16u,
+ bidiLine03
+ },
+ };
+ const unsigned int numberOfTests = 6u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !ReorderLinesTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliGetMirroredText(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliGetMirroredText");
+
+ struct GetMirroredTextData data[] =
+ {
+ {
+ "Zero characters.",
+ "",
+ 0u,
+ 0u,
+ ""
+ },
+ {
+ "Left to right characters only.",
+ "Hello world\nhello world demo.",
+ 0u,
+ 29u,
+ "Hello world\nhello world demo."
+ },
+ {
+ "Right to left characters but with no characters to mirror.",
+ "שלום עולם\nمرحبا بالعالم",
+ 0u,
+ 23u,
+ "שלום עולם\nمرحبا بالعالم"
+ },
+ {
+ "Right to left characters with some characters to mirror.",
+ "שלום עולם\n(مرحبا بالعالم)",
+ 0u,
+ 25u,
+ "שלום עולם\n)مرحبا بالعالم("
+ },
+ {
+ "Right to left characters with some characters to mirror. Update last paragraph.",
+ "שלום עולם\n(مرحبا بالعالم)",
+ 10u,
+ 15u,
+ "שלום עולם\n)مرحبا بالعالم("
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs.",
+ "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
+ 0u,
+ 239u,
+ "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום )hello) world demo )עולם(\nשלום )مرحبا بالعالم עולם( )hello("
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs. Update middle paragraphs.",
+ "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
+ 29u,
+ 38u,
+ "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום( עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs. Update middle paragraphs (2).",
+ "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם (hello) مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)",
+ 67u,
+ 100u,
+ "Hello world demo\nhello world\nhello world (مرحبا بالعالم שלום) עולם\nשלום مرحبا بالعالم עולם )hello( مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום (hello) world demo (עולם)\nשלום (مرحبا بالعالم עולם) (hello)"
+ },
+ };
+ const unsigned int numberOfTests = 8u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !GetMirroredTextTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliGetCharactersDirection(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliGetCharactersDirection");
+
+ bool directions01[] = {};
+ bool directions02[] = {
+ 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 };
+ bool directions03[] = {
+ true, true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true };
+ bool directions04[] = {
+ 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 };
+ bool directions05[] = {
+ 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 };
+
+ struct GetCharactersDirectionData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ 0u,
+ 0u,
+ directions01
+ },
+ {
+ "Left to right characters only",
+ "Hello world\nhello world demo",
+ 0u,
+ 28u,
+ directions02
+ },
+ {
+ "Right to left characters only",
+ "שלום עולם\nשלום עולם",
+ 0u,
+ 19u,
+ directions03
+ },
+ {
+ "Mix of bidirectional text",
+ "Hello world\nhello world שלום עולם\nשלום עולם hello world",
+ 0u,
+ 55u,
+ directions04
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs.",
+ "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
+ 0u,
+ 227u,
+ directions05
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs. Update first paragraph.",
+ "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
+ 0u,
+ 17u,
+ directions05
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs. Update from character 29",
+ "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
+ 29u,
+ 134u,
+ directions05
+ },
+ {
+ "Mix of bidirectional text. With more paragraphs. Update from character 163",
+ "Hello world demo\nhello world\nhello world مرحبا بالعالم שלום עולם\nשלום مرحبا بالعالم עולם hello مرحبا بالعالم world"
+ " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
+ 163u,
+ 35u,
+ directions05
+ }
+ };
+ const unsigned int numberOfTests = 8u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !GetCharactersDirectionTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-model.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions.
+//
+// void SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
+// Length numberOfRuns,
+// CharacterIndex startIndex )
+
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct SetVisualToLogicalMapData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The start index from where the visual to logical conversion table is set.
+ unsigned int numberOfCharacters; ///< The number of characters to set.
+ Size textArea; ///< The size of the area where the text is laid-out.
+ unsigned int expectedNumberOfCharacters; ///< The expected number of characters.
+ unsigned int* visualToLogical; ///< The expected visual to logical conversion table.
+};
+
+bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
+{
+ std::cout << " testing : " << data.description << std::endl;
+ // Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size layoutSize;
+
+ // Create the model with the whole text.
+ CreateTextModel( data.text,
+ data.textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // Get the visual to logical map.
+ Vector<CharacterIndex>& visualToLogicalMap = logicalModel->mVisualToLogicalMap;
+
+ // Compare the results.
+ if( data.expectedNumberOfCharacters != visualToLogicalMap.Count() )
+ {
+ std::cout << " differetn number of characters : " << visualToLogicalMap.Count() << ", expected : " << data.expectedNumberOfCharacters << std::endl;
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < data.expectedNumberOfCharacters; ++index )
+ {
+ if( data.visualToLogical[index] != visualToLogicalMap[index] )
+ {
+ std::cout << " different visualToLogical table : " << std::endl;
+ for( unsigned int i = 0; i < data.expectedNumberOfCharacters; ++i )
+ {
+ std::cout << visualToLogicalMap[i] << " ";
+ }
+ std::cout << std::endl;
+ std::cout << " expected : " << std::endl;
+ for( unsigned int i = 0; i < data.expectedNumberOfCharacters; ++i )
+ {
+ std::cout << data.visualToLogical[i] << " ";
+ }
+ std::cout << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliSetVisualToLogicalMap(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliSetVisualToLogicalMap");
+
+ unsigned int* visualToLogical01 = NULL;
+ unsigned int* visualToLogical02 = NULL;
+ unsigned int visualToLogical03[] = { 12u, 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u };
+ unsigned int visualToLogical04[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, };
+ unsigned int visualToLogical05[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 26u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u };
+ unsigned int visualToLogical06[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+ unsigned int visualToLogical07[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+ unsigned int visualToLogical08[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+ unsigned int visualToLogical09[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 25u, 24u, 23u, 22u, 21u, 20u, 19u, 18u, 17u, 16u, 15u, 14u, 13u, 26u, 27u, 28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, 54u, 53u, 52u, 51u, 50u, 49u, 48u, 47u, 46u, 45u, 44u, 43u, 42u, 41u, 40u, 67u, 66u, 55u, 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, 64u, 65u, 81u, 80u, 79u, 78u, 77u, 76u, 75u, 74u, 73u, 72u, 71u, 70u, 69u, 68u, 95u, 94u, 93u, 92u, 91u, 90u, 89u, 88u, 87u, 86u, 85u, 84u, 83u, 82u, 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, 104u, 105u, 106u };
+
+ struct SetVisualToLogicalMapData data[] =
+ {
+ {
+ "Zero characters text",
+ "",
+ 0u,
+ 0u,
+ Size( 100.f, 300.f ),
+ 0u,
+ visualToLogical01
+ },
+ {
+ "Left to right text only",
+ "Hello world",
+ 0u,
+ 11u,
+ Size( 100.f, 300.f ),
+ 0u,
+ visualToLogical02
+ },
+ {
+ "Right to left text only",
+ "مرحبا بالعالم",
+ 0u,
+ 13u,
+ Size( 100.f, 300.f ),
+ 13u,
+ visualToLogical03
+ },
+ {
+ "Mix of left to right and right to left text.",
+ "Hello world, مرحبا بالعالم",
+ 0u,
+ 26u,
+ Size( 100.f, 300.f ),
+ 26u,
+ visualToLogical04
+ },
+ {
+ "Mix of left to right and right to left text.",
+ "Hello world, \nمرحبا بالعالم",
+ 0u,
+ 27u,
+ Size( 100.f, 300.f ),
+ 27u,
+ visualToLogical05
+ },
+ {
+ "Mix of left to right and right to left text.",
+ "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
+ 0u,
+ 107u,
+ Size( 100.f, 300.f ),
+ 107u,
+ visualToLogical06
+ },
+ {
+ "Mix of left to right and right to left text. Updates from character index 5",
+ "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
+ 5u,
+ 107u,
+ Size( 100.f, 300.f ),
+ 107u,
+ visualToLogical07
+ },
+ {
+ "Mix of left to right and right to left text. Updates from character index 39",
+ "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
+ 39u,
+ 107u,
+ Size( 100.f, 300.f ),
+ 107u,
+ visualToLogical08
+ },
+ {
+ "Mix of left to right and right to left text. Updates from character index 70",
+ "Hello world, مرحبا بالعالم, hello world\nمرحبا بالعالم, hello world, مرحبا بالعالم\nمرحبا بالعالم\nhello world",
+ 70u,
+ 107u,
+ Size( 100.f, 300.f ),
+ 107u,
+ visualToLogical09
+ }
+ };
+ const unsigned int numberOfTests = 9u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !SetVisualToLogicalMapTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
// Tests the following functions for scripts with different number of bytes per character.
// Latin 1 byte per character, Arabic 2 bytes per character, Devanagari 3 bytes per character and emojis 4 bytes per character.
//
+// uint8_t GetUtf8Length( uint8_t utf8LeadByte );
// uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length );
// uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters );
// uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 );
//////////////////////////////////////////////////////////
+int UtcDaliTextCharacterSetConversionGetUtf8Length(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCharacterSetConversionGetUtf8Length");
+
+ // Copy of the table used to get the size in bytes of a character encoded with utf8.
+ // If the table used by the GetUtf8Length() function is updated, this one needs to be updated as well.
+ const static uint8_t U1 = 1u;
+ const static uint8_t U2 = 2u;
+ const static uint8_t U3 = 3u;
+ const static uint8_t U4 = 4u;
+ const static uint8_t U0 = 0u;
+ const static uint8_t UTF8_LENGTH[256] = {
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters)
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
+ U1, U1, //
+
+ U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, //
+ U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // lead byte = 110x xxxx (U+0080 - U+07FF)
+ U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, //
+ U2, U2, //
+
+ U3, U3, U3, U3, U3, U3, U3, U3, U3, U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF)
+ U3, U3, U3, U3, U3, U3, //
+
+ U4, U4, U4, U4, U4, U4, U4, U4, // lead byte = 1111 0xxx (U+10000 - U+1FFFFF)
+
+ U0, U0, U0, U0, // Non valid.
+ U0, U0, U0, U0, // Non valid.
+ };
+
+ for( unsigned int index = 0; index < 256u; ++index )
+ {
+ if( GetUtf8Length( index ) != UTF8_LENGTH[static_cast<uint8_t>(index)] )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+
int UtcDaliTextCharacterSetConversionGetNumberOfUtf8Characters(void)
{
ToolkitTestApplication application;
*/
#include <iostream>
-
#include <stdlib.h>
+#include <unistd.h>
+
+#include <dali/devel-api/text-abstraction/font-client.h>
#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/segmentation.h>
-#include <dali-toolkit/internal/text/multi-language-support.h>
#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/multi-language-helper-functions.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
-
using namespace Dali;
using namespace Toolkit;
using namespace Text;
// Tests the following functions with different scripts.
+//
+// void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
+// Vector<FontId>& fontIds,
+// const TextAbstraction::FontDescription& defaultFontDescription,
+// TextAbstraction::PointSize26Dot6 defaultPointSize,
+// CharacterIndex startIndex,
+// Length numberOfCharacters );
+//
+// Script GetScript( Length index,
+// Vector<ScriptRun>::ConstIterator& scriptRunIt,
+// const Vector<ScriptRun>::ConstIterator& scriptRunEndIt );
+//
// Constructor, destructor and MultilanguageSupport::Get()
-// void MultilanguageSupport::SetScripts( const Vector<Character>& text, const Vector<LineBreakInfo>& lineBreakInfo, Vector<ScriptRun>& scripts );
+//
+// void MultilanguageSupport::SetScripts( const Vector<Character>& text,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
+// Vector<ScriptRun>& scripts );
+//
// void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
// const Vector<ScriptRun>& scripts,
// const Vector<FontDescriptionRun>& fontDescriptions,
// FontId defaultFontId,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
// Vector<FontRun>& fonts );
//////////////////////////////////////////////////////////
namespace
{
+const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+const unsigned int EMOJI_FONT_SIZE = 3968u;
+const unsigned int NON_DEFAULT_FONT_SIZE = 40u;
+
+struct MergeFontDescriptionsData
+{
+ std::string description; ///< Description of the experiment.
+ Vector<FontDescriptionRun> fontDescriptionRuns; ///< The font description runs.
+ TextAbstraction::FontDescription defaultFontDescription; ///< The default font description.
+ TextAbstraction::PointSize26Dot6 defaultPointSize; ///< The default point size.
+ unsigned int startIndex; ///< The start index.
+ unsigned int numberOfCharacters; ///< The number of characters.
+ Vector<FontId> expectedFontIds; ///< The expected font ids.
+};
+
struct ScriptsData
{
- std::string description; ///< Description of the experiment.
- std::string text; ///< Input text.
- Vector<ScriptRun> scriptRuns; ///< Expected script runs.
+ std::string description; ///< Description of the experiment.
+ std::string text; ///< Input text.
+ unsigned int index; ///< The index of the first character to update the script.
+ unsigned int numberOfCharacters; ///< The numbers of characters to update the script.
+ Vector<ScriptRun> scriptRuns; ///< Expected script runs.
};
struct ValidateFontsData
{
- std::string description; ///< Description of the experiment.
- std::string text; ///< Input text.
+ std::string description; ///< Description of the experiment.
+ std::string text; ///< Input text.
+ std::string defaultFont; ///< The default font.
+ unsigned int defaultFontSize; ///< The default font size.
+ unsigned int index; ///< The index of the first character to update the script.
+ unsigned int numberOfCharacters; ///< The numbers of characters to update the script.
+ Vector<FontDescriptionRun> fontDescriptionRuns; ///< The font description runs.
+ Vector<FontRun> fontRuns; ///< The expected font runs.
};
//////////////////////////////////////////////////////////
+bool MergeFontDescriptionsTest( const MergeFontDescriptionsData& data )
+{
+ Vector<FontId> fontIds;
+ fontIds.Resize( data.startIndex + data.numberOfCharacters, 0u );
+
+ MergeFontDescriptions( data.fontDescriptionRuns,
+ fontIds,
+ data.defaultFontDescription,
+ data.defaultPointSize,
+ data.startIndex,
+ data.numberOfCharacters );
+
+ if( fontIds.Count() != data.expectedFontIds.Count() )
+ {
+ std::cout << data.description << " Different number of font ids : " << fontIds.Count() << ", expected : " << data.expectedFontIds.Count() << std::endl;
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < fontIds.Count(); ++index )
+ {
+ if( fontIds[index] != data.expectedFontIds[index] )
+ {
+ std::cout << data.description << " Different font id at index : " << index << ", font id : " << fontIds[index] << ", expected : " << data.expectedFontIds[index] << std::endl;
+ std::cout << " font ids : ";
+ for( unsigned int i=0;i<fontIds.Count();++i)
+ {
+ std::cout << fontIds[i] << " ";
+ }
+ std::cout << std::endl;
+ std::cout << " expected font ids : ";
+ for( unsigned int i=0;i<data.expectedFontIds.Count();++i)
+ {
+ std::cout << data.expectedFontIds[i] << " ";
+ }
+ std::cout << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool ScriptsTest( const ScriptsData& data )
{
MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
// 2) Set the script info.
Vector<ScriptRun> scripts;
multilanguageSupport.SetScripts( utf32,
+ 0u,
+ numberOfCharacters,
scripts );
- // 3) Compare the results.
+ if( ( 0u != data.index ) ||
+ ( numberOfCharacters != data.numberOfCharacters ) )
+ {
+ // 3) Clear the scripts.
+ ClearCharacterRuns( data.index,
+ data.index + data.numberOfCharacters - 1u,
+ scripts );
+
+ multilanguageSupport.SetScripts( utf32,
+ data.index,
+ data.numberOfCharacters,
+ scripts );
+ }
+
+ // 4) Compare the results.
tet_printf( "Testing %s\n", data.description.c_str() );
if( scripts.Count() != data.scriptRuns.Count() )
bool ValidateFontTest( const ValidateFontsData& data )
{
MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
// 1) Convert to utf32
Vector<Character> utf32;
// 2) Set the script info.
Vector<ScriptRun> scripts;
multilanguageSupport.SetScripts( utf32,
+ 0u,
+ numberOfCharacters,
scripts );
+ char* pathNamePtr = get_current_dir_name();
+ const std::string pathName( pathNamePtr );
+ free( pathNamePtr );
+
+ // Get the default font id.
+ const FontId defaultFontId = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + data.defaultFont,
+ data.defaultFontSize );
+
// To be completed ...
- Vector<FontDescriptionRun> fontDescriptions;
- FontId defaultFontId = 0u;
- Vector<FontRun> fonts;
+ Vector<FontRun> fontRuns;
- // 3) Validate the fonts
+ // 3) Validate the fonts.
multilanguageSupport.ValidateFonts( utf32,
scripts,
- fontDescriptions,
+ data.fontDescriptionRuns,
defaultFontId,
- fonts );
+ 0u,
+ numberOfCharacters,
+ fontRuns );
+
+ if( ( 0u != data.index ) ||
+ ( numberOfCharacters != data.numberOfCharacters ) )
+ {
+ // 4) Clear the fonts.
+ ClearCharacterRuns( data.index,
+ data.index + data.numberOfCharacters - 1u,
+ fontRuns );
+
+ multilanguageSupport.ValidateFonts( utf32,
+ scripts,
+ data.fontDescriptionRuns,
+ defaultFontId,
+ data.index,
+ data.numberOfCharacters,
+ fontRuns );
+ }
+
+ // 5) Compare the results.
+ if( data.fontRuns.Count() != fontRuns.Count() )
+ {
+ std::cout << " Different number of font runs : " << fontRuns.Count() << ", expected : " << data.fontRuns.Count() << std::endl;
+ return false;
+ }
+
+
+ for( unsigned int index = 0; index < data.fontRuns.Count(); ++index )
+ {
+ const FontRun& run = fontRuns[index];
+ const FontRun& expectedRun = data.fontRuns[index];
+
+ if( run.characterRun.characterIndex != expectedRun.characterRun.characterIndex )
+ {
+ std::cout << " character run : " << index << ", index : " << run.characterRun.characterIndex << ", expected : " << expectedRun.characterRun.characterIndex << std::endl;
+ return false;
+ }
+ if( run.characterRun.numberOfCharacters != expectedRun.characterRun.numberOfCharacters )
+ {
+ std::cout << " character run : " << index << ", num chars : " << run.characterRun.numberOfCharacters << ", expected : " << expectedRun.characterRun.numberOfCharacters << std::endl;
+ return false;
+ }
+ if( run.fontId != expectedRun.fontId )
+ {
+ std::cout << " character run : " << index << ", font : " << run.fontId << ", expected : " << expectedRun.fontId << std::endl;
+ return false;
+ }
+ }
+
return true;
}
} // namespace
+int UtcDaliTextGetScript(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextGetScript");
+
+ Script script = TextAbstraction::LATIN;
+
+ // Text with no scripts.
+ Vector<ScriptRun> scriptRuns;
+ Vector<ScriptRun>::ConstIterator scriptRunIt = scriptRuns.Begin();
+ script = GetScript( 0u,
+ scriptRunIt,
+ scriptRuns.End() );
+
+ DALI_TEST_CHECK( TextAbstraction::UNKNOWN == script );
+
+ const unsigned int numberOfCharacters = 7u;
+ // Add scripts.
+ ScriptRun scriptRun01 =
+ {
+ {
+ 0u,
+ 2u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun02 =
+ {
+ {
+ 2u,
+ 2u,
+ },
+ TextAbstraction::HEBREW
+ };
+ ScriptRun scriptRun03 =
+ {
+ {
+ 4u,
+ 2u,
+ },
+ TextAbstraction::ARABIC
+ };
+ scriptRuns.PushBack( scriptRun01 );
+ scriptRuns.PushBack( scriptRun02 );
+ scriptRuns.PushBack( scriptRun03 );
+
+ // Expected results
+ TextAbstraction::Script expectedScripts[]=
+ {
+ TextAbstraction::LATIN,
+ TextAbstraction::LATIN,
+ TextAbstraction::HEBREW,
+ TextAbstraction::HEBREW,
+ TextAbstraction::ARABIC,
+ TextAbstraction::ARABIC,
+ TextAbstraction::UNKNOWN
+ };
+
+ scriptRunIt = scriptRuns.Begin();
+ for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+ {
+ script = GetScript( index,
+ scriptRunIt,
+ scriptRuns.End() );
+
+ DALI_TEST_CHECK( expectedScripts[index] == script );
+ }
+ DALI_TEST_CHECK( scriptRunIt == scriptRuns.End() );
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextMergeFontDescriptions(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMergeFontDescriptions");
+
+ // Load some fonts.
+
+ char* pathNamePtr = get_current_dir_name();
+ const std::string pathName( pathNamePtr );
+ free( pathNamePtr );
+
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf" );
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf" );
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif.ttf", NON_DEFAULT_FONT_SIZE );
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Bold.ttf" );
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSerif-Italic.ttf" );
+
+ // To test the font width as GetFontId() with the font file path can't cache the width property.
+ TextAbstraction::FontDescription widthDescription;
+ widthDescription.path = "";
+ widthDescription.family = "DejaVu Serif";
+ widthDescription.weight = TextAbstraction::FontWeight::NORMAL;
+ widthDescription.width = TextAbstraction::FontWidth::EXPANDED;
+ widthDescription.slant = TextAbstraction::FontSlant::NORMAL;
+ fontClient.GetFontId( widthDescription );
+
+ // Test.
+
+ TextAbstraction::FontDescription defaultFontDescription01;
+ Vector<FontDescriptionRun> fontDescriptionRuns01;
+ Vector<FontId> expectedFontIds01;
+
+ TextAbstraction::FontDescription defaultFontDescription02;
+ Vector<FontDescriptionRun> fontDescriptionRuns02;
+ Vector<FontId> expectedFontIds02;
+ expectedFontIds02.PushBack( 0u );
+ expectedFontIds02.PushBack( 0u );
+
+ TextAbstraction::FontDescription defaultFontDescription03;
+ defaultFontDescription03.family = "DejaVu Serif";
+ Vector<FontDescriptionRun> fontDescriptionRuns03;
+
+ FontDescriptionRun fontDescription0301 =
+ {
+ {
+ 0u,
+ 2u
+ },
+ const_cast<char*>( "DejaVu Sans" ),
+ 11u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ FontDescriptionRun fontDescription0302 =
+ {
+ {
+ 2u,
+ 2u
+ },
+ NULL,
+ 0u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::ITALIC,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ false,
+ false,
+ false,
+ true,
+ false
+ };
+ FontDescriptionRun fontDescription0303 =
+ {
+ {
+ 4u,
+ 2u
+ },
+ NULL,
+ 0u,
+ TextAbstraction::FontWeight::BOLD,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ false,
+ true,
+ false,
+ false,
+ false
+ };
+ FontDescriptionRun fontDescription0304 =
+ {
+ {
+ 6u,
+ 2u
+ },
+ NULL,
+ 0u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ NON_DEFAULT_FONT_SIZE,
+ false,
+ false,
+ false,
+ false,
+ true
+ };
+ FontDescriptionRun fontDescription0305 =
+ {
+ {
+ 8u,
+ 2u
+ },
+ NULL,
+ 0u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::EXPANDED,
+ TextAbstraction::FontSlant::NORMAL,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ false,
+ false,
+ true,
+ false,
+ false
+ };
+
+ fontDescriptionRuns03.PushBack( fontDescription0301 );
+ fontDescriptionRuns03.PushBack( fontDescription0302 );
+ fontDescriptionRuns03.PushBack( fontDescription0303 );
+ fontDescriptionRuns03.PushBack( fontDescription0304 );
+ fontDescriptionRuns03.PushBack( fontDescription0305 );
+
+ Vector<FontId> expectedFontIds03;
+ expectedFontIds03.PushBack( 1u );
+ expectedFontIds03.PushBack( 1u );
+ expectedFontIds03.PushBack( 5u );
+ expectedFontIds03.PushBack( 5u );
+ expectedFontIds03.PushBack( 4u );
+ expectedFontIds03.PushBack( 4u );
+ expectedFontIds03.PushBack( 3u );
+ expectedFontIds03.PushBack( 3u );
+ expectedFontIds03.PushBack( 6u );
+ expectedFontIds03.PushBack( 6u );
+
+ const MergeFontDescriptionsData data[] =
+ {
+ {
+ "void text.",
+ fontDescriptionRuns01,
+ defaultFontDescription01,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 0u,
+ expectedFontIds01
+ },
+ {
+ "No description runs.",
+ fontDescriptionRuns02,
+ defaultFontDescription02,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 2u,
+ expectedFontIds02
+ },
+ {
+ "Some description runs.",
+ fontDescriptionRuns03,
+ defaultFontDescription03,
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 10u,
+ expectedFontIds03
+ }
+ };
+ const unsigned int numberOfTests = 3u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !MergeFontDescriptionsTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
int UtcDaliTextMultiLanguageConstructor(void)
{
ToolkitTestApplication application;
{
{
163u,
- 35u,
+ 18u,
+ },
+ TextAbstraction::HANGUL
+ };
+ ScriptRun scriptRun1011 =
+ {
+ {
+ 181u,
+ 17u,
},
TextAbstraction::HANGUL
};
scriptRuns10.PushBack( scriptRun1008 );
scriptRuns10.PushBack( scriptRun1009 );
scriptRuns10.PushBack( scriptRun1010 );
+ scriptRuns10.PushBack( scriptRun1011 );
// Paragraphs with no scripts mixed with paragraphs with scripts.
Vector<ScriptRun> scriptRuns11;
{
{
0u,
- 31u,
+ 3u,
},
TextAbstraction::LATIN
};
ScriptRun scriptRun1101 =
{
{
+ 3u,
+ 3u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1102 =
+ {
+ {
+ 6u,
+ 19u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1103 =
+ {
+ {
+ 25u,
+ 3u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1104 =
+ {
+ {
+ 28u,
+ 3u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1105 =
+ {
+ {
31u,
- 21u,
+ 15u,
},
TextAbstraction::HEBREW
};
+ ScriptRun scriptRun1106 =
+ {
+ {
+ 46u,
+ 2u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1107 =
+ {
+ {
+ 48u,
+ 2u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1108 =
+ {
+ {
+ 50u,
+ 2u,
+ },
+ TextAbstraction::LATIN
+ };
scriptRuns11.PushBack( scriptRun1100 );
scriptRuns11.PushBack( scriptRun1101 );
+ scriptRuns11.PushBack( scriptRun1102 );
+ scriptRuns11.PushBack( scriptRun1103 );
+ scriptRuns11.PushBack( scriptRun1104 );
+ scriptRuns11.PushBack( scriptRun1105 );
+ scriptRuns11.PushBack( scriptRun1106 );
+ scriptRuns11.PushBack( scriptRun1107 );
+ scriptRuns11.PushBack( scriptRun1108 );
// Paragraphs with no scripts.
Vector<ScriptRun> scriptRuns12;
{
{
0u,
- 11u,
+ 3u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1201 =
+ {
+ {
+ 3u,
+ 3u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1202 =
+ {
+ {
+ 6u,
+ 3u,
+ },
+ TextAbstraction::LATIN
+ };
+ ScriptRun scriptRun1203 =
+ {
+ {
+ 9u,
+ 2u,
},
TextAbstraction::LATIN
};
scriptRuns12.PushBack( scriptRun1200 );
+ scriptRuns12.PushBack( scriptRun1201 );
+ scriptRuns12.PushBack( scriptRun1202 );
+ scriptRuns12.PushBack( scriptRun1203 );
+
+ Vector<ScriptRun> scriptRuns13;
+ ScriptRun scriptRun1301 =
+ {
+ {
+ 0u,
+ 4u,
+ },
+ TextAbstraction::LATIN // An unknown script is transformed to LATIN
+ };
+ scriptRuns13.PushBack( scriptRun1301 );
const ScriptsData data[] =
{
{
"void text",
"",
+ 0u,
+ 0u,
scriptRuns00,
},
{
"Easy latin script",
"Hello world",
+ 0u,
+ 11u,
scriptRuns01,
},
{
"Mix of LTR '\\n'and RTL",
"Hello world\nمرحبا بالعالم",
+ 0u,
+ 25u,
+ scriptRuns02,
+ },
+ {
+ "Update mix of LTR '\\n'and RTL. Update LTR",
+ "Hello world\nمرحبا بالعالم",
+ 0u,
+ 12u,
+ scriptRuns02,
+ },
+ {
+ "Update mix of LTR '\\n'and RTL. Update RTL",
+ "Hello world\nمرحبا بالعالم",
+ 12u,
+ 13u,
scriptRuns02,
},
{
"Mix of RTL '\\n'and LTR",
"مرحبا بالعالم\nHello world",
+ 0u,
+ 25u,
+ scriptRuns03,
+ },
+ {
+ "Update mix of RTL '\\n'and LTR. Update RTL",
+ "مرحبا بالعالم\nHello world",
+ 0u,
+ 14u,
+ scriptRuns03,
+ },
+ {
+ "Update mix of RTL '\\n'and LTR. Update LTR",
+ "مرحبا بالعالم\nHello world",
+ 14u,
+ 11u,
scriptRuns03,
},
{
"White spaces. At the beginning of the text.",
" Hello world.",
+ 0u,
+ 16u,
scriptRuns04,
},
{
"White spaces. At the end of the text.",
"Hello world. ",
+ 0u,
+ 16u,
scriptRuns05,
},
{
"White spaces. At the middle of the text.",
"Hello world.",
+ 0u,
+ 16u,
scriptRuns06,
},
{
"White spaces between different scripts.",
" Hel 세계 ",
+ 0u,
+ 13u,
scriptRuns07,
},
{
"White spaces between different scripts and differetn directions. Starting LTR.",
" Hello world مرحبا بالعالم 안녕하세요 세계 ",
+ 0u,
+ 50u,
scriptRuns08,
},
{
"White spaces between different scripts and differetn directions. Starting RTL.",
" مرحبا بالعالم Hello world 안녕하세요 세계 مرحبا بالعالم ",
+ 0u,
+ 67u,
scriptRuns09
},
{
" مرحبا بالعالم Hello world שלום עולם \n "
" Hello world مرحبا بالعالم 안녕하세요 세계 \n "
" 안녕하세요 세계 ",
+ 0u,
+ 198u,
+ scriptRuns10
+ },
+ {
+ "Update paragraphs with different directions. Update initial paragraphs.",
+ " مرحبا بالعالم שלום עולם مرحبا بالعالم \n "
+ " Hello world 안녕하세요 세계 \n "
+ " مرحبا بالعالم Hello world שלום עולם \n "
+ " Hello world مرحبا بالعالم 안녕하세요 세계 \n "
+ " 안녕하세요 세계 ",
+ 0u,
+ 81u,
+ scriptRuns10
+ },
+ {
+ "Update paragraphs with different directions. Update middle paragraphs.",
+ " مرحبا بالعالم שלום עולם مرحبا بالعالم \n "
+ " Hello world 안녕하세요 세계 \n "
+ " مرحبا بالعالم Hello world שלום עולם \n "
+ " Hello world مرحبا بالعالم 안녕하세요 세계 \n "
+ " 안녕하세요 세계 ",
+ 49u,
+ 80u,
+ scriptRuns10
+ },
+ {
+ "Update paragraphs with different directions. Update final paragraphs.",
+ " مرحبا بالعالم שלום עולם مرحبا بالعالم \n "
+ " Hello world 안녕하세요 세계 \n "
+ " مرحبا بالعالم Hello world שלום עולם \n "
+ " Hello world مرحبا بالعالم 안녕하세요 세계 \n "
+ " 안녕하세요 세계 ",
+ 129u,
+ 69u,
scriptRuns10
},
{
"Paragraphs with no scripts mixed with paragraphs with scripts.",
" \n \n Hello world \n \n \n שלום עולם \n \n \n ",
+ 0u,
+ 52u,
scriptRuns11
},
{
"Paragraphs with no scripts.",
" \n \n \n ",
+ 0u,
+ 11u,
scriptRuns12
+ },
+ {
+ "Update paragraphs with no scripts. Update initial paragraphs.",
+ " \n \n \n ",
+ 0u,
+ 3u,
+ scriptRuns12
+ },
+ {
+ "Update paragraphs with no scripts. Update middle paragraphs.",
+ " \n \n \n ",
+ 3u,
+ 6u,
+ scriptRuns12
+ },
+ {
+ "Update paragraphs with no scripts. Update final paragraphs.",
+ " \n \n \n ",
+ 9u,
+ 2u,
+ scriptRuns12
+ },
+ {
+ "Unknown scripts.",
+ "ᚩᚯᚱᚸ", // Runic script not currentlu supported.
+ 0u,
+ 4u,
+ scriptRuns13
}
};
- const unsigned int numberOfTests = 13u;
+ const unsigned int numberOfTests = 24u;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+
+ char* pathNamePtr = get_current_dir_name();
+ const std::string pathName( pathNamePtr );
+ free( pathNamePtr );
+
+ // Load some fonts.
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+ fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenColorEmoji.ttf", EMOJI_FONT_SIZE );
+
+ // Font id 1 --> TizenSansArabicRegular.ttf
+ // Font id 2 --> TizenSansHebrewRegular.ttf
+ // Font id 3 --> TizenColorEmoji.ttf
+ // Font id 4 --> (default)
+
+ Vector<FontRun> fontRuns01;
+ Vector<FontDescriptionRun> fontDescriptions01;
+
+ FontRun fontRun0201 =
+ {
+ {
+ 0u,
+ 11u
+ },
+ 4u
+ };
+ Vector<FontRun> fontRuns02;
+ fontRuns02.PushBack( fontRun0201 );
+
+ FontDescriptionRun fontDescription0201 =
+ {
+ {
+ 0u,
+ 11u
+ },
+ const_cast<char*>( "TizenSans" ),
+ 9u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ 0u,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ Vector<FontDescriptionRun> fontDescriptions02;
+ fontDescriptions02.PushBack( fontDescription0201 );
+
+ FontRun fontRun0301 =
+ {
+ {
+ 0u,
+ 12u
+ },
+ 4u
+ };
+ FontRun fontRun0302 =
+ {
+ {
+ 12u,
+ 12u
+ },
+ 4u
+ };
+ FontRun fontRun0303 =
+ {
+ {
+ 24u,
+ 4u
+ },
+ 4u
+ };
+ Vector<FontRun> fontRuns03;
+ fontRuns03.PushBack( fontRun0301 );
+ fontRuns03.PushBack( fontRun0302 );
+ fontRuns03.PushBack( fontRun0303 );
+
+ Vector<FontDescriptionRun> fontDescriptions03;
+
+ FontRun fontRun0701 =
+ {
+ {
+ 0u,
+ 4u
+ },
+ 2u
+ };
+ FontRun fontRun0702 =
+ {
+ {
+ 4u,
+ 1u
+ },
+ 4u
+ };
+ FontRun fontRun0703 =
+ {
+ {
+ 5u,
+ 4u
+ },
+ 2u
+ };
+ Vector<FontRun> fontRuns07;
+ fontRuns07.PushBack( fontRun0701 );
+ fontRuns07.PushBack( fontRun0702 );
+ fontRuns07.PushBack( fontRun0703 );
+
+ FontDescriptionRun fontDescription0701 =
+ {
+ {
+ 0u,
+ 4u
+ },
+ const_cast<char*>( "TizenSansHebrew" ),
+ 15u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ 0u,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ FontDescriptionRun fontDescription0702 =
+ {
+ {
+ 5u,
+ 4u
+ },
+ const_cast<char*>( "TizenSansHebrew" ),
+ 15u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ 0u,
+ true,
+ false,
+ false,
+ false,
+ false
+ };
+ Vector<FontDescriptionRun> fontDescriptions07;
+ fontDescriptions07.PushBack( fontDescription0701 );
+ fontDescriptions07.PushBack( fontDescription0702 );
+
+ FontRun fontRun0801 =
+ {
+ {
+ 0u,
+ 9u
+ },
+ 2u
+ };
+ Vector<FontRun> fontRuns08;
+ fontRuns08.PushBack( fontRun0801 );
+
+ Vector<FontDescriptionRun> fontDescriptions08;
+
+ FontRun fontRun0901 =
+ {
+ {
+ 0u,
+ 4u
+ },
+ 3u
+ };
+ Vector<FontRun> fontRuns09;
+ fontRuns09.PushBack( fontRun0901 );
+
+ Vector<FontDescriptionRun> fontDescriptions09;
+ FontDescriptionRun fontDescription0901 =
+ {
+ {
+ 0u,
+ 4u
+ },
+ const_cast<char*>( "TizenColorEmoji" ),
+ 15u,
+ TextAbstraction::FontWeight::NORMAL,
+ TextAbstraction::FontWidth::NORMAL,
+ TextAbstraction::FontSlant::NORMAL,
+ EMOJI_FONT_SIZE,
+ true,
+ false,
+ false,
+ false,
+ true
+ };
+ fontDescriptions09.PushBack( fontDescription0901 );
+
const ValidateFontsData data[] =
{
{
- "void text",
+ "void text.",
"",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 0u,
+ fontDescriptions01,
+ fontRuns01
},
{
- "Easy latin script",
+ "Easy latin script.",
"Hello world",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 11u,
+ fontDescriptions02,
+ fontRuns02
+ },
+ {
+ "Different paragraphs.",
+ "Hello world\nhello world\ndemo",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 28u,
+ fontDescriptions03,
+ fontRuns03
+ },
+ {
+ "Different paragraphs. Update the initial paragraph.",
+ "Hello world\nhello world\ndemo",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 12u,
+ fontDescriptions03,
+ fontRuns03
+ },
+ {
+ "Different paragraphs. Update the middle paragraph.",
+ "Hello world\nhello world\ndemo",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 12u,
+ 12u,
+ fontDescriptions03,
+ fontRuns03
+ },
+ {
+ "Different paragraphs. Update the final paragraph.",
+ "Hello world\nhello world\ndemo",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 24u,
+ 4u,
+ fontDescriptions03,
+ fontRuns03
+ },
+ {
+ "Hebrew text. Default font: latin",
+ "שלום עולם",
+ "/tizen/TizenSansRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 9u,
+ fontDescriptions07,
+ fontRuns07
+ },
+ {
+ "Hebrew text. Default font: hebrew",
+ "שלום עולם",
+ "/tizen/TizenSansHebrewRegular.ttf",
+ TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
+ 0u,
+ 9u,
+ fontDescriptions08,
+ fontRuns08
+ },
+ {
+ "Emojis",
+ "\xF0\x9F\x98\x81\xF0\x9F\x98\x82\xF0\x9F\x98\x83\xF0\x9F\x98\x84",
+ "/tizen/TizenColorEmoji.ttf",
+ EMOJI_FONT_SIZE,
+ 0u,
+ 4u,
+ fontDescriptions09,
+ fontRuns09
},
};
- const unsigned int numberOfTests = 2u;
+ const unsigned int numberOfTests = 9u;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
using namespace Text;
// Tests the following functions with different scripts.
-// void SetLineBreakInfo( const Vector<Character>& text, Vector<LineBreakInfo>& lineBreakInfo );
-// void SetWordBreakInfo( const Vector<Character>& text, Vector<WordBreakInfo>& wordBreakInfo );
+// void SetLineBreakInfo( const Vector<Character>& text,
+// Vector<LineBreakInfo>& lineBreakInfo );
+// void SetWordBreakInfo( const Vector<Character>& text,
+// CharacterIndex startIndex,
+// Length numberOfCharacters,
+// Vector<WordBreakInfo>& wordBreakInfo );
//////////////////////////////////////////////////////////
struct BreakInfoData
{
- std::string description; ///< Description of the test.
- std::string text; ///< input text.
- std::string breakInfo; ///< The expected break info.
+ std::string description; ///< Description of the test.
+ std::string text; ///< input text.
+ uint32_t index; ///< The index from where to start to query the break info.
+ uint32_t numberOfCharacters; ///< The requested number of characters.
+ std::string breakInfo; ///< The expected break info.
};
bool LineBreakInfoTest( const BreakInfoData& data )
const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
data.text.size(),
&utf32[0u] );
+
utf32.Resize( numberOfCharacters );
// 2) Set the line break info.
breakInfo << static_cast<unsigned int>( lineBreakInfo[index] );
}
- return data.breakInfo == breakInfo.str();
+ if( data.breakInfo != breakInfo.str() )
+ {
+ std::cout << " expected : [" << data.breakInfo << "]" << std::endl;
+ std::cout << " got : [" << breakInfo.str() << "]" << std::endl;
+ return false;
+ }
+
+ return true;
}
bool WordBreakInfoTest( const BreakInfoData& data )
const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
data.text.size(),
&utf32[0u] );
+
utf32.Resize( numberOfCharacters );
- // 2) Set the word break info.
+ // 2) Set the word break info for the whole text.
Vector<WordBreakInfo> wordBreakInfo;
wordBreakInfo.Resize( numberOfCharacters );
- SetWordBreakInfo( utf32, wordBreakInfo );
+ SetWordBreakInfo( utf32,
+ 0u,
+ numberOfCharacters,
+ wordBreakInfo );
- // 3) compare the results
+ // 3) Update the word text info if it's requested for part of the text.
+ if( ( 0u != data.index ) &&
+ ( numberOfCharacters != data.numberOfCharacters ) )
+ {
+ // Clear part of the word break info.
+ wordBreakInfo.Erase( wordBreakInfo.Begin() + data.index,
+ wordBreakInfo.Begin() + data.index + data.numberOfCharacters );
+
+ // Update the word break info.
+ SetWordBreakInfo( utf32,
+ data.index,
+ data.numberOfCharacters,
+ wordBreakInfo );
+ }
+
+ // 4) compare the results
std::ostringstream breakInfo;
for( unsigned int index = 0u; index < numberOfCharacters; ++index )
breakInfo << static_cast<unsigned int>( wordBreakInfo[index] );
}
- return data.breakInfo == breakInfo.str();
+ if( data.breakInfo != breakInfo.str() )
+ {
+ std::cout << " text : [" << data.text << "]" << std::endl;
+ std::cout << " index : " << data.index << std::endl;
+ std::cout << " numberOfCharacters : " << data.numberOfCharacters << std::endl;
+ std::cout << " expected : [" << data.breakInfo << "]" << std::endl;
+ std::cout << " got : [" << breakInfo.str() << "]" << std::endl;
+ return false;
+ }
+
+ return true;
}
} // namespace
{
"Zero characters",
"",
+ 0u,
+ 0u,
"",
},
{
"Latin script",
- "Hello world",
- "22222122220",
- },
- {
- "Latin script with \n",
- "Hello\nworld",
- "22222022220",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 0u,
+ 317u,
+ "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+ "2221221222212222222122222222221222222122222222122222222122212220"
+ "221222122222122222221222222222122212222221222222212220"
+ "22122222212222222122222222222122221222122222122222222222122222222222212220"
+ "222222122222221221222212212221222222122222222220",
},
{
"Japanese script",
- "こんにちは世界",
- "1111110",
- },
- {
- "Japanese script with \n",
- "こんにちは\n世界",
- "11112010",
+ "韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
+ "国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
+ "韓国統一省によると15年だけで1320億ウォン(約130億円)が同工業団地を通じ北朝鮮に支払われたという。",
+ 0u,
+ 132u,
+ "1111111111111111111111220"
+ "111111211111111111111111111111111111111111111111111220"
+ "11111111121111122211111212211211111111111111111111120",
},
{
"Chinese script",
- "你好世界",
- "1110",
- },
- {
- "Chinese script with \n",
- "你好\n世界",
- "12010",
+ "在被捕的64人中,警方落案起訴了35名男子和3名女子,他們年齡介乎15到70歲。\n"
+ "38人中有1人獲准保釋。\n"
+ "16名年齡介乎14到33歲的被捕人士獲准保釋候查,另有10人仍被拘留作進一步調查。",
+ 0u,
+ 95u,
+ "11112112111111112111111112111111121121220"
+ "2111111111220"
+ "21111112112111111111111211121111111111120",
}
};
- const unsigned int numberOfTests = 7u;
+ const unsigned int numberOfTests = 4u;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
struct BreakInfoData data[] =
{
{
- "Zero characters",
+ "Zero characters.",
"",
+ 0u,
+ 0u,
"",
},
{
- "Latin script",
- "Hello world",
- "11110011110",
+ "Latin script, full text.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 0u,
+ 317u,
+ "11110011110011110011001110001111001111111110010011000111100111111110010011000"
+ "1100100111001111110011111111000111110011111110011111110011001000"
+ "100110011110011111100111111100011001111100111111001000"
+ "10011111001111110011111111110011000110011110011111111110011111111111001000"
+ "111110011111100100110001001100111110011111111100",
},
{
- "Latin script with \n",
- "Hello\nworld",
- "11110011110",
+ "Latin script, update first paragraph.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 0u,
+ 77u,
+ "11110011110011110011001110001111001111111110010011000111100111111110010011000"
+ "1100100111001111110011111111000111110011111110011111110011001000"
+ "100110011110011111100111111100011001111100111111001000"
+ "10011111001111110011111111110011000110011110011111111110011111111111001000"
+ "111110011111100100110001001100111110011111111100",
},
{
- "Japanese script",
- "こんにちは世界",
- "0000000",
+ "Latin script, update middle paragraphs.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 77u,
+ 118u,
+ "11110011110011110011001110001111001111111110010011000111100111111110010011000"
+ "1100100111001111110011111111000111110011111110011111110011001000"
+ "100110011110011111100111111100011001111100111111001000"
+ "10011111001111110011111111110011000110011110011111111110011111111111001000"
+ "111110011111100100110001001100111110011111111100",
},
{
- "Japanese script with \n",
- "こんにちは\n世界",
- "00000000",
+ "Latin script, update last paragraph.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 269u,
+ 48u,
+ "11110011110011110011001110001111001111111110010011000111100111111110010011000"
+ "1100100111001111110011111111000111110011111110011111110011001000"
+ "100110011110011111100111111100011001111100111111001000"
+ "10011111001111110011111111110011000110011110011111111110011111111111001000"
+ "111110011111100100110001001100111110011111111100",
},
{
- "Chinese script",
- "你好世界",
- "0000",
+ "Japanese script, full text.",
+ "韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
+ "国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
+ "韓国統一省によると15年だけで1320億ウォン(約130億円)が同工業団地を通じ北朝鮮に支払われたという。",
+ 0u,
+ 132u,
+ "0000000000000010000000000"
+ "000000000000000000000000000000000000000000000000000000"
+ "00000000010000011100110001100000000000000000000000000",
+ },
+ {
+ "Japanese script, update first paragraph.",
+ "韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
+ "国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
+ "韓国統一省によると15年だけで1320億ウォン(約130億円)が同工業団地を通じ北朝鮮に支払われたという。",
+ 0u,
+ 25u,
+ "0000000000000010000000000"
+ "000000000000000000000000000000000000000000000000000000"
+ "00000000010000011100110001100000000000000000000000000",
+ },
+ {
+ "Japanese script, update middle paragraph.",
+ "韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
+ "国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
+ "韓国統一省によると15年だけで1320億ウォン(約130億円)が同工業団地を通じ北朝鮮に支払われたという。",
+ 25u,
+ 54u,
+ "0000000000000010000000000"
+ "000000000000000000000000000000000000000000000000000000"
+ "00000000010000011100110001100000000000000000000000000",
+ },
+ {
+ "Japanese script, update last paragraph.",
+ "韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
+ "国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
+ "韓国統一省によると15年だけで1320億ウォン(約130億円)が同工業団地を通じ北朝鮮に支払われたという。",
+ 79u,
+ 53u,
+ "0000000000000010000000000"
+ "000000000000000000000000000000000000000000000000000000"
+ "00000000010000011100110001100000000000000000000000000",
+ },
+ {
+ "Chinese script, full text.",
+ "在被捕的64人中,警方落案起訴了35名男子和3名女子,他們年齡介乎15到70歲。\n"
+ "38人中有1人獲准保釋。\n"
+ "16名年齡介乎14到33歲的被捕人士獲准保釋候查,另有10人仍被拘留作進一步調查。",
+ 0u,
+ 95u,
+ "00001000000000001000000000000000010010000"
+ "1000000000000"
+ "10000001001000000000000000010000000000000",
+ },
+ {
+ "Chinese script, update first paragraph.",
+ "在被捕的64人中,警方落案起訴了35名男子和3名女子,他們年齡介乎15到70歲。\n"
+ "38人中有1人獲准保釋。\n"
+ "16名年齡介乎14到33歲的被捕人士獲准保釋候查,另有10人仍被拘留作進一步調查。",
+ 0u,
+ 41u,
+ "00001000000000001000000000000000010010000"
+ "1000000000000"
+ "10000001001000000000000000010000000000000",
+ },
+ {
+ "Chinese script, update middle paragraph.",
+ "在被捕的64人中,警方落案起訴了35名男子和3名女子,他們年齡介乎15到70歲。\n"
+ "38人中有1人獲准保釋。\n"
+ "16名年齡介乎14到33歲的被捕人士獲准保釋候查,另有10人仍被拘留作進一步調查。",
+ 41u,
+ 13u,
+ "00001000000000001000000000000000010010000"
+ "1000000000000"
+ "10000001001000000000000000010000000000000",
},
{
- "Chinese script with \n",
- "你好\n世界",
- "00000",
+ "Chinese script, update last paragraph.",
+ "在被捕的64人中,警方落案起訴了35名男子和3名女子,他們年齡介乎15到70歲。\n"
+ "38人中有1人獲准保釋。\n"
+ "16名年齡介乎14到33歲的被捕人士獲准保釋候查,另有10人仍被拘留作進一步調查。",
+ 54u,
+ 41u,
+ "00001000000000001000000000000000010010000"
+ "1000000000000"
+ "10000001001000000000000000010000000000000",
}
};
- const unsigned int numberOfTests = 7u;
+ const unsigned int numberOfTests = 13u;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "toolkit-text-model.h"
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-client.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/bidirectional-support.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/metrics.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/shaper.h>
+#include <dali-toolkit/internal/text/text-controller-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Frees previously allocated bidirectional resources.
+ *
+ * @param[in] bidirectionalLineInfo Bidirectional info per line.
+ * @param[in] index Index to the first line with bidirectional info to be freed.
+ */
+void FreeBidirectionalLineInfoResources( Vector<BidirectionalLineInfoRun> bidirectionalLineInfo,
+ uint32_t index )
+{
+ // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+ for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin() + index,
+ endIt = bidirectionalLineInfo.End();
+ it != endIt;
+ ++it )
+ {
+ BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+ free( bidiLineInfo.visualToLogicalMap );
+ }
+}
+
+/**
+ * @brief Clear all the model data except for LogicalModel::mText.
+ *
+ * @param[in] characterIndex Clear data starting from the index.
+ */
+void ClearModelData( CharacterIndex characterIndex,
+ LogicalModelPtr logicalModel,
+ VisualModelPtr visualModel )
+{
+ // n.b. This does not Clear the mText from mLogicalModel
+
+ // Frees previously allocated resources.
+ FreeBidirectionalLineInfoResources( logicalModel->mBidirectionalLineInfo, 0u );
+
+ logicalModel->mScriptRuns.Clear();
+ logicalModel->mFontRuns.Clear();
+ logicalModel->mWordBreakInfo.Clear();
+ logicalModel->mBidirectionalParagraphInfo.Clear();
+ logicalModel->mCharacterDirections.Clear();
+ logicalModel->mBidirectionalLineInfo.Clear();
+ logicalModel->mLogicalToVisualMap.Clear();
+ logicalModel->mVisualToLogicalMap.Clear();
+ visualModel->mGlyphs.Clear();
+ visualModel->mGlyphsToCharacters.Clear();
+ visualModel->mCharactersToGlyph.Clear();
+ visualModel->mCharactersPerGlyph.Clear();
+ visualModel->mGlyphsPerCharacter.Clear();
+ visualModel->mGlyphPositions.Clear();
+ visualModel->mLines.Clear();
+ visualModel->mColorRuns.Clear();
+
+ visualModel->ClearCaches();
+}
+
+void CreateTextModel( const std::string& text,
+ const Size& textArea,
+ Size& layoutSize,
+ LogicalModelPtr logicalModel,
+ VisualModelPtr visualModel )
+{
+ // 1) Convert to utf32
+ Vector<Character>& utf32Characters = logicalModel->mText;
+ utf32Characters.Resize( text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( text.c_str() ),
+ text.size(),
+ &utf32Characters[0u] );
+ utf32Characters.Resize( numberOfCharacters );
+
+ // 2) Set the break and paragraph info.
+ Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
+ lineBreakInfo.Resize( numberOfCharacters );
+
+ SetLineBreakInfo( utf32Characters, lineBreakInfo );
+
+ if( 0u == numberOfCharacters )
+ {
+ // Nothing else to do if the number of characters is zero.
+ return;
+ }
+
+ // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
+ Vector<WordBreakInfo>& wordBreakInfo = logicalModel->mWordBreakInfo;
+ wordBreakInfo.Resize( numberOfCharacters );
+
+ SetWordBreakInfo( utf32Characters,
+ 0u,
+ numberOfCharacters,
+ wordBreakInfo );
+
+ // 3) Set the script info.
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+ Vector<ScriptRun>& scripts = logicalModel->mScriptRuns;
+ multilanguageSupport.SetScripts( utf32Characters,
+ 0u,
+ numberOfCharacters,
+ scripts );
+
+ // 4) Set the font info
+ Vector<FontDescriptionRun>& fontDescriptionRuns = logicalModel->mFontDescriptionRuns;
+ Vector<FontRun>& validFonts = logicalModel->mFontRuns;
+
+ // The default font id.
+ FontDefaults fontDefaults;
+ fontDefaults.mFontDescription.family = "";
+ fontDefaults.familyDefined = true;
+ fontDefaults.mDefaultPointSize = 12.f;
+ fontDefaults.sizeDefined = true;
+
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+ fontClient.SetDpi( 96u, 96u );
+
+ const FontId defaultFontId = fontDefaults.GetFontId( fontClient );
+
+ // Validates the fonts. If there is a character with no assigned font it sets a default one.
+ // After this call, fonts are validated.
+ multilanguageSupport.ValidateFonts( utf32Characters,
+ scripts,
+ fontDescriptionRuns,
+ defaultFontId,
+ 0u,
+ numberOfCharacters,
+ validFonts );
+
+ // 5) Set the bidirectional info per paragraph.
+ Vector<Character> mirroredUtf32Characters;
+ bool textMirrored = false;
+
+ // Reserve some space for the vector of paragraph's bidirectional info.
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
+
+ // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
+ SetBidirectionalInfo( utf32Characters,
+ scripts,
+ lineBreakInfo,
+ 0u,
+ numberOfCharacters,
+ bidirectionalInfo );
+
+ // 6) Set character directions.
+ Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
+ if( 0u != bidirectionalInfo.Count() )
+ {
+ // Only set the character directions if there is right to left characters.
+ GetCharactersDirection( bidirectionalInfo,
+ numberOfCharacters,
+ 0u,
+ numberOfCharacters,
+ characterDirections );
+
+
+ // This paragraph has right to left text. Some characters may need to be mirrored.
+ textMirrored = GetMirroredText( utf32Characters,
+ characterDirections,
+ bidirectionalInfo,
+ 0u,
+ numberOfCharacters,
+ mirroredUtf32Characters );
+ }
+ else
+ {
+ // There is no right to left characters. Clear the directions vector.
+ characterDirections.Clear();
+ }
+
+ // 7) Shape the text.
+
+ Vector<GlyphInfo>& glyphs = visualModel->mGlyphs;
+ Vector<CharacterIndex>& glyphsToCharactersMap = visualModel->mGlyphsToCharacters;
+ Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph;
+ Vector<GlyphIndex> newParagraphGlyphs;
+
+ const Length currentNumberOfGlyphs = glyphs.Count();
+ const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
+
+ ShapeText( textToShape,
+ lineBreakInfo,
+ scripts,
+ validFonts,
+ glyphs,
+ glyphsToCharactersMap,
+ charactersPerGlyph,
+ newParagraphGlyphs );
+
+ // Create the 'number of glyphs' per character and the glyph to character conversion tables.
+ visualModel->CreateGlyphsPerCharacterTable( numberOfCharacters );
+ visualModel->CreateCharacterToGlyphTable( numberOfCharacters );
+
+ const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
+
+ // 8) Get the glyph metrics
+ MetricsPtr metrics = Metrics::New( fontClient );
+
+ const GlyphIndex glyphIndex = currentNumberOfGlyphs;
+
+ GlyphInfo* glyphsBuffer = glyphs.Begin() + glyphIndex;
+ metrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
+
+ // Update the width and advance of all new paragraph characters.
+ for( Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(),
+ endIt = newParagraphGlyphs.End();
+ it != endIt;
+ ++it )
+ {
+ const GlyphIndex index = *it;
+ GlyphInfo& glyph = *( glyphsBuffer + ( index - glyphIndex ) );
+
+ glyph.xBearing = 0.f;
+ glyph.width = 0.f;
+ glyph.advance = 0.f;
+ }
+
+ // 9) Layout the text
+ LayoutEngine layoutEngine;
+ layoutEngine.SetMetrics( metrics );
+ layoutEngine.SetLayout( LayoutEngine::MULTI_LINE_BOX );
+
+ // Set the layout parameters.
+ const Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
+ const Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+ LayoutParameters layoutParameters( textArea,
+ utf32Characters.Begin(),
+ lineBreakInfo.Begin(),
+ wordBreakInfo.Begin(),
+ ( 0u != characterDirections.Count() ) ? characterDirections.Begin() : NULL,
+ glyphs.Count(),
+ glyphs.Begin(),
+ glyphsToCharactersMap.Begin(),
+ charactersPerGlyph.Begin() );
+
+ // Get the character to glyph conversion table and set into the layout.
+ layoutParameters.charactersToGlyphsBuffer = charactersToGlyph.Begin();
+ // Get the glyphs per character table and set into the layout.
+ layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
+
+ Vector<LineRun>& lines = visualModel->mLines;
+
+ Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
+ glyphPositions.Resize( numberOfGlyphs );
+
+ layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( logicalModel->mText.Count() - 1u ) ) );
+
+ layoutEngine.LayoutText( layoutParameters,
+ glyphPositions,
+ lines,
+ layoutSize );
+
+ // 10) Reorder the lines
+ if( 0u != bidirectionalInfo.Count() )
+ {
+ Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = logicalModel->mBidirectionalLineInfo;
+
+ // Get the lines
+ const Length numberOfLines = lines.Count();
+
+ // Reorder the lines.
+ bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
+ ReorderLines( bidirectionalInfo,
+ 0u,
+ numberOfCharacters,
+ lines,
+ bidirectionalLineInfo );
+
+ // Set the bidirectional info per line into the layout parameters.
+ layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
+ layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
+
+ // Set the bidirectional info into the model.
+ logicalModel->SetVisualToLogicalMap( layoutParameters.lineBidirectionalInfoRunsBuffer,
+ layoutParameters.numberOfBidirectionalInfoRuns,
+ 0u,
+ numberOfCharacters );
+
+ // Re-layout the text. Reorder those lines with right to left characters.
+ layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
+ glyphPositions );
+ }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_MODEL_H__
+#define __DALI_TOOLKIT_TEXT_MODEL_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Creates and fills all the vectors of a text model: characters in utf32, segmentation info,
+ * scripts, fonts, bidi info, glyphs, conversion tables, etc.
+ *
+ * @param[in] text The given text.
+ * @param[in] textArea The area where to layout the text.
+ * @param[out] layoutSize The laid-out size.
+ * @param[out] Pointer to a logical text model instance.
+ * @param[out] Pointer to a visual text model instance.
+ */
+void CreateTextModel( const std::string& text,
+ const Size& textArea,
+ Size& layoutSize,
+ LogicalModelPtr logicalModel,
+ VisualModelPtr visualModel );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MODEL_H__
TestPageFactory factory(application);
Vector2 size = Stage::GetCurrent().GetSize();
PageTurnView portraitView = PageTurnPortraitView::New( factory, size );
- portraitView.SetPositionInheritanceMode( USE_PARENT_POSITION );
+ portraitView.SetParentOrigin( ParentOrigin::CENTER );
Stage::GetCurrent().Add( portraitView );
// Render and notify
tet_infoline(" UtcDaliPageTurnLanscapeViewSignals ");
application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE );
-
/***
* -----------------
* | |
TestPageFactory factory(application);
Vector2 stageSize = Stage::GetCurrent().GetSize();
PageTurnView landscapeView = PageTurnLandscapeView::New( factory, Vector2(stageSize.x*0.5f, stageSize.x*0.8f) );
- landscapeView.SetPositionInheritanceMode( USE_PARENT_POSITION );;
+ landscapeView.SetParentOrigin( ParentOrigin::CENTER );
Stage::GetCurrent().Add( landscapeView );
// Render and notify
Image borderImage = ResourceImage::New(FOCUS_BORDER_IMAGE_PATH);
ImageActor focusIndicator = ImageActor::New(borderImage);
- focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+ focusIndicator.SetParentOrigin( ParentOrigin::CENTER );
focusIndicator.SetStyle( ImageActor::STYLE_NINE_PATCH );
focusIndicator.SetNinePatchBorder(FOCUS_BORDER_IMAGE_BORDER);
focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
void BloomView::OnInitialize()
{
// root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
- mChildrenRoot.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
//////////////////////////////////////////////////////
// Create actors
// Create an ImageActor for rendering from the scene texture to the bloom texture
mBloomExtractImageActor = Toolkit::ImageView::New();
- mBloomExtractImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mBloomExtractImageActor.SetParentOrigin( ParentOrigin::CENTER );
// Create shader used for extracting the bright parts of an image
Property::Map customShader;
// Create an ImageActor for compositing the result (scene and bloom textures) to output
mCompositeImageActor = Toolkit::ImageView::New();
- mCompositeImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mCompositeImageActor.SetParentOrigin( ParentOrigin::CENTER );
// Create shader used to composite bloom and original image to output render target
customShader[ "fragmentShader" ] = COMPOSITE_FRAGMENT_SOURCE;
// Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
mTargetImageActor = Toolkit::ImageView::New();
- mTargetImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-
+ mTargetImageActor.SetParentOrigin( ParentOrigin::CENTER );
// Create the Gaussian Blur object + render tasks
// Note that we use mBloomExtractTarget as the source image and also re-use this as the gaussian blur final render target. This saves the gaussian blur code from creating it
// render targets etc internally, so we make better use of resources
// Note, this also internally creates the render tasks used by the Gaussian blur, this must occur after the bloom extraction and before the compositing
mGaussianBlurView = Dali::Toolkit::GaussianBlurView::New(mBlurNumSamples, mBlurBellCurveWidth, mPixelFormat, mDownsampleWidthScale, mDownsampleHeightScale, true);
- mGaussianBlurView.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mGaussianBlurView.SetParentOrigin( ParentOrigin::CENTER );
//////////////////////////////////////////////////////
mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
mActorForChildren = ImageActor::New();
- mActorForChildren.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mActorForChildren.SetParentOrigin( ParentOrigin::CENTER );
mActorForChildren.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
mActorPostFilter = ImageActor::New();
Actor self(Self());
mFrame = Actor::New( );
- mFrame.SetPositionInheritanceMode(DONT_INHERIT_POSITION);
+ mFrame.SetInheritPosition(false);
mFrame.SetInheritScale(true);
mFrame.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS );
Vector3 sizeOffset(IMAGE_BORDER_INDENT*2.f - 2.f, IMAGE_BORDER_INDENT*2.f - 2.f, 0.0f);
if( 0 < newPage.GetChildCount() )
{
ImageActor backImage = ImageActor::DownCast( newPage.GetChildAt( 0 ) );
- backImage.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+ backImage.SetParentOrigin( ParentOrigin::CENTER );
backImage.SetSize( mPageSize );
SetCullFace( backImage, CullFront );
backImage.SetZ( 0.25f * STATIC_PAGE_INTERVAL_DISTANCE );
mShadowView.SetShadowColor(DEFAULT_SHADOW_COLOR);
mShadowPlaneBackground = Actor::New();
- mShadowPlaneBackground.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+ mShadowPlaneBackground.SetParentOrigin( ParentOrigin::CENTER );
mShadowPlaneBackground.SetSize( mControlSize );
Self().Add( mShadowPlaneBackground );
mShadowView.SetShadowPlaneBackground( mShadowPlaneBackground );
backing.SetName( "popupBacking" );
// Must always be positioned top-left of stage, regardless of parent.
- backing.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
+ backing.SetInheritPosition(false);
backing.SetAnchorPoint( AnchorPoint::TOP_LEFT );
// Always the full size of the stage.
void ShadowView::OnInitialize()
{
// root actor to parent all user added actors. Used as source actor for shadow render task.
- mChildrenRoot.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
mChildrenRoot.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
Vector2 stageSize = Stage::GetCurrent().GetSize();
mBlurRootActor.SetName( "BLUR_ROOT_ACTOR" );
// Turn off inheritance to ensure filter renders properly
- mBlurRootActor.SetPositionInheritanceMode(USE_PARENT_POSITION);
+ mBlurRootActor.SetParentOrigin( ParentOrigin::CENTER );
mBlurRootActor.SetInheritOrientation(false);
mBlurRootActor.SetInheritScale(false);
mBlurRootActor.SetColorMode(USE_OWN_COLOR);
mLayout = Toolkit::TableView::New( 1, 1 );
mLayout.SetName( "TOOLBAR_LAYOUT" );
mLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
- mLayout.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ mLayout.SetParentOrigin( ParentOrigin::CENTER );
Self().Add( mLayout );
$(toolkit_src_dir)/text/visual-model-impl.cpp \
$(toolkit_src_dir)/text/decorator/text-decorator.cpp \
$(toolkit_src_dir)/text/layouts/layout-engine.cpp \
+ $(toolkit_src_dir)/text/multi-language-helper-functions.cpp \
$(toolkit_src_dir)/text/multi-language-support-impl.cpp \
$(toolkit_src_dir)/text/rendering/text-backend.cpp \
$(toolkit_src_dir)/text/rendering/text-renderer.cpp \
{
// Create a focus indicator actor shared by all the keyboard focusable actors
Toolkit::ImageView focusIndicator = Toolkit::ImageView::New(FOCUS_BORDER_IMAGE_PATH);
- focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+ focusIndicator.SetParentOrigin( ParentOrigin::CENTER );
// Apply size constraint to the focus indicator
focusIndicator.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
void SetBidirectionalInfo( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
const Vector<LineBreakInfo>& lineBreakInfo,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo )
{
+ // Find where to insert the new paragraphs.
+ BidirectionalRunIndex bidiInfoIndex = 0u;
+ for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = bidirectionalInfo.Begin(),
+ endIt = bidirectionalInfo.End();
+ it != endIt;
+ ++it )
+ {
+ const BidirectionalParagraphInfoRun& run = *it;
+
+ if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+ {
+ // Found where to insert the bidi info.
+ break;
+ }
+ ++bidiInfoIndex;
+ }
+
// Traverse the script runs. If there is one with a right to left script, create the bidirectional info for the paragraph containing that script is needed.
// From the bidirectional point of view, a paragraph is the piece of text between two LINE_MUST_BREAK.
// Index pointing the first character of the current paragraph.
- CharacterIndex paragraphCharacterIndex = 0u;
+ CharacterIndex paragraphCharacterIndex = startIndex;
// Pointer to the text buffer.
const Character* textBuffer = text.Begin();
// Pointer to the line break info buffer.
const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
- // The number of characters.
- const Length numberOfCharacters = text.Count();
-
// Handle to the bidirectional info module in text-abstraction.
TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
+ const CharacterIndex lastCharacter = startIndex + numberOfCharacters;
+
+ bool hasRightToLeftScript = false;
+
for( Vector<ScriptRun>::ConstIterator it = scripts.Begin(),
endIt = scripts.End();
it != endIt;
++it )
{
const ScriptRun& scriptRun = *it;
- const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters;
+ const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters - 1u;
+
+ if( startIndex > lastScriptRunIndex )
+ {
+ // Skip the run as it has already been processed.
+ continue;
+ }
+
+ if( lastCharacter <= scriptRun.characterRun.characterIndex )
+ {
+ // Do not get bidirectional info beyond startIndex + numberOfCharacters.
+ break;
+ }
+
+ if( !hasRightToLeftScript && TextAbstraction::IsRightToLeftScript( scriptRun.script ) )
+ {
+ // The script is right to left.
+ hasRightToLeftScript = true;
+ }
- if( ( lastScriptRunIndex > paragraphCharacterIndex ) && // It isn't part of a previous paragraph.
- TextAbstraction::IsRightToLeftScript( scriptRun.script ) ) // The script is right to left.
+ if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + lastScriptRunIndex ) )
{
- // Find the paragraphs which contains this script run.
- // Consider:
- // 1) Different paragraphs may contain this script run.
- // ------||------------------- rtl sr ------------------------||-------------------
- // --||----- p -----||------------------ p -------------||-------- p ------||------
- //
- // 2) The paragraph which contains this script run may contain other right to left script runs.
- // -----||--- rtl sr ---||---- ltr sr ----||---------- rtl sr -----------||--------
- // -----||---------------------------------- p -----------------------------------|
-
- while( lastScriptRunIndex > paragraphCharacterIndex )
+ // A new paragraph has been found.
+
+ if( hasRightToLeftScript )
{
- // There is a paragraph which contains the current script.
-
- Length index = paragraphCharacterIndex;
- while( ( index < numberOfCharacters ) && ( paragraphCharacterIndex < lastScriptRunIndex ) )
- {
- if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) )
- {
- if( index >= scriptRun.characterRun.characterIndex )
- {
- // The Bidirectional run must have the same number of characters than the paragraph.
- BidirectionalParagraphInfoRun bidirectionalRun;
- bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex;
- bidirectionalRun.characterRun.numberOfCharacters = ( index - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah.
-
- // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run.
- bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex,
- bidirectionalRun.characterRun.numberOfCharacters );
-
- bidirectionalInfo.PushBack( bidirectionalRun );
- }
-
- // Update the character index of the next paragraph.
- paragraphCharacterIndex = index + 1u;
- }
- ++index;
- }
-
- // The last character is always a must-break, so there is no need to check if there is characters left.
+ // The Bidirectional run must have the same number of characters than the paragraph.
+ BidirectionalParagraphInfoRun bidirectionalRun;
+ bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex;
+ bidirectionalRun.characterRun.numberOfCharacters = ( lastScriptRunIndex - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah.
+
+ // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run.
+ bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex,
+ bidirectionalRun.characterRun.numberOfCharacters );
+
+ bidirectionalInfo.Insert( bidirectionalInfo.Begin() + bidiInfoIndex, bidirectionalRun );
+ ++bidiInfoIndex;
}
+
+ // Point to the next paragraph.
+ paragraphCharacterIndex = lastScriptRunIndex + 1u;
+
+ // Reset whether there is a right to left script.
+ hasRightToLeftScript = false;
}
}
+
+ // Update indices of the bidi runs.
+ for( Vector<BidirectionalParagraphInfoRun>::Iterator it = bidirectionalInfo.Begin() + bidiInfoIndex,
+ endIt = bidirectionalInfo.End();
+ it != endIt;
+ ++it )
+ {
+ BidirectionalParagraphInfoRun& run = *it;
+
+ run.characterRun.characterIndex += numberOfCharacters;
+ }
}
void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<LineRun>& lineRuns,
Vector<BidirectionalLineInfoRun>& lineInfoRuns )
{
+ // Find where to insert the new paragraphs.
+ BidirectionalLineRunIndex bidiLineInfoIndex = 0u;
+ for( Vector<BidirectionalLineInfoRun>::ConstIterator it = lineInfoRuns.Begin(),
+ endIt = lineInfoRuns.End();
+ it != endIt;
+ ++it )
+ {
+ const BidirectionalLineInfoRun& run = *it;
+
+ if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+ {
+ // Found where to insert the bidi line info.
+ break;
+ }
+ ++bidiLineInfoIndex;
+ }
+
// Handle to the bidirectional info module in text-abstraction.
TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
+ const CharacterIndex lastCharacter = startIndex + numberOfCharacters;
+
// Keep an index to the first line to be checked if it's contained inside the paragraph.
// Avoids check the lines from the beginning for each paragraph.
unsigned int lineIndex = 0u;
++it )
{
const BidirectionalParagraphInfoRun& paragraphInfo = *it;
+
+ if( paragraphInfo.characterRun.characterIndex < startIndex )
+ {
+ // Do not process, the paragraph has already been processed.
+ continue;
+ }
+
+ if( lastCharacter <= paragraphInfo.characterRun.characterIndex )
+ {
+ // Do not process paragraphs beyond startIndex + numberOfCharacters.
+ break;
+ }
+
const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( paragraphInfo.bidirectionalInfoIndex );
// Get the lines for this paragraph.
}
// Push the run into the vector.
- lineInfoRuns.PushBack( lineInfoRun );
+ lineInfoRuns.Insert( lineInfoRuns.Begin() + bidiLineInfoIndex, lineInfoRun );
+ ++bidiLineInfoIndex;
}
}
+
+ // Update indices of the bidi runs.
+ for( Vector<BidirectionalLineInfoRun>::Iterator it = lineInfoRuns.Begin() + bidiLineInfoIndex,
+ endIt = lineInfoRuns.End();
+ it != endIt;
+ ++it )
+ {
+ BidirectionalLineInfoRun& run = *it;
+
+ run.characterRun.characterIndex += numberOfCharacters;
+ }
}
bool GetMirroredText( const Vector<Character>& text,
const Vector<CharacterDirection>& directions,
const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<Character>& mirroredText )
{
bool hasTextMirrored = false;
Character* mirroredTextBuffer = mirroredText.Begin();
CharacterDirection* directionsBuffer = directions.Begin();
+ CharacterIndex index = startIndex;
+ const CharacterIndex lastCharacter = startIndex + numberOfCharacters;
+
// Traverse the paragraphs and mirror the right to left ones.
for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = bidirectionalInfo.Begin(),
endIt = bidirectionalInfo.End();
{
const BidirectionalParagraphInfoRun& paragraph = *it;
+ if( index >= paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters )
+ {
+ // Skip the paragraph as it has already been processed.
+ continue;
+ }
+
+ if( lastCharacter <= paragraph.characterRun.characterIndex )
+ {
+ // Do not get mirror characters beyond startIndex + numberOfCharacters.
+ break;
+ }
+
+ index += paragraph.characterRun.numberOfCharacters;
const bool tmpMirrored = bidirectionalSupport.GetMirroredText( mirroredTextBuffer + paragraph.characterRun.characterIndex,
directionsBuffer + paragraph.characterRun.characterIndex,
paragraph.characterRun.numberOfCharacters );
}
void GetCharactersDirection( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+ Length totalNumberOfCharacters,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<CharacterDirection>& directions )
{
// Handle to the bidirectional info module in text-abstraction.
TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
- CharacterIndex index = 0u;
- CharacterDirection* directionsBuffer = directions.Begin();
+ // Resize the vector.
+ directions.Resize( totalNumberOfCharacters );
+
+ // Whether the current buffer is being updated or is set from scratch.
+ const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+ CharacterDirection* directionsBuffer = NULL;
+ Vector<CharacterDirection> newDirections;
+
+ if( updateCurrentBuffer )
+ {
+ newDirections.Resize( numberOfCharacters );
+ directionsBuffer = newDirections.Begin();
+ }
+ else
+ {
+ directionsBuffer = directions.Begin();
+ }
+
+ const CharacterIndex lastCharacter = startIndex + numberOfCharacters;
+ CharacterIndex index = startIndex;
+
for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = bidirectionalInfo.Begin(),
endIt = bidirectionalInfo.End();
it != endIt;
{
const BidirectionalParagraphInfoRun& paragraph = *it;
- // Fills with left to right those paragraphs without right to left characters.
- memset( directionsBuffer + index, false, ( paragraph.characterRun.characterIndex - index ) * sizeof( bool ) );
- index += paragraph.characterRun.numberOfCharacters;
+ if( index >= paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters )
+ {
+ // Skip the paragraph as it has already been processed.
+ continue;
+ }
+ if( lastCharacter <= paragraph.characterRun.characterIndex )
+ {
+ // Do not get the character directions beyond startIndex + numberOfCharacters.
+ break;
+ }
+
+ // Set the directions of any previous left to right characters.
+ const Length numberOfLeftToRightCharacters = paragraph.characterRun.characterIndex - index;
+ if( numberOfLeftToRightCharacters > 0u )
+ {
+ memset( directionsBuffer + index - startIndex, false, numberOfLeftToRightCharacters * sizeof( bool ) );
+ }
+
+ // Set the directions of the bidirectional text.
bidirectionalSupport.GetCharactersDirection( paragraph.bidirectionalInfoIndex,
- directionsBuffer + paragraph.characterRun.characterIndex,
+ directionsBuffer + paragraph.characterRun.characterIndex - startIndex,
paragraph.characterRun.numberOfCharacters );
+
+ // Update the index.
+ index += paragraph.characterRun.numberOfCharacters + numberOfLeftToRightCharacters;
}
// Fills with left to right those paragraphs without right to left characters.
- memset( directionsBuffer + index, false, ( directions.Count() - index ) * sizeof( bool ) );
+ memset( directionsBuffer + index - startIndex, false, ( lastCharacter - index ) * sizeof( bool ) );
+
+ // If the direction info is updated, it needs to be inserted in the model.
+ if( updateCurrentBuffer )
+ {
+ // Insert the directions in the given buffer.
+ directions.Insert( directions.Begin() + startIndex,
+ newDirections.Begin(),
+ newDirections.End() );
+ directions.Resize( totalNumberOfCharacters );
+ }
}
} // namespace Text
* @param[in] text Vector of UTF-32 characters.
* @param[in] scripts Vector containing the script runs for the whole text.
* @param[in] lineBreakInfo The line break info.
+ * @param[in] startIndex The character from where the bidirectional info is set.
+ * @param[in] numberOfCharacters The number of characters.
* @param[out] bidirectionalInfo Vector with the bidirectional infor for each paragraph.
*/
void SetBidirectionalInfo( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
const Vector<LineBreakInfo>& lineBreakInfo,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo );
/**
* @pre The @p visualModel needs to have the laid-out lines info set.
*
* @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph.
+ * @param[in] startIndex The character from where the bidirectional info is set.
+ * @param[in] numberOfCharacters The number of characters.
* @param[in,out] lineRuns The line runs converted to characters.
* @param[out] lineInfoRuns line runs with the visual to logical conversion maps.
*/
void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<LineRun>& lineRuns,
Vector<BidirectionalLineInfoRun>& lineInfoRuns );
* @param[in] text The text.
* @param[in] directions Vector with the direction of each paragraph.
* @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph.
+ * @param[in] startIndex The character from where the text is mirrored.
+ * @param[in] numberOfCharacters The number of characters.
* @param[out] mirroredText The mirroredText.
*
* @return @e true if a character has been replaced.
bool GetMirroredText( const Vector<Character>& text,
const Vector<CharacterDirection>& directions,
const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<Character>& mirroredText );
/**
* @pre The @p logicalModel needs to have the bidirectional info indices for each paragraph set.
*
* @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph.
+ * @param[in] totalNumberOfCharacters The number of characters of the whole text.
+ * @param[in] startIndex The character from where the direction info is set.
+ * @param[in] numberOfCharacters The number of characters.
* @param[out] directions The direction, @e false is left to right and @e true is right to left, of each character of the paragraph.
*/
void GetCharactersDirection( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
+ Length totalNumberOfCharacters,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<CharacterDirection>& directions );
} // namespace Text
// Create a root actor and an image actor for offscreen rendering.
mOffscreenRootActor = Layer::New();
mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
- mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
+ mOffscreenRootActor.SetInheritPosition( false );
mOffscreenRootActor.SetInheritScale( false );
mOffscreenRootActor.SetDepthTestDisabled( true );
mOffscreenRootActor.SetSize( offscreenSize );
mActiveLayer.SetParentOrigin( ParentOrigin::CENTER );
mActiveLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
- mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION );
// Add the active layer telling the controller it doesn't need clipping.
mController.AddDecoration( mActiveLayer, false );
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/input-style.h>
-#include <dali-toolkit/internal/text/text-style-run-container.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
namespace Dali
{
}
void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
- Length numberOfRuns )
+ Length numberOfRuns,
+ CharacterIndex startIndex,
+ Length numberOfCharacters )
{
- if( 0u == numberOfRuns )
- {
- mVisualToLogicalMap.Clear();
- mLogicalToVisualMap.Clear();
- mVisualToLogicalCursorMap.Clear();
- }
- else
- {
- const Length numberOfCharacters = mText.Count();
- mVisualToLogicalMap.Resize( numberOfCharacters );
- mLogicalToVisualMap.Resize( numberOfCharacters );
+ mVisualToLogicalMap.Resize( numberOfCharacters );
+ mLogicalToVisualMap.Resize( numberOfCharacters );
- const Length numberOfCharactersPlus = numberOfCharacters + 1u;
- mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus );
+ const Length numberOfCharactersPlus = numberOfCharacters + 1u;
+ mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus );
- CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
- CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin();
+ CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
+ CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin();
- CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin();
+ CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin();
- CharacterIndex lastIndex = 0u;
- for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
- {
- const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
+ CharacterIndex lastIndex = startIndex;
+ for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
+ {
+ const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
- if( lastIndex < bidiLineInfo.characterRun.characterIndex )
- {
- // Fill with the identity.
- for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
- {
- *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
- }
- }
+ if( bidiLineInfo.characterRun.characterIndex + bidiLineInfo.characterRun.numberOfCharacters <= startIndex )
+ {
+ // Skip this paragraph. It has been already processed.
+ continue;
+ }
- // Fill the conversion table of the run.
- for( CharacterIndex index = 0u;
- index < bidiLineInfo.characterRun.numberOfCharacters;
- ++index, ++lastIndex )
+ if( lastIndex < bidiLineInfo.characterRun.characterIndex )
+ {
+ // Fill with the identity.
+ for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
{
- *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
+ *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
}
}
- // Complete with the identity if there are some left to right characters after the last right to left.
- for( ; lastIndex < numberOfCharacters; ++lastIndex )
+ // Fill the conversion table of the run.
+ for( CharacterIndex index = 0u;
+ index < bidiLineInfo.characterRun.numberOfCharacters;
+ ++index, ++lastIndex )
{
- *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
+ *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
}
+ }
- // Sets the logical to visual conversion map.
- for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
- {
- *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index;
- }
+ // Complete with the identity if there are some left to right characters after the last right to left.
+ for( ; lastIndex < numberOfCharacters; ++lastIndex )
+ {
+ *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
+ }
+
+ // Sets the logical to visual conversion map.
+ for( CharacterIndex index = startIndex; index < numberOfCharacters; ++index )
+ {
+ *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index;
+ }
- // Sets the visual to logical conversion map for cursor positions.
+ // Sets the visual to logical conversion map for cursor positions.
- const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count();
- BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin();
- BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer;
+ const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count();
+ BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin();
+ BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer;
- const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
+ const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
+
+ Length bidirectionalParagraphIndex = 0u;
+ bool isRightToLeftParagraph = false;
+ for( CharacterIndex index = startIndex; index < numberOfCharactersPlus; ++index )
+ {
+ if( bidirectionalParagraph &&
+ ( bidirectionalParagraph->characterRun.characterIndex == index ) )
+ {
+ isRightToLeftParagraph = *( modelCharacterDirections + index );
+ }
- Length bidirectionalParagraphIndex = 0u;
- bool isRightToLeftParagraph = false;
- for( CharacterIndex index = 0u; index < numberOfCharactersPlus; ++index )
+ if( 0u == index )
{
- if( bidirectionalParagraph &&
- ( bidirectionalParagraph->characterRun.characterIndex == index ) )
+ if( isRightToLeftParagraph )
{
- isRightToLeftParagraph = *( modelCharacterDirections + index );
+ *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
}
-
- if( 0u == index )
+ else // else logical position is zero.
{
- if( isRightToLeftParagraph )
- {
- *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
- }
- else // else logical position is zero.
- {
- *( modelVisualToLogicalCursorMap + index ) = 0u;
- }
+ *( modelVisualToLogicalCursorMap + index ) = 0u;
}
- else if( numberOfCharacters == index )
+ }
+ else if( numberOfCharacters == index )
+ {
+ if( isRightToLeftParagraph )
{
- if( isRightToLeftParagraph )
+ *( modelVisualToLogicalCursorMap + index ) = 0u;
+ }
+ else // else logical position is the number of characters.
+ {
+ *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
+ }
+ }
+ else
+ {
+ // Get the character indexed by index - 1 and index
+ // and calculate the logical position according the directions of
+ // both characters and the direction of the paragraph.
+
+ const CharacterIndex previousIndex = index - 1u;
+ const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex );
+ const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index );
+
+ const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 );
+ const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 );
+
+ if( direction0 == direction1 )
+ {
+ // Both glyphs have the same direction.
+ if( direction0 )
{
- *( modelVisualToLogicalCursorMap + index ) = 0u;
+ *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
}
- else // else logical position is the number of characters.
+ else
{
- *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
+ *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
}
}
else
{
- // Get the character indexed by index - 1 and index
- // and calculate the logical position according the directions of
- // both characters and the direction of the paragraph.
-
- const CharacterIndex previousIndex = index - 1u;
- const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex );
- const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index );
-
- const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 );
- const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 );
-
- if( direction0 == direction1 )
+ if( isRightToLeftParagraph )
{
- // Both glyphs have the same direction.
- if( direction0 )
+ if( direction1 )
{
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
+ *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u;
}
else
{
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
+ *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
}
}
else
{
- if( isRightToLeftParagraph )
+ if( direction0 )
{
- if( direction1 )
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u;
- }
- else
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
- }
+ *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
}
else
{
- if( direction0 )
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
- }
- else
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u;
- }
+ *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u;
}
}
}
+ }
- if( bidirectionalParagraph &&
- ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) )
+ if( bidirectionalParagraph &&
+ ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) )
+ {
+ isRightToLeftParagraph = false;
+ ++bidirectionalParagraphIndex;
+ if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs )
{
- isRightToLeftParagraph = false;
- ++bidirectionalParagraphIndex;
- if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs )
- {
- bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex;
- }
- else
- {
- bidirectionalParagraph = NULL;
- }
+ bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex;
+ }
+ else
+ {
+ bidirectionalParagraph = NULL;
}
}
}
*
* @param[in] bidirectionalInfo Pointer to a buffer with all the bidirectional info runs.
* @param[in] numberOfRuns The number of bidirectional info runs.
+ * @param[in] startIndex Character index from where the conversion tables are set.
+ * @param[in] numberOfCharacters The number of characters.
*/
void SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
- Length numberOfRuns );
+ Length numberOfRuns,
+ CharacterIndex startIndex,
+ Length numberOfCharacters );
/**
* @brief Retrieves the logical character index for the given visual character index.
*/
CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const;
+ // Text style.
+
/**
* @brief Updates the text's style runs with the added or removed text.
*
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/multi-language-helper-functions.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-client.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
+ Vector<FontId>& fontIds,
+ const TextAbstraction::FontDescription& defaultFontDescription,
+ TextAbstraction::PointSize26Dot6 defaultPointSize,
+ CharacterIndex startIndex,
+ Length numberOfCharacters )
+{
+ // Get the handle to the font client.
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+
+ // Pointer to the font id buffer.
+ FontId* fontIdsBuffer = fontIds.Begin();
+
+ // Traverse all the characters.
+ for( CharacterIndex index = startIndex; index < numberOfCharacters; ++index )
+ {
+ // The default font description and font point size.
+ TextAbstraction::FontDescription fontDescription = defaultFontDescription;
+ TextAbstraction::PointSize26Dot6 fontSize = defaultPointSize;
+ bool defaultFont = true;
+
+ // Traverse all the font descriptions.
+ for( Vector<FontDescriptionRun>::ConstIterator it = fontDescriptions.Begin(),
+ endIt = fontDescriptions.End();
+ it != endIt;
+ ++it )
+ {
+ // Check whether the character's font is modified by the current font description.
+ const FontDescriptionRun& fontRun = *it;
+ if( ( index >= fontRun.characterRun.characterIndex ) &&
+ ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) )
+ {
+ if( fontRun.familyDefined )
+ {
+ fontDescription.family = std::string( fontRun.familyName, fontRun.familyLength );
+ defaultFont = false;
+ }
+ if( fontRun.weightDefined )
+ {
+ fontDescription.weight = fontRun.weight;
+ defaultFont = false;
+ }
+ if( fontRun.widthDefined )
+ {
+ fontDescription.width = fontRun.width;
+ defaultFont = false;
+ }
+ if( fontRun.slantDefined )
+ {
+ fontDescription.slant = fontRun.slant;
+ defaultFont = false;
+ }
+ if( fontRun.sizeDefined )
+ {
+ fontSize = fontRun.size;
+ defaultFont = false;
+ }
+ }
+ }
+
+ // Get the font id if is not the default font.
+ if( !defaultFont )
+ {
+ *( fontIdsBuffer + index - startIndex ) = fontClient.GetFontId( fontDescription, fontSize );
+ }
+ }
+}
+
+Script GetScript( Length index,
+ Vector<ScriptRun>::ConstIterator& scriptRunIt,
+ const Vector<ScriptRun>::ConstIterator& scriptRunEndIt )
+{
+ Script script = TextAbstraction::UNKNOWN;
+
+ while( scriptRunIt != scriptRunEndIt )
+ {
+ const ScriptRun& scriptRun = *scriptRunIt;
+
+ if( index >= scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters )
+ {
+ ++scriptRunIt;
+ }
+ else if( index >= scriptRun.characterRun.characterIndex )
+ {
+ script = scriptRun.script;
+
+ if( index + 1u == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters )
+ {
+ // All the characters of the current run have been traversed. Get the next one for the next iteration.
+ ++scriptRunIt;
+ }
+
+ break;
+ }
+ }
+
+ return script;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__
+#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Merges the font descriptions to retrieve the font Id for each character.
+ *
+ * @param[in] fontDescriptions The font descriptions.
+ * @param[out] fontIds The font id for each character.
+ * @param[in] defaultFontDescription The default font description.
+ * @param[in] defaultPointSize The default font size.
+ * @param[in] startIndex The character from where the fonts are merged.
+ * @param[in] numberOfCharacters The number of characters to set the font.
+ */
+void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
+ Vector<FontId>& fontIds,
+ const TextAbstraction::FontDescription& defaultFontDescription,
+ TextAbstraction::PointSize26Dot6 defaultPointSize,
+ CharacterIndex startIndex,
+ Length numberOfCharacters );
+
+/**
+ * @brief Retrieves the script Id from the script run for a given character's @p index.
+ *
+ * If the character's index exceeds the current script run it increases the iterator to get the next one.
+ *
+ * @param[in] index The character's index.
+ * @param[in,out] scriptRunIt Iterator to the current script run.
+ * @param[in] scriptRunEndIt Iterator to one after the last script run.
+ *
+ * @return The script.
+ */
+Script GetScript( Length index,
+ Vector<ScriptRun>::ConstIterator& scriptRunIt,
+ const Vector<ScriptRun>::ConstIterator& scriptRunEndIt );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__
#include <dali/devel-api/adaptor-framework/singleton-service.h>
#include <dali/devel-api/text-abstraction/font-client.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/multi-language-helper-functions.h>
+
namespace Dali
{
namespace Internal
{
-/**
- * @brief Merges the font descriptions to retrieve the font Id for each character.
- *
- * @param[in] fontDescriptions The font descriptions.
- * @param[out] fontIds The font id for each character.
- * @param[in] defaultFontDescription The default font description.
- * @param[in] defaultPointSize The default font size.
- */
-void MergeFontDescriptions( const Vector<FontDescriptionRun>& fontDescriptions,
- Vector<FontId>& fontIds,
- const TextAbstraction::FontDescription& defaultFontDescription,
- TextAbstraction::PointSize26Dot6 defaultPointSize )
-{
- // Get the handle to the font client.
- TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
-
- // Pointer to the font id buffer.
- FontId* fontIdsBuffer = fontIds.Begin();
-
- // Traverse all the characters.
- const Length numberOfCharacters = fontIds.Count();
- for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
- {
- // The default font description and font point size.
- TextAbstraction::FontDescription fontDescription = defaultFontDescription;
- TextAbstraction::PointSize26Dot6 fontSize = defaultPointSize;
- bool defaultFont = true;
-
- // Traverse all the font descriptions.
- for( Vector<FontDescriptionRun>::ConstIterator it = fontDescriptions.Begin(),
- endIt = fontDescriptions.End();
- it != endIt;
- ++it )
- {
- // Check whether the character's font is modified by the current font description.
- const FontDescriptionRun& fontRun = *it;
- if( ( index >= fontRun.characterRun.characterIndex ) &&
- ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) )
- {
- if( fontRun.familyDefined )
- {
- fontDescription.family = std::string( fontRun.familyName, fontRun.familyLength );
- defaultFont = false;
- }
- if( fontRun.weightDefined )
- {
- fontDescription.weight = fontRun.weight;
- defaultFont = false;
- }
- if( fontRun.widthDefined )
- {
- fontDescription.width = fontRun.width;
- defaultFont = false;
- }
- if( fontRun.slantDefined )
- {
- fontDescription.slant = fontRun.slant;
- defaultFont = false;
- }
- if( fontRun.sizeDefined )
- {
- fontSize = fontRun.size;
- defaultFont = false;
- }
- }
- }
-
- // Get the font id if is not the default font.
- if( !defaultFont )
- {
- *( fontIdsBuffer + index ) = fontClient.GetFontId( fontDescription, fontSize );
- }
- }
-}
-
-/**
- * @brief Retrieves the script Id from the script run for a given character's @p index.
- *
- * If the character's index exceeds the current script run it increases the iterator to get the next one.
- *
- * @param[in] index The character's index.
- * @param[in,out] scriptRunIt Iterator to the current font run.
- * @param[in] scriptRunEndIt Iterator to one after the last script run.
- *
- * @return The script.
- */
-Script GetScript( Length index,
- Vector<ScriptRun>::ConstIterator& scriptRunIt,
- const Vector<ScriptRun>::ConstIterator& scriptRunEndIt )
-{
- Script script = TextAbstraction::UNKNOWN;
-
- if( scriptRunIt != scriptRunEndIt )
- {
- const ScriptRun& scriptRun = *scriptRunIt;
-
- if( ( index >= scriptRun.characterRun.characterIndex ) &&
- ( index < scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) )
- {
- script = scriptRun.script;
- }
-
- if( index + 1u == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters )
- {
- // All the characters of the current run have been traversed. Get the next one for the next iteration.
- ++scriptRunIt;
- }
- }
-
- return script;
-}
-
bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const
{
for( Vector<FontId>::ConstIterator it = mValidFonts.Begin(),
}
void MultilanguageSupport::SetScripts( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<ScriptRun>& scripts )
{
- const Length numberOfCharacters = text.Count();
-
if( 0u == numberOfCharacters )
{
// Nothing to do if there are no characters.
return;
}
+ // Find the first index where to insert the script.
+ ScriptRunIndex scriptIndex = 0u;
+ if( 0u != startIndex )
+ {
+ for( Vector<ScriptRun>::ConstIterator it = scripts.Begin(),
+ endIt = scripts.End();
+ it != endIt;
+ ++it, ++scriptIndex )
+ {
+ const ScriptRun& run = *it;
+ if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+ {
+ // Run found.
+ break;
+ }
+ }
+ }
+
// Stores the current script run.
ScriptRun currentScriptRun;
- currentScriptRun.characterRun.characterIndex = 0u;
+ currentScriptRun.characterRun.characterIndex = startIndex;
currentScriptRun.characterRun.numberOfCharacters = 0u;
currentScriptRun.script = TextAbstraction::UNKNOWN;
// Reserve some space to reduce the number of reallocations.
- scripts.Reserve( numberOfCharacters << 2u );
+ scripts.Reserve( text.Count() << 2u );
// Whether the first valid script needs to be set.
bool isFirstScriptToBeSet = true;
const Character* const textBuffer = text.Begin();
// Traverse all characters and set the scripts.
- for( Length index = 0u; index < numberOfCharacters; ++index )
+ const Length lastCharacter = startIndex + numberOfCharacters;
+ for( Length index = startIndex; index < lastCharacter; ++index )
{
Character character = *( textBuffer + index );
// script of the first character of the paragraph with a defined script.
// Skip those characters valid for many scripts like white spaces or '\n'.
- bool endOfText = index == numberOfCharacters;
+ bool endOfText = index == lastCharacter;
while( !endOfText &&
( TextAbstraction::COMMON == script ) )
{
// the same direction than the first script of the paragraph.
isFirstScriptToBeSet = true;
- // Characters common to all scripts at the end of the paragraph are added to the last script (if the last one is not unknown).
- if( TextAbstraction::UNKNOWN != currentScriptRun.script )
+ // Characters common to all scripts at the end of the paragraph are added to the last script.
+ currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
+
+ // Store the script run.
+ if( TextAbstraction::UNKNOWN == currentScriptRun.script )
{
- currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
- numberOfAllScriptCharacters = 0u;
+ currentScriptRun.script = TextAbstraction::LATIN;
}
- }
+ scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun );
+ ++scriptIndex;
+
+ // Initialize the new one.
+ currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters;
+ currentScriptRun.characterRun.numberOfCharacters = 0u;
+ currentScriptRun.script = TextAbstraction::UNKNOWN;
+ numberOfAllScriptCharacters = 0u;
+ }
// Get the next character.
++index;
- endOfText = index == numberOfCharacters;
+ endOfText = index == lastCharacter;
if( !endOfText )
{
character = *( textBuffer + index );
if( 0u != currentScriptRun.characterRun.numberOfCharacters )
{
// Store the script run.
- scripts.PushBack( currentScriptRun );
+ scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun );
+ ++scriptIndex;
}
// Initialize the new one.
// Add remaining characters into the last script.
currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
- DALI_ASSERT_DEBUG( ( 0u != currentScriptRun.characterRun.numberOfCharacters ) && "MultilanguageSupport::SetScripts() Trying to insert a script run with zero characters." );
-
- if( TextAbstraction::UNKNOWN == currentScriptRun.script )
+ if( 0u != currentScriptRun.characterRun.numberOfCharacters )
{
- // There are only white spaces in the last script. Set the latin script.
- currentScriptRun.script = TextAbstraction::LATIN;
+ if( TextAbstraction::UNKNOWN == currentScriptRun.script )
+ {
+ // There are only white spaces in the last script. Set the latin script.
+ currentScriptRun.script = TextAbstraction::LATIN;
+ }
+
+ // Store the last run.
+ scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun );
+ ++scriptIndex;
}
- // Store the last run.
- scripts.PushBack( currentScriptRun );
+ if( scriptIndex < scripts.Count() )
+ {
+ // Update the indices of the next script runs.
+ const ScriptRun& run = *( scripts.Begin() + scriptIndex - 1u );
+ CharacterIndex nextCharacterIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters;
+
+ for( Vector<ScriptRun>::Iterator it = scripts.Begin() + scriptIndex,
+ endIt = scripts.End();
+ it != endIt;
+ ++it )
+ {
+ ScriptRun& run = *it;
+ run.characterRun.characterIndex = nextCharacterIndex;
+ nextCharacterIndex += run.characterRun.numberOfCharacters;
+ }
+ }
}
void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
const Vector<FontDescriptionRun>& fontDescriptions,
FontId defaultFontId,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<FontRun>& fonts )
{
- // Clear any previously validated font.
- fonts.Clear();
-
DALI_LOG_INFO( gLogFilter, Debug::General, "-->MultilanguageSupport::ValidateFonts\n" );
- const Length numberOfCharacters = text.Count();
if( 0u == numberOfCharacters )
{
return;
}
+ // Find the first index where to insert the font run.
+ FontRunIndex fontIndex = 0u;
+ if( 0u != startIndex )
+ {
+ for( Vector<FontRun>::ConstIterator it = fonts.Begin(),
+ endIt = fonts.End();
+ it != endIt;
+ ++it, ++fontIndex )
+ {
+ const FontRun& run = *it;
+ if( startIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+ {
+ // Run found.
+ break;
+ }
+ }
+ }
+
// Traverse the characters and validate/set the fonts.
// Get the caches.
// Initializes a validated font run.
FontRun currentFontRun;
- currentFontRun.characterRun.characterIndex = 0u;
+ currentFontRun.characterRun.characterIndex = startIndex;
currentFontRun.characterRun.numberOfCharacters = 0u;
currentFontRun.fontId = 0u;
MergeFontDescriptions( fontDescriptions,
fontIds,
defaultFontDescription,
- defaultPointSize );
+ defaultPointSize,
+ startIndex,
+ numberOfCharacters );
const Character* const textBuffer = text.Begin();
const FontId* const fontIdsBuffer = fontIds.Begin();
Vector<ScriptRun>::ConstIterator scriptRunIt = scripts.Begin();
Vector<ScriptRun>::ConstIterator scriptRunEndIt = scripts.End();
+ bool isNewParagraphCharacter = false;
- for( Length index = 0u; index < numberOfCharacters; ++index )
+ CharacterIndex lastCharacter = startIndex + numberOfCharacters;
+ for( Length index = startIndex; index < lastCharacter; ++index )
{
// Get the character.
const Character character = *( textBuffer + index );
// Get the font for the character.
- FontId fontId = *( fontIdsBuffer + index );
+ FontId fontId = *( fontIdsBuffer + index - startIndex );
// Get the script for the character.
Script script = GetScript( index,
}
#endif
- if( TextAbstraction::UNKNOWN == script )
- {
- DALI_LOG_WARNING( "MultilanguageSupport::ValidateFonts. Unknown script!" );
- script = TextAbstraction::LATIN;
- }
-
// Whether the font being validated is a default one not set by the user.
FontId preferredFont = fontId;
#endif
// The font is now validated.
-
- if( fontId != currentFontRun.fontId )
+ if( ( fontId != currentFontRun.fontId ) ||
+ isNewParagraphCharacter )
{
// Current run needs to be stored and a new one initialized.
if( 0u != currentFontRun.characterRun.numberOfCharacters )
{
// Store the font run.
- fonts.PushBack( currentFontRun );
+ fonts.Insert( fonts.Begin() + fontIndex, currentFontRun );
+ ++fontIndex;
}
// Initialize the new one.
// Add one more character to the run.
++currentFontRun.characterRun.numberOfCharacters;
+
+ // Whether the current character is a new paragraph character.
+ isNewParagraphCharacter = TextAbstraction::IsNewParagraph( character );
}
if( 0u != currentFontRun.characterRun.numberOfCharacters )
{
// Store the last run.
- fonts.PushBack( currentFontRun );
+ fonts.Insert( fonts.Begin() + fontIndex, currentFontRun );
+ ++fontIndex;
+ }
+
+ if( fontIndex < fonts.Count() )
+ {
+ // Update the indices of the next font runs.
+ const FontRun& run = *( fonts.Begin() + fontIndex - 1u );
+ CharacterIndex nextCharacterIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters;
+
+ for( Vector<FontRun>::Iterator it = fonts.Begin() + fontIndex,
+ endIt = fonts.End();
+ it != endIt;
+ ++it )
+ {
+ FontRun& run = *it;
+
+ run.characterRun.characterIndex = nextCharacterIndex;
+ nextCharacterIndex += run.characterRun.numberOfCharacters;
+ }
}
+
DALI_LOG_INFO( gLogFilter, Debug::General, "<--MultilanguageSupport::ValidateFonts\n" );
}
* @copydoc Dali::MultilanguageSupport::SetScripts()
*/
void SetScripts( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<ScriptRun>& scripts );
/**
const Vector<ScriptRun>& scripts,
const Vector<FontDescriptionRun>& fontDescriptions,
FontId defaultFontId,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<FontRun>& fonts );
private:
}
void MultilanguageSupport::SetScripts( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<ScriptRun>& scripts )
{
GetImplementation( *this ).SetScripts( text,
+ startIndex,
+ numberOfCharacters,
scripts );
}
const Vector<ScriptRun>& scripts,
const Vector<FontDescriptionRun>& fontDescriptions,
FontId defaultFontId,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<FontRun>& fonts )
{
GetImplementation( *this ).ValidateFonts( text,
scripts,
fontDescriptions,
defaultFontId,
+ startIndex,
+ numberOfCharacters,
fonts );
}
* script of the first character of the paragraph with a defined script.
*
* @param[in] text Vector of UTF-32 characters.
+ * @param[in] startIndex The character from where the script info is set.
+ * @param[in] numberOfCharacters The number of characters to set the script.
* @param[out] scripts Vector containing the script runs for the whole text.
*/
void SetScripts( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<ScriptRun>& scripts );
/**
* @param[in] scripts Vector containing the script runs for the whole text.
* @param[in] fontDescriptions The fonts set by the application developers.
* @param[in] defaultFontId The default font's id.
+ * @param[in] startIndex The character from where the font info is set.
+ * @param[in] numberOfCharacters The number of characters to set the font.
* @param[out] fonts The validated fonts.
*/
void ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
const Vector<FontDescriptionRun>& fontDescriptions,
FontId defaultFontId,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<FontRun>& fonts );
};
}
void SetWordBreakInfo( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<WordBreakInfo>& wordBreakInfo )
{
- const Length numberOfCharacters = text.Count();
+ const Length totalNumberOfCharacters = text.Count();
- if( 0u == numberOfCharacters )
+ if( 0u == totalNumberOfCharacters )
{
// Nothing to do if there are no characters.
return;
}
+ // Resize the vector.
+ wordBreakInfo.Resize( totalNumberOfCharacters );
+
+ // Whether the current buffer is being updated or is set from scratch.
+ const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+ WordBreakInfo* wordBreakInfoBuffer = NULL;
+ Vector<WordBreakInfo> newWordBreakInfo;
+
+ if( updateCurrentBuffer )
+ {
+ newWordBreakInfo.Resize( numberOfCharacters );
+ wordBreakInfoBuffer = newWordBreakInfo.Begin();
+ }
+ else
+ {
+ wordBreakInfoBuffer = wordBreakInfo.Begin();
+ }
+
// Retrieve the word break info.
- wordBreakInfo.Resize( numberOfCharacters );
- TextAbstraction::Segmentation::Get().GetWordBreakPositions( text.Begin(),
+ TextAbstraction::Segmentation::Get().GetWordBreakPositions( text.Begin() + startIndex,
numberOfCharacters,
- wordBreakInfo.Begin() );
+ wordBreakInfoBuffer );
+
+ // If the word break info is updated, it needs to be inserted in the model.
+ if( updateCurrentBuffer )
+ {
+ wordBreakInfo.Insert( wordBreakInfo.Begin() + startIndex,
+ newWordBreakInfo.Begin(),
+ newWordBreakInfo.End() );
+ wordBreakInfo.Resize( totalNumberOfCharacters );
+ }
+
#ifdef DEBUG_ENABLED
if( gLogFilter->IsEnabledFor(Debug::Verbose) )
{
std::string utf8;
- Utf32ToUtf8( text.Begin(), numberOfCharacters, utf8 );
+ Utf32ToUtf8( text.Begin(), totalNumberOfCharacters, utf8 );
std::string info;
- info.reserve( numberOfCharacters );
+ info.reserve( totalNumberOfCharacters );
for( unsigned int i=0; i<wordBreakInfo.Count(); ++i )
{
info.push_back( static_cast<char>('0' + wordBreakInfo[i]) );
* - 1 is a WORD_NO_BREAK. Text can't be broken into a new word.
*
* @param[in] text Vector of UTF-32 characters.
+ * @param[in] startIndex The character from where the break info is set.
+ * @param[in] numberOfCharacters The number of characters.
* @param[out] wordBreakInfo The word break info.
*/
void SetWordBreakInfo( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<WordBreakInfo>& wordBreakInfo );
} // namespace Text
const Length numberOfCharacters = utf32Characters.Count();
Vector<LineBreakInfo>& lineBreakInfo = mLogicalModel->mLineBreakInfo;
+ CharacterIndex startIndex = 0u;
+ Length requestedNumberOfCharacters = numberOfCharacters;
if( GET_LINE_BREAKS & operations )
{
// Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK );
SetWordBreakInfo( utf32Characters,
+ startIndex,
+ requestedNumberOfCharacters,
wordBreakInfo );
}
{
// Retrieves the scripts used in the text.
multilanguageSupport.SetScripts( utf32Characters,
+ startIndex,
+ requestedNumberOfCharacters,
scripts );
}
scripts,
fontDescriptionRuns,
defaultFontId,
+ startIndex,
+ requestedNumberOfCharacters,
validFonts );
}
}
SetBidirectionalInfo( utf32Characters,
scripts,
lineBreakInfo,
+ startIndex,
+ requestedNumberOfCharacters,
bidirectionalInfo );
if( 0u != bidirectionalInfo.Count() )
{
// Only set the character directions if there is right to left characters.
Vector<CharacterDirection>& directions = mLogicalModel->mCharacterDirections;
- directions.Resize( numberOfCharacters );
-
GetCharactersDirection( bidirectionalInfo,
+ numberOfCharacters,
+ startIndex,
+ requestedNumberOfCharacters,
directions );
// This paragraph has right to left text. Some characters may need to be mirrored.
textMirrored = GetMirroredText( utf32Characters,
directions,
bidirectionalInfo,
+ startIndex,
+ requestedNumberOfCharacters,
mirroredUtf32Characters );
}
else
if( REORDER & operations )
{
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
+ Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = mImpl->mLogicalModel->mBidirectionalLineInfo;
// Check first if there are paragraphs with bidirectional info.
if( 0u != bidirectionalInfo.Count() )
{
// Get the lines
const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
+ const CharacterIndex startIndex = 0u;
+ Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
// Reorder the lines.
- Vector<BidirectionalLineInfoRun> lineBidirectionalInfoRuns;
- lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
+ bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
ReorderLines( bidirectionalInfo,
+ startIndex,
+ requestedNumberOfCharacters,
lines,
- lineBidirectionalInfoRuns );
-
- // Set the bidirectional info into the model.
- const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count();
- mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(),
- numberOfBidirectionalInfoRuns );
+ bidirectionalLineInfo );
// Set the bidirectional info per line into the layout parameters.
- layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin();
- layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
+ layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
+ layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
+
+ // Set the bidirectional info into the model.
+ mImpl->mLogicalModel->SetVisualToLogicalMap( layoutParameters.lineBidirectionalInfoRunsBuffer,
+ layoutParameters.numberOfBidirectionalInfoRuns,
+ startIndex,
+ requestedNumberOfCharacters );
// Get the character to glyph conversion table and set into the layout.
layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin();
-
// Get the glyphs per character table and set into the layout.
layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin();
glyphPositions );
// Free the allocated memory used to store the conversion table in the bidirectional line info run.
- for( Vector<BidirectionalLineInfoRun>::Iterator it = lineBidirectionalInfoRuns.Begin(),
- endIt = lineBidirectionalInfoRuns.End();
+ for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin(),
+ endIt = bidirectionalLineInfo.End();
it != endIt;
++it )
{
BidirectionalLineInfoRun& bidiLineInfo = *it;
free( bidiLineInfo.visualToLogicalMap );
+ bidiLineInfo.visualToLogicalMap = NULL;
}
+
+ bidirectionalLineInfo.Clear();
}
} // REORDER
typedef TextAbstraction::WordBreakInfo WordBreakInfo; ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace).
typedef TextAbstraction::CharacterDirection CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left.
-typedef uint32_t GlyphIndex; ///< An index into an array of glyphs.
-typedef uint32_t ScriptRunIndex; ///< An index into an array of script runs.
-typedef uint32_t FontRunIndex; ///< An index into an array of font runs.
-typedef uint32_t UnderlineRunIndex; ///< An index into an array of underline runs.
-typedef uint32_t BidirectionalRunIndex; ///< An index into an array of font runs.
-typedef uint32_t LineIndex; ///< An index into an array of lines.
+typedef uint32_t GlyphIndex; ///< An index into an array of glyphs.
+typedef uint32_t ScriptRunIndex; ///< An index into an array of script runs.
+typedef uint32_t FontRunIndex; ///< An index into an array of font runs.
+typedef uint32_t UnderlineRunIndex; ///< An index into an array of underline runs.
+typedef uint32_t BidirectionalRunIndex; ///< An index into an array of bidirectional info.
+typedef uint32_t BidirectionalLineRunIndex; ///< An index into an array of bidirectional line info.
+typedef uint32_t LineIndex; ///< An index into an array of lines.
} // namespace Text
{
/**
+ * @brief Clears the runs starting from the given character index.
+ *
+ * @param[in] startIndex The starting character index used to remove runs.
+ * @param[in] endIndex The ending character index used to remove runs.
+ * @param[in,out] runs The text's runs.
+ * @param[out] startRemoveIndex The index to the first run to be removed.
+ * @param[out] endRemoveIndex The index to the last run to be removed.
+ */
+template< typename T >
+void ClearCharacterRuns( CharacterIndex startIndex,
+ CharacterIndex endIndex,
+ Vector<T>& runs,
+ uint32_t& startRemoveIndex,
+ uint32_t& endRemoveIndex )
+{
+ T* runsBuffer = runs.Begin();
+
+ const Length length = runs.Count();
+ for( Length index = 0u; index < length; ++index )
+ {
+ T* run = ( runsBuffer + index );
+
+ if( ( run->characterRun.characterIndex <= endIndex ) &&
+ ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
+ {
+ // Run found.
+
+ // Set the index to the first run to be removed.
+ startRemoveIndex = index;
+ break;
+ }
+ }
+
+ for( Length index = startRemoveIndex; index < length; ++index )
+ {
+ T* run = ( runsBuffer + index );
+
+ if( ( run->characterRun.characterIndex <= endIndex ) &&
+ ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
+ {
+ // Update the index to the last run to be removed.
+ endRemoveIndex = index + 1u;
+ }
+ else
+ {
+ // Run found. Nothing else to do.
+ break;
+ }
+ }
+
+ // The number of characters to remove.
+ const Length numberOfCharactersRemoved = 1u + endIndex - startIndex;
+
+ // Update the character index of the next runs.
+ for( Length index = 0u; index < length; ++index )
+ {
+ T* run = ( runsBuffer + index );
+
+ if( run->characterRun.characterIndex > startIndex )
+ {
+ run->characterRun.characterIndex -= numberOfCharactersRemoved;
+ }
+ }
+}
+
+/**
+ * @brief Clears the runs starting from the given character index.
+ *
+ * @param[in] startIndex The starting character index used to remove runs.
+ * @param[in] endIndex The ending character index used to remove runs.
+ * @param[in,out] runs The text's runs.
+ */
+template< typename T >
+void ClearCharacterRuns( CharacterIndex startIndex,
+ CharacterIndex endIndex,
+ Vector<T>& runs )
+{
+ uint32_t startRemoveIndex = runs.Count();
+ uint32_t endRemoveIndex = startRemoveIndex;
+ ClearCharacterRuns( startIndex,
+ endIndex,
+ runs,
+ startRemoveIndex,
+ endRemoveIndex );
+
+ // Remove all remaining runs.
+ T* runBuffer = runs.Begin();
+ runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex );
+}
+
+/**
* @brief Updates the number of characters and the character index of the text's style runs.
*
* If the @p numberOfCharacters is a negative value, it means the number of characters that are removed starting from the @p index.
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 23;
+const unsigned int TOOLKIT_MICRO_VERSION = 24;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
/*
-Copyright (c) 2000-2014 Samsung Electronics Co., Ltd All Rights Reserved
-
-This file is part of Dali Toolkit
-
-PROPRIETARY/CONFIDENTIAL
-
-This software is the confidential and proprietary information of
-SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
-disclose such Confidential Information and shall use it only in
-accordance with the terms of the license agreement you entered
-into with SAMSUNG ELECTRONICS.
-
-SAMSUNG make no representations or warranties about the suitability
-of the software, either express or implied, including but not limited
-to the implied warranties of merchantability, fitness for a particular
-purpose, or non-infringement. SAMSUNG shall not be liable for any
-damages suffered by licensee as a result of using, modifying or
-distributing this software or its derivatives.
-*/
-
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * This file is part of Dali Toolkit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
//******************************************************************************
/*
-Copyright (c) 2000-2014 Samsung Electronics Co., Ltd All Rights Reserved
-
-This file is part of Dali Toolkit
-
-PROPRIETARY/CONFIDENTIAL
-
-This software is the confidential and proprietary information of
-SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
-disclose such Confidential Information and shall use it only in
-accordance with the terms of the license agreement you entered
-into with SAMSUNG ELECTRONICS.
-
-SAMSUNG make no representations or warranties about the suitability
-of the software, either express or implied, including but not limited
-to the implied warranties of merchantability, fitness for a particular
-purpose, or non-infringement. SAMSUNG shall not be liable for any
-damages suffered by licensee as a result of using, modifying or
-distributing this software or its derivatives.
-*/
-
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * This file is part of Dali Toolkit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
//******************************************************************************
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.1.23
+Version: 1.1.24
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-2-Clause and MIT