/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
extraWidth( 0.f ),
wsLengthEndOfLine( 0.f ),
ascender( 0.f ),
- descender( MAX_FLOAT )
+ descender( MAX_FLOAT ),
+ lineSpacing( 0.f )
{}
~LineLayout()
float wsLengthEndOfLine; ///< The length of the white spaces at the end of the line.
float ascender; ///< The maximum ascender of all fonts in the line.
float descender; ///< The minimum descender of all fonts in the line.
+ float lineSpacing; ///< The line spacing
};
struct Engine::Impl
Impl()
: mLayout( Layout::Engine::SINGLE_LINE_BOX ),
mCursorWidth( CURSOR_WIDTH ),
- mDefaultLineSpacing( LINE_SPACING )
+ mDefaultLineSpacing( LINE_SPACING ),
+ mPreviousCharacterExtraWidth( 0.0f )
{
}
{
lineLayout.descender = fontMetrics.descender;
}
+
+ // set the line spacing
+ lineLayout.lineSpacing = mDefaultLineSpacing;
}
/**
LineLayout tmpLineLayout;
const bool isMultiline = mLayout == MULTI_LINE_BOX;
+ const bool isWordLaidOut = parameters.lineWrapMode == Text::LineWrap::WORD;
// The last glyph to be laid-out.
const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
// Get the line break info for the current character.
const LineBreakInfo lineBreakInfo = hasCharacters ? *( parameters.lineBreakInfoBuffer + characterLastIndex ) : TextAbstraction::LINE_NO_BREAK;
- // Get the word break info for the current character.
- const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex );
-
// Increase the number of characters.
tmpLineLayout.numberOfCharacters += charactersPerGlyph;
const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
}
}
else
const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
}
else // LTR
{
const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
}
}
}
tmpLineLayout.wsLengthEndOfLine = 0.f;
}
+ // Save the current extra width to compare with the next one
+ mPreviousCharacterExtraWidth = tmpExtraWidth;
+
// Check if the accumulated length fits in the width of the box.
if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
( tmpExtraBearing + lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpExtraWidth > parameters.boundingBox.width ) )
}
if( isMultiline &&
- ( TextAbstraction::WORD_BREAK == wordBreakInfo ) )
+ ( TextAbstraction::LINE_ALLOW_BREAK == lineBreakInfo ) )
{
- oneWordLaidOut = true;
+ oneWordLaidOut = isWordLaidOut;
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " One word laid-out\n" );
// Current glyph is the last one of the current word.
void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
Length numberOfGlyphs,
+ float outlineWidth,
Vector2* glyphPositionsBuffer )
{
// Traverse the glyphs and set the positions.
// so the penX position needs to be moved to the right.
const GlyphInfo& glyph = *glyphsBuffer;
- float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+ float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing + outlineWidth : outlineWidth;
+
for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i )
{
// Get the last line and layout it again with the 'completelyFill' flag to true.
lineRun = linesBuffer + ( numberOfLines - 1u );
- penY -= layout.ascender - lineRun->descender;
+ penY -= layout.ascender - lineRun->descender + lineRun->lineSpacing;
ellipsisLayout.glyphIndex = lineRun->glyphRun.glyphIndex;
}
layoutSize.width = layoutParameters.boundingBox.width;
if( layoutSize.height < Math::MACHINE_EPSILON_1000 )
{
- layoutSize.height += ( lineRun->ascender + -lineRun->descender );
+ layoutSize.height += ( lineRun->ascender + -lineRun->descender ) + lineRun->lineSpacing;
}
SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex,
ellipsisLayout.numberOfGlyphs,
+ layoutParameters.outlineWidth,
glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex );
}
lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs;
lineRun.characterRun.characterIndex = layout.characterIndex;
lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
+ lineRun.lineSpacing = mDefaultLineSpacing;
+
if( isLastLine && !layoutParameters.isLastNewParagraph )
{
const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
layoutSize.width = lineRun.width;
}
- layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+ layoutSize.height += ( lineRun.ascender + -lineRun.descender ) + lineRun.lineSpacing;
}
/**
lineRun.alignmentOffset = 0.f;
lineRun.direction = !RTL;
lineRun.ellipsis = false;
+ lineRun.lineSpacing = mDefaultLineSpacing;
- layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+ layoutSize.height += ( lineRun.ascender + -lineRun.descender ) + lineRun.lineSpacing;
}
/**
layoutSize.width = line.width;
}
- layoutSize.height += ( line.ascender + -line.descender );
+ layoutSize.height += ( line.ascender + -line.descender ) + line.lineSpacing;
}
}
// Sets the positions of the glyphs.
SetGlyphPositions( layoutParameters.glyphsBuffer + index,
layout.numberOfGlyphs,
+ layoutParameters.outlineWidth,
glyphPositionsBuffer + index - layoutParameters.startGlyphIndex );
// Updates the vertical pen's position.
- penY += -layout.descender;
+ penY += -layout.descender + layout.lineSpacing + mDefaultLineSpacing;
// Increase the glyph index.
index = nextIndex;
const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap;
const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) );
- float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+ float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing - layoutParameters.outlineWidth : -layoutParameters.outlineWidth;
Vector2* glyphPositionsBuffer = glyphPositions.Begin();
void Align( const Size& size,
CharacterIndex startIndex,
Length numberOfCharacters,
- HorizontalAlignment horizontalAlignment,
+ Text::HorizontalAlignment::Type horizontalAlignment,
Vector<LineRun>& lines,
float& alignmentOffset )
{
}
void CalculateHorizontalAlignment( float boxWidth,
- HorizontalAlignment horizontalAlignment,
+ HorizontalAlignment::Type horizontalAlignment,
LineRun& line )
{
line.alignmentOffset = 0.f;
const bool isRTL = RTL == line.direction;
float lineLength = line.width;
- HorizontalAlignment alignment = horizontalAlignment;
+ HorizontalAlignment::Type alignment = horizontalAlignment;
if( isRTL )
{
// Swap the alignment type if the line is right to left.
switch( alignment )
{
- case HORIZONTAL_ALIGN_BEGIN:
+ case HorizontalAlignment::BEGIN:
{
- alignment = HORIZONTAL_ALIGN_END;
+ alignment = HorizontalAlignment::END;
break;
}
- case HORIZONTAL_ALIGN_CENTER:
+ case HorizontalAlignment::CENTER:
{
// Nothing to do.
break;
}
- case HORIZONTAL_ALIGN_END:
+ case HorizontalAlignment::END:
{
- alignment = HORIZONTAL_ALIGN_BEGIN;
+ alignment = HorizontalAlignment::BEGIN;
break;
}
}
// Calculate the horizontal line offset.
switch( alignment )
{
- case HORIZONTAL_ALIGN_BEGIN:
+ case HorizontalAlignment::BEGIN:
{
line.alignmentOffset = 0.f;
}
break;
}
- case HORIZONTAL_ALIGN_CENTER:
+ case HorizontalAlignment::CENTER:
{
line.alignmentOffset = 0.5f * ( boxWidth - lineLength );
line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment.
break;
}
- case HORIZONTAL_ALIGN_END:
+ case HorizontalAlignment::END:
{
if( isRTL )
{
line.alignmentOffset = 0.f;
line.direction = !RTL;
line.ellipsis = false;
+ line.lineSpacing = mDefaultLineSpacing;
}
Type mLayout;
float mCursorWidth;
float mDefaultLineSpacing;
+ float mPreviousCharacterExtraWidth;
IntrusivePtr<Metrics> mMetrics;
};
void Engine::Align( const Size& size,
CharacterIndex startIndex,
Length numberOfCharacters,
- Layout::HorizontalAlignment horizontalAlignment,
+ Text::HorizontalAlignment::Type horizontalAlignment,
Vector<LineRun>& lines,
float& alignmentOffset )
{