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