+ // Whether the current character is common for all scripts (i.e. white spaces, ...)
+
+ // Is not desirable to cache fonts for the common script.
+ //
+ // i.e. Consider the text " हिंदी", the 'white space' has assigned the DEVANAGARI script.
+ // The user may have set a font or the platform's default is used.
+ //
+ // As the 'white space' is the first character, no font is cached so the font validation
+ // retrieves a glyph from the given font.
+ //
+ // 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) || TextAbstraction::IsEmojiPresentationSelector(character);
+
+ // Check in the valid fonts cache.
+ ValidateFontsPerScript* validateFontsPerScript = *(validFontsPerScriptCacheBuffer + script);
+
+ if(NULL != validateFontsPerScript)
+ {
+ // This cache stores valid fonts set by the user.
+ isValidFont = validateFontsPerScript->IsValidFont(fontId);
+
+ // It may happen that a validated font for a script doesn't have all the glyphs for that script.
+ // i.e a font validated for the CJK script may contain glyphs for the chinese language but not for the Japanese.
+ if(isValidFont)
+ {
+ // Checks if the current character is supported by the font is needed.
+ isValidFont = fontClient.IsCharacterSupportedByFont(fontId, character);
+ }
+ }
+
+ if(!isValidFont) // (2)
+ {
+ // The selected font is not stored in any cache.
+
+ // Checks if the current character is supported by the selected font.
+ isValidFont = fontClient.IsCharacterSupportedByFont(fontId, character);
+
+ // If there is a valid font, cache it.
+ if(isValidFont && !isCommonScript)
+ {
+ if(NULL == validateFontsPerScript)
+ {
+ validateFontsPerScript = new ValidateFontsPerScript();
+
+ *(validFontsPerScriptCacheBuffer + script) = validateFontsPerScript;
+ }
+
+ validateFontsPerScript->Cache(fontId);
+ }
+
+ if(!isValidFont && (fontId != cachedDefaultFontId) && (!TextAbstraction::IsNewParagraph(character))) // (3)
+ {
+ // The selected font by the user or the platform's default font has failed to validate the character.
+
+ // Checks if the previously discarted cached default font supports the character.
+ bool isValidCachedFont = false;
+ if(isValidCachedDefaultFont)
+ {
+ isValidCachedFont = fontClient.IsCharacterSupportedByFont(cachedDefaultFontId, character);
+ }
+
+ if(isValidCachedFont)
+ {
+ // Use the cached default font for the script if there is one.
+ fontId = cachedDefaultFontId;
+ isValidFont = true;
+ }
+ else
+ {
+ // There is no valid cached default font for the script.
+
+ DefaultFonts* defaultFontsPerScript = NULL;
+
+ // Find a fallback-font.
+ fontId = fontClient.FindFallbackFont(character,
+ currentFontDescription,
+ currentFontPointSize,
+ false);
+
+ if(0u == fontId)
+ {
+ fontId = fontClient.FindDefaultFont(UTF32_A, currentFontPointSize);
+ }
+
+ if(!isCommonScript && (script != TextAbstraction::UNKNOWN))
+ {
+ // Cache the font if it is not an unknown script
+ if(NULL == defaultFontsPerScript)
+ {
+ defaultFontsPerScript = *(defaultFontPerScriptCacheBuffer + script);
+
+ if(NULL == defaultFontsPerScript)
+ {
+ defaultFontsPerScript = new DefaultFonts();
+ *(defaultFontPerScriptCacheBuffer + script) = defaultFontsPerScript;
+ }
+ }
+ defaultFontsPerScript->Cache(currentFontDescription, fontId);
+ isValidFont = true;
+ }
+ }
+ } // !isValidFont (3)
+ } // !isValidFont (2)
+ } // !isValidFont (1)
+}
+} // unnamed namespace
+
+bool ValidateFontsPerScript::IsValidFont(FontId fontId) const
+{
+ for(Vector<FontId>::ConstIterator it = mValidFonts.Begin(),
+ endIt = mValidFonts.End();
+ it != endIt;
+ ++it)
+ {
+ if(fontId == *it)