X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller-impl.cpp;h=5e64f8796fec3a53a3afd7e36aa2a1d1829a1463;hb=36a4d207b64a34433a19d78dc0c9f768f6990773;hp=c36b1d812e2e1690ef3e0f6aaa664cea1997d132;hpb=93865ae71c4937b0301c7160f9b1496b81c5af3e;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index c36b1d8..5e64f87 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -25,13 +25,9 @@ // INTERNAL INCLUDES #include #include -#include #include -#include #include #include -#include -#include namespace { @@ -329,7 +325,6 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) { // Retrieves the scripts used in the text. multilanguageSupport.SetScripts( utf32Characters, - lineBreakInfo, scripts ); } @@ -352,13 +347,12 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) Vector mirroredUtf32Characters; bool textMirrored = false; + Length numberOfParagraphs = 0u; if( BIDI_INFO & operations ) { // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's // bidirectional info. - Length numberOfParagraphs = 0u; - const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); for( Length index = 0u; index < numberOfCharacters; ++index ) { @@ -382,7 +376,9 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) // This paragraph has right to left text. Some characters may need to be mirrored. // TODO: consider if the mirrored string can be stored as well. - textMirrored = GetMirroredText( utf32Characters, mirroredUtf32Characters ); + textMirrored = GetMirroredText( utf32Characters, + mirroredUtf32Characters, + bidirectionalInfo ); // Only set the character directions if there is right to left characters. Vector& directions = mLogicalModel->mCharacterDirections; @@ -401,6 +397,9 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) Vector& glyphs = mVisualModel->mGlyphs; Vector& glyphsToCharactersMap = mVisualModel->mGlyphsToCharacters; Vector& charactersPerGlyph = mVisualModel->mCharactersPerGlyph; + Vector newParagraphGlyphs; + newParagraphGlyphs.Reserve( numberOfParagraphs ); + if( SHAPE_TEXT & operations ) { const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters; @@ -411,7 +410,8 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) validFonts, glyphs, glyphsToCharactersMap, - charactersPerGlyph ); + charactersPerGlyph, + newParagraphGlyphs ); // Create the 'number of glyphs' per character and the glyph to character conversion tables. mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters ); @@ -422,7 +422,40 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired ) if( GET_GLYPH_METRICS & operations ) { - mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs ); + GlyphInfo* glyphsBuffer = glyphs.Begin(); + mFontClient.GetGlyphMetrics( glyphsBuffer, numberOfGlyphs ); + + // Update the width and advance of all new paragraph characters. + for( Vector::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it ) + { + const GlyphIndex index = *it; + GlyphInfo& glyph = *( glyphsBuffer + index ); + + glyph.xBearing = 0.f; + glyph.width = 0.f; + glyph.advance = 0.f; + } + } + + if( mEventData && + mEventData->mPreEditFlag && + ( 0u != mVisualModel->mCharactersToGlyph.Count() ) ) + { + // Add the underline for the pre-edit text. + const GlyphIndex* const charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin(); + const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin(); + + const GlyphIndex glyphStart = *( charactersToGlyphBuffer + mEventData->mPreEditStartPosition ); + const CharacterIndex lastPreEditCharacter = mEventData->mPreEditStartPosition + ( ( mEventData->mPreEditLength > 0u ) ? mEventData->mPreEditLength - 1u : 0u ); + const Length numberOfGlyphsLastCharacter = *( glyphsPerCharacterBuffer + lastPreEditCharacter ); + const GlyphIndex glyphEnd = *( charactersToGlyphBuffer + lastPreEditCharacter ) + ( numberOfGlyphsLastCharacter > 1u ? numberOfGlyphsLastCharacter - 1u : 0u ); + + GlyphRun underlineRun; + underlineRun.glyphIndex = glyphStart; + underlineRun.numberOfGlyphs = 1u + glyphEnd - glyphStart; + + // TODO: At the moment the underline runs are only for pre-edit. + mVisualModel->mUnderlineRuns.PushBack( underlineRun ); } } @@ -504,13 +537,16 @@ void Controller::Impl::OnTapEvent( const Event& event ) if( 1u == tapCount ) { - if( ! IsShowingPlaceholderText() ) + if( IsShowingRealText() ) { const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x; const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y; mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, yPosition ); + + // When the cursor position is changing, delay cursor blinking + mEventData->mDecorator->DelayCursorBlink(); } else { @@ -988,7 +1024,7 @@ void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart mEventData->mDecorator->AddHighlight( xPosition, offset.y, xPosition + static_cast( numberOfCharacters ) * glyphAdvance, - height ); + offset.y + height ); splitStartGlyph = false; continue; @@ -1013,14 +1049,17 @@ void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart mEventData->mDecorator->AddHighlight( xPosition, offset.y, xPosition + static_cast( interGlyphIndex ) * glyphAdvance, - height ); + offset.y + height ); splitEndGlyph = false; continue; } const float xPosition = position.x - glyph.xBearing + offset.x; - mEventData->mDecorator->AddHighlight( xPosition, offset.y, xPosition + glyph.advance, height ); + mEventData->mDecorator->AddHighlight( xPosition, + offset.y, + xPosition + glyph.advance, + offset.y + height ); } CursorInfo primaryCursorInfo; @@ -1038,6 +1077,9 @@ void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE, secondaryPosition.x, secondaryPosition.y, secondaryCursorInfo.lineHeight ); + // Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection + mEventData->mPrimaryCursorPosition = (indicesSwapped)?mEventData->mLeftSelectionPosition:mEventData->mRightSelectionPosition; + // Set the flag to update the decorator. mEventData->mDecoratorUpdated = true; } @@ -1302,10 +1344,25 @@ LineIndex Controller::Impl::GetClosestLine( float y ) const void Controller::Impl::FindSelectionIndices( float visualX, float visualY, CharacterIndex& startIndex, CharacterIndex& endIndex ) { CharacterIndex hitCharacter = GetClosestCursorIndex( visualX, visualY ); + DALI_ASSERT_DEBUG( hitCharacter <= mLogicalModel->mText.Count() && "GetClosestCursorIndex returned out of bounds index" ); + + if ( mLogicalModel->mText.Count() == 0 ) + { + return; // if model empty + } + if( hitCharacter >= mLogicalModel->mText.Count() ) { - // Selection out of bounds. - return; + // Closest hit character is the last character. + if ( hitCharacter == mLogicalModel->mText.Count() ) + { + hitCharacter--; //Hit character index set to last character in logical model + } + else + { + // hitCharacter is out of bounds + return; + } } startIndex = hitCharacter; @@ -1337,6 +1394,8 @@ void Controller::Impl::FindSelectionIndices( float visualX, float visualY, Chara CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX, float visualY ) { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "GetClosestCursorIndex %p closest visualX %f visualY %f\n", this, visualX, visualY ); + if( NULL == mEventData ) { // Nothing to do if there is no text input. @@ -1440,6 +1499,8 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX, logicalIndex = hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex; DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%p closest visualIndex %d logicalIndex %d\n", this, visualIndex, logicalIndex ); + DALI_ASSERT_DEBUG( ( logicalIndex <= mLogicalModel->mText.Count() && logicalIndex >= 0 ) && "GetClosestCursorIndex - Out of bounds index" ); + return logicalIndex; } @@ -1458,7 +1519,7 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical, cursorInfo.lineHeight = GetDefaultFontLineHeight(); cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; - cursorInfo.primaryPosition.x = 1.f; + cursorInfo.primaryPosition.x = mEventData->mDecorator->GetCursorWidth(); cursorInfo.primaryPosition.y = 0.f; // Nothing else to do. @@ -1694,7 +1755,7 @@ void Controller::Impl::UpdateCursorPosition() return; } - if( IsShowingPlaceholderText() ) + if( IsShowingPlaceholderText() || ( 0u == mLogicalModel->mText.Count() ) ) { // Do not want to use the place-holder text to set the cursor position. @@ -1727,7 +1788,7 @@ void Controller::Impl::UpdateCursorPosition() { case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: { - cursorPosition.x = 1.f; + cursorPosition.x = mEventData->mDecorator->GetCursorWidth(); break; } case LayoutEngine::HORIZONTAL_ALIGN_CENTER: @@ -1939,8 +2000,9 @@ void Controller::Impl::ScrollTextToMatchCursor() } // Set which cursors are active according the state. - if( ( EventData::EDITING == mEventData->mState ) || - ( EventData::EDITING_WITH_POPUP == mEventData->mState ) || + if( ( EventData::EDITING == mEventData->mState ) || + ( EventData::EDITING_WITH_POPUP == mEventData->mState ) || + ( EventData::EDITING_WITH_GRAB_HANDLE == mEventData->mState ) || ( EventData::GRAB_HANDLE_PANNING == mEventData->mState ) ) { if( cursorInfo.isSecondaryCursor )