X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fmulti-language-support-impl.cpp;h=dbd110ba863f6f8489fb49b0c04c786740ddad55;hp=82470f8de4c0ff027b359f0e4001ec6cae6688d8;hb=fbd8d4da2506b57b46a71c5d113f4cb86f23c731;hpb=7a3b4a33993cd79bb5e8cb34fefb0e7ee6ce602f diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp index 82470f8..dbd110b 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.cpp +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -24,6 +24,7 @@ #include // INTERNAL INCLUDES +#include #include namespace Dali @@ -97,11 +98,11 @@ MultilanguageSupport::MultilanguageSupport() { // Initializes the default font cache to zero (invalid font). // Reserves space to cache the default fonts and access them with the script as an index. - mDefaultFontPerScriptCache.Resize(TextAbstraction::UNKNOWN + 1, NULL); + mDefaultFontPerScriptCache.Resize(TextAbstraction::GetNumberOfScripts(), NULL); // Initializes the valid fonts cache to NULL (no valid fonts). // Reserves space to cache the valid fonts and access them with the script as an index. - mValidFontsPerScriptCache.Resize(TextAbstraction::UNKNOWN + 1, NULL); + mValidFontsPerScriptCache.Resize(TextAbstraction::GetNumberOfScripts(), NULL); } MultilanguageSupport::~MultilanguageSupport() @@ -205,6 +206,7 @@ void MultilanguageSupport::SetScripts(const Vector& text, // Traverse all characters and set the scripts. const Length lastCharacter = startIndex + numberOfCharacters; + for(Length index = startIndex; index < lastCharacter; ++index) { Character character = *(textBuffer + index); @@ -222,26 +224,40 @@ void MultilanguageSupport::SetScripts(const Vector& text, // Skip those characters valid for many scripts like white spaces or '\n'. bool endOfText = index == lastCharacter; + + //Handle all Emoji Sequence cases + if(IsNewSequence(textBuffer, currentScriptRun.script, index, lastCharacter, script)) + { + AddCurrentScriptAndCreatNewScript(script, + false, + false, + currentScriptRun, + numberOfAllScriptCharacters, + scripts, + scriptIndex); + } + else if(IsScriptChangedToFollowSequence(currentScriptRun.script, character, script)) + { + currentScriptRun.script = script; + } + else if(IsOneOfEmojiScripts(currentScriptRun.script) && (TextAbstraction::COMMON == script)) + { + // Emojis doesn't mix well with characters common to all scripts. Insert the emoji run. + AddCurrentScriptAndCreatNewScript(TextAbstraction::UNKNOWN, + false, + false, + currentScriptRun, + numberOfAllScriptCharacters, + scripts, + scriptIndex); + } + while(!endOfText && (TextAbstraction::COMMON == script)) { // Check if whether is right to left markup and Keeps true if the previous value was true. currentScriptRun.isRightToLeft = currentScriptRun.isRightToLeft || TextAbstraction::IsRightToLeftMark(character); - // ZWJ, ZWNJ between emojis should be treated as EMOJI. - if(TextAbstraction::EMOJI == currentScriptRun.script && !(TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character))) - { - // Emojis doesn't mix well with characters common to all scripts. Insert the emoji run. - 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; - } - // Count all these characters to be added into a script. ++numberOfAllScriptCharacters; @@ -253,20 +269,13 @@ 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. - currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; - - // Store the script run. - 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; - // Initialize whether is right to left direction - currentScriptRun.isRightToLeft = false; + AddCurrentScriptAndCreatNewScript(TextAbstraction::UNKNOWN, + false, + false, + currentScriptRun, + numberOfAllScriptCharacters, + scripts, + scriptIndex); } // Get the next character. @@ -276,6 +285,22 @@ void MultilanguageSupport::SetScripts(const Vector& text, { character = *(textBuffer + index); script = TextAbstraction::GetCharacterScript(character); + + //Handle all Emoji Sequence cases + if(IsNewSequence(textBuffer, currentScriptRun.script, index, lastCharacter, script)) + { + AddCurrentScriptAndCreatNewScript(script, + false, + false, + currentScriptRun, + numberOfAllScriptCharacters, + scripts, + scriptIndex); + } + else if(IsScriptChangedToFollowSequence(currentScriptRun.script, character, script)) + { + currentScriptRun.script = script; + } } } // end while( !endOfText && ( TextAbstraction::COMMON == script ) ) @@ -290,7 +315,10 @@ void MultilanguageSupport::SetScripts(const Vector& text, if(isFirstScriptToBeSet && (TextAbstraction::UNKNOWN != script) && (TextAbstraction::COMMON != script) && - (TextAbstraction::EMOJI != script)) + (TextAbstraction::EMOJI != script) && + (TextAbstraction::EMOJI_TEXT != script) && + (TextAbstraction::EMOJI_COLOR != script) && + (!TextAbstraction::IsSymbolScript(script))) { // Sets the direction of the first valid script. isParagraphRTL = currentScriptRun.isRightToLeft || TextAbstraction::IsRightToLeftScript(script); @@ -319,26 +347,21 @@ void MultilanguageSupport::SetScripts(const Vector& text, numberOfAllScriptCharacters = 0u; } else if((TextAbstraction::UNKNOWN == currentScriptRun.script) && - (TextAbstraction::EMOJI == script)) + (TextAbstraction::IsSymbolOrEmojiOrTextScript(script))) { currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; numberOfAllScriptCharacters = 0u; } - if(0u != currentScriptRun.characterRun.numberOfCharacters) - { - // Store the script run. - scripts.Insert(scripts.Begin() + scriptIndex, currentScriptRun); - ++scriptIndex; - } - - // Initialize the new one. - currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters; - currentScriptRun.characterRun.numberOfCharacters = numberOfAllScriptCharacters + 1u; // Adds the white spaces which are at the begining of the script. - currentScriptRun.script = script; - numberOfAllScriptCharacters = 0u; - // Check if whether is right to left script. - currentScriptRun.isRightToLeft = TextAbstraction::IsRightToLeftScript(currentScriptRun.script); + // Adds the white spaces which are at the begining of the script. + numberOfAllScriptCharacters++; + AddCurrentScriptAndCreatNewScript(script, + TextAbstraction::IsRightToLeftScript(script), + true, + currentScriptRun, + numberOfAllScriptCharacters, + scripts, + scriptIndex); } else { @@ -445,8 +468,8 @@ void MultilanguageSupport::ValidateFonts(const Vector& Vector::ConstIterator scriptRunEndIt = scripts.End(); bool isNewParagraphCharacter = false; - bool isPreviousEmojiScript = false; - FontId previousEmojiFontId = 0u; + FontId previousEmojiFontId = 0u; + TextAbstraction::Script previousScript = TextAbstraction::UNKNOWN; CharacterIndex lastCharacter = startIndex + numberOfCharacters; for(Length index = startIndex; index < lastCharacter; ++index) @@ -518,28 +541,11 @@ void MultilanguageSupport::ValidateFonts(const Vector& } bool isCommonScript = false; - bool isEmojiScript = TextAbstraction::EMOJI == script; - - if(isEmojiScript && !isPreviousEmojiScript) - { - if(0u != currentFontRun.characterRun.numberOfCharacters) - { - // Store the font run. - fonts.Insert(fonts.Begin() + fontIndex, currentFontRun); - ++fontIndex; - } - - // Initialize the new one. - currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters; - currentFontRun.characterRun.numberOfCharacters = 0u; - currentFontRun.fontId = fontId; - currentFontRun.isItalicRequired = false; - currentFontRun.isBoldRequired = false; - } + bool isEmojiScript = TextAbstraction::IsEmojiScript(script) || TextAbstraction::IsEmojiColorScript(script) || TextAbstraction::IsEmojiTextScript(script); - // ZWJ, ZWNJ between emojis should use the previous emoji font. - if(isEmojiScript && (TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character))) + if(isEmojiScript && (previousScript == script)) { + // Emoji sequence should use the previous emoji font. if(0u != previousEmojiFontId) { fontId = previousEmojiFontId; @@ -567,7 +573,7 @@ void MultilanguageSupport::ValidateFonts(const Vector& // // Many fonts support 'white spaces' so probably the font set by the user or the platform's default // supports the 'white space'. However, that font may not support the DEVANAGARI script. - isCommonScript = TextAbstraction::IsCommonScript(character); + isCommonScript = TextAbstraction::IsCommonScript(character) || TextAbstraction::IsEmojiPresentationSelector(character); // Check in the valid fonts cache. ValidateFontsPerScript* validateFontsPerScript = *(validFontsPerScriptCacheBuffer + script); @@ -659,14 +665,55 @@ void MultilanguageSupport::ValidateFonts(const Vector& } // !isValidFont (2) } // !isValidFont (1) + if(isEmojiScript && (previousScript != script)) + { + //New Emoji sequence should select font according to the variation selector (VS15 or VS16). + if(0u != currentFontRun.characterRun.numberOfCharacters) + { + // Store the font run. + fonts.Insert(fonts.Begin() + fontIndex, currentFontRun); + ++fontIndex; + } + + // Initialize the new one. + currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = fontId; + currentFontRun.isItalicRequired = false; + currentFontRun.isBoldRequired = false; + + if(TextAbstraction::IsEmojiColorScript(script) || TextAbstraction::IsEmojiTextScript(script)) + { + bool isModifiedByVariationSelector = false; + GlyphIndex glyphIndexChar = fontClient.GetGlyphIndex(fontId, character); + GlyphIndex glyphIndexCharByVS = fontClient.GetGlyphIndex(fontId, character, Text::GetVariationSelectorByScript(script)); + + isModifiedByVariationSelector = glyphIndexChar != glyphIndexCharByVS; + + if(isModifiedByVariationSelector) + { + FontId requestedFontId = fontClient.FindDefaultFont(character, currentFontPointSize, IsEmojiColorScript(script)); + if(0u != requestedFontId) + { + currentFontRun.fontId = fontId = requestedFontId; + isValidFont = true; + } + } + } + } + // Store the font id when the first character is an emoji. - if(isEmojiScript && !isPreviousEmojiScript) + if(isEmojiScript) { - if(0u != fontId) + if(0u != fontId && previousScript != script) { previousEmojiFontId = fontId; } } + else + { + previousEmojiFontId = 0u; + } #ifdef DEBUG_ENABLED { @@ -715,7 +762,7 @@ void MultilanguageSupport::ValidateFonts(const Vector& // Whether the current character is a new paragraph character. isNewParagraphCharacter = TextAbstraction::IsNewParagraph(character); - isPreviousEmojiScript = isEmojiScript; + previousScript = script; } // end traverse characters. if(0u != currentFontRun.characterRun.numberOfCharacters) @@ -746,6 +793,34 @@ void MultilanguageSupport::ValidateFonts(const Vector& DALI_LOG_INFO(gLogFilter, Debug::General, "<--MultilanguageSupport::ValidateFonts\n"); } +void MultilanguageSupport::AddCurrentScriptAndCreatNewScript(const Script requestedScript, + const bool isRightToLeft, + const bool addScriptCharactersToNewScript, + ScriptRun& currentScriptRun, + Length& numberOfAllScriptCharacters, + Vector& scripts, + ScriptRunIndex& scriptIndex) +{ + // Add the pending characters to the current script + currentScriptRun.characterRun.numberOfCharacters += (addScriptCharactersToNewScript ? 0u : numberOfAllScriptCharacters); + + // In-case the current script is empty then no need to add it for scripts + if(0u != currentScriptRun.characterRun.numberOfCharacters) + { + // Store the script run. + scripts.Insert(scripts.Begin() + scriptIndex, currentScriptRun); + ++scriptIndex; + } + + // Initialize the new one by the requested script + currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters; + currentScriptRun.characterRun.numberOfCharacters = (addScriptCharactersToNewScript ? numberOfAllScriptCharacters : 0u); + currentScriptRun.script = requestedScript; + numberOfAllScriptCharacters = 0u; + // Initialize whether is right to left direction + currentScriptRun.isRightToLeft = isRightToLeft; +} + } // namespace Internal } // namespace Text