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_textbreak.h"
8
9 #include <algorithm>
10
11 #include "core/fxcrt/include/fx_arabic.h"
12 #include "core/fxcrt/include/fx_arb.h"
13 #include "core/fxcrt/include/fx_memory.h"
14 #include "xfa/fgas/font/fgas_gefont.h"
15 #include "xfa/fgas/layout/fgas_linebreak.h"
16 #include "xfa/fgas/layout/fgas_unicode.h"
17
18 namespace {
19
20 typedef uint32_t (CFX_TxtBreak::*FX_TxtBreak_LPFAppendChar)(
21 CFX_TxtChar* pCurChar,
22 int32_t iRotation);
23 const FX_TxtBreak_LPFAppendChar g_FX_TxtBreak_lpfAppendChar[16] = {
24 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Tab,
25 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Control,
26 &CFX_TxtBreak::AppendChar_Combination, &CFX_TxtBreak::AppendChar_Others,
27 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Arabic,
28 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
29 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
30 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Others,
31 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Others,
32 };
33
34 } // namespace
35
CFX_TxtBreak(uint32_t dwPolicies)36 CFX_TxtBreak::CFX_TxtBreak(uint32_t dwPolicies)
37 : m_dwPolicies(dwPolicies),
38 m_iLineWidth(2000000),
39 m_dwLayoutStyles(0),
40 m_bVertical(FALSE),
41 m_bArabicContext(FALSE),
42 m_bArabicShapes(FALSE),
43 m_bRTL(FALSE),
44 m_bSingleLine(FALSE),
45 m_bCombText(FALSE),
46 m_iArabicContext(1),
47 m_iCurArabicContext(1),
48 m_pFont(nullptr),
49 m_iFontSize(240),
50 m_bEquidistant(TRUE),
51 m_iTabWidth(720000),
52 m_wDefChar(0xFEFF),
53 m_wParagBreakChar(L'\n'),
54 m_iDefChar(0),
55 m_iLineRotation(0),
56 m_iCharRotation(0),
57 m_iRotation(0),
58 m_iAlignment(FX_TXTLINEALIGNMENT_Left),
59 m_dwContextCharStyles(0),
60 m_iCombWidth(360000),
61 m_pUserData(nullptr),
62 m_eCharType(FX_CHARTYPE_Unknown),
63 m_bArabicNumber(FALSE),
64 m_bArabicComma(FALSE),
65 m_pCurLine(nullptr),
66 m_iReady(0),
67 m_iTolerance(0),
68 m_iHorScale(100),
69 m_iVerScale(100),
70 m_iCharSpace(0) {
71 m_bPagination = (m_dwPolicies & FX_TXTBREAKPOLICY_Pagination) != 0;
72 if (m_bPagination) {
73 m_pTxtLine1 = new CFX_TxtLine(sizeof(CFX_Char));
74 m_pTxtLine2 = new CFX_TxtLine(sizeof(CFX_Char));
75 } else {
76 m_pTxtLine1 = new CFX_TxtLine(sizeof(CFX_TxtChar));
77 m_pTxtLine2 = new CFX_TxtLine(sizeof(CFX_TxtChar));
78 }
79 m_pCurLine = m_pTxtLine1;
80 ResetArabicContext();
81 }
~CFX_TxtBreak()82 CFX_TxtBreak::~CFX_TxtBreak() {
83 Reset();
84 delete m_pTxtLine1;
85 delete m_pTxtLine2;
86 }
SetLineWidth(FX_FLOAT fLineWidth)87 void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth) {
88 m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
89 ASSERT(m_iLineWidth >= 20000);
90 }
SetLinePos(FX_FLOAT fLinePos)91 void CFX_TxtBreak::SetLinePos(FX_FLOAT fLinePos) {
92 int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f);
93 if (iLinePos < 0) {
94 iLinePos = 0;
95 }
96 if (iLinePos > m_iLineWidth) {
97 iLinePos = m_iLineWidth;
98 }
99 m_pCurLine->m_iStart = iLinePos;
100 m_pCurLine->m_iWidth += iLinePos;
101 }
SetLayoutStyles(uint32_t dwLayoutStyles)102 void CFX_TxtBreak::SetLayoutStyles(uint32_t dwLayoutStyles) {
103 m_dwLayoutStyles = dwLayoutStyles;
104 m_bVertical = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
105 m_bArabicContext = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicContext) != 0;
106 m_bArabicShapes = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicShapes) != 0;
107 m_bRTL = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_RTLReadingOrder) != 0;
108 m_bSingleLine = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
109 m_bCombText = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
110 ResetArabicContext();
111 m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
112 m_iRotation = m_iLineRotation + m_iCharRotation;
113 m_iRotation %= 4;
114 }
SetFont(CFGAS_GEFont * pFont)115 void CFX_TxtBreak::SetFont(CFGAS_GEFont* pFont) {
116 if (!pFont) {
117 return;
118 }
119 if (m_pFont == pFont) {
120 return;
121 }
122 SetBreakStatus();
123 m_pFont = pFont;
124 m_iDefChar = 0;
125 if (m_wDefChar != 0xFEFF && m_pFont) {
126 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
127 m_iDefChar *= m_iFontSize;
128 }
129 }
SetFontSize(FX_FLOAT fFontSize)130 void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize) {
131 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
132 if (m_iFontSize == iFontSize) {
133 return;
134 }
135 SetBreakStatus();
136 m_iFontSize = iFontSize;
137 m_iDefChar = 0;
138 if (m_wDefChar != 0xFEFF && m_pFont) {
139 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
140 m_iDefChar *= m_iFontSize;
141 }
142 }
SetTabWidth(FX_FLOAT fTabWidth,FX_BOOL bEquidistant)143 void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) {
144 m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
145 if (m_iTabWidth < FX_TXTBREAK_MinimumTabWidth) {
146 m_iTabWidth = FX_TXTBREAK_MinimumTabWidth;
147 }
148 m_bEquidistant = bEquidistant;
149 }
SetDefaultChar(FX_WCHAR wch)150 void CFX_TxtBreak::SetDefaultChar(FX_WCHAR wch) {
151 m_wDefChar = wch;
152 m_iDefChar = 0;
153 if (m_wDefChar != 0xFEFF && m_pFont) {
154 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
155 if (m_iDefChar < 0) {
156 m_iDefChar = 0;
157 } else {
158 m_iDefChar *= m_iFontSize;
159 }
160 }
161 }
SetParagraphBreakChar(FX_WCHAR wch)162 void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch) {
163 if (wch != L'\r' && wch != L'\n') {
164 return;
165 }
166 m_wParagBreakChar = wch;
167 }
SetLineBreakTolerance(FX_FLOAT fTolerance)168 void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
169 m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
170 }
SetCharRotation(int32_t iCharRotation)171 void CFX_TxtBreak::SetCharRotation(int32_t iCharRotation) {
172 if (iCharRotation < 0) {
173 iCharRotation += (-iCharRotation / 4 + 1) * 4;
174 } else if (iCharRotation > 3) {
175 iCharRotation -= (iCharRotation / 4) * 4;
176 }
177 if (m_iCharRotation == iCharRotation) {
178 return;
179 }
180 SetBreakStatus();
181 m_iCharRotation = iCharRotation;
182 m_iRotation = m_iLineRotation + m_iCharRotation;
183 m_iRotation %= 4;
184 }
SetAlignment(int32_t iAlignment)185 void CFX_TxtBreak::SetAlignment(int32_t iAlignment) {
186 ASSERT(iAlignment >= FX_TXTLINEALIGNMENT_Left &&
187 iAlignment <= FX_TXTLINEALIGNMENT_Distributed);
188 m_iAlignment = iAlignment;
189 ResetArabicContext();
190 }
ResetContextCharStyles()191 void CFX_TxtBreak::ResetContextCharStyles() {
192 m_dwContextCharStyles = m_bArabicContext ? m_iCurAlignment : m_iAlignment;
193 if (m_bArabicNumber) {
194 m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicNumber;
195 }
196 if (m_bArabicComma) {
197 m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
198 }
199 if ((m_bArabicContext && m_bCurRTL) || (!m_bArabicContext && m_bRTL)) {
200 m_dwContextCharStyles |= FX_TXTCHARSTYLE_RTLReadingOrder;
201 }
202 m_dwContextCharStyles |= (m_iArabicContext << 8);
203 }
GetContextCharStyles() const204 uint32_t CFX_TxtBreak::GetContextCharStyles() const {
205 return m_dwContextCharStyles;
206 }
SetContextCharStyles(uint32_t dwCharStyles)207 void CFX_TxtBreak::SetContextCharStyles(uint32_t dwCharStyles) {
208 m_iCurAlignment = dwCharStyles & 0x0F;
209 m_bArabicNumber = (dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
210 m_bArabicComma = (dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
211 m_bCurRTL = (dwCharStyles & FX_TXTCHARSTYLE_RTLReadingOrder) != 0;
212 m_iCurArabicContext = m_iArabicContext = ((dwCharStyles & 0x0300) >> 8);
213 ResetContextCharStyles();
214 }
SetCombWidth(FX_FLOAT fCombWidth)215 void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth) {
216 m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
217 }
SetUserData(void * pUserData)218 void CFX_TxtBreak::SetUserData(void* pUserData) {
219 if (m_pUserData == pUserData) {
220 return;
221 }
222 SetBreakStatus();
223 m_pUserData = pUserData;
224 }
SetBreakStatus()225 void CFX_TxtBreak::SetBreakStatus() {
226 if (m_bPagination) {
227 return;
228 }
229 int32_t iCount = m_pCurLine->CountChars();
230 if (iCount < 1) {
231 return;
232 }
233 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
234 if (pTC->m_dwStatus == 0) {
235 pTC->m_dwStatus = FX_TXTBREAK_PieceBreak;
236 }
237 }
SetHorizontalScale(int32_t iScale)238 void CFX_TxtBreak::SetHorizontalScale(int32_t iScale) {
239 if (iScale < 0) {
240 iScale = 0;
241 }
242 if (iScale == m_iHorScale) {
243 return;
244 }
245 SetBreakStatus();
246 m_iHorScale = iScale;
247 }
SetVerticalScale(int32_t iScale)248 void CFX_TxtBreak::SetVerticalScale(int32_t iScale) {
249 if (iScale < 0) {
250 iScale = 0;
251 }
252 if (iScale == m_iHorScale) {
253 return;
254 }
255 SetBreakStatus();
256 m_iVerScale = iScale;
257 }
SetCharSpace(FX_FLOAT fCharSpace)258 void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace) {
259 m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
260 }
261 static const int32_t gs_FX_TxtLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
GetLineRotation(uint32_t dwStyles) const262 int32_t CFX_TxtBreak::GetLineRotation(uint32_t dwStyles) const {
263 return gs_FX_TxtLineRotations[(dwStyles & 0x0E) >> 1];
264 }
GetLastChar(int32_t index,FX_BOOL bOmitChar) const265 CFX_TxtChar* CFX_TxtBreak::GetLastChar(int32_t index, FX_BOOL bOmitChar) const {
266 CFX_TxtCharArray& ca = *m_pCurLine->m_pLineChars;
267 int32_t iCount = ca.GetSize();
268 if (index < 0 || index >= iCount) {
269 return nullptr;
270 }
271 CFX_TxtChar* pTC;
272 int32_t iStart = iCount - 1;
273 while (iStart > -1) {
274 pTC = ca.GetDataPtr(iStart--);
275 if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination) {
276 continue;
277 }
278 if (--index < 0) {
279 return pTC;
280 }
281 }
282 return nullptr;
283 }
GetTxtLine(FX_BOOL bReady) const284 CFX_TxtLine* CFX_TxtBreak::GetTxtLine(FX_BOOL bReady) const {
285 if (!bReady)
286 return m_pCurLine;
287 if (m_iReady == 1)
288 return m_pTxtLine1;
289 if (m_iReady == 2)
290 return m_pTxtLine2;
291 return nullptr;
292 }
GetTxtPieces(FX_BOOL bReady) const293 CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces(FX_BOOL bReady) const {
294 CFX_TxtLine* pTxtLine = GetTxtLine(bReady);
295 if (!pTxtLine) {
296 return nullptr;
297 }
298 return pTxtLine->m_pLinePieces;
299 }
GetUnifiedCharType(FX_CHARTYPE chartype) const300 inline FX_CHARTYPE CFX_TxtBreak::GetUnifiedCharType(
301 FX_CHARTYPE chartype) const {
302 return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
303 }
ResetArabicContext()304 void CFX_TxtBreak::ResetArabicContext() {
305 if (m_bArabicContext) {
306 m_bCurRTL = m_iCurArabicContext > 1;
307 m_iCurAlignment = m_iCurArabicContext > 1 ? FX_TXTLINEALIGNMENT_Right
308 : FX_TXTLINEALIGNMENT_Left;
309 m_iCurAlignment |= (m_iAlignment & FX_TXTLINEALIGNMENT_HigherMask);
310 m_bArabicNumber = m_iArabicContext >= 1 && m_bArabicShapes;
311 } else {
312 if (m_bPagination) {
313 m_bCurRTL = FALSE;
314 m_iCurAlignment = 0;
315 } else {
316 m_bCurRTL = m_bRTL;
317 m_iCurAlignment = m_iAlignment;
318 }
319 if (m_bRTL) {
320 m_bArabicNumber = m_iArabicContext >= 1;
321 } else {
322 m_bArabicNumber = m_iArabicContext > 1;
323 }
324 m_bArabicNumber = m_bArabicNumber && m_bArabicShapes;
325 }
326 m_bArabicComma = m_bArabicNumber;
327 ResetContextCharStyles();
328 }
AppendChar_PageLoad(CFX_TxtChar * pCurChar,uint32_t dwProps)329 void CFX_TxtBreak::AppendChar_PageLoad(CFX_TxtChar* pCurChar,
330 uint32_t dwProps) {
331 if (!m_bPagination) {
332 pCurChar->m_dwStatus = 0;
333 pCurChar->m_pUserData = m_pUserData;
334 }
335 if (m_bArabicContext || m_bArabicShapes) {
336 int32_t iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS;
337 int32_t iArabicContext =
338 (iBidiCls == FX_BIDICLASS_R || iBidiCls == FX_BIDICLASS_AL)
339 ? 2
340 : ((iBidiCls == FX_BIDICLASS_L || iBidiCls == FX_BIDICLASS_S) ? 0
341 : 1);
342 if (iArabicContext != m_iArabicContext && iArabicContext != 1) {
343 m_iArabicContext = iArabicContext;
344 if (m_iCurArabicContext == 1) {
345 m_iCurArabicContext = iArabicContext;
346 }
347 ResetArabicContext();
348 if (!m_bPagination) {
349 CFX_TxtChar* pLastChar = GetLastChar(1, FALSE);
350 if (pLastChar && pLastChar->m_dwStatus < 1) {
351 pLastChar->m_dwStatus = FX_TXTBREAK_PieceBreak;
352 }
353 }
354 }
355 }
356 pCurChar->m_dwCharStyles = m_dwContextCharStyles;
357 }
AppendChar_Combination(CFX_TxtChar * pCurChar,int32_t iRotation)358 uint32_t CFX_TxtBreak::AppendChar_Combination(CFX_TxtChar* pCurChar,
359 int32_t iRotation) {
360 FX_WCHAR wch = pCurChar->m_wCharCode;
361 FX_WCHAR wForm;
362 int32_t iCharWidth = 0;
363 pCurChar->m_iCharWidth = -1;
364 if (m_bCombText) {
365 iCharWidth = m_iCombWidth;
366 } else {
367 if (m_bVertical != FX_IsOdd(iRotation)) {
368 iCharWidth = 1000;
369 } else {
370 wForm = wch;
371 if (!m_bPagination) {
372 CFX_TxtChar* pLastChar = GetLastChar(0, FALSE);
373 if (pLastChar &&
374 (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) {
375 FX_BOOL bShadda = FALSE;
376 if (wch == 0x0651) {
377 FX_WCHAR wLast = pLastChar->m_wCharCode;
378 if (wLast >= 0x064C && wLast <= 0x0650) {
379 wForm = FX_GetArabicFromShaddaTable(wLast);
380 bShadda = TRUE;
381 }
382 } else if (wch >= 0x064C && wch <= 0x0650) {
383 if (pLastChar->m_wCharCode == 0x0651) {
384 wForm = FX_GetArabicFromShaddaTable(wch);
385 bShadda = TRUE;
386 }
387 }
388 if (bShadda) {
389 pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
390 pLastChar->m_iCharWidth = 0;
391 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
392 }
393 }
394 }
395 if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
396 iCharWidth = 0;
397 }
398 }
399 iCharWidth *= m_iFontSize;
400 iCharWidth = iCharWidth * m_iHorScale / 100;
401 }
402 pCurChar->m_iCharWidth = -iCharWidth;
403 return FX_TXTBREAK_None;
404 }
AppendChar_Tab(CFX_TxtChar * pCurChar,int32_t iRotation)405 uint32_t CFX_TxtBreak::AppendChar_Tab(CFX_TxtChar* pCurChar,
406 int32_t iRotation) {
407 m_eCharType = FX_CHARTYPE_Tab;
408 if ((m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ExpandTab) == 0) {
409 return FX_TXTBREAK_None;
410 }
411 int32_t& iLineWidth = m_pCurLine->m_iWidth;
412 int32_t iCharWidth;
413 if (m_bCombText) {
414 iCharWidth = m_iCombWidth;
415 } else {
416 if (m_bEquidistant) {
417 iCharWidth = iLineWidth;
418 iCharWidth = m_iTabWidth * (iCharWidth / m_iTabWidth + 1) - iCharWidth;
419 if (iCharWidth < FX_TXTBREAK_MinimumTabWidth) {
420 iCharWidth += m_iTabWidth;
421 }
422 } else {
423 iCharWidth = m_iTabWidth;
424 }
425 }
426 pCurChar->m_iCharWidth = iCharWidth;
427 iLineWidth += iCharWidth;
428 if (!m_bSingleLine && iLineWidth >= m_iLineWidth + m_iTolerance) {
429 return EndBreak(FX_TXTBREAK_LineBreak);
430 }
431 return FX_TXTBREAK_None;
432 }
AppendChar_Control(CFX_TxtChar * pCurChar,int32_t iRotation)433 uint32_t CFX_TxtBreak::AppendChar_Control(CFX_TxtChar* pCurChar,
434 int32_t iRotation) {
435 m_eCharType = FX_CHARTYPE_Control;
436 uint32_t dwRet = FX_TXTBREAK_None;
437 if (!m_bSingleLine) {
438 FX_WCHAR wch = pCurChar->m_wCharCode;
439 switch (wch) {
440 case L'\v':
441 case 0x2028:
442 dwRet = FX_TXTBREAK_LineBreak;
443 break;
444 case L'\f':
445 dwRet = FX_TXTBREAK_PageBreak;
446 break;
447 case 0x2029:
448 dwRet = FX_TXTBREAK_ParagraphBreak;
449 break;
450 default:
451 if (wch == m_wParagBreakChar) {
452 dwRet = FX_TXTBREAK_ParagraphBreak;
453 }
454 break;
455 }
456 if (dwRet != FX_TXTBREAK_None) {
457 dwRet = EndBreak(dwRet);
458 }
459 }
460 return dwRet;
461 }
AppendChar_Arabic(CFX_TxtChar * pCurChar,int32_t iRotation)462 uint32_t CFX_TxtBreak::AppendChar_Arabic(CFX_TxtChar* pCurChar,
463 int32_t iRotation) {
464 FX_CHARTYPE chartype = pCurChar->GetCharType();
465 int32_t& iLineWidth = m_pCurLine->m_iWidth;
466 FX_WCHAR wForm;
467 int32_t iCharWidth = 0;
468 CFX_Char* pLastChar = nullptr;
469 FX_BOOL bAlef = FALSE;
470 if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef &&
471 m_eCharType <= FX_CHARTYPE_ArabicDistortion) {
472 pLastChar = GetLastChar(1);
473 if (pLastChar) {
474 iCharWidth = pLastChar->m_iCharWidth;
475 if (iCharWidth > 0) {
476 iLineWidth -= iCharWidth;
477 }
478 CFX_Char* pPrevChar = GetLastChar(2);
479 wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar);
480 bAlef = (wForm == 0xFEFF &&
481 pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
482 int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
483 if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
484 iLastRotation++;
485 }
486 if (m_bVertical != FX_IsOdd(iLastRotation)) {
487 iCharWidth = 1000;
488 } else {
489 m_pFont->GetCharWidth(wForm, iCharWidth, FALSE);
490 }
491 if (wForm == 0xFEFF) {
492 iCharWidth = m_iDefChar;
493 }
494 iCharWidth *= m_iFontSize;
495 iCharWidth = iCharWidth * m_iHorScale / 100;
496 pLastChar->m_iCharWidth = iCharWidth;
497 iLineWidth += iCharWidth;
498 iCharWidth = 0;
499 }
500 }
501 m_eCharType = chartype;
502 wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar,
503 nullptr);
504 if (m_bCombText) {
505 iCharWidth = m_iCombWidth;
506 } else {
507 if (m_bVertical != FX_IsOdd(iRotation)) {
508 iCharWidth = 1000;
509 } else {
510 m_pFont->GetCharWidth(wForm, iCharWidth, FALSE);
511 }
512 if (wForm == 0xFEFF) {
513 iCharWidth = m_iDefChar;
514 }
515 iCharWidth *= m_iFontSize;
516 iCharWidth = iCharWidth * m_iHorScale / 100;
517 }
518 pCurChar->m_iCharWidth = iCharWidth;
519 iLineWidth += iCharWidth;
520 m_pCurLine->m_iArabicChars++;
521 if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) {
522 return EndBreak(FX_TXTBREAK_LineBreak);
523 }
524 return FX_TXTBREAK_None;
525 }
AppendChar_Others(CFX_TxtChar * pCurChar,int32_t iRotation)526 uint32_t CFX_TxtBreak::AppendChar_Others(CFX_TxtChar* pCurChar,
527 int32_t iRotation) {
528 uint32_t dwProps = pCurChar->m_dwCharProps;
529 FX_CHARTYPE chartype = pCurChar->GetCharType();
530 int32_t& iLineWidth = m_pCurLine->m_iWidth;
531 int32_t iCharWidth = 0;
532 m_eCharType = chartype;
533 FX_WCHAR wch = pCurChar->m_wCharCode;
534 FX_WCHAR wForm = wch;
535 if (chartype == FX_CHARTYPE_Numeric) {
536 if (m_bArabicNumber) {
537 wForm = wch + 0x0630;
538 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicIndic;
539 }
540 } else if (wch == L',') {
541 if (m_bArabicShapes && m_iCurArabicContext > 0) {
542 wForm = 0x060C;
543 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
544 }
545 } else if (m_bCurRTL || m_bVertical) {
546 wForm = FX_GetMirrorChar(wch, dwProps, m_bCurRTL, m_bVertical);
547 }
548 if (m_bCombText) {
549 iCharWidth = m_iCombWidth;
550 } else {
551 if (m_bVertical != FX_IsOdd(iRotation)) {
552 iCharWidth = 1000;
553 } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
554 iCharWidth = m_iDefChar;
555 }
556 iCharWidth *= m_iFontSize;
557 iCharWidth = iCharWidth * m_iHorScale / 100;
558 }
559 iCharWidth += m_iCharSpace;
560 pCurChar->m_iCharWidth = iCharWidth;
561 iLineWidth += iCharWidth;
562 FX_BOOL bBreak = (chartype != FX_CHARTYPE_Space ||
563 (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0);
564 if (!m_bSingleLine && bBreak && iLineWidth > m_iLineWidth + m_iTolerance) {
565 return EndBreak(FX_TXTBREAK_LineBreak);
566 }
567 return FX_TXTBREAK_None;
568 }
569
AppendChar(FX_WCHAR wch)570 uint32_t CFX_TxtBreak::AppendChar(FX_WCHAR wch) {
571 uint32_t dwProps = kTextLayoutCodeProperties[(uint16_t)wch];
572 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
573 CFX_TxtChar* pCurChar = m_pCurLine->m_pLineChars->AddSpace();
574 pCurChar->m_wCharCode = (uint16_t)wch;
575 pCurChar->m_nRotation = m_iCharRotation;
576 pCurChar->m_dwCharProps = dwProps;
577 pCurChar->m_dwCharStyles = 0;
578 pCurChar->m_iCharWidth = 0;
579 pCurChar->m_iHorizontalScale = m_iHorScale;
580 pCurChar->m_iVertialScale = m_iVerScale;
581 pCurChar->m_dwStatus = 0;
582 pCurChar->m_iBidiClass = 0;
583 pCurChar->m_iBidiLevel = 0;
584 pCurChar->m_iBidiPos = 0;
585 pCurChar->m_iBidiOrder = 0;
586 pCurChar->m_pUserData = nullptr;
587 AppendChar_PageLoad(pCurChar, dwProps);
588 uint32_t dwRet1 = FX_TXTBREAK_None;
589 if (chartype != FX_CHARTYPE_Combination &&
590 GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype)) {
591 if (m_eCharType != FX_CHARTYPE_Unknown &&
592 m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine) {
593 if (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control) {
594 dwRet1 = EndBreak(FX_TXTBREAK_LineBreak);
595 int32_t iCount = m_pCurLine->CountChars();
596 if (iCount > 0) {
597 pCurChar = m_pCurLine->m_pLineChars->GetDataPtr(iCount - 1);
598 }
599 }
600 }
601 }
602 int32_t iRotation = m_iRotation;
603 if (m_bVertical && (dwProps & 0x8000) != 0) {
604 iRotation = (iRotation + 1) % 4;
605 }
606 uint32_t dwRet2 =
607 (this->*g_FX_TxtBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])(
608 pCurChar, iRotation);
609 return std::max(dwRet1, dwRet2);
610 }
EndBreak_UpdateArabicShapes()611 void CFX_TxtBreak::EndBreak_UpdateArabicShapes() {
612 ASSERT(m_bArabicShapes);
613 int32_t iCount = m_pCurLine->CountChars();
614 if (iCount < 2) {
615 return;
616 }
617 int32_t& iLineWidth = m_pCurLine->m_iWidth;
618 CFX_Char *pCur, *pNext;
619 pCur = m_pCurLine->GetCharPtr(0);
620 FX_BOOL bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
621 pCur = m_pCurLine->GetCharPtr(1);
622 FX_WCHAR wch, wForm;
623 FX_BOOL bNextNum;
624 int32_t i = 1, iCharWidth, iRotation;
625 do {
626 i++;
627 if (i < iCount) {
628 pNext = m_pCurLine->GetCharPtr(i);
629 bNextNum = (pNext->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
630 } else {
631 pNext = nullptr;
632 bNextNum = FALSE;
633 }
634 wch = pCur->m_wCharCode;
635 if (wch == L'.') {
636 if (bPrevNum && bNextNum) {
637 iRotation = m_iRotation;
638 if (m_bVertical && (pCur->m_dwCharProps & 0x8000) != 0) {
639 iRotation = ((iRotation + 1) & 0x03);
640 }
641 wForm = wch == L'.' ? 0x066B : 0x066C;
642 iLineWidth -= pCur->m_iCharWidth;
643 if (m_bCombText) {
644 iCharWidth = m_iCombWidth;
645 } else {
646 if (m_bVertical != FX_IsOdd(iRotation)) {
647 iCharWidth = 1000;
648 } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
649 iCharWidth = m_iDefChar;
650 }
651 iCharWidth *= m_iFontSize;
652 iCharWidth = iCharWidth * m_iHorScale / 100;
653 }
654 pCur->m_iCharWidth = iCharWidth;
655 iLineWidth += iCharWidth;
656 }
657 }
658 bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
659 pCur = pNext;
660 } while (i < iCount);
661 }
EndBreak_SplitLine(CFX_TxtLine * pNextLine,FX_BOOL bAllChars,uint32_t dwStatus)662 FX_BOOL CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine* pNextLine,
663 FX_BOOL bAllChars,
664 uint32_t dwStatus) {
665 int32_t iCount = m_pCurLine->CountChars();
666 FX_BOOL bDone = FALSE;
667 CFX_Char* pTC;
668 if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
669 pTC = m_pCurLine->GetCharPtr(iCount - 1);
670 switch (pTC->GetCharType()) {
671 case FX_CHARTYPE_Tab:
672 case FX_CHARTYPE_Control:
673 break;
674 case FX_CHARTYPE_Space:
675 if ((m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0) {
676 SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
677 bDone = TRUE;
678 }
679 break;
680 default:
681 SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
682 bDone = TRUE;
683 break;
684 }
685 }
686 iCount = m_pCurLine->CountChars();
687 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
688 CFX_TxtPiece tp;
689 if (m_bPagination) {
690 tp.m_dwStatus = dwStatus;
691 tp.m_iStartPos = m_pCurLine->m_iStart;
692 tp.m_iWidth = m_pCurLine->m_iWidth;
693 tp.m_iStartChar = 0;
694 tp.m_iChars = iCount;
695 tp.m_pChars = m_pCurLine->m_pLineChars;
696 tp.m_pUserData = m_pUserData;
697 pTC = m_pCurLine->GetCharPtr(0);
698 tp.m_dwCharStyles = pTC->m_dwCharStyles;
699 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
700 tp.m_iVerticalScale = pTC->m_iVertialScale;
701 pCurPieces->Add(tp);
702 m_pCurLine = pNextLine;
703 m_eCharType = FX_CHARTYPE_Unknown;
704 return TRUE;
705 }
706 if (bAllChars && !bDone) {
707 int32_t iEndPos = m_pCurLine->m_iWidth;
708 GetBreakPos(*m_pCurLine->m_pLineChars, iEndPos, bAllChars, TRUE);
709 }
710 return FALSE;
711 }
EndBreak_BidiLine(CFX_TPOArray & tpos,uint32_t dwStatus)712 void CFX_TxtBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, uint32_t dwStatus) {
713 CFX_TxtPiece tp;
714 FX_TPO tpo;
715 CFX_TxtChar* pTC;
716 int32_t i, j;
717 CFX_TxtCharArray& chars = *m_pCurLine->m_pLineChars;
718 int32_t iCount = m_pCurLine->CountChars();
719 FX_BOOL bDone = (m_pCurLine->m_iArabicChars > 0 || m_bCurRTL);
720 if (!m_bPagination && bDone) {
721 int32_t iBidiNum = 0;
722 for (i = 0; i < iCount; i++) {
723 pTC = chars.GetDataPtr(i);
724 pTC->m_iBidiPos = i;
725 if (pTC->GetCharType() != FX_CHARTYPE_Control) {
726 iBidiNum = i;
727 }
728 if (i == 0) {
729 pTC->m_iBidiLevel = 1;
730 }
731 }
732 FX_BidiLine(chars, iBidiNum + 1, m_bCurRTL ? 1 : 0);
733 }
734 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
735 if (!m_bPagination &&
736 (bDone || (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_MutipleFormat) != 0)) {
737 tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
738 tp.m_iStartPos = m_pCurLine->m_iStart;
739 tp.m_pChars = m_pCurLine->m_pLineChars;
740 int32_t iBidiLevel = -1, iCharWidth;
741 i = 0, j = -1;
742 while (i < iCount) {
743 pTC = chars.GetDataPtr(i);
744 if (iBidiLevel < 0) {
745 iBidiLevel = pTC->m_iBidiLevel;
746 tp.m_iWidth = 0;
747 tp.m_iBidiLevel = iBidiLevel;
748 tp.m_iBidiPos = pTC->m_iBidiOrder;
749 tp.m_dwCharStyles = pTC->m_dwCharStyles;
750 tp.m_pUserData = pTC->m_pUserData;
751 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
752 tp.m_iVerticalScale = pTC->m_iVertialScale;
753 tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
754 }
755 if (iBidiLevel != pTC->m_iBidiLevel || pTC->m_dwStatus != 0) {
756 if (iBidiLevel == pTC->m_iBidiLevel) {
757 tp.m_dwStatus = pTC->m_dwStatus;
758 iCharWidth = pTC->m_iCharWidth;
759 if (iCharWidth > 0) {
760 tp.m_iWidth += iCharWidth;
761 }
762 i++;
763 }
764 tp.m_iChars = i - tp.m_iStartChar;
765 pCurPieces->Add(tp);
766 tp.m_iStartPos += tp.m_iWidth;
767 tp.m_iStartChar = i;
768 tpo.index = ++j;
769 tpo.pos = tp.m_iBidiPos;
770 tpos.Add(tpo);
771 iBidiLevel = -1;
772 } else {
773 iCharWidth = pTC->m_iCharWidth;
774 if (iCharWidth > 0) {
775 tp.m_iWidth += iCharWidth;
776 }
777 i++;
778 }
779 }
780 if (i > tp.m_iStartChar) {
781 tp.m_dwStatus = dwStatus;
782 tp.m_iChars = i - tp.m_iStartChar;
783 pCurPieces->Add(tp);
784 tpo.index = ++j;
785 tpo.pos = tp.m_iBidiPos;
786 tpos.Add(tpo);
787 }
788 if (j > -1) {
789 if (j > 0) {
790 FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
791 int32_t iStartPos = 0;
792 for (i = 0; i <= j; i++) {
793 tpo = tpos.GetAt(i);
794 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
795 ttp.m_iStartPos = iStartPos;
796 iStartPos += ttp.m_iWidth;
797 }
798 }
799 CFX_TxtPiece& ttp = pCurPieces->GetAt(j);
800 ttp.m_dwStatus = dwStatus;
801 }
802 } else {
803 tp.m_dwStatus = dwStatus;
804 tp.m_iStartPos = m_pCurLine->m_iStart;
805 tp.m_iWidth = m_pCurLine->m_iWidth;
806 tp.m_iStartChar = 0;
807 tp.m_iChars = iCount;
808 tp.m_pChars = m_pCurLine->m_pLineChars;
809 tp.m_pUserData = m_pUserData;
810 pTC = chars.GetDataPtr(0);
811 tp.m_dwCharStyles = pTC->m_dwCharStyles;
812 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
813 tp.m_iVerticalScale = pTC->m_iVertialScale;
814 pCurPieces->Add(tp);
815 tpo.index = 0;
816 tpo.pos = 0;
817 tpos.Add(tpo);
818 }
819 }
EndBreak_Alignment(CFX_TPOArray & tpos,FX_BOOL bAllChars,uint32_t dwStatus)820 void CFX_TxtBreak::EndBreak_Alignment(CFX_TPOArray& tpos,
821 FX_BOOL bAllChars,
822 uint32_t dwStatus) {
823 int32_t iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
824 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
825 int32_t i, j, iCount = pCurPieces->GetSize();
826 FX_BOOL bFind = FALSE;
827 FX_TPO tpo;
828 CFX_TxtChar* pTC;
829 FX_CHARTYPE chartype;
830 for (i = iCount - 1; i > -1; i--) {
831 tpo = tpos.GetAt(i);
832 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
833 if (!bFind) {
834 iNetWidth = ttp.GetEndPos();
835 }
836 FX_BOOL bArabic = FX_IsOdd(ttp.m_iBidiLevel);
837 j = bArabic ? 0 : ttp.m_iChars - 1;
838 while (j > -1 && j < ttp.m_iChars) {
839 pTC = ttp.GetCharPtr(j);
840 if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) {
841 iGapChars++;
842 }
843 if (!bFind || !bAllChars) {
844 chartype = pTC->GetCharType();
845 if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) {
846 if (!bFind) {
847 iCharWidth = pTC->m_iCharWidth;
848 if (bAllChars && iCharWidth > 0) {
849 iNetWidth -= iCharWidth;
850 }
851 }
852 } else {
853 bFind = TRUE;
854 if (!bAllChars) {
855 break;
856 }
857 }
858 }
859 j += bArabic ? 1 : -1;
860 }
861 if (!bAllChars && bFind) {
862 break;
863 }
864 }
865 int32_t iOffset = m_iLineWidth - iNetWidth;
866 int32_t iLowerAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_LowerMask);
867 int32_t iHigherAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_HigherMask);
868 if (iGapChars > 0 && (iHigherAlignment == FX_TXTLINEALIGNMENT_Distributed ||
869 (iHigherAlignment == FX_TXTLINEALIGNMENT_Justified &&
870 dwStatus != FX_TXTBREAK_ParagraphBreak))) {
871 int32_t iStart = -1;
872 for (i = 0; i < iCount; i++) {
873 tpo = tpos.GetAt(i);
874 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
875 if (iStart < -1) {
876 iStart = ttp.m_iStartPos;
877 } else {
878 ttp.m_iStartPos = iStart;
879 }
880 int32_t k;
881 for (j = 0; j < ttp.m_iChars; j++) {
882 pTC = ttp.GetCharPtr(j);
883 if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) {
884 continue;
885 }
886 k = iOffset / iGapChars;
887 pTC->m_iCharWidth += k;
888 ttp.m_iWidth += k;
889 iOffset -= k;
890 iGapChars--;
891 if (iGapChars < 1) {
892 break;
893 }
894 }
895 iStart += ttp.m_iWidth;
896 }
897 } else if (iLowerAlignment > FX_TXTLINEALIGNMENT_Left) {
898 if (iLowerAlignment == FX_TXTLINEALIGNMENT_Center) {
899 iOffset /= 2;
900 }
901 if (iOffset > 0) {
902 for (i = 0; i < iCount; i++) {
903 CFX_TxtPiece& ttp = pCurPieces->GetAt(i);
904 ttp.m_iStartPos += iOffset;
905 }
906 }
907 }
908 }
EndBreak(uint32_t dwStatus)909 uint32_t CFX_TxtBreak::EndBreak(uint32_t dwStatus) {
910 ASSERT(dwStatus >= FX_TXTBREAK_PieceBreak &&
911 dwStatus <= FX_TXTBREAK_PageBreak);
912 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
913 int32_t iCount = pCurPieces->GetSize();
914 if (iCount > 0) {
915 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
916 if (dwStatus > FX_TXTBREAK_PieceBreak) {
917 pLastPiece->m_dwStatus = dwStatus;
918 } else {
919 dwStatus = pLastPiece->m_dwStatus;
920 }
921 return dwStatus;
922 } else {
923 CFX_TxtLine* pLastLine = GetTxtLine(TRUE);
924 if (pLastLine) {
925 pCurPieces = pLastLine->m_pLinePieces;
926 iCount = pCurPieces->GetSize();
927 if (iCount-- > 0) {
928 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
929 if (dwStatus > FX_TXTBREAK_PieceBreak) {
930 pLastPiece->m_dwStatus = dwStatus;
931 } else {
932 dwStatus = pLastPiece->m_dwStatus;
933 }
934 return dwStatus;
935 }
936 return FX_TXTBREAK_None;
937 }
938 iCount = m_pCurLine->CountChars();
939 if (iCount < 1) {
940 return FX_TXTBREAK_None;
941 }
942 if (!m_bPagination) {
943 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
944 pTC->m_dwStatus = dwStatus;
945 }
946 if (dwStatus <= FX_TXTBREAK_PieceBreak) {
947 return dwStatus;
948 }
949 }
950 m_iReady = (m_pCurLine == m_pTxtLine1) ? 1 : 2;
951 CFX_TxtLine* pNextLine =
952 (m_pCurLine == m_pTxtLine1) ? m_pTxtLine2 : m_pTxtLine1;
953 FX_BOOL bAllChars = (m_iCurAlignment > FX_TXTLINEALIGNMENT_Right);
954 CFX_TPOArray tpos;
955 CFX_Char* pTC;
956 if (m_bArabicShapes) {
957 EndBreak_UpdateArabicShapes();
958 }
959 if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
960 goto EndBreak_Ret;
961 }
962 EndBreak_BidiLine(tpos, dwStatus);
963 if (!m_bPagination && m_iCurAlignment > FX_TXTLINEALIGNMENT_Left) {
964 EndBreak_Alignment(tpos, bAllChars, dwStatus);
965 }
966 EndBreak_Ret:
967 m_pCurLine = pNextLine;
968 pTC = GetLastChar(0, FALSE);
969 m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown;
970 if (dwStatus == FX_TXTBREAK_ParagraphBreak) {
971 m_iArabicContext = m_iCurArabicContext = 1;
972 ResetArabicContext();
973 }
974 return dwStatus;
975 }
GetBreakPos(CFX_TxtCharArray & ca,int32_t & iEndPos,FX_BOOL bAllChars,FX_BOOL bOnlyBrk)976 int32_t CFX_TxtBreak::GetBreakPos(CFX_TxtCharArray& ca,
977 int32_t& iEndPos,
978 FX_BOOL bAllChars,
979 FX_BOOL bOnlyBrk) {
980 int32_t iLength = ca.GetSize() - 1;
981 if (iLength < 1) {
982 return iLength;
983 }
984 int32_t iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1,
985 iLast = -1, iLastPos = -1;
986 if (m_bSingleLine || iEndPos <= m_iLineWidth) {
987 if (!bAllChars) {
988 return iLength;
989 }
990 iBreak = iLength;
991 iBreakPos = iEndPos;
992 }
993 FX_BOOL bSpaceBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0;
994 FX_BOOL bNumberBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_NumberBreak) != 0;
995 FX_LINEBREAKTYPE eType;
996 uint32_t nCodeProp, nCur, nNext;
997 CFX_Char* pCur = ca.GetDataPtr(iLength--);
998 if (bAllChars) {
999 pCur->m_nBreakType = FX_LBT_UNKNOWN;
1000 }
1001 nCodeProp = pCur->m_dwCharProps;
1002 nNext = nCodeProp & 0x003F;
1003 int32_t iCharWidth = pCur->m_iCharWidth;
1004 if (iCharWidth > 0) {
1005 iEndPos -= iCharWidth;
1006 }
1007 while (iLength >= 0) {
1008 pCur = ca.GetDataPtr(iLength);
1009 nCodeProp = pCur->m_dwCharProps;
1010 nCur = nCodeProp & 0x003F;
1011 if (nCur == FX_CBP_SP) {
1012 if (nNext == FX_CBP_SP) {
1013 eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
1014 } else {
1015 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
1016 }
1017 } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
1018 eType = FX_LBT_DIRECT_BRK;
1019 } else {
1020 if (nNext == FX_CBP_SP) {
1021 eType = FX_LBT_PROHIBITED_BRK;
1022 } else {
1023 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
1024 }
1025 }
1026 if (bAllChars) {
1027 pCur->m_nBreakType = (uint8_t)eType;
1028 }
1029 if (!bOnlyBrk) {
1030 if (m_bSingleLine || iEndPos <= m_iLineWidth ||
1031 (nCur == FX_CBP_SP && !bSpaceBreak)) {
1032 if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
1033 iBreak = iLength;
1034 iBreakPos = iEndPos;
1035 if (!bAllChars) {
1036 return iLength;
1037 }
1038 } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
1039 iIndirect = iLength;
1040 iIndirectPos = iEndPos;
1041 }
1042 if (iLast < 0) {
1043 iLast = iLength;
1044 iLastPos = iEndPos;
1045 }
1046 }
1047 iCharWidth = pCur->m_iCharWidth;
1048 if (iCharWidth > 0) {
1049 iEndPos -= iCharWidth;
1050 }
1051 }
1052 nNext = nCodeProp & 0x003F;
1053 iLength--;
1054 }
1055 if (bOnlyBrk) {
1056 return 0;
1057 }
1058 if (iBreak > -1) {
1059 iEndPos = iBreakPos;
1060 return iBreak;
1061 }
1062 if (iIndirect > -1) {
1063 iEndPos = iIndirectPos;
1064 return iIndirect;
1065 }
1066 if (iLast > -1) {
1067 iEndPos = iLastPos;
1068 return iLast;
1069 }
1070 return 0;
1071 }
SplitTextLine(CFX_TxtLine * pCurLine,CFX_TxtLine * pNextLine,FX_BOOL bAllChars)1072 void CFX_TxtBreak::SplitTextLine(CFX_TxtLine* pCurLine,
1073 CFX_TxtLine* pNextLine,
1074 FX_BOOL bAllChars) {
1075 ASSERT(pCurLine && pNextLine);
1076 int32_t iCount = pCurLine->CountChars();
1077 if (iCount < 2) {
1078 return;
1079 }
1080 int32_t iEndPos = pCurLine->m_iWidth;
1081 CFX_TxtCharArray& curChars = *pCurLine->m_pLineChars;
1082 int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, FALSE);
1083 if (iCharPos < 0) {
1084 iCharPos = 0;
1085 }
1086 iCharPos++;
1087 if (iCharPos >= iCount) {
1088 pNextLine->RemoveAll(TRUE);
1089 CFX_Char* pTC = curChars.GetDataPtr(iCharPos - 1);
1090 pTC->m_nBreakType = FX_LBT_UNKNOWN;
1091 return;
1092 }
1093 CFX_TxtCharArray& nextChars = *pNextLine->m_pLineChars;
1094 int cur_size = curChars.GetSize();
1095 nextChars.SetSize(cur_size - iCharPos);
1096 FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos),
1097 (cur_size - iCharPos) * sizeof(CFX_TxtChar));
1098 iCount -= iCharPos;
1099 cur_size = curChars.GetSize();
1100 curChars.RemoveAt(cur_size - iCount, iCount);
1101 pCurLine->m_iWidth = iEndPos;
1102 CFX_TxtChar* pTC = curChars.GetDataPtr(iCharPos - 1);
1103 pTC->m_nBreakType = FX_LBT_UNKNOWN;
1104 iCount = nextChars.GetSize();
1105 int32_t iCharWidth, iWidth = 0;
1106 for (int32_t i = 0; i < iCount; i++) {
1107 pTC = nextChars.GetDataPtr(i);
1108 if (pTC->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
1109 pCurLine->m_iArabicChars--;
1110 pNextLine->m_iArabicChars++;
1111 }
1112 iCharWidth = pTC->m_iCharWidth;
1113 if (iCharWidth > 0) {
1114 iWidth += iCharWidth;
1115 }
1116 if (m_bPagination) {
1117 continue;
1118 }
1119 pTC->m_dwStatus = 0;
1120 }
1121 pNextLine->m_iWidth = iWidth;
1122 }
CountBreakChars() const1123 int32_t CFX_TxtBreak::CountBreakChars() const {
1124 CFX_TxtLine* pTxtLine = GetTxtLine(TRUE);
1125 return pTxtLine ? pTxtLine->CountChars() : 0;
1126 }
CountBreakPieces() const1127 int32_t CFX_TxtBreak::CountBreakPieces() const {
1128 CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(TRUE);
1129 return pTxtPieces ? pTxtPieces->GetSize() : 0;
1130 }
GetBreakPiece(int32_t index) const1131 const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const {
1132 CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(TRUE);
1133 if (!pTxtPieces) {
1134 return nullptr;
1135 }
1136 if (index < 0 || index >= pTxtPieces->GetSize()) {
1137 return nullptr;
1138 }
1139 return pTxtPieces->GetPtrAt(index);
1140 }
ClearBreakPieces()1141 void CFX_TxtBreak::ClearBreakPieces() {
1142 CFX_TxtLine* pTxtLine = GetTxtLine(TRUE);
1143 if (pTxtLine) {
1144 pTxtLine->RemoveAll(TRUE);
1145 }
1146 m_iReady = 0;
1147 }
Reset()1148 void CFX_TxtBreak::Reset() {
1149 m_eCharType = FX_CHARTYPE_Unknown;
1150 m_iArabicContext = m_iCurArabicContext = 1;
1151 ResetArabicContext();
1152 m_pTxtLine1->RemoveAll(TRUE);
1153 m_pTxtLine2->RemoveAll(TRUE);
1154 }
1155
1156 struct FX_FORMCHAR {
1157 uint16_t wch;
1158 uint16_t wForm;
1159 int32_t iWidth;
1160 };
1161
GetDisplayPos(const FX_TXTRUN * pTxtRun,FXTEXT_CHARPOS * pCharPos,FX_BOOL bCharCode,CFX_WideString * pWSForms,FX_AdjustCharDisplayPos pAdjustPos) const1162 int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
1163 FXTEXT_CHARPOS* pCharPos,
1164 FX_BOOL bCharCode,
1165 CFX_WideString* pWSForms,
1166 FX_AdjustCharDisplayPos pAdjustPos) const {
1167 if (!pTxtRun || pTxtRun->iLength < 1) {
1168 return 0;
1169 }
1170 IFX_TxtAccess* pAccess = pTxtRun->pAccess;
1171 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
1172 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
1173 int32_t* pWidths = pTxtRun->pWidths;
1174 int32_t iLength = pTxtRun->iLength - 1;
1175 CFGAS_GEFont* pFont = pTxtRun->pFont;
1176 uint32_t dwStyles = pTxtRun->dwStyles;
1177 CFX_RectF rtText(*pTxtRun->pRect);
1178 FX_BOOL bRTLPiece =
1179 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
1180 FX_BOOL bArabicNumber =
1181 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
1182 FX_BOOL bArabicComma =
1183 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
1184 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1185 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1186 int32_t iAscent = pFont->GetAscent();
1187 int32_t iDescent = pFont->GetDescent();
1188 int32_t iMaxHeight = iAscent - iDescent;
1189 FX_FLOAT fFontHeight = fFontSize;
1190 FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
1191 FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
1192 FX_BOOL bVerticalDoc = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
1193 FX_BOOL bVerticalChar = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
1194 int32_t iRotation = GetLineRotation(dwStyles) + pTxtRun->iCharRotation;
1195 FX_FLOAT fX, fY, fCharWidth, fCharHeight;
1196 int32_t iHorScale = pTxtRun->iHorizontalScale;
1197 int32_t iVerScale = pTxtRun->iVerticalScale;
1198 FX_BOOL bSkipSpace = pTxtRun->bSkipSpace;
1199 FX_FORMCHAR formChars[3];
1200 FX_FLOAT fYBase;
1201 fX = rtText.left;
1202 if (bVerticalDoc) {
1203 fX += (rtText.width - fFontSize) / 2.0f;
1204 fYBase = bRTLPiece ? rtText.bottom() : rtText.top;
1205 fY = fYBase;
1206 } else {
1207 if (bRTLPiece) {
1208 fX = rtText.right();
1209 }
1210 fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
1211 fY = fYBase + fAscent;
1212 }
1213 int32_t iCount = 0;
1214 int32_t iNext = 0;
1215 FX_WCHAR wPrev = 0xFEFF;
1216 FX_WCHAR wNext = 0xFEFF;
1217 FX_WCHAR wForm = 0xFEFF;
1218 FX_WCHAR wLast = 0xFEFF;
1219 FX_BOOL bShadda = FALSE;
1220 FX_BOOL bLam = FALSE;
1221 for (int32_t i = 0; i <= iLength; i++) {
1222 int32_t iWidth;
1223 FX_WCHAR wch;
1224 if (pAccess) {
1225 wch = pAccess->GetChar(pIdentity, i);
1226 iWidth = pAccess->GetWidth(pIdentity, i);
1227 } else {
1228 wch = *pStr++;
1229 iWidth = *pWidths++;
1230 }
1231 uint32_t dwProps = FX_GetUnicodeProperties(wch);
1232 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
1233 if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
1234 wPrev = 0xFEFF;
1235 wLast = wch;
1236 continue;
1237 }
1238 if (chartype >= FX_CHARTYPE_ArabicAlef) {
1239 if (i < iLength) {
1240 if (pAccess) {
1241 iNext = i + 1;
1242 while (iNext <= iLength) {
1243 wNext = pAccess->GetChar(pIdentity, iNext);
1244 dwProps = FX_GetUnicodeProperties(wNext);
1245 if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination) {
1246 break;
1247 }
1248 iNext++;
1249 }
1250 if (iNext > iLength) {
1251 wNext = 0xFEFF;
1252 }
1253 } else {
1254 int32_t j = -1;
1255 do {
1256 j++;
1257 if (i + j >= iLength) {
1258 break;
1259 }
1260 wNext = pStr[j];
1261 dwProps = FX_GetUnicodeProperties(wNext);
1262 } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
1263 if (i + j >= iLength) {
1264 wNext = 0xFEFF;
1265 }
1266 }
1267 } else {
1268 wNext = 0xFEFF;
1269 }
1270 wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext);
1271 bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
1272 } else if (chartype == FX_CHARTYPE_Combination) {
1273 wForm = wch;
1274 if (wch >= 0x064C && wch <= 0x0651) {
1275 if (bShadda) {
1276 wForm = 0xFEFF;
1277 bShadda = FALSE;
1278 } else {
1279 wNext = 0xFEFF;
1280 if (pAccess) {
1281 iNext = i + 1;
1282 if (iNext <= iLength) {
1283 wNext = pAccess->GetChar(pIdentity, iNext);
1284 }
1285 } else {
1286 if (i < iLength) {
1287 wNext = *pStr;
1288 }
1289 }
1290 if (wch == 0x0651) {
1291 if (wNext >= 0x064C && wNext <= 0x0650) {
1292 wForm = FX_GetArabicFromShaddaTable(wNext);
1293 bShadda = TRUE;
1294 }
1295 } else {
1296 if (wNext == 0x0651) {
1297 wForm = FX_GetArabicFromShaddaTable(wch);
1298 bShadda = TRUE;
1299 }
1300 }
1301 }
1302 } else {
1303 bShadda = FALSE;
1304 }
1305 } else if (chartype == FX_CHARTYPE_Numeric) {
1306 wForm = wch;
1307 if (bArabicNumber) {
1308 wForm += 0x0630;
1309 }
1310 } else if (wch == L'.') {
1311 wForm = wch;
1312 if (bArabicNumber) {
1313 wNext = 0xFEFF;
1314 if (pAccess) {
1315 iNext = i + 1;
1316 if (iNext <= iLength) {
1317 wNext = pAccess->GetChar(pIdentity, iNext);
1318 }
1319 } else {
1320 if (i < iLength) {
1321 wNext = *pStr;
1322 }
1323 }
1324 if (wNext >= L'0' && wNext <= L'9') {
1325 wForm = 0x066B;
1326 }
1327 }
1328 } else if (wch == L',') {
1329 wForm = wch;
1330 if (bArabicComma) {
1331 wForm = 0x060C;
1332 }
1333 } else if (bRTLPiece || bVerticalChar) {
1334 wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
1335 } else {
1336 wForm = wch;
1337 }
1338 if (chartype != FX_CHARTYPE_Combination) {
1339 bShadda = FALSE;
1340 }
1341 if (chartype < FX_CHARTYPE_ArabicAlef) {
1342 bLam = FALSE;
1343 }
1344 dwProps = FX_GetUnicodeProperties(wForm);
1345 int32_t iCharRotation = iRotation;
1346 if (bVerticalChar && (dwProps & 0x8000) != 0) {
1347 iCharRotation++;
1348 }
1349 iCharRotation %= 4;
1350 FX_BOOL bEmptyChar =
1351 (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control);
1352 if (wForm == 0xFEFF) {
1353 bEmptyChar = TRUE;
1354 }
1355 int32_t iForms = bLam ? 3 : 1;
1356 iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
1357 if (!pCharPos) {
1358 if (iWidth > 0) {
1359 wPrev = wch;
1360 }
1361 wLast = wch;
1362 continue;
1363 }
1364 int32_t iCharWidth = iWidth;
1365 if (iCharWidth < 0) {
1366 iCharWidth = -iCharWidth;
1367 }
1368 iCharWidth /= iFontSize;
1369 formChars[0].wch = wch;
1370 formChars[0].wForm = wForm;
1371 formChars[0].iWidth = iCharWidth;
1372 if (bLam) {
1373 formChars[1].wForm = 0x0651;
1374 iCharWidth = 0;
1375 pFont->GetCharWidth(0x0651, iCharWidth, FALSE);
1376 formChars[1].iWidth = iCharWidth;
1377 formChars[2].wForm = 0x0670;
1378 iCharWidth = 0;
1379 pFont->GetCharWidth(0x0670, iCharWidth, FALSE);
1380 formChars[2].iWidth = iCharWidth;
1381 }
1382 for (int32_t j = 0; j < iForms; j++) {
1383 wForm = (FX_WCHAR)formChars[j].wForm;
1384 iCharWidth = formChars[j].iWidth;
1385 if (j > 0) {
1386 chartype = FX_CHARTYPE_Combination;
1387 wch = wForm;
1388 wLast = (FX_WCHAR)formChars[j - 1].wForm;
1389 }
1390 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1391 pCharPos->m_GlyphIndex =
1392 bCharCode ? wch : pFont->GetGlyphIndex(wForm, FALSE);
1393 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
1394 pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
1395 #endif
1396 pCharPos->m_FontCharWidth = iCharWidth;
1397 if (pWSForms) {
1398 *pWSForms += wForm;
1399 }
1400 }
1401 int32_t iCharHeight;
1402 if (bVerticalDoc) {
1403 iCharHeight = iCharWidth;
1404 iCharWidth = 1000;
1405 } else {
1406 iCharHeight = 1000;
1407 }
1408 fCharWidth = fFontSize * iCharWidth / 1000.0f;
1409 fCharHeight = fFontSize * iCharHeight / 1000.0f;
1410 if (bRTLPiece && chartype != FX_CHARTYPE_Combination) {
1411 if (bVerticalDoc) {
1412 fY -= fCharHeight;
1413 } else {
1414 fX -= fCharWidth;
1415 }
1416 }
1417 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1418 pCharPos->m_OriginX = fX;
1419 pCharPos->m_OriginY = fY;
1420 if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) {
1421 int32_t iFormWidth = iCharWidth;
1422 pFont->GetCharWidth(wForm, iFormWidth, FALSE);
1423 FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
1424 if (bVerticalDoc) {
1425 pCharPos->m_OriginY += fOffset;
1426 } else {
1427 pCharPos->m_OriginX += fOffset;
1428 }
1429 }
1430 if (chartype == FX_CHARTYPE_Combination) {
1431 CFX_Rect rtBBox;
1432 rtBBox.Reset();
1433 if (pFont->GetCharBBox(wForm, rtBBox, FALSE)) {
1434 pCharPos->m_OriginY =
1435 fYBase + fFontSize -
1436 fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight;
1437 }
1438 if (wForm == wch && wLast != 0xFEFF) {
1439 uint32_t dwLastProps = FX_GetUnicodeProperties(wLast);
1440 if ((dwLastProps & FX_CHARTYPEBITSMASK) ==
1441 FX_CHARTYPE_Combination) {
1442 CFX_Rect rtBox;
1443 rtBox.Reset();
1444 if (pFont->GetCharBBox(wLast, rtBox, FALSE)) {
1445 pCharPos->m_OriginY -= fFontSize * rtBox.height / iMaxHeight;
1446 }
1447 }
1448 }
1449 }
1450 CFX_PointF ptOffset;
1451 FX_BOOL bAdjusted = FALSE;
1452 if (pAdjustPos) {
1453 bAdjusted = pAdjustPos(wForm, bCharCode, pFont, fFontSize,
1454 bVerticalChar, ptOffset);
1455 }
1456 if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) {
1457 CFX_Rect rtBBox;
1458 rtBBox.Reset();
1459 if (pFont->GetCharBBox(wForm, rtBBox, FALSE)) {
1460 ptOffset.x = fFontSize * (850 - rtBBox.right()) / iMaxHeight;
1461 ptOffset.y = fFontSize * (iAscent - rtBBox.top - 150) / iMaxHeight;
1462 }
1463 }
1464 pCharPos->m_OriginX += ptOffset.x;
1465 pCharPos->m_OriginY -= ptOffset.y;
1466 }
1467 if (!bRTLPiece && chartype != FX_CHARTYPE_Combination) {
1468 if (bVerticalDoc) {
1469 fY += fCharHeight;
1470 } else {
1471 fX += fCharWidth;
1472 }
1473 }
1474 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1475 pCharPos->m_bGlyphAdjust = TRUE;
1476 if (bVerticalDoc) {
1477 if (iCharRotation == 0) {
1478 pCharPos->m_AdjustMatrix[0] = -1;
1479 pCharPos->m_AdjustMatrix[1] = 0;
1480 pCharPos->m_AdjustMatrix[2] = 0;
1481 pCharPos->m_AdjustMatrix[3] = 1;
1482 pCharPos->m_OriginY += fAscent;
1483 } else if (iCharRotation == 1) {
1484 pCharPos->m_AdjustMatrix[0] = 0;
1485 pCharPos->m_AdjustMatrix[1] = -1;
1486 pCharPos->m_AdjustMatrix[2] = -1;
1487 pCharPos->m_AdjustMatrix[3] = 0;
1488 pCharPos->m_OriginX -= fDescent;
1489 } else if (iCharRotation == 2) {
1490 pCharPos->m_AdjustMatrix[0] = 1;
1491 pCharPos->m_AdjustMatrix[1] = 0;
1492 pCharPos->m_AdjustMatrix[2] = 0;
1493 pCharPos->m_AdjustMatrix[3] = -1;
1494 pCharPos->m_OriginX += fCharWidth;
1495 pCharPos->m_OriginY += fAscent;
1496 } else {
1497 pCharPos->m_AdjustMatrix[0] = 0;
1498 pCharPos->m_AdjustMatrix[1] = 1;
1499 pCharPos->m_AdjustMatrix[2] = 1;
1500 pCharPos->m_AdjustMatrix[3] = 0;
1501 pCharPos->m_OriginX += fAscent;
1502 }
1503 } else {
1504 if (iCharRotation == 0) {
1505 pCharPos->m_AdjustMatrix[0] = -1;
1506 pCharPos->m_AdjustMatrix[1] = 0;
1507 pCharPos->m_AdjustMatrix[2] = 0;
1508 pCharPos->m_AdjustMatrix[3] = 1;
1509 } else if (iCharRotation == 1) {
1510 pCharPos->m_AdjustMatrix[0] = 0;
1511 pCharPos->m_AdjustMatrix[1] = -1;
1512 pCharPos->m_AdjustMatrix[2] = -1;
1513 pCharPos->m_AdjustMatrix[3] = 0;
1514 pCharPos->m_OriginX -= fDescent;
1515 pCharPos->m_OriginY -= fAscent + fDescent;
1516 } else if (iCharRotation == 2) {
1517 pCharPos->m_AdjustMatrix[0] = 1;
1518 pCharPos->m_AdjustMatrix[1] = 0;
1519 pCharPos->m_AdjustMatrix[2] = 0;
1520 pCharPos->m_AdjustMatrix[3] = -1;
1521 pCharPos->m_OriginX += fCharWidth;
1522 pCharPos->m_OriginY -= fAscent;
1523 } else {
1524 pCharPos->m_AdjustMatrix[0] = 0;
1525 pCharPos->m_AdjustMatrix[1] = 1;
1526 pCharPos->m_AdjustMatrix[2] = 1;
1527 pCharPos->m_AdjustMatrix[3] = 0;
1528 pCharPos->m_OriginX += fAscent;
1529 }
1530 }
1531 if (iHorScale != 100 || iVerScale != 100) {
1532 pCharPos->m_AdjustMatrix[0] =
1533 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
1534 pCharPos->m_AdjustMatrix[1] =
1535 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
1536 pCharPos->m_AdjustMatrix[2] =
1537 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
1538 pCharPos->m_AdjustMatrix[3] =
1539 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
1540 }
1541 pCharPos++;
1542 }
1543 }
1544 if (iWidth > 0) {
1545 wPrev = (FX_WCHAR)formChars[0].wch;
1546 }
1547 wLast = wch;
1548 }
1549 return iCount;
1550 }
GetCharRects(const FX_TXTRUN * pTxtRun,CFX_RectFArray & rtArray,FX_BOOL bCharBBox) const1551 int32_t CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
1552 CFX_RectFArray& rtArray,
1553 FX_BOOL bCharBBox) const {
1554 if (!pTxtRun || pTxtRun->iLength < 1) {
1555 return 0;
1556 }
1557 IFX_TxtAccess* pAccess = pTxtRun->pAccess;
1558 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
1559 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
1560 int32_t* pWidths = pTxtRun->pWidths;
1561 int32_t iLength = pTxtRun->iLength;
1562 CFX_RectF rect(*pTxtRun->pRect);
1563 FX_BOOL bRTLPiece =
1564 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
1565 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1566 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1567 FX_FLOAT fScale = fFontSize / 1000.0f;
1568 CFGAS_GEFont* pFont = pTxtRun->pFont;
1569 if (!pFont) {
1570 bCharBBox = FALSE;
1571 }
1572 CFX_Rect bbox;
1573 bbox.Set(0, 0, 0, 0);
1574 if (bCharBBox) {
1575 bCharBBox = pFont->GetBBox(bbox);
1576 }
1577 FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
1578 FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
1579 rtArray.RemoveAll();
1580 rtArray.SetSize(iLength);
1581 FX_BOOL bVertical =
1582 (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
1583 FX_BOOL bSingleLine = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
1584 FX_BOOL bCombText = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
1585 FX_WCHAR wch, wLineBreakChar = pTxtRun->wLineBreakChar;
1586 int32_t iCharSize;
1587 FX_FLOAT fCharSize, fStart;
1588 if (bVertical) {
1589 fStart = bRTLPiece ? rect.bottom() : rect.top;
1590 } else {
1591 fStart = bRTLPiece ? rect.right() : rect.left;
1592 }
1593 for (int32_t i = 0; i < iLength; i++) {
1594 if (pAccess) {
1595 wch = pAccess->GetChar(pIdentity, i);
1596 iCharSize = pAccess->GetWidth(pIdentity, i);
1597 } else {
1598 wch = *pStr++;
1599 iCharSize = *pWidths++;
1600 }
1601 fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
1602 FX_BOOL bRet = (!bSingleLine && FX_IsCtrlCode(wch));
1603 if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
1604 (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
1605 bRet = FALSE;
1606 }
1607 if (bRet) {
1608 iCharSize = iFontSize * 500;
1609 fCharSize = fFontSize / 2.0f;
1610 }
1611 if (bVertical) {
1612 rect.top = fStart;
1613 if (bRTLPiece) {
1614 rect.top -= fCharSize;
1615 fStart -= fCharSize;
1616 } else {
1617 fStart += fCharSize;
1618 }
1619 rect.height = fCharSize;
1620 } else {
1621 rect.left = fStart;
1622 if (bRTLPiece) {
1623 rect.left -= fCharSize;
1624 fStart -= fCharSize;
1625 } else {
1626 fStart += fCharSize;
1627 }
1628 rect.width = fCharSize;
1629 }
1630 if (bCharBBox && !bRet) {
1631 int32_t iCharWidth = 1000;
1632 pFont->GetCharWidth(wch, iCharWidth);
1633 FX_FLOAT fRTLeft = 0, fCharWidth = 0;
1634 if (iCharWidth > 0) {
1635 fCharWidth = iCharWidth * fScale;
1636 fRTLeft = fLeft;
1637 if (bCombText) {
1638 fRTLeft = (rect.width - fCharWidth) / 2.0f;
1639 }
1640 }
1641 CFX_RectF rtBBoxF;
1642 if (bVertical) {
1643 rtBBoxF.top = rect.left + fRTLeft;
1644 rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
1645 rtBBoxF.height = fCharWidth;
1646 rtBBoxF.width = fHeight;
1647 rtBBoxF.left = std::max(rtBBoxF.left, 0.0f);
1648 } else {
1649 rtBBoxF.left = rect.left + fRTLeft;
1650 rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
1651 rtBBoxF.width = fCharWidth;
1652 rtBBoxF.height = fHeight;
1653 rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
1654 }
1655 rtArray.SetAt(i, rtBBoxF);
1656 continue;
1657 }
1658 rtArray.SetAt(i, rect);
1659 }
1660 return iLength;
1661 }
1662
FX_TXTRUN()1663 FX_TXTRUN::FX_TXTRUN()
1664 : pAccess(nullptr),
1665 pIdentity(nullptr),
1666 pWidths(nullptr),
1667 iLength(0),
1668 pFont(nullptr),
1669 fFontSize(12),
1670 dwStyles(0),
1671 iHorizontalScale(100),
1672 iVerticalScale(100),
1673 iCharRotation(0),
1674 dwCharStyles(0),
1675 pRect(nullptr),
1676 wLineBreakChar(L'\n'),
1677 bSkipSpace(TRUE) {}
1678
~FX_TXTRUN()1679 FX_TXTRUN::~FX_TXTRUN() {}
1680
1681 FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default;
1682
CFX_TxtPiece()1683 CFX_TxtPiece::CFX_TxtPiece()
1684 : m_dwStatus(FX_TXTBREAK_PieceBreak),
1685 m_iStartPos(0),
1686 m_iWidth(-1),
1687 m_iStartChar(0),
1688 m_iChars(0),
1689 m_iBidiLevel(0),
1690 m_iBidiPos(0),
1691 m_iHorizontalScale(100),
1692 m_iVerticalScale(100),
1693 m_dwCharStyles(0),
1694 m_pChars(nullptr),
1695 m_pUserData(nullptr) {}
1696
CFX_TxtLine(int32_t iBlockSize)1697 CFX_TxtLine::CFX_TxtLine(int32_t iBlockSize)
1698 : m_iStart(0), m_iWidth(0), m_iArabicChars(0) {
1699 m_pLineChars = new CFX_TxtCharArray;
1700 m_pLinePieces = new CFX_TxtPieceArray(16);
1701 }
1702
~CFX_TxtLine()1703 CFX_TxtLine::~CFX_TxtLine() {
1704 RemoveAll();
1705 delete m_pLineChars;
1706 delete m_pLinePieces;
1707 }
1708