39 #include <unicode/ubidi.h>
40 #include <unicode/uchar.h>
48 #define GF_FONTMASK 0xF0000000
49 #define GF_FONTSHIFT 28
57 s <<
"ImplLayoutArgs{";
65 #define TEST(x) if (rArgs.mnFlags & SalLayoutFlags::x) { if (need_or) s << "|"; s << #x; need_or = true; }
80 s <<
",Length=" << nLength;
88 for (
int i = 0;
i < lim;
i++) {
89 if (rArgs.
mrStr[
i] ==
'\n')
92 s <<
"\\0x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(rArgs.
mrStr[
i]) << std::setfill(
' ') << std::setw(1) << std::dec;
93 else if (rArgs.
mrStr[
i] < 0x7F)
94 s << static_cast<char>(rArgs.
mrStr[
i]);
96 s <<
"\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(rArgs.
mrStr[
i]) << std::setfill(
' ') << std::setw(1) << std::dec;
109 for (
int i = 0;
i < lim;
i++) {
133 nChar = u_charMirror( nChar );
140 if( (nChar <
'0') || (
'9' < nChar) )
149 nOffset = 0x0660 -
'0';
155 nOffset = 0x06F0 -
'0';
157 nOffset = 0x09E6 -
'0';
159 nOffset = 0x0966 -
'0';
164 nOffset = 0x1369 -
'0';
166 nOffset = 0x0AE6 -
'0';
167 #ifdef LANGUAGE_GURMUKHI // TODO case:
168 else if ( pri ==
primary(LANGUAGE_GURMUKHI) )
169 nOffset = 0x0A66 -
'0';
172 nOffset = 0x0CE6 -
'0';
174 nOffset = 0x17E0 -
'0';
176 nOffset = 0x0ED0 -
'0';
178 nOffset = 0x0D66 -
'0';
185 nOffset = 0x1810 -
'0';
190 nOffset = 0x1040 -
'0';
192 nOffset = 0x0B66 -
'0';
194 nOffset = 0x0BE7 -
'0';
196 nOffset = 0x0C66 -
'0';
198 nOffset = 0x0E50 -
'0';
200 nOffset = 0x0F20 -
'0';
213 if( (0x0001 <= cChar) && (cChar <= 0x001F) )
216 if( (0x200E <= cChar) && (cChar <= 0x200F) )
218 if( (0x2028 <= cChar) && (cChar <= 0x202E) )
221 if( (0x206A <= cChar) && (cChar <= 0x206F) )
223 if( 0x2060 == cChar )
226 if( (cChar == 0xFEFF) || (cChar == 0xFFFE) || (cChar == 0xFFFF) )
237 int nRunPos0 =
maRuns[ nIndex-2 ];
238 int nRunPos1 =
maRuns[ nIndex-1 ];
239 if( ((nCharPos +
int(bRTL)) == nRunPos1) && ((nRunPos0 > nRunPos1) == bRTL) )
242 maRuns[ nIndex-1 ] = nCharPos +
int(!bRTL);
246 if( (nRunPos0 <= nCharPos) && (nCharPos < nRunPos1) )
248 if( (nRunPos1 <= nCharPos) && (nCharPos < nRunPos0) )
253 maRuns.push_back( nCharPos + (bRTL ? 1 : 0) );
254 maRuns.push_back( nCharPos + (bRTL ? 0 : 1) );
259 if( nCharPos0 == nCharPos1 )
263 if( bRTL == (nCharPos0 < nCharPos1) )
265 int nTemp = nCharPos0;
266 nCharPos0 = nCharPos1;
277 maRuns.push_back( nCharPos0 );
278 maRuns.push_back( nCharPos1 );
288 if( nMinCharPos > nEndCharPos )
290 int nTemp = nMinCharPos;
291 nMinCharPos = nEndCharPos;
295 if( nCharPos < nMinCharPos )
297 if( nCharPos >= nEndCharPos )
311 for (
size_t i = 0;
i <
maRuns.size();
i+=2)
335 *bRightToLeft = (nRunPos0 > nRunPos1);
340 *nCharPos = nRunPos0;
349 if( *nCharPos == nRunPos1 )
355 *bRightToLeft = (nRunPos0 > nRunPos1);
356 *nCharPos = nRunPos0;
374 *bRightToLeft = (nRunPos1 < nRunPos0) ;
377 *nMinRunPos = nRunPos0;
378 *nEndRunPos = nRunPos1;
382 *nMinRunPos = nRunPos1;
383 *nEndRunPos = nRunPos0;
395 mnMinCharPos( nMinCharPos ),
396 mnEndCharPos( nEndCharPos ),
397 m_pTextLayoutCache(pLayoutCache),
398 mpDXArray( nullptr ),
419 UErrorCode rcI18n = U_ZERO_ERROR;
421 UBiDi* pParaBidi = ubidi_openSized(nLength, 0, &rcI18n);
424 ubidi_setPara(pParaBidi, reinterpret_cast<const UChar *>(
mrStr.getStr()), nLength, nLevel,
nullptr, &rcI18n);
426 UBiDi* pLineBidi = pParaBidi;
428 if (nSubLength != nLength)
430 pLineBidi = ubidi_openSized( nSubLength, 0, &rcI18n );
431 ubidi_setLine( pParaBidi, mnMinCharPos,
mnEndCharPos, pLineBidi, &rcI18n );
435 const int nRunCount = ubidi_countRuns( pLineBidi, &rcI18n );
437 for(
int i = 0;
i < nRunCount; ++
i )
439 int32_t nMinPos, nRunLength;
440 const UBiDiDirection nDir = ubidi_getVisualRun( pLineBidi,
i, &nMinPos, &nRunLength );
442 const int nPos1 = nPos0 + nRunLength;
444 const bool bRTL = (nDir == UBIDI_RTL);
445 AddRun( nPos0, nPos1, bRTL );
449 if( pLineBidi != pParaBidi )
450 ubidi_close( pLineBidi );
451 ubidi_close( pParaBidi );
461 SAL_WARN_IF( nCharPos0 > nCharPos1,
"vcl",
"ImplLayoutArgs::AddRun() nCharPos0>=nCharPos1" );
466 for(
int i = nCharPos0;
i < nCharPos1; ++
i )
476 for(
int i = nCharPos1; --
i >= nCharPos0; )
503 std::vector<int> aPosVector;
504 aPosVector.reserve(
mrStr.getLength());
507 for(
int i = nMin;
i < nEnd; ++
i )
508 aPosVector.push_back(
i );
512 std::sort( aPosVector.begin(), aPosVector.end() );
520 auto it = std::lower_bound( aPosVector.begin(), aPosVector.end(), nMin );
521 for(; (it != aPosVector.end()) && (*it < nEnd); ++it )
522 aNewRuns.AddPos( *it, bRTL );
524 auto it = std::upper_bound( aPosVector.begin(), aPosVector.end(), nEnd );
525 while( (it != aPosVector.begin()) && (*--it >= nMin) )
526 aNewRuns.AddPos( *it, bRTL );
537 bool bValid =
maRuns.
GetRun( nMinRunPos, nEndRunPos, bRTL );
543 : mnMinCharPos( -1 ),
545 mnUnitsPerPixel( 1 ),
571 static double fCos = 1.0, fSin = 0.0;
580 double fX = aOfs.X();
581 double fY = aOfs.Y();
584 aPos +=
Point( nX, nY );
607 if( bSuccess && (aGlyphOutline.
count() > 0) )
609 if( aPos.X() || aPos.Y() )
615 rVector.push_back( aGlyphOutline );
619 return (bAllOk && bOneOk);
642 rRect.
Union(aRectangle);
672 if( nMinPos > nXPos )
674 nXPos += aGlyphItem.m_nNewWidth - aGlyphItem.xOffset();
675 if( nMaxPos < nXPos )
687 if( !nOldWidth || nNewWidth==nOldWidth )
695 std::vector<GlyphItem>::iterator pGlyphIterRight =
m_GlyphItems.
Impl()->begin();
697 std::vector<GlyphItem>::iterator pGlyphIter;
699 int nStretchable = 0;
700 int nMaxGlyphWidth = 0;
701 for(pGlyphIter =
m_GlyphItems.
Impl()->begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter)
703 if( !pGlyphIter->IsDiacritic() )
705 if (nMaxGlyphWidth < pGlyphIter->origWidth())
706 nMaxGlyphWidth = pGlyphIter->origWidth();
710 nOldWidth -= pGlyphIterRight->origWidth();
713 if( nNewWidth < nMaxGlyphWidth)
714 nNewWidth = nMaxGlyphWidth;
715 nNewWidth -= pGlyphIterRight->origWidth();
716 pGlyphIterRight->m_aLinearPos.setX( nNewWidth );
719 int nDiffWidth = nNewWidth - nOldWidth;
724 for( pGlyphIter =
m_GlyphItems.
Impl()->begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter )
727 pGlyphIter->m_aLinearPos.AdjustX(nDeltaSum );
730 if( pGlyphIter->IsDiacritic() || (nStretchable <= 0) )
734 int nDeltaWidth = nDiffWidth / nStretchable--;
735 nDiffWidth -= nDeltaWidth;
736 pGlyphIter->m_nNewWidth += nDeltaWidth;
737 nDeltaSum += nDeltaWidth;
743 double fSqueeze =
static_cast<double>(nNewWidth) / nOldWidth;
746 for( pGlyphIter =
m_GlyphItems.
Impl()->begin(); ++pGlyphIter != pGlyphIterRight;)
748 int nX = pGlyphIter->m_aLinearPos.getX();
749 nX =
static_cast<int>(nX * fSqueeze);
750 pGlyphIter->m_aLinearPos.setX( nX );
754 for( pGlyphIter =
m_GlyphItems.
Impl()->begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter )
755 pGlyphIter->m_nNewWidth = pGlyphIter[1].m_aLinearPos.getX() - pGlyphIter[0].m_aLinearPos.getX();
766 static const signed char nTable[0x30] =
768 0, -2, -2, 0, 0, 0, 0, 0, +2, -2, +2, -2, +2, -2, +2, -2,
769 +2, -2, 0, 0, +2, -2, +2, -2, 0, 0, 0, 0, 0, +2, -2, -2,
770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, +2, +2, -2, -2
774 if( (c >= 0x3000) && (c < 0x3030) )
775 nResult = nTable[ c - 0x3000 ];
779 nResult = bLeft ? -1 : +1;
781 case 0x2019:
case 0x201D:
782 case 0xFF01:
case 0xFF09:
case 0xFF0C:
783 case 0xFF1A:
case 0xFF1B:
786 case 0x2018:
case 0x201C:
799 return (0x3000 == (cp & 0xFF00)) || (0xFF00 == (cp & 0xFF00)) || (0x2010 == (cp & 0xFFF0));
804 const int nLength = rStr.getLength();
807 for (std::vector<GlyphItem>::iterator pGlyphIter =
m_GlyphItems.
Impl()->begin(),
809 pGlyphIter != pGlyphIterEnd; ++pGlyphIter)
811 const int n = pGlyphIter->charPos();
824 if (nKernCurrent == 0)
831 int nDelta = (nKernCurrent < nKernNext) ? nKernCurrent : nKernNext;
834 nDelta = (nDelta * pGlyphIter->origWidth() + 2) / 4;
835 if( pGlyphIter+1 == pGlyphIterEnd )
836 pGlyphIter->m_nNewWidth += nDelta;
842 if( pGlyphIter+1 != pGlyphIterEnd )
843 pGlyphIter->m_aLinearPos.AdjustX(nOffset);
850 for (
int i = 0;
i < nMaxIndex; ++
i)
851 pCaretXArray[
i] = -1;
856 tools::Long nXPos = aGlyphItem.m_aLinearPos.getX();
857 tools::Long nXRight = nXPos + aGlyphItem.origWidth();
858 int n = aGlyphItem.charPos();
861 if (aGlyphItem.IsInCluster() && pCaretXArray[nCurrIdx] != -1)
863 if (!aGlyphItem.IsRTLGlyph() )
866 pCaretXArray[ nCurrIdx ] = nXPos;
867 pCaretXArray[ nCurrIdx+1 ] = nXRight;
872 pCaretXArray[ nCurrIdx ] = nXRight;
873 pCaretXArray[ nCurrIdx+1 ] = nXPos;
881 std::unique_ptr<DeviceCoordinate[]>
const pCharWidths(
new DeviceCoordinate[nCharCapacity]);
888 if( nWidth > nMaxWidth )
890 nWidth += nCharExtra;
897 Point& rPos,
int& nStart,
900 std::vector<GlyphItem>::const_iterator pGlyphIter =
m_GlyphItems.
Impl()->begin();
901 std::vector<GlyphItem>::const_iterator pGlyphIterEnd =
m_GlyphItems.
Impl()->end();
902 pGlyphIter += nStart;
905 for(; pGlyphIter != pGlyphIterEnd; ++nStart, ++pGlyphIter )
907 int n = pGlyphIter->charPos();
916 if( pGlyphIter == pGlyphIterEnd )
920 *pGlyph = &(*pGlyphIter);
924 Point aRelativePos = pGlyphIter->m_aLinearPos;
939 pGlyphIter += nStart;
944 if( pGlyphIter->IsRTLGlyph() )
945 nNewXPos += pGlyphIter->m_nNewWidth - pGlyphIter->origWidth();
947 tools::Long nXDelta = nNewXPos - pGlyphIter->m_aLinearPos.getX();
951 for( std::vector<GlyphItem>::iterator pGlyphIterEnd =
m_GlyphItems.
Impl()->end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter )
953 pGlyphIter->m_aLinearPos.AdjustX(nXDelta );
964 pGlyphIter += nStart;
965 pGlyphIter->dropGlyph();
991 , mbIncomplete( false )
993 assert(dynamic_cast<GenericSalLayout*>(pBaseLayout.get()));
995 mpLayouts[ 0 ].reset(static_cast<GenericSalLayout*>(pBaseLayout.release()));
1017 assert(dynamic_cast<GenericSalLayout*>(pFallback.get()));
1021 mpLayouts[
mnLevel ].reset(static_cast<GenericSalLayout*>(pFallback.release()));
1039 std::unique_ptr<DeviceCoordinate[]> pJustificationArray;
1060 int nStretchable = 0;
1061 for(
int i = 0;
i < nCharCount; ++
i )
1064 nOrigWidth += pJustificationArray[
i];
1065 if( pJustificationArray[
i] > 0 )
1070 if( nOrigWidth && (nTargetWidth != nOrigWidth) )
1074 for(
int i = 0;
i < nCharCount; ++
i )
1077 if( (nJustWidth > 0) && (nStretchable > 0) )
1080 nJustWidth += nDeltaWidth;
1081 nDiffWidth -= nDeltaWidth;
1084 nWidthSum += nJustWidth;
1085 pJustificationArray[
i] = nWidthSum;
1087 if( nWidthSum != nTargetWidth )
1088 pJustificationArray[ nCharCount-1 ] = nTargetWidth;
1094 for(
int i = 0;
i < nCharCount; ++
i )
1103 aMultiArgs.
mpDXArray = pJustificationArray.get();
1112 int nRunStart, nRunEnd;
1113 while (rArgs.
GetNextRun(&nRunStart, &nRunEnd, &bRtl))
1115 if (bRtl) std::fill(vRtl.begin() + (nRunStart - rArgs.
mnMinCharPos),
1148 nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
1149 bValid[nLevel] =
mpLayouts[
n]->GetNextGlyph(&pGlyphs[nLevel], aPos, nStartNew[nLevel]);
1151 if( (
n > 0) && !bValid[ nLevel ] )
1171 double fUnitMul = 1.0;
1172 for(
n = 0;
n < nLevel; ++
n )
1175 int nFirstValid = -1;
1176 for(
n = 0;
n < nLevel; ++
n )
1184 assert(nFirstValid >= 0);
1187 int nActiveCharPos = pGlyphs[nFirstValid]->
charPos();
1190 int nLastRunEndChar = (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex]) ?
1192 int nRunVisibleEndChar = pGlyphs[nFirstValid]->
charPos();
1194 while( bValid[nFirstValid] && (nLevel > 0))
1197 for(
n = 0;
n < nLevel; ++
n )
1207 fUnitMul /=
mpLayouts[
n]->GetUnitsPerPixel();
1225 mpLayouts[0]->DropGlyph( nStartOld[0] );
1226 nStartOld[0] = nStartNew[0];
1227 bValid[nFirstValid] =
mpLayouts[0]->GetNextGlyph(&pGlyphs[nFirstValid], aPos, nStartNew[0]);
1229 if( !bValid[nFirstValid] )
1236 bool bKeepNotDef = (nFBLevel >= nLevel);
1242 nStartOld[
n] = nStartNew[
n];
1243 int nOrigCharPos = pGlyphs[
n]->
charPos();
1244 bValid[
n] =
mpLayouts[
n]->GetNextGlyph(&pGlyphs[
n], aPos, nStartNew[n]);
1257 if ((n+1 < nLevel) && (pGlyphs[n]->charPos() != nOrigCharPos))
1259 if (nOrigCharPos < pGlyphs[n]->charPos())
1261 if (pGlyphs[n+1]->charPos() > nOrigCharPos && (pGlyphs[n+1]->charPos() < pGlyphs[n]->charPos()))
1264 else if (nOrigCharPos > pGlyphs[n]->charPos())
1266 if (pGlyphs[n+1]->charPos() > pGlyphs[n]->charPos() && (pGlyphs[n+1]->charPos() < nOrigCharPos))
1283 if (!
maFallbackRuns[nLevel-1].PosIsInRun(pGlyphs[nFirstValid]->charPos()))
1286 if( bKeepNotDef && !bNeedFallback )
1288 bKeepNotDef = bNeedFallback;
1293 nRunVisibleEndChar >= mnMinCharPos &&
1297 if (vRtl[nActiveCharPos - mnMinCharPos])
1299 if (aMultiArgs.
mpDXArray[nRunVisibleEndChar-mnMinCharPos]
1302 nRunVisibleEndChar = pGlyphs[n]->
charPos();
1305 else if (aMultiArgs.
mpDXArray[nRunVisibleEndChar-mnMinCharPos]
1308 nRunVisibleEndChar = pGlyphs[n]->
charPos();
1321 if (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex])
1323 if (nRunVisibleEndChar > mnMinCharPos && nRunVisibleEndChar <=
mnEndCharPos)
1325 if (nLastRunEndChar > mnMinCharPos && nLastRunEndChar <=
mnEndCharPos)
1330 if (nRunVisibleEndChar >= mnMinCharPos)
1332 if (nLastRunEndChar >= mnMinCharPos)
1335 nLastRunEndChar = nRunVisibleEndChar;
1336 nRunVisibleEndChar = pGlyphs[nFirstValid]->
charPos();
1346 nRunAdvance =
static_cast<tools::Long>(nRunAdvance*fUnitMul + 0.5);
1350 nXPos += nRunAdvance;
1353 nActiveCharPos = pGlyphs[nFirstValid]->
charPos();
1357 for(
int i = nFBLevel; --
i >= 0;)
1363 if (nRunStart > nActiveCharPos)
1368 if (nRunEnd <= nActiveCharPos)
1404 return mpLayouts[0]->GetTextBreak( nMaxWidth, nCharExtra, nFactor );
1407 std::unique_ptr<DeviceCoordinate[]>
const pCharWidths(
new DeviceCoordinate[nCharCount]);
1408 std::unique_ptr<DeviceCoordinate[]>
const pFallbackCharWidths(
new DeviceCoordinate[nCharCount]);
1409 mpLayouts[0]->FillDXArray( pCharWidths.get() );
1417 for(
int i = 0;
i < nCharCount; ++
i )
1419 if( pCharWidths[
i ] == 0 )
1423 pCharWidths[
i ] = w;
1429 for(
int i = 0;
i < nCharCount; ++
i )
1431 nWidth += pCharWidths[
i ] * nFactor;
1432 if( nWidth > nMaxWidth )
1433 return (
i + mnMinCharPos);
1434 nWidth += nCharExtra;
1445 std::unique_ptr<DeviceCoordinate[]> pTempWidths;
1449 for(
int i = 0;
i < nCharCount; ++
i )
1462 fUnitMul /=
mpLayouts[
n]->GetUnitsPerPixel();
1464 if( nMaxWidth < nTextWidth )
1465 nMaxWidth = nTextWidth;
1469 for(
int i = 0;
i < nCharCount; ++
i )
1473 if( pCharWidths[
i] != 0 )
1479 pCharWidths[
i] = nCharWidth;
1494 std::unique_ptr<tools::Long[]>
const pTempPos(
new tools::Long[nMaxIndex]);
1497 mpLayouts[
n ]->GetCaretPositions( nMaxIndex, pTempPos.get() );
1499 fUnitMul /=
mpLayouts[
n]->GetUnitsPerPixel();
1500 for(
int i = 0;
i < nMaxIndex; ++
i )
1501 if( pTempPos[
i] >= 0 )
1505 pCaretXArray[
i] = w;
1511 Point& rPos,
int& nStart,
1515 int nLevel =
static_cast<unsigned>(nStart) >>
GF_FONTSHIFT;
1517 for(; nLevel <
mnLevel; ++nLevel, nStart=0 )
1527 *pFallbackFont = pFontFace;
1559 bool bValid =
mpLayouts[0]->IsKashidaPosValid(nCharPos);
1570 bValid =
mpLayouts[
i]->IsKashidaPosValid(nCharPos);
DeviceCoordinate GetTextWidth() const final override
const size_t count(pCandidateA->getBorderLines().size())
virtual bool GetOutline(basegfx::B2DPolyPolygonVector &) const
void AddFallback(std::unique_ptr< SalLayout > pFallbackLayout, ImplLayoutRuns const &)
int GetUnitsPerPixel() const
#define LANGUAGE_ARABIC_SAUDI_ARABIA
std::unique_ptr< SalLayout > ReleaseBaseLayout()
#define LANGUAGE_URDU_PAKISTAN
bool GetOutline(basegfx::B2DPolyPolygonVector &) const override
std::unique_ptr< GenericSalLayout > mpLayouts[MAX_FALLBACK]
#define LANGUAGE_MONGOLIAN_MONGOLIAN_LSO
void InitFont() const override
bool GetGlyphOutline(basegfx::B2DPolyPolygon &) const
#define LANGUAGE_AMHARIC_ETHIOPIA
void AddRun(int nMinCharPos, int nEndCharPos, bool bRTL)
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
sal_UCS4 GetMirroredChar(sal_UCS4 nChar)
void Justify(DeviceCoordinate nNewWidth)
double toRadians(Degree10 x)
LogicalFontInstance & GetFont() const
MultiSalLayout(std::unique_ptr< SalLayout > pBaseLayout)
void GetCaretPositions(int nArraySize, tools::Long *pCaretXArray) const override
#define LANGUAGE_GUJARATI
std::vector< int > maRuns
void SetIncomplete(bool bIncomplete)
void AddPos(int nCharPos, bool bRTL)
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static bool lcl_CanApplyAsianKerning(sal_Unicode cp)
void GetCaretPositions(int nArraySize, tools::Long *pCaretXArray) const final override
bool IsKashidaPosValid(int nCharPos) const override
virtual void AdjustLayout(ImplLayoutArgs &)
DeviceCoordinate mnLayoutWidth
void ApplyAsianKerning(const OUString &rStr)
bool GetBoundRect(tools::Rectangle &) const
virtual DeviceCoordinate FillDXArray(DeviceCoordinate *pDXArray) const =0
abstract base class for physical font faces
virtual void InitFont() const
DeviceCoordinate FillDXArray(DeviceCoordinate *pDXArray) const final override
virtual void DrawText(SalGraphics &) const =0
SalLayoutGlyphsImpl * Impl() const
bool GetNextGlyph(const GlyphItem **pGlyph, Point &rPos, int &nStart, const PhysicalFontFace **pFallbackFont=nullptr) const override
bool PosIsInRun(int nCharPos) const
void GetCharWidths(DeviceCoordinate *pCharWidths) const
void DropGlyph(int nStart)
tools::Long DeviceCoordinate
void transform(const basegfx::B2DHomMatrix &rMatrix)
bool GetNextGlyph(const GlyphItem **pGlyph, Point &rPos, int &nStart, const PhysicalFontFace **pFallbackFont=nullptr) const override
#define LANGUAGE_TIGRIGNA_ETHIOPIA
Point GetDrawPosition(const Point &rRelative=Point(0, 0)) const
constexpr LanguageType primary(LanguageType lt)
virtual ~MultiSalLayout() override
#define LANGUAGE_MALAYALAM
virtual void GetCaretPositions(int nArraySize, tools::Long *pCaretXArray) const =0
bool GetNextRun(int *nMinRunPos, int *nEndRunPos, bool *bRTL)
#define LANGUAGE_MONGOLIAN_MONGOLIAN_MONGOLIA
bool GetNextPos(int *nCharPos, bool *bRTL)
static bool IsControlChar(sal_UCS4 cChar)
std::ostream & operator<<(std::ostream &s, ImplLayoutArgs const &rArgs)
void MoveGlyph(int nStart, tools::Long nNewXPos)
bool GetRun(int *nMinRunPos, int *nEndRunPos, bool *bRTL) const
void AdjustLayout(ImplLayoutArgs &) override
static int lcl_CalcAsianKerning(sal_UCS4 c, bool bLeft)
#define SAL_WARN_IF(condition, area, stream)
void DrawText(SalGraphics &) const override
bool LayoutText(ImplLayoutArgs &, const SalLayoutGlyphs *) override
#define LANGUAGE_MONGOLIAN_MONGOLIAN_CHINA
void AddRun(int nMinRunPos, int nEndRunPos, bool bRTL)
sal_UCS4 GetLocalizedChar(sal_UCS4 nChar, LanguageType eLang)
const PhysicalFontFace * GetFontFace() const
ImplLayoutArgs(const OUString &rStr, int nMinCharPos, int nEndCharPos, SalLayoutFlags nFlags, const LanguageTag &rLanguageTag, vcl::TextLayoutCache const *pLayoutCache)
LanguageTag maLanguageTag
SalLayoutGlyphs m_GlyphItems
ImplLayoutRuns maFallbackRuns
ImplLayoutRuns maFallbackRuns[MAX_FALLBACK]
virtual bool GetNextGlyph(const GlyphItem **pGlyph, Point &rPos, int &nStart, const PhysicalFontFace **pFallbackFont=nullptr) const =0
bool PosIsInAnyRun(int nCharPos) const
DeviceCoordinate FillDXArray(DeviceCoordinate *pDXArray) const override
sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const final override
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
bool GetGlyphBoundRect(tools::Rectangle &) const
virtual const SalLayoutGlyphs * GetGlyphs() const
void Simplify(bool bIsBase)
sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override
const DeviceCoordinate * mpDXArray
bool anyOf(strong_int v) const
::std::vector< B2DPolyPolygon > B2DPolyPolygonVector