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