* Aligns the placement actor within the text control according with the alignment properties.
Change-Id: I62782283d13195081b56d395eecb854eb30f1df9
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
if( options.align )
{
+ float alignmentOffset = 0.f;
layoutEngine.Align( textArea,
0u,
numberOfCharacters,
- lines );
+ lines,
+ alignmentOffset );
}
}
engine.SetHorizontalAlignment( data.horizontalAlignment );
engine.SetVerticalAlignment( data.verticalAlignment );
+ float alignmentOffset = 0.f;
engine.Align( data.textArea,
data.startIndex,
data.numberOfCharacters,
- visualModel->mLines );
+ visualModel->mLines,
+ alignmentOffset );
// Compare results.
if( data.numberOfLines != visualModel->mLines.Count() )
tet_result(TET_FAIL);
}
+ try
+ {
+ // Render some text with the shared atlas backend
+ label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_VECTOR_BASED );
+ application.SendNotification();
+ application.Render();
+ }
+ catch( ... )
+ {
+ tet_result(TET_FAIL);
+ }
END_TEST;
}
{
if( mRenderer )
{
- renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
+ renderableActor = mRenderer->Render( mController->GetView(),
+ mAlignmentOffset,
+ DepthIndex::TEXT );
}
if( renderableActor != mRenderableActor )
{
const Vector2& scrollOffset = mController->GetScrollPosition();
- mRenderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+ mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y );
// Make sure the actors are parented correctly with/without clipping
Actor self = mStencil ? mStencil : Self();
TextEditor::TextEditor()
: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
mIdleCallback( NULL ),
+ mAlignmentOffset( 0.f ),
mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
mHasBeenStaged( false )
{
Actor mRenderableActor;
CallbackBase* mIdleCallback;
+ float mAlignmentOffset;
int mRenderingBackend;
bool mHasBeenStaged:1;
};
{
if( mRenderer )
{
- renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
+ renderableActor = mRenderer->Render( mController->GetView(),
+ mAlignmentOffset,
+ DepthIndex::TEXT );
}
if( renderableActor != mRenderableActor )
{
const Vector2& scrollOffset = mController->GetScrollPosition();
- mRenderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+ mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y );
// Make sure the actors are parented correctly with/without clipping
Actor self = mStencil ? mStencil : Self();
TextField::TextField()
: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
mIdleCallback( NULL ),
+ mAlignmentOffset( 0.f ),
mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ),
mHasBeenStaged( false )
Actor mRenderableActor;
CallbackBase* mIdleCallback;
+ float mAlignmentOffset;
int mRenderingBackend;
int mExceedPolicy;
bool mHasBeenStaged:1;
Actor self = Self();
Actor renderableActor;
+ float alignmentOffset = 0.f;
if( mRenderer )
{
- renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
+ renderableActor = mRenderer->Render( mController->GetView(),
+ alignmentOffset,
+ DepthIndex::TEXT );
}
if( renderableActor != mRenderableActor )
if( renderableActor )
{
const Vector2& scrollOffset = mController->GetScrollPosition();
- renderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+ renderableActor.SetPosition( scrollOffset.x + alignmentOffset, scrollOffset.y );
self.Add( renderableActor );
}
void Align( const Size& size,
CharacterIndex startIndex,
Length numberOfCharacters,
- Vector<LineRun>& lines )
+ Vector<LineRun>& lines,
+ float& alignmentOffset )
{
const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters;
+ alignmentOffset = MAX_FLOAT;
// Traverse all lines and align the glyphs.
for( Vector<LineRun>::Iterator it = lines.Begin(), endIt = lines.End();
it != endIt;
// the box width, line length, and the paragraph's direction.
CalculateHorizontalAlignment( size.width,
line );
+
+ // Updates the alignment offset.
+ alignmentOffset = std::min( alignmentOffset, line.alignmentOffset );
}
}
void LayoutEngine::Align( const Size& size,
CharacterIndex startIndex,
Length numberOfCharacters,
- Vector<LineRun>& lines )
+ Vector<LineRun>& lines,
+ float& alignmentOffset )
{
mImpl->Align( size,
startIndex,
numberOfCharacters,
- lines );
+ lines,
+ alignmentOffset );
}
void LayoutEngine::SetDefaultLineSpacing( float lineSpacing )
* @param[in] startIndex Character index of the line from where the lines are aligned.
* @param[in] numberOfCharacters The number of characters.
* @param[in,out] lines The laid-out lines.
+ * @param[out] alignmentOffset The alignment offset.
*/
void Align( const Size& size,
CharacterIndex startIndex,
Length numberOfCharacters,
- Vector<LineRun>& lines );
+ Vector<LineRun>& lines,
+ float& alignmentOffset );
/**
* @brief Sets the default line spacing.
const Vector4& defaultColor,
const Vector4* const colorsBuffer,
const ColorIndex* const colorIndicesBuffer,
- int depth )
+ int depth,
+ float minLineOffset )
{
AtlasManager::AtlasSlot slot;
std::vector< MeshRecord > meshContainer;
Vector< TextCacheEntry > newTextCache;
const GlyphInfo* const glyphsBuffer = glyphs.Begin();
const Vector2* const positionsBuffer = positions.Begin();
+ const Vector2 lineOffsetPosition( minLineOffset, 0.f );
for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
{
const GlyphInfo& glyph = *( glyphsBuffer + i );
-
const bool underlineGlyph = underlineEnabled || IsGlyphUnderlined( i, underlineRuns );
thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph;
}
// Move the origin (0,0) of the mesh to the center of the actor
- const Vector2 position = *( positionsBuffer + i ) - halfTextSize;
+ const Vector2 position = *( positionsBuffer + i ) - halfTextSize - lineOffsetPosition;
// Generate mesh data for this quad, plugging in our supplied position
AtlasManager::Mesh2D newMesh;
return Text::RendererPtr( new AtlasRenderer() );
}
-Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
+Actor AtlasRenderer::Render( Text::ViewInterface& view,
+ float& alignmentOffset,
+ int depth )
{
DALI_LOG_INFO( gLogFilter, Debug::General, "Text::AtlasRenderer::Render()\n" );
numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
positions.Begin(),
+ alignmentOffset,
0u,
numberOfGlyphs );
defaultColor,
colorsBuffer,
colorIndicesBuffer,
- depth );
+ depth,
+ alignmentOffset );
/* In the case where AddGlyphs does not create a renderable Actor for example when glyphs are all whitespace create a new Actor. */
/* This renderable actor is used to position the text, other "decorations" can rely on there always being an Actor regardless of it is whitespace or regular text. */
static RendererPtr New();
/**
- * @brief Render the glyphs from a ViewInterface.
- *
- * @param[in] view The interface to a view.
- * @param[in] depth The depth in the tree of the parent.
- * @return The Renderable actor used to position the text.
+ * @copydoc Renderer::Render()
*/
- virtual Actor Render( ViewInterface& view, int depth );
+ virtual Actor Render( ViewInterface& view,
+ float& alignmentOffset,
+ int depth );
protected:
* @brief Render the glyphs from a ViewInterface.
*
* @param[in] view The interface to a view.
+ * @param[out] alignmentOffset Offset used to internally align the placement actor.
* @param[in] depth The depth in the tree of the parent.
* @return The Renderable actor used to position the text.
*/
- virtual Actor Render( ViewInterface& view, int depth ) = 0;
+ virtual Actor Render( ViewInterface& view,
+ float& alignmentOffset,
+ int depth ) = 0;
protected:
return Text::RendererPtr( new VectorBasedRenderer() );
}
-Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
+Actor VectorBasedRenderer::Render( Text::ViewInterface& view,
+ float& alignmentOffset,
+ int /*depth*/ )
{
UnparentAndReset( mImpl->mActor );
numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
positions.Begin(),
+ alignmentOffset,
0u,
numberOfGlyphs );
+
glyphs.Resize( numberOfGlyphs );
positions.Resize( numberOfGlyphs );
Vector< unsigned short > indices;
const Vector2& controlSize = view.GetControlSize();
- float xOffset = controlSize.width * -0.5f;
+ float xOffset = -alignmentOffset + controlSize.width * -0.5f;
float yOffset = controlSize.height * -0.5f;
if( ! mImpl->mAtlas ||
static RendererPtr New();
/**
- * @brief Render the glyphs from a ViewInterface.
- *
- * @param[in] view The interface to a view.
- * @param[in] depth The depth in the tree of the parent.
- * @return The Renderable actor used to position the text.
+ * @copydoc Renderer::Render()
*/
- virtual Actor Render( ViewInterface& view, int depth );
+ virtual Actor Render( ViewInterface& view,
+ float& alignmentOffset,
+ int depth );
protected:
void Controller::Impl::ClampHorizontalScroll( const Vector2& layoutSize )
{
- // Clamp between -space & 0.
+ // Clamp between -space & -alignment offset.
if( layoutSize.width > mVisualModel->mControlSize.width )
{
- const float space = ( layoutSize.width - mVisualModel->mControlSize.width );
+ const float space = ( layoutSize.width - mVisualModel->mControlSize.width ) + mAlignmentOffset;
mScrollPosition.x = ( mScrollPosition.x < -space ) ? -space : mScrollPosition.x;
- mScrollPosition.x = ( mScrollPosition.x > 0.f ) ? 0.f : mScrollPosition.x;
+ mScrollPosition.x = ( mScrollPosition.x > -mAlignmentOffset ) ? -mAlignmentOffset : mScrollPosition.x;
mEventData->mDecoratorUpdated = true;
}
mLayoutEngine(),
mModifyEvents(),
mTextColor( Color::BLACK ),
+ mScrollPosition(),
mTextUpdateInfo(),
mOperationsPending( NO_OPERATION ),
mMaximumNumberOfCharacters( 50u ),
+ mAlignmentOffset( 0.f ),
mRecalculateNaturalSize( true ),
mMarkupProcessorEnabled( false ),
mClipboardHideEnabled( true ),
TextUpdateInfo mTextUpdateInfo; ///< Info of the characters updated.
OperationsMask mOperationsPending; ///< Operations pending to be done to layout the text.
Length mMaximumNumberOfCharacters; ///< Maximum number of characters that can be inserted.
+ float mAlignmentOffset; ///< The alignment offset.
bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated.
bool mMarkupProcessorEnabled:1; ///< Whether the mark-up procesor is enabled.
// The laid-out lines.
Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
+ // Need to align with the control's size as the text may contain lines
+ // starting either with left to right text or right to left.
mImpl->mLayoutEngine.Align( size,
startIndex,
requestedNumberOfCharacters,
- lines );
+ lines,
+ mImpl->mAlignmentOffset );
viewUpdated = true;
}
*
* @param[out] glyphs Pointer to a buffer where the glyphs are copied.
* @param[out] glyphPositions Pointer to a buffer where the glyph's positions are copied.
+ * @param[out] minLineOffset The minimum line offset.
* @param[in] glyphIndex Index to the first glyph.
* @param[in] numberOfGlyphs Number of glyphs to be copied.
*
*/
virtual Length GetGlyphs( GlyphInfo* glyphs,
Vector2* glyphPositions,
+ float& minLineOffset,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const = 0;
Length View::GetGlyphs( GlyphInfo* glyphs,
Vector2* glyphPositions,
+ float& minLineOffset,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
{
// Add the alignment offset to the glyph's position.
+ minLineOffset = line->alignmentOffset;
float penY = line->ascender;
for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index )
{
if( lineIndex < numberOfLines )
{
line = lineBuffer + lineIndex;
+ minLineOffset = std::min( minLineOffset, line->alignmentOffset );
lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
*/
virtual Length GetGlyphs( GlyphInfo* glyphs,
Vector2* glyphPositions,
+ float& minLineOffset,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const;