X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller.cpp;h=153a36ca9f3633d51f7a04b160e4bc0b13b3166d;hp=f22278a6897255a556119e80c68120a1d068a2e3;hb=834452d5624e8c11d8cb3b8a31bdbafe3e47351f;hpb=bd0b6d9d85d1e484aad8e96b0de89c494f013827 diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index f22278a..153a36c 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include #include #include #include @@ -42,7 +43,6 @@ const float MAX_FLOAT = std::numeric_limits::max(); const unsigned int POINTS_PER_INCH = 72; const std::string EMPTY_STRING(""); -const unsigned int ZERO = 0u; float ConvertToEven( float value ) { @@ -61,6 +61,39 @@ namespace Toolkit namespace Text { +/** + * @brief Adds a new font description run for the selected text. + * + * The new font parameters are added after the call to this method. + * + * @param[in] eventData The event data pointer. + * @param[in] logicalModel The logical model where to add the new font description run. + */ +FontDescriptionRun& UpdateSelectionFontStyleRun( EventData* eventData, + LogicalModelPtr logicalModel ) +{ + const bool handlesCrossed = eventData->mLeftSelectionPosition > eventData->mRightSelectionPosition; + + // Get start and end position of selection + const CharacterIndex startOfSelectedText = handlesCrossed ? eventData->mRightSelectionPosition : eventData->mLeftSelectionPosition; + const Length lengthOfSelectedText = ( handlesCrossed ? eventData->mLeftSelectionPosition : eventData->mRightSelectionPosition ) - startOfSelectedText; + + // Add the font run. + const VectorBase::SizeType numberOfRuns = logicalModel->mFontDescriptionRuns.Count(); + logicalModel->mFontDescriptionRuns.Resize( numberOfRuns + 1u ); + + FontDescriptionRun& fontDescriptionRun = *( logicalModel->mFontDescriptionRuns.Begin() + numberOfRuns ); + + fontDescriptionRun.characterRun.characterIndex = startOfSelectedText; + fontDescriptionRun.characterRun.numberOfCharacters = lengthOfSelectedText; + + // Recalculate the selection highlight as the metrics may have changed. + eventData->mUpdateLeftSelectionPosition = true; + eventData->mUpdateRightSelectionPosition = true; + + return fontDescriptionRun; +} + ControllerPtr Controller::New( ControlInterface& controlInterface ) { return ControllerPtr( new Controller( controlInterface ) ); @@ -113,7 +146,8 @@ void Controller::SetText( const std::string& text ) if( !text.empty() ) { - MarkupProcessData markupProcessData( mImpl->mLogicalModel->mColorRuns ); + MarkupProcessData markupProcessData( mImpl->mLogicalModel->mColorRuns, + mImpl->mLogicalModel->mFontDescriptionRuns ); Length textSize = 0u; const uint8_t* utf8 = NULL; @@ -247,12 +281,9 @@ void Controller::GetPlaceholderText( PlaceholderType type, std::string& text ) c } } -void Controller::SetMaximumNumberOfCharacters( int maxCharacters ) +void Controller::SetMaximumNumberOfCharacters( Length maxCharacters ) { - if( maxCharacters >= 0 ) - { - mImpl->mMaximumNumberOfCharacters = maxCharacters; - } + mImpl->mMaximumNumberOfCharacters = maxCharacters; } int Controller::GetMaximumNumberOfCharacters() @@ -269,7 +300,7 @@ void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily ) mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily; DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str()); - mImpl->mUserDefinedFontFamily = true; + mImpl->mFontDefaults->familyDefined = true; // Clear the font-specific data ClearFontData(); @@ -310,14 +341,15 @@ const std::string& Controller::GetDefaultFontStyle() const return EMPTY_STRING; } -void Controller::SetDefaultFontWidth( FontWidth width ) +void Controller::SetDefaultFontWeight( FontWeight weight ) { if( NULL == mImpl->mFontDefaults ) { mImpl->mFontDefaults = new FontDefaults(); } - mImpl->mFontDefaults->mFontDescription.width = width; + mImpl->mFontDefaults->mFontDescription.weight = weight; + mImpl->mFontDefaults->weightDefined = true; // Clear the font-specific data ClearFontData(); @@ -328,24 +360,25 @@ void Controller::SetDefaultFontWidth( FontWidth width ) mImpl->RequestRelayout(); } -FontWidth Controller::GetDefaultFontWidth() const +FontWeight Controller::GetDefaultFontWeight() const { if( NULL != mImpl->mFontDefaults ) { - return mImpl->mFontDefaults->mFontDescription.width; + return mImpl->mFontDefaults->mFontDescription.weight; } - return TextAbstraction::FontWidth::NORMAL; + return TextAbstraction::FontWeight::NORMAL; } -void Controller::SetDefaultFontWeight( FontWeight weight ) +void Controller::SetDefaultFontWidth( FontWidth width ) { if( NULL == mImpl->mFontDefaults ) { mImpl->mFontDefaults = new FontDefaults(); } - mImpl->mFontDefaults->mFontDescription.weight = weight; + mImpl->mFontDefaults->mFontDescription.width = width; + mImpl->mFontDefaults->widthDefined = true; // Clear the font-specific data ClearFontData(); @@ -356,14 +389,14 @@ void Controller::SetDefaultFontWeight( FontWeight weight ) mImpl->RequestRelayout(); } -FontWeight Controller::GetDefaultFontWeight() const +FontWidth Controller::GetDefaultFontWidth() const { if( NULL != mImpl->mFontDefaults ) { - return mImpl->mFontDefaults->mFontDescription.weight; + return mImpl->mFontDefaults->mFontDescription.width; } - return TextAbstraction::FontWeight::NORMAL; + return TextAbstraction::FontWidth::NORMAL; } void Controller::SetDefaultFontSlant( FontSlant slant ) @@ -374,6 +407,7 @@ void Controller::SetDefaultFontSlant( FontSlant slant ) } mImpl->mFontDefaults->mFontDescription.slant = slant; + mImpl->mFontDefaults->slantDefined = true; // Clear the font-specific data ClearFontData(); @@ -402,6 +436,7 @@ void Controller::SetDefaultPointSize( float pointSize ) } mImpl->mFontDefaults->mDefaultPointSize = pointSize; + mImpl->mFontDefaults->sizeDefined = true; unsigned int horizontalDpi( 0u ); unsigned int verticalDpi( 0u ); @@ -435,7 +470,7 @@ void Controller::UpdateAfterFontChange( std::string& newDefaultFont ) { DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange"); - if( !mImpl->mUserDefinedFontFamily ) // If user defined font then should not update when system font changes + if( !mImpl->mFontDefaults->familyDefined ) // If user defined font then should not update when system font changes { DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str() ); ClearFontData(); @@ -651,6 +686,220 @@ const Vector4& Controller::GetInputColor() const } +void Controller::SetInputFontFamily( const std::string& fontFamily ) +{ + if( NULL != mImpl->mEventData ) + { + mImpl->mEventData->mInputStyle.familyName = fontFamily; + mImpl->mEventData->mInputStyle.familyDefined = true; + + if( EventData::SELECTING == mImpl->mEventData->mState ) + { + FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData, + mImpl->mLogicalModel ); + + fontDescriptionRun.familyLength = fontFamily.size(); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyDefined = true; + + // The memory allocated for the font family name is freed when the font description is removed from the logical model. + + // Request to relayout. + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + mImpl->RequestRelayout(); + + // As the font changes, recalculate the handle positions is needed. + mImpl->mEventData->mUpdateLeftSelectionPosition = true; + mImpl->mEventData->mUpdateRightSelectionPosition = true; + mImpl->mEventData->mScrollAfterUpdatePosition = true; + } + } +} + +const std::string& Controller::GetInputFontFamily() const +{ + if( NULL != mImpl->mEventData ) + { + return mImpl->mEventData->mInputStyle.familyName; + } + + // Return the default font's family if there is no EventData. + return GetDefaultFontFamily(); +} + +void Controller::SetInputFontStyle( const std::string& fontStyle ) +{ + if( NULL != mImpl->mEventData ) + { + mImpl->mEventData->mInputStyle.fontStyle = fontStyle; + } +} + +const std::string& Controller::GetInputFontStyle() const +{ + if( NULL != mImpl->mEventData ) + { + return mImpl->mEventData->mInputStyle.fontStyle; + } + + // Return the default font's style if there is no EventData. + return GetDefaultFontStyle(); +} + +void Controller::SetInputFontWeight( FontWeight weight ) +{ + if( NULL != mImpl->mEventData ) + { + mImpl->mEventData->mInputStyle.weight = weight; + mImpl->mEventData->mInputStyle.weightDefined = true; + + if( EventData::SELECTING == mImpl->mEventData->mState ) + { + FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData, + mImpl->mLogicalModel ); + + fontDescriptionRun.weight = weight; + fontDescriptionRun.weightDefined = true; + + // Request to relayout. + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + mImpl->RequestRelayout(); + + // As the font might change, recalculate the handle positions is needed. + mImpl->mEventData->mUpdateLeftSelectionPosition = true; + mImpl->mEventData->mUpdateRightSelectionPosition = true; + mImpl->mEventData->mScrollAfterUpdatePosition = true; + } + } +} + +FontWeight Controller::GetInputFontWeight() const +{ + if( NULL != mImpl->mEventData ) + { + return mImpl->mEventData->mInputStyle.weight; + } + + return GetDefaultFontWeight(); +} + +void Controller::SetInputFontWidth( FontWidth width ) +{ + if( NULL != mImpl->mEventData ) + { + mImpl->mEventData->mInputStyle.width = width; + mImpl->mEventData->mInputStyle.widthDefined = true; + + if( EventData::SELECTING == mImpl->mEventData->mState ) + { + FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData, + mImpl->mLogicalModel ); + + fontDescriptionRun.width = width; + fontDescriptionRun.widthDefined = true; + + // Request to relayout. + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + mImpl->RequestRelayout(); + + // As the font might change, recalculate the handle positions is needed. + mImpl->mEventData->mUpdateLeftSelectionPosition = true; + mImpl->mEventData->mUpdateRightSelectionPosition = true; + mImpl->mEventData->mScrollAfterUpdatePosition = true; + } + } +} + +FontWidth Controller::GetInputFontWidth() const +{ + if( NULL != mImpl->mEventData ) + { + return mImpl->mEventData->mInputStyle.width; + } + + return GetDefaultFontWidth(); +} + +void Controller::SetInputFontSlant( FontSlant slant ) +{ + if( NULL != mImpl->mEventData ) + { + mImpl->mEventData->mInputStyle.slant = slant; + mImpl->mEventData->mInputStyle.slantDefined = true; + + if( EventData::SELECTING == mImpl->mEventData->mState ) + { + FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData, + mImpl->mLogicalModel ); + + fontDescriptionRun.slant = slant; + fontDescriptionRun.slantDefined = true; + + // Request to relayout. + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + mImpl->RequestRelayout(); + + // As the font might change, recalculate the handle positions is needed. + mImpl->mEventData->mUpdateLeftSelectionPosition = true; + mImpl->mEventData->mUpdateRightSelectionPosition = true; + mImpl->mEventData->mScrollAfterUpdatePosition = true; + } + } +} + +FontSlant Controller::GetInputFontSlant() const +{ + if( NULL != mImpl->mEventData ) + { + return mImpl->mEventData->mInputStyle.slant; + } + + return GetDefaultFontSlant(); +} + +void Controller::SetInputFontPointSize( float size ) +{ + if( NULL != mImpl->mEventData ) + { + mImpl->mEventData->mInputStyle.size = size; + + if( EventData::SELECTING == mImpl->mEventData->mState ) + { + FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData, + mImpl->mLogicalModel ); + + fontDescriptionRun.size = static_cast( size * 64.f ); + fontDescriptionRun.sizeDefined = true; + + // Request to relayout. + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + mImpl->RequestRelayout(); + + // As the font might change, recalculate the handle positions is needed. + mImpl->mEventData->mUpdateLeftSelectionPosition = true; + mImpl->mEventData->mUpdateRightSelectionPosition = true; + mImpl->mEventData->mScrollAfterUpdatePosition = true; + } + } +} + +float Controller::GetInputFontPointSize() const +{ + if( NULL != mImpl->mEventData ) + { + return mImpl->mEventData->mInputStyle.size; + } + + // Return the default font's point size if there is no EventData. + return GetDefaultPointSize(); +} + void Controller::SetEnableCursorBlink( bool enable ) { DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "TextInput disabled" ); @@ -791,7 +1040,7 @@ float Controller::GetHeightForWidth( float width ) } else { - layoutSize = mImpl->mVisualModel->GetActualSize(); + layoutSize = mImpl->mVisualModel->GetLayoutSize(); DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height ); } @@ -815,6 +1064,7 @@ bool Controller::Relayout( const Size& size ) return glyphsRemoved; } + // Whether a new size has been set. const bool newSize = ( size != mImpl->mVisualModel->mControlSize ); if( newSize ) @@ -1077,6 +1327,11 @@ bool Controller::DoRelayout( const Size& size, if( 0u == numberOfGlyphs ) { + if( UPDATE_ACTUAL_SIZE & operations ) + { + mImpl->mVisualModel->SetLayoutSize( Size::ZERO ); + } + // Nothing else to do if there is no glyphs. DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout no glyphs, view updated true\n" ); return true; @@ -1089,6 +1344,8 @@ bool Controller::DoRelayout( const Size& size, const Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; const Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; const Character* const textBuffer = mImpl->mLogicalModel->mText.Begin(); + const Vector& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter; // Set the layout parameters. LayoutParameters layoutParameters( size, @@ -1096,10 +1353,12 @@ bool Controller::DoRelayout( const Size& size, lineBreakInfo.Begin(), wordBreakInfo.Begin(), ( 0u != characterDirection.Count() ) ? characterDirection.Begin() : NULL, - numberOfGlyphs, glyphs.Begin(), glyphsToCharactersMap.Begin(), - charactersPerGlyph.Begin() ); + charactersPerGlyph.Begin(), + charactersToGlyph.Begin(), + glyphsPerCharacter.Begin(), + numberOfGlyphs ); // The laid-out lines. // It's not possible to know in how many lines the text is going to be laid-out, @@ -1120,6 +1379,10 @@ bool Controller::DoRelayout( const Size& size, // Whether the last character is a new paragraph character. layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mLogicalModel->mText.Count() - 1u ) ) ); + // The initial glyph and the number of glyphs to layout. + layoutParameters.startGlyphIndex = 0u; + layoutParameters.numberOfGlyphs = numberOfGlyphs; + // Update the visual model. viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, glyphPositions, @@ -1132,62 +1395,66 @@ bool Controller::DoRelayout( const Size& size, if( REORDER & operations ) { Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; + Vector& bidirectionalLineInfo = mImpl->mLogicalModel->mBidirectionalLineInfo; // Check first if there are paragraphs with bidirectional info. if( 0u != bidirectionalInfo.Count() ) { // Get the lines const Length numberOfLines = mImpl->mVisualModel->mLines.Count(); + const CharacterIndex startIndex = 0u; + const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count(); // Reorder the lines. - Vector lineBidirectionalInfoRuns; - lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters. + bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters. ReorderLines( bidirectionalInfo, + startIndex, + requestedNumberOfCharacters, lines, - lineBidirectionalInfoRuns ); - - // Set the bidirectional info into the model. - const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count(); - mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(), - numberOfBidirectionalInfoRuns ); + bidirectionalLineInfo ); // Set the bidirectional info per line into the layout parameters. - layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin(); - layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns; - - // Get the character to glyph conversion table and set into the layout. - layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin(); + layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin(); + layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count(); - // Get the glyphs per character table and set into the layout. - layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin(); + // Set the bidirectional info into the model. + mImpl->mLogicalModel->SetVisualToLogicalMap( layoutParameters.lineBidirectionalInfoRunsBuffer, + layoutParameters.numberOfBidirectionalInfoRuns, + startIndex, + requestedNumberOfCharacters ); // Re-layout the text. Reorder those lines with right to left characters. mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters, + startIndex, + requestedNumberOfCharacters, glyphPositions ); // Free the allocated memory used to store the conversion table in the bidirectional line info run. - for( Vector::Iterator it = lineBidirectionalInfoRuns.Begin(), - endIt = lineBidirectionalInfoRuns.End(); + for( Vector::Iterator it = bidirectionalLineInfo.Begin(), + endIt = bidirectionalLineInfo.End(); it != endIt; ++it ) { BidirectionalLineInfoRun& bidiLineInfo = *it; free( bidiLineInfo.visualToLogicalMap ); + bidiLineInfo.visualToLogicalMap = NULL; } + + bidirectionalLineInfo.Clear(); } } // REORDER // Sets the actual size. if( UPDATE_ACTUAL_SIZE & operations ) { - mImpl->mVisualModel->SetActualSize( layoutSize ); + mImpl->mVisualModel->SetLayoutSize( layoutSize ); } } // view updated } else { - layoutSize = mImpl->mVisualModel->GetActualSize(); + layoutSize = mImpl->mVisualModel->GetLayoutSize(); } if( ALIGN & operations ) @@ -1195,7 +1462,12 @@ bool Controller::DoRelayout( const Size& size, // The laid-out lines. Vector& lines = mImpl->mVisualModel->mLines; - mImpl->mLayoutEngine.Align( layoutSize, + const CharacterIndex startIndex = 0u; + const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count(); + + mImpl->mLayoutEngine.Align( size, + startIndex, + requestedNumberOfCharacters, lines ); viewUpdated = true; @@ -1268,49 +1540,62 @@ LayoutEngine::VerticalAlignment Controller::GetVerticalAlignment() const return mImpl->mLayoutEngine.GetVerticalAlignment(); } -void Controller::CalculateTextAlignment( const Size& size ) +void Controller::CalculateTextAlignment( const Size& controlSize ) { - // Get the direction of the first character. - const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); + Size layoutSize = mImpl->mVisualModel->GetLayoutSize(); - Size actualSize = mImpl->mVisualModel->GetActualSize(); - if( fabsf( actualSize.height ) < Math::MACHINE_EPSILON_1000 ) + if( fabsf( layoutSize.height ) < Math::MACHINE_EPSILON_1000 ) { // Get the line height of the default font. - actualSize.height = mImpl->GetDefaultFontLineHeight(); + layoutSize.height = mImpl->GetDefaultFontLineHeight(); } - // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; - LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); - if( firstParagraphDirection && - ( LayoutEngine::HORIZONTAL_ALIGN_CENTER != horizontalAlignment ) ) + if( LayoutEngine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout() ) { - if( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == horizontalAlignment ) - { - horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; - } - else - { - horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; - } - } + // Get the direction of the first character. + const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); - switch( horizontalAlignment ) - { - case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; + LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); + if( firstParagraphDirection ) { - mImpl->mAlignmentOffset.x = 0.f; - break; - } - case LayoutEngine::HORIZONTAL_ALIGN_CENTER: - { - mImpl->mAlignmentOffset.x = floorf( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. - break; + switch( horizontalAlignment ) + { + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + // Nothing to do. + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; + break; + } + } } - case LayoutEngine::HORIZONTAL_ALIGN_END: + + switch( horizontalAlignment ) { - mImpl->mAlignmentOffset.x = size.width - actualSize.width; - break; + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + mImpl->mAlignmentOffset.x = 0.f; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + mImpl->mAlignmentOffset.x = floorf( 0.5f * ( controlSize.width - layoutSize.width ) ); // try to avoid pixel alignment. + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + mImpl->mAlignmentOffset.x = controlSize.width - layoutSize.width; + break; + } } } @@ -1324,12 +1609,12 @@ void Controller::CalculateTextAlignment( const Size& size ) } case LayoutEngine::VERTICAL_ALIGN_CENTER: { - mImpl->mAlignmentOffset.y = floorf( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment. + mImpl->mAlignmentOffset.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment. break; } case LayoutEngine::VERTICAL_ALIGN_BOTTOM: { - mImpl->mAlignmentOffset.y = size.height - actualSize.height; + mImpl->mAlignmentOffset.y = controlSize.height - layoutSize.height; break; } } @@ -1558,13 +1843,15 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count(); // Restrict new text to fit within Maximum characters setting - Length maxSizeOfNewText = std::min ( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount ); + Length maxSizeOfNewText = std::min( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount ); maxLengthReached = ( characterCount > maxSizeOfNewText ); // The cursor position. CharacterIndex& cursorIndex = mImpl->mEventData->mPrimaryCursorPosition; - // Updates the text style runs. + // Update the text's style. + + // Updates the text style runs by adding characters. mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, maxSizeOfNewText ); // Get the character index from the cursor index. @@ -1577,6 +1864,13 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ // Whether to add a new text color run. const bool addColorRun = style.textColor != mImpl->mEventData->mInputStyle.textColor; + // Whether to add a new font run. + const bool addFontNameRun = style.familyName != mImpl->mEventData->mInputStyle.familyName; + const bool addFontWeightRun = style.weight != mImpl->mEventData->mInputStyle.weight; + const bool addFontWidthRun = style.width != mImpl->mEventData->mInputStyle.width; + const bool addFontSlantRun = style.slant != mImpl->mEventData->mInputStyle.slant; + const bool addFontSizeRun = style.size != mImpl->mEventData->mInputStyle.size; + // Add style runs. if( addColorRun ) { @@ -1589,6 +1883,55 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ colorRun.characterRun.numberOfCharacters = maxSizeOfNewText; } + if( addFontNameRun || + addFontWeightRun || + addFontWidthRun || + addFontSlantRun || + addFontSizeRun ) + { + const VectorBase::SizeType numberOfRuns = mImpl->mLogicalModel->mFontDescriptionRuns.Count(); + mImpl->mLogicalModel->mFontDescriptionRuns.Resize( numberOfRuns + 1u ); + + FontDescriptionRun& fontDescriptionRun = *( mImpl->mLogicalModel->mFontDescriptionRuns.Begin() + numberOfRuns ); + + if( addFontNameRun ) + { + fontDescriptionRun.familyLength = mImpl->mEventData->mInputStyle.familyName.size(); + fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength]; + memcpy( fontDescriptionRun.familyName, mImpl->mEventData->mInputStyle.familyName.c_str(), fontDescriptionRun.familyLength ); + fontDescriptionRun.familyDefined = true; + + // The memory allocated for the font family name is freed when the font description is removed from the logical model. + } + + if( addFontWeightRun ) + { + fontDescriptionRun.weight = mImpl->mEventData->mInputStyle.weight; + fontDescriptionRun.weightDefined = true; + } + + if( addFontWidthRun ) + { + fontDescriptionRun.width = mImpl->mEventData->mInputStyle.width; + fontDescriptionRun.widthDefined = true; + } + + if( addFontSlantRun ) + { + fontDescriptionRun.slant = mImpl->mEventData->mInputStyle.slant; + fontDescriptionRun.slantDefined = true; + } + + if( addFontSizeRun ) + { + fontDescriptionRun.size = static_cast( mImpl->mEventData->mInputStyle.size * 64.f ); + fontDescriptionRun.sizeDefined = true; + } + + fontDescriptionRun.characterRun.characterIndex = cursorIndex; + fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText; + } + // Insert at current cursor position. Vector& modifyText = mImpl->mLogicalModel->mText; @@ -2228,6 +2571,7 @@ void Controller::ClearFontData() void Controller::ClearStyleData() { mImpl->mLogicalModel->mColorRuns.Clear(); + mImpl->mLogicalModel->ClearFontDescriptionRuns(); } Controller::Controller( ControlInterface& controlInterface )