From a314b4d8d02b983f50b5faafb225f0f3e4593a45 Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Fri, 6 Mar 2015 09:26:01 +0000 Subject: [PATCH] TextController fix. - Fixes the sequence of operations done for the GetNaturalSize(), GetHeightForWidth() and Relayout() methods avoiding redo the same tasks more than once. Change-Id: If42b480667469b848dc2618bc11192e787a755c8 Signed-off-by: Victor Cebollada --- dali-toolkit/internal/text/text-controller.cpp | 241 +++++++++++++++---------- dali-toolkit/internal/text/text-controller.h | 5 +- 2 files changed, 152 insertions(+), 94 deletions(-) diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 60016d2..3433301 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -38,6 +38,11 @@ using std::vector; +namespace +{ +const float MAX_FLOAT = std::numeric_limits::max(); +} // namespace + namespace Dali { @@ -284,19 +289,23 @@ struct Controller::TextInput Vector glyphs; glyphs.Resize( numberOfGlyphs ); - mVisualModel->GetGlyphs( &glyphs[0], 0, numberOfGlyphs ); + mVisualModel->GetGlyphs( glyphs.Begin(), 0, numberOfGlyphs ); + const GlyphInfo* const glyphsBuffer = glyphs.Begin(); - std::vector positions; - positions.resize( numberOfGlyphs ); - mVisualModel->GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); + Vector positions; + positions.Resize( numberOfGlyphs ); + mVisualModel->GetGlyphPositions( positions.Begin(), 0, numberOfGlyphs ); + const Vector2* const positionsBuffer = positions.Begin(); unsigned int closestGlyph = 0; - float closestDistance = std::numeric_limits::max(); + float closestDistance = MAX_FLOAT; - for( unsigned int i=0; imNewText = text; - mImpl->mOperations = ALL_OPERATIONS; + + // All operations need to be done. (convert to utf32, get break info, ..., layout, ...) + mImpl->mOperationsPending = ALL_OPERATIONS; + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; if( mImpl->mTextInput ) { @@ -462,7 +472,8 @@ void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily ) mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily; mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID - mImpl->mOperations = ALL_OPERATIONS; + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; } const std::string& Controller::GetDefaultFontFamily() const @@ -484,7 +495,8 @@ void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle ) mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle; mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID - mImpl->mOperations = ALL_OPERATIONS; + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; } const std::string& Controller::GetDefaultFontStyle() const @@ -506,7 +518,8 @@ void Controller::SetDefaultPointSize( float pointSize ) mImpl->mFontDefaults->mDefaultPointSize = pointSize; mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID - mImpl->mOperations = ALL_OPERATIONS; + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; } float Controller::GetDefaultPointSize() const @@ -535,18 +548,26 @@ bool Controller::Relayout( const Vector2& size ) return false; } - bool updated = false; - if( size != mImpl->mControlSize ) { - updated = DoRelayout( size, mImpl->mOperations ); - - // Do not re-do any operation until something changes. - mImpl->mOperations = NO_OPERATION; + // Operations that need to be done if the size changes. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | + LAYOUT | + UPDATE_ACTUAL_SIZE | + UPDATE_POSITIONS | + REORDER ); mImpl->mControlSize = size; } + Size layoutSize; + bool updated = DoRelayout( mImpl->mControlSize, + mImpl->mOperationsPending, + layoutSize ); + + // Do not re-do any operation until something changes. + mImpl->mOperationsPending = NO_OPERATION; + if( mImpl->mTextInput ) { // Move the cursor, grab handle etc. @@ -556,10 +577,15 @@ bool Controller::Relayout( const Vector2& size ) return updated; } -bool Controller::DoRelayout( const Vector2& size, OperationsMask operations ) +bool Controller::DoRelayout( const Vector2& size, + OperationsMask operationsRequired, + Size& layoutSize ) { bool viewUpdated( false ); + // Calculate the operations to be done. + const OperationsMask operations = static_cast( mImpl->mOperationsPending & operationsRequired ); + Vector utf32Characters; Length characterCount = 0u; if( CONVERT_TO_UTF32 & operations ) @@ -581,7 +607,7 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations ) mImpl->mLogicalModel->SetText( utf32Characters.Begin(), characterCount ); // Discard temporary text - //text.clear(); temporary keep the text. will be fixed in the next patch. + text.clear(); } Vector lineBreakInfo; @@ -729,19 +755,27 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations ) Vector glyphPositions; glyphPositions.Resize( numberOfGlyphs ); - Size layoutSize; - // Update the visual model viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, glyphPositions, layoutSize ); // Sets the positions into the model. - mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(), - numberOfGlyphs ); + if( UPDATE_POSITIONS & operations ) + { + mImpl->mVisualModel->SetGlyphPositions( glyphPositions.Begin(), + numberOfGlyphs ); + } // Sets the actual size. - mImpl->mVisualModel->SetActualSize( layoutSize ); + if( UPDATE_ACTUAL_SIZE & operations ) + { + mImpl->mVisualModel->SetActualSize( layoutSize ); + } + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); } return viewUpdated; @@ -749,62 +783,83 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations ) Vector3 Controller::GetNaturalSize() { - // TODO - Finish implementing - return Vector3::ZERO; + Vector3 naturalSize; - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - GET_WORD_BREAKS | - SHAPE_TEXT | - GET_GLYPH_METRICS ); + if( mImpl->mRecalculateNaturalSize ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + SHAPE_TEXT | + GET_GLYPH_METRICS ); - // Operations that need to be done if the size or the text changes. - const OperationsMask sizeOperations = static_cast( LAYOUT | - REORDER ); + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + REORDER ); - const float maxFloat = std::numeric_limits::max(); - DoRelayout( Vector2( maxFloat, maxFloat ), - static_cast( onlyOnceOperations | - sizeOperations ) ); + DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + naturalSize.GetVectorXY() ); - // Do not do again the only once operations. - mImpl->mOperations = static_cast( mImpl->mOperations & ~onlyOnceOperations ); + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); - // Do the size related operations again. - mImpl->mOperations = static_cast( mImpl->mOperations | sizeOperations ); + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); - return Vector3( mImpl->mVisualModel->GetNaturalSize() ); + // 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 ) { - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - GET_WORD_BREAKS | - SHAPE_TEXT | - GET_GLYPH_METRICS ); + Size layoutSize; + if( width != mImpl->mControlSize.width ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + SHAPE_TEXT | + GET_GLYPH_METRICS ); - // Operations that need to be done if the size or the text changes. - const OperationsMask sizeOperations = static_cast( LAYOUT | - REORDER ); + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + REORDER ); - DoRelayout( Size( width, 0.f ), - static_cast( onlyOnceOperations | - sizeOperations ) ); + DoRelayout( Size( width, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + layoutSize ); - // Do not do again the only once operations. - mImpl->mOperations = static_cast( mImpl->mOperations & ~onlyOnceOperations ); + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); - // Do the size related operations again. - mImpl->mOperations = static_cast( mImpl->mOperations | sizeOperations ); + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); + } - return mImpl->mVisualModel->GetActualSize().height; + return layoutSize.height; } View& Controller::GetView() diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 11d212b..5623a11 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -186,8 +186,11 @@ public: * * @param[in] size A the size of a bounding box to layout text within. * @param[in] operations The layout operations which need to be done. + * @param[out] layoutSize The size of the laid-out text. */ - bool DoRelayout( const Vector2& size, OperationsMask operations ); + bool DoRelayout( const Vector2& size, + OperationsMask operations, + Size& layoutSize ); /** * @copydoc Control::GetNaturalSize() -- 2.7.4