diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-10-17 17:04:03 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-10-17 18:45:29 +0200 |
commit | 8fa7d052e772ebdb612e596cf06bf57bf88da12f (patch) | |
tree | a9cc9911aa256cbf8cb8dac840e7341c5e460b73 /editeng | |
parent | 3a44d7058dd7f7addf21d9292104d7eb73ec9716 (diff) |
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@libreoffice.org>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'editeng')
-rw-r--r-- | editeng/source/editeng/impedit3.cxx | 89 |
1 files changed, 70 insertions, 19 deletions
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; } } } |