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=020a5cbe38d9a2b9385029c6d694d4d62b8b6606;hp=1e8abf2a627a665aee80b3b22c7f5f1c67f674f9;hb=efb94d8c348a12264e102ccf085ab5d707c85826;hpb=3e30971f9884dc48e80ef82de4ef85fc9dba1229 diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp index 1e8abf2..020a5cb 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.cpp +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -63,23 +63,38 @@ bool ValidateFontsPerScript::IsValidFont( FontId fontId ) const return false; } -FontId DefaultFonts::FindFont( TextAbstraction::FontClient& fontClient, PointSize26Dot6 size ) const +FontId DefaultFonts::FindFont( TextAbstraction::FontClient& fontClient, + const TextAbstraction::FontDescription& description, + PointSize26Dot6 size ) const { - for( Vector::ConstIterator it = mFonts.Begin(), - endIt = mFonts.End(); + for( std::vector::const_iterator it = mFonts.begin(), + endIt = mFonts.end(); it != endIt; ++it ) { - const FontId fontId = *it; - if( size == fontClient.GetPointSize( fontId ) ) + const CacheItem& item = *it; + + if( ( ( TextAbstraction::FontWeight::NONE == description.weight ) || ( description.weight == item.description.weight ) ) && + ( ( TextAbstraction::FontWidth::NONE == description.width ) || ( description.width == item.description.width ) ) && + ( ( TextAbstraction::FontSlant::NONE == description.slant ) || ( description.slant == item.description.slant ) ) && + ( size == fontClient.GetPointSize( item.fontId ) ) && + ( description.family.empty() || ( description.family == item.description.family ) ) ) { - return fontId; + return item.fontId; } } return 0u; } +void DefaultFonts::Cache( const TextAbstraction::FontDescription& description, FontId fontId ) +{ + CacheItem item; + item.description = description; + item.fontId = fontId; + mFonts.push_back( item ); +} + MultilanguageSupport::MultilanguageSupport() : mDefaultFontPerScriptCache(), mValidFontsPerScriptCache() @@ -211,6 +226,19 @@ void MultilanguageSupport::SetScripts( const Vector& text, while( !endOfText && ( TextAbstraction::COMMON == script ) ) { + if( TextAbstraction::EMOJI == currentScriptRun.script ) + { + // 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; @@ -248,7 +276,7 @@ void MultilanguageSupport::SetScripts( const Vector& text, character = *( textBuffer + index ); script = TextAbstraction::GetCharacterScript( character ); } - } + } // end while( !endOfText && ( TextAbstraction::COMMON == script ) ) if( endOfText ) { @@ -260,7 +288,8 @@ void MultilanguageSupport::SetScripts( const Vector& text, // Check if it is the first character of a paragraph. if( isFirstScriptToBeSet && ( TextAbstraction::UNKNOWN != script ) && - ( TextAbstraction::COMMON != script ) ) + ( TextAbstraction::COMMON != script ) && + ( TextAbstraction::EMOJI != script ) ) { // Sets the direction of the first valid script. isParagraphRTL = TextAbstraction::IsRightToLeftScript( script ); @@ -288,6 +317,13 @@ void MultilanguageSupport::SetScripts( const Vector& text, currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; numberOfAllScriptCharacters = 0u; } + else if( ( TextAbstraction::UNKNOWN == currentScriptRun.script ) && + ( TextAbstraction::EMOJI == script ) ) + { + currentScriptRun.script = TextAbstraction::LATIN; + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + numberOfAllScriptCharacters = 0u; + } if( 0u != currentScriptRun.characterRun.numberOfCharacters ) { @@ -353,7 +389,8 @@ void MultilanguageSupport::SetScripts( const Vector& text, void MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, const Vector& fontDescriptions, - FontId defaultFontId, + const TextAbstraction::FontDescription& defaultFontDescription, + TextAbstraction::PointSize26Dot6 defaultFontPointSize, CharacterIndex startIndex, Length numberOfCharacters, Vector& fonts ) @@ -403,38 +440,16 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, // Get the font client. TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); - // Get the default font description and default size. - TextAbstraction::FontDescription defaultFontDescription; - TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE; - if( defaultFontId > 0u ) - { - fontClient.GetDescription( defaultFontId, defaultFontDescription ); - defaultPointSize = fontClient.GetPointSize( defaultFontId ); - } - - // Merge font descriptions - Vector fontIds; - fontIds.Resize( numberOfCharacters, defaultFontId ); - Vector isDefaultFont; - isDefaultFont.Resize( numberOfCharacters, true ); - MergeFontDescriptions( fontDescriptions, - fontIds, - isDefaultFont, - defaultFontDescription, - defaultPointSize, - startIndex, - numberOfCharacters ); - const Character* const textBuffer = text.Begin(); - const FontId* const fontIdsBuffer = fontIds.Begin(); - const bool* const isDefaultFontBuffer = isDefaultFont.Begin(); + + // Iterators of the script runs. Vector::ConstIterator scriptRunIt = scripts.Begin(); Vector::ConstIterator scriptRunEndIt = scripts.End(); bool isNewParagraphCharacter = false; - PointSize26Dot6 currentPointSize = defaultPointSize; FontId currentFontId = 0u; FontId previousFontId = 0u; + bool isPreviousEmojiScript = false; // Whether it's the first set of characters to be validated. // Used in case the paragraph starts with characters common to all scripts. @@ -446,23 +461,25 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, // Get the current character. const Character character = *( textBuffer + index ); - // Get the font for the current character. - FontId fontId = *( fontIdsBuffer + index - startIndex ); + TextAbstraction::FontDescription currentFontDescription; + TextAbstraction::PointSize26Dot6 currentFontPointSize = defaultFontPointSize; + bool isDefaultFont = true; + MergeFontDescriptions( fontDescriptions, + defaultFontDescription, + defaultFontPointSize, + index, + currentFontDescription, + currentFontPointSize, + isDefaultFont ); - // Whether the font being validated for the current character is a default one not set by the user. - const bool isDefault = *( isDefaultFontBuffer + index - startIndex ); + // Get the font for the current character. + FontId fontId = fontClient.GetFontId( currentFontDescription, currentFontPointSize ); + currentFontId = fontId; // Get the script for the current character. - const Script script = GetScript( index, - scriptRunIt, - scriptRunEndIt ); - - // Get the current point size. - if( currentFontId != fontId ) - { - currentPointSize = fontClient.GetPointSize( fontId ); - currentFontId = fontId; - } + Script script = GetScript( index, + scriptRunIt, + scriptRunEndIt ); #ifdef DEBUG_ENABLED { @@ -477,6 +494,10 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, description.path.c_str() ); } #endif + if (script == TextAbstraction::UNKNOWN) + { + script = TextAbstraction::LATIN; + } // Validate whether the current character is supported by the given font. bool isValidFont = false; @@ -487,7 +508,9 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, FontId cachedDefaultFontId = 0u; if( NULL != defaultFonts ) { - cachedDefaultFontId = defaultFonts->FindFont( fontClient, currentPointSize ); + cachedDefaultFontId = defaultFonts->FindFont( fontClient, + currentFontDescription, + currentFontPointSize ); } // Whether the cached default font is valid. @@ -497,6 +520,23 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, isValidFont = isValidCachedDefaultFont && ( fontId == cachedDefaultFontId ); 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; + } + // If the given font is not valid, it means either: // - there is no cached font for the current script yet or, @@ -523,12 +563,12 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, if( isCommonScript ) { if( isValidCachedDefaultFont && - ( isDefault || ( currentFontId == previousFontId ) ) ) + ( isDefaultFont || ( currentFontId == previousFontId ) ) && + !isEmojiScript ) { // At this point the character common for all scripts has no font assigned. // If there is a valid previously cached default font for it, use that one. fontId = cachedDefaultFontId; - isValidFont = true; } } else @@ -551,12 +591,10 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, // Emojis are present in many monochrome fonts; prefer color by default. if( isValidFont && - ( TextAbstraction::EMOJI == script ) ) + isEmojiScript ) { - const BufferImage bitmap = fontClient.CreateBitmap( fontId, glyphIndex ); - - // For color emojis, the font is valid if the bitmap is RGBA. - isValidFont = bitmap && ( Pixel::BGRA8888 == bitmap.GetPixelFormat() ); + // For color emojis, the font is valid if the glyph is a color glyph (the bitmap is RGBA). + isValidFont = fontClient.IsColorGlyph( fontId, glyphIndex ); } // If there is a valid font, cache it. @@ -575,8 +613,9 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, if( !isValidFont ) // (3) { // The given font has not been validated. + int validCharacterIndex = fontClient.GetGlyphIndex(cachedDefaultFontId, character ); - if( isValidCachedDefaultFont ) + if( isValidCachedDefaultFont && validCharacterIndex != 0u ) { // Use the cached default font for the script if there is one. fontId = cachedDefaultFontId; @@ -591,7 +630,10 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, const bool preferColor = ( TextAbstraction::EMOJI == script ); // Find a fallback-font. - fontId = fontClient.FindFallbackFont( currentFontId, character, currentPointSize, preferColor ); + fontId = fontClient.FindFallbackFont( character, + currentFontDescription, + currentFontPointSize, + preferColor ); if( 0u == fontId ) { @@ -599,22 +641,29 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, defaultFontsPerScript = *( defaultFontPerScriptCacheBuffer + TextAbstraction::LATIN ); if( NULL != defaultFontsPerScript ) { - fontId = defaultFontsPerScript->FindFont( fontClient, currentPointSize ); + fontId = defaultFontsPerScript->FindFont( fontClient, + currentFontDescription, + currentFontPointSize ); } } if( 0u == fontId ) { - fontId = fontClient.FindDefaultFont( UTF32_A, currentPointSize ); + fontId = fontClient.FindDefaultFont( UTF32_A, currentFontPointSize ); } // Cache the font. if( NULL == defaultFontsPerScript ) { - defaultFontsPerScript = new DefaultFonts(); - *( defaultFontPerScriptCacheBuffer + script ) = defaultFontsPerScript; + defaultFontsPerScript = *( defaultFontPerScriptCacheBuffer + script ); + + if( NULL == defaultFontsPerScript ) + { + defaultFontsPerScript = new DefaultFonts(); + *( defaultFontPerScriptCacheBuffer + script ) = defaultFontsPerScript; + } } - defaultFontsPerScript->mFonts.PushBack( fontId ); + defaultFontsPerScript->Cache( currentFontDescription, fontId ); } } // !isValidFont (3) } // !isValidFont (2) @@ -670,6 +719,7 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, // Whether the current character is a new paragraph character. isNewParagraphCharacter = TextAbstraction::IsNewParagraph( character ); previousFontId = currentFontId; + isPreviousEmojiScript = isEmojiScript; } // end traverse characters. if( 0u != currentFontRun.characterRun.numberOfCharacters )