+ if( 0u != mModel->mLogicalModel->mBidirectionalParagraphInfo.Count() )
+ {
+ if( NO_OPERATION != ( BIDI_INFO & operations ) )
+ {
+ // Clear the bidirectional paragraph info.
+ ClearCharacterRuns( startIndex,
+ endIndex,
+ mModel->mLogicalModel->mBidirectionalParagraphInfo );
+
+ // Clear the character's directions.
+ CharacterDirection* characterDirectionsBuffer = mModel->mLogicalModel->mCharacterDirections.Begin();
+
+ mModel->mLogicalModel->mCharacterDirections.Erase( characterDirectionsBuffer + startIndex,
+ characterDirectionsBuffer + endIndexPlusOne );
+ }
+
+ if( NO_OPERATION != ( REORDER & operations ) )
+ {
+ uint32_t startRemoveIndex = mModel->mLogicalModel->mBidirectionalLineInfo.Count();
+ uint32_t endRemoveIndex = startRemoveIndex;
+ ClearCharacterRuns( startIndex,
+ endIndex,
+ mModel->mLogicalModel->mBidirectionalLineInfo,
+ startRemoveIndex,
+ endRemoveIndex );
+
+ BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = mModel->mLogicalModel->mBidirectionalLineInfo.Begin();
+
+ // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+ for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfoBuffer + startRemoveIndex,
+ endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
+ it != endIt;
+ ++it )
+ {
+ BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+ free( bidiLineInfo.visualToLogicalMap );
+ bidiLineInfo.visualToLogicalMap = NULL;
+ }
+
+ mModel->mLogicalModel->mBidirectionalLineInfo.Erase( bidirectionalLineInfoBuffer + startRemoveIndex,
+ bidirectionalLineInfoBuffer + endRemoveIndex );
+ }
+ }
+}
+
+void Controller::Impl::ClearGlyphModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations )
+{
+ const CharacterIndex endIndexPlusOne = endIndex + 1u;
+ const Length numberOfCharactersRemoved = endIndexPlusOne - startIndex;
+
+ // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
+ GlyphIndex* charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
+ Length* glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
+
+ const GlyphIndex endGlyphIndexPlusOne = *( charactersToGlyphBuffer + endIndex ) + *( glyphsPerCharacterBuffer + endIndex );
+ const Length numberOfGlyphsRemoved = endGlyphIndexPlusOne - mTextUpdateInfo.mStartGlyphIndex;
+
+ if( NO_OPERATION != ( SHAPE_TEXT & operations ) )
+ {
+ // Update the character to glyph indices.
+ for( Vector<GlyphIndex>::Iterator it = charactersToGlyphBuffer + endIndexPlusOne,
+ endIt = charactersToGlyphBuffer + mModel->mVisualModel->mCharactersToGlyph.Count();
+ it != endIt;
+ ++it )
+ {
+ CharacterIndex& index = *it;
+ index -= numberOfGlyphsRemoved;
+ }
+
+ // Clear the character to glyph conversion table.
+ mModel->mVisualModel->mCharactersToGlyph.Erase( charactersToGlyphBuffer + startIndex,
+ charactersToGlyphBuffer + endIndexPlusOne );
+
+ // Clear the glyphs per character table.
+ mModel->mVisualModel->mGlyphsPerCharacter.Erase( glyphsPerCharacterBuffer + startIndex,
+ glyphsPerCharacterBuffer + endIndexPlusOne );
+
+ // Clear the glyphs buffer.
+ GlyphInfo* glyphsBuffer = mModel->mVisualModel->mGlyphs.Begin();
+ mModel->mVisualModel->mGlyphs.Erase( glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex,
+ glyphsBuffer + endGlyphIndexPlusOne );
+
+ CharacterIndex* glyphsToCharactersBuffer = mModel->mVisualModel->mGlyphsToCharacters.Begin();
+
+ // Update the glyph to character indices.
+ for( Vector<CharacterIndex>::Iterator it = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
+ endIt = glyphsToCharactersBuffer + mModel->mVisualModel->mGlyphsToCharacters.Count();
+ it != endIt;
+ ++it )
+ {
+ CharacterIndex& index = *it;
+ index -= numberOfCharactersRemoved;
+ }
+
+ // Clear the glyphs to characters buffer.
+ mModel->mVisualModel->mGlyphsToCharacters.Erase( glyphsToCharactersBuffer + mTextUpdateInfo.mStartGlyphIndex,
+ glyphsToCharactersBuffer + endGlyphIndexPlusOne );
+
+ // Clear the characters per glyph buffer.
+ Length* charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
+ mModel->mVisualModel->mCharactersPerGlyph.Erase( charactersPerGlyphBuffer + mTextUpdateInfo.mStartGlyphIndex,
+ charactersPerGlyphBuffer + endGlyphIndexPlusOne );
+
+ // Clear the positions buffer.
+ Vector2* positionsBuffer = mModel->mVisualModel->mGlyphPositions.Begin();
+ mModel->mVisualModel->mGlyphPositions.Erase( positionsBuffer + mTextUpdateInfo.mStartGlyphIndex,
+ positionsBuffer + endGlyphIndexPlusOne );
+ }
+
+ if( NO_OPERATION != ( LAYOUT & operations ) )
+ {
+ // Clear the lines.
+ uint32_t startRemoveIndex = mModel->mVisualModel->mLines.Count();
+ uint32_t endRemoveIndex = startRemoveIndex;
+ ClearCharacterRuns( startIndex,
+ endIndex,
+ mModel->mVisualModel->mLines,
+ startRemoveIndex,
+ endRemoveIndex );
+
+ // Will update the glyph runs.
+ startRemoveIndex = mModel->mVisualModel->mLines.Count();
+ endRemoveIndex = startRemoveIndex;
+ ClearGlyphRuns( mTextUpdateInfo.mStartGlyphIndex,
+ endGlyphIndexPlusOne - 1u,
+ mModel->mVisualModel->mLines,
+ startRemoveIndex,
+ endRemoveIndex );
+
+ // Set the line index from where to insert the new laid-out lines.
+ mTextUpdateInfo.mStartLineIndex = startRemoveIndex;
+
+ LineRun* linesBuffer = mModel->mVisualModel->mLines.Begin();
+ mModel->mVisualModel->mLines.Erase( linesBuffer + startRemoveIndex,
+ linesBuffer + endRemoveIndex );
+ }
+
+ if( NO_OPERATION != ( COLOR & operations ) )
+ {
+ if( 0u != mModel->mVisualModel->mColorIndices.Count() )
+ {
+ ColorIndex* colorIndexBuffer = mModel->mVisualModel->mColorIndices.Begin();
+ mModel->mVisualModel->mColorIndices.Erase( colorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
+ colorIndexBuffer + endGlyphIndexPlusOne );
+ }
+ }
+}
+
+void Controller::Impl::ClearModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations )
+{
+ if( mTextUpdateInfo.mClearAll ||
+ ( ( 0u == startIndex ) &&
+ ( mTextUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u ) ) )
+ {
+ ClearFullModelData( operations );
+ }
+ else
+ {
+ // Clear the model data related with characters.
+ ClearCharacterModelData( startIndex, endIndex, operations );
+
+ // Clear the model data related with glyphs.
+ ClearGlyphModelData( startIndex, endIndex, operations );
+ }
+
+ // The estimated number of lines. Used to avoid reallocations when layouting.
+ mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count() );
+
+ mModel->mVisualModel->ClearCaches();
+}
+
+bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::UpdateModel\n" );
+
+ // Calculate the operations to be done.
+ const OperationsMask operations = static_cast<OperationsMask>( mOperationsPending & operationsRequired );
+
+ if( NO_OPERATION == operations )
+ {
+ // Nothing to do if no operations are pending and required.
+ return false;
+ }
+
+ Vector<Character>& srcCharacters = mModel->mLogicalModel->mText;
+ Vector<Character> displayCharacters;
+ bool useHiddenText = false;
+ if ( mHiddenInput && mEventData != NULL && !mEventData->mIsShowingPlaceholderText)
+ {
+ mHiddenInput->Substitute( srcCharacters,displayCharacters );
+ useHiddenText = true;
+ }
+
+ Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
+ const Length numberOfCharacters = utf32Characters.Count();
+
+ // Index to the first character of the first paragraph to be updated.
+ CharacterIndex startIndex = 0u;
+ // Number of characters of the paragraphs to be removed.
+ Length paragraphCharacters = 0u;
+
+ CalculateTextUpdateIndices( paragraphCharacters );
+
+ // Check whether the indices for updating the text is valid
+ if ( numberOfCharacters > 0u &&
+ ( mTextUpdateInfo.mParagraphCharacterIndex >= numberOfCharacters ||
+ mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters ) )
+ {
+ std::string currentText;
+ Utf32ToUtf8( mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText );
+
+ DALI_LOG_ERROR( "Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n" );
+ DALI_LOG_ERROR( "Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str() );
+
+ // Dump mTextUpdateInfo
+ DALI_LOG_ERROR( "Dump mTextUpdateInfo:\n" );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mCharacterIndex = %u\n", mTextUpdateInfo.mCharacterIndex );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", mTextUpdateInfo.mNumberOfCharactersToRemove );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", mTextUpdateInfo.mNumberOfCharactersToAdd );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", mTextUpdateInfo.mPreviousNumberOfCharacters );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mParagraphCharacterIndex = %u\n", mTextUpdateInfo.mParagraphCharacterIndex );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", mTextUpdateInfo.mRequestedNumberOfCharacters );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mStartGlyphIndex = %u\n", mTextUpdateInfo.mStartGlyphIndex );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mStartLineIndex = %u\n", mTextUpdateInfo.mStartLineIndex );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", mTextUpdateInfo.mEstimatedNumberOfLines );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mClearAll = %d\n", mTextUpdateInfo.mClearAll );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mFullRelayoutNeeded = %d\n", mTextUpdateInfo.mFullRelayoutNeeded );
+ DALI_LOG_ERROR( " mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", mTextUpdateInfo.mIsLastCharacterNewParagraph );
+
+ return false;
+ }
+
+ startIndex = mTextUpdateInfo.mParagraphCharacterIndex;
+
+ if( mTextUpdateInfo.mClearAll ||
+ ( 0u != paragraphCharacters ) )
+ {
+ ClearModelData( startIndex, startIndex + ( ( paragraphCharacters > 0u ) ? paragraphCharacters - 1u : 0u ), operations );
+ }
+
+ mTextUpdateInfo.mClearAll = false;
+
+ // Whether the model is updated.
+ bool updated = false;
+
+ Vector<LineBreakInfo>& lineBreakInfo = mModel->mLogicalModel->mLineBreakInfo;
+ const Length requestedNumberOfCharacters = mTextUpdateInfo.mRequestedNumberOfCharacters;
+
+ if( NO_OPERATION != ( GET_LINE_BREAKS & operations ) )
+ {
+ // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
+ // calculate the bidirectional info for each 'paragraph'.
+ // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
+ // is not shaped together).
+ lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK );
+
+ SetLineBreakInfo( utf32Characters,
+ startIndex,
+ requestedNumberOfCharacters,
+ lineBreakInfo );
+
+ // Create the paragraph info.
+ mModel->mLogicalModel->CreateParagraphInfo( startIndex,
+ requestedNumberOfCharacters );
+ updated = true;
+ }
+
+ Vector<WordBreakInfo>& wordBreakInfo = mModel->mLogicalModel->mWordBreakInfo;
+ if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
+ {
+ // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
+ wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK );
+
+ SetWordBreakInfo( utf32Characters,
+ startIndex,
+ requestedNumberOfCharacters,
+ wordBreakInfo );
+ updated = true;
+ }
+
+ const bool getScripts = NO_OPERATION != ( GET_SCRIPTS & operations );
+ const bool validateFonts = NO_OPERATION != ( VALIDATE_FONTS & operations );
+
+ Vector<ScriptRun>& scripts = mModel->mLogicalModel->mScriptRuns;
+ Vector<FontRun>& validFonts = mModel->mLogicalModel->mFontRuns;
+
+ if( getScripts || validateFonts )
+ {
+ // Validates the fonts assigned by the application or assigns default ones.
+ // It makes sure all the characters are going to be rendered by the correct font.
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+ if( getScripts )
+ {
+ // Retrieves the scripts used in the text.
+ multilanguageSupport.SetScripts( utf32Characters,
+ startIndex,
+ requestedNumberOfCharacters,
+ scripts );
+ }
+
+ if( validateFonts )
+ {
+ // Validate the fonts set through the mark-up string.
+ Vector<FontDescriptionRun>& fontDescriptionRuns = mModel->mLogicalModel->mFontDescriptionRuns;
+
+ // Get the default font's description.
+ TextAbstraction::FontDescription defaultFontDescription;
+ TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
+
+ if( IsShowingPlaceholderText() && mEventData && ( NULL != mEventData->mPlaceholderFont ) )
+ {
+ // If the placeholder font is set specifically, only placeholder font is changed.
+ defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription;
+ if( mEventData->mPlaceholderFont->sizeDefined )
+ {
+ defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * 64u;
+ }
+ }
+ else if( NULL != mFontDefaults )
+ {
+ // Set the normal font and the placeholder font.
+ defaultFontDescription = mFontDefaults->mFontDescription;
+ defaultPointSize = mFontDefaults->mDefaultPointSize * 64u;
+ }
+
+ // Validates the fonts. If there is a character with no assigned font it sets a default one.
+ // After this call, fonts are validated.
+ multilanguageSupport.ValidateFonts( utf32Characters,
+ scripts,
+ fontDescriptionRuns,
+ defaultFontDescription,
+ defaultPointSize,
+ startIndex,
+ requestedNumberOfCharacters,
+ validFonts );
+ }
+ updated = true;
+ }
+
+ Vector<Character> mirroredUtf32Characters;
+ bool textMirrored = false;
+ const Length numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count();
+ if( NO_OPERATION != ( BIDI_INFO & operations ) )
+ {
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mModel->mLogicalModel->mBidirectionalParagraphInfo;
+ bidirectionalInfo.Reserve( numberOfParagraphs );
+
+ // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
+ SetBidirectionalInfo( utf32Characters,
+ scripts,
+ lineBreakInfo,
+ startIndex,
+ requestedNumberOfCharacters,
+ bidirectionalInfo );
+
+ if( 0u != bidirectionalInfo.Count() )
+ {
+ // Only set the character directions if there is right to left characters.
+ Vector<CharacterDirection>& directions = mModel->mLogicalModel->mCharacterDirections;
+ GetCharactersDirection( bidirectionalInfo,
+ numberOfCharacters,
+ startIndex,
+ requestedNumberOfCharacters,
+ directions );
+
+ // 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,
+ directions,
+ bidirectionalInfo,
+ startIndex,
+ requestedNumberOfCharacters,
+ mirroredUtf32Characters );
+ }
+ else
+ {
+ // 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( 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 );
+
+ updated = true;
+ }
+
+ if( ( NULL != mEventData ) &&
+ mEventData->mPreEditFlag &&
+ ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) )
+ {
+ // Add the underline for the pre-edit text.
+ const GlyphIndex* const charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
+ const Length* const glyphsPerCharacterBuffer = mModel->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.
+ mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+ }
+
+ // 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 );