[Libreoffice-commits] core.git: editeng/source

Armin Le Grand Armin.Le.Grand at cib.de
Tue Oct 17 16:45:52 UTC 2017


 editeng/source/editeng/impedit3.cxx |   89 ++++++++++++++++++++++++++++--------
 1 file changed, 70 insertions(+), 19 deletions(-)

New commits:
commit 8fa7d052e772ebdb612e596cf06bf57bf88da12f
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Oct 17 17:04:03 2017 +0200

    EditEngine: Enhance visualization of URLs
    
    When URLs get layouted Multi-Lined from the EditEngine,
    a rough 'guess' how many chars per line should be used
    was in place up to now. This could lead to lines being
    too short or being longer than the available space, also
    looked ugly. Layouting now using the needed space properly.
    Also adapted vertical (for horizontal text) space usage,
    with multiple lines the space was 'compressed' and wrong
    calculated.
    
    Change-Id: I7255e3e65c85a3a50497b771ed2ca1ef5d97c0dd
    Reviewed-on: https://gerrit.libreoffice.org/43464
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>

diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
index f68f2eff166a..0a5bd8490809 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -1045,32 +1045,77 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
                         OUString aFieldValue = cChar ? OUString(cChar) : static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue();
                         if ( bCalcCharPositions || !pPortion->HasValidSize() )
                         {
-                            pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(), aFieldValue, 0, aFieldValue.getLength() );
+                            // get size, but also DXArray to allow length information in line breaking below
+                            const sal_Int32 nLength(aFieldValue.getLength());
+                            std::unique_ptr<long[]> pTmpDXArray(new long[nLength]);
+                            pPortion->GetSize() = aTmpFont.QuickGetTextSize(GetRefDevice(), aFieldValue, 0, aFieldValue.getLength(), pTmpDXArray.get());
+
                             // So no scrolling for oversized fields
                             if ( pPortion->GetSize().Width() > nXWidth )
                             {
-                                sal_Int32 nWidthOrg         = pPortion->GetSize().Width();
-                                sal_Int32 nChars            = aFieldValue.getLength();
-                                sal_Int32 nApproxWC         = nXWidth / ( nWidthOrg / nChars );
-                                ExtraPortionInfo *pExtraInfo= pPortion->GetExtraInfos();
-                                if( !nApproxWC ) nApproxWC++;
-                                if( pExtraInfo == nullptr )
+                                // create ExtraPortionInfo on-demand, flush lineBreaksList
+                                ExtraPortionInfo *pExtraInfo = pPortion->GetExtraInfos();
+
+                                if(nullptr == pExtraInfo)
                                 {
                                     pExtraInfo = new ExtraPortionInfo();
                                     pExtraInfo->nOrgWidth = nXWidth;
-                                    pPortion->SetExtraInfos( pExtraInfo );
+                                    pPortion->SetExtraInfos(pExtraInfo);
                                 }
                                 else
                                 {
                                     pExtraInfo->lineBreaksList.clear();
                                 }
 
-                                pPortion->GetSize().Width() = nXWidth;
-
-                                while( nChars > 0 )
+                                // iterate over CellBreaks using XBreakIterator to be on the
+                                // safe side with international texts/charSets
+                                Reference < i18n::XBreakIterator > xBreakIterator(ImplGetBreakIterator());
+                                const sal_Int32 nTextLength(aFieldValue.getLength());
+                                const lang::Locale aLocale(GetLocale(EditPaM(pNode, nPortionStart)));
+                                sal_Int32 nDone(0);
+                                sal_Int32 nNextCellBreak(
+                                    xBreakIterator->nextCharacters(
+                                            aFieldValue,
+                                            0,
+                                            aLocale,
+                                            css::i18n::CharacterIteratorMode::SKIPCELL,
+                                            0,
+                                            nDone));
+                                sal_Int32 nLastCellBreak(0);
+                                sal_Int32 nLineStartX(0);
+
+                                // always add 1st line break (safe, we already know we are larger than nXWidth)
+                                pExtraInfo->lineBreaksList.push_back(0);
+
+                                for(sal_Int32 a(0); a < nTextLength; a++)
                                 {
-                                    pExtraInfo->lineBreaksList.push_back( aFieldValue.getLength() - nChars );
-                                    nChars -= nApproxWC;
+                                    if(a == nNextCellBreak)
+                                    {
+                                        // check width
+                                        if(pTmpDXArray[a] - nLineStartX > nXWidth)
+                                        {
+                                            // new CellBreak does not fit in current line, need to
+                                            // create a break at LastCellBreak - but do not add 1st
+                                            // line break twice for very tall frames
+                                            if(0 != a)
+                                            {
+                                                pExtraInfo->lineBreaksList.push_back(a);
+                                            }
+
+                                            // moveLineStart forward in X
+                                            nLineStartX = pTmpDXArray[nLastCellBreak];
+                                        }
+
+                                        // update CellBreak iteration values
+                                        nLastCellBreak = a;
+                                        nNextCellBreak = xBreakIterator->nextCharacters(
+                                            aFieldValue,
+                                            a,
+                                            aLocale,
+                                            css::i18n::CharacterIteratorMode::SKIPCELL,
+                                            1,
+                                            nDone);
+                                    }
                                 }
                             }
                         }
@@ -3262,26 +3307,32 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, tools::Rectangle aClipRect, Po
                                         bParsingFields = true;
                                         itSubLines = pExtraInfo->lineBreaksList.begin();
                                     }
+
                                     if( bParsingFields )
                                     {
                                         if( itSubLines != pExtraInfo->lineBreaksList.begin() )
                                         {
+                                            // only use GetMaxAscent(), pLine->GetHeight() will not
+                                            // proceed as needed (see PortionKind::TEXT above and nAdvanceY)
+                                            // what will lead to a compressed look with multiple lines
+                                            const sal_uInt16 nMaxAscent(pLine->GetMaxAscent());
+
                                             if ( !IsVertical() )
                                             {
-                                                aStartPos.Y() += pLine->GetMaxAscent();
-                                                aTmpPos.Y() += pLine->GetHeight();
+                                                aStartPos.Y() += nMaxAscent;
+                                                aTmpPos.Y() += nMaxAscent;
                                             }
                                             else
                                             {
                                                 if (IsTopToBottom())
                                                 {
-                                                    aTmpPos.X() -= pLine->GetMaxAscent();
-                                                    aStartPos.X() -= pLine->GetHeight();
+                                                    aTmpPos.X() -= nMaxAscent;
+                                                    aStartPos.X() -= nMaxAscent;
                                                 }
                                                 else
                                                 {
-                                                    aTmpPos.X() += pLine->GetMaxAscent();
-                                                    aStartPos.X() += pLine->GetHeight();
+                                                    aTmpPos.X() += nMaxAscent;
+                                                    aStartPos.X() += nMaxAscent;
                                                 }
                                             }
                                         }


More information about the Libreoffice-commits mailing list