// EXTERNAL INCLUDES
#include <limits>
+#include <memory.h>
#include <dali/public-api/adaptor-framework/key.h>
#include <dali/integration-api/debug.h>
#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
const unsigned int POINTS_PER_INCH = 72;
const std::string EMPTY_STRING("");
-const unsigned int ZERO = 0u;
float ConvertToEven( float value )
{
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 ) );
if( !text.empty() )
{
- MarkupProcessData markupProcessData( mImpl->mLogicalModel->mColorRuns );
+ MarkupProcessData markupProcessData( mImpl->mLogicalModel->mColorRuns,
+ mImpl->mLogicalModel->mFontDescriptionRuns );
Length textSize = 0u;
const uint8_t* utf8 = NULL;
}
}
-void Controller::SetMaximumNumberOfCharacters( int maxCharacters )
+void Controller::SetMaximumNumberOfCharacters( Length maxCharacters )
{
- if( maxCharacters >= 0 )
- {
- mImpl->mMaximumNumberOfCharacters = maxCharacters;
- }
+ mImpl->mMaximumNumberOfCharacters = maxCharacters;
}
int Controller::GetMaximumNumberOfCharacters()
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();
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();
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();
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 )
}
mImpl->mFontDefaults->mFontDescription.slant = slant;
+ mImpl->mFontDefaults->slantDefined = true;
// Clear the font-specific data
ClearFontData();
}
mImpl->mFontDefaults->mDefaultPointSize = pointSize;
+ mImpl->mFontDefaults->sizeDefined = true;
unsigned int horizontalDpi( 0u );
unsigned int verticalDpi( 0u );
{
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();
}
+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<PointSize26Dot6>( 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" );
}
else
{
- layoutSize = mImpl->mVisualModel->GetActualSize();
+ layoutSize = mImpl->mVisualModel->GetLayoutSize();
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height );
}
return glyphsRemoved;
}
+ // Whether a new size has been set.
const bool newSize = ( size != mImpl->mVisualModel->mControlSize );
if( newSize )
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;
const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
const Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
const Character* const textBuffer = mImpl->mLogicalModel->mText.Begin();
+ const Vector<GlyphIndex>& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph;
+ const Vector<Length>& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter;
// Set the layout parameters.
LayoutParameters layoutParameters( 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,
// 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,
if( REORDER & operations )
{
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
+ Vector<BidirectionalLineInfoRun>& 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<BidirectionalLineInfoRun> 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<BidirectionalLineInfoRun>::Iterator it = lineBidirectionalInfoRuns.Begin(),
- endIt = lineBidirectionalInfoRuns.End();
+ for( Vector<BidirectionalLineInfoRun>::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 )
// The laid-out lines.
Vector<LineRun>& 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;
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;
+ }
}
}
}
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;
}
}
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.
// 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 )
{
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<PointSize26Dot6>( mImpl->mEventData->mInputStyle.size * 64.f );
+ fontDescriptionRun.sizeDefined = true;
+ }
+
+ fontDescriptionRun.characterRun.characterIndex = cursorIndex;
+ fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText;
+ }
+
// Insert at current cursor position.
Vector<Character>& modifyText = mImpl->mLogicalModel->mText;
void Controller::ClearStyleData()
{
mImpl->mLogicalModel->mColorRuns.Clear();
+ mImpl->mLogicalModel->ClearFontDescriptionRuns();
}
Controller::Controller( ControlInterface& controlInterface )