OLD | NEW |
| (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 } | |
OLD | NEW |