1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/fgas/layout/fgas_rtfbreak.h"
8 
9 #include <algorithm>
10 
11 #include "core/fxcrt/include/fx_arabic.h"
12 #include "core/fxcrt/include/fx_arb.h"
13 #include "xfa/fgas/font/fgas_gefont.h"
14 #include "xfa/fgas/layout/fgas_linebreak.h"
15 #include "xfa/fgas/layout/fgas_unicode.h"
16 
CFX_RTFBreak(uint32_t dwPolicies)17 CFX_RTFBreak::CFX_RTFBreak(uint32_t dwPolicies)
18     : m_dwPolicies(dwPolicies),
19       m_iBoundaryStart(0),
20       m_iBoundaryEnd(2000000),
21       m_dwLayoutStyles(0),
22       m_bPagination(FALSE),
23       m_bVertical(FALSE),
24       m_bSingleLine(FALSE),
25       m_bCharCode(FALSE),
26       m_pFont(nullptr),
27       m_iFontHeight(240),
28       m_iFontSize(240),
29       m_iTabWidth(720000),
30       m_PositionedTabs(),
31       m_bOrphanLine(FALSE),
32       m_wDefChar(0xFEFF),
33       m_iDefChar(0),
34       m_wLineBreakChar(L'\n'),
35       m_iHorizontalScale(100),
36       m_iVerticalScale(100),
37       m_iLineRotation(0),
38       m_iCharRotation(0),
39       m_iRotation(0),
40       m_iCharSpace(0),
41       m_bWordSpace(FALSE),
42       m_iWordSpace(0),
43       m_bRTL(FALSE),
44       m_iAlignment(FX_RTFLINEALIGNMENT_Left),
45       m_pUserData(nullptr),
46       m_eCharType(FX_CHARTYPE_Unknown),
47       m_dwIdentity(0),
48       m_RTFLine1(),
49       m_RTFLine2(),
50       m_pCurLine(nullptr),
51       m_iReady(0),
52       m_iTolerance(0) {
53   m_pCurLine = &m_RTFLine1;
54 }
~CFX_RTFBreak()55 CFX_RTFBreak::~CFX_RTFBreak() {
56   Reset();
57   m_PositionedTabs.RemoveAll();
58   if (m_pUserData) {
59     m_pUserData->Release();
60   }
61 }
SetLineBoundary(FX_FLOAT fLineStart,FX_FLOAT fLineEnd)62 void CFX_RTFBreak::SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd) {
63   if (fLineStart > fLineEnd)
64     return;
65   m_iBoundaryStart = FXSYS_round(fLineStart * 20000.0f);
66   m_iBoundaryEnd = FXSYS_round(fLineEnd * 20000.0f);
67   m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iBoundaryEnd);
68   m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iBoundaryStart);
69 }
SetLineStartPos(FX_FLOAT fLinePos)70 void CFX_RTFBreak::SetLineStartPos(FX_FLOAT fLinePos) {
71   int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f);
72   iLinePos = std::min(iLinePos, m_iBoundaryEnd);
73   iLinePos = std::max(iLinePos, m_iBoundaryStart);
74   m_pCurLine->m_iStart = iLinePos;
75 }
SetLayoutStyles(uint32_t dwLayoutStyles)76 void CFX_RTFBreak::SetLayoutStyles(uint32_t dwLayoutStyles) {
77   if (m_dwLayoutStyles == dwLayoutStyles) {
78     return;
79   }
80   SetBreakStatus();
81   m_dwLayoutStyles = dwLayoutStyles;
82   m_bPagination = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_Pagination) != 0;
83   m_bVertical = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0;
84   m_bSingleLine = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0;
85   m_bCharCode = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
86   m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
87   m_iRotation = m_iLineRotation + m_iCharRotation;
88   m_iRotation %= 4;
89 }
SetFont(CFGAS_GEFont * pFont)90 void CFX_RTFBreak::SetFont(CFGAS_GEFont* pFont) {
91   if (!pFont) {
92     return;
93   }
94   if (m_pFont == pFont) {
95     return;
96   }
97   SetBreakStatus();
98   m_pFont = pFont;
99   m_iDefChar = 0;
100   if (m_pFont) {
101     m_iFontHeight = m_iFontSize;
102     if (m_wDefChar != 0xFEFF) {
103       m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
104       m_iDefChar *= m_iFontSize;
105     }
106   }
107 }
SetFontSize(FX_FLOAT fFontSize)108 void CFX_RTFBreak::SetFontSize(FX_FLOAT fFontSize) {
109   int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
110   if (m_iFontSize == iFontSize) {
111     return;
112   }
113   SetBreakStatus();
114   m_iFontSize = iFontSize;
115   m_iDefChar = 0;
116   if (m_pFont) {
117     m_iFontHeight = m_iFontSize;
118     if (m_wDefChar != 0xFEFF) {
119       m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
120       m_iDefChar *= m_iFontSize;
121     }
122   }
123 }
SetTabWidth(FX_FLOAT fTabWidth)124 void CFX_RTFBreak::SetTabWidth(FX_FLOAT fTabWidth) {
125   m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
126 }
AddPositionedTab(FX_FLOAT fTabPos)127 void CFX_RTFBreak::AddPositionedTab(FX_FLOAT fTabPos) {
128   int32_t iLineEnd = m_iBoundaryEnd;
129   int32_t iTabPos = FXSYS_round(fTabPos * 20000.0f) + m_iBoundaryStart;
130   if (iTabPos > iLineEnd) {
131     iTabPos = iLineEnd;
132   }
133   if (m_PositionedTabs.Find(iTabPos, 0) > -1) {
134     return;
135   }
136   int32_t iCount = m_PositionedTabs.GetSize();
137   int32_t iFind = 0;
138   for (; iFind < iCount; iFind++) {
139     if (m_PositionedTabs[iFind] > iTabPos) {
140       break;
141     }
142   }
143   m_PositionedTabs.InsertAt(iFind, iTabPos);
144   if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) {
145     m_bOrphanLine = GetLastPositionedTab() >= iLineEnd;
146   } else {
147     m_bOrphanLine = FALSE;
148   }
149 }
SetPositionedTabs(const CFX_FloatArray & tabs)150 void CFX_RTFBreak::SetPositionedTabs(const CFX_FloatArray& tabs) {
151   m_PositionedTabs.RemoveAll();
152   int32_t iCount = tabs.GetSize();
153   m_PositionedTabs.SetSize(iCount);
154   int32_t iLineEnd = m_iBoundaryEnd;
155   int32_t iTabPos;
156   for (int32_t i = 0; i < iCount; i++) {
157     iTabPos = FXSYS_round(tabs[i] * 20000.0f) + m_iBoundaryStart;
158     if (iTabPos > iLineEnd) {
159       iTabPos = iLineEnd;
160     }
161     m_PositionedTabs[i] = iTabPos;
162   }
163   if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) {
164     m_bOrphanLine = GetLastPositionedTab() >= iLineEnd;
165   } else {
166     m_bOrphanLine = FALSE;
167   }
168 }
ClearPositionedTabs()169 void CFX_RTFBreak::ClearPositionedTabs() {
170   m_PositionedTabs.RemoveAll();
171   m_bOrphanLine = FALSE;
172 }
SetDefaultChar(FX_WCHAR wch)173 void CFX_RTFBreak::SetDefaultChar(FX_WCHAR wch) {
174   m_wDefChar = wch;
175   m_iDefChar = 0;
176   if (m_wDefChar != 0xFEFF && m_pFont) {
177     m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
178     if (m_iDefChar < 0) {
179       m_iDefChar = 0;
180     } else {
181       m_iDefChar *= m_iFontSize;
182     }
183   }
184 }
SetLineBreakChar(FX_WCHAR wch)185 void CFX_RTFBreak::SetLineBreakChar(FX_WCHAR wch) {
186   if (wch != L'\r' && wch != L'\n') {
187     return;
188   }
189   m_wLineBreakChar = wch;
190 }
SetLineBreakTolerance(FX_FLOAT fTolerance)191 void CFX_RTFBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
192   m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
193 }
SetHorizontalScale(int32_t iScale)194 void CFX_RTFBreak::SetHorizontalScale(int32_t iScale) {
195   if (iScale < 0) {
196     iScale = 0;
197   }
198   if (m_iHorizontalScale == iScale) {
199     return;
200   }
201   SetBreakStatus();
202   m_iHorizontalScale = iScale;
203 }
SetVerticalScale(int32_t iScale)204 void CFX_RTFBreak::SetVerticalScale(int32_t iScale) {
205   if (iScale < 0) {
206     iScale = 0;
207   }
208   if (m_iVerticalScale == iScale) {
209     return;
210   }
211   SetBreakStatus();
212   m_iVerticalScale = iScale;
213 }
SetCharRotation(int32_t iCharRotation)214 void CFX_RTFBreak::SetCharRotation(int32_t iCharRotation) {
215   if (iCharRotation < 0) {
216     iCharRotation += (-iCharRotation / 4 + 1) * 4;
217   } else if (iCharRotation > 3) {
218     iCharRotation -= (iCharRotation / 4) * 4;
219   }
220   if (m_iCharRotation == iCharRotation) {
221     return;
222   }
223   SetBreakStatus();
224   m_iCharRotation = iCharRotation;
225   m_iRotation = m_iLineRotation + m_iCharRotation;
226   m_iRotation %= 4;
227 }
SetCharSpace(FX_FLOAT fCharSpace)228 void CFX_RTFBreak::SetCharSpace(FX_FLOAT fCharSpace) {
229   m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
230 }
SetWordSpace(FX_BOOL bDefault,FX_FLOAT fWordSpace)231 void CFX_RTFBreak::SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace) {
232   m_bWordSpace = !bDefault;
233   m_iWordSpace = FXSYS_round(fWordSpace * 20000.0f);
234 }
SetReadingOrder(FX_BOOL bRTL)235 void CFX_RTFBreak::SetReadingOrder(FX_BOOL bRTL) {
236   m_bRTL = bRTL;
237 }
SetAlignment(int32_t iAlignment)238 void CFX_RTFBreak::SetAlignment(int32_t iAlignment) {
239   ASSERT(iAlignment >= FX_RTFLINEALIGNMENT_Left &&
240          iAlignment <= FX_RTFLINEALIGNMENT_Distributed);
241   m_iAlignment = iAlignment;
242 }
SetUserData(IFX_Retainable * pUserData)243 void CFX_RTFBreak::SetUserData(IFX_Retainable* pUserData) {
244   if (m_pUserData == pUserData) {
245     return;
246   }
247   SetBreakStatus();
248   if (m_pUserData) {
249     m_pUserData->Release();
250   }
251   m_pUserData = pUserData;
252   if (m_pUserData) {
253     m_pUserData->Retain();
254   }
255 }
256 static const int32_t gs_FX_RTFLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
GetLineRotation(uint32_t dwStyles) const257 int32_t CFX_RTFBreak::GetLineRotation(uint32_t dwStyles) const {
258   return gs_FX_RTFLineRotations[(dwStyles & 0x0E) >> 1];
259 }
SetBreakStatus()260 void CFX_RTFBreak::SetBreakStatus() {
261   m_dwIdentity++;
262   int32_t iCount = m_pCurLine->CountChars();
263   if (iCount < 1) {
264     return;
265   }
266   CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1);
267   if (tc.m_dwStatus == 0) {
268     tc.m_dwStatus = FX_RTFBREAK_PieceBreak;
269   }
270 }
GetLastChar(int32_t index) const271 CFX_RTFChar* CFX_RTFBreak::GetLastChar(int32_t index) const {
272   CFX_RTFCharArray& tca = m_pCurLine->m_LineChars;
273   int32_t iCount = tca.GetSize();
274   if (index < 0 || index >= iCount) {
275     return nullptr;
276   }
277   CFX_RTFChar* pTC;
278   int32_t iStart = iCount - 1;
279   while (iStart > -1) {
280     pTC = tca.GetDataPtr(iStart--);
281     if (pTC->m_iCharWidth >= 0 ||
282         pTC->GetCharType() != FX_CHARTYPE_Combination) {
283       if (--index < 0) {
284         return pTC;
285       }
286     }
287   }
288   return nullptr;
289 }
GetRTFLine(FX_BOOL bReady) const290 CFX_RTFLine* CFX_RTFBreak::GetRTFLine(FX_BOOL bReady) const {
291   if (bReady) {
292     if (m_iReady == 1) {
293       return (CFX_RTFLine*)&m_RTFLine1;
294     } else if (m_iReady == 2) {
295       return (CFX_RTFLine*)&m_RTFLine2;
296     } else {
297       return nullptr;
298     }
299   }
300   ASSERT(m_pCurLine);
301   return m_pCurLine;
302 }
GetRTFPieces(FX_BOOL bReady) const303 CFX_RTFPieceArray* CFX_RTFBreak::GetRTFPieces(FX_BOOL bReady) const {
304   CFX_RTFLine* pRTFLine = GetRTFLine(bReady);
305   return pRTFLine ? &pRTFLine->m_LinePieces : nullptr;
306 }
GetUnifiedCharType(FX_CHARTYPE chartype) const307 inline FX_CHARTYPE CFX_RTFBreak::GetUnifiedCharType(
308     FX_CHARTYPE chartype) const {
309   return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
310 }
GetLastPositionedTab() const311 int32_t CFX_RTFBreak::GetLastPositionedTab() const {
312   int32_t iCount = m_PositionedTabs.GetSize();
313   if (iCount < 1) {
314     return m_iBoundaryStart;
315   }
316   return m_PositionedTabs[iCount - 1];
317 }
GetPositionedTab(int32_t & iTabPos) const318 FX_BOOL CFX_RTFBreak::GetPositionedTab(int32_t& iTabPos) const {
319   int32_t iCount = m_PositionedTabs.GetSize();
320   for (int32_t i = 0; i < iCount; i++) {
321     if (m_PositionedTabs[i] > iTabPos) {
322       iTabPos = m_PositionedTabs[i];
323       return TRUE;
324     }
325   }
326   return FALSE;
327 }
328 typedef uint32_t (CFX_RTFBreak::*FX_RTFBreak_LPFAppendChar)(
329     CFX_RTFChar* pCurChar,
330     int32_t iRotation);
331 static const FX_RTFBreak_LPFAppendChar g_FX_RTFBreak_lpfAppendChar[16] = {
332     &CFX_RTFBreak::AppendChar_Others,      &CFX_RTFBreak::AppendChar_Tab,
333     &CFX_RTFBreak::AppendChar_Others,      &CFX_RTFBreak::AppendChar_Control,
334     &CFX_RTFBreak::AppendChar_Combination, &CFX_RTFBreak::AppendChar_Others,
335     &CFX_RTFBreak::AppendChar_Others,      &CFX_RTFBreak::AppendChar_Arabic,
336     &CFX_RTFBreak::AppendChar_Arabic,      &CFX_RTFBreak::AppendChar_Arabic,
337     &CFX_RTFBreak::AppendChar_Arabic,      &CFX_RTFBreak::AppendChar_Arabic,
338     &CFX_RTFBreak::AppendChar_Arabic,      &CFX_RTFBreak::AppendChar_Others,
339     &CFX_RTFBreak::AppendChar_Others,      &CFX_RTFBreak::AppendChar_Others,
340 };
AppendChar(FX_WCHAR wch)341 uint32_t CFX_RTFBreak::AppendChar(FX_WCHAR wch) {
342   ASSERT(m_pFont && m_pCurLine);
343   if (m_bCharCode) {
344     return AppendChar_CharCode(wch);
345   }
346   uint32_t dwProps = kTextLayoutCodeProperties[(uint16_t)wch];
347   FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
348   CFX_RTFCharArray& tca = m_pCurLine->m_LineChars;
349   CFX_RTFChar* pCurChar = tca.AddSpace();
350   pCurChar->m_dwStatus = 0;
351   pCurChar->m_wCharCode = wch;
352   pCurChar->m_dwCharProps = dwProps;
353   pCurChar->m_dwCharStyles = 0;
354   pCurChar->m_dwLayoutStyles = 0;
355   pCurChar->m_iFontSize = m_iFontSize;
356   pCurChar->m_iFontHeight = m_iFontHeight;
357   pCurChar->m_iHorizontalScale = m_iHorizontalScale;
358   pCurChar->m_iVertialScale = m_iVerticalScale;
359   pCurChar->m_nRotation = m_iCharRotation;
360   pCurChar->m_iCharWidth = 0;
361   pCurChar->m_dwIdentity = m_dwIdentity;
362   if (m_pUserData) {
363     m_pUserData->Retain();
364   }
365   pCurChar->m_pUserData = m_pUserData;
366   uint32_t dwRet1 = FX_RTFBREAK_None;
367   if (chartype != FX_CHARTYPE_Combination &&
368       GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype)) {
369     if (!m_bSingleLine && !m_bOrphanLine &&
370         m_eCharType != FX_CHARTYPE_Unknown &&
371         m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
372       if (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control) {
373         dwRet1 = EndBreak(FX_RTFBREAK_LineBreak);
374         int32_t iCount = m_pCurLine->CountChars();
375         if (iCount > 0) {
376           pCurChar = m_pCurLine->m_LineChars.GetDataPtr(iCount - 1);
377         }
378       }
379     }
380   }
381   int32_t iRotation = m_iRotation;
382   if (m_bVertical && (dwProps & 0x8000) != 0) {
383     iRotation = (iRotation + 1) % 4;
384   }
385   uint32_t dwRet2 =
386       (this->*g_FX_RTFBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])(
387           pCurChar, iRotation);
388   m_eCharType = chartype;
389   return std::max(dwRet1, dwRet2);
390 }
AppendChar_CharCode(FX_WCHAR wch)391 uint32_t CFX_RTFBreak::AppendChar_CharCode(FX_WCHAR wch) {
392   ASSERT(m_pFont && m_pCurLine);
393   ASSERT(m_bCharCode);
394   m_pCurLine->m_iMBCSChars++;
395   CFX_RTFCharArray& tca = m_pCurLine->m_LineChars;
396   CFX_RTFChar* pCurChar = tca.AddSpace();
397   pCurChar->m_dwStatus = 0;
398   pCurChar->m_wCharCode = wch;
399   pCurChar->m_dwCharProps = 0;
400   pCurChar->m_dwCharStyles = 0;
401   pCurChar->m_dwLayoutStyles = m_dwLayoutStyles;
402   pCurChar->m_iFontSize = m_iFontSize;
403   pCurChar->m_iFontHeight = m_iFontHeight;
404   pCurChar->m_iHorizontalScale = m_iHorizontalScale;
405   pCurChar->m_iVertialScale = m_iVerticalScale;
406   pCurChar->m_nRotation = m_iCharRotation;
407   pCurChar->m_iCharWidth = 0;
408   pCurChar->m_dwIdentity = m_dwIdentity;
409   if (m_pUserData) {
410     m_pUserData->Retain();
411   }
412   pCurChar->m_pUserData = m_pUserData;
413   int32_t iCharWidth = 0;
414   if (m_bVertical != FX_IsOdd(m_iRotation)) {
415     iCharWidth = 1000;
416   } else {
417     if (!m_pFont->GetCharWidth(wch, iCharWidth, TRUE)) {
418       iCharWidth = m_iDefChar;
419     }
420   }
421   iCharWidth *= m_iFontSize;
422   iCharWidth = iCharWidth * m_iHorizontalScale / 100;
423   iCharWidth += m_iCharSpace;
424   pCurChar->m_iCharWidth = iCharWidth;
425   m_pCurLine->m_iWidth += iCharWidth;
426   m_eCharType = FX_CHARTYPE_Unknown;
427   if (!m_bSingleLine &&
428       m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
429     return EndBreak(FX_RTFBREAK_LineBreak);
430   }
431   return FX_RTFBREAK_None;
432 }
AppendChar_Combination(CFX_RTFChar * pCurChar,int32_t iRotation)433 uint32_t CFX_RTFBreak::AppendChar_Combination(CFX_RTFChar* pCurChar,
434                                               int32_t iRotation) {
435   int32_t iCharWidth = 0;
436   if (m_bVertical != FX_IsOdd(iRotation)) {
437     iCharWidth = 1000;
438   } else {
439     if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth,
440                                m_bCharCode)) {
441       iCharWidth = 0;
442     }
443   }
444   iCharWidth *= m_iFontSize;
445   iCharWidth = iCharWidth * m_iHorizontalScale / 100;
446   CFX_RTFChar* pLastChar = GetLastChar(0);
447   if (pLastChar && pLastChar->GetCharType() > FX_CHARTYPE_Combination) {
448     iCharWidth = -iCharWidth;
449   } else {
450     m_eCharType = FX_CHARTYPE_Combination;
451   }
452   pCurChar->m_iCharWidth = iCharWidth;
453   if (iCharWidth > 0) {
454     m_pCurLine->m_iWidth += iCharWidth;
455   }
456   return FX_RTFBREAK_None;
457 }
AppendChar_Tab(CFX_RTFChar * pCurChar,int32_t iRotation)458 uint32_t CFX_RTFBreak::AppendChar_Tab(CFX_RTFChar* pCurChar,
459                                       int32_t iRotation) {
460   if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ExpandTab) {
461     FX_BOOL bBreak = FALSE;
462     if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) {
463       bBreak = (m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance);
464     }
465     int32_t& iLineWidth = m_pCurLine->m_iWidth;
466     int32_t iCharWidth = iLineWidth;
467     if (GetPositionedTab(iCharWidth)) {
468       iCharWidth -= iLineWidth;
469     } else {
470       iCharWidth = m_iTabWidth * (iLineWidth / m_iTabWidth + 1) - iLineWidth;
471     }
472     pCurChar->m_iCharWidth = iCharWidth;
473     iLineWidth += iCharWidth;
474     if (!m_bSingleLine && !m_bOrphanLine && bBreak) {
475       return EndBreak(FX_RTFBREAK_LineBreak);
476     }
477   }
478   return FX_RTFBREAK_None;
479 }
AppendChar_Control(CFX_RTFChar * pCurChar,int32_t iRotation)480 uint32_t CFX_RTFBreak::AppendChar_Control(CFX_RTFChar* pCurChar,
481                                           int32_t iRotation) {
482   uint32_t dwRet2 = FX_RTFBREAK_None;
483   if (!m_bSingleLine) {
484     switch (pCurChar->m_wCharCode) {
485       case L'\v':
486       case 0x2028:
487         dwRet2 = FX_RTFBREAK_LineBreak;
488         break;
489       case L'\f':
490         dwRet2 = FX_RTFBREAK_PageBreak;
491         break;
492       case 0x2029:
493         dwRet2 = FX_RTFBREAK_ParagraphBreak;
494         break;
495       default:
496         if (pCurChar->m_wCharCode == m_wLineBreakChar) {
497           dwRet2 = FX_RTFBREAK_ParagraphBreak;
498         }
499         break;
500     }
501     if (dwRet2 != FX_RTFBREAK_None) {
502       dwRet2 = EndBreak(dwRet2);
503     }
504   }
505   return dwRet2;
506 }
AppendChar_Arabic(CFX_RTFChar * pCurChar,int32_t iRotation)507 uint32_t CFX_RTFBreak::AppendChar_Arabic(CFX_RTFChar* pCurChar,
508                                          int32_t iRotation) {
509   CFX_RTFChar* pLastChar = nullptr;
510   int32_t& iLineWidth = m_pCurLine->m_iWidth;
511   int32_t iCharWidth = 0;
512   FX_WCHAR wForm;
513   FX_BOOL bAlef = FALSE;
514   if (m_eCharType >= FX_CHARTYPE_ArabicAlef &&
515       m_eCharType <= FX_CHARTYPE_ArabicDistortion) {
516     pLastChar = GetLastChar(1);
517     if (pLastChar) {
518       iLineWidth -= pLastChar->m_iCharWidth;
519       CFX_RTFChar* pPrevChar = GetLastChar(2);
520       wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar);
521       bAlef = (wForm == 0xFEFF &&
522                pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
523       int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
524       if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
525         iLastRotation++;
526       }
527       if (m_bVertical != FX_IsOdd(iLastRotation)) {
528         iCharWidth = 1000;
529       } else {
530         if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) {
531           if (!m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth,
532                                      m_bCharCode)) {
533             iCharWidth = m_iDefChar;
534           }
535         }
536       }
537       iCharWidth *= m_iFontSize;
538       iCharWidth = iCharWidth * m_iHorizontalScale / 100;
539       pLastChar->m_iCharWidth = iCharWidth;
540       iLineWidth += iCharWidth;
541       iCharWidth = 0;
542     }
543   }
544   wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar,
545                                       nullptr);
546   if (m_bVertical != FX_IsOdd(iRotation)) {
547     iCharWidth = 1000;
548   } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode) &&
549              !m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth,
550                                     m_bCharCode)) {
551     iCharWidth = m_iDefChar;
552   }
553 
554   iCharWidth *= m_iFontSize;
555   iCharWidth = iCharWidth * m_iHorizontalScale / 100;
556   pCurChar->m_iCharWidth = iCharWidth;
557   iLineWidth += iCharWidth;
558   m_pCurLine->m_iArabicChars++;
559   if (!m_bSingleLine && !m_bOrphanLine &&
560       m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
561     return EndBreak(FX_RTFBREAK_LineBreak);
562   }
563   return FX_RTFBREAK_None;
564 }
AppendChar_Others(CFX_RTFChar * pCurChar,int32_t iRotation)565 uint32_t CFX_RTFBreak::AppendChar_Others(CFX_RTFChar* pCurChar,
566                                          int32_t iRotation) {
567   FX_CHARTYPE chartype = pCurChar->GetCharType();
568   FX_WCHAR wForm;
569   if (chartype == FX_CHARTYPE_Numeric) {
570     if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) {
571       wForm = pCurChar->m_wCharCode + 0x0630;
572     } else {
573       wForm = pCurChar->m_wCharCode;
574     }
575   } else if (m_bRTL || m_bVertical) {
576     wForm = FX_GetMirrorChar(pCurChar->m_wCharCode, pCurChar->m_dwCharProps,
577                              m_bRTL, m_bVertical);
578   } else {
579     wForm = pCurChar->m_wCharCode;
580   }
581   int32_t iCharWidth = 0;
582   if (m_bVertical != FX_IsOdd(iRotation)) {
583     iCharWidth = 1000;
584   } else {
585     if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) {
586       iCharWidth = m_iDefChar;
587     }
588   }
589   iCharWidth *= m_iFontSize;
590   iCharWidth = iCharWidth * m_iHorizontalScale / 100;
591   iCharWidth += m_iCharSpace;
592   if (chartype == FX_CHARTYPE_Space && m_bWordSpace) {
593     iCharWidth += m_iWordSpace;
594   }
595   pCurChar->m_iCharWidth = iCharWidth;
596   m_pCurLine->m_iWidth += iCharWidth;
597   FX_BOOL bBreak = (chartype != FX_CHARTYPE_Space ||
598                     (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0);
599   if (!m_bSingleLine && !m_bOrphanLine && bBreak &&
600       m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
601     return EndBreak(FX_RTFBREAK_LineBreak);
602   }
603   return FX_RTFBREAK_None;
604 }
EndBreak(uint32_t dwStatus)605 uint32_t CFX_RTFBreak::EndBreak(uint32_t dwStatus) {
606   ASSERT(dwStatus >= FX_RTFBREAK_PieceBreak &&
607          dwStatus <= FX_RTFBREAK_PageBreak);
608   m_dwIdentity++;
609   CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
610   int32_t iCount = pCurPieces->GetSize();
611   if (iCount > 0) {
612     CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
613     if (dwStatus > FX_RTFBREAK_PieceBreak) {
614       pLastPiece->m_dwStatus = dwStatus;
615     } else {
616       dwStatus = pLastPiece->m_dwStatus;
617     }
618     return dwStatus;
619   } else {
620     CFX_RTFLine* pLastLine = GetRTFLine(TRUE);
621     if (pLastLine) {
622       pCurPieces = &pLastLine->m_LinePieces;
623       iCount = pCurPieces->GetSize();
624       if (iCount-- > 0) {
625         CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
626         if (dwStatus > FX_RTFBREAK_PieceBreak) {
627           pLastPiece->m_dwStatus = dwStatus;
628         } else {
629           dwStatus = pLastPiece->m_dwStatus;
630         }
631         return dwStatus;
632       }
633       return FX_RTFBREAK_None;
634     }
635     iCount = m_pCurLine->CountChars();
636     if (iCount < 1) {
637       return FX_RTFBREAK_None;
638     }
639     CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1);
640     tc.m_dwStatus = dwStatus;
641     if (dwStatus <= FX_RTFBREAK_PieceBreak) {
642       return dwStatus;
643     }
644   }
645   m_iReady = (m_pCurLine == &m_RTFLine1) ? 1 : 2;
646   CFX_RTFLine* pNextLine =
647       (m_pCurLine == &m_RTFLine1) ? &m_RTFLine2 : &m_RTFLine1;
648   FX_BOOL bAllChars = (m_iAlignment > FX_RTFLINEALIGNMENT_Right);
649   CFX_TPOArray tpos;
650   if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
651     goto EndBreak_Ret;
652   }
653   if (!m_bCharCode) {
654     EndBreak_BidiLine(tpos, dwStatus);
655   }
656   if (!m_bPagination && m_iAlignment > FX_RTFLINEALIGNMENT_Left) {
657     EndBreak_Alignment(tpos, bAllChars, dwStatus);
658   }
659 EndBreak_Ret:
660   m_pCurLine = pNextLine;
661   m_pCurLine->m_iStart = m_iBoundaryStart;
662   CFX_RTFChar* pTC = GetLastChar(0);
663   m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown;
664   return dwStatus;
665 }
EndBreak_SplitLine(CFX_RTFLine * pNextLine,FX_BOOL bAllChars,uint32_t dwStatus)666 FX_BOOL CFX_RTFBreak::EndBreak_SplitLine(CFX_RTFLine* pNextLine,
667                                          FX_BOOL bAllChars,
668                                          uint32_t dwStatus) {
669   FX_BOOL bDone = FALSE;
670   if (!m_bSingleLine && !m_bOrphanLine &&
671       m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
672     CFX_RTFChar& tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1);
673     switch (tc.GetCharType()) {
674       case FX_CHARTYPE_Tab:
675         if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) {
676           SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
677           bDone = TRUE;
678         }
679         break;
680       case FX_CHARTYPE_Control:
681         break;
682       case FX_CHARTYPE_Space:
683         if ((m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0) {
684           SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
685           bDone = TRUE;
686         }
687         break;
688       default:
689         SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
690         bDone = TRUE;
691         break;
692     }
693   }
694   if (m_bPagination || m_pCurLine->m_iMBCSChars > 0) {
695     const CFX_RTFChar* pCurChars = m_pCurLine->m_LineChars.GetData();
696     const CFX_RTFChar* pTC;
697     CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
698     CFX_RTFPiece tp;
699     tp.m_pChars = &m_pCurLine->m_LineChars;
700     FX_BOOL bNew = TRUE;
701     uint32_t dwIdentity = (uint32_t)-1;
702     int32_t iLast = m_pCurLine->CountChars() - 1, j = 0;
703     for (int32_t i = 0; i <= iLast;) {
704       pTC = pCurChars + i;
705       if (bNew) {
706         tp.m_iStartChar = i;
707         tp.m_iStartPos += tp.m_iWidth;
708         tp.m_iWidth = 0;
709         tp.m_dwStatus = pTC->m_dwStatus;
710         tp.m_iFontSize = pTC->m_iFontSize;
711         tp.m_iFontHeight = pTC->m_iFontHeight;
712         tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
713         tp.m_iVerticalScale = pTC->m_iVertialScale;
714         tp.m_dwLayoutStyles = pTC->m_dwLayoutStyles;
715         dwIdentity = pTC->m_dwIdentity;
716         tp.m_dwIdentity = dwIdentity;
717         tp.m_pUserData = pTC->m_pUserData;
718         j = i;
719         bNew = FALSE;
720       }
721       if (i == iLast || pTC->m_dwStatus != FX_RTFBREAK_None ||
722           pTC->m_dwIdentity != dwIdentity) {
723         tp.m_iChars = i - j;
724         if (pTC->m_dwIdentity == dwIdentity) {
725           tp.m_dwStatus = pTC->m_dwStatus;
726           tp.m_iWidth += pTC->m_iCharWidth;
727           tp.m_iChars += 1;
728           i++;
729         }
730         pCurPieces->Add(tp);
731         bNew = TRUE;
732       } else {
733         tp.m_iWidth += pTC->m_iCharWidth;
734         i++;
735       }
736     }
737     return TRUE;
738   }
739   if (bAllChars && !bDone) {
740     int32_t iEndPos = m_pCurLine->GetLineEnd();
741     GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, TRUE);
742   }
743   return FALSE;
744 }
EndBreak_BidiLine(CFX_TPOArray & tpos,uint32_t dwStatus)745 void CFX_RTFBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, uint32_t dwStatus) {
746   FX_TPO tpo;
747   CFX_RTFPiece tp;
748   CFX_RTFChar* pTC;
749   int32_t i, j;
750   CFX_RTFCharArray& chars = m_pCurLine->m_LineChars;
751   int32_t iCount = m_pCurLine->CountChars();
752   FX_BOOL bDone = (!m_bPagination && !m_bCharCode &&
753                    (m_pCurLine->m_iArabicChars > 0 || m_bRTL));
754   if (bDone) {
755     int32_t iBidiNum = 0;
756     for (i = 0; i < iCount; i++) {
757       pTC = chars.GetDataPtr(i);
758       pTC->m_iBidiPos = i;
759       if (pTC->GetCharType() != FX_CHARTYPE_Control) {
760         iBidiNum = i;
761       }
762       if (i == 0) {
763         pTC->m_iBidiLevel = 1;
764       }
765     }
766     FX_BidiLine(chars, iBidiNum + 1, m_bRTL ? 1 : 0);
767   } else {
768     for (i = 0; i < iCount; i++) {
769       pTC = chars.GetDataPtr(i);
770       pTC->m_iBidiLevel = 0;
771       pTC->m_iBidiPos = 0;
772       pTC->m_iBidiOrder = 0;
773     }
774   }
775   tp.m_dwStatus = FX_RTFBREAK_PieceBreak;
776   tp.m_iStartPos = m_pCurLine->m_iStart;
777   tp.m_pChars = &chars;
778   CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
779   int32_t iBidiLevel = -1, iCharWidth;
780   uint32_t dwIdentity = (uint32_t)-1;
781   i = j = 0;
782   while (i < iCount) {
783     pTC = chars.GetDataPtr(i);
784     if (iBidiLevel < 0) {
785       iBidiLevel = pTC->m_iBidiLevel;
786       iCharWidth = pTC->m_iCharWidth;
787       if (iCharWidth < 1) {
788         tp.m_iWidth = 0;
789       } else {
790         tp.m_iWidth = iCharWidth;
791       }
792       tp.m_iBidiLevel = iBidiLevel;
793       tp.m_iBidiPos = pTC->m_iBidiOrder;
794       tp.m_iFontSize = pTC->m_iFontSize;
795       tp.m_iFontHeight = pTC->m_iFontHeight;
796       tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
797       tp.m_iVerticalScale = pTC->m_iVertialScale;
798       dwIdentity = pTC->m_dwIdentity;
799       tp.m_dwIdentity = dwIdentity;
800       tp.m_pUserData = pTC->m_pUserData;
801       tp.m_dwStatus = FX_RTFBREAK_PieceBreak;
802       i++;
803     } else if (iBidiLevel != pTC->m_iBidiLevel ||
804                pTC->m_dwIdentity != dwIdentity) {
805       tp.m_iChars = i - tp.m_iStartChar;
806       pCurPieces->Add(tp);
807       tp.m_iStartPos += tp.m_iWidth;
808       tp.m_iStartChar = i;
809       tpo.index = j++;
810       tpo.pos = tp.m_iBidiPos;
811       tpos.Add(tpo);
812       iBidiLevel = -1;
813     } else {
814       iCharWidth = pTC->m_iCharWidth;
815       if (iCharWidth > 0) {
816         tp.m_iWidth += iCharWidth;
817       }
818       i++;
819     }
820   }
821   if (i > tp.m_iStartChar) {
822     tp.m_dwStatus = dwStatus;
823     tp.m_iChars = i - tp.m_iStartChar;
824     pCurPieces->Add(tp);
825     tpo.index = j;
826     tpo.pos = tp.m_iBidiPos;
827     tpos.Add(tpo);
828   }
829   if (!m_bCharCode) {
830     j = tpos.GetSize() - 1;
831     FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
832     int32_t iStartPos = m_pCurLine->m_iStart;
833     for (i = 0; i <= j; i++) {
834       tpo = tpos.GetAt(i);
835       CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index);
836       ttp.m_iStartPos = iStartPos;
837       iStartPos += ttp.m_iWidth;
838     }
839   }
840 }
EndBreak_Alignment(CFX_TPOArray & tpos,FX_BOOL bAllChars,uint32_t dwStatus)841 void CFX_RTFBreak::EndBreak_Alignment(CFX_TPOArray& tpos,
842                                       FX_BOOL bAllChars,
843                                       uint32_t dwStatus) {
844   CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
845   int32_t iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
846   int32_t iCount = pCurPieces->GetSize();
847   FX_BOOL bFind = FALSE;
848   uint32_t dwCharType;
849   int32_t i, j;
850   FX_TPO tpo;
851   for (i = iCount - 1; i > -1; i--) {
852     tpo = tpos.GetAt(i);
853     CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index);
854     if (!bFind) {
855       iNetWidth = ttp.GetEndPos();
856     }
857     FX_BOOL bArabic = FX_IsOdd(ttp.m_iBidiLevel);
858     j = bArabic ? 0 : ttp.m_iChars - 1;
859     while (j > -1 && j < ttp.m_iChars) {
860       const CFX_RTFChar& tc = ttp.GetChar(j);
861       if (tc.m_nBreakType == FX_LBT_DIRECT_BRK) {
862         iGapChars++;
863       }
864       if (!bFind || !bAllChars) {
865         dwCharType = tc.GetCharType();
866         if (dwCharType == FX_CHARTYPE_Space ||
867             dwCharType == FX_CHARTYPE_Control) {
868           if (!bFind) {
869             iCharWidth = tc.m_iCharWidth;
870             if (bAllChars && iCharWidth > 0) {
871               iNetWidth -= iCharWidth;
872             }
873           }
874         } else {
875           bFind = TRUE;
876           if (!bAllChars) {
877             break;
878           }
879         }
880       }
881       j += bArabic ? 1 : -1;
882     }
883     if (!bAllChars && bFind) {
884       break;
885     }
886   }
887   int32_t iOffset = m_iBoundaryEnd - iNetWidth;
888   int32_t iLowerAlignment = (m_iAlignment & FX_RTFLINEALIGNMENT_LowerMask);
889   int32_t iHigherAlignment = (m_iAlignment & FX_RTFLINEALIGNMENT_HigherMask);
890   if (iGapChars > 0 && (iHigherAlignment == FX_RTFLINEALIGNMENT_Distributed ||
891                         (iHigherAlignment == FX_RTFLINEALIGNMENT_Justified &&
892                          dwStatus != FX_RTFBREAK_ParagraphBreak))) {
893     int32_t iStart = -1;
894     for (i = 0; i < iCount; i++) {
895       tpo = tpos.GetAt(i);
896       CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index);
897       if (iStart < 0) {
898         iStart = ttp.m_iStartPos;
899       } else {
900         ttp.m_iStartPos = iStart;
901       }
902       int32_t k;
903       for (j = 0; j < ttp.m_iChars; j++) {
904         CFX_RTFChar& tc = ttp.GetChar(j);
905         if (tc.m_nBreakType != FX_LBT_DIRECT_BRK || tc.m_iCharWidth < 0) {
906           continue;
907         }
908         k = iOffset / iGapChars;
909         tc.m_iCharWidth += k;
910         ttp.m_iWidth += k;
911         iOffset -= k;
912         iGapChars--;
913         if (iGapChars < 1) {
914           break;
915         }
916       }
917       iStart += ttp.m_iWidth;
918     }
919   } else if (iLowerAlignment > FX_RTFLINEALIGNMENT_Left) {
920     if (iLowerAlignment == FX_RTFLINEALIGNMENT_Center) {
921       iOffset /= 2;
922     }
923     if (iOffset > 0) {
924       for (i = 0; i < iCount; i++) {
925         CFX_RTFPiece& ttp = pCurPieces->GetAt(i);
926         ttp.m_iStartPos += iOffset;
927       }
928     }
929   }
930 }
GetBreakPos(CFX_RTFCharArray & tca,int32_t & iEndPos,FX_BOOL bAllChars,FX_BOOL bOnlyBrk)931 int32_t CFX_RTFBreak::GetBreakPos(CFX_RTFCharArray& tca,
932                                   int32_t& iEndPos,
933                                   FX_BOOL bAllChars,
934                                   FX_BOOL bOnlyBrk) {
935   int32_t iLength = tca.GetSize() - 1;
936   if (iLength < 1) {
937     return iLength;
938   }
939   int32_t iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1,
940           iLast = -1, iLastPos = -1;
941   if (m_bSingleLine || m_bOrphanLine || iEndPos <= m_iBoundaryEnd) {
942     if (!bAllChars || m_bCharCode) {
943       return iLength;
944     }
945     iBreak = iLength;
946     iBreakPos = iEndPos;
947   }
948   CFX_RTFChar* pCharArray = tca.GetData();
949   if (m_bCharCode) {
950     const CFX_RTFChar* pChar;
951     int32_t iCharWidth;
952     while (iLength > 0) {
953       if (iEndPos <= m_iBoundaryEnd) {
954         break;
955       }
956       pChar = pCharArray + iLength--;
957       iCharWidth = pChar->m_iCharWidth;
958       if (iCharWidth > 0) {
959         iEndPos -= iCharWidth;
960       }
961     }
962     return iLength;
963   }
964   FX_BOOL bSpaceBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0;
965   FX_BOOL bTabBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0;
966   FX_BOOL bNumberBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_NumberBreak) != 0;
967   FX_BOOL bInfixBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_InfixBreak) != 0;
968   FX_LINEBREAKTYPE eType;
969   uint32_t nCodeProp, nCur, nNext;
970   CFX_RTFChar* pCur = pCharArray + iLength--;
971   if (bAllChars) {
972     pCur->m_nBreakType = FX_LBT_UNKNOWN;
973   }
974   nCodeProp = pCur->m_dwCharProps;
975   nNext = nCodeProp & 0x003F;
976   int32_t iCharWidth = pCur->m_iCharWidth;
977   if (iCharWidth > 0) {
978     iEndPos -= iCharWidth;
979   }
980   while (iLength >= 0) {
981     pCur = pCharArray + iLength;
982     nCodeProp = pCur->m_dwCharProps;
983     nCur = nCodeProp & 0x003F;
984     FX_BOOL bNeedBreak = FALSE;
985     if (nCur == FX_CBP_SP) {
986       bNeedBreak = !bSpaceBreak;
987       if (nNext == FX_CBP_SP) {
988         eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
989       } else {
990         eType = gs_FX_LineBreak_PairTable[nCur][nNext];
991       }
992     } else if (nCur == FX_CBP_TB) {
993       bNeedBreak = !bTabBreak;
994       if (nNext == FX_CBP_TB) {
995         eType = bTabBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
996       } else {
997         eType = gs_FX_LineBreak_PairTable[nCur][nNext];
998       }
999     } else if ((bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) ||
1000                (bInfixBreak && nCur == FX_CBP_IS && nNext == FX_CBP_IS)) {
1001       eType = FX_LBT_DIRECT_BRK;
1002     } else {
1003       if (nNext == FX_CBP_SP) {
1004         eType = FX_LBT_PROHIBITED_BRK;
1005       } else {
1006         eType = gs_FX_LineBreak_PairTable[nCur][nNext];
1007       }
1008     }
1009     if (bAllChars) {
1010       pCur->m_nBreakType = eType;
1011     }
1012     if (!bOnlyBrk) {
1013       iCharWidth = pCur->m_iCharWidth;
1014       FX_BOOL bBreak = FALSE;
1015       if (nCur == FX_CBP_TB && bTabBreak) {
1016         bBreak = iCharWidth > 0 && iEndPos - iCharWidth <= m_iBoundaryEnd;
1017       } else {
1018         bBreak = iEndPos <= m_iBoundaryEnd;
1019       }
1020       if (m_bSingleLine || m_bOrphanLine || bBreak || bNeedBreak) {
1021         if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
1022           iBreak = iLength;
1023           iBreakPos = iEndPos;
1024           if (!bAllChars) {
1025             return iLength;
1026           }
1027         } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
1028           iIndirect = iLength;
1029           iIndirectPos = iEndPos;
1030         }
1031         if (iLast < 0) {
1032           iLast = iLength;
1033           iLastPos = iEndPos;
1034         }
1035       }
1036       if (iCharWidth > 0) {
1037         iEndPos -= iCharWidth;
1038       }
1039     }
1040     nNext = nCodeProp & 0x003F;
1041     iLength--;
1042   }
1043   if (bOnlyBrk) {
1044     return 0;
1045   }
1046   if (iBreak > -1) {
1047     iEndPos = iBreakPos;
1048     return iBreak;
1049   }
1050   if (iIndirect > -1) {
1051     iEndPos = iIndirectPos;
1052     return iIndirect;
1053   }
1054   if (iLast > -1) {
1055     iEndPos = iLastPos;
1056     return iLast;
1057   }
1058   return 0;
1059 }
SplitTextLine(CFX_RTFLine * pCurLine,CFX_RTFLine * pNextLine,FX_BOOL bAllChars)1060 void CFX_RTFBreak::SplitTextLine(CFX_RTFLine* pCurLine,
1061                                  CFX_RTFLine* pNextLine,
1062                                  FX_BOOL bAllChars) {
1063   ASSERT(pCurLine && pNextLine);
1064   int32_t iCount = pCurLine->CountChars();
1065   if (iCount < 2) {
1066     return;
1067   }
1068   int32_t iEndPos = pCurLine->GetLineEnd();
1069   CFX_RTFCharArray& curChars = pCurLine->m_LineChars;
1070   int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, FALSE);
1071   if (iCharPos < 0) {
1072     iCharPos = 0;
1073   }
1074   iCharPos++;
1075   if (iCharPos >= iCount) {
1076     pNextLine->RemoveAll(TRUE);
1077     CFX_Char* pTC = curChars.GetDataPtr(iCharPos - 1);
1078     pTC->m_nBreakType = FX_LBT_UNKNOWN;
1079     return;
1080   }
1081   CFX_RTFCharArray& nextChars = pNextLine->m_LineChars;
1082   int cur_size = curChars.GetSize();
1083   nextChars.SetSize(cur_size - iCharPos);
1084   FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos),
1085                (cur_size - iCharPos) * sizeof(CFX_RTFChar));
1086   iCount -= iCharPos;
1087   cur_size = curChars.GetSize();
1088   curChars.RemoveAt(cur_size - iCount, iCount);
1089   pNextLine->m_iStart = pCurLine->m_iStart;
1090   pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos;
1091   pCurLine->m_iWidth = iEndPos;
1092   curChars.GetDataPtr(iCharPos - 1)->m_nBreakType = FX_LBT_UNKNOWN;
1093   iCount = nextChars.GetSize();
1094   CFX_RTFChar* pNextChars = nextChars.GetData();
1095   for (int32_t i = 0; i < iCount; i++) {
1096     CFX_RTFChar* tc = pNextChars + i;
1097     if (tc->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
1098       pCurLine->m_iArabicChars--;
1099       pNextLine->m_iArabicChars++;
1100     }
1101     if (tc->m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) {
1102       pCurLine->m_iMBCSChars--;
1103       pNextLine->m_iMBCSChars++;
1104     }
1105     tc->m_dwStatus = 0;
1106   }
1107 }
CountBreakPieces() const1108 int32_t CFX_RTFBreak::CountBreakPieces() const {
1109   CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(TRUE);
1110   return pRTFPieces ? pRTFPieces->GetSize() : 0;
1111 }
GetBreakPiece(int32_t index) const1112 const CFX_RTFPiece* CFX_RTFBreak::GetBreakPiece(int32_t index) const {
1113   CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(TRUE);
1114   if (!pRTFPieces) {
1115     return nullptr;
1116   }
1117   if (index < 0 || index >= pRTFPieces->GetSize()) {
1118     return nullptr;
1119   }
1120   return pRTFPieces->GetPtrAt(index);
1121 }
GetLineRect(CFX_RectF & rect) const1122 void CFX_RTFBreak::GetLineRect(CFX_RectF& rect) const {
1123   rect.top = 0;
1124   CFX_RTFLine* pRTFLine = GetRTFLine(TRUE);
1125   if (!pRTFLine) {
1126     rect.left = ((FX_FLOAT)m_iBoundaryStart) / 20000.0f;
1127     rect.width = rect.height = 0;
1128     return;
1129   }
1130   rect.left = ((FX_FLOAT)pRTFLine->m_iStart) / 20000.0f;
1131   rect.width = ((FX_FLOAT)pRTFLine->m_iWidth) / 20000.0f;
1132   CFX_RTFPieceArray& rtfPieces = pRTFLine->m_LinePieces;
1133   int32_t iCount = rtfPieces.GetSize();
1134   if (iCount < 1) {
1135     rect.width = 0;
1136     return;
1137   }
1138   CFX_RTFPiece* pBreakPiece;
1139   int32_t iLineHeight = 0, iMax;
1140   for (int32_t i = 0; i < iCount; i++) {
1141     pBreakPiece = rtfPieces.GetPtrAt(i);
1142     int32_t iFontHeight = FXSYS_round(pBreakPiece->m_iFontHeight *
1143                                       pBreakPiece->m_iVerticalScale / 100.0f);
1144     iMax = std::max(pBreakPiece->m_iFontSize, iFontHeight);
1145     if (i == 0) {
1146       iLineHeight = iMax;
1147     } else if (iLineHeight < iMax) {
1148       iLineHeight = iMax;
1149     }
1150   }
1151   rect.height = ((FX_FLOAT)iLineHeight) / 20.0f;
1152 }
ClearBreakPieces()1153 void CFX_RTFBreak::ClearBreakPieces() {
1154   CFX_RTFLine* pRTFLine = GetRTFLine(TRUE);
1155   if (pRTFLine) {
1156     pRTFLine->RemoveAll(TRUE);
1157   }
1158   m_iReady = 0;
1159 }
Reset()1160 void CFX_RTFBreak::Reset() {
1161   m_eCharType = FX_CHARTYPE_Unknown;
1162   m_RTFLine1.RemoveAll(TRUE);
1163   m_RTFLine2.RemoveAll(TRUE);
1164 }
GetDisplayPos(const FX_RTFTEXTOBJ * pText,FXTEXT_CHARPOS * pCharPos,FX_BOOL bCharCode,CFX_WideString * pWSForms,FX_AdjustCharDisplayPos pAdjustPos) const1165 int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText,
1166                                     FXTEXT_CHARPOS* pCharPos,
1167                                     FX_BOOL bCharCode,
1168                                     CFX_WideString* pWSForms,
1169                                     FX_AdjustCharDisplayPos pAdjustPos) const {
1170   if (!pText || pText->iLength < 1) {
1171     return 0;
1172   }
1173   ASSERT(pText->pStr && pText->pWidths && pText->pFont && pText->pRect);
1174   const FX_WCHAR* pStr = pText->pStr;
1175   int32_t* pWidths = pText->pWidths;
1176   int32_t iLength = pText->iLength - 1;
1177   CFGAS_GEFont* pFont = pText->pFont;
1178   uint32_t dwStyles = pText->dwLayoutStyles;
1179   CFX_RectF rtText(*pText->pRect);
1180   FX_BOOL bRTLPiece = FX_IsOdd(pText->iBidiLevel);
1181   FX_FLOAT fFontSize = pText->fFontSize;
1182   int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1183   int32_t iAscent = pFont->GetAscent();
1184   int32_t iDescent = pFont->GetDescent();
1185   int32_t iMaxHeight = iAscent - iDescent;
1186   FX_FLOAT fFontHeight = fFontSize;
1187   FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
1188   FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
1189   FX_BOOL bVerticalDoc = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0;
1190   FX_BOOL bVerticalChar = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0;
1191   FX_BOOL bArabicNumber = (dwStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) != 0;
1192   FX_BOOL bMBCSCode = (dwStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
1193   int32_t iRotation = GetLineRotation(dwStyles) + pText->iCharRotation;
1194   int32_t iCharRotation;
1195   FX_WCHAR wch, wPrev = 0xFEFF, wNext, wForm;
1196   int32_t iWidth, iCharWidth, iCharHeight;
1197   FX_FLOAT fX, fY, fCharWidth, fCharHeight;
1198   int32_t iHorScale = pText->iHorizontalScale;
1199   int32_t iVerScale = pText->iVerticalScale;
1200   FX_BOOL bEmptyChar;
1201   uint32_t dwProps, dwCharType;
1202   fX = rtText.left;
1203   fY = rtText.top;
1204   if (bVerticalDoc) {
1205     fX += (rtText.width - fFontSize) / 2.0f;
1206     if (bRTLPiece) {
1207       fY = rtText.bottom();
1208     }
1209   } else {
1210     if (bRTLPiece) {
1211       fX = rtText.right();
1212     }
1213     fY += fAscent;
1214   }
1215   int32_t iCount = 0;
1216   for (int32_t i = 0; i <= iLength; i++) {
1217     wch = *pStr++;
1218     iWidth = *pWidths++;
1219     if (!bMBCSCode) {
1220       dwProps = FX_GetUnicodeProperties(wch);
1221       dwCharType = (dwProps & FX_CHARTYPEBITSMASK);
1222       if (dwCharType == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
1223         wPrev = 0xFEFF;
1224         continue;
1225       }
1226     } else {
1227       dwProps = 0;
1228       dwCharType = 0;
1229     }
1230     if (iWidth != 0) {
1231       iCharWidth = iWidth;
1232       if (iCharWidth < 0) {
1233         iCharWidth = -iCharWidth;
1234       }
1235       if (!bMBCSCode) {
1236         bEmptyChar = (dwCharType >= FX_CHARTYPE_Tab &&
1237                       dwCharType <= FX_CHARTYPE_Control);
1238       } else {
1239         bEmptyChar = FALSE;
1240       }
1241       if (!bEmptyChar) {
1242         iCount++;
1243       }
1244       if (pCharPos) {
1245         iCharWidth /= iFontSize;
1246         wForm = wch;
1247         if (!bMBCSCode) {
1248           if (dwCharType >= FX_CHARTYPE_ArabicAlef) {
1249             if (i < iLength) {
1250               wNext = *pStr;
1251               if (*pWidths < 0) {
1252                 if (i + 1 < iLength) {
1253                   wNext = pStr[1];
1254                 }
1255               }
1256             } else {
1257               wNext = 0xFEFF;
1258             }
1259             wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext);
1260           } else if (bRTLPiece || bVerticalChar) {
1261             wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
1262           } else if (dwCharType == FX_CHARTYPE_Numeric && bArabicNumber) {
1263             wForm = wch + 0x0630;
1264           }
1265           dwProps = FX_GetUnicodeProperties(wForm);
1266         }
1267         iCharRotation = iRotation;
1268         if (!bMBCSCode && bVerticalChar && (dwProps & 0x8000) != 0) {
1269           iCharRotation++;
1270           iCharRotation %= 4;
1271         }
1272         if (!bEmptyChar) {
1273           if (bCharCode) {
1274             pCharPos->m_GlyphIndex = wch;
1275           } else {
1276             pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, bMBCSCode);
1277             if (pCharPos->m_GlyphIndex == 0xFFFF) {
1278               pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, bMBCSCode);
1279             }
1280           }
1281 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
1282           pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
1283 #endif
1284           pCharPos->m_FontCharWidth = iCharWidth;
1285           if (pWSForms) {
1286             *pWSForms += wForm;
1287           }
1288         }
1289         if (bVerticalDoc) {
1290           iCharHeight = iCharWidth;
1291           iCharWidth = 1000;
1292         } else {
1293           iCharHeight = 1000;
1294         }
1295         fCharWidth = fFontSize * iCharWidth / 1000.0f;
1296         fCharHeight = fFontSize * iCharHeight / 1000.0f;
1297         if (!bMBCSCode && bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
1298           if (bVerticalDoc) {
1299             fY -= fCharHeight;
1300           } else {
1301             fX -= fCharWidth;
1302           }
1303         }
1304         if (!bEmptyChar) {
1305           CFX_PointF ptOffset;
1306           FX_BOOL bAdjusted = FALSE;
1307           if (pAdjustPos) {
1308             bAdjusted = pAdjustPos(wForm, bMBCSCode, pFont, fFontSize,
1309                                    bVerticalChar, ptOffset);
1310           }
1311           if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) {
1312             CFX_Rect rtBBox;
1313             rtBBox.Reset();
1314             if (pFont->GetCharBBox(wForm, rtBBox, bMBCSCode)) {
1315               ptOffset.x = fFontSize * (850 - rtBBox.right()) / 1000.0f;
1316               ptOffset.y = fFontSize * (1000 - rtBBox.height) / 2000.0f;
1317             }
1318           }
1319           pCharPos->m_OriginX = fX + ptOffset.x;
1320           pCharPos->m_OriginY = fY - ptOffset.y;
1321         }
1322         if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
1323           if (bVerticalDoc) {
1324             fY += fCharHeight;
1325           } else {
1326             fX += fCharWidth;
1327           }
1328         }
1329         if (!bEmptyChar) {
1330           pCharPos->m_bGlyphAdjust = TRUE;
1331           if (bVerticalDoc) {
1332             if (iCharRotation == 0) {
1333               pCharPos->m_AdjustMatrix[0] = -1;
1334               pCharPos->m_AdjustMatrix[1] = 0;
1335               pCharPos->m_AdjustMatrix[2] = 0;
1336               pCharPos->m_AdjustMatrix[3] = 1;
1337               pCharPos->m_OriginY += fAscent * iVerScale / 100.0f;
1338             } else if (iCharRotation == 1) {
1339               pCharPos->m_AdjustMatrix[0] = 0;
1340               pCharPos->m_AdjustMatrix[1] = -1;
1341               pCharPos->m_AdjustMatrix[2] = -1;
1342               pCharPos->m_AdjustMatrix[3] = 0;
1343               pCharPos->m_OriginX -=
1344                   fDescent + fAscent * iVerScale / 100.0f - fAscent;
1345             } else if (iCharRotation == 2) {
1346               pCharPos->m_AdjustMatrix[0] = 1;
1347               pCharPos->m_AdjustMatrix[1] = 0;
1348               pCharPos->m_AdjustMatrix[2] = 0;
1349               pCharPos->m_AdjustMatrix[3] = -1;
1350               pCharPos->m_OriginX += fCharWidth;
1351               pCharPos->m_OriginY += fAscent;
1352             } else {
1353               pCharPos->m_AdjustMatrix[0] = 0;
1354               pCharPos->m_AdjustMatrix[1] = 1;
1355               pCharPos->m_AdjustMatrix[2] = 1;
1356               pCharPos->m_AdjustMatrix[3] = 0;
1357               pCharPos->m_OriginX += fAscent;
1358               pCharPos->m_OriginY += fCharWidth;
1359             }
1360           } else {
1361             if (iCharRotation == 0) {
1362               pCharPos->m_AdjustMatrix[0] = -1;
1363               pCharPos->m_AdjustMatrix[1] = 0;
1364               pCharPos->m_AdjustMatrix[2] = 0;
1365               pCharPos->m_AdjustMatrix[3] = 1;
1366               pCharPos->m_OriginY += fAscent * iVerScale / 100.0f - fAscent;
1367             } else if (iCharRotation == 1) {
1368               pCharPos->m_AdjustMatrix[0] = 0;
1369               pCharPos->m_AdjustMatrix[1] = -1;
1370               pCharPos->m_AdjustMatrix[2] = -1;
1371               pCharPos->m_AdjustMatrix[3] = 0;
1372               pCharPos->m_OriginX -= fDescent;
1373               pCharPos->m_OriginY -= fAscent + fDescent;
1374             } else if (iCharRotation == 2) {
1375               pCharPos->m_AdjustMatrix[0] = 1;
1376               pCharPos->m_AdjustMatrix[1] = 0;
1377               pCharPos->m_AdjustMatrix[2] = 0;
1378               pCharPos->m_AdjustMatrix[3] = -1;
1379               pCharPos->m_OriginX += fCharWidth;
1380               pCharPos->m_OriginY -= fAscent;
1381             } else {
1382               pCharPos->m_AdjustMatrix[0] = 0;
1383               pCharPos->m_AdjustMatrix[1] = 1;
1384               pCharPos->m_AdjustMatrix[2] = 1;
1385               pCharPos->m_AdjustMatrix[3] = 0;
1386               pCharPos->m_OriginX += fAscent * iVerScale / 100.0f;
1387             }
1388           }
1389           if (iHorScale != 100 || iVerScale != 100) {
1390             pCharPos->m_AdjustMatrix[0] =
1391                 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
1392             pCharPos->m_AdjustMatrix[1] =
1393                 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
1394             pCharPos->m_AdjustMatrix[2] =
1395                 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
1396             pCharPos->m_AdjustMatrix[3] =
1397                 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
1398           }
1399           pCharPos++;
1400         }
1401       }
1402     }
1403     if (iWidth > 0) {
1404       wPrev = wch;
1405     }
1406   }
1407   return iCount;
1408 }
GetCharRects(const FX_RTFTEXTOBJ * pText,CFX_RectFArray & rtArray,FX_BOOL bCharBBox) const1409 int32_t CFX_RTFBreak::GetCharRects(const FX_RTFTEXTOBJ* pText,
1410                                    CFX_RectFArray& rtArray,
1411                                    FX_BOOL bCharBBox) const {
1412   if (!pText || pText->iLength < 1) {
1413     return 0;
1414   }
1415   ASSERT(pText->pStr && pText->pWidths && pText->pFont && pText->pRect);
1416   const FX_WCHAR* pStr = pText->pStr;
1417   int32_t* pWidths = pText->pWidths;
1418   int32_t iLength = pText->iLength;
1419   CFX_RectF rect(*pText->pRect);
1420   FX_BOOL bRTLPiece = FX_IsOdd(pText->iBidiLevel);
1421   FX_FLOAT fFontSize = pText->fFontSize;
1422   int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1423   FX_FLOAT fScale = fFontSize / 1000.0f;
1424   CFGAS_GEFont* pFont = pText->pFont;
1425   if (!pFont) {
1426     bCharBBox = FALSE;
1427   }
1428   CFX_Rect bbox;
1429   bbox.Set(0, 0, 0, 0);
1430   if (bCharBBox) {
1431     bCharBBox = pFont->GetBBox(bbox);
1432   }
1433   FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
1434   FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
1435   rtArray.RemoveAll();
1436   rtArray.SetSize(iLength);
1437   uint32_t dwStyles = pText->dwLayoutStyles;
1438   FX_BOOL bVertical = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0;
1439   FX_BOOL bSingleLine = (dwStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0;
1440   FX_BOOL bCombText = (dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
1441   FX_WCHAR wch, wLineBreakChar = pText->wLineBreakChar;
1442   int32_t iCharSize;
1443   FX_FLOAT fCharSize, fStart;
1444   if (bVertical) {
1445     fStart = bRTLPiece ? rect.bottom() : rect.top;
1446   } else {
1447     fStart = bRTLPiece ? rect.right() : rect.left;
1448   }
1449   for (int32_t i = 0; i < iLength; i++) {
1450     wch = *pStr++;
1451     iCharSize = *pWidths++;
1452     fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
1453     FX_BOOL bRet = (!bSingleLine && FX_IsCtrlCode(wch));
1454     if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
1455           (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
1456       bRet = FALSE;
1457     }
1458     if (bRet) {
1459       iCharSize = iFontSize * 500;
1460       fCharSize = fFontSize / 2.0f;
1461     }
1462     if (bVertical) {
1463       rect.top = fStart;
1464       if (bRTLPiece) {
1465         rect.top -= fCharSize;
1466         fStart -= fCharSize;
1467       } else {
1468         fStart += fCharSize;
1469       }
1470       rect.height = fCharSize;
1471     } else {
1472       rect.left = fStart;
1473       if (bRTLPiece) {
1474         rect.left -= fCharSize;
1475         fStart -= fCharSize;
1476       } else {
1477         fStart += fCharSize;
1478       }
1479       rect.width = fCharSize;
1480     }
1481     if (bCharBBox && !bRet) {
1482       int32_t iCharWidth = 1000;
1483       pFont->GetCharWidth(wch, iCharWidth);
1484       FX_FLOAT fRTLeft = 0, fCharWidth = 0;
1485       if (iCharWidth > 0) {
1486         fCharWidth = iCharWidth * fScale;
1487         fRTLeft = fLeft;
1488         if (bCombText) {
1489           fRTLeft = (rect.width - fCharWidth) / 2.0f;
1490         }
1491       }
1492       CFX_RectF rtBBoxF;
1493       if (bVertical) {
1494         rtBBoxF.top = rect.left + fRTLeft;
1495         rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
1496         rtBBoxF.height = fCharWidth;
1497         rtBBoxF.width = fHeight;
1498         rtBBoxF.left = std::max(rtBBoxF.left, 0.0f);
1499       } else {
1500         rtBBoxF.left = rect.left + fRTLeft;
1501         rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
1502         rtBBoxF.width = fCharWidth;
1503         rtBBoxF.height = fHeight;
1504         rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
1505       }
1506       rtArray.SetAt(i, rtBBoxF);
1507       continue;
1508     }
1509     rtArray.SetAt(i, rect);
1510   }
1511   return iLength;
1512 }
1513 
CFX_RTFPiece()1514 CFX_RTFPiece::CFX_RTFPiece()
1515     : m_dwStatus(FX_RTFBREAK_PieceBreak),
1516       m_iStartPos(0),
1517       m_iWidth(-1),
1518       m_iStartChar(0),
1519       m_iChars(0),
1520       m_iBidiLevel(0),
1521       m_iBidiPos(0),
1522       m_iFontSize(0),
1523       m_iFontHeight(0),
1524       m_iHorizontalScale(100),
1525       m_iVerticalScale(100),
1526       m_dwLayoutStyles(0),
1527       m_dwIdentity(0),
1528       m_pChars(nullptr),
1529       m_pUserData(nullptr) {}
1530 
~CFX_RTFPiece()1531 CFX_RTFPiece::~CFX_RTFPiece() {
1532   Reset();
1533 }
1534 
CFX_RTFLine()1535 CFX_RTFLine::CFX_RTFLine()
1536     : m_LinePieces(16),
1537       m_iStart(0),
1538       m_iWidth(0),
1539       m_iArabicChars(0),
1540       m_iMBCSChars(0) {}
1541 
~CFX_RTFLine()1542 CFX_RTFLine::~CFX_RTFLine() {
1543   RemoveAll();
1544 }
1545 
FX_RTFTEXTOBJ()1546 FX_RTFTEXTOBJ::FX_RTFTEXTOBJ()
1547     : pStr(nullptr),
1548       pWidths(nullptr),
1549       iLength(0),
1550       pFont(nullptr),
1551       fFontSize(12.0f),
1552       dwLayoutStyles(0),
1553       iCharRotation(0),
1554       iBidiLevel(0),
1555       pRect(nullptr),
1556       wLineBreakChar(L'\n'),
1557       iHorizontalScale(100),
1558       iVerticalScale(100) {}
1559