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 mbSubpixelPositioning(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 double 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 double nDiffWidth = nNewWidth - nOldWidth;
319 for( pGlyphIter =
m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter )
322 pGlyphIter->adjustLinearPosX(nDeltaSum);
325 if( pGlyphIter->IsInCluster() || (nStretchable <= 0) )
329 double nDeltaWidth = nDiffWidth / nStretchable--;
330 nDiffWidth -= nDeltaWidth;
331 pGlyphIter->addNewWidth(nDeltaWidth);
332 nDeltaSum += nDeltaWidth;
338 double fSqueeze = nNewWidth / nOldWidth;
341 for( pGlyphIter =
m_GlyphItems.begin(); ++pGlyphIter != pGlyphIterRight;)
343 double nX = pGlyphIter->linearPos().getX();
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 double 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);
443 const OUString& rStr)
const
447 rCaretPositions.clear();
448 rCaretPositions.resize(nCaretPositions, -1);
453 std::vector<double> aCharWidths;
459 auto nCurrX = aGlyphItem.linearPos().getX() - aGlyphItem.xOffset();
460 auto nCharStart = aGlyphItem.charPos();
461 auto nCharEnd = nCharStart + aGlyphItem.charCount() - 1;
462 if (!aGlyphItem.IsRTLGlyph())
465 for (
int i = nCharStart;
i <= nCharEnd;
i++)
468 int nCurrIdx = 2 *
n;
471 nCurrX += aCharWidths[
n];
472 auto nRight = nCurrX;
474 rCaretPositions[nCurrIdx] = nLeft;
475 rCaretPositions[nCurrIdx + 1] = nRight;
481 for (
int i = nCharEnd;
i >= nCharStart;
i--)
484 int nCurrIdx = 2 *
n;
486 auto nRight = nCurrX;
487 nCurrX += aCharWidths[
n];
490 rCaretPositions[nCurrIdx] = nLeft;
491 rCaretPositions[nCurrIdx + 1] = nRight;
499 std::vector<double> aCharWidths;
510 if( nWidth > nMaxWidth )
513 nWidth += nCharExtra;
524 std::vector<GlyphItem>::const_iterator pGlyphIter =
m_GlyphItems.begin();
525 std::vector<GlyphItem>::const_iterator pGlyphIterEnd =
m_GlyphItems.end();
526 pGlyphIter += nStart;
529 for(; pGlyphIter != pGlyphIterEnd; ++nStart, ++pGlyphIter )
531 int n = pGlyphIter->charPos();
540 if( pGlyphIter == pGlyphIterEnd )
544 *pGlyph = &(*pGlyphIter);
562 std::vector<GlyphItem>::iterator pGlyphIter =
m_GlyphItems.begin();
563 pGlyphIter += nStart;
568 if( pGlyphIter->IsRTLGlyph() )
569 nNewXPos += pGlyphIter->newWidth() - pGlyphIter->origWidth();
571 double nXDelta = nNewXPos - pGlyphIter->linearPos().getX() + pGlyphIter->xOffset();
575 for( std::vector<GlyphItem>::iterator pGlyphIterEnd =
m_GlyphItems.end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter )
577 pGlyphIter->adjustLinearPosX(nXDelta);
587 std::vector<GlyphItem>::iterator pGlyphIter =
m_GlyphItems.begin();
588 pGlyphIter += nStart;
589 pGlyphIter->dropGlyph();
614, mbIncomplete( false )
661 std::vector<double> aJustificationArray;
679 double nOrigWidth = 0;
680 int nStretchable = 0;
681 for(
int i = 0;
i < nCharCount; ++
i )
684 nOrigWidth += aJustificationArray[
i];
685 if( aJustificationArray[
i] > 0 )
690 if( nOrigWidth && (nTargetWidth != nOrigWidth) )
692 double nDiffWidth = nTargetWidth - nOrigWidth;
693 double nWidthSum = 0;
694 for(
int i = 0;
i < nCharCount; ++
i )
696 double nJustWidth = aJustificationArray[
i];
697 if( (nJustWidth > 0) && (nStretchable > 0) )
699 double nDeltaWidth = nDiffWidth / nStretchable;
700 nJustWidth += nDeltaWidth;
701 nDiffWidth -= nDeltaWidth;
704 nWidthSum += nJustWidth;
705 aJustificationArray[
i] = nWidthSum;
707 if( nWidthSum != nTargetWidth )
708 aJustificationArray[ nCharCount-1 ] = nTargetWidth;
711 aMultiArgs.
mpDXArray = aJustificationArray.data();
720 const double* pMultiDXArray)
727 int nRunStart, nRunEnd;
728 while (rArgs.
GetNextRun(&nRunStart, &nRunEnd, &bRtl))
730 if (bRtl) std::fill(vRtl.begin() + (nRunStart - rArgs.
mnMinCharPos),
763 nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
764 bValid[nLevel] =
mpLayouts[
n]->GetNextGlyph(&pGlyphs[nLevel], aPos, nStartNew[nLevel]);
766 if( (
n > 0) && !bValid[ nLevel ] )
786 for(
n = 0;
n < nLevel; ++
n )
789 int nFirstValid = -1;
790 for(
n = 0;
n < nLevel; ++
n )
798 assert(nFirstValid >= 0);
801 int nActiveCharPos = pGlyphs[nFirstValid]->
charPos();
804 int nLastRunEndChar = (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex]) ?
806 int nRunVisibleEndChar = pGlyphs[nFirstValid]->
charPos();
808 while( bValid[nFirstValid] && (nLevel > 0))
811 for(
n = 0;
n < nLevel; ++
n )
831 (
maFallbackRuns[
n-1].PosIsInAnyRun(pGlyphs[nFirstValid]->charPos())) &&
836 nStartOld[0] = nStartNew[0];
837 bValid[nFirstValid] =
mpLayouts[0]->GetNextGlyph(&pGlyphs[nFirstValid], aPos, nStartNew[0]);
839 if( !bValid[nFirstValid] )
845 double nRunAdvance = 0;
846 bool bKeepNotDef = (nFBLevel >= nLevel);
852 nStartOld[
n] = nStartNew[
n];
853 int nOrigCharPos = pGlyphs[
n]->
charPos();
854 bValid[
n] =
mpLayouts[
n]->GetNextGlyph(&pGlyphs[
n], aPos, nStartNew[
n]);
867 if ((
n+1 < nLevel) && (pGlyphs[
n]->
charPos() != nOrigCharPos))
869 if (nOrigCharPos < pGlyphs[
n]->charPos())
871 if (pGlyphs[
n+1]->charPos() > nOrigCharPos && (pGlyphs[
n+1]->
charPos() < pGlyphs[
n]->
charPos()))
874 else if (nOrigCharPos > pGlyphs[
n]->charPos())
876 if (pGlyphs[
n+1]->charPos() > pGlyphs[
n]->
charPos() && (pGlyphs[
n+1]->
charPos() < nOrigCharPos))
893 if (!
maFallbackRuns[nLevel-1].PosIsInRun(pGlyphs[nFirstValid]->charPos()))
896 if( bKeepNotDef && !bNeedFallback )
898 bKeepNotDef = bNeedFallback;
912 nRunVisibleEndChar = pGlyphs[
n]->
charPos();
918 nRunVisibleEndChar = pGlyphs[
n]->
charPos();
931 if (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex])
934 nRunAdvance -= pMultiDXArray[nRunVisibleEndChar - 1 -
mnMinCharPos];
936 nRunAdvance += pMultiDXArray[nLastRunEndChar - 1 -
mnMinCharPos];
941 nRunAdvance += pMultiDXArray[nRunVisibleEndChar -
mnMinCharPos];
943 nRunAdvance -= pMultiDXArray[nLastRunEndChar -
mnMinCharPos];
945 nLastRunEndChar = nRunVisibleEndChar;
946 nRunVisibleEndChar = pGlyphs[nFirstValid]->
charPos();
950 nXPos += nRunAdvance;
953 nActiveCharPos = pGlyphs[nFirstValid]->
charPos();
957 for(
int i = nFBLevel; --
i >= 0;)
963 if (nRunStart > nActiveCharPos)
968 if (nRunEnd <= nActiveCharPos)
1004 return mpLayouts[0]->GetTextBreak( nMaxWidth, nCharExtra, nFactor );
1007 std::vector<double> aCharWidths;
1008 std::vector<double> aFallbackCharWidths;
1009 mpLayouts[0]->FillDXArray( &aCharWidths, {} );
1015 for(
int i = 0;
i < nCharCount; ++
i )
1016 if( aCharWidths[
i ] == 0 )
1017 aCharWidths[
i] = aFallbackCharWidths[
i];
1021 for(
int i = 0;
i < nCharCount; ++
i )
1023 nWidth += aCharWidths[
i ] * nFactor;
1024 if( nWidth > nMaxWidth )
1026 nWidth += nCharExtra;
1053 std::vector<double> aTempWidths;
1055 pCharWidths->clear();
1056 pCharWidths->resize(nCharCount, 0);
1061 mpLayouts[
n]->FillDXArray(&aTempWidths, rStr);
1064 for (
int i = 0;
i < nCharCount; ++
i)
1068 if ((*pCharWidths)[
i] != 0)
1070 double nCharWidth = aTempWidths[
i];
1073 (*pCharWidths)[
i] = nCharWidth;
1082 const OUString& rStr)
const
1085 std::vector<double> aTempPos;
1087 rCaretPositions.clear();
1088 rCaretPositions.resize(nCaretPositions, -1);
1093 mpLayouts[
n]->GetCaretPositions(aTempPos, rStr);
1096 for (
int i = 0;
i < nCaretPositions; ++
i)
1099 if (rCaretPositions[
i] != -1)
1101 if (aTempPos[
i] >= 0)
1102 rCaretPositions[
i] = aTempPos[
i];
1112 int nLevel =
static_cast<unsigned>(nStart) >>
GF_FONTSHIFT;
1113 nStart &= ~GF_FONTMASK;
1114 for(; nLevel <
mnLevel; ++nLevel, nStart=0 )
1118 if (rLayout.
GetNextGlyph(pGlyph, rPos, nStart, ppGlyphFont))
1153 bool bValid =
mpLayouts[0]->IsKashidaPosValid(nCharPos, nNextCharPos);
1165 bValid =
mpLayouts[
i]->IsKashidaPosValid(nCharPos, nNextCharPos);
void DropGlyph(int nStart)
SalLayoutGlyphsImpl m_GlyphItems
void GetCharWidths(std::vector< double > &rCharWidths, const OUString &rStr) const
bool GetNextGlyph(const GlyphItem **pGlyph, basegfx::B2DPoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const override
sal_Int32 GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const final override
void MoveGlyph(int nStart, double nNewXPos)
double FillDXArray(std::vector< double > *pDXArray, const OUString &rStr) const final override
void GetCaretPositions(std::vector< double > &rCaretPositions, const OUString &rStr) const override
void Justify(double nNewWidth)
void Simplify(bool bIsBase)
void ApplyAsianKerning(std::u16string_view rStr)
double GetTextWidth() const final override
bool GetGlyphBoundRect(const LogicalFontInstance *, tools::Rectangle &) const
bool GetGlyphOutline(const LogicalFontInstance *, basegfx::B2DPolyPolygon &) const
bool PosIsInRun(int nCharPos) const
bool PosIsInAnyRun(int nCharPos) const
bool GetNextGlyph(const GlyphItem **pGlyph, basegfx::B2DPoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const override
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()
sal_Int32 GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const override
void DrawText(SalGraphics &) const override
void InitFont() const override
double GetTextWidth() const final override
double FillDXArray(std::vector< double > *pDXArray, const OUString &rStr) const override
bool LayoutText(vcl::text::ImplLayoutArgs &, const SalLayoutGlyphsImpl *) override
SalLayoutGlyphs GetGlyphs() const final override
ImplLayoutRuns maFallbackRuns[MAX_FALLBACK]
void AddFallback(std::unique_ptr< SalLayout > pFallbackLayout, ImplLayoutRuns const &)
virtual ~MultiSalLayout() override
void GetCaretPositions(std::vector< double > &rCaretPositions, const OUString &rStr) const override
bool IsKashidaPosValid(int nCharPos, int nNextCharPos) const override
MultiSalLayout(std::unique_ptr< SalLayout > pBaseLayout)
constexpr tools::Long Y() const
constexpr tools::Long X() const
const rtl::Reference< LogicalFontInstance > & GetFont() const
void AppendImpl(SalLayoutGlyphsImpl *pImpl)
LanguageTag maLanguageTag
virtual void InitFont() const
virtual double FillDXArray(std::vector< double > *pDXArray, const OUString &rStr) const =0
virtual bool GetOutline(basegfx::B2DPolyPolygonVector &) const
basegfx::B2DPoint GetDrawPosition(const basegfx::B2DPoint &rRelative=basegfx::B2DPoint(0, 0)) const
bool mbSubpixelPositioning
bool GetBoundRect(tools::Rectangle &) const
basegfx::B2DPoint & DrawBase()
virtual void AdjustLayout(vcl::text::ImplLayoutArgs &)
basegfx::B2DPoint maDrawBase
virtual void DrawText(SalGraphics &) const =0
virtual bool GetNextGlyph(const GlyphItem **pGlyph, basegfx::B2DPoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const =0
virtual SalLayoutGlyphs GetGlyphs() const
void transform(const basegfx::B2DHomMatrix &rMatrix)
bool GetNextRun(int *nMinRunPos, int *nEndRunPos, bool *bRTL)
LanguageTag maLanguageTag
#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