| 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 |