// 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;
// 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;
bool LayoutText( const LayoutParameters& layoutParameters,
Vector<Vector2>& glyphPositions,
+ Vector<LineRun>& lines,
Size& actualSize )
{
// TODO Switch between different layouts
{
update = SingleLineLayout( layoutParameters,
glyphPositions,
+ lines,
actualSize );
break;
}
{
update = MultiLineLayout( layoutParameters,
glyphPositions,
+ lines,
actualSize );
break;
}
// TODO - Rewrite this to handle bidi
bool SingleLineLayout( const LayoutParameters& layoutParameters,
Vector<Vector2>& glyphPositions,
+ Vector<LineRun>& lines,
Size& actualSize )
{
LineLayout layout;
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;
// TODO - Rewrite this to handle bidi
bool MultiLineLayout( const LayoutParameters& layoutParameters,
Vector<Vector2>& glyphPositions,
+ Vector<LineRun>& lines,
Size& actualSize )
{
float penY = 0.f;
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 )
{
bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters,
Vector<Vector2>& glyphPositions,
+ Vector<LineRun>& lines,
Size& actualSize )
{
return mImpl->LayoutText( layoutParameters,
glyphPositions,
+ lines,
actualSize );
}
*/
// INTERNAL INCLUDE
-#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/line-run.h>
// EXTERNAL INCLUDE
#include <dali/public-api/common/dali-vector.h>
*
* @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<Vector2>& glyphPositions,
+ Vector<LineRun>& lines,
Size& actualSize );
private:
*
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+
// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/character-run.h>
namespace Dali
{
*/
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
LAYOUT |
UPDATE_ACTUAL_SIZE |
UPDATE_POSITIONS |
+ UPDATE_LINES |
REORDER );
mImpl->mControlSize = 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 );
Vector<Vector2> 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<LineRun> 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
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
};
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<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
+ Vector<LineRun> 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()
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
{
- Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
+ const Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
}
CharacterIndex characterIndex,
Length numberOfCharacters ) const
{
- Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
+ const Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
}
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
{
- Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
+ const Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
}
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
{
- Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
+ const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
}
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
{
- Vector<Vector2> modelPositions = mImpl->mGlyphPositions;
+ const Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
}
void VisualModel::SetLines( const LineRun* const lines,
Length numberOfLines )
{
+ Vector<LineRun>& 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<LineRun>& 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<LineRun>& modelLines = mImpl->mLines;
+ const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
+
+ // Traverse the lines and cound those lines within the range of glyphs.
+ for( Vector<LineRun>::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<LineRun>& 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 )
*
* @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.
*