From 0a88df264063357348ba3e2caee1258e90e55cfb Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Thu, 26 Feb 2015 10:40:01 +0000 Subject: [PATCH] Lines added to the model. Change-Id: Ie80d79ad0ab7b050d4871a9f95d633f0fbdbc970 Signed-off-by: Victor Cebollada --- .../internal/text/layouts/layout-engine.cpp | 52 ++++++---- dali-toolkit/internal/text/layouts/layout-engine.h | 4 +- dali-toolkit/internal/text/line-run.h | 12 ++- dali-toolkit/internal/text/text-controller.cpp | 42 ++++++-- dali-toolkit/internal/text/text-controller.h | 7 +- dali-toolkit/internal/text/visual-model.cpp | 111 +++++++++++++++++++-- dali-toolkit/internal/text/visual-model.h | 4 +- 7 files changed, 182 insertions(+), 50 deletions(-) diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index b5c3b16..9544a66 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -86,14 +86,6 @@ struct LayoutEngine::Impl // because there are glyphs formed by more than one character but their break info is // given only for the last character. const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex ); - const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex ); - const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u ); - - // Get the line break info for the current character. - const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex ); - - // Get the word break info for the current character. - const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex ); // Increase the number of characters. lineLayout.numberOfCharacters += charactersPerGlyph; @@ -104,13 +96,6 @@ struct LayoutEngine::Impl // Increase the accumulated length. lineLayout.length += ( glyphIndex == lastGlyphIndex ) ? glyphInfo.width : glyphInfo.advance; - if( TextAbstraction::LINE_MUST_BREAK == lineBreakInfo ) - { - } - if( TextAbstraction::WORD_BREAK == wordBreakInfo ) - { - } - if( lastFontId != glyphInfo.fontId ) { Text::FontMetrics fontMetrics; @@ -277,6 +262,7 @@ struct LayoutEngine::Impl bool LayoutText( const LayoutParameters& layoutParameters, Vector& glyphPositions, + Vector& lines, Size& actualSize ) { // TODO Switch between different layouts @@ -288,6 +274,7 @@ struct LayoutEngine::Impl { update = SingleLineLayout( layoutParameters, glyphPositions, + lines, actualSize ); break; } @@ -295,6 +282,7 @@ struct LayoutEngine::Impl { update = MultiLineLayout( layoutParameters, glyphPositions, + lines, actualSize ); break; } @@ -308,6 +296,7 @@ struct LayoutEngine::Impl // TODO - Rewrite this to handle bidi bool SingleLineLayout( const LayoutParameters& layoutParameters, Vector& glyphPositions, + Vector& lines, Size& actualSize ) { LineLayout layout; @@ -315,11 +304,18 @@ struct LayoutEngine::Impl GetLineLayoutForBox( layoutParameters, layout ); - if( 0u == layout.numberOfGlyphs ) - { - // The width is too small and no characters are laid-out. - return false; - } + // Create a line run and add it to the lines. + const GlyphIndex lastGlyphIndex = layoutParameters.totalNumberOfGlyphs - 1u; + + LineRun lineRun; + lineRun.glyphIndex = 0u; + lineRun.numberOfGlyphs = layoutParameters.totalNumberOfGlyphs; + lineRun.characterRun.characterIndex = 0u; + lineRun.characterRun.numberOfCharacters = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ); + lineRun.lineSize.width = layout.length; + lineRun.lineSize.height = layout.height; + + lines.PushBack( lineRun ); // Update the actual size. actualSize.width = layout.length; @@ -346,6 +342,7 @@ struct LayoutEngine::Impl // TODO - Rewrite this to handle bidi bool MultiLineLayout( const LayoutParameters& layoutParameters, Vector& glyphPositions, + Vector& lines, Size& actualSize ) { float penY = 0.f; @@ -365,6 +362,19 @@ struct LayoutEngine::Impl return false; } + // Create a line run and add it to the lines. + const GlyphIndex lastGlyphIndex = index + layout.numberOfGlyphs - 1u; + + LineRun lineRun; + lineRun.glyphIndex = index; + lineRun.numberOfGlyphs = layout.numberOfGlyphs; + lineRun.characterRun.characterIndex = *( layoutParameters.glyphsToCharactersBuffer + index ); + lineRun.characterRun.numberOfCharacters = ( *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex ) ) - lineRun.characterRun.characterIndex; + lineRun.lineSize.width = layout.length; + lineRun.lineSize.height = layout.height; + + lines.PushBack( lineRun ); + // Update the actual size. if( layout.length > actualSize.width ) { @@ -424,10 +434,12 @@ unsigned int LayoutEngine::GetLayout() const bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters, Vector& glyphPositions, + Vector& lines, Size& actualSize ) { return mImpl->LayoutText( layoutParameters, glyphPositions, + lines, actualSize ); } diff --git a/dali-toolkit/internal/text/layouts/layout-engine.h b/dali-toolkit/internal/text/layouts/layout-engine.h index febf485..59977c2 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.h +++ b/dali-toolkit/internal/text/layouts/layout-engine.h @@ -19,7 +19,7 @@ */ // INTERNAL INCLUDE -#include +#include // EXTERNAL INCLUDE #include @@ -80,12 +80,14 @@ public: * * @param[in] layoutParameters The parameters needed to layout the text. * @param[out] glyphPositions The positions of all the glyphs. + * @param[out] lines The laid-out lines. * @param[out] actualSize The size of the text after it has been laid-out. * * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character. */ bool LayoutText( const LayoutParameters& layoutParameters, Vector& glyphPositions, + Vector& lines, Size& actualSize ); private: diff --git a/dali-toolkit/internal/text/line-run.h b/dali-toolkit/internal/text/line-run.h index ad25d59..aedd3f7 100644 --- a/dali-toolkit/internal/text/line-run.h +++ b/dali-toolkit/internal/text/line-run.h @@ -18,8 +18,11 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES -#include +#include namespace Dali { @@ -35,9 +38,10 @@ namespace Text */ struct LineRun { - GlyphIndex glyphIndex; ///< The initial glyph index. - Length numberOfGlyphs; ///< The number of characters of the run. - // VCC More info to be added. i.e the size, ... + GlyphIndex glyphIndex; ///< The initial glyph index. + Length numberOfGlyphs; ///< The number of glyphs of the run. + CharacterRun characterRun; ///< The initial character and the number of characters. + Size lineSize; ///< The size of the line. }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 3433301..b0fb0d1 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -555,6 +555,7 @@ bool Controller::Relayout( const Vector2& size ) LAYOUT | UPDATE_ACTUAL_SIZE | UPDATE_POSITIONS | + UPDATE_LINES | REORDER ); mImpl->mControlSize = size; @@ -710,9 +711,10 @@ bool Controller::DoRelayout( const Vector2& size, if( LAYOUT & operations ) { + const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); + if( 0u == numberOfGlyphs ) { - const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs(); lineBreakInfo.Resize( numberOfCharacters ); @@ -755,22 +757,40 @@ bool Controller::DoRelayout( const Vector2& size, Vector glyphPositions; glyphPositions.Resize( numberOfGlyphs ); - // Update the visual model + // 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 ) ); + + // Update the visual model. viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, glyphPositions, + lines, layoutSize ); - // Sets the positions into the model. - if( UPDATE_POSITIONS & operations ) + if( viewUpdated ) { - mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(), - numberOfGlyphs ); - } + // Sets the positions into the model. + if( UPDATE_POSITIONS & operations ) + { + mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(), + numberOfGlyphs ); + } - // Sets the actual size. - if( UPDATE_ACTUAL_SIZE & operations ) - { - mImpl->mVisualModel->SetActualSize( layoutSize ); + // 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 ) + { + mImpl->mVisualModel->SetActualSize( layoutSize ); + } } } else diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 5623a11..b061330 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -75,9 +75,10 @@ private: LAYOUT = 0x0080, UPDATE_ACTUAL_SIZE = 0x0100, UPDATE_POSITIONS = 0x0200, - REORDER = 0x0400, - ALIGNMENT = 0x0800, - RENDER = 0x1000, + UPDATE_LINES = 0x0400, + REORDER = 0x0800, + ALIGNMENT = 0x1000, + RENDER = 0x2000, ALL_OPERATIONS = 0xFFFF }; diff --git a/dali-toolkit/internal/text/visual-model.cpp b/dali-toolkit/internal/text/visual-model.cpp index ab183e4..73400f0 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 of the text with no line wrapping. + Size mActualSize; ///< Size of the laid-out text considering the layout properties set. - Size mNaturalSize; - Size mActualSize; + GetLineCache mGetLineCache; ///< Caches the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation. }; VisualModelPtr VisualModel::New() @@ -101,7 +116,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 +144,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 +152,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 +160,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 ) ); } @@ -161,7 +176,7 @@ 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 +188,107 @@ const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const void VisualModel::SetLines( const LineRun* const lines, Length numberOfLines ) { + Vector& modelLines = mImpl->mLines; + GetLineCache& lineCache = mImpl->mGetLineCache; + + 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 ) diff --git a/dali-toolkit/internal/text/visual-model.h b/dali-toolkit/internal/text/visual-model.h index ad2a137..ec74764 100644 --- a/dali-toolkit/internal/text/visual-model.h +++ b/dali-toolkit/internal/text/visual-model.h @@ -241,8 +241,8 @@ public: * * @return The number of lines. */ - TextAbstraction::Length GetNumberOfLines( GlyphIndex glyphIndex, - Length numberOfGlyphs ) const; + Length GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; /** * Retrieves the lines where the given range of glyphs is laid out. * -- 2.7.4