47#define GF_FONTMASK 0xF0000000
48#define GF_FONTSHIFT 28
54 if( (nChar <
'0') || (
'9' < nChar) )
63 nOffset = 0x0660 -
'0';
69 nOffset = 0x06F0 -
'0';
71 nOffset = 0x09E6 -
'0';
73 nOffset = 0x0966 -
'0';
78 nOffset = 0x1369 -
'0';
80 nOffset = 0x0AE6 -
'0';
81#ifdef LANGUAGE_GURMUKHI
82 else if ( pri ==
primary(LANGUAGE_GURMUKHI) )
83 nOffset = 0x0A66 -
'0';
86 nOffset = 0x0CE6 -
'0';
88 nOffset = 0x17E0 -
'0';
90 nOffset = 0x0ED0 -
'0';
92 nOffset = 0x0D66 -
'0';
99 nOffset = 0x1810 -
'0';
104 nOffset = 0x1040 -
'0';
106 nOffset = 0x0B66 -
'0';
108 nOffset = 0x0BE7 -
'0';
110 nOffset = 0x0C66 -
'0';
112 nOffset = 0x0E50 -
'0';
114 nOffset = 0x0F20 -
'0';
129 maDrawOffset( 0, 0 ),
130 mbTextRenderModeForResolutionIndependentLayout(false)
156 static double fCos = 1.0, fSin = 0.0;
165 double fX = aOfs.
getX();
166 double fY = aOfs.
getY();
169 double nX = +fCos * fX + fSin * fY;
170 double nY = +fCos * fY - fSin * fX;
195 while (
GetNextGlyph(&pGlyph, aPos, nStart, &pGlyphFont))
202 if( bSuccess && (aGlyphOutline.
count() > 0) )
210 rVector.push_back( aGlyphOutline );
214 return (bAllOk && bOneOk);
228 while (
GetNextGlyph(&pGlyph, aPos, nStart, &pGlyphFont))
244 rRect.
Union(aRectangle);
274 nWidth += aGlyphItem.newWidth();
282 if( !nOldWidth || nNewWidth==nOldWidth )
290 std::vector<GlyphItem>::iterator pGlyphIterRight =
m_GlyphItems.begin();
292 std::vector<GlyphItem>::iterator pGlyphIter;
294 int nStretchable = 0;
295 int nMaxGlyphWidth = 0;
296 for(pGlyphIter =
m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter)
298 if( !pGlyphIter->IsInCluster() )
300 if (nMaxGlyphWidth < pGlyphIter->origWidth())
301 nMaxGlyphWidth = pGlyphIter->origWidth();
305 nOldWidth -= pGlyphIterRight->origWidth();
308 if( nNewWidth < nMaxGlyphWidth)
309 nNewWidth = nMaxGlyphWidth;
310 nNewWidth -= pGlyphIterRight->origWidth();
311 pGlyphIterRight->setLinearPosX( nNewWidth );
314 int nDiffWidth = nNewWidth - nOldWidth;
319 for( pGlyphIter =
m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter )
322 pGlyphIter->adjustLinearPosX(nDeltaSum);
325 if( pGlyphIter->IsInCluster() || (nStretchable <= 0) )
329 int nDeltaWidth = nDiffWidth / nStretchable--;
330 nDiffWidth -= nDeltaWidth;
331 pGlyphIter->addNewWidth(nDeltaWidth);
332 nDeltaSum += nDeltaWidth;
338 double fSqueeze =
static_cast<double>(nNewWidth) / nOldWidth;
341 for( pGlyphIter =
m_GlyphItems.begin(); ++pGlyphIter != pGlyphIterRight;)
343 int nX = pGlyphIter->linearPos().getX();
344 nX =
static_cast<int>(nX * fSqueeze);
345 pGlyphIter->setLinearPosX( nX );
349 for( pGlyphIter =
m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter )
350 pGlyphIter->setNewWidth( pGlyphIter[1].linearPos().getX() - pGlyphIter[0].linearPos().getX());
361 static const signed char nTable[0x30] =
363 0, -2, -2, 0, 0, 0, 0, 0, +2, -2, +2, -2, +2, -2, +2, -2,
364 +2, -2, 0, 0, +2, -2, +2, -2, 0, 0, 0, 0, 0, +2, -2, -2,
365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, +2, +2, -2, -2
369 if( (c >= 0x3000) && (c < 0x3030) )
370 nResult = nTable[ c - 0x3000 ];
374 nResult = bLeft ? -1 : +1;
376 case 0x2019:
case 0x201D:
377 case 0xFF01:
case 0xFF09:
case 0xFF0C:
378 case 0xFF1A:
case 0xFF1B:
381 case 0x2018:
case 0x201C:
394 return (0x3000 == (cp & 0xFF00)) || (0xFF00 == (cp & 0xFF00)) || (0x2010 == (cp & 0xFFF0));
399 const int nLength = rStr.size();
402 for (std::vector<GlyphItem>::iterator pGlyphIter =
m_GlyphItems.begin(),
404 pGlyphIter != pGlyphIterEnd; ++pGlyphIter)
406 const int n = pGlyphIter->charPos();
419 if (nKernCurrent == 0)
426 DeviceCoordinate nDelta = (nKernCurrent < nKernNext) ? nKernCurrent : nKernNext;
429 nDelta = (nDelta * pGlyphIter->origWidth() + 2) / 4;
430 if( pGlyphIter+1 == pGlyphIterEnd )
431 pGlyphIter->addNewWidth( nDelta );
437 if( pGlyphIter+1 != pGlyphIterEnd )
438 pGlyphIter->adjustLinearPosX(nOffset);
445 for (
int i = 0;
i < nMaxIndex; ++
i)
446 pCaretXArray[
i] = -1;
452 tools::Long nXRight = nXPos + aGlyphItem.origWidth();
453 int n = aGlyphItem.charPos();
456 if (aGlyphItem.IsInCluster() && pCaretXArray[nCurrIdx] != -1)
458 if (!aGlyphItem.IsRTLGlyph() )
461 pCaretXArray[ nCurrIdx ] = nXPos;
462 pCaretXArray[ nCurrIdx+1 ] = nXRight;
467 pCaretXArray[ nCurrIdx ] = nXRight;
468 pCaretXArray[ nCurrIdx+1 ] = nXPos;
475 std::vector<DeviceCoordinate> aCharWidths;
486 if( nWidth > nMaxWidth )
489 nWidth += nCharExtra;
500 std::vector<GlyphItem>::const_iterator pGlyphIter =
m_GlyphItems.begin();
501 std::vector<GlyphItem>::const_iterator pGlyphIterEnd =
m_GlyphItems.end();
502 pGlyphIter += nStart;
505 for(; pGlyphIter != pGlyphIterEnd; ++nStart, ++pGlyphIter )
507 int n = pGlyphIter->charPos();
516 if( pGlyphIter == pGlyphIterEnd )
520 *pGlyph = &(*pGlyphIter);
526 DevicePoint aRelativePos = pGlyphIter->linearPos();
538 std::vector<GlyphItem>::iterator pGlyphIter =
m_GlyphItems.begin();
539 pGlyphIter += nStart;
544 if( pGlyphIter->IsRTLGlyph() )
545 nNewXPos += pGlyphIter->newWidth() - pGlyphIter->origWidth();
547 double nXDelta = nNewXPos - pGlyphIter->linearPos().getX() + pGlyphIter->xOffset();
551 for( std::vector<GlyphItem>::iterator pGlyphIterEnd =
m_GlyphItems.end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter )
553 pGlyphIter->adjustLinearPosX(nXDelta);
563 std::vector<GlyphItem>::iterator pGlyphIter =
m_GlyphItems.begin();
564 pGlyphIter += nStart;
565 pGlyphIter->dropGlyph();
590, mbIncomplete( false )
637 std::vector<DeviceCoordinate> aJustificationArray;
638 std::vector<double> aNaturalJustificationArray;
657 int nStretchable = 0;
658 for(
int i = 0;
i < nCharCount; ++
i )
661 nOrigWidth += aJustificationArray[
i];
662 if( aJustificationArray[
i] > 0 )
667 if( nOrigWidth && (nTargetWidth != nOrigWidth) )
671 for(
int i = 0;
i < nCharCount; ++
i )
674 if( (nJustWidth > 0) && (nStretchable > 0) )
677 nJustWidth += nDeltaWidth;
678 nDiffWidth -= nDeltaWidth;
681 nWidthSum += nJustWidth;
682 aJustificationArray[
i] = nWidthSum;
684 if( nWidthSum != nTargetWidth )
685 aJustificationArray[ nCharCount-1 ] = nTargetWidth;
687 aNaturalJustificationArray.reserve(aJustificationArray.size());
689 aNaturalJustificationArray.push_back(
a);
700 const double* pMultiDXArray)
707 int nRunStart, nRunEnd;
708 while (rArgs.
GetNextRun(&nRunStart, &nRunEnd, &bRtl))
710 if (bRtl) std::fill(vRtl.begin() + (nRunStart - rArgs.
mnMinCharPos),
743 nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
744 bValid[nLevel] =
mpLayouts[
n]->GetNextGlyph(&pGlyphs[nLevel], aPos, nStartNew[nLevel]);
746 if( (
n > 0) && !bValid[ nLevel ] )
766 for(
n = 0;
n < nLevel; ++
n )
769 int nFirstValid = -1;
770 for(
n = 0;
n < nLevel; ++
n )
778 assert(nFirstValid >= 0);
781 int nActiveCharPos = pGlyphs[nFirstValid]->
charPos();
784 int nLastRunEndChar = (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex]) ?
786 int nRunVisibleEndChar = pGlyphs[nFirstValid]->
charPos();
788 while( bValid[nFirstValid] && (nLevel > 0))
791 for(
n = 0;
n < nLevel; ++
n )
811 (
maFallbackRuns[
n-1].PosIsInAnyRun(pGlyphs[nFirstValid]->charPos())) &&
816 nStartOld[0] = nStartNew[0];
817 bValid[nFirstValid] =
mpLayouts[0]->GetNextGlyph(&pGlyphs[nFirstValid], aPos, nStartNew[0]);
819 if( !bValid[nFirstValid] )
825 double nRunAdvance = 0;
826 bool bKeepNotDef = (nFBLevel >= nLevel);
832 nStartOld[
n] = nStartNew[
n];
833 int nOrigCharPos = pGlyphs[
n]->
charPos();
834 bValid[
n] =
mpLayouts[
n]->GetNextGlyph(&pGlyphs[
n], aPos, nStartNew[
n]);
847 if ((
n+1 < nLevel) && (pGlyphs[
n]->
charPos() != nOrigCharPos))
849 if (nOrigCharPos < pGlyphs[
n]->charPos())
851 if (pGlyphs[
n+1]->charPos() > nOrigCharPos && (pGlyphs[
n+1]->
charPos() < pGlyphs[
n]->
charPos()))
854 else if (nOrigCharPos > pGlyphs[
n]->charPos())
856 if (pGlyphs[
n+1]->charPos() > pGlyphs[
n]->
charPos() && (pGlyphs[
n+1]->
charPos() < nOrigCharPos))
873 if (!
maFallbackRuns[nLevel-1].PosIsInRun(pGlyphs[nFirstValid]->charPos()))
876 if( bKeepNotDef && !bNeedFallback )
878 bKeepNotDef = bNeedFallback;
892 nRunVisibleEndChar = pGlyphs[
n]->
charPos();
898 nRunVisibleEndChar = pGlyphs[
n]->
charPos();
911 if (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex])
914 nRunAdvance -= pMultiDXArray[nRunVisibleEndChar - 1 -
mnMinCharPos];
916 nRunAdvance += pMultiDXArray[nLastRunEndChar - 1 -
mnMinCharPos];
921 nRunAdvance += pMultiDXArray[nRunVisibleEndChar -
mnMinCharPos];
923 nRunAdvance -= pMultiDXArray[nLastRunEndChar -
mnMinCharPos];
925 nLastRunEndChar = nRunVisibleEndChar;
926 nRunVisibleEndChar = pGlyphs[nFirstValid]->
charPos();
930 nXPos += nRunAdvance;
933 nActiveCharPos = pGlyphs[nFirstValid]->
charPos();
937 for(
int i = nFBLevel; --
i >= 0;)
943 if (nRunStart > nActiveCharPos)
948 if (nRunEnd <= nActiveCharPos)
984 return mpLayouts[0]->GetTextBreak( nMaxWidth, nCharExtra, nFactor );
987 std::vector<DeviceCoordinate> aCharWidths;
988 std::vector<DeviceCoordinate> aFallbackCharWidths;
989 mpLayouts[0]->FillDXArray( &aCharWidths, {} );
995 for(
int i = 0;
i < nCharCount; ++
i )
996 if( aCharWidths[
i ] == 0 )
997 aCharWidths[
i] = aFallbackCharWidths[
i];
1001 for(
int i = 0;
i < nCharCount; ++
i )
1003 nWidth += aCharWidths[
i ] * nFactor;
1004 if( nWidth > nMaxWidth )
1006 nWidth += nCharExtra;
1017 std::vector<DeviceCoordinate> aTempWidths;
1021 pCharWidths->clear();
1022 pCharWidths->resize(nCharCount, 0);
1032 if( nMaxWidth < nTextWidth )
1033 nMaxWidth = nTextWidth;
1037 for(
int i = 0;
i < nCharCount; ++
i )
1041 if( (*pCharWidths)[
i] != 0 )
1046 (*pCharWidths)[
i] = nCharWidth;
1061 std::unique_ptr<sal_Int32[]>
const pTempPos(
new sal_Int32[nMaxIndex]);
1064 mpLayouts[
n ]->GetCaretPositions( nMaxIndex, pTempPos.get() );
1065 for(
int i = 0;
i < nMaxIndex; ++
i )
1066 if( pTempPos[
i] >= 0 )
1067 pCaretXArray[
i] = pTempPos[
i];
1076 int nLevel =
static_cast<unsigned>(nStart) >>
GF_FONTSHIFT;
1077 nStart &= ~GF_FONTMASK;
1078 for(; nLevel <
mnLevel; ++nLevel, nStart=0 )
1082 if (rLayout.
GetNextGlyph(pGlyph, rPos, nStart, ppGlyphFont))
1117 bool bValid =
mpLayouts[0]->IsKashidaPosValid(nCharPos, nNextCharPos);
1129 bValid =
mpLayouts[
i]->IsKashidaPosValid(nCharPos, nNextCharPos);
void DropGlyph(int nStart)
SalLayoutGlyphsImpl m_GlyphItems
void GetCaretPositions(int nArraySize, sal_Int32 *pCaretXArray) const final override
void Justify(DeviceCoordinate nNewWidth)
DeviceCoordinate FillDXArray(std::vector< DeviceCoordinate > *pDXArray, const OUString &rStr) const final override
DeviceCoordinate GetTextWidth() const final override
void GetCharWidths(std::vector< DeviceCoordinate > &rCharWidths, const OUString &rStr) const
void MoveGlyph(int nStart, double nNewXPos)
bool GetNextGlyph(const GlyphItem **pGlyph, DevicePoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const override
void Simplify(bool bIsBase)
void ApplyAsianKerning(std::u16string_view rStr)
sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const final override
bool GetGlyphBoundRect(const LogicalFontInstance *, tools::Rectangle &) const
bool GetGlyphOutline(const LogicalFontInstance *, basegfx::B2DPolyPolygon &) const
DeviceCoordinate newWidth() const
bool PosIsInRun(int nCharPos) const
bool PosIsInAnyRun(int nCharPos) const
bool GetOutline(basegfx::B2DPolyPolygonVector &) const override
void AdjustLayout(vcl::text::ImplLayoutArgs &) override
void ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs &rArgs, vcl::text::ImplLayoutArgs &rMultiArgs, const double *pMultiDXArray)
void SetIncomplete(bool bIncomplete)
std::unique_ptr< GenericSalLayout > mpLayouts[MAX_FALLBACK]
std::unique_ptr< SalLayout > ReleaseBaseLayout()
void DrawText(SalGraphics &) const override
void InitFont() const override
DeviceCoordinate FillDXArray(std::vector< DeviceCoordinate > *pDXArray, const OUString &rStr) const override
sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override
bool LayoutText(vcl::text::ImplLayoutArgs &, const SalLayoutGlyphsImpl *) override
SalLayoutGlyphs GetGlyphs() const final override
void GetCaretPositions(int nArraySize, sal_Int32 *pCaretXArray) const override
ImplLayoutRuns maFallbackRuns[MAX_FALLBACK]
void AddFallback(std::unique_ptr< SalLayout > pFallbackLayout, ImplLayoutRuns const &)
virtual ~MultiSalLayout() override
bool GetNextGlyph(const GlyphItem **pGlyph, DevicePoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const override
bool IsKashidaPosValid(int nCharPos, int nNextCharPos) const override
MultiSalLayout(std::unique_ptr< SalLayout > pBaseLayout)
const rtl::Reference< LogicalFontInstance > & GetFont() const
void AppendImpl(SalLayoutGlyphsImpl *pImpl)
virtual void GetCaretPositions(int nArraySize, sal_Int32 *pCaretXArray) const =0
bool mbTextRenderModeForResolutionIndependentLayout
LanguageTag maLanguageTag
virtual void InitFont() const
virtual bool GetOutline(basegfx::B2DPolyPolygonVector &) const
virtual bool GetNextGlyph(const GlyphItem **pGlyph, DevicePoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const =0
bool GetBoundRect(tools::Rectangle &) const
DevicePoint GetDrawPosition(const DevicePoint &rRelative=DevicePoint(0, 0)) const
virtual void AdjustLayout(vcl::text::ImplLayoutArgs &)
virtual void DrawText(SalGraphics &) const =0
virtual DeviceCoordinate FillDXArray(std::vector< DeviceCoordinate > *pDXArray, const OUString &rStr) const =0
virtual SalLayoutGlyphs GetGlyphs() const
void transform(const basegfx::B2DHomMatrix &rMatrix)
bool GetNextRun(int *nMinRunPos, int *nEndRunPos, bool *bRTL)
DeviceCoordinate mnLayoutWidth
const double * mpNaturalDXArray
LanguageTag maLanguageTag
sal_Int32 DeviceCoordinate
basegfx::B2DPoint DevicePoint
#define LANGUAGE_MONGOLIAN_MONGOLIAN_CHINA
#define LANGUAGE_MONGOLIAN_MONGOLIAN_MONGOLIA
#define LANGUAGE_ARABIC_SAUDI_ARABIA
#define LANGUAGE_DONTKNOW
#define LANGUAGE_MALAYALAM
constexpr LanguageType primary(LanguageType lt)
#define LANGUAGE_URDU_PAKISTAN
#define LANGUAGE_AMHARIC_ETHIOPIA
#define LANGUAGE_GUJARATI
#define LANGUAGE_TIGRIGNA_ETHIOPIA
#define LANGUAGE_MONGOLIAN_MONGOLIAN_LSO
LanguageTag maLanguageTag
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
::std::vector< B2DPolyPolygon > B2DPolyPolygonVector
sal_UCS4 GetLocalizedChar(sal_UCS4 nChar, LanguageType eLang)
static int lcl_CalcAsianKerning(sal_UCS4 c, bool bLeft)
static bool lcl_CanApplyAsianKerning(sal_Unicode cp)
bool anyOf(strong_int v) const