From 93239b0a0c53c6475cc8398b091eb9f80a9c64e1 Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Tue, 17 Mar 2015 14:10:09 +0000 Subject: [PATCH] Internal text model inteface. Modify the internal interface of the text's logical and visual model to access the data directly without copying it. Change-Id: I3de4509653c473cf03c70c96474dd78bcd3aaa50 Signed-off-by: Victor Cebollada --- dali-toolkit/internal/file.list | 4 +- .../{logical-model.cpp => logical-model-impl.cpp} | 310 +++++---------- .../text/{logical-model.h => logical-model-impl.h} | 57 ++- .../internal/text/multi-language-support-impl.cpp | 2 +- dali-toolkit/internal/text/shaper.cpp | 4 +- dali-toolkit/internal/text/text-controller.cpp | 382 +++++++----------- dali-toolkit/internal/text/text-controller.h | 28 +- dali-toolkit/internal/text/text-definitions.h | 37 +- dali-toolkit/internal/text/text-view.h | 2 +- dali-toolkit/internal/text/visual-model-impl.cpp | 376 ++++++++++++++++++ .../text/{visual-model.h => visual-model-impl.h} | 50 ++- dali-toolkit/internal/text/visual-model.cpp | 426 --------------------- 12 files changed, 721 insertions(+), 957 deletions(-) rename dali-toolkit/internal/text/{logical-model.cpp => logical-model-impl.cpp} (52%) rename dali-toolkit/internal/text/{logical-model.h => logical-model-impl.h} (89%) create mode 100644 dali-toolkit/internal/text/visual-model-impl.cpp rename dali-toolkit/internal/text/{visual-model.h => visual-model-impl.h} (86%) delete mode 100644 dali-toolkit/internal/text/visual-model.cpp diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 3293406..4a27e26 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -78,7 +78,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/text/bidirectional-support.cpp \ $(toolkit_src_dir)/text/character-set-conversion.cpp \ $(toolkit_src_dir)/text/clipping/text-clipper.cpp \ - $(toolkit_src_dir)/text/logical-model.cpp \ + $(toolkit_src_dir)/text/logical-model-impl.cpp \ $(toolkit_src_dir)/text/multi-language-support.cpp \ $(toolkit_src_dir)/text/segmentation.cpp \ $(toolkit_src_dir)/text/shaper.cpp \ @@ -87,7 +87,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/text/text-io.cpp \ $(toolkit_src_dir)/text/text-view.cpp \ $(toolkit_src_dir)/text/text-view-interface.cpp \ - $(toolkit_src_dir)/text/visual-model.cpp \ + $(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-support-impl.cpp \ diff --git a/dali-toolkit/internal/text/logical-model.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp similarity index 52% rename from dali-toolkit/internal/text/logical-model.cpp rename to dali-toolkit/internal/text/logical-model-impl.cpp index 20cd630..807f7fb 100644 --- a/dali-toolkit/internal/text/logical-model.cpp +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -16,17 +16,11 @@ */ // CLASS HEADER -#include +#include // EXTERNAL INCLUDES #include -// INTERNAL INCLUDES -#include -#include -#include -#include - namespace Dali { @@ -35,36 +29,6 @@ namespace Toolkit namespace Text { -/** - * @brief caches some temporary values of the GetNumberOfScriptRuns( characterIndex, numberOfCharacters ) - * operation and the GetNumberOfFontRuns( characterIndex, numberOfCharacters ) as they are going to be - * used in the GetScriptRuns() and the GetFontRuns() calls. - */ -struct GetRunCache -{ - CharacterIndex characterIndex; ///< The character index. - Length numberOfCharacters; ///< The number of characters. - Length firstRun; ///< Index to the first run. - Length numberOfRuns; ///< The number of runs. -}; - -struct LogicalModel::Impl -{ - Vector mText; - Vector mScriptRuns; - Vector mFontRuns; - Vector mLineBreakInfo; - Vector mWordBreakInfo; - Vector mBidirectionalParagraphInfo; - - Vector mBidirectionalLineInfo; - Vector mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table. - Vector mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table. - - GetRunCache mGetScriptCache; ///< Caches the GetNumberOfScriptRuns( characterIndex, numberOfCharacters ) operation. - GetRunCache mGetFontCache; ///< Caches the GetNumberOfFontRuns( characterIndex, numberOfCharacters ) operation. - GetRunCache mGetBidirectionalCache; ///< Caches the GetNumberOfBidirectionalInfoRuns( characterIndex, numberOfCharacters ) operation. -}; LogicalModelPtr LogicalModel::New() { @@ -74,35 +38,32 @@ LogicalModelPtr LogicalModel::New() void LogicalModel::SetText( const Character* const text, Length numberOfCharacters ) { - Vector& modelText = mImpl->mText; - if( 0u == numberOfCharacters ) { - modelText.Clear(); + mText.Clear(); } else { - modelText.Resize( numberOfCharacters ); - memcpy( modelText.Begin(), text, numberOfCharacters * sizeof( Character ) ); + mText.Resize( numberOfCharacters ); + memcpy( mText.Begin(), text, numberOfCharacters * sizeof( Character ) ); } } Length LogicalModel::GetNumberOfCharacters() const { - return mImpl->mText.Count(); + return mText.Count(); } void LogicalModel::GetText( Character* text, CharacterIndex characterIndex, Length numberOfCharacters ) const { - Vector& modelText = mImpl->mText; - memcpy( text, modelText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) ); + memcpy( text, mText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) ); } Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const { - return mImpl->mText[characterIndex]; + return mText[characterIndex]; } void LogicalModel::ReplaceText( CharacterIndex characterIndex, @@ -115,52 +76,32 @@ void LogicalModel::ReplaceText( CharacterIndex characterIndex, void LogicalModel::SetScripts( const ScriptRun* const scripts, Length numberOfRuns ) { - Vector& scriptRuns = mImpl->mScriptRuns; - if( 0u == numberOfRuns ) { - scriptRuns.Clear(); + mScriptRuns.Clear(); } else { - scriptRuns.Resize( numberOfRuns ); - memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) ); + mScriptRuns.Resize( numberOfRuns ); + memcpy( mScriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) ); } - - mImpl->mGetScriptCache.characterIndex = 0u; - mImpl->mGetScriptCache.numberOfCharacters = 0u; - mImpl->mGetScriptCache.firstRun = 0u; - mImpl->mGetScriptCache.numberOfRuns = 0u; } -Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, - Length numberOfCharacters ) const +void LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + ScriptRunIndex& firstScriptRun, + Length& numberOfScriptRuns ) const { - GetRunCache& scriptCache = mImpl->mGetScriptCache; - - // Set the character index and the number of characters into the cache. - scriptCache.characterIndex = characterIndex; - scriptCache.numberOfCharacters = numberOfCharacters; - - if( ( 0u == characterIndex ) && - ( mImpl->mText.Count() == numberOfCharacters ) ) - { - scriptCache.firstRun = 0u; - scriptCache.numberOfRuns = mImpl->mScriptRuns.Count(); - return scriptCache.numberOfRuns; - } - // Initialize the number of scripts and the index to the first script. - scriptCache.firstRun = 0u; - scriptCache.numberOfRuns = 0; + firstScriptRun = 0u; + numberOfScriptRuns = 0; bool firstScriptFound = false; - const Vector& modelScripts = mImpl->mScriptRuns; const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; // Traverse the scripts and count those scripts within the range of characters. - for( Vector::ConstIterator it = modelScripts.Begin(), - endIt = modelScripts.End(); + for( Vector::ConstIterator it = mScriptRuns.Begin(), + endIt = mScriptRuns.End(); it != endIt; ++it ) { @@ -170,7 +111,7 @@ Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, ( lastCharacterIndex > script.characterRun.characterIndex ) ) { firstScriptFound = true; - ++scriptCache.numberOfRuns; + ++numberOfScriptRuns; } else if( lastCharacterIndex <= script.characterRun.characterIndex ) { @@ -180,37 +121,33 @@ Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, if( !firstScriptFound ) { - ++scriptCache.firstRun; + ++firstScriptRun; } } - - return scriptCache.numberOfRuns; } void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns, CharacterIndex characterIndex, Length numberOfCharacters ) const { - const Vector& modelScripts = mImpl->mScriptRuns; - GetRunCache& scriptCache = mImpl->mGetScriptCache; + ScriptRunIndex firstScriptRun = 0u; + Length numberOfScriptRuns = 0u; - if( ( characterIndex != scriptCache.characterIndex ) || - ( numberOfCharacters != scriptCache.numberOfCharacters ) ) - { - GetNumberOfScriptRuns( characterIndex, - numberOfCharacters ); - } + GetNumberOfScriptRuns( characterIndex, + numberOfCharacters, + firstScriptRun, + numberOfScriptRuns ); - memcpy( scriptRuns, modelScripts.Begin() + scriptCache.firstRun, scriptCache.numberOfRuns * sizeof( ScriptRun ) ); + memcpy( scriptRuns, mScriptRuns.Begin() + firstScriptRun, numberOfScriptRuns * sizeof( ScriptRun ) ); } Script LogicalModel::GetScript( CharacterIndex characterIndex ) const { // If this operation is too slow, consider a binary search. - for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index ) + for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index ) { - const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index; + const ScriptRun* const scriptRun = mScriptRuns.Begin() + index; if( ( scriptRun->characterRun.characterIndex <= characterIndex ) && ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) ) @@ -232,52 +169,32 @@ void LogicalModel::ReplaceScripts( CharacterIndex characterIndex, void LogicalModel::SetFonts( const FontRun* const fonts, Length numberOfRuns ) { - Vector& fontRuns = mImpl->mFontRuns; - if( 0u == numberOfRuns ) { - fontRuns.Clear(); + mFontRuns.Clear(); } else { - fontRuns.Resize( numberOfRuns ); - memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) ); + mFontRuns.Resize( numberOfRuns ); + memcpy( mFontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) ); } - - mImpl->mGetFontCache.characterIndex = 0u; - mImpl->mGetFontCache.numberOfCharacters = 0u; - mImpl->mGetFontCache.firstRun = 0u; - mImpl->mGetFontCache.numberOfRuns = 0u; } -Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, - Length numberOfCharacters ) const +void LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + FontRunIndex& firstFontRun, + Length& numberOfFontRuns ) const { - GetRunCache& fontCache = mImpl->mGetFontCache; - - // Set the character index and the number of characters into the cache. - fontCache.characterIndex = characterIndex; - fontCache.numberOfCharacters = numberOfCharacters; - - if( ( 0u == characterIndex ) && - ( mImpl->mText.Count() == numberOfCharacters ) ) - { - fontCache.firstRun = 0u; - fontCache.numberOfRuns = mImpl->mFontRuns.Count(); - return fontCache.numberOfRuns; - } - // Initialize the number of fonts and the index to the first font. - fontCache.firstRun = 0u; - fontCache.numberOfRuns = 0; + firstFontRun = 0u; + numberOfFontRuns = 0; bool firstFontFound = false; - const Vector& modelFonts = mImpl->mFontRuns; const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; // Traverse the fonts and count those fonts within the range of characters. - for( Vector::ConstIterator it = modelFonts.Begin(), - endIt = modelFonts.End(); + for( Vector::ConstIterator it = mFontRuns.Begin(), + endIt = mFontRuns.End(); it != endIt; ++it ) { @@ -287,7 +204,7 @@ Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) ) { firstFontFound = true; - ++fontCache.numberOfRuns; + ++numberOfFontRuns; } else if( lastCharacterIndex <= font.characterRun.characterIndex ) { @@ -297,35 +214,31 @@ Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, if( !firstFontFound ) { - ++fontCache.firstRun; + ++firstFontRun; } } - - return fontCache.numberOfRuns; } void LogicalModel::GetFontRuns( FontRun* fontRuns, CharacterIndex characterIndex, Length numberOfCharacters ) const { - const Vector& modelFonts = mImpl->mFontRuns; - GetRunCache& fontCache = mImpl->mGetFontCache; + FontRunIndex firstFontRun = 0u; + Length numberOfFontRuns = 0u; - if( ( characterIndex != fontCache.characterIndex ) || - ( numberOfCharacters != fontCache.numberOfCharacters ) ) - { - GetNumberOfFontRuns( characterIndex, - numberOfCharacters ); - } + GetNumberOfFontRuns( characterIndex, + numberOfCharacters, + firstFontRun, + numberOfFontRuns ); - memcpy( fontRuns, modelFonts.Begin() + fontCache.firstRun, fontCache.numberOfRuns * sizeof( FontRun ) ); + memcpy( fontRuns, mFontRuns.Begin() + firstFontRun, numberOfFontRuns * sizeof( FontRun ) ); } FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const { - for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index ) + for( Length index = 0u, length = mFontRuns.Count(); index < length; ++index ) { - const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index; + const FontRun* const fontRun = mFontRuns.Begin() + index; if( ( fontRun->characterRun.characterIndex <= characterIndex ) && ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) ) @@ -347,16 +260,14 @@ void LogicalModel::ReplaceFonts( CharacterIndex characterIndex, void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo, Length length ) { - Vector& modelLineBreakInfo = mImpl->mLineBreakInfo; - if( 0u == length ) { - modelLineBreakInfo.Clear(); + mLineBreakInfo.Clear(); } else { - modelLineBreakInfo.Resize( length ); - memcpy( modelLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) ); + mLineBreakInfo.Resize( length ); + memcpy( mLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) ); } } @@ -364,12 +275,12 @@ void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo, CharacterIndex characterIndex, Length numberOfItems ) const { - memcpy( lineBreakInfo, mImpl->mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) ); + memcpy( lineBreakInfo, mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) ); } LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const { - return *( mImpl->mLineBreakInfo.Begin() + characterIndex ); + return *( mLineBreakInfo.Begin() + characterIndex ); } void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex, @@ -382,16 +293,14 @@ void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex, void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo, Length length ) { - Vector& modelWordBreakInfo = mImpl->mWordBreakInfo; - if( 0u == length ) { - modelWordBreakInfo.Clear(); + mWordBreakInfo.Clear(); } else { - modelWordBreakInfo.Resize( length ); - memcpy( modelWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) ); + mWordBreakInfo.Resize( length ); + memcpy( mWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) ); } } @@ -399,12 +308,12 @@ void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo, CharacterIndex characterIndex, Length numberOfItems ) const { - memcpy( wordBreakInfo, mImpl->mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) ); + memcpy( wordBreakInfo, mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) ); } WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const { - return *( mImpl->mWordBreakInfo.Begin() + characterIndex ); + return *( mWordBreakInfo.Begin() + characterIndex ); } void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex, @@ -417,51 +326,30 @@ void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex, void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo, Length numberOfRuns ) { - Vector& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo; - if( 0u == numberOfRuns ) { - modelBidirectionalParagraphInfo.Clear(); + mBidirectionalParagraphInfo.Clear(); } else { - modelBidirectionalParagraphInfo.Resize( numberOfRuns ); - memcpy( modelBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) ); + mBidirectionalParagraphInfo.Resize( numberOfRuns ); + memcpy( mBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) ); } - - mImpl->mGetBidirectionalCache.characterIndex = 0u; - mImpl->mGetBidirectionalCache.numberOfCharacters = 0u; - mImpl->mGetBidirectionalCache.firstRun = 0u; - mImpl->mGetBidirectionalCache.numberOfRuns = 0u; } -Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, - Length numberOfCharacters ) const +void LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + BidirectionalRunIndex& firstBidirectionalRun, + Length& numberOfFontRuns ) const { - GetRunCache& bidiCache = mImpl->mGetBidirectionalCache; - - // Set the character index and the number of characters into the cache. - bidiCache.characterIndex = characterIndex; - bidiCache.numberOfCharacters = numberOfCharacters; - - if( ( 0u == characterIndex ) && - ( mImpl->mText.Count() == numberOfCharacters ) ) - { - bidiCache.firstRun = 0u; - bidiCache.numberOfRuns = mImpl->mBidirectionalParagraphInfo.Count(); - return bidiCache.numberOfRuns; - } - // Initialize the number of bidi paragraphs and the index to the first paragraph. - bidiCache.firstRun = 0u; - bidiCache.numberOfRuns = 0; + firstBidirectionalRun = 0u; + numberOfFontRuns = 0; bool firstParagraphFound = false; - const Vector& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo; - // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters. - for( Vector::ConstIterator it = modelBidirectionalParagraphInfo.Begin(), - endIt = modelBidirectionalParagraphInfo.End(); + for( Vector::ConstIterator it = mBidirectionalParagraphInfo.Begin(), + endIt = mBidirectionalParagraphInfo.End(); it != endIt; ++it ) { @@ -471,33 +359,29 @@ Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterI ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) ) { firstParagraphFound = true; - ++bidiCache.numberOfRuns; + ++numberOfFontRuns; } if( !firstParagraphFound ) { - ++bidiCache.firstRun; + ++firstBidirectionalRun; } } - - return bidiCache.numberOfRuns; } void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo, CharacterIndex characterIndex, Length numberOfCharacters ) const { - const Vector& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo; - GetRunCache& bidiCache = mImpl->mGetBidirectionalCache; + BidirectionalRunIndex firstBidirectionalRun = 0u; + Length numberOfFontRuns = 0u; - if( ( characterIndex != bidiCache.characterIndex ) || - ( numberOfCharacters != bidiCache.numberOfCharacters ) ) - { - GetNumberOfBidirectionalInfoRuns( characterIndex, - numberOfCharacters ); - } + GetNumberOfBidirectionalInfoRuns( characterIndex, + numberOfCharacters, + firstBidirectionalRun, + numberOfFontRuns ); - memcpy( bidirectionalInfo, modelBidirectionalParagraphInfo.Begin() + bidiCache.firstRun, bidiCache.numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) ); + memcpy( bidirectionalInfo, mBidirectionalParagraphInfo.Begin() + firstBidirectionalRun, numberOfFontRuns * sizeof( BidirectionalParagraphInfoRun ) ); } void ReplaceBidirectionalInfo( CharacterIndex characterIndex, @@ -521,22 +405,19 @@ CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex character void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo, Length numberOfRuns ) { - Vector& modelVisualToLogicalMap = mImpl->mVisualToLogicalMap; - Vector& modelLogicalToVisualMap = mImpl->mLogicalToVisualMap; - if( 0u == numberOfRuns ) { - modelVisualToLogicalMap.Clear(); - modelLogicalToVisualMap.Clear(); + mVisualToLogicalMap.Clear(); + mLogicalToVisualMap.Clear(); } else { - const Length numberOfCharacters = mImpl->mText.Count(); - modelVisualToLogicalMap.Resize( numberOfCharacters ); - modelLogicalToVisualMap.Resize( numberOfCharacters ); + const Length numberOfCharacters = mText.Count(); + mVisualToLogicalMap.Resize( numberOfCharacters ); + mLogicalToVisualMap.Resize( numberOfCharacters ); - CharacterIndex* modelVisualToLogicalMapBuffer = modelVisualToLogicalMap.Begin(); - CharacterIndex* modelLogicalToVisualMapBuffer = modelLogicalToVisualMap.Begin(); + CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin(); + CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin(); CharacterIndex lastIndex = 0u; for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex ) @@ -584,51 +465,48 @@ void LogicalModel::ReplaceVisualToLogicalMap( CharacterIndex characterIndex, CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const { - if( 0u == mImpl->mLogicalToVisualMap.Count() ) + if( 0u == mLogicalToVisualMap.Count() ) { // If there is no logical to visual info is because the whole text is left to right. // Return the identity. return logicalCharacterIndex; } - return *( mImpl->mLogicalToVisualMap.Begin() + logicalCharacterIndex ); + return *( mLogicalToVisualMap.Begin() + logicalCharacterIndex ); } CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const { - if( 0u == mImpl->mVisualToLogicalMap.Count() ) + if( 0u == mVisualToLogicalMap.Count() ) { // If there is no visual to logical info is because the whole text is left to right. // Return the identity. return visualCharacterIndex; } - return *( mImpl->mVisualToLogicalMap.Begin() + visualCharacterIndex ); + return *( mVisualToLogicalMap.Begin() + visualCharacterIndex ); } void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap, CharacterIndex characterIndex, Length numberOfCharacters ) const { - memcpy( logicalToVisualMap, mImpl->mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); + memcpy( logicalToVisualMap, mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); } void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap, CharacterIndex characterIndex, Length numberOfCharacters ) const { - memcpy( visualToLogicalMap, mImpl->mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); + memcpy( visualToLogicalMap, mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); } LogicalModel::~LogicalModel() { - delete mImpl; } LogicalModel::LogicalModel() -: mImpl( NULL ) { - mImpl = new LogicalModel::Impl(); } } // namespace Text diff --git a/dali-toolkit/internal/text/logical-model.h b/dali-toolkit/internal/text/logical-model-impl.h similarity index 89% rename from dali-toolkit/internal/text/logical-model.h rename to dali-toolkit/internal/text/logical-model-impl.h index 43490d1..c73190e 100644 --- a/dali-toolkit/internal/text/logical-model.h +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__ -#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__ +#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd. @@ -24,7 +24,10 @@ #include // INTERNAL INCLUDES -#include +#include +#include +#include +#include namespace Dali { @@ -134,17 +137,19 @@ public: Length numberOfRuns ); /** - * Retrieves the number of script runs for the given range of characters. + * Retrieves the number of script runs and the index to the first one for the given range of characters. * * A run is a group of consecutive characters. A script run contains the script for a run. * * @param[in] characterIndex Index to the first character. * @param[in] numberOfCharacters The number of characters. - * - * @return The number of script runs. + * @param[out] firstScriptRun Index to the script run containing the character index. + * @param[out] numberOfScriptRuns The number of script runs. */ - Length GetNumberOfScriptRuns( CharacterIndex characterIndex, - Length numberOfCharacters ) const; + void GetNumberOfScriptRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + ScriptRunIndex& firstScriptRun, + Length& numberOfScriptRuns ) const; /** * Retrieves the script runs for the given range of characters. @@ -201,17 +206,19 @@ public: Length numberOfRuns ); /** - * Retrieves the number of font runs for the given range of characters. + * Retrieves the number of font runs and the index of the first one for the given range of characters. * * A run is a group of consecutive characters. A font run contains the font id for a run. * * @param[in] characterIndex Index to the first character. * @param[in] numberOfCharacters The number of characters. - * - * @return The number of font runs. + * @param[out] firstFontRun Index to the font run containing the character index. + * @param[out] numberOfFontRuns The number of font runs. */ - Length GetNumberOfFontRuns( CharacterIndex characterIndex, - Length numberOfCharacters ) const; + void GetNumberOfFontRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + FontRunIndex& firstFontRun, + Length& numberOfFontRuns ) const; /** * Retrieves the font runs for the given range of characters. @@ -405,7 +412,7 @@ public: Length numberOfRuns ); /** - * Retrieves the number of bidirectional info runs for the given range of characters. + * Retrieves the number of bidirectional info runs and the index to the first one for the given range of characters. * * It may be zero if there is no right to left scripts. * @@ -414,8 +421,10 @@ public: * * @return The number of bidirectional info runs. */ - Length GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, - Length numberOfCharacters ) const; + void GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + BidirectionalRunIndex& firstBidirectionalRun, + Length& numberOfFontRuns ) const; /** * Retrieves the bidirectional paragraph info runs for the given range of characters. @@ -572,10 +581,18 @@ private: // Undefined LogicalModel& operator=( const LogicalModel& handle ); -private: +public: + + Vector mText; + Vector mScriptRuns; + Vector mFontRuns; + Vector mLineBreakInfo; + Vector mWordBreakInfo; + Vector mBidirectionalParagraphInfo; - struct Impl; - Impl* mImpl; + Vector mBidirectionalLineInfo; + Vector mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table. + Vector mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table. }; } // namespace Text @@ -584,4 +601,4 @@ private: } // namespace Dali -#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__ +#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp index f251025..fa50497 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.cpp +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -26,7 +26,7 @@ #include // INTERNAL INCLUDES -#include +#include #include #include #include diff --git a/dali-toolkit/internal/text/shaper.cpp b/dali-toolkit/internal/text/shaper.cpp index c0c45fd..55101eb 100644 --- a/dali-toolkit/internal/text/shaper.cpp +++ b/dali-toolkit/internal/text/shaper.cpp @@ -24,9 +24,9 @@ // INTERNAL INCLUDES #include -#include +#include #include -#include +#include namespace Dali { diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index a203e03..24521a5 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -29,13 +29,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include +#include using std::vector; @@ -309,14 +309,10 @@ struct Controller::TextInput return; } - Vector glyphs; - glyphs.Resize( numberOfGlyphs ); - mVisualModel->GetGlyphs( glyphs.Begin(), 0, numberOfGlyphs ); + Vector& glyphs = mVisualModel->mGlyphs; const GlyphInfo* const glyphsBuffer = glyphs.Begin(); - Vector positions; - positions.Resize( numberOfGlyphs ); - mVisualModel->GetGlyphPositions( positions.Begin(), 0, numberOfGlyphs ); + Vector& positions = mVisualModel->mGlyphPositions; const Vector2* const positionsBuffer = positions.Begin(); unsigned int closestGlyph = 0; @@ -615,6 +611,92 @@ bool Controller::GetEnableCursorBlink() const return false; } +Vector3 Controller::GetNaturalSize() +{ + Vector3 naturalSize; + + if( mImpl->mRecalculateNaturalSize ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + SHAPE_TEXT | + GET_GLYPH_METRICS ); + // Make sure the model is up-to-date before layouting + ReplaceText( onlyOnceOperations ); + + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + REORDER ); + + DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + naturalSize.GetVectorXY() ); + + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); + + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + + // Stores the natural size to avoid recalculate it again + // unless the text/style changes. + mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() ); + + mImpl->mRecalculateNaturalSize = false; + } + else + { + naturalSize = mImpl->mVisualModel->GetNaturalSize(); + } + + return naturalSize; +} + +float Controller::GetHeightForWidth( float width ) +{ + Size layoutSize; + if( width != mImpl->mControlSize.width ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + SHAPE_TEXT | + GET_GLYPH_METRICS ); + + // Make sure the model is up-to-date before layouting + ReplaceText( onlyOnceOperations ); + + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + REORDER ); + + DoRelayout( Size( width, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + layoutSize ); + + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); + + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); + } + + return layoutSize.height; +} + bool Controller::Relayout( const Vector2& size ) { if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) @@ -636,8 +718,6 @@ bool Controller::Relayout( const Vector2& size ) mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | LAYOUT | UPDATE_ACTUAL_SIZE | - UPDATE_POSITIONS | - UPDATE_LINES | REORDER ); mImpl->mControlSize = size; @@ -668,8 +748,7 @@ void Controller::ReplaceText( OperationsMask operationsRequired ) // Calculate the operations to be done. const OperationsMask operations = static_cast( mImpl->mOperationsPending & operationsRequired ); - Vector utf32Characters; - Length characterCount = 0u; + Vector& utf32Characters = mImpl->mLogicalModel->mText; if( CONVERT_TO_UTF32 & operations ) { std::string& text = mImpl->mNewText; @@ -682,50 +761,43 @@ void Controller::ReplaceText( OperationsMask operationsRequired ) // Transform a text array encoded in utf8 into an array encoded in utf32. // It returns the actual number of characters. - characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() ); + const Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() ); utf32Characters.Resize( characterCount ); - // Sets the text into the model. - mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount ); - // Discard temporary text text.clear(); } const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); - Vector lineBreakInfo; + Vector& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo; if( GET_LINE_BREAKS & operations ) { // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to // calculate the bidirectional info for each 'paragraph'. // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines // is not shaped together). - lineBreakInfo.Resize( characterCount, TextAbstraction::LINE_NO_BREAK ); + lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK ); SetLineBreakInfo( utf32Characters, lineBreakInfo ); - - mImpl->mLogicalModel->SetLineBreakInfo( lineBreakInfo.Begin(), characterCount ); } - Vector wordBreakInfo; + Vector& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo; if( GET_WORD_BREAKS & operations ) { // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines). - wordBreakInfo.Resize( characterCount, TextAbstraction::WORD_NO_BREAK ); + wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK ); SetWordBreakInfo( utf32Characters, wordBreakInfo ); - - mImpl->mLogicalModel->SetWordBreakInfo( wordBreakInfo.Begin(), characterCount ); } const bool getScripts = GET_SCRIPTS & operations; const bool validateFonts = VALIDATE_FONTS & operations; - Vector scripts; - Vector validFonts; + Vector& scripts = mImpl->mLogicalModel->mScriptRuns; + Vector& validFonts = mImpl->mLogicalModel->mFontRuns; if( getScripts || validateFonts ) { @@ -739,68 +811,34 @@ void Controller::ReplaceText( OperationsMask operationsRequired ) multilanguageSupport.SetScripts( utf32Characters, lineBreakInfo, scripts ); - - // Sets the scripts into the model. - mImpl->mLogicalModel->SetScripts( scripts.Begin(), scripts.Count() ); } if( validateFonts ) { - // Copy the requested font defaults received via the property system. - // These may not be valid i.e. may not contain glyphs for the necessary scripts. - GetDefaultFonts( validFonts, numberOfCharacters ); + if( 0u == validFonts.Count() ) + { + // Copy the requested font defaults received via the property system. + // These may not be valid i.e. may not contain glyphs for the necessary scripts. + GetDefaultFonts( validFonts, numberOfCharacters ); + } // Validates the fonts. If there is a character with no assigned font it sets a default one. // After this call, fonts are validated. multilanguageSupport.ValidateFonts( utf32Characters, scripts, validFonts ); - - // Sets the fonts into the model. - mImpl->mLogicalModel->SetFonts( validFonts.Begin(), validFonts.Count() ); } } if( BIDI_INFO & operations ) { - // Some vectors with data needed to get the paragraph's bidirectional info may be void - // after the first time the text has been laid out. - // Fill the vectors again. - - if( 0u == utf32Characters.Count() ) - { - utf32Characters.Resize( numberOfCharacters ); - - mImpl->mLogicalModel->GetText( utf32Characters.Begin(), - 0u, - numberOfCharacters ); - } - - if( 0u == lineBreakInfo.Count() ) - { - lineBreakInfo.Resize( numberOfCharacters ); - - mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(), - 0u, - numberOfCharacters ); - } - - if( 0u == scripts.Count() ) - { - scripts.Resize( mImpl->mLogicalModel->GetNumberOfScriptRuns( 0u, - numberOfCharacters ) ); - mImpl->mLogicalModel->GetScriptRuns( scripts.Begin(), - 0u, - numberOfCharacters ); - } - // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's // bidirectional info. Length numberOfParagraphs = 0u; const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); - for( Length index = 0u; index < characterCount; ++index ) + for( Length index = 0u; index < numberOfCharacters; ++index ) { if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) ) { @@ -808,7 +846,7 @@ void Controller::ReplaceText( OperationsMask operationsRequired ) } } - Vector bidirectionalInfo; + Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; bidirectionalInfo.Reserve( numberOfParagraphs ); // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. @@ -816,25 +854,13 @@ void Controller::ReplaceText( OperationsMask operationsRequired ) scripts, lineBreakInfo, bidirectionalInfo ); - - mImpl->mLogicalModel->SetBidirectionalInfo( bidirectionalInfo.Begin(), - bidirectionalInfo.Count() ); } - Vector glyphs; - Vector glyphsToCharactersMap; - Vector charactersPerGlyph; + Vector& glyphs = mImpl->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; if( SHAPE_TEXT & operations ) { - if( 0u == validFonts.Count() ) - { - validFonts.Resize( mImpl->mLogicalModel->GetNumberOfFontRuns( 0u, - numberOfCharacters ) ); - mImpl->mLogicalModel->GetFontRuns( validFonts.Begin(), - 0u, - numberOfCharacters ); - } - // Shapes the text. ShapeText( utf32Characters, lineBreakInfo, @@ -845,19 +871,18 @@ void Controller::ReplaceText( OperationsMask operationsRequired ) charactersPerGlyph ); } + const Length numberOfGlyphs = glyphs.Count(); + if( GET_GLYPH_METRICS & operations ) { - mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() ); + mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs ); } - Length numberOfGlyphs = glyphs.Count(); if( 0u != numberOfGlyphs ) { - // Sets the glyphs into the model. - mImpl->mVisualModel->SetGlyphs( glyphs.Begin(), - glyphsToCharactersMap.Begin(), - charactersPerGlyph.Begin(), - numberOfGlyphs ); + // Create the glyph to character conversion table and the 'number of glyphs' per character. + mImpl->mVisualModel->CreateCharacterToGlyphTable(numberOfCharacters ); + mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters ); } } @@ -879,35 +904,11 @@ bool Controller::DoRelayout( const Vector2& size, const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs(); - Vector lineBreakInfo; - lineBreakInfo.Resize( numberOfCharacters ); - mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(), - 0u, - numberOfCharacters ); - - Vector wordBreakInfo; - wordBreakInfo.Resize( numberOfCharacters ); - mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(), - 0u, - numberOfCharacters ); - - Vector glyphs; - glyphs.Resize( numberOfGlyphs ); - mImpl->mVisualModel->GetGlyphs( glyphs.Begin(), - 0u, - numberOfGlyphs ); - - Vector glyphsToCharactersMap; - glyphsToCharactersMap.Resize( numberOfGlyphs ); - mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(), - 0u, - numberOfGlyphs ); - - Vector charactersPerGlyph; - charactersPerGlyph.Resize( numberOfGlyphs ); - mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(), - 0u, - numberOfGlyphs ); + Vector& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo; + Vector& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo; + Vector& glyphs = mImpl->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; // Set the layout parameters. LayoutParameters layoutParameters( size, @@ -918,16 +919,23 @@ bool Controller::DoRelayout( const Vector2& size, glyphsToCharactersMap.Begin(), charactersPerGlyph.Begin() ); - // Reserve space to set the positions of the glyphs. - Vector glyphPositions; - glyphPositions.Resize( numberOfGlyphs ); - // The laid-out lines. // It's not possible to know in how many lines the text is going to be laid-out, // but it can be resized at least with the number of 'paragraphs' to avoid // some re-allocations. - Vector lines; - lines.Reserve( mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ) ); + Vector& lines = mImpl->mVisualModel->mLines; + + // Resize the vector of positions to have the same size than the vector of glyphs. + Vector& glyphPositions = mImpl->mVisualModel->mGlyphPositions; + glyphPositions.Resize( numberOfGlyphs ); + + BidirectionalRunIndex firstBidiRunIndex = 0u; + Length numberOfBidiRuns = 0u; + mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters, firstBidiRunIndex, numberOfBidiRuns ); + + // Delete any previous laid out lines before setting the new ones. + lines.Clear(); + lines.Reserve( numberOfBidiRuns ); // Update the visual model. viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, @@ -940,13 +948,7 @@ bool Controller::DoRelayout( const Vector2& size, // Reorder the lines if( REORDER & operations ) { - const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ); - - Vector bidirectionalInfo; - bidirectionalInfo.Resize( numberOfBidiParagraphs ); - mImpl->mLogicalModel->GetBidirectionalInfo( bidirectionalInfo.Begin(), - 0u, - numberOfCharacters ); + Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; // Check first if there are paragraphs with bidirectional info. if( 0u != bidirectionalInfo.Count() ) @@ -971,22 +973,10 @@ bool Controller::DoRelayout( const Vector2& size, layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns; // Get the character to glyph conversion table and set into the layout. - Vector characterToGlyphMap; - characterToGlyphMap.Resize( numberOfCharacters ); - - layoutParameters.charactersToGlyphsBuffer = characterToGlyphMap.Begin(); - mImpl->mVisualModel->GetCharacterToGlyphMap( layoutParameters.charactersToGlyphsBuffer, - 0u, - numberOfCharacters ); + layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin(); // Get the glyphs per character table and set into the layout. - Vector glyphsPerCharacter; - glyphsPerCharacter.Resize( numberOfCharacters ); - - layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin(); - mImpl->mVisualModel->GetGlyphsPerCharacterMap( layoutParameters.glyphsPerCharacterBuffer, - 0u, - numberOfCharacters ); + layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin(); // Re-layout the text. Reorder those lines with right to left characters. mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters, @@ -1005,20 +995,6 @@ bool Controller::DoRelayout( const Vector2& size, } } - // Sets the positions into the model. - if( UPDATE_POSITIONS & operations ) - { - mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(), - numberOfGlyphs ); - } - - // Sets the lines into the model. - if( UPDATE_LINES & operations ) - { - mImpl->mVisualModel->SetLines( lines.Begin(), - lines.Count() ); - } - // Sets the actual size. if( UPDATE_ACTUAL_SIZE & operations ) { @@ -1034,92 +1010,6 @@ bool Controller::DoRelayout( const Vector2& size, return viewUpdated; } -Vector3 Controller::GetNaturalSize() -{ - Vector3 naturalSize; - - if( mImpl->mRecalculateNaturalSize ) - { - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - GET_WORD_BREAKS | - SHAPE_TEXT | - GET_GLYPH_METRICS ); - // Make sure the model is up-to-date before layouting - ReplaceText( onlyOnceOperations ); - - // Operations that need to be done if the size changes. - const OperationsMask sizeOperations = static_cast( LAYOUT | - REORDER ); - - DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ), - static_cast( onlyOnceOperations | - sizeOperations ), - naturalSize.GetVectorXY() ); - - // Do not do again the only once operations. - mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); - - // Do the size related operations again. - mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); - - // Stores the natural size to avoid recalculate it again - // unless the text/style changes. - mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() ); - - mImpl->mRecalculateNaturalSize = false; - } - else - { - naturalSize = mImpl->mVisualModel->GetNaturalSize(); - } - - return naturalSize; -} - -float Controller::GetHeightForWidth( float width ) -{ - Size layoutSize; - if( width != mImpl->mControlSize.width ) - { - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - GET_WORD_BREAKS | - SHAPE_TEXT | - GET_GLYPH_METRICS ); - - // Make sure the model is up-to-date before layouting - ReplaceText( onlyOnceOperations ); - - // Operations that need to be done if the size changes. - const OperationsMask sizeOperations = static_cast( LAYOUT | - REORDER ); - - DoRelayout( Size( width, MAX_FLOAT ), - static_cast( onlyOnceOperations | - sizeOperations ), - layoutSize ); - - // Do not do again the only once operations. - mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); - - // Do the size related operations again. - mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); - } - else - { - layoutSize = mImpl->mVisualModel->GetActualSize(); - } - - return layoutSize.height; -} - View& Controller::GetView() { return mImpl->mView; diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index ee77ca3..46bf38f 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -77,11 +77,9 @@ private: GET_GLYPH_METRICS = 0x0080, LAYOUT = 0x0100, UPDATE_ACTUAL_SIZE = 0x0200, - UPDATE_POSITIONS = 0x0400, - UPDATE_LINES = 0x0800, - REORDER = 0x1000, - ALIGNMENT = 0x2000, - RENDER = 0x4000, + REORDER = 0x0400, + ALIGNMENT = 0x0800, + RENDER = 0x1000, ALL_OPERATIONS = 0xFFFF }; @@ -198,6 +196,16 @@ public: bool GetEnableCursorBlink() const; /** + * @copydoc Control::GetNaturalSize() + */ + Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + float GetHeightForWidth( float width ); + + /** * @brief Triggers a relayout which updates View (if necessary). * * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation. @@ -227,16 +235,6 @@ public: Size& layoutSize ); /** - * @copydoc Control::GetNaturalSize() - */ - Vector3 GetNaturalSize(); - - /** - * @copydoc Control::GetHeightForWidth() - */ - float GetHeightForWidth( float width ); - - /** * @brief Return the layout engine. * * @return A reference to the layout engine. diff --git a/dali-toolkit/internal/text/text-definitions.h b/dali-toolkit/internal/text/text-definitions.h index d991384..6f00b7b 100644 --- a/dali-toolkit/internal/text/text-definitions.h +++ b/dali-toolkit/internal/text/text-definitions.h @@ -33,23 +33,26 @@ namespace Toolkit namespace Text { -typedef TextAbstraction::FontId FontId; ///< The unique identifier for a font face (generated by FontClient). -typedef TextAbstraction::FontMetrics FontMetrics; ///< The metrics for a Font expressed in 26.6 fractional pixel format. -typedef TextAbstraction::PointSize26Dot6 PointSize26Dot6; ///< The point size in 26.6 fractional points. -typedef TextAbstraction::FaceIndex FaceIndex; ///< Used with fonts which allow several font faces. -typedef TextAbstraction::GlyphIndex GlyphIndex; ///< Uniquely identifies a glyph within a particular font. -typedef TextAbstraction::Character Character; ///< A UTF-32 representation of a character. -typedef TextAbstraction::GlyphInfo GlyphInfo; ///< The information describing a glyph (font ID, index, metrics). -typedef TextAbstraction::CharacterIndex CharacterIndex; ///< An index into an array of characters. -typedef TextAbstraction::Length Length; ///< The length of an array. -typedef TextAbstraction::BidiInfoIndex BidiInfoIndex; ///< Index to the bidirectional info for a paragraph. -typedef TextAbstraction::Script Script; ///< The character's script. -typedef TextAbstraction::LineBreakInfo LineBreakInfo; ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace). -typedef TextAbstraction::WordBreakInfo WordBreakInfo; ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace). - -typedef uint32_t GlyphIndex; ///< An index into an array of glyphs. -typedef bool CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left. -typedef uint32_t LineIndex; ///< An index into an array of lines. +typedef TextAbstraction::FontId FontId; ///< The unique identifier for a font face (generated by FontClient). +typedef TextAbstraction::FontMetrics FontMetrics; ///< The metrics for a Font expressed in 26.6 fractional pixel format. +typedef TextAbstraction::PointSize26Dot6 PointSize26Dot6; ///< The point size in 26.6 fractional points. +typedef TextAbstraction::FaceIndex FaceIndex; ///< Used with fonts which allow several font faces. +typedef TextAbstraction::GlyphIndex GlyphIndex; ///< Uniquely identifies a glyph within a particular font. +typedef TextAbstraction::Character Character; ///< A UTF-32 representation of a character. +typedef TextAbstraction::GlyphInfo GlyphInfo; ///< The information describing a glyph (font ID, index, metrics). +typedef TextAbstraction::CharacterIndex CharacterIndex; ///< An index into an array of characters. +typedef TextAbstraction::Length Length; ///< The length of an array. +typedef TextAbstraction::BidiInfoIndex BidiInfoIndex; ///< Index to the bidirectional info for a paragraph. +typedef TextAbstraction::Script Script; ///< The character's script. +typedef TextAbstraction::LineBreakInfo LineBreakInfo; ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace). +typedef TextAbstraction::WordBreakInfo WordBreakInfo; ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace). + +typedef uint32_t GlyphIndex; ///< An index into an array of glyphs. +typedef bool CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left. +typedef uint32_t ScriptRunIndex; ///< An index into an array of script runs. +typedef uint32_t FontRunIndex; ///< An index into an array of font runs. +typedef uint32_t BidirectionalRunIndex; ///< An index into an array of font runs. +typedef uint32_t LineIndex; ///< An index into an array of lines. } // namespace Text diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h index c3d033e..56ce0be 100644 --- a/dali-toolkit/internal/text/text-view.h +++ b/dali-toolkit/internal/text/text-view.h @@ -20,7 +20,7 @@ // INTERNAL INCLUDES #include -#include +#include namespace Dali { diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp new file mode 100644 index 0000000..5822469 --- /dev/null +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -0,0 +1,376 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +VisualModelPtr VisualModel::New() +{ + return VisualModelPtr( new VisualModel() ); +} + +void VisualModel::SetGlyphs( const GlyphInfo* glyphs, + const CharacterIndex* characterIndices, + const Length* charactersPerGlyph, + Length numberOfGlyphs ) +{ + if( 0u == numberOfGlyphs ) + { + mGlyphs.Clear(); + mGlyphsToCharacters.Clear(); + mCharactersToGlyph.Clear(); + mCharactersPerGlyph.Clear(); + mGlyphsPerCharacter.Clear(); + } + else + { + if( NULL != glyphs ) + { + mGlyphs.Resize( numberOfGlyphs ); + memcpy( mGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); + } + + if( NULL != characterIndices ) + { + mGlyphsToCharacters.Resize( numberOfGlyphs ); + memcpy( mGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) ); + } + + if( NULL != charactersPerGlyph ) + { + mCharactersPerGlyph.Resize( numberOfGlyphs ); + memcpy( mCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) ); + + // Build the characters to glyph conversion table. + CreateCharacterToGlyphTable(); + + // Build the glyphs per character table. + CreateGlyphsPerCharacterTable(); + } + } +} + +void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters ) +{ + // 1) Reserve some space for the characters to avoid reallocations. + if( 0u == numberOfCharacters ) + { + // If no number of characters is given, just set something sensible to avoid reallocations. + numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + } + mCharactersToGlyph.Reserve( numberOfCharacters ); + + // 2) Traverse the glyphs and set the glyph indices per character. + + // Index to the glyph. + GlyphIndex glyphIndex = 0u; + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + endIt = mCharactersPerGlyph.End(); + it != endIt; + ++it, ++glyphIndex ) + { + const Length numberOfCharactersPerGlyph = *it; + + // Set the glyph indices. + for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index ) + { + mCharactersToGlyph.PushBack( glyphIndex ); + } + } +} + +void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters ) +{ + // 1) Reserve some space for the characters to avoid reallocations. + if( 0u == numberOfCharacters ) + { + // If no number of characters is given, just set something sensible to avoid reallocations. + numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + } + mCharactersToGlyph.Reserve( numberOfCharacters ); + + // 2) Traverse the glyphs and set the number of glyphs per character. + + // The number of 'characters per glyph' equal to zero. + Length zeroCharactersPerGlyph = 0u; + + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + endIt = mCharactersPerGlyph.End(); + it != endIt; + ++it ) + { + const Length numberOfCharactersPerGlyph = *it; + + // Set the glyphs per character. + if( 0u == numberOfCharactersPerGlyph ) + { + ++zeroCharactersPerGlyph; + } + else + { + const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u ); + for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex ) + { + mGlyphsPerCharacter.PushBack( 0u ); + } + + mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph ); + + zeroCharactersPerGlyph = 0u; + } + } +} + +Length VisualModel::GetNumberOfGlyphs() const +{ + return mGlyphs.Count(); +} + +void VisualModel::GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) ); +} + +const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const +{ + return mGlyphs[glyphIndex]; +} + +void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const GlyphInfo* const glyphs, + const Length* const numberOfCharacters, + Length numberOfGlyphsToInsert ) +{ +} + +CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const +{ + return mGlyphsToCharacters[glyphIndex]; +} + +Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const +{ + return mCharactersPerGlyph[glyphIndex]; +} + +GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const +{ + return mCharactersToGlyph[characterIndex]; +} + +void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) ); +} + +void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) ); +} + +void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) ); +} + +void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) ); +} + +void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, + Length numberOfGlyphs ) +{ + if( 0u == numberOfGlyphs ) + { + mGlyphPositions.Clear(); + } + else + { + mGlyphPositions.Resize( numberOfGlyphs ); + memcpy( mGlyphPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); + } +} + +Length VisualModel::GetNumberOfGlyphPositions() const +{ + return mGlyphPositions.Count(); +} + +void VisualModel::GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) ); +} + +const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const +{ + return *( mGlyphPositions.Begin() + glyphIndex ); +} + +void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const Vector2* const positions, + Length numberOfGlyphsToInsert ) +{ +} + +void VisualModel::SetLines( const LineRun* const lines, + Length numberOfLines ) +{ + if( 0u == numberOfLines ) + { + mLines.Clear(); + } + else + { + mLines.Resize( numberOfLines ); + memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) ); + } +} + +Length VisualModel::GetNumberOfLines() const +{ + return mLines.Count(); +} + +void VisualModel::GetLines( LineRun* lines, + LineIndex lineIndex, + Length numberOfLines ) const +{ + memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) ); +} + +void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs, + LineIndex& firstLine, + Length& numberOfLines ) const +{ + // Initialize the number of lines and the first line. + firstLine = 0u; + numberOfLines = 0u; + bool firstLineFound = false; + + const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs; + + // Traverse the lines and count those lines within the range of glyphs. + for( Vector::ConstIterator it = mLines.Begin(), + endIt = mLines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) && + ( lastGlyphIndex > line.glyphIndex ) ) + { + firstLineFound = true; + ++numberOfLines; + } + else if( lastGlyphIndex <= line.glyphIndex ) + { + // nothing else to do. + break; + } + + if( !firstLineFound ) + { + ++firstLine; + } + } +} + +void VisualModel::GetLinesOfGlyphRange( LineRun* lines, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + LineIndex firstLine = 0u; + Length numberOfLines = 0u; + + GetNumberOfLines( glyphIndex, + numberOfGlyphs, + firstLine, + numberOfLines ); + + memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) ); +} + +void VisualModel::ReplaceLines( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const LineRun* const lines, + Length numberOfGlyphsToInsert ) +{ +} + +void VisualModel::SetNaturalSize( const Vector2& size ) +{ + mNaturalSize = size; +} + +const Vector2& VisualModel::GetNaturalSize() const +{ + return mNaturalSize; +} + +void VisualModel::SetActualSize( const Vector2& size ) +{ + mActualSize = size; +} + +const Vector2& VisualModel::GetActualSize() const +{ + return mActualSize; +} + +VisualModel::~VisualModel() +{ +} + +VisualModel::VisualModel() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/visual-model.h b/dali-toolkit/internal/text/visual-model-impl.h similarity index 86% rename from dali-toolkit/internal/text/visual-model.h rename to dali-toolkit/internal/text/visual-model-impl.h index 4dee216..415b4a0 100644 --- a/dali-toolkit/internal/text/visual-model.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_H__ -#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_H__ +#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ /* * Copyright (c) 2015 Samsung Electronics Co., Ltd. @@ -19,11 +19,12 @@ */ // EXTERNAL INCLUDES +#include #include #include // INTERNAL INCLUDES -#include +#include namespace Dali { @@ -77,6 +78,20 @@ public: Length numberOfGlyphs ); /** + * @brief Creates the character to glyph conversion table. + * + * @param[in] numberOfCharacters The number of characters. + */ + void CreateCharacterToGlyphTable( Length numberOfCharacters = 0u ); + + /** + * @brief Creates an array containing the number of glyphs per character. + * + * @param[in] numberOfCharacters The number of characters. + */ + void CreateGlyphsPerCharacterTable( Length numberOfCharacters = 0u ); + + /** * Retrieves the number of glyphs. * * @return The number of glyphs. @@ -296,15 +311,17 @@ public: Length numberOfLines ) const; /** - * Retrieves the number of lines where the given range of glyphs is laid out. + * Retrieves the number of lines and the index to the first line where the given range of glyphs is laid out. * * @param[in] glyphIndex Index to the first glyph. * @param[in] numberOfGlyphs The number of glyph. - * - * @return The number of lines. + * @param[out] firstLine Index to the line containing the glyph index. + * @param[out] numberOfLines The number of lines. */ - Length GetNumberOfLines( GlyphIndex glyphIndex, - Length numberOfGlyphs ) const; + void GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs, + LineIndex& firstLine, + Length& numberOfLines ) const; /** * Retrieves the lines where the given range of glyphs is laid out. * @@ -384,15 +401,26 @@ private: // Undefined VisualModel& operator=( const VisualModel& handle ); +public: + + Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. + Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. + Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. + Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. + Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. + Vector mGlyphPositions; ///< For each glyph, the position. + Vector mLines; ///< The laid out lines. + private: - struct Impl; - Impl* mImpl; + Size mNaturalSize; ///< Size of the text with no line wrapping. + Size mActualSize; ///< Size of the laid-out text considering the layout properties set. }; + } // namespace Text } // namespace Toolkit } // namespace Dali -#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_H__ +#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ diff --git a/dali-toolkit/internal/text/visual-model.cpp b/dali-toolkit/internal/text/visual-model.cpp deleted file mode 100644 index e7015e0..0000000 --- a/dali-toolkit/internal/text/visual-model.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* - * 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 - -// EXTERNAL INCLUDES -#include -#include -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Text -{ - -/** - * @brief caches some temporary values of the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation - * as they are going to be used in the GetLinesOfGlyphRange() call. - */ -struct GetLineCache -{ - GlyphIndex glyphIndex; ///< The glyph index. - Length numberOfGlyphs; ///< The number of glyphs. - Length firstLine; ///< Index to the first line. - Length numberOfLines; ///< The number of lines. -}; - -struct VisualModel::Impl -{ - Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. - Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. - Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. - Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. - Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. - Vector mGlyphPositions; ///< For each glyph, the position. - Vector mLines; ///< The laid out lines. - - Size mNaturalSize; ///< Size of the text with no line wrapping. - Size mActualSize; ///< Size of the laid-out text considering the layout properties set. - - GetLineCache mGetLineCache; ///< Caches the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation. -}; - -VisualModelPtr VisualModel::New() -{ - return VisualModelPtr( new VisualModel() ); -} - -void VisualModel::SetGlyphs( const GlyphInfo* glyphs, - const CharacterIndex* characterIndices, - const Length* charactersPerGlyph, - Length numberOfGlyphs ) -{ - Vector& modelGlyphs = mImpl->mGlyphs; - Vector& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters; - Vector& modelCharactersToGlyph = mImpl->mCharactersToGlyph; - Vector& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph; - Vector& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter; - - if( 0u == numberOfGlyphs ) - { - modelGlyphs.Clear(); - modelGlyphsToCharacters.Clear(); - modelCharactersToGlyph.Clear(); - modelCharactersPerGlyph.Clear(); - modelGlyphsPerCharacter.Clear(); - } - else - { - if( NULL != glyphs ) - { - modelGlyphs.Resize( numberOfGlyphs ); - memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); - } - - if( NULL != characterIndices ) - { - modelGlyphsToCharacters.Resize( numberOfGlyphs ); - memcpy( modelGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) ); - } - - if( NULL != charactersPerGlyph ) - { - modelCharactersPerGlyph.Resize( numberOfGlyphs ); - memcpy( modelCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) ); - - // Build the characters to glyph conversion table. - - // 1) Reserve some space for the characters to avoid reallocations. - const Length numberOfCharacters = static_cast ( static_cast( numberOfGlyphs ) * 1.3f ); - modelCharactersToGlyph.Reserve( numberOfCharacters ); - modelGlyphsPerCharacter.Reserve( numberOfCharacters ); - - // 2) Traverse the glyphs and set the glyph indices and the glyphs per character. - - // The number of 'characters per glyph' equal to zero. - Length zeroCharactersPerGlyph = 0u; - - // Index to the glyph. - GlyphIndex glyphIndex = 0u; - for( Vector::ConstIterator it = modelCharactersPerGlyph.Begin(), - endIt = modelCharactersPerGlyph.End(); - it != endIt; - ++it, ++glyphIndex ) - { - const Length numberOfCharacters = *it; - - // Set the glyph indices. - for( Length index = 0u; index < numberOfCharacters; ++index ) - { - modelCharactersToGlyph.PushBack( glyphIndex ); - } - - // Set the glyphs per character. - if( 0u == numberOfCharacters ) - { - ++zeroCharactersPerGlyph; - } - else - { - const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharacters - 1u ); - for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex ) - { - modelGlyphsPerCharacter.PushBack( 0u ); - } - - modelGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph ); - - zeroCharactersPerGlyph = 0u; - } - } - } - } -} - -Length VisualModel::GetNumberOfGlyphs() const -{ - return mImpl->mGlyphs.Count(); -} - -void VisualModel::GetGlyphs( GlyphInfo* glyphs, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - const Vector& modelGlyphs = mImpl->mGlyphs; - memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) ); -} - -const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const -{ - return mImpl->mGlyphs[glyphIndex]; -} - -void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const GlyphInfo* const glyphs, - const Length* const numberOfCharacters, - Length numberOfGlyphsToInsert ) -{ -} - -CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const -{ - return mImpl->mGlyphsToCharacters[glyphIndex]; -} - -Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const -{ - return mImpl->mCharactersPerGlyph[glyphIndex]; -} - -GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const -{ - return mImpl->mCharactersToGlyph[characterIndex]; -} - -void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - const Vector& modelCharactersToGlyph = mImpl->mCharactersToGlyph; - memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) ); -} - -void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - const Vector& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters; - memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) ); -} - -void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - const Vector& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph; - memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) ); -} - -void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - const Vector& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter; - memcpy( glyphsPerCharacter, modelGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) ); -} - -void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, - Length numberOfGlyphs ) -{ - Vector& modelPositions = mImpl->mGlyphPositions; - if( 0u == numberOfGlyphs ) - { - modelPositions.Clear(); - } - else - { - modelPositions.Resize( numberOfGlyphs ); - memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); - } -} - -Length VisualModel::GetNumberOfGlyphPositions() const -{ - return mImpl->mGlyphPositions.Count(); -} - -void VisualModel::GetGlyphPositions( Vector2* glyphPositions, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - const Vector& modelPositions = mImpl->mGlyphPositions; - memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) ); -} - -const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const -{ - return *( mImpl->mGlyphPositions.Begin() + glyphIndex ); -} - -void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const Vector2* const positions, - Length numberOfGlyphsToInsert ) -{ -} - -void VisualModel::SetLines( const LineRun* const lines, - Length numberOfLines ) -{ - Vector& modelLines = mImpl->mLines; - GetLineCache& lineCache = mImpl->mGetLineCache; - - if( 0u == numberOfLines ) - { - modelLines.Clear(); - } - else - { - modelLines.Resize( numberOfLines ); - memcpy( modelLines.Begin(), lines, numberOfLines * sizeof( LineRun ) ); - } - - // Clear the get line cache. - lineCache.glyphIndex = 0u; - lineCache.numberOfGlyphs = 0u; - lineCache.firstLine = 0u; - lineCache.numberOfLines = 0u; -} - -Length VisualModel::GetNumberOfLines() const -{ - return mImpl->mLines.Count(); -} - -void VisualModel::GetLines( LineRun* lines, - LineIndex lineIndex, - Length numberOfLines ) const -{ - const Vector& modelLines = mImpl->mLines; - memcpy( lines, modelLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) ); -} - -Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - // If is likely the user query consecutively for the number of lines with the same - // glyph index and number of glyphs, use the cache could be considered. - GetLineCache& lineCache = mImpl->mGetLineCache; - - // Cache the glyph index and number of glyphs to be used in the GetLinesOfGlyphRange(). - lineCache.glyphIndex = glyphIndex; - lineCache.numberOfGlyphs = numberOfGlyphs; - - // Check first if the query is for the total number of glyphs. - const Length totalNumberOfGlyphs = mImpl->mGlyphs.Count(); - - if( ( 0u == glyphIndex ) && - ( totalNumberOfGlyphs == numberOfGlyphs ) ) - { - lineCache.firstLine = 0u; - lineCache.numberOfLines = mImpl->mLines.Count(); - - return lineCache.numberOfLines; - } - - // Initialize the number of lines and the first line. - lineCache.numberOfLines = 0u; - lineCache.firstLine = 0u; - bool firstLineFound = false; - - const Vector& modelLines = mImpl->mLines; - const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs; - - // Traverse the lines and count those lines within the range of glyphs. - for( Vector::ConstIterator it = modelLines.Begin(), - endIt = modelLines.End(); - it != endIt; - ++it ) - { - const LineRun& line = *it; - - if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) && - ( lastGlyphIndex > line.glyphIndex ) ) - { - firstLineFound = true; - ++lineCache.numberOfLines; - } - else if( lastGlyphIndex <= line.glyphIndex ) - { - // nothing else to do. - break; - } - - if( !firstLineFound ) - { - ++lineCache.firstLine; - } - } - - return lineCache.numberOfLines; -} - -void VisualModel::GetLinesOfGlyphRange( LineRun* lines, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - const Vector& modelLines = mImpl->mLines; - GetLineCache& lineCache = mImpl->mGetLineCache; - - if( ( glyphIndex != lineCache.glyphIndex ) || - ( numberOfGlyphs != lineCache.numberOfGlyphs ) ) - { - GetNumberOfLines( glyphIndex, - numberOfGlyphs ); - } - - memcpy( lines, modelLines.Begin() + lineCache.firstLine, lineCache.numberOfLines * sizeof( LineRun ) ); -} - -void VisualModel::ReplaceLines( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const LineRun* const lines, - Length numberOfGlyphsToInsert ) -{ -} - -void VisualModel::SetNaturalSize( const Vector2& size ) -{ - mImpl->mNaturalSize = size; -} - -const Vector2& VisualModel::GetNaturalSize() const -{ - return mImpl->mNaturalSize; -} - -void VisualModel::SetActualSize( const Vector2& size ) -{ - mImpl->mActualSize = size; -} - -const Vector2& VisualModel::GetActualSize() const -{ - return mImpl->mActualSize; -} - -VisualModel::~VisualModel() -{ - delete mImpl; -} - -VisualModel::VisualModel() -: mImpl( NULL ) -{ - mImpl = new VisualModel::Impl(); -} - -} // namespace Text - -} // namespace Toolkit - -} // namespace Dali -- 2.7.4