X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fcursor-helper-functions.cpp;h=1fbca0d907aacafaa7b89b23eebdfd582b681432;hb=63f9b5207c2794cdc460d587723be89585872a51;hp=b3b7250e163cbe8595784ad712a331ccce68c1ac;hpb=8d92a2cdf4665c1831b524af0a316208947e27c1;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/cursor-helper-functions.cpp b/dali-toolkit/internal/text/cursor-helper-functions.cpp index b3b7250..1fbca0d 100644 --- a/dali-toolkit/internal/text/cursor-helper-functions.cpp +++ b/dali-toolkit/internal/text/cursor-helper-functions.cpp @@ -33,6 +33,97 @@ namespace const Dali::Toolkit::Text::CharacterDirection LTR = false; ///< Left To Right direction. +struct FindWordData +{ + FindWordData( const Dali::Toolkit::Text::Character* const textBuffer, + Dali::Toolkit::Text::Length totalNumberOfCharacters, + Dali::Toolkit::Text::CharacterIndex hitCharacter, + bool isWhiteSpace, + bool isNewParagraph ) + : textBuffer( textBuffer ), + totalNumberOfCharacters( totalNumberOfCharacters ), + hitCharacter( hitCharacter ), + foundIndex( 0u ), + isWhiteSpace( isWhiteSpace ), + isNewParagraph( isNewParagraph ) + {} + + ~FindWordData() + {} + + const Dali::Toolkit::Text::Character* const textBuffer; + Dali::Toolkit::Text::Length totalNumberOfCharacters; + Dali::Toolkit::Text::CharacterIndex hitCharacter; + Dali::Toolkit::Text::CharacterIndex foundIndex; + bool isWhiteSpace : 1u; + bool isNewParagraph : 1u; +}; + +bool IsWhiteSpaceOrNewParagraph( Dali::Toolkit::Text::Character character, + bool isHitWhiteSpace, + bool isHitWhiteSpaceOrNewParagraph ) +{ + bool isWhiteSpaceOrNewParagraph = false; + if( isHitWhiteSpaceOrNewParagraph ) + { + if( isHitWhiteSpace ) + { + // Whether the current character is a white space. Note a new paragraph character is a white space as well but here is not wanted. + isWhiteSpaceOrNewParagraph = Dali::TextAbstraction::IsWhiteSpace( character ) && !Dali::TextAbstraction::IsNewParagraph( character ); + } + else + { + // Whether the current character is a new paragraph character. + isWhiteSpaceOrNewParagraph = Dali::TextAbstraction::IsNewParagraph( character ); + } + } + else + { + // Whether the current character is a white space or a new paragraph character (note the new paragraph character is a white space as well). + isWhiteSpaceOrNewParagraph = Dali::TextAbstraction::IsWhiteSpace( character ); + } + + return isWhiteSpaceOrNewParagraph; +} + +void FindStartOfWord( FindWordData& data ) +{ + const bool isHitWhiteSpaceOrNewParagraph = data.isWhiteSpace || data.isNewParagraph; + + for( data.foundIndex = data.hitCharacter; data.foundIndex > 0; --data.foundIndex ) + { + const Dali::Toolkit::Text::Character character = *( data.textBuffer + data.foundIndex - 1u ); + + const bool isWhiteSpaceOrNewParagraph = IsWhiteSpaceOrNewParagraph( character, + data.isWhiteSpace, + isHitWhiteSpaceOrNewParagraph ); + + if( isHitWhiteSpaceOrNewParagraph != isWhiteSpaceOrNewParagraph ) + { + break; + } + } +} + +void FindEndOfWord( FindWordData& data ) +{ + const bool isHitWhiteSpaceOrNewParagraph = data.isWhiteSpace || data.isNewParagraph; + + for( data.foundIndex = data.hitCharacter + 1u; data.foundIndex < data.totalNumberOfCharacters; ++data.foundIndex ) + { + const Dali::Toolkit::Text::Character character = *( data.textBuffer + data.foundIndex ); + + const bool isWhiteSpaceOrNewParagraph = IsWhiteSpaceOrNewParagraph( character, + data.isWhiteSpace, + isHitWhiteSpaceOrNewParagraph ); + + if( isHitWhiteSpaceOrNewParagraph != isWhiteSpaceOrNewParagraph ) + { + break; + } + } +} + } //namespace namespace Dali @@ -587,7 +678,7 @@ void GetCursorPosition( VisualModelPtr visualModel, ( isFirstPositionOfLine && !isRightToLeftParagraph ) ); cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( addGlyphAdvance ? glyphMetrics.advance : 0.f ); - cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender ); + cursorInfo.secondaryPosition.y = cursorInfo.lineOffset + cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight; // Transform the cursor info from line's coords to text's coords. cursorInfo.secondaryPosition.x += line.alignmentOffset; @@ -595,7 +686,7 @@ void GetCursorPosition( VisualModelPtr visualModel, } } -void FindSelectionIndices( VisualModelPtr visualModel, +bool FindSelectionIndices( VisualModelPtr visualModel, LogicalModelPtr logicalModel, MetricsPtr metrics, float visualX, @@ -603,52 +694,122 @@ void FindSelectionIndices( VisualModelPtr visualModel, CharacterIndex& startIndex, CharacterIndex& endIndex ) { + +/* + Hit character Select +|-------------------------------------------------------|------------------------------------------| +| On a word | The word | +| On a single white space between words | The word before or after the white space | +| On one of the multiple contiguous white spaces | The white spaces | +| On a single white space which is in the position zero | The white space and the next word | +| On a new paragraph character | The word or group of white spaces before | +|-------------------------------------------------------|------------------------------------------| +*/ + CharacterIndex hitCharacter = Text::GetClosestCursorIndex( visualModel, logicalModel, metrics, visualX, visualY ); - DALI_ASSERT_DEBUG( hitCharacter <= logicalModel->mText.Count() && "GetClosestCursorIndex returned out of bounds index" ); - if( logicalModel->mText.Count() == 0 ) + const Length totalNumberOfCharacters = logicalModel->mText.Count(); + + DALI_ASSERT_DEBUG( ( hitCharacter <= totalNumberOfCharacters ) && "GetClosestCursorIndex returned out of bounds index" ); + + if( 0u == totalNumberOfCharacters ) { - return; // if model empty + // Nothing to do if the model is empty. + return false; } - if( hitCharacter >= logicalModel->mText.Count() ) + if( hitCharacter >= totalNumberOfCharacters ) { // Closest hit character is the last character. - if( hitCharacter == logicalModel->mText.Count() ) + if( hitCharacter == totalNumberOfCharacters ) { hitCharacter--; //Hit character index set to last character in logical model } else { // hitCharacter is out of bounds - return; + return false; } } + const Character* const textBuffer = logicalModel->mText.Begin(); + startIndex = hitCharacter; endIndex = hitCharacter; - bool isHitCharacterWhitespace = TextAbstraction::IsWhiteSpace( logicalModel->mText[hitCharacter] ); - // Find the start and end of the text - for( startIndex = hitCharacter; startIndex > 0; --startIndex ) + // Whether the hit character is a new paragraph character. + const bool isHitCharacterNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + hitCharacter ) ); + + // Whether the hit character is a white space. Note a new paragraph character is a white space as well but here is not wanted. + const bool isHitCharacterWhiteSpace = TextAbstraction::IsWhiteSpace( *( textBuffer + hitCharacter ) ) && !isHitCharacterNewParagraph; + + FindWordData data( textBuffer, + totalNumberOfCharacters, + hitCharacter, + isHitCharacterWhiteSpace, + isHitCharacterNewParagraph ); + + if( isHitCharacterNewParagraph ) { - if( isHitCharacterWhitespace != TextAbstraction::IsWhiteSpace( logicalModel->mText[ startIndex-1 ] ) ) + // Find the first character before the hit one which is not a new paragraph character. + + if( hitCharacter > 0u ) { - break; + endIndex = hitCharacter - 1u; + for( ; endIndex > 0; --endIndex ) + { + const Dali::Toolkit::Text::Character character = *( data.textBuffer + endIndex ); + + if( !Dali::TextAbstraction::IsNewParagraph( character ) ) + { + break; + } + } } + + data.hitCharacter = endIndex; + data.isNewParagraph = false; + data.isWhiteSpace = TextAbstraction::IsWhiteSpace( *( textBuffer + data.hitCharacter ) ); } - const CharacterIndex pastTheEnd = logicalModel->mText.Count(); - for( endIndex = hitCharacter + 1u; endIndex < pastTheEnd; ++endIndex ) + + // Find the start of the word. + FindStartOfWord( data ); + startIndex = data.foundIndex; + + // Find the end of the word. + FindEndOfWord( data ); + endIndex = data.foundIndex; + + if( 1u == ( endIndex - startIndex ) ) { - if( isHitCharacterWhitespace != TextAbstraction::IsWhiteSpace( logicalModel->mText[ endIndex ] ) ) + if( isHitCharacterWhiteSpace ) { - break; + // Select the word before or after the white space + + if( 0u == hitCharacter ) + { + data.isWhiteSpace = false; + FindEndOfWord( data ); + endIndex = data.foundIndex; + } + else if( hitCharacter > 0u ) + { + // Find the start of the word. + data.hitCharacter = hitCharacter - 1u; + data.isWhiteSpace = false; + FindStartOfWord( data ); + startIndex = data.foundIndex; + + --endIndex; + } } } + + return true; } } // namespace Text