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=caee1f8143a1f2b10cdd3e9a38ce9a266681a5ff;hp=e7bd2629c388191176addcea1946fa6acd6f3c5d;hb=95b3d088e01890ea7d105b98e6a7759903a42dfc;hpb=91c61abfba80ae007ca86fd12f25764395b207b0 diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index e7bd262..caee1f8 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -20,7 +20,7 @@ // EXTERNAL INCLUDES #include -#include +#include namespace Dali { @@ -55,8 +55,46 @@ void View::SetVisualModel( VisualModelPtr visualModel ) mImpl->mVisualModel = visualModel; } +const Vector2& View::GetControlSize() const +{ + if ( mImpl->mVisualModel ) + { + return mImpl->mVisualModel->mControlSize; + } + + return Vector2::ZERO; +} + +const Vector2& View::GetActualSize() const +{ + if ( mImpl->mVisualModel ) + { + return mImpl->mVisualModel->GetActualSize(); + } + + return Vector2::ZERO; +} + +Length View::GetNumberOfGlyphs() const +{ + if( mImpl->mVisualModel ) + { + const VisualModel& model = *mImpl->mVisualModel; + + const Length glyphCount = model.mGlyphs.Count(); + const Length positionCount = model.mGlyphPositions.Count(); + + DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" ); + + return (positionCount < glyphCount) ? positionCount : glyphCount; + } + + return 0; +} + Length View::GetGlyphs( GlyphInfo* glyphs, Vector2* glyphPositions, + Vector4* glyphColors, GlyphIndex glyphIndex, Length numberOfGlyphs ) const { @@ -67,7 +105,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs, // 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(); + const Length numberOfLines = mImpl->mVisualModel->mLines.Count(); if( numberOfLines > 0u ) { const LineRun& lastLine = *( mImpl->mVisualModel->mLines.Begin() + ( numberOfLines - 1u ) ); @@ -76,111 +114,186 @@ Length View::GetGlyphs( GlyphInfo* glyphs, // Otherwise use the given number of glyphs. if( lastLine.ellipsis ) { - numberOfLaidOutGlyphs = lastLine.glyphIndex + lastLine.numberOfGlyphs; + numberOfLaidOutGlyphs = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.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 ) + if( 0u < 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 ) + // Retrieve from the visual model the glyphs and positions. + mImpl->mVisualModel->GetGlyphs( glyphs, + glyphIndex, + numberOfLaidOutGlyphs ); + + mImpl->mVisualModel->GetGlyphPositions( glyphPositions, + glyphIndex, + numberOfLaidOutGlyphs ); + + // Set the colors. + const GlyphIndex lastLaidOutGlyphIndex = glyphIndex + numberOfLaidOutGlyphs; + + for( Vector::ConstIterator it = mImpl->mVisualModel->mColorRuns.Begin(), + endIt = mImpl->mVisualModel->mColorRuns.End(); + it != endIt; + ++it ) { - 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 ) ); + const ColorGlyphRun& colorGlyphRun = *it; + const GlyphIndex lastGlyphIndex = colorGlyphRun.glyphRun.glyphIndex + colorGlyphRun.glyphRun.numberOfGlyphs; - if( !firstPenSet ) + if( ( colorGlyphRun.glyphRun.glyphIndex < lastLaidOutGlyphIndex ) && + ( glyphIndex < lastGlyphIndex ) ) { - 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 ) + for( GlyphIndex index = glyphIndex < colorGlyphRun.glyphRun.glyphIndex ? colorGlyphRun.glyphRun.glyphIndex : glyphIndex, + endIndex = lastLaidOutGlyphIndex < lastGlyphIndex ? lastLaidOutGlyphIndex : lastGlyphIndex; + index < endIndex; + ++index ) { - // Avoids to exceed the bounding box when rtl text is elided. - firstPenX = -ellipsisGlyph.xBearing; + *( glyphColors + index - glyphIndex ) = colorGlyphRun.color; } + } + } - removedGlypsWidth = -ellipsisGlyph.xBearing; + // 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 ); - firstPenSet = true; - } + Vector lines; + lines.Resize( numberOfLines ); + LineRun* lineBuffer = lines.Begin(); - removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) ); + mImpl->mVisualModel->GetLinesOfGlyphRange( lineBuffer, + glyphIndex, + numberOfLaidOutGlyphs ); - // 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; + // Get the first line for the given glyph range. + LineIndex lineIndex = firstLine; + LineRun* line = lineBuffer + lineIndex; - // Replace the glyph by the ellipsis glyph. - glyphInfo = ellipsisGlyph; + // Index of the last glyph of the line. + GlyphIndex lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u; - // Change the 'x' and 'y' position of the ellipsis glyph. + // Add the alignment offset to the glyph's position. + for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index ) + { + ( *( glyphPositions + index ) ).x += line->alignmentOffset; + + if( lastGlyphIndexOfLine == index ) + { + // Get the next line. + ++lineIndex; - if( position.x > firstPenX ) + if( lineIndex < numberOfLines ) { - position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth; + line = lineBuffer + lineIndex; + lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u; } + } + } - position.x += ellipsisGlyph.xBearing; - position.y = penY - ellipsisGlyph.yBearing; + if( 1u == numberOfLaidOutGlyphs ) + { + // not a point try to do ellipsis with only one laid out character. + return numberOfLaidOutGlyphs; + } - inserted = true; - } - else + 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 ) { - if( index > 0u ) + const GlyphInfo& glyphToRemove = *( glyphs + index ); + + if( 0u != glyphToRemove.fontId ) { - --index; + // 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 ) ); + + 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 -= ( 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 ) + { + position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth; + } + + position.x += ellipsisGlyph.xBearing; + position.y = penY - ellipsisGlyph.yBearing; + + inserted = true; + } } - else + + if( !inserted ) { - // No space for the ellipsis. - inserted = true; + if( index > 0u ) + { + --index; + } + else + { + // No space for the ellipsis. + inserted = true; + } + ++numberOfRemovedGlyphs; } - ++numberOfRemovedGlyphs; } - } - // 'Removes' all the glyphs after the ellipsis glyph. - numberOfLaidOutGlyphs -= numberOfRemovedGlyphs; + // 'Removes' all the glyphs after the ellipsis glyph. + numberOfLaidOutGlyphs -= numberOfRemovedGlyphs; + } } } } @@ -190,79 +303,78 @@ Length View::GetGlyphs( GlyphInfo* glyphs, const Vector4& View::GetTextColor() const { - if ( mImpl->mVisualModel ) + if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - return model.GetTextColor(); + return mImpl->mVisualModel->GetTextColor(); } return Vector4::ZERO; } const Vector2& View::GetShadowOffset() const { - if ( mImpl->mVisualModel ) + if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - return model.GetShadowOffset(); + return mImpl->mVisualModel->GetShadowOffset(); } return Vector2::ZERO; } const Vector4& View::GetShadowColor() const { - if ( mImpl->mVisualModel ) + if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - return model.GetShadowColor(); + return mImpl->mVisualModel->GetShadowColor(); } return Vector4::ZERO; } const Vector4& View::GetUnderlineColor() const { - if ( mImpl->mVisualModel ) + if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - return model.GetUnderlineColor(); + return mImpl->mVisualModel->GetUnderlineColor(); } return Vector4::ZERO; } bool View::IsUnderlineEnabled() const { - if ( mImpl->mVisualModel ) + if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - return model.IsUnderlineEnabled(); + return mImpl->mVisualModel->IsUnderlineEnabled(); } return false; } float View::GetUnderlineHeight() const { - if ( mImpl->mVisualModel ) + if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - return model.GetUnderlineHeight(); + return mImpl->mVisualModel->GetUnderlineHeight(); } return 0.0f; } -Length View::GetNumberOfGlyphs() const +Length View::GetNumberOfUnderlineRuns() const { if( mImpl->mVisualModel ) { - VisualModel& model = *mImpl->mVisualModel; - - Length glyphCount = model.GetNumberOfGlyphs(); - Length positionCount = model.GetNumberOfGlyphPositions(); + return mImpl->mVisualModel->mUnderlineRuns.Count(); + } - DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" ); + return 0u; +} - return (positionCount < glyphCount) ? positionCount : glyphCount; +void View::GetUnderlineRuns( GlyphRun* underlineRuns, + UnderlineRunIndex index, + Length numberOfRuns ) const +{ + if( mImpl->mVisualModel ) + { + mImpl->mVisualModel->GetUnderlineRuns( underlineRuns, + index, + numberOfRuns ); } - - return 0; } } // namespace Text