X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-view.cpp;h=e7bd2629c388191176addcea1946fa6acd6f3c5d;hp=b0825f6e9061e1e5d409685e7c6c45b4b72a28cb;hb=e82c3165d7d7eeaa8cd8c911ab73b1ed2f46ddf4;hpb=d04c5bdbb95cc98f90848c7a98b0b2804df6e5b8 diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index b0825f6..e7bd262 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include namespace Dali { @@ -33,12 +34,15 @@ namespace Text struct View::Impl { VisualModelPtr mVisualModel; + TextAbstraction::FontClient mFontClient; ///< Handle to the font client. }; View::View() : mImpl( NULL ) { mImpl = new View::Impl(); + + mImpl->mFontClient = TextAbstraction::FontClient::Get(); } View::~View() @@ -51,6 +55,139 @@ void View::SetVisualModel( VisualModelPtr visualModel ) mImpl->mVisualModel = visualModel; } +Length View::GetGlyphs( GlyphInfo* glyphs, + Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + Length numberOfLaidOutGlyphs = 0u; + + if( mImpl->mVisualModel ) + { + // If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'. + // Check the last laid out line to know if the layout engine elided some text. + + const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines(); + if( numberOfLines > 0u ) + { + const LineRun& lastLine = *( mImpl->mVisualModel->mLines.Begin() + ( numberOfLines - 1u ) ); + + // If ellipsis is enabled, calculate the number of laid out glyphs. + // Otherwise use the given number of glyphs. + if( lastLine.ellipsis ) + { + numberOfLaidOutGlyphs = lastLine.glyphIndex + lastLine.numberOfGlyphs; + } + else + { + numberOfLaidOutGlyphs = numberOfGlyphs; + } + + // Retrieve from the visual model the glyphs and positions. + mImpl->mVisualModel->GetGlyphs( glyphs, + glyphIndex, + numberOfLaidOutGlyphs ); + + mImpl->mVisualModel->GetGlyphPositions( glyphPositions, + glyphIndex, + numberOfLaidOutGlyphs ); + + if( 1u == numberOfLaidOutGlyphs ) + { + // not a point try to do ellipsis with only one laid out character. + return numberOfLaidOutGlyphs; + } + + if( lastLine.ellipsis ) + { + // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed. + float firstPenX = 0.f; // Used if rtl text is elided. + float penY = 0.f; + bool firstPenSet = false; + + // Add the ellipsis glyph. + bool inserted = false; + float removedGlypsWidth = 0.f; + Length numberOfRemovedGlyphs = 0u; + GlyphIndex index = numberOfLaidOutGlyphs - 1u; + + // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed. + while( !inserted ) + { + const GlyphInfo& glyphToRemove = *( glyphs + index ); + + // Need to reshape the glyph as the font may be different in size. + const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) ); + + if( !firstPenSet ) + { + const Vector2& position = *( glyphPositions + index ); + + // Calculates the penY of the current line. It will be used to position the ellipsis glyph. + penY = position.y + glyphToRemove.yBearing; + + // Calculates the first penX which will be used if rtl text is elided. + firstPenX = position.x - glyphToRemove.xBearing; + if( firstPenX < -ellipsisGlyph.xBearing ) + { + // Avoids to exceed the bounding box when rtl text is elided. + firstPenX = -ellipsisGlyph.xBearing; + } + + removedGlypsWidth = -ellipsisGlyph.xBearing; + + firstPenSet = true; + } + + removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) ); + + // Calculate the width of the ellipsis glyph and check if it fits. + const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing; + if( ellipsisGlyphWidth < removedGlypsWidth ) + { + GlyphInfo& glyphInfo = *( glyphs + index ); + Vector2& position = *( glyphPositions + index ); + position.x -= glyphInfo.xBearing; + + // Replace the glyph by the ellipsis glyph. + glyphInfo = ellipsisGlyph; + + // Change the 'x' and 'y' position of the ellipsis glyph. + + if( position.x > firstPenX ) + { + position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth; + } + + position.x += ellipsisGlyph.xBearing; + position.y = penY - ellipsisGlyph.yBearing; + + inserted = true; + } + else + { + if( index > 0u ) + { + --index; + } + else + { + // No space for the ellipsis. + inserted = true; + } + ++numberOfRemovedGlyphs; + } + } + + // 'Removes' all the glyphs after the ellipsis glyph. + numberOfLaidOutGlyphs -= numberOfRemovedGlyphs; + } + } + } + + return numberOfLaidOutGlyphs; +} + const Vector4& View::GetTextColor() const { if ( mImpl->mVisualModel ) @@ -101,6 +238,16 @@ bool View::IsUnderlineEnabled() const return false; } +float View::GetUnderlineHeight() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetUnderlineHeight(); + } + return 0.0f; +} + Length View::GetNumberOfGlyphs() const { if( mImpl->mVisualModel ) @@ -118,26 +265,6 @@ Length View::GetNumberOfGlyphs() const return 0; } -void View::GetGlyphs( GlyphInfo* glyphs, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - if( mImpl->mVisualModel ) - { - mImpl->mVisualModel->GetGlyphs( glyphs, glyphIndex, numberOfGlyphs ); - } -} - -void View::GetGlyphPositions( Vector2* glyphPositions, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const -{ - if( mImpl->mVisualModel ) - { - mImpl->mVisualModel->GetGlyphPositions( glyphPositions, glyphIndex, numberOfGlyphs ); - } -} - } // namespace Text } // namespace Toolkit