$(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 \
$(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 \
*/
// CLASS HEADER
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
// EXTERNAL INCLUDES
#include <memory.h>
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
-#include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
-#include <dali-toolkit/internal/text/font-run.h>
-#include <dali-toolkit/internal/text/script-run.h>
-
namespace Dali
{
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<Character> mText;
- Vector<ScriptRun> mScriptRuns;
- Vector<FontRun> mFontRuns;
- Vector<LineBreakInfo> mLineBreakInfo;
- Vector<WordBreakInfo> mWordBreakInfo;
- Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
-
- Vector<BidirectionalLineInfoRun> mBidirectionalLineInfo;
- Vector<CharacterIndex> mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table.
- Vector<CharacterIndex> 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()
{
void LogicalModel::SetText( const Character* const text,
Length numberOfCharacters )
{
- Vector<Character>& 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<Character>& 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,
void LogicalModel::SetScripts( const ScriptRun* const scripts,
Length numberOfRuns )
{
- Vector<ScriptRun>& 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<ScriptRun>& modelScripts = mImpl->mScriptRuns;
const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
// Traverse the scripts and count those scripts within the range of characters.
- for( Vector<ScriptRun>::ConstIterator it = modelScripts.Begin(),
- endIt = modelScripts.End();
+ for( Vector<ScriptRun>::ConstIterator it = mScriptRuns.Begin(),
+ endIt = mScriptRuns.End();
it != endIt;
++it )
{
( lastCharacterIndex > script.characterRun.characterIndex ) )
{
firstScriptFound = true;
- ++scriptCache.numberOfRuns;
+ ++numberOfScriptRuns;
}
else if( lastCharacterIndex <= script.characterRun.characterIndex )
{
if( !firstScriptFound )
{
- ++scriptCache.firstRun;
+ ++firstScriptRun;
}
}
-
- return scriptCache.numberOfRuns;
}
void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
CharacterIndex characterIndex,
Length numberOfCharacters ) const
{
- const Vector<ScriptRun>& 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 ) )
void LogicalModel::SetFonts( const FontRun* const fonts,
Length numberOfRuns )
{
- Vector<FontRun>& 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<FontRun>& modelFonts = mImpl->mFontRuns;
const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
// Traverse the fonts and count those fonts within the range of characters.
- for( Vector<FontRun>::ConstIterator it = modelFonts.Begin(),
- endIt = modelFonts.End();
+ for( Vector<FontRun>::ConstIterator it = mFontRuns.Begin(),
+ endIt = mFontRuns.End();
it != endIt;
++it )
{
( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) )
{
firstFontFound = true;
- ++fontCache.numberOfRuns;
+ ++numberOfFontRuns;
}
else if( lastCharacterIndex <= font.characterRun.characterIndex )
{
if( !firstFontFound )
{
- ++fontCache.firstRun;
+ ++firstFontRun;
}
}
-
- return fontCache.numberOfRuns;
}
void LogicalModel::GetFontRuns( FontRun* fontRuns,
CharacterIndex characterIndex,
Length numberOfCharacters ) const
{
- const Vector<FontRun>& 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 ) )
void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
Length length )
{
- Vector<LineBreakInfo>& 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 ) );
}
}
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,
void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
Length length )
{
- Vector<WordBreakInfo>& 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 ) );
}
}
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,
void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
Length numberOfRuns )
{
- Vector<BidirectionalParagraphInfoRun>& 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<BidirectionalParagraphInfoRun>& modelBidirectionalParagraphInfo = mImpl->mBidirectionalParagraphInfo;
-
// Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters.
- for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = modelBidirectionalParagraphInfo.Begin(),
- endIt = modelBidirectionalParagraphInfo.End();
+ for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = mBidirectionalParagraphInfo.Begin(),
+ endIt = mBidirectionalParagraphInfo.End();
it != endIt;
++it )
{
( 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<BidirectionalParagraphInfoRun>& 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,
void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
Length numberOfRuns )
{
- Vector<CharacterIndex>& modelVisualToLogicalMap = mImpl->mVisualToLogicalMap;
- Vector<CharacterIndex>& 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 )
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
-#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.
#include <dali/public-api/object/ref-object.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
+#include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
+#include <dali-toolkit/internal/text/font-run.h>
+#include <dali-toolkit/internal/text/script-run.h>
namespace Dali
{
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.
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.
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.
*
*
* @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.
// Undefined
LogicalModel& operator=( const LogicalModel& handle );
-private:
+public:
+
+ Vector<Character> mText;
+ Vector<ScriptRun> mScriptRuns;
+ Vector<FontRun> mFontRuns;
+ Vector<LineBreakInfo> mLineBreakInfo;
+ Vector<WordBreakInfo> mWordBreakInfo;
+ Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
- struct Impl;
- Impl* mImpl;
+ Vector<BidirectionalLineInfoRun> mBidirectionalLineInfo;
+ Vector<CharacterIndex> mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table.
+ Vector<CharacterIndex> mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table.
};
} // namespace Text
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_H__
+#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
#include <dali/public-api/text-abstraction/script.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
#include <dali-toolkit/internal/text/font-run.h>
#include <dali-toolkit/internal/text/script-run.h>
#include <dali-toolkit/internal/text/text-io.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/font-run.h>
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
#include <dali-toolkit/internal/text/script-run.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
namespace Dali
{
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
-#include <dali-toolkit/internal/text/logical-model.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
#include <dali-toolkit/internal/text/multi-language-support.h>
#include <dali-toolkit/internal/text/script-run.h>
#include <dali-toolkit/internal/text/segmentation.h>
#include <dali-toolkit/internal/text/shaper.h>
#include <dali-toolkit/internal/text/text-view.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
using std::vector;
return;
}
- Vector<GlyphInfo> glyphs;
- glyphs.Resize( numberOfGlyphs );
- mVisualModel->GetGlyphs( glyphs.Begin(), 0, numberOfGlyphs );
+ Vector<GlyphInfo>& glyphs = mVisualModel->mGlyphs;
const GlyphInfo* const glyphsBuffer = glyphs.Begin();
- Vector<Vector2> positions;
- positions.Resize( numberOfGlyphs );
- mVisualModel->GetGlyphPositions( positions.Begin(), 0, numberOfGlyphs );
+ Vector<Vector2>& positions = mVisualModel->mGlyphPositions;
const Vector2* const positionsBuffer = positions.Begin();
unsigned int closestGlyph = 0;
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<OperationsMask>( 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<OperationsMask>( LAYOUT |
+ REORDER );
+
+ DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
+ static_cast<OperationsMask>( onlyOnceOperations |
+ sizeOperations ),
+ naturalSize.GetVectorXY() );
+
+ // Do not do again the only once operations.
+ mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
+
+ // Do the size related operations again.
+ mImpl->mOperationsPending = static_cast<OperationsMask>( 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<OperationsMask>( 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<OperationsMask>( LAYOUT |
+ REORDER );
+
+ DoRelayout( Size( width, MAX_FLOAT ),
+ static_cast<OperationsMask>( onlyOnceOperations |
+ sizeOperations ),
+ layoutSize );
+
+ // Do not do again the only once operations.
+ mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
+
+ // Do the size related operations again.
+ mImpl->mOperationsPending = static_cast<OperationsMask>( 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 ) )
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
LAYOUT |
UPDATE_ACTUAL_SIZE |
- UPDATE_POSITIONS |
- UPDATE_LINES |
REORDER );
mImpl->mControlSize = size;
// Calculate the operations to be done.
const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
- Vector<Character> utf32Characters;
- Length characterCount = 0u;
+ Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
if( CONVERT_TO_UTF32 & operations )
{
std::string& text = mImpl->mNewText;
// 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> lineBreakInfo;
+ Vector<LineBreakInfo>& 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> wordBreakInfo;
+ Vector<WordBreakInfo>& 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<ScriptRun> scripts;
- Vector<FontRun> validFonts;
+ Vector<ScriptRun>& scripts = mImpl->mLogicalModel->mScriptRuns;
+ Vector<FontRun>& validFonts = mImpl->mLogicalModel->mFontRuns;
if( getScripts || validateFonts )
{
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 ) )
{
}
}
- Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
bidirectionalInfo.Reserve( numberOfParagraphs );
// Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
scripts,
lineBreakInfo,
bidirectionalInfo );
-
- mImpl->mLogicalModel->SetBidirectionalInfo( bidirectionalInfo.Begin(),
- bidirectionalInfo.Count() );
}
- Vector<GlyphInfo> glyphs;
- Vector<CharacterIndex> glyphsToCharactersMap;
- Vector<Length> charactersPerGlyph;
+ Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
+ Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
+ Vector<Length>& 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,
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 );
}
}
const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters();
Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
- Vector<LineBreakInfo> lineBreakInfo;
- lineBreakInfo.Resize( numberOfCharacters );
- mImpl->mLogicalModel->GetLineBreakInfo( lineBreakInfo.Begin(),
- 0u,
- numberOfCharacters );
-
- Vector<WordBreakInfo> wordBreakInfo;
- wordBreakInfo.Resize( numberOfCharacters );
- mImpl->mLogicalModel->GetWordBreakInfo( wordBreakInfo.Begin(),
- 0u,
- numberOfCharacters );
-
- Vector<GlyphInfo> glyphs;
- glyphs.Resize( numberOfGlyphs );
- mImpl->mVisualModel->GetGlyphs( glyphs.Begin(),
- 0u,
- numberOfGlyphs );
-
- Vector<CharacterIndex> glyphsToCharactersMap;
- glyphsToCharactersMap.Resize( numberOfGlyphs );
- mImpl->mVisualModel->GetGlyphToCharacterMap( glyphsToCharactersMap.Begin(),
- 0u,
- numberOfGlyphs );
-
- Vector<Length> charactersPerGlyph;
- charactersPerGlyph.Resize( numberOfGlyphs );
- mImpl->mVisualModel->GetCharactersPerGlyphMap( charactersPerGlyph.Begin(),
- 0u,
- numberOfGlyphs );
+ Vector<LineBreakInfo>& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo;
+ Vector<WordBreakInfo>& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo;
+ Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
+ Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
+ Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
// Set the layout parameters.
LayoutParameters layoutParameters( size,
glyphsToCharactersMap.Begin(),
charactersPerGlyph.Begin() );
- // Reserve space to set the positions of the glyphs.
- Vector<Vector2> 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<LineRun> lines;
- lines.Reserve( mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters ) );
+ Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
+
+ // Resize the vector of positions to have the same size than the vector of glyphs.
+ Vector<Vector2>& 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,
// Reorder the lines
if( REORDER & operations )
{
- const Length numberOfBidiParagraphs = mImpl->mLogicalModel->GetNumberOfBidirectionalInfoRuns( 0u, numberOfCharacters );
-
- Vector<BidirectionalParagraphInfoRun> bidirectionalInfo;
- bidirectionalInfo.Resize( numberOfBidiParagraphs );
- mImpl->mLogicalModel->GetBidirectionalInfo( bidirectionalInfo.Begin(),
- 0u,
- numberOfCharacters );
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
// Check first if there are paragraphs with bidirectional info.
if( 0u != bidirectionalInfo.Count() )
layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns;
// Get the character to glyph conversion table and set into the layout.
- Vector<GlyphIndex> 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<Length> 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,
}
}
- // 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 )
{
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<OperationsMask>( 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<OperationsMask>( LAYOUT |
- REORDER );
-
- DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
- static_cast<OperationsMask>( onlyOnceOperations |
- sizeOperations ),
- naturalSize.GetVectorXY() );
-
- // Do not do again the only once operations.
- mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
-
- // Do the size related operations again.
- mImpl->mOperationsPending = static_cast<OperationsMask>( 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<OperationsMask>( 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<OperationsMask>( LAYOUT |
- REORDER );
-
- DoRelayout( Size( width, MAX_FLOAT ),
- static_cast<OperationsMask>( onlyOnceOperations |
- sizeOperations ),
- layoutSize );
-
- // Do not do again the only once operations.
- mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
-
- // Do the size related operations again.
- mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
- }
- else
- {
- layoutSize = mImpl->mVisualModel->GetActualSize();
- }
-
- return layoutSize.height;
-}
-
View& Controller::GetView()
{
return mImpl->mView;
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
};
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.
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.
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
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/text-view-interface.h>
-#include <dali-toolkit/internal/text/visual-model.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
namespace Dali
{
--- /dev/null
+/*
+ * 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 <dali-toolkit/internal/text/visual-model-impl.h>
+
+// EXTERNAL INCLUDES
+#include <memory.h>
+#include <dali/public-api/math/vector2.h>
+
+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<Length> ( static_cast<float>( 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<Length>::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<Length> ( static_cast<float>( 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<Length>::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<LineRun>::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
-#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.
*/
// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/object/ref-object.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/line-run.h>
namespace Dali
{
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.
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.
*
// Undefined
VisualModel& operator=( const VisualModel& handle );
+public:
+
+ Vector<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
+ Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
+ Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
+ Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
+ Vector<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
+ Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
+ Vector<LineRun> 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__
+++ /dev/null
-/*
- * 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 <dali-toolkit/internal/text/visual-model.h>
-
-// EXTERNAL INCLUDES
-#include <memory.h>
-#include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/math/vector2.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/line-run.h>
-
-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<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
- Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
- Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
- Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
- Vector<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
- Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
- Vector<LineRun> 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<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
- Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
- Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
- Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
- Vector<Length>& 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<Length> ( static_cast<float>( 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<Length>::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<GlyphInfo>& 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<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
- memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
-}
-
-void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
- GlyphIndex glyphIndex,
- Length numberOfGlyphs ) const
-{
- const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
- memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
-}
-
-void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
- GlyphIndex glyphIndex,
- Length numberOfGlyphs ) const
-{
- const Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
- memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
-}
-
-void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- const Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
- memcpy( glyphsPerCharacter, modelGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
-}
-
-void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
- Length numberOfGlyphs )
-{
- Vector<Vector2>& 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<Vector2>& 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<LineRun>& 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<LineRun>& 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<LineRun>& modelLines = mImpl->mLines;
- const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
-
- // Traverse the lines and count those lines within the range of glyphs.
- for( Vector<LineRun>::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<LineRun>& 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