X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fvisual-model.cpp;h=6351ec34b873379fb8e3c70c9768ea169d1fc8ef;hb=479e2b5a95c62cf2b6d39c4499e11aab49ded6cb;hp=ab183e4b3019407705717d199b1d69934d7815dc;hpb=eea53605c5acb244aebb72d75bdd9b3a68a9678a;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/visual-model.cpp b/dali-toolkit/internal/text/visual-model.cpp index ab183e4..6351ec3 100644 --- a/dali-toolkit/internal/text/visual-model.cpp +++ b/dali-toolkit/internal/text/visual-model.cpp @@ -35,6 +35,18 @@ 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. @@ -42,9 +54,12 @@ struct VisualModel::Impl 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 mGlyphPositions; ///< For each glyph, the position. + Vector mLines; ///< The laid out lines. - Size mNaturalSize; - Size mActualSize; + 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() @@ -58,36 +73,56 @@ void VisualModel::SetGlyphs( const GlyphInfo* glyphs, Length numberOfGlyphs ) { Vector& modelGlyphs = mImpl->mGlyphs; - modelGlyphs.Resize( numberOfGlyphs ); - memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); - Vector& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters; - modelGlyphsToCharacters.Resize( numberOfGlyphs ); - memcpy( modelGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) ); - Vector& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph; - modelCharactersPerGlyph.Resize( numberOfGlyphs ); - memcpy( modelCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) ); - - // Build the characters to glyph conversion table. Vector& modelCharactersToGlyph = mImpl->mCharactersToGlyph; - // 1) Reserve some space for the characters to avoid reallocations. - modelCharactersToGlyph.Reserve( static_cast ( static_cast( numberOfGlyphs ) * 1.3f ) ); - - // 2) Traverse the glyphs and set the glyph indices. - GlyphIndex glyphIndex = 0u; - Length totalNumberOfCharacters = 0u; - for( Vector::ConstIterator it = modelCharactersPerGlyph.Begin(), - endIt = modelCharactersPerGlyph.End(); - it != endIt; - ++it, ++glyphIndex ) + if( 0u == numberOfGlyphs ) { - const Length numberOfCharacters = *it; + modelGlyphs.Clear(); + modelGlyphsToCharacters.Clear(); + modelCharactersToGlyph.Clear(); + modelCharactersPerGlyph.Clear(); + } + else + { + if( NULL != glyphs ) + { + modelGlyphs.Resize( numberOfGlyphs ); + memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); + } - for( Length index = 0u; index < numberOfCharacters; ++index, ++totalNumberOfCharacters ) + if( NULL != characterIndices ) { - modelCharactersToGlyph.PushBack( glyphIndex ); + 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. + modelCharactersToGlyph.Reserve( static_cast ( static_cast( numberOfGlyphs ) * 1.3f ) ); + + // 2) Traverse the glyphs and set the glyph indices. + GlyphIndex glyphIndex = 0u; + Length totalNumberOfCharacters = 0u; + for( Vector::ConstIterator it = modelCharactersPerGlyph.Begin(), + endIt = modelCharactersPerGlyph.End(); + it != endIt; + ++it, ++glyphIndex ) + { + const Length numberOfCharacters = *it; + + for( Length index = 0u; index < numberOfCharacters; ++index, ++totalNumberOfCharacters ) + { + modelCharactersToGlyph.PushBack( glyphIndex ); + } + } } } } @@ -101,7 +136,7 @@ void VisualModel::GetGlyphs( GlyphInfo* glyphs, GlyphIndex glyphIndex, Length numberOfGlyphs ) const { - Vector& modelGlyphs = mImpl->mGlyphs; + const Vector& modelGlyphs = mImpl->mGlyphs; memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) ); } @@ -129,7 +164,7 @@ void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, CharacterIndex characterIndex, Length numberOfCharacters ) const { - Vector& modelCharactersToGlyph = mImpl->mCharactersToGlyph; + const Vector& modelCharactersToGlyph = mImpl->mCharactersToGlyph; memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) ); } @@ -137,7 +172,7 @@ void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph, GlyphIndex glyphIndex, Length numberOfGlyphs ) const { - Vector& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph; + const Vector& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph; memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) ); } @@ -145,7 +180,7 @@ void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, GlyphIndex glyphIndex, Length numberOfGlyphs ) const { - Vector& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters; + const Vector& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters; memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) ); } @@ -153,15 +188,22 @@ void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, Length numberOfGlyphs ) { Vector& modelPositions = mImpl->mGlyphPositions; - modelPositions.Resize( numberOfGlyphs ); - memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); + if( 0u == numberOfGlyphs ) + { + modelPositions.Clear(); + } + else + { + modelPositions.Resize( numberOfGlyphs ); + memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); + } } void VisualModel::GetGlyphPositions( Vector2* glyphPositions, GlyphIndex glyphIndex, Length numberOfGlyphs ) const { - Vector modelPositions = mImpl->mGlyphPositions; + const Vector& modelPositions = mImpl->mGlyphPositions; memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) ); } @@ -173,29 +215,114 @@ const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const 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 0u; + 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 { - return 0u; + // 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 cound 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::SetNaturalSize( const Vector2& size )