- // There is no right to left characters. Clear the directions vector.
- mModel->mLogicalModel->mCharacterDirections.Clear();
- }
- updated = true;
- }
-
- Vector<GlyphInfo>& glyphs = mModel->mVisualModel->mGlyphs;
- Vector<CharacterIndex>& glyphsToCharactersMap = mModel->mVisualModel->mGlyphsToCharacters;
- Vector<Length>& charactersPerGlyph = mModel->mVisualModel->mCharactersPerGlyph;
- Vector<GlyphIndex> newParagraphGlyphs;
- newParagraphGlyphs.Reserve( numberOfParagraphs );
-
- const Length currentNumberOfGlyphs = glyphs.Count();
- if( NO_OPERATION != ( SHAPE_TEXT & operations ) )
- {
- const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
- // Shapes the text.
- ShapeText( textToShape,
- lineBreakInfo,
- scripts,
- validFonts,
- startIndex,
- mTextUpdateInfo.mStartGlyphIndex,
- requestedNumberOfCharacters,
- glyphs,
- glyphsToCharactersMap,
- charactersPerGlyph,
- newParagraphGlyphs );
-
- // Create the 'number of glyphs' per character and the glyph to character conversion tables.
- mModel->mVisualModel->CreateGlyphsPerCharacterTable( startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters );
- mModel->mVisualModel->CreateCharacterToGlyphTable( startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters );
- updated = true;
- }
-
- const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
-
- if( NO_OPERATION != ( GET_GLYPH_METRICS & operations ) )
- {
- GlyphInfo* glyphsBuffer = glyphs.Begin();
- mMetrics->GetGlyphMetrics( glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs );
-
- // Update the width and advance of all new paragraph characters.
- for( Vector<GlyphIndex>::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;
- }
- updated = true;
- }
-
- if( ( NULL != mEventData ) &&
- mEventData->mPreEditFlag &&
- ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) )
- {
- Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
- mEventData->mInputMethodContext.GetPreeditStyle( attrs );
- Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
-
- // Check the type of preedit and run it.
- for( Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++ )
- {
- Dali::InputMethodContext::PreeditAttributeData attrData = *it;
- DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex );
- type = attrData.preeditType;
-
- // Check the number of commit characters for the start position.
- unsigned int numberOfCommit = mEventData->mPrimaryCursorPosition - mEventData->mPreEditLength;
- Length numberOfIndices = attrData.endIndex - attrData.startIndex;
-
- switch( type )
- {
- case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
- {
- // Add the underline for the pre-edit text.
- GlyphRun underlineRun;
- underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
- underlineRun.numberOfGlyphs = numberOfIndices;
- mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::REVERSE:
- {
- Vector4 textColor = mModel->mVisualModel->GetTextColor();
- ColorRun backgroundColorRun;
- backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
- backgroundColorRun.color = textColor;
- mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
-
- Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor();
- Vector<ColorRun> colorRuns;
- colorRuns.Resize( 1u );
- ColorRun& colorRun = *( colorRuns.Begin() );
- colorRun.color = backgroundColor;
- colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- colorRun.characterRun.numberOfCharacters = numberOfIndices;
-
- mModel->mLogicalModel->mColorRuns.PushBack( colorRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
- {
- ColorRun backgroundColorRun;
- backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
- backgroundColorRun.color = LIGHT_BLUE;
- mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
- {
- // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
- ColorRun backgroundColorRun;
- backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
- backgroundColorRun.color = BACKGROUND_SUB4;
- mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
-
- GlyphRun underlineRun;
- underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
- underlineRun.numberOfGlyphs = numberOfIndices;
- mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
- {
- // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
- ColorRun backgroundColorRun;
- backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
- backgroundColorRun.color = BACKGROUND_SUB5;
- mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
-
- GlyphRun underlineRun;
- underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
- underlineRun.numberOfGlyphs = numberOfIndices;
- mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
- {
- // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
- ColorRun backgroundColorRun;
- backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
- backgroundColorRun.color = BACKGROUND_SUB6;
- mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
-
- GlyphRun underlineRun;
- underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
- underlineRun.numberOfGlyphs = numberOfIndices;
- mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
- {
- // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
- ColorRun backgroundColorRun;
- backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
- backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
- backgroundColorRun.color = BACKGROUND_SUB7;
- mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
-
- GlyphRun underlineRun;
- underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
- underlineRun.numberOfGlyphs = numberOfIndices;
- mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
- break;
- }
- case Dali::InputMethodContext::PreeditStyle::NONE:
- default:
- {
- break;
- }
- }
- }
- attrs.Clear();
- updated = true;
- }
-
- if( NO_OPERATION != ( COLOR & operations ) )
- {
- // Set the color runs in glyphs.
- SetColorSegmentationInfo( mModel->mLogicalModel->mColorRuns,
- mModel->mVisualModel->mCharactersToGlyph,
- mModel->mVisualModel->mGlyphsPerCharacter,
- startIndex,
- mTextUpdateInfo.mStartGlyphIndex,
- requestedNumberOfCharacters,
- mModel->mVisualModel->mColors,
- mModel->mVisualModel->mColorIndices );
-
- // Set the background color runs in glyphs.
- SetColorSegmentationInfo( mModel->mLogicalModel->mBackgroundColorRuns,
- mModel->mVisualModel->mCharactersToGlyph,
- mModel->mVisualModel->mGlyphsPerCharacter,
- startIndex,
- mTextUpdateInfo.mStartGlyphIndex,
- requestedNumberOfCharacters,
- mModel->mVisualModel->mBackgroundColors,
- mModel->mVisualModel->mBackgroundColorIndices );
-
- updated = true;
- }
-
-
- // The estimated number of lines. Used to avoid reallocations when layouting.
- mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count() );
-
- // Set the previous number of characters for the next time the text is updated.
- mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
-
- return updated;
-}
-
-void Controller::Impl::RetrieveDefaultInputStyle( InputStyle& inputStyle )
-{
- // Sets the default text's color.
- inputStyle.textColor = mTextColor;
- inputStyle.isDefaultColor = true;
-
- inputStyle.familyName.clear();
- inputStyle.weight = TextAbstraction::FontWeight::NORMAL;
- inputStyle.width = TextAbstraction::FontWidth::NORMAL;
- inputStyle.slant = TextAbstraction::FontSlant::NORMAL;
- inputStyle.size = 0.f;
-
- inputStyle.lineSpacing = 0.f;
-
- inputStyle.underlineProperties.clear();
- inputStyle.shadowProperties.clear();
- inputStyle.embossProperties.clear();
- inputStyle.outlineProperties.clear();
-
- inputStyle.isFamilyDefined = false;
- inputStyle.isWeightDefined = false;
- inputStyle.isWidthDefined = false;
- inputStyle.isSlantDefined = false;
- inputStyle.isSizeDefined = false;
-
- inputStyle.isLineSpacingDefined = false;
-
- inputStyle.isUnderlineDefined = false;
- inputStyle.isShadowDefined = false;
- inputStyle.isEmbossDefined = false;
- inputStyle.isOutlineDefined = false;
-
- // Sets the default font's family name, weight, width, slant and size.
- if( mFontDefaults )
- {
- if( mFontDefaults->familyDefined )
- {
- inputStyle.familyName = mFontDefaults->mFontDescription.family;
- inputStyle.isFamilyDefined = true;
- }
-
- if( mFontDefaults->weightDefined )
- {
- inputStyle.weight = mFontDefaults->mFontDescription.weight;
- inputStyle.isWeightDefined = true;
- }
-
- if( mFontDefaults->widthDefined )
- {
- inputStyle.width = mFontDefaults->mFontDescription.width;
- inputStyle.isWidthDefined = true;
- }
-
- if( mFontDefaults->slantDefined )
- {
- inputStyle.slant = mFontDefaults->mFontDescription.slant;
- inputStyle.isSlantDefined = true;
- }
-
- if( mFontDefaults->sizeDefined )
- {
- inputStyle.size = mFontDefaults->mDefaultPointSize;
- inputStyle.isSizeDefined = true;
- }
- }
-}
-
-float Controller::Impl::GetDefaultFontLineHeight()
-{
- FontId defaultFontId = 0u;
- if( NULL == mFontDefaults )
- {
- TextAbstraction::FontDescription fontDescription;
- defaultFontId = mFontClient.GetFontId( fontDescription );
- }
- else
- {
- defaultFontId = mFontDefaults->GetFontId( mFontClient );
- }
-
- Text::FontMetrics fontMetrics;
- mMetrics->GetFontMetrics( defaultFontId, fontMetrics );
-
- return( fontMetrics.ascender - fontMetrics.descender );
-}
-
-void Controller::Impl::OnCursorKeyEvent( const Event& event )
-{
- if( NULL == mEventData || !IsShowingRealText() )
- {
- // Nothing to do if there is no text input.
- return;
- }
-
- int keyCode = event.p1.mInt;
- bool isShiftModifier = event.p2.mBool;
-
- CharacterIndex previousPrimaryCursorPosition = mEventData->mPrimaryCursorPosition;
-
- if( Dali::DALI_KEY_CURSOR_LEFT == keyCode )
- {
- if( mEventData->mPrimaryCursorPosition > 0u )
- {
- if ( !isShiftModifier && mEventData->mDecorator->IsHighlightVisible() )
- {
- mEventData->mPrimaryCursorPosition = std::min(mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
- }
- else
- {
- mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition - 1u );
- }
- }
- }
- else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
- {
- if( mModel->mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition )
- {
- if ( !isShiftModifier && mEventData->mDecorator->IsHighlightVisible() )
- {
- mEventData->mPrimaryCursorPosition = std::max(mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
- }
- else
- {
- mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition );
- }
- }
- }
- else if( Dali::DALI_KEY_CURSOR_UP == keyCode && !isShiftModifier )
- {
- // Ignore Shift-Up for text selection for now.
-
- // Get first the line index of the current cursor position index.
- CharacterIndex characterIndex = 0u;
-
- if( mEventData->mPrimaryCursorPosition > 0u )
- {
- characterIndex = mEventData->mPrimaryCursorPosition - 1u;
- }
-
- const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( characterIndex );
- const LineIndex previousLineIndex = ( lineIndex > 0 ? lineIndex - 1u : lineIndex );
-
- // Retrieve the cursor position info.
- CursorInfo cursorInfo;
- GetCursorPosition( mEventData->mPrimaryCursorPosition,
- cursorInfo );
-
- // Get the line above.
- const LineRun& line = *( mModel->mVisualModel->mLines.Begin() + previousLineIndex );
-
- // Get the next hit 'y' point.
- const float hitPointY = cursorInfo.lineOffset - 0.5f * ( line.ascender - line.descender );
-
- // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
- bool matchedCharacter = false;
- mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
- mModel->mLogicalModel,
- mMetrics,
- mEventData->mCursorHookPositionX,
- hitPointY,
- CharacterHitTest::TAP,
- matchedCharacter );
- }
- else if( Dali::DALI_KEY_CURSOR_DOWN == keyCode && !isShiftModifier )
- {
- // Ignore Shift-Down for text selection for now.
-
- // Get first the line index of the current cursor position index.
- CharacterIndex characterIndex = 0u;
-
- if( mEventData->mPrimaryCursorPosition > 0u )
- {
- characterIndex = mEventData->mPrimaryCursorPosition - 1u;
- }
-
- const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( characterIndex );
-
- if( lineIndex + 1u < mModel->mVisualModel->mLines.Count() )
- {
- // Retrieve the cursor position info.
- CursorInfo cursorInfo;
- GetCursorPosition( mEventData->mPrimaryCursorPosition,
- cursorInfo );
-
- // Get the line below.
- const LineRun& line = *( mModel->mVisualModel->mLines.Begin() + lineIndex + 1u );
-
- // Get the next hit 'y' point.
- const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * ( line.ascender - line.descender );
-
- // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
- bool matchedCharacter = false;
- mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
- mModel->mLogicalModel,
- mMetrics,
- mEventData->mCursorHookPositionX,
- hitPointY,
- CharacterHitTest::TAP,
- matchedCharacter );
- }
- }
-
- if ( !isShiftModifier && mEventData->mState != EventData::SELECTING )
- {
- // Update selection position after moving the cursor
- mEventData->mLeftSelectionPosition = mEventData->mPrimaryCursorPosition;
- mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
- }
-
- if ( isShiftModifier && IsShowingRealText() && mEventData->mShiftSelectionFlag )
- {
- // Handle text selection
- bool selecting = false;
-
- if ( Dali::DALI_KEY_CURSOR_LEFT == keyCode || Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
- {
- // Shift-Left/Right to select the text
- int cursorPositionDelta = mEventData->mPrimaryCursorPosition - previousPrimaryCursorPosition;
- if ( cursorPositionDelta > 0 || mEventData->mRightSelectionPosition > 0u ) // Check the boundary
- {
- mEventData->mRightSelectionPosition += cursorPositionDelta;
- }
- selecting = true;
- }
- else if ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition )
- {
- // Show no grab handles and text highlight if Shift-Up/Down pressed but no selected text
- selecting = true;
- }
-
- if ( selecting )
- {
- // Notify the cursor position to the InputMethodContext.
- if( mEventData->mInputMethodContext )
- {
- mEventData->mInputMethodContext.SetCursorPosition( mEventData->mPrimaryCursorPosition );
- mEventData->mInputMethodContext.NotifyCursorPosition();
- }
-
- ChangeState( EventData::SELECTING );
-
- mEventData->mUpdateLeftSelectionPosition = true;