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