summaryrefslogtreecommitdiff
path: root/editeng
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2017-10-17 17:04:03 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2017-10-17 18:45:29 +0200
commit8fa7d052e772ebdb612e596cf06bf57bf88da12f (patch)
treea9cc9911aa256cbf8cb8dac840e7341c5e460b73 /editeng
parent3a44d7058dd7f7addf21d9292104d7eb73ec9716 (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.cxx89
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;
}
}
}