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