* 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,
Layout::HORIZONTAL_ALIGN_BEGIN,
- lines );
+ lines,
+ alignmentOffset );
}
}
Layout::Engine engine;
engine.SetMetrics( metrics );
+ float alignmentOffset = 0.f;
engine.Align( data.textArea,
data.startIndex,
data.numberOfCharacters,
data.horizontalAlignment,
- 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->GetTextModel()->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->GetTextModel()->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();
mStencil.SetParentOrigin( ParentOrigin::CENTER );
// Creates a background visual. Even if the color is transparent it updates the stencil.
- // Property::Map backgroundMap;
mStencil.SetProperty( Toolkit::Control::Property::BACKGROUND,
Property::Map().Add( Toolkit::Visual::Property::TYPE, DevelVisual::COLOR ).
Add( ColorVisual::Property::MIX_COLOR, Color::TRANSPARENT ) );
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->GetTextModel()->GetScrollPosition();
- renderableActor.SetPosition( scrollOffset.x, scrollOffset.y );
+ renderableActor.SetPosition( scrollOffset.x + alignmentOffset, scrollOffset.y );
self.Add( renderableActor );
}
CharacterIndex startIndex,
Length numberOfCharacters,
HorizontalAlignment horizontalAlignment,
- 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;
CalculateHorizontalAlignment( size.width,
horizontalAlignment,
line );
+
+ // Updates the alignment offset.
+ alignmentOffset = std::min( alignmentOffset, line.alignmentOffset );
}
}
CharacterIndex startIndex,
Length numberOfCharacters,
Layout::HorizontalAlignment horizontalAlignment,
- Vector<LineRun>& lines )
+ Vector<LineRun>& lines,
+ float& alignmentOffset )
{
mImpl->Align( size,
startIndex,
numberOfCharacters,
horizontalAlignment,
- lines );
+ lines,
+ alignmentOffset );
}
void Engine::SetDefaultLineSpacing( float lineSpacing )
* @param[in] numberOfCharacters The number of characters.
* @param[in] horizontalAlignment The horizontal alignment.
* @param[in,out] lines The laid-out lines.
+ * @param[out] alignmentOffset The alignment offset.
*/
void Align( const Size& size,
CharacterIndex startIndex,
Length numberOfCharacters,
Layout::HorizontalAlignment horizontalAlignment,
- 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 > mModel->mVisualModel->mControlSize.width )
{
- const float space = ( layoutSize.width - mModel->mVisualModel->mControlSize.width );
+ const float space = ( layoutSize.width - mModel->mVisualModel->mControlSize.width ) + mModel->mAlignmentOffset;
mModel->mScrollPosition.x = ( mModel->mScrollPosition.x < -space ) ? -space : mModel->mScrollPosition.x;
- mModel->mScrollPosition.x = ( mModel->mScrollPosition.x > 0.f ) ? 0.f : mModel->mScrollPosition.x;
+ mModel->mScrollPosition.x = ( mModel->mScrollPosition.x > -mModel->mAlignmentOffset ) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
mEventData->mDecoratorUpdated = true;
}
// The laid-out lines.
Vector<LineRun>& lines = mImpl->mModel->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,
mImpl->mModel->mHorizontalAlignment,
- lines );
+ lines,
+ mImpl->mModel->mAlignmentOffset );
viewUpdated = true;
}
Vector2 mScrollPosition; ///< The text is offset by this position when scrolling.
Layout::HorizontalAlignment mHorizontalAlignment; ///< The layout's horizontal alignment.
Layout::VerticalAlignment mVerticalAlignment; ///< The layout's vertical alignment.
+ float mAlignmentOffset; ///< The alignment offset.
bool mElideEnabled:1; ///< Whether the text's elide is enabled.
};
*
* @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;