Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1669)

Side by Side Diff: xfa/src/fgas/layout/fgas_textbreak.cpp

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

Powered by Google App Engine
This is Rietveld 408576698