From: Victor Cebollada Date: Fri, 12 Feb 2016 09:11:31 +0000 (+0000) Subject: TextModel - Create the text language info for a given range of characters inside... X-Git-Tag: dali_1.1.24~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=cdefdbdee1cb3fd4051e220bb185d97b6000a037 TextModel - Create the text language info for a given range of characters inside a text. Change-Id: I48fdb5f7fda20f2f3c45566160b5e7d739f8afb9 Signed-off-by: Victor Cebollada --- diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf new file mode 100644 index 0000000..5267218 Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf differ diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf new file mode 100644 index 0000000..d683eb2 Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Bold.ttf differ diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf new file mode 100644 index 0000000..45b508b Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSerif-Italic.ttf differ diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf new file mode 100644 index 0000000..39dd394 Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSerif.ttf differ diff --git a/automated-tests/resources/fonts/dejavu/LICENSE b/automated-tests/resources/fonts/dejavu/LICENSE new file mode 100644 index 0000000..254e2cc --- /dev/null +++ b/automated-tests/resources/fonts/dejavu/LICENSE @@ -0,0 +1,99 @@ +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 $ diff --git a/automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf b/automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf new file mode 100644 index 0000000..25234ea Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenColorEmoji.ttf differ diff --git a/automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf new file mode 100644 index 0000000..55fc232 Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansArabicRegular.ttf differ diff --git a/automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf new file mode 100644 index 0000000..b9a25d7 Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansHebrewRegular.ttf differ diff --git a/automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf new file mode 100644 index 0000000..d451f59 Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansHindiRegular.ttf differ diff --git a/automated-tests/resources/fonts/tizen/TizenSansRegular.ttf b/automated-tests/resources/fonts/tizen/TizenSansRegular.ttf new file mode 100644 index 0000000..00863b6 Binary files /dev/null and b/automated-tests/resources/fonts/tizen/TizenSansRegular.ttf differ diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp index 11a2af7..f602e8a 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp @@ -16,27 +16,49 @@ */ #include - #include +#include + +#include #include -#include -#include #include +#include +#include +#include +#include #include #include - using namespace Dali; using namespace Toolkit; using namespace Text; // Tests the following functions with different scripts. +// +// void MergeFontDescriptions( const Vector& fontDescriptions, +// Vector& fontIds, +// const TextAbstraction::FontDescription& defaultFontDescription, +// TextAbstraction::PointSize26Dot6 defaultPointSize, +// CharacterIndex startIndex, +// Length numberOfCharacters ); +// +// Script GetScript( Length index, +// Vector::ConstIterator& scriptRunIt, +// const Vector::ConstIterator& scriptRunEndIt ); +// // Constructor, destructor and MultilanguageSupport::Get() -// void MultilanguageSupport::SetScripts( const Vector& text, const Vector& lineBreakInfo, Vector& scripts ); +// +// void MultilanguageSupport::SetScripts( const Vector& text, +// CharacterIndex startIndex, +// Length numberOfCharacters, +// Vector& scripts ); +// // void MultilanguageSupport::ValidateFonts( const Vector& text, // const Vector& scripts, // const Vector& fontDescriptions, // FontId defaultFontId, +// CharacterIndex startIndex, +// Length numberOfCharacters, // Vector& fonts ); ////////////////////////////////////////////////////////// @@ -44,21 +66,86 @@ using namespace Text; 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 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 expectedFontIds; ///< The expected font ids. +}; + struct ScriptsData { - std::string description; ///< Description of the experiment. - std::string text; ///< Input text. - Vector 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 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 fontDescriptionRuns; ///< The font description runs. + Vector fontRuns; ///< The expected font runs. }; ////////////////////////////////////////////////////////// +bool MergeFontDescriptionsTest( const MergeFontDescriptionsData& data ) +{ + Vector 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 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() ) @@ -116,6 +219,7 @@ bool ScriptsTest( const ScriptsData& data ) bool ValidateFontTest( const ValidateFontsData& data ) { MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); // 1) Convert to utf32 Vector utf32; @@ -129,24 +233,351 @@ bool ValidateFontTest( const ValidateFontsData& data ) // 2) Set the script info. Vector 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 fontDescriptions; - FontId defaultFontId = 0u; - Vector fonts; + Vector 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 scriptRuns; + Vector::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 fontDescriptionRuns01; + Vector expectedFontIds01; + + TextAbstraction::FontDescription defaultFontDescription02; + Vector fontDescriptionRuns02; + Vector expectedFontIds02; + expectedFontIds02.PushBack( 0u ); + expectedFontIds02.PushBack( 0u ); + + TextAbstraction::FontDescription defaultFontDescription03; + defaultFontDescription03.family = "DejaVu Serif"; + Vector fontDescriptionRuns03; + + FontDescriptionRun fontDescription0301 = + { + { + 0u, + 2u + }, + const_cast( "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 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; @@ -442,7 +873,15 @@ int UtcDaliTextMultiLanguageSetScripts(void) { { 163u, - 35u, + 18u, + }, + TextAbstraction::HANGUL + }; + ScriptRun scriptRun1011 = + { + { + 181u, + 17u, }, TextAbstraction::HANGUL }; @@ -457,6 +896,7 @@ int UtcDaliTextMultiLanguageSetScripts(void) scriptRuns10.PushBack( scriptRun1008 ); scriptRuns10.PushBack( scriptRun1009 ); scriptRuns10.PushBack( scriptRun1010 ); + scriptRuns10.PushBack( scriptRun1011 ); // Paragraphs with no scripts mixed with paragraphs with scripts. Vector scriptRuns11; @@ -464,20 +904,83 @@ int UtcDaliTextMultiLanguageSetScripts(void) { { 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 scriptRuns12; @@ -485,62 +988,148 @@ int UtcDaliTextMultiLanguageSetScripts(void) { { 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 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 }, { @@ -550,20 +1139,87 @@ int UtcDaliTextMultiLanguageSetScripts(void) " مرحبا بالعالم 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 ) { @@ -582,18 +1238,296 @@ int UtcDaliTextMultiLanguageValidateFonts01(void) 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 fontRuns01; + Vector fontDescriptions01; + + FontRun fontRun0201 = + { + { + 0u, + 11u + }, + 4u + }; + Vector fontRuns02; + fontRuns02.PushBack( fontRun0201 ); + + FontDescriptionRun fontDescription0201 = + { + { + 0u, + 11u + }, + const_cast( "TizenSans" ), + 9u, + TextAbstraction::FontWeight::NORMAL, + TextAbstraction::FontWidth::NORMAL, + TextAbstraction::FontSlant::NORMAL, + 0u, + true, + false, + false, + false, + false + }; + Vector fontDescriptions02; + fontDescriptions02.PushBack( fontDescription0201 ); + + FontRun fontRun0301 = + { + { + 0u, + 12u + }, + 4u + }; + FontRun fontRun0302 = + { + { + 12u, + 12u + }, + 4u + }; + FontRun fontRun0303 = + { + { + 24u, + 4u + }, + 4u + }; + Vector fontRuns03; + fontRuns03.PushBack( fontRun0301 ); + fontRuns03.PushBack( fontRun0302 ); + fontRuns03.PushBack( fontRun0303 ); + + Vector fontDescriptions03; + + FontRun fontRun0701 = + { + { + 0u, + 4u + }, + 2u + }; + FontRun fontRun0702 = + { + { + 4u, + 1u + }, + 4u + }; + FontRun fontRun0703 = + { + { + 5u, + 4u + }, + 2u + }; + Vector fontRuns07; + fontRuns07.PushBack( fontRun0701 ); + fontRuns07.PushBack( fontRun0702 ); + fontRuns07.PushBack( fontRun0703 ); + + FontDescriptionRun fontDescription0701 = + { + { + 0u, + 4u + }, + const_cast( "TizenSansHebrew" ), + 15u, + TextAbstraction::FontWeight::NORMAL, + TextAbstraction::FontWidth::NORMAL, + TextAbstraction::FontSlant::NORMAL, + 0u, + true, + false, + false, + false, + false + }; + FontDescriptionRun fontDescription0702 = + { + { + 5u, + 4u + }, + const_cast( "TizenSansHebrew" ), + 15u, + TextAbstraction::FontWeight::NORMAL, + TextAbstraction::FontWidth::NORMAL, + TextAbstraction::FontSlant::NORMAL, + 0u, + true, + false, + false, + false, + false + }; + Vector fontDescriptions07; + fontDescriptions07.PushBack( fontDescription0701 ); + fontDescriptions07.PushBack( fontDescription0702 ); + + FontRun fontRun0801 = + { + { + 0u, + 9u + }, + 2u + }; + Vector fontRuns08; + fontRuns08.PushBack( fontRun0801 ); + + Vector fontDescriptions08; + + FontRun fontRun0901 = + { + { + 0u, + 4u + }, + 3u + }; + Vector fontRuns09; + fontRuns09.PushBack( fontRun0901 ); + + Vector fontDescriptions09; + FontDescriptionRun fontDescription0901 = + { + { + 0u, + 4u + }, + const_cast( "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 ) { diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 96501dd..1e037b1 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -102,6 +102,7 @@ toolkit_src_files = \ $(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 \ diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp index d4a9d94..822f9f8 100644 --- a/dali-toolkit/internal/text/logical-model-impl.cpp +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -20,7 +20,7 @@ // INTERNAL INCLUDES #include -#include +#include namespace Dali { diff --git a/dali-toolkit/internal/text/multi-language-helper-functions.cpp b/dali-toolkit/internal/text/multi-language-helper-functions.cpp new file mode 100644 index 0000000..a5feaef --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-helper-functions.cpp @@ -0,0 +1,136 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +void MergeFontDescriptions( const Vector& fontDescriptions, + Vector& 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::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::ConstIterator& scriptRunIt, + const Vector::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 diff --git a/dali-toolkit/internal/text/multi-language-helper-functions.h b/dali-toolkit/internal/text/multi-language-helper-functions.h new file mode 100644 index 0000000..b73da2f --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-helper-functions.h @@ -0,0 +1,75 @@ +#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 + +// INTERNAL INCLUDES +#include +#include + +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& fontDescriptions, + Vector& 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::ConstIterator& scriptRunIt, + const Vector::ConstIterator& scriptRunEndIt ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_HELPER_FUNCTIONS_H__ diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp index f37bdc2..81598d9 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.cpp +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -23,6 +23,9 @@ #include #include +// INTERNAL INCLUDES +#include + namespace Dali { @@ -44,118 +47,6 @@ namespace Text 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& fontDescriptions, - Vector& 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::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::ConstIterator& scriptRunIt, - const Vector::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::ConstIterator it = mValidFonts.Begin(), @@ -224,24 +115,42 @@ Text::MultilanguageSupport MultilanguageSupport::Get() } void MultilanguageSupport::SetScripts( const Vector& text, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& 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::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; @@ -256,7 +165,8 @@ void MultilanguageSupport::SetScripts( const Vector& text, 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 ); @@ -272,7 +182,7 @@ void MultilanguageSupport::SetScripts( const Vector& text, // 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 ) ) { @@ -287,17 +197,27 @@ void MultilanguageSupport::SetScripts( const Vector& text, // 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 ); @@ -347,7 +267,8 @@ void MultilanguageSupport::SetScripts( const Vector& text, if( 0u != currentScriptRun.characterRun.numberOfCharacters ) { // Store the script run. - scripts.PushBack( currentScriptRun ); + scripts.Insert( scripts.Begin() + scriptIndex, currentScriptRun ); + ++scriptIndex; } // Initialize the new one. @@ -373,29 +294,46 @@ void MultilanguageSupport::SetScripts( const Vector& text, // 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::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& text, const Vector& scripts, const Vector& fontDescriptions, FontId defaultFontId, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& 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 ) { @@ -404,6 +342,24 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, return; } + // Find the first index where to insert the font run. + FontRunIndex fontIndex = 0u; + if( 0u != startIndex ) + { + for( Vector::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. @@ -415,7 +371,7 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, // Initializes a validated font run. FontRun currentFontRun; - currentFontRun.characterRun.characterIndex = 0u; + currentFontRun.characterRun.characterIndex = startIndex; currentFontRun.characterRun.numberOfCharacters = 0u; currentFontRun.fontId = 0u; @@ -437,20 +393,24 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, MergeFontDescriptions( fontDescriptions, fontIds, defaultFontDescription, - defaultPointSize ); + defaultPointSize, + startIndex, + numberOfCharacters ); const Character* const textBuffer = text.Begin(); const FontId* const fontIdsBuffer = fontIds.Begin(); Vector::ConstIterator scriptRunIt = scripts.Begin(); Vector::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, @@ -471,12 +431,6 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, } #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; @@ -594,15 +548,16 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, #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. @@ -613,13 +568,36 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, // 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::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" ); } diff --git a/dali-toolkit/internal/text/multi-language-support-impl.h b/dali-toolkit/internal/text/multi-language-support-impl.h index e6105ac..781aed5 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.h +++ b/dali-toolkit/internal/text/multi-language-support-impl.h @@ -94,6 +94,8 @@ public: * @copydoc Dali::MultilanguageSupport::SetScripts() */ void SetScripts( const Vector& text, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& scripts ); /** @@ -103,6 +105,8 @@ public: const Vector& scripts, const Vector& fontDescriptions, FontId defaultFontId, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& fonts ); private: diff --git a/dali-toolkit/internal/text/multi-language-support.cpp b/dali-toolkit/internal/text/multi-language-support.cpp index 87e594d..e612054 100644 --- a/dali-toolkit/internal/text/multi-language-support.cpp +++ b/dali-toolkit/internal/text/multi-language-support.cpp @@ -49,9 +49,13 @@ MultilanguageSupport MultilanguageSupport::Get() } void MultilanguageSupport::SetScripts( const Vector& text, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& scripts ) { GetImplementation( *this ).SetScripts( text, + startIndex, + numberOfCharacters, scripts ); } @@ -59,12 +63,16 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, const Vector& fontDescriptions, FontId defaultFontId, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& fonts ) { GetImplementation( *this ).ValidateFonts( text, scripts, fontDescriptions, defaultFontId, + startIndex, + numberOfCharacters, fonts ); } diff --git a/dali-toolkit/internal/text/multi-language-support.h b/dali-toolkit/internal/text/multi-language-support.h index bcbb130..d4fd1c7 100644 --- a/dali-toolkit/internal/text/multi-language-support.h +++ b/dali-toolkit/internal/text/multi-language-support.h @@ -90,9 +90,13 @@ public: * 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& text, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& scripts ); /** @@ -110,12 +114,16 @@ public: * @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& text, const Vector& scripts, const Vector& fontDescriptions, FontId defaultFontId, + CharacterIndex startIndex, + Length numberOfCharacters, Vector& fonts ); }; diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 4ac12b7..2a76cb2 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -367,6 +367,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) { // Retrieves the scripts used in the text. multilanguageSupport.SetScripts( utf32Characters, + startIndex, + requestedNumberOfCharacters, scripts ); } @@ -384,6 +386,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) scripts, fontDescriptionRuns, defaultFontId, + startIndex, + requestedNumberOfCharacters, validFonts ); } } diff --git a/dali-toolkit/internal/text/text-style-run-container.h b/dali-toolkit/internal/text/text-run-container.h similarity index 64% rename from dali-toolkit/internal/text/text-style-run-container.h rename to dali-toolkit/internal/text/text-run-container.h index e35ccea..67d0373 100644 --- a/dali-toolkit/internal/text/text-style-run-container.h +++ b/dali-toolkit/internal/text/text-run-container.h @@ -31,6 +31,97 @@ 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& 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& 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.