+ /**
+ * @brief Resizes the line buffer.
+ *
+ * @param[in,out] lines The vector of lines. Used when the layout is created from scratch.
+ * @param[in,out] newLines The vector of lines used instead of @p lines when the layout is updated.
+ * @param[in,out] linesCapacity The capacity of the vector (either lines or newLines).
+ * @param[in] updateCurrentBuffer Whether the layout is updated.
+ *
+ * @return Pointer to either lines or newLines.
+ */
+ LineRun* ResizeLinesBuffer( Vector<LineRun>& lines,
+ Vector<LineRun>& newLines,
+ Length& linesCapacity,
+ bool updateCurrentBuffer )
+ {
+ LineRun* linesBuffer = NULL;
+ // Reserve more space for the next lines.
+ linesCapacity *= 2u;
+ if( updateCurrentBuffer )
+ {
+ newLines.Resize( linesCapacity );
+ linesBuffer = newLines.Begin();
+ }
+ else
+ {
+ lines.Resize( linesCapacity );
+ linesBuffer = lines.Begin();
+ }
+
+ return linesBuffer;
+ }
+
+ /**
+ * Ellipsis a line if it exceeds the width's of the bounding box.
+ *
+ * @param[in] layoutParameters The parameters needed to layout the text.
+ * @param[in] layout The line layout.
+ * @param[in,out] layoutSize The text's layout size.
+ * @param[in,out] linesBuffer Pointer to the line's buffer.
+ * @param[in,out] glyphPositionsBuffer Pointer to the position's buffer.
+ * @param[in,out] numberOfLines The number of laid-out lines.
+ * @param[in] penY The vertical layout position.
+ * @param[in] currentParagraphDirection The current paragraph's direction.
+ *
+ * return Whether the line is ellipsized.
+ */
+ bool EllipsisLine( const Parameters& layoutParameters,
+ const LineLayout& layout,
+ Size& layoutSize,
+ LineRun* linesBuffer,
+ Vector2* glyphPositionsBuffer,
+ Length& numberOfLines,
+ float penY,
+ CharacterDirection currentParagraphDirection )
+ {
+ const bool ellipsis = ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
+ ( ( mLayout == SINGLE_LINE_BOX ) &&
+ ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) );
+
+ if( ellipsis )
+ {
+ // Do not layout more lines if ellipsis is enabled.
+
+ // The last line needs to be completely filled with characters.
+ // Part of a word may be used.
+
+ LineRun* lineRun = NULL;
+ LineLayout ellipsisLayout;
+ if( 0u != numberOfLines )
+ {
+ // Get the last line and layout it again with the 'completelyFill' flag to true.
+ lineRun = linesBuffer + ( numberOfLines - 1u );
+
+ penY -= layout.ascender - lineRun->descender;
+
+ ellipsisLayout.glyphIndex = lineRun->glyphRun.glyphIndex;
+ }
+ else
+ {
+ // At least there is space reserved for one line.
+ lineRun = linesBuffer;
+
+ lineRun->glyphRun.glyphIndex = 0u;
+ ellipsisLayout.glyphIndex = 0u;
+
+ ++numberOfLines;
+ }
+
+ GetLineLayoutForBox( layoutParameters,
+ ellipsisLayout,
+ currentParagraphDirection,
+ true );
+
+ lineRun->glyphRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
+ lineRun->characterRun.characterIndex = ellipsisLayout.characterIndex;
+ lineRun->characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
+ lineRun->width = ellipsisLayout.length;
+ lineRun->extraLength = ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f;
+ lineRun->ascender = ellipsisLayout.ascender;
+ lineRun->descender = ellipsisLayout.descender;
+ lineRun->direction = !RTL;
+ lineRun->ellipsis = true;
+
+ layoutSize.width = layoutParameters.boundingBox.width;
+ if( layoutSize.height < Math::MACHINE_EPSILON_1000 )
+ {
+ layoutSize.height += ( lineRun->ascender + -lineRun->descender );
+ }
+
+ SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex,
+ ellipsisLayout.numberOfGlyphs,
+ glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex );
+ }
+
+ return ellipsis;
+ }
+
+ /**
+ * @brief Updates the text layout with a new laid-out line.
+ *
+ * @param[in] layoutParameters The parameters needed to layout the text.
+ * @param[in] layout The line layout.
+ * @param[in,out] layoutSize The text's layout size.
+ * @param[in,out] linesBuffer Pointer to the line's buffer.
+ * @param[in] index Index to the vector of glyphs.
+ * @param[in,out] numberOfLines The number of laid-out lines.
+ * @param[in] isLastLine Whether the laid-out line is the last one.
+ */
+ void UpdateTextLayout( const Parameters& layoutParameters,
+ const LineLayout& layout,
+ Size& layoutSize,
+ LineRun* linesBuffer,
+ GlyphIndex index,
+ Length& numberOfLines,
+ bool isLastLine )
+ {
+ LineRun& lineRun = *( linesBuffer + numberOfLines );
+ ++numberOfLines;
+
+ lineRun.glyphRun.glyphIndex = index;
+ lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs;
+ lineRun.characterRun.characterIndex = layout.characterIndex;
+ lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
+ if( isLastLine && !layoutParameters.isLastNewParagraph )
+ {
+ const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
+ if( MULTI_LINE_BOX == mLayout )
+ {
+ lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width;
+ }
+ else
+ {
+ lineRun.width = width;
+ }
+
+ lineRun.extraLength = 0.f;
+ }
+ else
+ {
+ lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
+ lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+ }
+ lineRun.ascender = layout.ascender;
+ lineRun.descender = layout.descender;
+ lineRun.direction = !RTL;
+ lineRun.ellipsis = false;
+
+ // Update the actual size.
+ if( lineRun.width > layoutSize.width )
+ {
+ layoutSize.width = lineRun.width;
+ }
+
+ layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+ }
+
+ /**
+ * @brief Updates the text layout with the last laid-out line.
+ *
+ * @param[in] layoutParameters The parameters needed to layout the text.
+ * @param[in] characterIndex The character index of the line.
+ * @param[in] glyphIndex The glyph index of the line.
+ * @param[in,out] layoutSize The text's layout size.
+ * @param[in,out] linesBuffer Pointer to the line's buffer.
+ * @param[in,out] numberOfLines The number of laid-out lines.
+ */
+ void UpdateTextLayout( const Parameters& layoutParameters,
+ CharacterIndex characterIndex,
+ GlyphIndex glyphIndex,
+ Size& layoutSize,
+ LineRun* linesBuffer,
+ Length& numberOfLines )
+ {
+ // Need to add a new line with no characters but with height to increase the layoutSize.height
+ const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u );
+
+ Text::FontMetrics fontMetrics;
+ mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
+
+ LineRun& lineRun = *( linesBuffer + numberOfLines );
+ ++numberOfLines;
+
+ lineRun.glyphRun.glyphIndex = glyphIndex;
+ lineRun.glyphRun.numberOfGlyphs = 0u;
+ lineRun.characterRun.characterIndex = characterIndex;
+ lineRun.characterRun.numberOfCharacters = 0u;
+ lineRun.width = 0.f;
+ lineRun.ascender = fontMetrics.ascender;
+ lineRun.descender = fontMetrics.descender;
+ lineRun.extraLength = 0.f;
+ lineRun.alignmentOffset = 0.f;
+ lineRun.direction = !RTL;
+ lineRun.ellipsis = false;
+
+ layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+ }
+
+ /**
+ * @brief Updates the text's layout size adding the size of the previously laid-out lines.
+ *
+ * @param[in] lines The vector of lines (before the new laid-out lines are inserted).
+ * @param[in,out] layoutSize The text's layout size.
+ */
+ void UpdateLayoutSize( const Vector<LineRun>& lines,
+ Size& layoutSize )
+ {
+ for( Vector<LineRun>::ConstIterator it = lines.Begin(),
+ endIt = lines.End();
+ it != endIt;
+ ++it )
+ {
+ const LineRun& line = *it;
+
+ if( line.width > layoutSize.width )
+ {
+ layoutSize.width = line.width;
+ }
+
+ layoutSize.height += ( line.ascender + -line.descender );
+ }
+ }
+
+ /**
+ * @brief Updates the indices of the character and glyph runs of the lines before the new lines are inserted.
+ *
+ * @param[in] layoutParameters The parameters needed to layout the text.
+ * @param[in,out] lines The vector of lines (before the new laid-out lines are inserted).
+ * @param[in] characterOffset The offset to be added to the runs of characters.
+ * @param[in] glyphOffset The offset to be added to the runs of glyphs.
+ */
+ void UpdateLineIndexOffsets( const Parameters& layoutParameters,
+ Vector<LineRun>& lines,
+ Length characterOffset,
+ Length glyphOffset )
+ {
+ // Update the glyph and character runs.
+ for( Vector<LineRun>::Iterator it = lines.Begin() + layoutParameters.startLineIndex,
+ endIt = lines.End();
+ it != endIt;
+ ++it )
+ {
+ LineRun& line = *it;
+
+ line.glyphRun.glyphIndex = glyphOffset;
+ line.characterRun.characterIndex = characterOffset;
+
+ glyphOffset += line.glyphRun.numberOfGlyphs;
+ characterOffset += line.characterRun.numberOfCharacters;
+ }
+ }
+
+ bool LayoutText( const Parameters& layoutParameters,