From 5064025f6246c31c82cd1531084b639ac9c3237d Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Tue, 9 Jun 2015 09:47:25 +0100 Subject: [PATCH 1/1] Add the alignment offset to the glyph lines. When the lines are horizontally aligned, we don't want to modify the original layout. Subsequent calls to Layout::Align() will always use the original layout and modify only the alignment offset of each line. The TextView is the responsible of adding the offset to get the final layout. Change-Id: Id8c1fea9a75e77b597b6744f226ef566408e6e8c Signed-off-by: Victor Cebollada --- .../internal/text/layouts/layout-engine.cpp | 103 ++++++--------------- dali-toolkit/internal/text/layouts/layout-engine.h | 10 +- dali-toolkit/internal/text/line-run.h | 19 ++-- dali-toolkit/internal/text/text-controller.cpp | 32 +++---- dali-toolkit/internal/text/text-view.cpp | 42 +++++++++ dali-toolkit/internal/text/visual-model-impl.cpp | 8 +- dali-toolkit/internal/text/visual-model-impl.h | 8 +- 7 files changed, 103 insertions(+), 119 deletions(-) diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index d1c38e2..b018ed1 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -508,6 +508,7 @@ struct LayoutEngine::Impl } DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" ); + return true; } @@ -556,76 +557,36 @@ struct LayoutEngine::Impl } } - void Align( const LayoutParameters& layoutParameters, - const Size& layoutSize, - const Vector& lines, - Vector& glyphPositions ) + void Align( const Size& layoutSize, + Vector& lines ) { - Vector2* glyphPositionsBuffer = glyphPositions.Begin(); - // Traverse all lines and align the glyphs. - // LayoutParameters contains bidirectional info for those lines with - // right to left text, this info includes the paragraph's direction. - LineIndex bidiLineIndex = 0u; - for( Vector::ConstIterator it = lines.Begin(), endIt = lines.End(); + for( Vector::Iterator it = lines.Begin(), endIt = lines.End(); it != endIt; ++it ) { - const LineRun& line = *it; - - // 1) Get the paragrap's direction. - bool paragraphDirection = false; - - // Check if there is any right to left line. - if( ( NULL != layoutParameters.lineBidirectionalInfoRunsBuffer ) && - ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) ) - { - const BidirectionalLineInfoRun* bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex; - - // Get the right to left line that match with current line. - while( ( line.characterRun.characterIndex > bidiLine->characterRun.characterIndex ) && - ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) ) - { - ++bidiLineIndex; - bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex; - } - - if( line.characterRun.characterIndex == bidiLine->characterRun.characterIndex ) - { - paragraphDirection = bidiLine->direction; - } - } - - // 2) Calculate the alignment offset accordingly with the align option, - // the box width, line length, and the paragraphs direction. - float alignOffset = CalculateHorizontalAlignment( layoutSize.width, - line.width, - line.extraLength, - paragraphDirection ); - - // 3) Traverse all glyphs and update the 'x' position. - for( GlyphIndex index = line.glyphIndex, - endIndex = line.glyphIndex + line.numberOfGlyphs; - index < endIndex; - ++index ) - { - Vector2& position = *( glyphPositionsBuffer + index ); - - position.x += alignOffset; - } + LineRun& line = *it; + const bool isLastLine = lines.End() == it + 1u; + + // Calculate the alignment offset accordingly with the align option, + // the box width, line length, and the paragraphs direction. + CalculateHorizontalAlignment( layoutSize.width, + line, + isLastLine ); } } - float CalculateHorizontalAlignment( float boxWidth, - float lineLength, - float extraLength, - bool paragraphDirection ) + void CalculateHorizontalAlignment( float boxWidth, + LineRun& line, + bool isLastLine ) { - float offset = 0.f; + line.alignmentOffset = 0.f; + const bool isRTL = RTL == line.direction; + float lineLength = line.width; HorizontalAlignment alignment = mHorizontalAlignment; - if( paragraphDirection && + if( isRTL && ( HORIZONTAL_ALIGN_CENTER != alignment ) ) { if( HORIZONTAL_ALIGN_BEGIN == alignment ) @@ -642,29 +603,25 @@ struct LayoutEngine::Impl { case HORIZONTAL_ALIGN_BEGIN: { - offset = 0.f; + line.alignmentOffset = 0.f; break; } case HORIZONTAL_ALIGN_CENTER: { - offset = 0.5f * ( boxWidth - lineLength ); - const int intOffset = static_cast( offset ); // try to avoid pixel alignment. - offset = static_cast( intOffset ); + line.alignmentOffset = floorf( 0.5f * ( boxWidth - lineLength ) ); // try to avoid pixel alignment. break; } case HORIZONTAL_ALIGN_END: { - offset = boxWidth - lineLength; + line.alignmentOffset = boxWidth - lineLength; break; } } - if( paragraphDirection ) + if( isRTL ) { - offset -= extraLength; + line.alignmentOffset -= line.extraLength; } - - return offset; } LayoutEngine::Layout mLayout; @@ -745,15 +702,11 @@ void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParam glyphPositions ); } -void LayoutEngine::Align( const LayoutParameters& layoutParameters, - const Size& layoutSize, - const Vector& lines, - Vector& glyphPositions ) +void LayoutEngine::Align( const Size& layoutSize, + Vector& lines ) { - mImpl->Align( layoutParameters, - layoutSize, - lines, - glyphPositions ); + mImpl->Align( layoutSize, + lines ); } } // namespace Text diff --git a/dali-toolkit/internal/text/layouts/layout-engine.h b/dali-toolkit/internal/text/layouts/layout-engine.h index 42ff1aa..e48de90 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.h +++ b/dali-toolkit/internal/text/layouts/layout-engine.h @@ -158,15 +158,11 @@ public: /** * @brief Aligns the laid out lines. * - * @param[in] layoutParameters The parameters needed to layout the text. * @param[in] layoutSize The size of the laid out the text. - * @param[in] lines The laid-out lines. - * @param[in,out] glyphPositions The positions of all the glyphs. + * @param[in,out] lines The laid-out lines. */ - void Align( const LayoutParameters& layoutParameters, - const Size& layoutSize, - const Vector& lines, - Vector& glyphPositions ); + void Align( const Size& layoutSize, + Vector& lines ); private: diff --git a/dali-toolkit/internal/text/line-run.h b/dali-toolkit/internal/text/line-run.h index 5668669..584d758 100644 --- a/dali-toolkit/internal/text/line-run.h +++ b/dali-toolkit/internal/text/line-run.h @@ -38,15 +38,16 @@ namespace Text */ struct LineRun { - 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. - float width; ///< The line's width. - float ascender; ///< The line's ascender. - float descender; ///< The line's descender. - float extraLength; ///< The length of the white spaces at the end of the line. - CharacterDirection direction : 1; ///< Direction of the first character of the paragraph. - bool ellipsis : 1; ///< Wheter ellipsis is added to the line. + 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. + float width; ///< The line's width. + float ascender; ///< The line's ascender. + float descender; ///< The line's descender. + float extraLength; ///< The length of the white spaces at the end of the line. + float alignmentOffset; ///< The horizontal alignment offset. + CharacterDirection direction : 1; ///< Direction of the first character of the paragraph. + bool ellipsis : 1; ///< Wheter ellipsis is added to the line. }; } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 36b566b..d584c73 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -893,17 +893,6 @@ bool Controller::DoRelayout( const Size& size, } } // REORDER - // TODO: I'm working on a patch that changes the LayoutEngine::Align() method. - // The layoutParameters is not needed and this call can be moved outside the if(). - // Then there is no need to do the layout again to change the alignment. - if( ALIGN & operations ) - { - mImpl->mLayoutEngine.Align( layoutParameters, - layoutSize, - lines, - glyphPositions ); - } - // Sets the actual size. if( UPDATE_ACTUAL_SIZE & operations ) { @@ -916,6 +905,17 @@ bool Controller::DoRelayout( const Size& size, layoutSize = mImpl->mVisualModel->GetActualSize(); } + if( ALIGN & operations ) + { + // The laid-out lines. + Vector& lines = mImpl->mVisualModel->mLines; + + mImpl->mLayoutEngine.Align( layoutSize, + lines ); + + viewUpdated = true; + } + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) ); return viewUpdated; } @@ -954,15 +954,7 @@ void Controller::SetHorizontalAlignment( LayoutEngine::HorizontalAlignment align mImpl->mLayoutEngine.SetHorizontalAlignment( alignment ); // Set the flag to redo the alignment operation. - // TODO : Is not needed re-layout and reorder again but with the current implementation it is. - // Im working on a different patch to fix an issue with the alignment. When that patch - // is in, this issue can be fixed. - const OperationsMask layoutOperations = static_cast( LAYOUT | - UPDATE_ACTUAL_SIZE | - ALIGN | - REORDER ); - - mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | layoutOperations ); + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | ALIGN ); mImpl->RequestRelayout(); } diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 47a2028..414fffa 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -92,6 +92,48 @@ Length View::GetGlyphs( GlyphInfo* glyphs, glyphIndex, numberOfLaidOutGlyphs ); + // Get the lines for the given range of glyphs. + // The lines contain the alignment offset which needs to be added to the glyph's position. + LineIndex firstLine = 0u; + Length numberOfLines = 0u; + mImpl->mVisualModel->GetNumberOfLines( glyphIndex, + numberOfLaidOutGlyphs, + firstLine, + numberOfLines ); + + Vector lines; + lines.Resize( numberOfLines ); + LineRun* lineBuffer = lines.Begin(); + + mImpl->mVisualModel->GetLinesOfGlyphRange( lineBuffer, + glyphIndex, + numberOfLaidOutGlyphs ); + + // Get the first line for the given glyph range. + LineIndex lineIndex = firstLine; + LineRun* line = lineBuffer + lineIndex; + + // Index of the last glyph of the line. + GlyphIndex lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u; + + // Add the alignment offset to the glyph's position. + for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index ) + { + ( *( glyphPositions + index ) ).x += line->alignmentOffset; + + if( lastGlyphIndexOfLine == index ) + { + // Get the next line. + ++lineIndex; + + if( lineIndex < numberOfLines ) + { + line = lineBuffer + lineIndex; + lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u; + } + } + } + if( 1u == numberOfLaidOutGlyphs ) { // not a point try to do ellipsis with only one laid out character. diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index 5f36226..beeb08b 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -36,9 +36,9 @@ VisualModelPtr VisualModel::New() return VisualModelPtr( new VisualModel() ); } -void VisualModel::SetGlyphs( const GlyphInfo* glyphs, - const CharacterIndex* characterIndices, - const Length* charactersPerGlyph, +void VisualModel::SetGlyphs( const GlyphInfo* const glyphs, + const CharacterIndex* const characterIndices, + const Length* const charactersPerGlyph, Length numberOfGlyphs ) { if( 0u == numberOfGlyphs ) @@ -225,7 +225,7 @@ void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) ); } -void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, +void VisualModel::SetGlyphPositions( const Vector2* const glyphPositions, Length numberOfGlyphs ) { if( 0u == numberOfGlyphs ) diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index fb9f7bc..227019f 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -73,9 +73,9 @@ public: * @param[in] charactersPerGlyph An array containing the number of characters per glyph. * @param[in] numberOfGlyphs The number of glyphs. */ - void SetGlyphs( const GlyphInfo* glyphs, - const CharacterIndex* characterIndices, - const Length* charactersPerGlyph, + void SetGlyphs( const GlyphInfo* const glyphs, + const CharacterIndex* const characterIndices, + const Length* const charactersPerGlyph, Length numberOfGlyphs ); /** @@ -228,7 +228,7 @@ public: * @param[in] glyphPositions An array of visual positions for each glyph. * @param[in] numberOfGlyphs The number of positions. */ - void SetGlyphPositions( const Vector2* glyphPositions, + void SetGlyphPositions( const Vector2* const glyphPositions, Length numberOfGlyphs ); /** -- 2.7.4