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

New commits:
commit 8fa7d052e772ebdb612e596cf06bf57bf88da12f
Author: Armin Le Grand <armin.le.gr...@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 <c...@libreoffice.org>
    Reviewed-by: Armin Le Grand <armin.le.gr...@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;
                                                 }
                                             }
                                         }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to