From 73cf0e19b868c872ce5c91ed3bc012abba23aa62 Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Wed, 4 Feb 2015 09:42:49 +0000 Subject: [PATCH] Multi-language support implementation. Change-Id: Ia6dee3e9e85f1a7ff2043eebbe3680967bf2fafc Signed-off-by: Victor Cebollada --- base/dali-toolkit/internal/file.list | 1 + .../internal/text/multi-language-support-impl.cpp | 471 +++++++++++++++++++++ .../internal/text/multi-language-support-impl.h | 130 ++++++ base/dali-toolkit/public-api/file.list | 2 + .../public-api/text/multi-language-support.cpp | 8 +- .../public-api/text/multi-language-support.h | 15 +- base/dali-toolkit/public-api/text/script.cpp | 332 +++++++++++++++ 7 files changed, 955 insertions(+), 4 deletions(-) create mode 100644 base/dali-toolkit/internal/text/multi-language-support-impl.cpp create mode 100644 base/dali-toolkit/internal/text/multi-language-support-impl.h diff --git a/base/dali-toolkit/internal/file.list b/base/dali-toolkit/internal/file.list index a6cb7ca..621ffbc 100644 --- a/base/dali-toolkit/internal/file.list +++ b/base/dali-toolkit/internal/file.list @@ -38,6 +38,7 @@ toolkit_base_src_files = \ $(toolkit_base_src_dir)/focus-manager/keyboard-focus-manager-impl.cpp \ $(toolkit_base_src_dir)/focus-manager/keyinput-focus-manager-impl.cpp \ $(toolkit_base_src_dir)/styling/style-manager-impl.cpp \ + $(toolkit_base_src_dir)/text/multi-language-support-impl.cpp \ $(toolkit_base_src_dir)/builder/builder-impl.cpp \ $(toolkit_base_src_dir)/builder/builder-animations.cpp \ $(toolkit_base_src_dir)/builder/builder-set-property.cpp \ diff --git a/base/dali-toolkit/internal/text/multi-language-support-impl.cpp b/base/dali-toolkit/internal/text/multi-language-support-impl.cpp new file mode 100644 index 0000000..4143b03 --- /dev/null +++ b/base/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -0,0 +1,471 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +/** + * @brief Retrieves the font Id from the font run for a given character's @p index. + * + * If the character's index exceeds the current font run it increases the iterator to get the next one. + * + * @param[in] index The character's index. + * @param[in,out] fontRunIt Iterator to the current font run. + * @param[in] fontRunEndIt Iterator to one after the last font run. + * + * @return The font id. + */ +FontId GetFontId( Length index, + Vector::ConstIterator& fontRunIt, + const Vector::ConstIterator& fontRunEndIt ) +{ + FontId fontId = 0u; + + if( fontRunIt != fontRunEndIt ) + { + const FontRun& fontRun = *fontRunIt; + + if( ( index >= fontRun.characterRun.characterIndex ) && + ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) ) + { + fontId = fontRun.fontId; + } + + if( index == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) + { + // All the characters of the current run have been traversed. Get the next one for the next iteration. + ++fontRunIt; + } + } + + return fontId; +} + +/** + * @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 == 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(), + endIt = mValidFonts.End(); + it != endIt; + ++it ) + { + if( fontId == *it ) + { + return true; + } + } + + return false; +} + +MultilanguageSupport::MultilanguageSupport() +: mDefaultFontPerScriptCache(), + mValidFontsPerScriptCache() +{ + // 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, 0u ); + + // 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, NULL ); +} + +MultilanguageSupport::~MultilanguageSupport() +{ + // Destroy the valid fonts per script cache. + + for( Vector::Iterator it = mValidFontsPerScriptCache.Begin(), + endIt = mValidFontsPerScriptCache.End(); + it != endIt; + ++it ) + { + delete *it; + } +} + +Text::MultilanguageSupport MultilanguageSupport::Get() +{ + Text::MultilanguageSupport multilanguageSupportHandle; + + SingletonService service( SingletonService::Get() ); + if( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Text::MultilanguageSupport ) ); + if( handle ) + { + // If so, downcast the handle + MultilanguageSupport* impl = dynamic_cast< Internal::MultilanguageSupport* >( handle.GetObjectPtr() ); + multilanguageSupportHandle = Text::MultilanguageSupport( impl ); + } + else // create and register the object + { + multilanguageSupportHandle = Text::MultilanguageSupport( new MultilanguageSupport ); + service.Register( typeid( multilanguageSupportHandle ), multilanguageSupportHandle ); + } + } + + return multilanguageSupportHandle; +} + +void MultilanguageSupport::SetScripts( LogicalModel& model ) +{ + // 1) Retrieve the text from the model. + const Length numberOfCharacters = model.GetNumberOfCharacters(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + Vector text; + text.Resize( numberOfCharacters ); + + model.GetText( 0u, + text.Begin(), + numberOfCharacters ); + + // 2) Traverse all characters and set the scripts. + + // Stores the current script run. + ScriptRun currentScriptRun; + currentScriptRun.characterRun.characterIndex = 0u; + currentScriptRun.characterRun.numberOfCharacters = 0u; + currentScriptRun.script = TextAbstraction::UNKNOWN; + + // Temporary stores the script runs. + std::vector scriptRuns; + scriptRuns.reserve( numberOfCharacters << 2u ); // To reduce the number of reallocations. + + for( Vector::ConstIterator it = text.Begin(), + endIt = text.End(); + it != endIt; + ++it ) + { + const Character character = *it; + + Script script = GetCharacterScript( character ); + + if( TextAbstraction::UNKNOWN == script ) + { + script = TextAbstraction::LATIN; + DALI_ASSERT_DEBUG( !"MultilanguageSupport::SetScripts. Unkown script!" ); + } + + if( script != currentScriptRun.script ) + { + // Current run needs to be stored and a new one initialized. + + if( 0u != currentScriptRun.characterRun.numberOfCharacters ) + { + // Store the script run. + scriptRuns.push_back( currentScriptRun ); + } + + // Initialize the new one. + currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters; + currentScriptRun.characterRun.numberOfCharacters = 0u; + currentScriptRun.script = script; + } + + // Add one more character to the run. + ++currentScriptRun.characterRun.numberOfCharacters; + } + + if( 0u != currentScriptRun.characterRun.numberOfCharacters ) + { + // Store the last run. + scriptRuns.push_back( currentScriptRun ); + } + + // 3) Set the script runs into the model. + + model.SetScripts( &scriptRuns[0u], + scriptRuns.size() ); +} + +void MultilanguageSupport::ValidateFonts( LogicalModel& model ) +{ + // 1) Retrieve the text from the model. + const Length numberOfCharacters = model.GetNumberOfCharacters(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + Vector text; + text.Resize( numberOfCharacters ); + + Character* textBuffer = text.Begin(); + model.GetText( 0u, + textBuffer, + numberOfCharacters ); + + // 2) Retrieve any font previously set. + + const Length numberOfFontRuns = model.GetNumberOfFontRuns( 0u, numberOfCharacters ); + + Vector fontRuns; + fontRuns.Reserve( numberOfFontRuns ); + + FontRun* fontRunsBuffer = fontRuns.Begin(); + model.GetFontRuns( fontRunsBuffer, + 0u, + numberOfCharacters ); + + // 3) Retrieve the scripts from the model. + + const Length numberOfScriptRuns = model.GetNumberOfScriptRuns( 0u, numberOfCharacters ); + + Vector scriptRuns; + scriptRuns.Reserve( numberOfScriptRuns ); + + ScriptRun* scriptRunsBuffer = scriptRuns.Begin(); + model.GetScriptRuns( scriptRunsBuffer, + 0u, + numberOfCharacters ); + + // 4) Traverse the characters and validate/set the fonts. + + // Get the caches. + FontId* defaultFontPerScriptCacheBuffer = mDefaultFontPerScriptCache.Begin(); + ValidateFontsPerScript** validFontsPerScriptCacheBuffer = mValidFontsPerScriptCache.Begin(); + + // Stores the validated font runs. + Vector validatedFontRuns; + validatedFontRuns.Reserve( numberOfFontRuns ); + + // Initializes a validated font run. + FontRun currentFontRun; + currentFontRun.characterRun.characterIndex = 0u; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = 0u; + currentFontRun.isDefault = false; + + // Get the font client. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + + // Iterators of the font and script runs. + Vector::ConstIterator fontRunIt = fontRuns.Begin(); + Vector::ConstIterator fontRunEndIt = fontRuns.End(); + Vector::ConstIterator scriptRunIt = scriptRuns.Begin(); + Vector::ConstIterator scriptRunEndIt = scriptRuns.End(); + + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + // Get the character. + const Character character = *( textBuffer + index ); + + // Get the font for the character. + FontId fontId = GetFontId( index, + fontRunIt, + fontRunEndIt ); + + // Get the script for the character. + Script script = GetScript( index, + scriptRunIt, + scriptRunEndIt ); + + 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. + const bool isDefault = ( 0u == fontId ); + + // The default font point size. + PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE; + + if( !isDefault ) + { + // Validate if the font set by the user supports the character. + + // Check first in the caches. + + // The user may have set the default font. Check it. Otherwise check in the valid fonts cache. + if( fontId != *( defaultFontPerScriptCacheBuffer + script ) ) + { + // Check in the valid fonts cache. + ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script ); + if( NULL != validateFontsPerScript ) + { + if( !validateFontsPerScript->FindValidFont( fontId ) ) + { + // Use the font client to validate the font. + const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character ); + + if( 0u == glyphIndex ) + { + // Get the point size of the current font. It will be used to get a default font id. + pointSize = fontClient.GetPointSize( fontId ); + + // The font is not valid. Set to zero and a default one will be set. + fontId = 0u; + } + else + { + // Add the font to the valid font cache. + validateFontsPerScript->mValidFonts.PushBack( fontId ); + } + } + } + else + { + // Use the font client to validate the font. + const GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character ); + + if( 0u == glyphIndex ) + { + // Get the point size of the current font. It will be used to get a default font id. + pointSize = fontClient.GetPointSize( fontId ); + + // The font is not valid. Set to zero and a default one will be set. + fontId = 0u; + } + else + { + // Add the font to the valid font cache. + validateFontsPerScript = new ValidateFontsPerScript(); + *( validFontsPerScriptCacheBuffer + script ) = validateFontsPerScript; + + validateFontsPerScript->mValidFonts.PushBack( fontId ); + } + } + } + } + + // The font has not been validated. Find a default one. + if( 0u == fontId ) + { + // The character has no font assigned. Get a default one from the cache + fontId = *( defaultFontPerScriptCacheBuffer + script ); + + // If the cache has not a default font, get one from the font client. + if( 0u == fontId ) + { + // Find a default font. + fontId = fontClient.FindDefaultFont( character, pointSize ); + + // Cache the font. + *( defaultFontPerScriptCacheBuffer + script ) = fontId; + } + } + + // The font is now validated. + + if( ( fontId != currentFontRun.fontId ) || + ( isDefault != currentFontRun.isDefault ) ) + { + // Current run needs to be stored and a new one initialized. + + if( 0u != currentFontRun.characterRun.numberOfCharacters ) + { + // Store the font run. + validatedFontRuns.PushBack( currentFontRun ); + } + + // Initialize the new one. + currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = fontId; + currentFontRun.isDefault = isDefault; + } + + // Add one more character to the run. + ++currentFontRun.characterRun.numberOfCharacters; + } + + if( 0u != currentFontRun.characterRun.numberOfCharacters ) + { + // Store the last run. + validatedFontRuns.PushBack( currentFontRun ); + } + + // 5) Sets the validated font runs to the model. + model.SetFonts( validatedFontRuns.Begin(), + validatedFontRuns.Count() ); +} + +} // namespace Internal + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/base/dali-toolkit/internal/text/multi-language-support-impl.h b/base/dali-toolkit/internal/text/multi-language-support-impl.h new file mode 100644 index 0000000..f527031 --- /dev/null +++ b/base/dali-toolkit/internal/text/multi-language-support-impl.h @@ -0,0 +1,130 @@ +#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ + +/* + * 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. + * + */ + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +/** + * @brief Stores valid font ids per script. + */ +struct ValidateFontsPerScript +{ + /** + * Default constructor. + */ + ValidateFontsPerScript() + : mValidFonts() + {} + + /** + * Default destructor. + */ + ~ValidateFontsPerScript() + {} + + /** + * @brief Whether the given @p fontId is in the vector of valid fonts. + * + * @param[in] fontId The font id. + * + * @return @e true if the font is in the vector of valid fonts. + */ + bool FindValidFont( FontId fontId ) const; + + Vector mValidFonts; +}; + +/** + * @brief Multi-language support implementation. @see Text::MultilanguageSupport. + */ +class MultilanguageSupport : public BaseObject +{ +public: + + /** + * Constructor + */ + MultilanguageSupport(); + + /** + * Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~MultilanguageSupport(); + + /** + * @copydoc Dali::MultilanguageSupport::Get() + */ + static Text::MultilanguageSupport Get(); + + /** + * @copydoc Dali::MultilanguageSupport::SetScripts() + */ + void SetScripts( LogicalModel& model ); + + /** + * @copydoc Dali::MultilanguageSupport::ValidateFonts() + */ + void ValidateFonts( LogicalModel& model ); + +private: + Vector mDefaultFontPerScriptCache; ///< Caches the default font for a script. + Vector mValidFontsPerScriptCache; ///< Caches valid fonts for a script. +}; + +} // namespace Internal + +inline static Internal::MultilanguageSupport& GetImplementation( MultilanguageSupport& multilanguageSupport ) +{ + DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" ); + BaseObject& handle = multilanguageSupport.GetBaseObject(); + return static_cast( handle ); +} + +inline static const Internal::MultilanguageSupport& GetImplementation( const MultilanguageSupport& multilanguageSupport ) +{ + DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" ); + const BaseObject& handle = multilanguageSupport.GetBaseObject(); + return static_cast( handle ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ diff --git a/base/dali-toolkit/public-api/file.list b/base/dali-toolkit/public-api/file.list index 5755eba..7ab17c8 100755 --- a/base/dali-toolkit/public-api/file.list +++ b/base/dali-toolkit/public-api/file.list @@ -41,6 +41,7 @@ public_api_base_src_files = \ $(public_api_base_src_dir)/text/character-set-conversion.cpp \ $(public_api_base_src_dir)/text/logical-model.cpp \ $(public_api_base_src_dir)/text/multi-language-support.cpp \ + $(public_api_base_src_dir)/text/script.cpp \ $(public_api_base_src_dir)/text/segmentation.cpp \ $(public_api_base_src_dir)/text/text-controller.cpp \ $(public_api_base_src_dir)/text/text-view.cpp \ @@ -131,6 +132,7 @@ public_api_base_text_header_files = \ $(public_api_base_src_dir)/text/logical-model.h \ $(public_api_base_src_dir)/text/multi-language-support.h \ $(public_api_base_src_dir)/text/script.h \ + $(public_api_base_src_dir)/text/script-run.h \ $(public_api_base_src_dir)/text/segmentation.h \ $(public_api_base_src_dir)/text/text-controller.h \ $(public_api_base_src_dir)/text/text-definitions.h \ diff --git a/base/dali-toolkit/public-api/text/multi-language-support.cpp b/base/dali-toolkit/public-api/text/multi-language-support.cpp index a017d12..1eb6805 100644 --- a/base/dali-toolkit/public-api/text/multi-language-support.cpp +++ b/base/dali-toolkit/public-api/text/multi-language-support.cpp @@ -18,6 +18,9 @@ // FILE HEADER #include +// INTERNAL INCLUDES +#include + namespace Dali { @@ -36,20 +39,23 @@ MultilanguageSupport::~MultilanguageSupport() } MultilanguageSupport::MultilanguageSupport( Internal::MultilanguageSupport* implementation ) +: BaseHandle( implementation ) { } MultilanguageSupport MultilanguageSupport::Get() { - return MultilanguageSupport(); + return Internal::MultilanguageSupport::Get(); } void MultilanguageSupport::SetScripts( LogicalModel& model ) { + GetImplementation( *this ).SetScripts( model ); } void MultilanguageSupport::ValidateFonts( LogicalModel& model ) { + GetImplementation( *this ).ValidateFonts( model ); } } // namespace Text diff --git a/base/dali-toolkit/public-api/text/multi-language-support.h b/base/dali-toolkit/public-api/text/multi-language-support.h index a1e4c99..dbd2552 100644 --- a/base/dali-toolkit/public-api/text/multi-language-support.h +++ b/base/dali-toolkit/public-api/text/multi-language-support.h @@ -64,7 +64,7 @@ public: /** * @brief This constructor is used by MultilanguageSupport::Get(). * - * @param[in] implementation A pointer to the internal multilanguage support object. + * @param[in] implementation A pointer to the internal multi-language support object. */ explicit DALI_INTERNAL MultilanguageSupport( Internal::MultilanguageSupport* implementation ); @@ -80,6 +80,8 @@ public: * * Any script info previously set is removed. * + * Scripts are used to validate and set default fonts and to shape the text in further steps. + * * @pre The @p model needs to have a text set. * * @param[in,out] model The text's logical model. @@ -89,8 +91,15 @@ public: /** * @brief Validates the character's font of the whole text. * - * It may update fonts set by the mark-up processor. - * It sets default fonts based on the script to those characters without a font set. + * It may update fonts set by application developers. + * + * This method ensures all characters are going to be rendered using an appropriate font. Provided a valid font + * exists in the platform. + * + * For those characters with no font set, it sets a default one. + * + * If a font has been set by the application developer, this method checks if the font supports the character. + * If it doesn't, this method replaces it by a default one. * * @pre The @p model needs to have a text set. * @pre The @p model needs to have the scripts set. diff --git a/base/dali-toolkit/public-api/text/script.cpp b/base/dali-toolkit/public-api/text/script.cpp index a001f94..8860a14 100644 --- a/base/dali-toolkit/public-api/text/script.cpp +++ b/base/dali-toolkit/public-api/text/script.cpp @@ -29,6 +29,338 @@ namespace Text Script GetCharacterScript( Character character ) { + // Latin script: + // 0x0000 - 0x007f C0 Controls and Basic Latin + // 0x0080 - 0x00ff C1 Controls and Latin-1 Supplement + // 0x0100 - 0x017f Latin Extended-A + // 0x0180 - 0x024f Latin Extended-B + // 0x0250 - 0x02af IPA Extensions + // 0x02b0 - 0x02ff Spacing Modifier Letters + // 0x1d00 - 0x1d7f Phonetic Extensions + // 0x1d80 - 0x1dbf Phonetic Extensions Supplement + // 0x1e00 - 0x1eff Latin Extended Additional + // 0x2070 - 0x209f Superscripts and Subscripts + // 0x2100 - 0x214f Letterlike symbols + // 0x2150 - 0x218f Number Forms + // 0x2c60 - 0x2c7f Latin Extended-C + // 0xa720 - 0xa7ff Latin Extended-D + // 0xab30 - 0xab6f Latin Extended-E + // 0xfb00 - 0xfb4f Alphabetic Presentation Forms + // 0xff00 - 0xffef Halfwidth and Fullwidth Forms + + // Brahmic scripts: + // 0x0900 - 0x097f Devanagari + // 0x0980 - 0x09ff Bengali + // 0x0a00 - 0x0a7f Gurmukhi + // 0x0a80 - 0x0aff Gujarati + // 0x0b00 - 0x0b7f Oriya + // 0x0b80 - 0x0bff Tamil + // 0x0c00 - 0x0c7f Telugu + // 0x0c80 - 0x0cff Kannada + // 0x0d00 - 0x0d7f Malayalam + + // Sinhala script. + // 0x0d80 - 0x0dff Sinhala + + // Arabic script. + // 0x0600 - 0x06ff Arabic + // 0x0750 - 0x077f Arabic Supplement + // 0x08A0 - 0x08ff Arabic Extended-A + // 0xfb50 - 0xfdff Arabic Presentation Forms-A + // 0xfe70 - 0xfeff Arabic Presentation Forms-B + // 0x1ee00 - 0x1eeff Arabic Mathematical Alphabetic Symbols + + // CJK and Vietnamese script. + // 0x2E80 - 0x2eff CJK Radicals Supplement + // 0x3000 - 0x303f CJK Symbols and Punctuation + // 0x3200 - 0x32ff Enclosed CJK Letters and Months + // 0x3400 - 0x4dbf CJK Unified Ideographs Extension A + // 0x4e00 - 0x62ff CJK Unified Ideographs + // 0x6300 - 0x77ff CJK Unified Ideographs + // 0x7800 - 0x8cff CJK Unified Ideographs + // 0x8d00 - 0x9fff CJK Unified Ideographs + // 0x20000 - 0x215ff CJK Unified Ideographs Extension B + // 0x21600 - 0x230ff CJK Unified Ideographs Extension B + // 0x23100 - 0x245ff CJK Unified Ideographs Extension B + // 0x24600 - 0x260ff CJK Unified Ideographs Extension B + // 0x26100 - 0x275ff CJK Unified Ideographs Extension B + // 0x27600 - 0x290ff CJK Unified Ideographs Extension B + // 0x29100 - 0x2a6df CJK Unified Ideographs Extension B + // 2a700-2b73f. CJK Unified Ideographs Extension C + // 2b740-2b81f. CJK Unified Ideographs Extension D + + // Hangul script + // 0x1100 - 0x11ff Hangul jamo + // 0x3130 - 0x318f Hangul Compatibility Jamo + // 0xa960 - 0xa97f Hangul Jamo Extended-A + // 0xac00 - 0xd7af Hangul Syllables + // 0xd7b0 - 0xd7ff Hangul Jamo Extended-B + + // Khmer script + // 0x1780 - 0x17ff Khmer + // 0x19e0 - 0x19ff Khmer Symbols + + // Lao script + // 0x0e80 - 0x0eff Lao + + // Thai script + // 0x0e00 - 0x0e7f Thai + + // Burmese script + // 0x1000 - 0x104f Myanmar + + + if( character <= 0x0cff ) + { + if( character <= 0x09ff ) + { + if( character <= 0x077f ) + { + if( character <= 0x02ff ) + { + return TextAbstraction::LATIN; + } + if( ( 0x0600 <= character ) && ( character <= 0x06ff ) ) + { + return TextAbstraction::ARABIC; + } + if( ( 0x0750 <= character ) && ( character <= 0x077f ) ) + { + return TextAbstraction::ARABIC; + } + } + else // > 0x077f + { + if( ( 0x08A0 <= character ) && ( character <= 0x08ff ) ) + { + return TextAbstraction::ARABIC; + } + if( ( 0x0900 <= character ) && ( character <= 0x097f ) ) + { + return TextAbstraction::DEVANAGARI; + } + if( ( 0x0980 <= character ) && ( character <= 0x09ff ) ) + { + return TextAbstraction::BENGALI; + } + } + } + else // > 0x09ff + { + if( character <= 0x0b7f ) + { + if( ( 0x0a00 <= character ) && ( character <= 0x0a7f ) ) + { + return TextAbstraction::GURMUKHI; + } + if( ( 0x0a80 <= character ) && ( character <= 0x0aff ) ) + { + return TextAbstraction::GUJARATI; + } + if( ( 0x0b00 <= character ) && ( character <= 0x0b7f ) ) + { + return TextAbstraction::ORIYA; + } + } + else // > 0x0b7f + { + if( ( 0x0b80 <= character ) && ( character <= 0x0bff ) ) + { + return TextAbstraction::TAMIL; + } + if( ( 0x0c00 <= character ) && ( character <= 0x0c7f ) ) + { + return TextAbstraction::TELUGU; + } + if( ( 0x0c80 <= character ) && ( character <= 0x0cff ) ) + { + return TextAbstraction::KANNADA; + } + } + } + } + else // > 0x0cff + { + if( character <= 0x2c7f ) + { + if( character <= 0x1eff ) + { + if( ( 0x0d00 <= character ) && ( character <= 0x0d7f ) ) + { + return TextAbstraction::MALAYALAM; + } + if( ( 0x0d80 <= character ) && ( character <= 0x0dff ) ) + { + return TextAbstraction::SINHALA; + } + if( ( 0x0e00 <= character ) && ( character <= 0x0e7f ) ) + { + return TextAbstraction::THAI; + } + if( ( 0x0e80 <= character ) && ( character <= 0x0eff ) ) + { + return TextAbstraction::LAO; + } + if( ( 0x1000 <= character ) && ( character <= 0x104f ) ) + { + return TextAbstraction::BURMESE; + } + if( ( 0x1100 <= character ) && ( character <= 0x11ff ) ) + { + return TextAbstraction::HANGUL; + } + if( ( 0x1780 <= character ) && ( character <= 0x17ff ) ) + { + return TextAbstraction::KHMER; + } + if( ( 0x19e0 <= character ) && ( character <= 0x19ff ) ) + { + return TextAbstraction::KHMER; + } + if( ( 0x1d00 <= character ) && ( character <= 0x1eff ) ) + { + return TextAbstraction::LATIN; + } + } + else // > 0x1eff + { + if( ( 0x2070 <= character ) && ( character <= 0x209f ) ) + { + return TextAbstraction::LATIN; + } + if( ( 0x2100 <= character ) && ( character <= 0x218f ) ) + { + return TextAbstraction::LATIN; + } + if( ( 0x2c60 <= character ) && ( character <= 0x2c7f ) ) + { + return TextAbstraction::LATIN; + } + } + } + else // > 0x2c7f + { + if( character <= 0xfdff ) + { + if( ( 0x2e80 <= character ) && ( character <= 0x2eff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x3000 <= character ) && ( character <= 0x303f ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x3130 <= character ) && ( character <= 0x318f ) ) + { + return TextAbstraction::HANGUL; + } + if( ( 0x3200 <= character ) && ( character <= 0x32ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x3400 <= character ) && ( character <= 0x4dbf ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x4e00 <= character ) && ( character <= 0x62ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x6300 <= character ) && ( character <= 0x77ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x7800 <= character ) && ( character <= 0x8cff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x8d00 <= character ) && ( character <= 0x9fff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0xa720 <= character ) && ( character <= 0xa7ff ) ) + { + return TextAbstraction::LATIN; + } + if( ( 0xa960 <= character ) && ( character <= 0xa97f ) ) + { + return TextAbstraction::HANGUL; + } + if( ( 0xab30 <= character ) && ( character <= 0xab6f ) ) + { + return TextAbstraction::LATIN; + } + if( ( 0xac00 <= character ) && ( character <= 0xd7af ) ) + { + return TextAbstraction::HANGUL; + } + if( ( 0xd7b0 <= character ) && ( character <= 0xd7ff ) ) + { + return TextAbstraction::HANGUL; + } + if( ( 0xfb00 <= character ) && ( character <= 0xfb4f ) ) + { + return TextAbstraction::LATIN; + } + if( ( 0xfb50 <= character ) && ( character <= 0xfdff ) ) + { + return TextAbstraction::ARABIC; + } + } + else // > 0xfdff + { + if( ( 0xfe70 <= character ) && ( character <= 0xfeff ) ) + { + return TextAbstraction::ARABIC; + } + if( ( 0xff00 <= character ) && ( character <= 0xffef ) ) + { + return TextAbstraction::LATIN; + } + if( ( 0x1ee00 <= character ) && ( character <= 0x1eeff ) ) + { + return TextAbstraction::ARABIC; + } + if( ( 0x20000 <= character ) && ( character <= 0x215ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x21600 <= character ) && ( character <= 0x230ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x23100 <= character ) && ( character <= 0x245ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x24600 <= character ) && ( character <= 0x260ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x26100 <= character ) && ( character <= 0x275ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x27600 <= character ) && ( character <= 0x290ff ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x29100 <= character ) && ( character <= 0x2a6df ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x2a700 <= character ) && ( character <= 0x2b73f ) ) + { + return TextAbstraction::CJK; + } + if( ( 0x2b740 <= character ) && ( character <= 0x2b81f ) ) + { + return TextAbstraction::CJK; + } + } + } + } + return TextAbstraction::UNKNOWN; } -- 2.7.4