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