X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-view.cpp;h=83ad28fd8aba8e4bcc8b824c6a8a7b2e1083103c;hb=d74d70d51ed70b00e29a2b6feac5419124fffc49;hp=be6ac8f9733cd7bc420544da1f1064b59dca2d02;hpb=32b0b5f6c65842c8bd1140b1eeb9691fdca0c866;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index be6ac8f..83ad28f 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -19,26 +19,23 @@ #include // EXTERNAL INCLUDES -#include #include +#include namespace Dali { - namespace Toolkit { - namespace Text { - struct View::Impl { - VisualModelPtr mVisualModel; + VisualModelPtr mVisualModel; TextAbstraction::FontClient mFontClient; ///< Handle to the font client. }; View::View() -: mImpl( NULL ) +: mImpl(NULL) { mImpl = new View::Impl(); @@ -50,14 +47,14 @@ View::~View() delete mImpl; } -void View::SetVisualModel( VisualModelPtr visualModel ) +void View::SetVisualModel(VisualModelPtr visualModel) { mImpl->mVisualModel = visualModel; } const Vector2& View::GetControlSize() const { - if ( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->mControlSize; } @@ -67,7 +64,7 @@ const Vector2& View::GetControlSize() const const Vector2& View::GetLayoutSize() const { - if ( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->GetLayoutSize(); } @@ -77,14 +74,14 @@ const Vector2& View::GetLayoutSize() const Length View::GetNumberOfGlyphs() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { const VisualModel& model = *mImpl->mVisualModel; - const Length glyphCount = model.mGlyphs.Count(); + const Length glyphCount = model.mGlyphs.Count(); const Length positionCount = model.mGlyphPositions.Count(); - DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" ); + DALI_ASSERT_DEBUG(positionCount <= glyphCount && "Invalid glyph positions in Model"); return (positionCount < glyphCount) ? positionCount : glyphCount; } @@ -92,26 +89,27 @@ Length View::GetNumberOfGlyphs() const return 0; } -Length View::GetGlyphs( GlyphInfo* glyphs, - Vector2* glyphPositions, - GlyphIndex glyphIndex, - Length numberOfGlyphs ) const +Length View::GetGlyphs(GlyphInfo* glyphs, + Vector2* glyphPositions, + float& minLineOffset, + GlyphIndex glyphIndex, + Length numberOfGlyphs) const { Length numberOfLaidOutGlyphs = 0u; - if( mImpl->mVisualModel ) + 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->mLines.Count(); - if( numberOfLines > 0u ) + if(numberOfLines > 0u) { - const LineRun& lastLine = *( mImpl->mVisualModel->mLines.Begin() + ( numberOfLines - 1u ) ); + 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 ) + if(lastLine.ellipsis) { numberOfLaidOutGlyphs = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs; } @@ -120,60 +118,62 @@ Length View::GetGlyphs( GlyphInfo* glyphs, numberOfLaidOutGlyphs = numberOfGlyphs; } - if( 0u < numberOfLaidOutGlyphs ) + if(0u < numberOfLaidOutGlyphs) { // Retrieve from the visual model the glyphs and positions. - mImpl->mVisualModel->GetGlyphs( glyphs, - glyphIndex, - numberOfLaidOutGlyphs ); + mImpl->mVisualModel->GetGlyphs(glyphs, + glyphIndex, + numberOfLaidOutGlyphs); - mImpl->mVisualModel->GetGlyphPositions( glyphPositions, - glyphIndex, - numberOfLaidOutGlyphs ); + mImpl->mVisualModel->GetGlyphPositions(glyphPositions, + glyphIndex, + numberOfLaidOutGlyphs); // Get the lines for the given range of glyphs. // The lines contain the alignment offset which needs to be added to the glyph's position. - LineIndex firstLine = 0u; - Length numberOfLines = 0u; - mImpl->mVisualModel->GetNumberOfLines( glyphIndex, - numberOfLaidOutGlyphs, - firstLine, - numberOfLines ); + LineIndex firstLine = 0u; + Length numberOfLines = 0u; + mImpl->mVisualModel->GetNumberOfLines(glyphIndex, + numberOfLaidOutGlyphs, + firstLine, + numberOfLines); Vector lines; - lines.Resize( numberOfLines ); + lines.Resize(numberOfLines); LineRun* lineBuffer = lines.Begin(); - mImpl->mVisualModel->GetLinesOfGlyphRange( lineBuffer, - glyphIndex, - numberOfLaidOutGlyphs ); + mImpl->mVisualModel->GetLinesOfGlyphRange(lineBuffer, + glyphIndex, + numberOfLaidOutGlyphs); // Get the first line for the given glyph range. LineIndex lineIndex = firstLine; - LineRun* line = lineBuffer + lineIndex; + LineRun* line = lineBuffer + lineIndex; // Index of the last glyph of the line. GlyphIndex lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u; // Add the alignment offset to the glyph's position. - float penY = line->ascender; - for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index ) + minLineOffset = line->alignmentOffset; + float penY = line->ascender; + for(Length index = 0u; index < numberOfLaidOutGlyphs; ++index) { - Vector2& position = *( glyphPositions + index ); + Vector2& position = *(glyphPositions + index); position.x += line->alignmentOffset; position.y += penY; - if( lastGlyphIndexOfLine == index ) + if(lastGlyphIndexOfLine == index) { penY += -line->descender; // Get the next line. ++lineIndex; - if( lineIndex < numberOfLines ) + if(lineIndex < numberOfLines) { - line = lineBuffer + lineIndex; + line = lineBuffer + lineIndex; + minLineOffset = std::min(minLineOffset, line->alignmentOffset); lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u; @@ -182,47 +182,65 @@ Length View::GetGlyphs( GlyphInfo* glyphs, } } - if( 1u == numberOfLaidOutGlyphs ) + if(1u == numberOfLaidOutGlyphs) { // not a point try to do ellipsis with only one laid out character. return numberOfLaidOutGlyphs; } - if( lastLine.ellipsis ) + if(lastLine.ellipsis) { + if((1u == numberOfLines) && + (lastLine.ascender - lastLine.descender > mImpl->mVisualModel->mControlSize.height)) + { + // Get the first glyph which is going to be replaced and the ellipsis glyph. + GlyphInfo& glyphInfo = *glyphs; + const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph(mImpl->mFontClient.GetPointSize(glyphInfo.fontId)); + + // Change the 'x' and 'y' position of the ellipsis glyph. + Vector2& position = *glyphPositions; + position.x = ellipsisGlyph.xBearing; + position.y = mImpl->mVisualModel->mControlSize.height - ellipsisGlyph.yBearing; + + // Replace the glyph by the ellipsis glyph. + glyphInfo = ellipsisGlyph; + + return 1u; + } + // 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; + 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; + 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 ) + while(!inserted) { - const GlyphInfo& glyphToRemove = *( glyphs + index ); + const GlyphInfo& glyphToRemove = *(glyphs + index); - if( 0u != glyphToRemove.fontId ) + if(0u != glyphToRemove.fontId) { // i.e. The font id of the glyph shaped from the '\n' character is zero. // Need to reshape the glyph as the font may be different in size. - const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) ); + const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph(mImpl->mFontClient.GetPointSize(glyphToRemove.fontId)); - if( !firstPenSet ) + if(!firstPenSet) { - const Vector2& position = *( glyphPositions + index ); + 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 ) + if(firstPenX < -ellipsisGlyph.xBearing) { // Avoids to exceed the bounding box when rtl text is elided. firstPenX = -ellipsisGlyph.xBearing; @@ -233,22 +251,22 @@ Length View::GetGlyphs( GlyphInfo* glyphs, firstPenSet = true; } - removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) ); + 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 ) + if(ellipsisGlyphWidth < removedGlypsWidth) { - GlyphInfo& glyphInfo = *( glyphs + index ); - Vector2& position = *( glyphPositions + index ); - position.x -= ( 0.f > glyphInfo.xBearing ) ? glyphInfo.xBearing : 0.f; + GlyphInfo& glyphInfo = *(glyphs + index); + Vector2& position = *(glyphPositions + index); + position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f; // Replace the glyph by the ellipsis glyph. glyphInfo = ellipsisGlyph; // Change the 'x' and 'y' position of the ellipsis glyph. - if( position.x > firstPenX ) + if(position.x > firstPenX) { position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth; } @@ -260,9 +278,9 @@ Length View::GetGlyphs( GlyphInfo* glyphs, } } - if( !inserted ) + if(!inserted) { - if( index > 0u ) + if(index > 0u) { --index; } @@ -287,7 +305,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs, const Vector4* const View::GetColors() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->mColors.Begin(); } @@ -297,7 +315,7 @@ const Vector4* const View::GetColors() const const ColorIndex* const View::GetColorIndices() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->mColorIndices.Begin(); } @@ -305,9 +323,29 @@ const ColorIndex* const View::GetColorIndices() const return NULL; } +const Vector4* const View::GetBackgroundColors() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->mBackgroundColors.Begin(); + } + + return nullptr; +} + +const ColorIndex* const View::GetBackgroundColorIndices() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->mBackgroundColorIndices.Begin(); + } + + return nullptr; +} + const Vector4& View::GetTextColor() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->GetTextColor(); } @@ -316,7 +354,7 @@ const Vector4& View::GetTextColor() const const Vector2& View::GetShadowOffset() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->GetShadowOffset(); } @@ -325,7 +363,7 @@ const Vector2& View::GetShadowOffset() const const Vector4& View::GetShadowColor() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->GetShadowColor(); } @@ -334,7 +372,7 @@ const Vector4& View::GetShadowColor() const const Vector4& View::GetUnderlineColor() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->GetUnderlineColor(); } @@ -343,7 +381,7 @@ const Vector4& View::GetUnderlineColor() const bool View::IsUnderlineEnabled() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->IsUnderlineEnabled(); } @@ -352,7 +390,7 @@ bool View::IsUnderlineEnabled() const float View::GetUnderlineHeight() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { return mImpl->mVisualModel->GetUnderlineHeight(); } @@ -361,26 +399,44 @@ float View::GetUnderlineHeight() const Length View::GetNumberOfUnderlineRuns() const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { - return mImpl->mVisualModel->mUnderlineRuns.Count(); + return mImpl->mVisualModel->GetNumberOfUnderlineRuns(); } return 0u; } -void View::GetUnderlineRuns( GlyphRun* underlineRuns, - UnderlineRunIndex index, - Length numberOfRuns ) const +void View::GetUnderlineRuns(GlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns) const { - if( mImpl->mVisualModel ) + if(mImpl->mVisualModel) { - mImpl->mVisualModel->GetUnderlineRuns( underlineRuns, - index, - numberOfRuns ); + mImpl->mVisualModel->GetUnderlineRuns(underlineRuns, + index, + numberOfRuns); } } +const Vector4& View::GetOutlineColor() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->GetOutlineColor(); + } + return Vector4::ZERO; +} + +uint16_t View::GetOutlineWidth() const +{ + if(mImpl->mVisualModel) + { + return mImpl->mVisualModel->GetOutlineWidth(); + } + return 0u; +} + } // namespace Text } // namespace Toolkit