X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fvisual-model-impl.cpp;h=1b114c444a9d9bffae87eb138d19206eb66666b3;hp=ec94ecc007abf67c4768250dc90d1b970fd04ece;hb=3a23cbcd64ab5780928e4a141e497242c9989110;hpb=9db1f87a421a896c62580a733449486512315c9a diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index ec94ecc..1b114c4 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include namespace Dali { @@ -36,70 +35,50 @@ VisualModelPtr VisualModel::New() return VisualModelPtr( new VisualModel() ); } -void VisualModel::SetGlyphs( const GlyphInfo* glyphs, - const CharacterIndex* characterIndices, - const Length* charactersPerGlyph, - Length numberOfGlyphs ) +void VisualModel::CreateCharacterToGlyphTable( CharacterIndex startIndex, + GlyphIndex startGlyphIndex, + Length numberOfCharacters ) { - if( 0u == numberOfGlyphs ) + if( 0u == numberOfCharacters ) { - mGlyphs.Clear(); - mGlyphsToCharacters.Clear(); - mCharactersToGlyph.Clear(); - mCharactersPerGlyph.Clear(); - mGlyphsPerCharacter.Clear(); + // Nothing to do. + return; } - else - { - if( NULL != glyphs ) - { - mGlyphs.Resize( numberOfGlyphs ); - memcpy( mGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); - } - if( NULL != characterIndices ) - { - mGlyphsToCharacters.Resize( numberOfGlyphs ); - memcpy( mGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) ); - } + DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u ); - if( NULL != charactersPerGlyph ) - { - mCharactersPerGlyph.Resize( numberOfGlyphs ); - memcpy( mCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) ); + // Get the total number of characters. + const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph. - // Build the glyphs per character table. - CreateGlyphsPerCharacterTable(); + // Whether the current buffer is being updated or is set from scratch. + const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters; - // Build the characters to glyph conversion table. - CreateCharacterToGlyphTable(); - } - } -} + Vector newCharactersToGlyph; + GlyphIndex* charactersToGlyphBuffer = NULL; -void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters ) -{ - // 1) Reserve some space for the characters to avoid reallocations. - if( 0u == numberOfCharacters ) + // 1) Reserve some space for the glyph indices to avoid reallocations. + if( updateCurrentBuffer ) { - // If no number of characters is given, just set something sensible to avoid reallocations. - numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + newCharactersToGlyph.Resize( numberOfCharacters ); + charactersToGlyphBuffer = newCharactersToGlyph.Begin(); + } + else + { + mCharactersToGlyph.Resize( numberOfCharacters ); + charactersToGlyphBuffer = mCharactersToGlyph.Begin() + startIndex; } - mCharactersToGlyph.Reserve( numberOfCharacters ); - - DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u || - ( 0u == numberOfCharacters ) ); const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin(); // 2) Traverse the glyphs and set the glyph indices per character. // Index to the glyph. - GlyphIndex glyphIndex = 0u; - CharacterIndex characterIndex = 0u; - for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + GlyphIndex glyphIndex = startGlyphIndex; + CharacterIndex characterIndex = startIndex; + const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters; + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin() + glyphIndex, endIt = mCharactersPerGlyph.End(); - it != endIt; + ( it != endIt ) && ( characterIndex < lastCharacterIndexPlusOne ); ++it ) { const Length numberOfCharactersPerGlyph = *it; @@ -108,34 +87,78 @@ void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters ) // Set the glyph indices. for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex ) { - mCharactersToGlyph.PushBack( glyphIndex ); + *charactersToGlyphBuffer = glyphIndex; numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex ); + ++charactersToGlyphBuffer; } glyphIndex += numberOfGlyphs; } + + // If the character to glyph buffer is updated, it needs to be inserted in the model. + if( updateCurrentBuffer ) + { + // Update the indices. + const Length numberOfGlyphs = glyphIndex - startGlyphIndex; + for( Vector::Iterator it = mCharactersToGlyph.Begin() + startIndex, + endIt = mCharactersToGlyph.End(); + it != endIt; + ++it ) + { + *it += numberOfGlyphs; + } + + mCharactersToGlyph.Insert( mCharactersToGlyph.Begin() + startIndex, + newCharactersToGlyph.Begin(), + newCharactersToGlyph.End() ); + + } } -void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters ) +void VisualModel::CreateGlyphsPerCharacterTable( CharacterIndex startIndex, + GlyphIndex startGlyphIndex, + Length numberOfCharacters ) { - // 1) Reserve some space for the characters to avoid reallocations. if( 0u == numberOfCharacters ) { - // If no number of characters is given, just set something sensible to avoid reallocations. - numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + // Nothing to do. + return; + } + + // Get the total number of characters. + const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph. + + // Whether the current buffer is being updated or is set from scratch. + const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters; + + Vector newGlyphsPerCharacter; + Length* glyphsPerCharacterBuffer = NULL; + + // 1) Reserve some space for the glyphs per character to avoid reallocations. + if( updateCurrentBuffer ) + { + newGlyphsPerCharacter.Resize( numberOfCharacters ); + glyphsPerCharacterBuffer = newGlyphsPerCharacter.Begin(); + } + else + { + mGlyphsPerCharacter.Resize( numberOfCharacters ); + glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin() + startIndex; } - mGlyphsPerCharacter.Reserve( numberOfCharacters ); // 2) Traverse the glyphs and set the number of glyphs per character. + Length traversedCharacters = 0; + // The number of 'characters per glyph' equal to zero. Length zeroCharactersPerGlyph = 0u; - for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin() + startGlyphIndex, endIt = mCharactersPerGlyph.End(); - it != endIt; + ( it != endIt ) && ( traversedCharacters < numberOfCharacters ); ++it ) { const Length numberOfCharactersPerGlyph = *it; + traversedCharacters += numberOfCharactersPerGlyph; // Set the glyphs per character. if( 0u == numberOfCharactersPerGlyph ) @@ -145,21 +168,30 @@ void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters ) else { const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u ); - for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex ) + for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter; ++zeroIndex ) { - mGlyphsPerCharacter.PushBack( 0u ); + *glyphsPerCharacterBuffer = 0u; + + // Point to the next position in the buffer. + ++glyphsPerCharacterBuffer; } - mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph ); + *glyphsPerCharacterBuffer = zeroCharactersPerGlyph + 1u; zeroCharactersPerGlyph = 0u; + + // Point to the next position in the buffer. + ++glyphsPerCharacterBuffer; } } -} -Length VisualModel::GetNumberOfGlyphs() const -{ - return mGlyphs.Count(); + // If the glyphs per character buffer is updated, it needs to be inserted in the model. + if( updateCurrentBuffer ) + { + mGlyphsPerCharacter.Insert( mGlyphsPerCharacter.Begin() + startIndex, + newGlyphsPerCharacter.Begin(), + newGlyphsPerCharacter.End() ); + } } void VisualModel::GetGlyphs( GlyphInfo* glyphs, @@ -169,81 +201,6 @@ void VisualModel::GetGlyphs( GlyphInfo* glyphs, memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) ); } -const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const -{ - return mGlyphs[glyphIndex]; -} - -void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const GlyphInfo* const glyphs, - const Length* const numberOfCharacters, - Length numberOfGlyphsToInsert ) -{ -} - -CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const -{ - return mGlyphsToCharacters[glyphIndex]; -} - -Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const -{ - return mCharactersPerGlyph[glyphIndex]; -} - -GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const -{ - return mCharactersToGlyph[characterIndex]; -} - -void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) ); -} - -void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) ); -} - -void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) ); -} - -void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) ); -} - -void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, - Length numberOfGlyphs ) -{ - if( 0u == numberOfGlyphs ) - { - mGlyphPositions.Clear(); - } - else - { - mGlyphPositions.Resize( numberOfGlyphs ); - memcpy( mGlyphPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); - } -} - -Length VisualModel::GetNumberOfGlyphPositions() const -{ - return mGlyphPositions.Count(); -} - void VisualModel::GetGlyphPositions( Vector2* glyphPositions, GlyphIndex glyphIndex, Length numberOfGlyphs ) const @@ -251,44 +208,6 @@ void VisualModel::GetGlyphPositions( Vector2* glyphPositions, memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) ); } -const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const -{ - return *( mGlyphPositions.Begin() + glyphIndex ); -} - -void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const Vector2* const positions, - Length numberOfGlyphsToInsert ) -{ -} - -void VisualModel::SetLines( const LineRun* const lines, - Length numberOfLines ) -{ - if( 0u == numberOfLines ) - { - mLines.Clear(); - } - else - { - mLines.Resize( numberOfLines ); - memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) ); - } -} - -Length VisualModel::GetNumberOfLines() const -{ - return mLines.Count(); -} - -void VisualModel::GetLines( LineRun* lines, - LineIndex lineIndex, - Length numberOfLines ) const -{ - memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) ); -} - void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex, Length numberOfGlyphs, LineIndex& firstLine, @@ -309,13 +228,13 @@ void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex, { const LineRun& line = *it; - if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) && - ( lastGlyphIndex > line.glyphIndex ) ) + if( ( line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs > glyphIndex ) && + ( lastGlyphIndex > line.glyphRun.glyphIndex ) ) { firstLineFound = true; ++numberOfLines; } - else if( lastGlyphIndex <= line.glyphIndex ) + else if( lastGlyphIndex <= line.glyphRun.glyphIndex ) { // nothing else to do. break; @@ -343,11 +262,46 @@ void VisualModel::GetLinesOfGlyphRange( LineRun* lines, memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) ); } -void VisualModel::ReplaceLines( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const LineRun* const lines, - Length numberOfGlyphsToInsert ) +LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex ) +{ + // 1) Check first in the cached line. + + const LineRun& lineRun = *( mLines.Begin() + mCachedLineIndex ); + + if( ( lineRun.characterRun.characterIndex <= characterIndex ) && + ( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) ) + { + return mCachedLineIndex; + } + + // 2) Is not in the cached line. Check in the other lines. + + LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u; + + for( Vector::ConstIterator it = mLines.Begin() + index, + endIt = mLines.End(); + it != endIt; + ++it, ++index ) + { + const LineRun& lineRun = *it; + + if( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) + { + mCachedLineIndex = index; + break; + } + } + + return index; +} + +void VisualModel::GetUnderlineRuns( GlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns ) const { + memcpy( underlineRuns, + mUnderlineRuns.Begin() + index, + numberOfRuns * sizeof( GlyphRun ) ); } void VisualModel::SetNaturalSize( const Vector2& size ) @@ -360,14 +314,14 @@ const Vector2& VisualModel::GetNaturalSize() const return mNaturalSize; } -void VisualModel::SetActualSize( const Vector2& size ) +void VisualModel::SetLayoutSize( const Vector2& size ) { - mActualSize = size; + mLayoutSize = size; } -const Vector2& VisualModel::GetActualSize() const +const Vector2& VisualModel::GetLayoutSize() const { - return mActualSize; + return mLayoutSize; } void VisualModel::SetTextColor( const Vector4& textColor ) @@ -401,6 +355,11 @@ void VisualModel::SetUnderlineEnabled( bool enabled ) mUnderlineEnabled = enabled; } +void VisualModel::SetUnderlineHeight( float height ) +{ + mUnderlineHeight = height; +} + const Vector4& VisualModel::GetTextColor() const { return mTextColor; @@ -426,12 +385,44 @@ bool VisualModel::IsUnderlineEnabled() const return mUnderlineEnabled; } +float VisualModel::GetUnderlineHeight() const +{ + return mUnderlineHeight; +} + +Length VisualModel::GetNumberOfUnderlineRuns() const +{ + return mUnderlineRuns.Count(); +} + +void VisualModel::ClearCaches() +{ + mCachedLineIndex = 0u; +} + VisualModel::~VisualModel() { } VisualModel::VisualModel() -: mUnderlineColorSet( false ) +: mGlyphs(), + mGlyphsToCharacters(), + mCharactersToGlyph(), + mCharactersPerGlyph(), + mGlyphsPerCharacter(), + mGlyphPositions(), + mLines(), + mTextColor( Color::BLACK ), + mShadowColor( Color::BLACK ), + mUnderlineColor( Color::BLACK ), + mControlSize(), + mShadowOffset(), + mUnderlineHeight( 0.0f ), + mNaturalSize(), + mLayoutSize(), + mCachedLineIndex( 0u ), + mUnderlineEnabled( false ), + mUnderlineColorSet( false ) { }