fgas_rtfbreak.cpp revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
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/fgas/layout/fgas_rtfbreak.h" 8 9#include <algorithm> 10 11#include "core/fxcrt/fx_arabic.h" 12#include "core/fxcrt/fx_arb.h" 13#include "third_party/base/stl_util.h" 14#include "xfa/fgas/font/cfgas_gefont.h" 15#include "xfa/fgas/layout/fgas_linebreak.h" 16#include "xfa/fgas/layout/fgas_unicode.h" 17 18CFX_RTFBreak::CFX_RTFBreak(uint32_t dwPolicies) 19 : m_dwPolicies(dwPolicies), 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(nullptr), 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(nullptr), 47 m_eCharType(FX_CHARTYPE_Unknown), 48 m_dwIdentity(0), 49 m_RTFLine1(), 50 m_RTFLine2(), 51 m_pCurLine(nullptr), 52 m_iReady(0), 53 m_iTolerance(0) { 54 m_pCurLine = &m_RTFLine1; 55} 56 57CFX_RTFBreak::~CFX_RTFBreak() { 58 Reset(); 59 m_PositionedTabs.RemoveAll(); 60 if (m_pUserData) 61 m_pUserData->Release(); 62} 63 64void CFX_RTFBreak::SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd) { 65 if (fLineStart > fLineEnd) 66 return; 67 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 74void CFX_RTFBreak::SetLineStartPos(FX_FLOAT fLinePos) { 75 int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f); 76 iLinePos = std::min(iLinePos, m_iBoundaryEnd); 77 iLinePos = std::max(iLinePos, m_iBoundaryStart); 78 m_pCurLine->m_iStart = iLinePos; 79} 80 81void CFX_RTFBreak::SetLayoutStyles(uint32_t dwLayoutStyles) { 82 if (m_dwLayoutStyles == dwLayoutStyles) 83 return; 84 85 SetBreakStatus(); 86 m_dwLayoutStyles = dwLayoutStyles; 87 m_bPagination = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_Pagination) != 0; 88 m_bVertical = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0; 89 m_bSingleLine = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0; 90 m_bCharCode = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0; 91 m_iLineRotation = GetLineRotation(m_dwLayoutStyles); 92 m_iRotation = m_iLineRotation + m_iCharRotation; 93 m_iRotation %= 4; 94} 95 96void CFX_RTFBreak::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) { 97 if (!pFont || pFont == m_pFont) 98 return; 99 100 SetBreakStatus(); 101 m_pFont = pFont; 102 m_iDefChar = 0; 103 if (m_pFont) { 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 112void CFX_RTFBreak::SetFontSize(FX_FLOAT fFontSize) { 113 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); 114 if (m_iFontSize == iFontSize) { 115 return; 116 } 117 SetBreakStatus(); 118 m_iFontSize = iFontSize; 119 m_iDefChar = 0; 120 if (m_pFont) { 121 m_iFontHeight = m_iFontSize; 122 if (m_wDefChar != 0xFEFF) { 123 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false); 124 m_iDefChar *= m_iFontSize; 125 } 126 } 127} 128void CFX_RTFBreak::SetTabWidth(FX_FLOAT fTabWidth) { 129 m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f); 130} 131void CFX_RTFBreak::AddPositionedTab(FX_FLOAT fTabPos) { 132 int32_t iLineEnd = m_iBoundaryEnd; 133 int32_t iTabPos = FXSYS_round(fTabPos * 20000.0f) + m_iBoundaryStart; 134 if (iTabPos > iLineEnd) { 135 iTabPos = iLineEnd; 136 } 137 if (m_PositionedTabs.Find(iTabPos, 0) > -1) { 138 return; 139 } 140 int32_t iCount = m_PositionedTabs.GetSize(); 141 int32_t iFind = 0; 142 for (; iFind < iCount; iFind++) { 143 if (m_PositionedTabs[iFind] > iTabPos) { 144 break; 145 } 146 } 147 m_PositionedTabs.InsertAt(iFind, iTabPos); 148 if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) { 149 m_bOrphanLine = GetLastPositionedTab() >= iLineEnd; 150 } else { 151 m_bOrphanLine = false; 152 } 153} 154void CFX_RTFBreak::SetPositionedTabs(const std::vector<FX_FLOAT>& tabs) { 155 m_PositionedTabs.RemoveAll(); 156 int32_t iCount = pdfium::CollectionSize<int32_t>(tabs); 157 m_PositionedTabs.SetSize(iCount); 158 int32_t iLineEnd = m_iBoundaryEnd; 159 int32_t iTabPos; 160 for (int32_t i = 0; i < iCount; i++) { 161 iTabPos = FXSYS_round(tabs[i] * 20000.0f) + m_iBoundaryStart; 162 if (iTabPos > iLineEnd) { 163 iTabPos = iLineEnd; 164 } 165 m_PositionedTabs[i] = iTabPos; 166 } 167 if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) { 168 m_bOrphanLine = GetLastPositionedTab() >= iLineEnd; 169 } else { 170 m_bOrphanLine = false; 171 } 172} 173void CFX_RTFBreak::ClearPositionedTabs() { 174 m_PositionedTabs.RemoveAll(); 175 m_bOrphanLine = false; 176} 177void CFX_RTFBreak::SetDefaultChar(FX_WCHAR wch) { 178 m_wDefChar = wch; 179 m_iDefChar = 0; 180 if (m_wDefChar != 0xFEFF && m_pFont) { 181 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false); 182 if (m_iDefChar < 0) { 183 m_iDefChar = 0; 184 } else { 185 m_iDefChar *= m_iFontSize; 186 } 187 } 188} 189void CFX_RTFBreak::SetLineBreakChar(FX_WCHAR wch) { 190 if (wch != L'\r' && wch != L'\n') { 191 return; 192 } 193 m_wLineBreakChar = wch; 194} 195void CFX_RTFBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) { 196 m_iTolerance = FXSYS_round(fTolerance * 20000.0f); 197} 198void CFX_RTFBreak::SetHorizontalScale(int32_t iScale) { 199 if (iScale < 0) { 200 iScale = 0; 201 } 202 if (m_iHorizontalScale == iScale) { 203 return; 204 } 205 SetBreakStatus(); 206 m_iHorizontalScale = iScale; 207} 208void CFX_RTFBreak::SetVerticalScale(int32_t iScale) { 209 if (iScale < 0) { 210 iScale = 0; 211 } 212 if (m_iVerticalScale == iScale) { 213 return; 214 } 215 SetBreakStatus(); 216 m_iVerticalScale = iScale; 217} 218void CFX_RTFBreak::SetCharRotation(int32_t iCharRotation) { 219 if (iCharRotation < 0) { 220 iCharRotation += (-iCharRotation / 4 + 1) * 4; 221 } else if (iCharRotation > 3) { 222 iCharRotation -= (iCharRotation / 4) * 4; 223 } 224 if (m_iCharRotation == iCharRotation) { 225 return; 226 } 227 SetBreakStatus(); 228 m_iCharRotation = iCharRotation; 229 m_iRotation = m_iLineRotation + m_iCharRotation; 230 m_iRotation %= 4; 231} 232void CFX_RTFBreak::SetCharSpace(FX_FLOAT fCharSpace) { 233 m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f); 234} 235void CFX_RTFBreak::SetWordSpace(bool bDefault, FX_FLOAT fWordSpace) { 236 m_bWordSpace = !bDefault; 237 m_iWordSpace = FXSYS_round(fWordSpace * 20000.0f); 238} 239void CFX_RTFBreak::SetReadingOrder(bool bRTL) { 240 m_bRTL = bRTL; 241} 242void CFX_RTFBreak::SetAlignment(int32_t iAlignment) { 243 ASSERT(iAlignment >= FX_RTFLINEALIGNMENT_Left && 244 iAlignment <= FX_RTFLINEALIGNMENT_Distributed); 245 m_iAlignment = iAlignment; 246} 247void CFX_RTFBreak::SetUserData(IFX_Retainable* pUserData) { 248 if (m_pUserData == pUserData) { 249 return; 250 } 251 SetBreakStatus(); 252 if (m_pUserData) { 253 m_pUserData->Release(); 254 } 255 m_pUserData = pUserData; 256 if (m_pUserData) { 257 m_pUserData->Retain(); 258 } 259} 260static const int32_t gs_FX_RTFLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2}; 261int32_t CFX_RTFBreak::GetLineRotation(uint32_t dwStyles) const { 262 return gs_FX_RTFLineRotations[(dwStyles & 0x0E) >> 1]; 263} 264void CFX_RTFBreak::SetBreakStatus() { 265 m_dwIdentity++; 266 int32_t iCount = m_pCurLine->CountChars(); 267 if (iCount < 1) { 268 return; 269 } 270 CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1); 271 if (tc.m_dwStatus == 0) { 272 tc.m_dwStatus = FX_RTFBREAK_PieceBreak; 273 } 274} 275CFX_RTFChar* CFX_RTFBreak::GetLastChar(int32_t index) const { 276 CFX_RTFCharArray& tca = m_pCurLine->m_LineChars; 277 int32_t iCount = tca.GetSize(); 278 if (index < 0 || index >= iCount) { 279 return nullptr; 280 } 281 CFX_RTFChar* pTC; 282 int32_t iStart = iCount - 1; 283 while (iStart > -1) { 284 pTC = tca.GetDataPtr(iStart--); 285 if (pTC->m_iCharWidth >= 0 || 286 pTC->GetCharType() != FX_CHARTYPE_Combination) { 287 if (--index < 0) { 288 return pTC; 289 } 290 } 291 } 292 return nullptr; 293} 294CFX_RTFLine* CFX_RTFBreak::GetRTFLine(bool bReady) const { 295 if (bReady) { 296 if (m_iReady == 1) { 297 return (CFX_RTFLine*)&m_RTFLine1; 298 } else if (m_iReady == 2) { 299 return (CFX_RTFLine*)&m_RTFLine2; 300 } else { 301 return nullptr; 302 } 303 } 304 ASSERT(m_pCurLine); 305 return m_pCurLine; 306} 307CFX_RTFPieceArray* CFX_RTFBreak::GetRTFPieces(bool bReady) const { 308 CFX_RTFLine* pRTFLine = GetRTFLine(bReady); 309 return pRTFLine ? &pRTFLine->m_LinePieces : nullptr; 310} 311inline FX_CHARTYPE CFX_RTFBreak::GetUnifiedCharType( 312 FX_CHARTYPE chartype) const { 313 return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype; 314} 315int32_t CFX_RTFBreak::GetLastPositionedTab() const { 316 int32_t iCount = m_PositionedTabs.GetSize(); 317 if (iCount < 1) { 318 return m_iBoundaryStart; 319 } 320 return m_PositionedTabs[iCount - 1]; 321} 322bool CFX_RTFBreak::GetPositionedTab(int32_t& iTabPos) const { 323 int32_t iCount = m_PositionedTabs.GetSize(); 324 for (int32_t i = 0; i < iCount; i++) { 325 if (m_PositionedTabs[i] > iTabPos) { 326 iTabPos = m_PositionedTabs[i]; 327 return true; 328 } 329 } 330 return false; 331} 332typedef uint32_t (CFX_RTFBreak::*FX_RTFBreak_LPFAppendChar)( 333 CFX_RTFChar* pCurChar, 334 int32_t iRotation); 335static const FX_RTFBreak_LPFAppendChar g_FX_RTFBreak_lpfAppendChar[16] = { 336 &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Tab, 337 &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Control, 338 &CFX_RTFBreak::AppendChar_Combination, &CFX_RTFBreak::AppendChar_Others, 339 &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Arabic, 340 &CFX_RTFBreak::AppendChar_Arabic, &CFX_RTFBreak::AppendChar_Arabic, 341 &CFX_RTFBreak::AppendChar_Arabic, &CFX_RTFBreak::AppendChar_Arabic, 342 &CFX_RTFBreak::AppendChar_Arabic, &CFX_RTFBreak::AppendChar_Others, 343 &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Others, 344}; 345uint32_t CFX_RTFBreak::AppendChar(FX_WCHAR wch) { 346 ASSERT(m_pFont && m_pCurLine); 347 if (m_bCharCode) 348 return AppendChar_CharCode(wch); 349 350 uint32_t dwProps = kTextLayoutCodeProperties[(uint16_t)wch]; 351 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); 352 CFX_RTFCharArray& tca = m_pCurLine->m_LineChars; 353 CFX_RTFChar* pCurChar = tca.AddSpace(); 354 pCurChar->m_dwStatus = 0; 355 pCurChar->m_wCharCode = wch; 356 pCurChar->m_dwCharProps = dwProps; 357 pCurChar->m_dwCharStyles = 0; 358 pCurChar->m_dwLayoutStyles = 0; 359 pCurChar->m_iFontSize = m_iFontSize; 360 pCurChar->m_iFontHeight = m_iFontHeight; 361 pCurChar->m_iHorizontalScale = m_iHorizontalScale; 362 pCurChar->m_iVertialScale = m_iVerticalScale; 363 pCurChar->m_nRotation = m_iCharRotation; 364 pCurChar->m_iCharWidth = 0; 365 pCurChar->m_dwIdentity = m_dwIdentity; 366 if (m_pUserData) { 367 m_pUserData->Retain(); 368 } 369 pCurChar->m_pUserData = m_pUserData; 370 uint32_t dwRet1 = FX_RTFBREAK_None; 371 if (chartype != FX_CHARTYPE_Combination && 372 GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype)) { 373 if (!m_bSingleLine && !m_bOrphanLine && 374 m_eCharType != FX_CHARTYPE_Unknown && 375 m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) { 376 if (m_eCharType != FX_CHARTYPE_Space || chartype != 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 uint32_t dwRet2 = 390 (this->*g_FX_RTFBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])( 391 pCurChar, iRotation); 392 m_eCharType = chartype; 393 return std::max(dwRet1, dwRet2); 394} 395 396uint32_t CFX_RTFBreak::AppendChar_CharCode(FX_WCHAR wch) { 397 ASSERT(m_pFont && m_pCurLine); 398 ASSERT(m_bCharCode); 399 m_pCurLine->m_iMBCSChars++; 400 CFX_RTFCharArray& tca = m_pCurLine->m_LineChars; 401 CFX_RTFChar* pCurChar = tca.AddSpace(); 402 pCurChar->m_dwStatus = 0; 403 pCurChar->m_wCharCode = wch; 404 pCurChar->m_dwCharProps = 0; 405 pCurChar->m_dwCharStyles = 0; 406 pCurChar->m_dwLayoutStyles = m_dwLayoutStyles; 407 pCurChar->m_iFontSize = m_iFontSize; 408 pCurChar->m_iFontHeight = m_iFontHeight; 409 pCurChar->m_iHorizontalScale = m_iHorizontalScale; 410 pCurChar->m_iVertialScale = m_iVerticalScale; 411 pCurChar->m_nRotation = m_iCharRotation; 412 pCurChar->m_iCharWidth = 0; 413 pCurChar->m_dwIdentity = m_dwIdentity; 414 if (m_pUserData) 415 m_pUserData->Retain(); 416 417 pCurChar->m_pUserData = m_pUserData; 418 int32_t iCharWidth = 0; 419 if (m_bVertical != FX_IsOdd(m_iRotation)) { 420 iCharWidth = 1000; 421 } else { 422 if (!m_pFont->GetCharWidth(wch, iCharWidth, true)) { 423 iCharWidth = m_iDefChar; 424 } 425 } 426 iCharWidth *= m_iFontSize; 427 iCharWidth = iCharWidth * m_iHorizontalScale / 100; 428 iCharWidth += m_iCharSpace; 429 pCurChar->m_iCharWidth = iCharWidth; 430 m_pCurLine->m_iWidth += iCharWidth; 431 m_eCharType = FX_CHARTYPE_Unknown; 432 if (!m_bSingleLine && 433 m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) { 434 return EndBreak(FX_RTFBREAK_LineBreak); 435 } 436 return FX_RTFBREAK_None; 437} 438 439uint32_t CFX_RTFBreak::AppendChar_Combination(CFX_RTFChar* pCurChar, 440 int32_t iRotation) { 441 int32_t iCharWidth = 0; 442 if (m_bVertical != FX_IsOdd(iRotation)) { 443 iCharWidth = 1000; 444 } else { 445 if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, 446 m_bCharCode)) { 447 iCharWidth = 0; 448 } 449 } 450 iCharWidth *= m_iFontSize; 451 iCharWidth = iCharWidth * m_iHorizontalScale / 100; 452 CFX_RTFChar* pLastChar = GetLastChar(0); 453 if (pLastChar && pLastChar->GetCharType() > FX_CHARTYPE_Combination) { 454 iCharWidth = -iCharWidth; 455 } else { 456 m_eCharType = FX_CHARTYPE_Combination; 457 } 458 pCurChar->m_iCharWidth = iCharWidth; 459 if (iCharWidth > 0) { 460 m_pCurLine->m_iWidth += iCharWidth; 461 } 462 return FX_RTFBREAK_None; 463} 464uint32_t CFX_RTFBreak::AppendChar_Tab(CFX_RTFChar* pCurChar, 465 int32_t iRotation) { 466 if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ExpandTab) { 467 bool bBreak = false; 468 if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) { 469 bBreak = (m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance); 470 } 471 int32_t& iLineWidth = m_pCurLine->m_iWidth; 472 int32_t iCharWidth = iLineWidth; 473 if (GetPositionedTab(iCharWidth)) { 474 iCharWidth -= iLineWidth; 475 } else { 476 iCharWidth = m_iTabWidth * (iLineWidth / m_iTabWidth + 1) - iLineWidth; 477 } 478 pCurChar->m_iCharWidth = iCharWidth; 479 iLineWidth += iCharWidth; 480 if (!m_bSingleLine && !m_bOrphanLine && bBreak) { 481 return EndBreak(FX_RTFBREAK_LineBreak); 482 } 483 } 484 return FX_RTFBREAK_None; 485} 486uint32_t CFX_RTFBreak::AppendChar_Control(CFX_RTFChar* pCurChar, 487 int32_t iRotation) { 488 uint32_t dwRet2 = FX_RTFBREAK_None; 489 if (!m_bSingleLine) { 490 switch (pCurChar->m_wCharCode) { 491 case L'\v': 492 case 0x2028: 493 dwRet2 = FX_RTFBREAK_LineBreak; 494 break; 495 case L'\f': 496 dwRet2 = FX_RTFBREAK_PageBreak; 497 break; 498 case 0x2029: 499 dwRet2 = FX_RTFBREAK_ParagraphBreak; 500 break; 501 default: 502 if (pCurChar->m_wCharCode == m_wLineBreakChar) { 503 dwRet2 = FX_RTFBREAK_ParagraphBreak; 504 } 505 break; 506 } 507 if (dwRet2 != FX_RTFBREAK_None) { 508 dwRet2 = EndBreak(dwRet2); 509 } 510 } 511 return dwRet2; 512} 513 514uint32_t CFX_RTFBreak::AppendChar_Arabic(CFX_RTFChar* pCurChar, 515 int32_t iRotation) { 516 CFX_RTFChar* pLastChar = nullptr; 517 int32_t& iLineWidth = m_pCurLine->m_iWidth; 518 int32_t iCharWidth = 0; 519 FX_WCHAR wForm; 520 bool bAlef = false; 521 if (m_eCharType >= FX_CHARTYPE_ArabicAlef && 522 m_eCharType <= FX_CHARTYPE_ArabicDistortion) { 523 pLastChar = GetLastChar(1); 524 if (pLastChar) { 525 iLineWidth -= pLastChar->m_iCharWidth; 526 CFX_RTFChar* pPrevChar = GetLastChar(2); 527 wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); 528 bAlef = (wForm == 0xFEFF && 529 pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); 530 int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation; 531 if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) { 532 iLastRotation++; 533 } 534 if (m_bVertical != FX_IsOdd(iLastRotation)) { 535 iCharWidth = 1000; 536 } else { 537 if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) { 538 if (!m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth, 539 m_bCharCode)) { 540 iCharWidth = m_iDefChar; 541 } 542 } 543 } 544 iCharWidth *= m_iFontSize; 545 iCharWidth = iCharWidth * m_iHorizontalScale / 100; 546 pLastChar->m_iCharWidth = iCharWidth; 547 iLineWidth += iCharWidth; 548 iCharWidth = 0; 549 } 550 } 551 wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, 552 nullptr); 553 if (m_bVertical != FX_IsOdd(iRotation)) { 554 iCharWidth = 1000; 555 } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode) && 556 !m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, 557 m_bCharCode)) { 558 iCharWidth = m_iDefChar; 559 } 560 561 iCharWidth *= m_iFontSize; 562 iCharWidth = iCharWidth * m_iHorizontalScale / 100; 563 pCurChar->m_iCharWidth = iCharWidth; 564 iLineWidth += iCharWidth; 565 m_pCurLine->m_iArabicChars++; 566 if (!m_bSingleLine && !m_bOrphanLine && 567 m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) { 568 return EndBreak(FX_RTFBREAK_LineBreak); 569 } 570 return FX_RTFBREAK_None; 571} 572 573uint32_t CFX_RTFBreak::AppendChar_Others(CFX_RTFChar* pCurChar, 574 int32_t iRotation) { 575 FX_CHARTYPE chartype = pCurChar->GetCharType(); 576 FX_WCHAR wForm; 577 if (chartype == FX_CHARTYPE_Numeric) { 578 if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) 579 wForm = pCurChar->m_wCharCode + 0x0630; 580 else 581 wForm = pCurChar->m_wCharCode; 582 } else if (m_bRTL || m_bVertical) { 583 wForm = FX_GetMirrorChar(pCurChar->m_wCharCode, pCurChar->m_dwCharProps, 584 m_bRTL, m_bVertical); 585 } else { 586 wForm = pCurChar->m_wCharCode; 587 } 588 int32_t iCharWidth = 0; 589 if (m_bVertical == FX_IsOdd(iRotation)) { 590 if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) 591 iCharWidth = m_iDefChar; 592 } else { 593 iCharWidth = 1000; 594 } 595 iCharWidth *= m_iFontSize; 596 iCharWidth *= m_iHorizontalScale / 100; 597 iCharWidth += m_iCharSpace; 598 if (chartype == FX_CHARTYPE_Space && m_bWordSpace) 599 iCharWidth += m_iWordSpace; 600 601 pCurChar->m_iCharWidth = iCharWidth; 602 m_pCurLine->m_iWidth += iCharWidth; 603 bool bBreak = (chartype != FX_CHARTYPE_Space || 604 (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0); 605 if (!m_bSingleLine && !m_bOrphanLine && bBreak && 606 m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) { 607 return EndBreak(FX_RTFBREAK_LineBreak); 608 } 609 return FX_RTFBREAK_None; 610} 611 612uint32_t CFX_RTFBreak::EndBreak(uint32_t dwStatus) { 613 ASSERT(dwStatus >= FX_RTFBREAK_PieceBreak && 614 dwStatus <= FX_RTFBREAK_PageBreak); 615 m_dwIdentity++; 616 CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces; 617 int32_t iCount = pCurPieces->GetSize(); 618 if (iCount > 0) { 619 CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount); 620 if (dwStatus > FX_RTFBREAK_PieceBreak) 621 pLastPiece->m_dwStatus = dwStatus; 622 else 623 dwStatus = pLastPiece->m_dwStatus; 624 return dwStatus; 625 } 626 627 CFX_RTFLine* pLastLine = GetRTFLine(true); 628 if (pLastLine) { 629 pCurPieces = &pLastLine->m_LinePieces; 630 iCount = pCurPieces->GetSize(); 631 if (iCount-- > 0) { 632 CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(iCount); 633 if (dwStatus > FX_RTFBREAK_PieceBreak) 634 pLastPiece->m_dwStatus = dwStatus; 635 else 636 dwStatus = pLastPiece->m_dwStatus; 637 return dwStatus; 638 } 639 return FX_RTFBREAK_None; 640 } 641 iCount = m_pCurLine->CountChars(); 642 if (iCount < 1) 643 return FX_RTFBREAK_None; 644 645 CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1); 646 tc.m_dwStatus = dwStatus; 647 if (dwStatus <= FX_RTFBREAK_PieceBreak) 648 return dwStatus; 649 650 m_iReady = (m_pCurLine == &m_RTFLine1) ? 1 : 2; 651 CFX_RTFLine* pNextLine = 652 (m_pCurLine == &m_RTFLine1) ? &m_RTFLine2 : &m_RTFLine1; 653 bool bAllChars = (m_iAlignment > FX_RTFLINEALIGNMENT_Right); 654 CFX_TPOArray tpos(100); 655 if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) { 656 if (!m_bCharCode) 657 EndBreak_BidiLine(tpos, dwStatus); 658 659 if (!m_bPagination && m_iAlignment > FX_RTFLINEALIGNMENT_Left) 660 EndBreak_Alignment(tpos, bAllChars, dwStatus); 661 } 662 663 m_pCurLine = pNextLine; 664 m_pCurLine->m_iStart = m_iBoundaryStart; 665 CFX_RTFChar* pTC = GetLastChar(0); 666 m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; 667 return dwStatus; 668} 669 670bool CFX_RTFBreak::EndBreak_SplitLine(CFX_RTFLine* pNextLine, 671 bool bAllChars, 672 uint32_t dwStatus) { 673 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 bool bNew = true; 705 uint32_t dwIdentity = (uint32_t)-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} 749void CFX_RTFBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, uint32_t 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 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 uint32_t dwIdentity = (uint32_t)-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} 845void CFX_RTFBreak::EndBreak_Alignment(CFX_TPOArray& tpos, 846 bool bAllChars, 847 uint32_t 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 bool bFind = false; 852 uint32_t 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 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 936int32_t CFX_RTFBreak::GetBreakPos(CFX_RTFCharArray& tca, 937 int32_t& iEndPos, 938 bool bAllChars, 939 bool bOnlyBrk) { 940 int32_t iLength = tca.GetSize() - 1; 941 if (iLength < 1) 942 return iLength; 943 944 int32_t iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1, 945 iLast = -1, iLastPos = -1; 946 if (m_bSingleLine || m_bOrphanLine || iEndPos <= m_iBoundaryEnd) { 947 if (!bAllChars || m_bCharCode) 948 return iLength; 949 950 iBreak = iLength; 951 iBreakPos = iEndPos; 952 } 953 CFX_RTFChar* pCharArray = tca.GetData(); 954 if (m_bCharCode) { 955 const CFX_RTFChar* pChar; 956 int32_t iCharWidth; 957 while (iLength > 0) { 958 if (iEndPos <= m_iBoundaryEnd) 959 break; 960 961 pChar = pCharArray + iLength--; 962 iCharWidth = pChar->m_iCharWidth; 963 if (iCharWidth > 0) 964 iEndPos -= iCharWidth; 965 } 966 return iLength; 967 } 968 bool bSpaceBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0; 969 bool bTabBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0; 970 bool bNumberBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_NumberBreak) != 0; 971 bool bInfixBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_InfixBreak) != 0; 972 FX_LINEBREAKTYPE eType; 973 uint32_t 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 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 = gs_FX_LineBreak_PairTable[nCur][nNext]; 995 } 996 } else if (nCur == FX_CBP_TB) { 997 bNeedBreak = !bTabBreak; 998 if (nNext == FX_CBP_TB) { 999 eType = bTabBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK; 1000 } else { 1001 eType = gs_FX_LineBreak_PairTable[nCur][nNext]; 1002 } 1003 } else if ((bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) || 1004 (bInfixBreak && nCur == FX_CBP_IS && nNext == FX_CBP_IS)) { 1005 eType = FX_LBT_DIRECT_BRK; 1006 } else { 1007 if (nNext == FX_CBP_SP) { 1008 eType = FX_LBT_PROHIBITED_BRK; 1009 } else { 1010 eType = gs_FX_LineBreak_PairTable[nCur][nNext]; 1011 } 1012 } 1013 if (bAllChars) { 1014 pCur->m_nBreakType = eType; 1015 } 1016 if (!bOnlyBrk) { 1017 iCharWidth = pCur->m_iCharWidth; 1018 bool bBreak = false; 1019 if (nCur == FX_CBP_TB && bTabBreak) { 1020 bBreak = iCharWidth > 0 && iEndPos - iCharWidth <= m_iBoundaryEnd; 1021 } else { 1022 bBreak = iEndPos <= m_iBoundaryEnd; 1023 } 1024 if (m_bSingleLine || m_bOrphanLine || bBreak || bNeedBreak) { 1025 if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) { 1026 iBreak = iLength; 1027 iBreakPos = iEndPos; 1028 if (!bAllChars) { 1029 return iLength; 1030 } 1031 } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) { 1032 iIndirect = iLength; 1033 iIndirectPos = iEndPos; 1034 } 1035 if (iLast < 0) { 1036 iLast = iLength; 1037 iLastPos = iEndPos; 1038 } 1039 } 1040 if (iCharWidth > 0) { 1041 iEndPos -= iCharWidth; 1042 } 1043 } 1044 nNext = nCodeProp & 0x003F; 1045 iLength--; 1046 } 1047 if (bOnlyBrk) 1048 return 0; 1049 1050 if (iBreak > -1) { 1051 iEndPos = iBreakPos; 1052 return iBreak; 1053 } 1054 if (iIndirect > -1) { 1055 iEndPos = iIndirectPos; 1056 return iIndirect; 1057 } 1058 if (iLast > -1) { 1059 iEndPos = iLastPos; 1060 return iLast; 1061 } 1062 return 0; 1063} 1064 1065void CFX_RTFBreak::SplitTextLine(CFX_RTFLine* pCurLine, 1066 CFX_RTFLine* pNextLine, 1067 bool bAllChars) { 1068 ASSERT(pCurLine && pNextLine); 1069 int32_t iCount = pCurLine->CountChars(); 1070 if (iCount < 2) { 1071 return; 1072 } 1073 int32_t iEndPos = pCurLine->GetLineEnd(); 1074 CFX_RTFCharArray& curChars = pCurLine->m_LineChars; 1075 int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); 1076 if (iCharPos < 0) { 1077 iCharPos = 0; 1078 } 1079 iCharPos++; 1080 if (iCharPos >= iCount) { 1081 pNextLine->RemoveAll(true); 1082 CFX_Char* pTC = curChars.GetDataPtr(iCharPos - 1); 1083 pTC->m_nBreakType = FX_LBT_UNKNOWN; 1084 return; 1085 } 1086 CFX_RTFCharArray& nextChars = pNextLine->m_LineChars; 1087 int cur_size = curChars.GetSize(); 1088 nextChars.SetSize(cur_size - iCharPos); 1089 FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos), 1090 (cur_size - iCharPos) * sizeof(CFX_RTFChar)); 1091 iCount -= iCharPos; 1092 cur_size = curChars.GetSize(); 1093 curChars.RemoveAt(cur_size - iCount, iCount); 1094 pNextLine->m_iStart = pCurLine->m_iStart; 1095 pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos; 1096 pCurLine->m_iWidth = iEndPos; 1097 curChars.GetDataPtr(iCharPos - 1)->m_nBreakType = FX_LBT_UNKNOWN; 1098 iCount = nextChars.GetSize(); 1099 CFX_RTFChar* pNextChars = nextChars.GetData(); 1100 for (int32_t i = 0; i < iCount; i++) { 1101 CFX_RTFChar* tc = pNextChars + i; 1102 if (tc->GetCharType() >= FX_CHARTYPE_ArabicAlef) { 1103 pCurLine->m_iArabicChars--; 1104 pNextLine->m_iArabicChars++; 1105 } 1106 if (tc->m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) { 1107 pCurLine->m_iMBCSChars--; 1108 pNextLine->m_iMBCSChars++; 1109 } 1110 tc->m_dwStatus = 0; 1111 } 1112} 1113 1114int32_t CFX_RTFBreak::CountBreakPieces() const { 1115 CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(true); 1116 return pRTFPieces ? pRTFPieces->GetSize() : 0; 1117} 1118 1119const CFX_RTFPiece* CFX_RTFBreak::GetBreakPiece(int32_t index) const { 1120 CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(true); 1121 if (!pRTFPieces) 1122 return nullptr; 1123 1124 if (index < 0 || index >= pRTFPieces->GetSize()) 1125 return nullptr; 1126 1127 return pRTFPieces->GetPtrAt(index); 1128} 1129 1130void CFX_RTFBreak::GetLineRect(CFX_RectF& rect) const { 1131 rect.top = 0; 1132 CFX_RTFLine* pRTFLine = GetRTFLine(true); 1133 if (!pRTFLine) { 1134 rect.left = ((FX_FLOAT)m_iBoundaryStart) / 20000.0f; 1135 rect.width = rect.height = 0; 1136 return; 1137 } 1138 rect.left = ((FX_FLOAT)pRTFLine->m_iStart) / 20000.0f; 1139 rect.width = ((FX_FLOAT)pRTFLine->m_iWidth) / 20000.0f; 1140 CFX_RTFPieceArray& rtfPieces = pRTFLine->m_LinePieces; 1141 int32_t iCount = rtfPieces.GetSize(); 1142 if (iCount < 1) { 1143 rect.width = 0; 1144 return; 1145 } 1146 CFX_RTFPiece* pBreakPiece; 1147 int32_t iLineHeight = 0, iMax; 1148 for (int32_t i = 0; i < iCount; i++) { 1149 pBreakPiece = rtfPieces.GetPtrAt(i); 1150 int32_t iFontHeight = FXSYS_round(pBreakPiece->m_iFontHeight * 1151 pBreakPiece->m_iVerticalScale / 100.0f); 1152 iMax = std::max(pBreakPiece->m_iFontSize, iFontHeight); 1153 if (i == 0) { 1154 iLineHeight = iMax; 1155 } else if (iLineHeight < iMax) { 1156 iLineHeight = iMax; 1157 } 1158 } 1159 rect.height = ((FX_FLOAT)iLineHeight) / 20.0f; 1160} 1161void CFX_RTFBreak::ClearBreakPieces() { 1162 CFX_RTFLine* pRTFLine = GetRTFLine(true); 1163 if (pRTFLine) { 1164 pRTFLine->RemoveAll(true); 1165 } 1166 m_iReady = 0; 1167} 1168void CFX_RTFBreak::Reset() { 1169 m_eCharType = FX_CHARTYPE_Unknown; 1170 m_RTFLine1.RemoveAll(true); 1171 m_RTFLine2.RemoveAll(true); 1172} 1173int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText, 1174 FXTEXT_CHARPOS* pCharPos, 1175 bool bCharCode, 1176 CFX_WideString* pWSForms, 1177 FX_AdjustCharDisplayPos pAdjustPos) const { 1178 if (!pText || pText->iLength < 1) { 1179 return 0; 1180 } 1181 ASSERT(pText->pStr && pText->pWidths && pText->pFont && pText->pRect); 1182 const FX_WCHAR* pStr = pText->pStr; 1183 int32_t* pWidths = pText->pWidths; 1184 int32_t iLength = pText->iLength - 1; 1185 CFX_RetainPtr<CFGAS_GEFont> pFont = pText->pFont; 1186 uint32_t dwStyles = pText->dwLayoutStyles; 1187 CFX_RectF rtText(*pText->pRect); 1188 bool bRTLPiece = FX_IsOdd(pText->iBidiLevel); 1189 FX_FLOAT fFontSize = pText->fFontSize; 1190 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); 1191 int32_t iAscent = pFont->GetAscent(); 1192 int32_t iDescent = pFont->GetDescent(); 1193 int32_t iMaxHeight = iAscent - iDescent; 1194 FX_FLOAT fFontHeight = fFontSize; 1195 FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight; 1196 FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight; 1197 bool bVerticalDoc = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0; 1198 bool bVerticalChar = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0; 1199 bool bArabicNumber = (dwStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) != 0; 1200 bool bMBCSCode = (dwStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0; 1201 int32_t iRotation = GetLineRotation(dwStyles) + pText->iCharRotation; 1202 int32_t iCharRotation; 1203 FX_WCHAR wch, wPrev = 0xFEFF, wNext, wForm; 1204 int32_t iWidth, iCharWidth, iCharHeight; 1205 FX_FLOAT fX, fY, fCharWidth, fCharHeight; 1206 int32_t iHorScale = pText->iHorizontalScale; 1207 int32_t iVerScale = pText->iVerticalScale; 1208 bool bEmptyChar; 1209 uint32_t dwProps, dwCharType; 1210 fX = rtText.left; 1211 fY = rtText.top; 1212 if (bVerticalDoc) { 1213 fX += (rtText.width - fFontSize) / 2.0f; 1214 if (bRTLPiece) { 1215 fY = rtText.bottom(); 1216 } 1217 } else { 1218 if (bRTLPiece) { 1219 fX = rtText.right(); 1220 } 1221 fY += fAscent; 1222 } 1223 int32_t iCount = 0; 1224 for (int32_t i = 0; i <= iLength; i++) { 1225 wch = *pStr++; 1226 iWidth = *pWidths++; 1227 if (!bMBCSCode) { 1228 dwProps = FX_GetUnicodeProperties(wch); 1229 dwCharType = (dwProps & FX_CHARTYPEBITSMASK); 1230 if (dwCharType == FX_CHARTYPE_ArabicAlef && iWidth == 0) { 1231 wPrev = 0xFEFF; 1232 continue; 1233 } 1234 } else { 1235 dwProps = 0; 1236 dwCharType = 0; 1237 } 1238 if (iWidth != 0) { 1239 iCharWidth = iWidth; 1240 if (iCharWidth < 0) { 1241 iCharWidth = -iCharWidth; 1242 } 1243 if (!bMBCSCode) { 1244 bEmptyChar = (dwCharType >= FX_CHARTYPE_Tab && 1245 dwCharType <= FX_CHARTYPE_Control); 1246 } else { 1247 bEmptyChar = false; 1248 } 1249 if (!bEmptyChar) { 1250 iCount++; 1251 } 1252 if (pCharPos) { 1253 iCharWidth /= iFontSize; 1254 wForm = wch; 1255 if (!bMBCSCode) { 1256 if (dwCharType >= FX_CHARTYPE_ArabicAlef) { 1257 if (i < iLength) { 1258 wNext = *pStr; 1259 if (*pWidths < 0) { 1260 if (i + 1 < iLength) { 1261 wNext = pStr[1]; 1262 } 1263 } 1264 } else { 1265 wNext = 0xFEFF; 1266 } 1267 wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); 1268 } else if (bRTLPiece || bVerticalChar) { 1269 wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar); 1270 } else if (dwCharType == FX_CHARTYPE_Numeric && bArabicNumber) { 1271 wForm = wch + 0x0630; 1272 } 1273 dwProps = FX_GetUnicodeProperties(wForm); 1274 } 1275 iCharRotation = iRotation; 1276 if (!bMBCSCode && bVerticalChar && (dwProps & 0x8000) != 0) { 1277 iCharRotation++; 1278 iCharRotation %= 4; 1279 } 1280 if (!bEmptyChar) { 1281 if (bCharCode) { 1282 pCharPos->m_GlyphIndex = wch; 1283 } else { 1284 pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, bMBCSCode); 1285 if (pCharPos->m_GlyphIndex == 0xFFFF) { 1286 pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, bMBCSCode); 1287 } 1288 } 1289#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ 1290 pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; 1291#endif 1292 pCharPos->m_FontCharWidth = iCharWidth; 1293 if (pWSForms) { 1294 *pWSForms += wForm; 1295 } 1296 } 1297 if (bVerticalDoc) { 1298 iCharHeight = iCharWidth; 1299 iCharWidth = 1000; 1300 } else { 1301 iCharHeight = 1000; 1302 } 1303 fCharWidth = fFontSize * iCharWidth / 1000.0f; 1304 fCharHeight = fFontSize * iCharHeight / 1000.0f; 1305 if (!bMBCSCode && bRTLPiece && dwCharType != FX_CHARTYPE_Combination) { 1306 if (bVerticalDoc) { 1307 fY -= fCharHeight; 1308 } else { 1309 fX -= fCharWidth; 1310 } 1311 } 1312 if (!bEmptyChar) { 1313 CFX_PointF ptOffset; 1314 bool bAdjusted = false; 1315 if (pAdjustPos) { 1316 bAdjusted = pAdjustPos(wForm, bMBCSCode, pFont, fFontSize, 1317 bVerticalChar, ptOffset); 1318 } 1319 if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) { 1320 CFX_Rect rtBBox; 1321 rtBBox.Reset(); 1322 if (pFont->GetCharBBox(wForm, &rtBBox, bMBCSCode)) { 1323 ptOffset.x = fFontSize * (850 - rtBBox.right()) / 1000.0f; 1324 ptOffset.y = fFontSize * (1000 - rtBBox.height) / 2000.0f; 1325 } 1326 } 1327 pCharPos->m_OriginX = fX + ptOffset.x; 1328 pCharPos->m_OriginY = fY - ptOffset.y; 1329 } 1330 if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) { 1331 if (bVerticalDoc) { 1332 fY += fCharHeight; 1333 } else { 1334 fX += fCharWidth; 1335 } 1336 } 1337 if (!bEmptyChar) { 1338 pCharPos->m_bGlyphAdjust = true; 1339 if (bVerticalDoc) { 1340 if (iCharRotation == 0) { 1341 pCharPos->m_AdjustMatrix[0] = -1; 1342 pCharPos->m_AdjustMatrix[1] = 0; 1343 pCharPos->m_AdjustMatrix[2] = 0; 1344 pCharPos->m_AdjustMatrix[3] = 1; 1345 pCharPos->m_OriginY += fAscent * iVerScale / 100.0f; 1346 } else if (iCharRotation == 1) { 1347 pCharPos->m_AdjustMatrix[0] = 0; 1348 pCharPos->m_AdjustMatrix[1] = -1; 1349 pCharPos->m_AdjustMatrix[2] = -1; 1350 pCharPos->m_AdjustMatrix[3] = 0; 1351 pCharPos->m_OriginX -= 1352 fDescent + fAscent * iVerScale / 100.0f - fAscent; 1353 } else if (iCharRotation == 2) { 1354 pCharPos->m_AdjustMatrix[0] = 1; 1355 pCharPos->m_AdjustMatrix[1] = 0; 1356 pCharPos->m_AdjustMatrix[2] = 0; 1357 pCharPos->m_AdjustMatrix[3] = -1; 1358 pCharPos->m_OriginX += fCharWidth; 1359 pCharPos->m_OriginY += fAscent; 1360 } else { 1361 pCharPos->m_AdjustMatrix[0] = 0; 1362 pCharPos->m_AdjustMatrix[1] = 1; 1363 pCharPos->m_AdjustMatrix[2] = 1; 1364 pCharPos->m_AdjustMatrix[3] = 0; 1365 pCharPos->m_OriginX += fAscent; 1366 pCharPos->m_OriginY += fCharWidth; 1367 } 1368 } else { 1369 if (iCharRotation == 0) { 1370 pCharPos->m_AdjustMatrix[0] = -1; 1371 pCharPos->m_AdjustMatrix[1] = 0; 1372 pCharPos->m_AdjustMatrix[2] = 0; 1373 pCharPos->m_AdjustMatrix[3] = 1; 1374 pCharPos->m_OriginY += fAscent * iVerScale / 100.0f - fAscent; 1375 } else if (iCharRotation == 1) { 1376 pCharPos->m_AdjustMatrix[0] = 0; 1377 pCharPos->m_AdjustMatrix[1] = -1; 1378 pCharPos->m_AdjustMatrix[2] = -1; 1379 pCharPos->m_AdjustMatrix[3] = 0; 1380 pCharPos->m_OriginX -= fDescent; 1381 pCharPos->m_OriginY -= fAscent + fDescent; 1382 } else if (iCharRotation == 2) { 1383 pCharPos->m_AdjustMatrix[0] = 1; 1384 pCharPos->m_AdjustMatrix[1] = 0; 1385 pCharPos->m_AdjustMatrix[2] = 0; 1386 pCharPos->m_AdjustMatrix[3] = -1; 1387 pCharPos->m_OriginX += fCharWidth; 1388 pCharPos->m_OriginY -= fAscent; 1389 } else { 1390 pCharPos->m_AdjustMatrix[0] = 0; 1391 pCharPos->m_AdjustMatrix[1] = 1; 1392 pCharPos->m_AdjustMatrix[2] = 1; 1393 pCharPos->m_AdjustMatrix[3] = 0; 1394 pCharPos->m_OriginX += fAscent * iVerScale / 100.0f; 1395 } 1396 } 1397 if (iHorScale != 100 || iVerScale != 100) { 1398 pCharPos->m_AdjustMatrix[0] = 1399 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f; 1400 pCharPos->m_AdjustMatrix[1] = 1401 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f; 1402 pCharPos->m_AdjustMatrix[2] = 1403 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f; 1404 pCharPos->m_AdjustMatrix[3] = 1405 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f; 1406 } 1407 pCharPos++; 1408 } 1409 } 1410 } 1411 if (iWidth > 0) { 1412 wPrev = wch; 1413 } 1414 } 1415 return iCount; 1416} 1417int32_t CFX_RTFBreak::GetCharRects(const FX_RTFTEXTOBJ* pText, 1418 CFX_RectFArray& rtArray, 1419 bool bCharBBox) const { 1420 if (!pText || pText->iLength < 1) 1421 return 0; 1422 1423 ASSERT(pText->pStr && pText->pWidths && pText->pFont && pText->pRect); 1424 const FX_WCHAR* pStr = pText->pStr; 1425 int32_t* pWidths = pText->pWidths; 1426 int32_t iLength = pText->iLength; 1427 CFX_RectF rect(*pText->pRect); 1428 bool bRTLPiece = FX_IsOdd(pText->iBidiLevel); 1429 FX_FLOAT fFontSize = pText->fFontSize; 1430 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); 1431 FX_FLOAT fScale = fFontSize / 1000.0f; 1432 CFX_RetainPtr<CFGAS_GEFont> pFont = pText->pFont; 1433 if (!pFont) 1434 bCharBBox = false; 1435 1436 CFX_Rect bbox; 1437 bbox.Set(0, 0, 0, 0); 1438 if (bCharBBox) 1439 bCharBBox = pFont->GetBBox(&bbox); 1440 1441 FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale); 1442 FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale); 1443 rtArray.RemoveAll(); 1444 rtArray.SetSize(iLength); 1445 uint32_t dwStyles = pText->dwLayoutStyles; 1446 bool bVertical = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0; 1447 bool bSingleLine = (dwStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0; 1448 bool bCombText = (dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0; 1449 FX_WCHAR wch, wLineBreakChar = pText->wLineBreakChar; 1450 int32_t iCharSize; 1451 FX_FLOAT fCharSize, fStart; 1452 if (bVertical) { 1453 fStart = bRTLPiece ? rect.bottom() : rect.top; 1454 } else { 1455 fStart = bRTLPiece ? rect.right() : rect.left; 1456 } 1457 for (int32_t i = 0; i < iLength; i++) { 1458 wch = *pStr++; 1459 iCharSize = *pWidths++; 1460 fCharSize = (FX_FLOAT)iCharSize / 20000.0f; 1461 bool bRet = (!bSingleLine && FX_IsCtrlCode(wch)); 1462 if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 || 1463 (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) { 1464 bRet = false; 1465 } 1466 if (bRet) { 1467 iCharSize = iFontSize * 500; 1468 fCharSize = fFontSize / 2.0f; 1469 } 1470 if (bVertical) { 1471 rect.top = fStart; 1472 if (bRTLPiece) { 1473 rect.top -= fCharSize; 1474 fStart -= fCharSize; 1475 } else { 1476 fStart += fCharSize; 1477 } 1478 rect.height = fCharSize; 1479 } else { 1480 rect.left = fStart; 1481 if (bRTLPiece) { 1482 rect.left -= fCharSize; 1483 fStart -= fCharSize; 1484 } else { 1485 fStart += fCharSize; 1486 } 1487 rect.width = fCharSize; 1488 } 1489 if (bCharBBox && !bRet) { 1490 int32_t iCharWidth = 1000; 1491 pFont->GetCharWidth(wch, iCharWidth, false); 1492 FX_FLOAT fRTLeft = 0, fCharWidth = 0; 1493 if (iCharWidth > 0) { 1494 fCharWidth = iCharWidth * fScale; 1495 fRTLeft = fLeft; 1496 if (bCombText) { 1497 fRTLeft = (rect.width - fCharWidth) / 2.0f; 1498 } 1499 } 1500 CFX_RectF rtBBoxF; 1501 if (bVertical) { 1502 rtBBoxF.top = rect.left + fRTLeft; 1503 rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f; 1504 rtBBoxF.height = fCharWidth; 1505 rtBBoxF.width = fHeight; 1506 rtBBoxF.left = std::max(rtBBoxF.left, 0.0f); 1507 } else { 1508 rtBBoxF.left = rect.left + fRTLeft; 1509 rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f; 1510 rtBBoxF.width = fCharWidth; 1511 rtBBoxF.height = fHeight; 1512 rtBBoxF.top = std::max(rtBBoxF.top, 0.0f); 1513 } 1514 rtArray.SetAt(i, rtBBoxF); 1515 continue; 1516 } 1517 rtArray.SetAt(i, rect); 1518 } 1519 return iLength; 1520} 1521 1522CFX_RTFPiece::CFX_RTFPiece() 1523 : m_dwStatus(FX_RTFBREAK_PieceBreak), 1524 m_iStartPos(0), 1525 m_iWidth(-1), 1526 m_iStartChar(0), 1527 m_iChars(0), 1528 m_iBidiLevel(0), 1529 m_iBidiPos(0), 1530 m_iFontSize(0), 1531 m_iFontHeight(0), 1532 m_iHorizontalScale(100), 1533 m_iVerticalScale(100), 1534 m_dwLayoutStyles(0), 1535 m_dwIdentity(0), 1536 m_pChars(nullptr), 1537 m_pUserData(nullptr) {} 1538 1539CFX_RTFPiece::~CFX_RTFPiece() { 1540 Reset(); 1541} 1542 1543CFX_RTFLine::CFX_RTFLine() 1544 : m_LinePieces(16), 1545 m_iStart(0), 1546 m_iWidth(0), 1547 m_iArabicChars(0), 1548 m_iMBCSChars(0) {} 1549 1550CFX_RTFLine::~CFX_RTFLine() { 1551 RemoveAll(); 1552} 1553 1554FX_RTFTEXTOBJ::FX_RTFTEXTOBJ() 1555 : pStr(nullptr), 1556 pWidths(nullptr), 1557 iLength(0), 1558 pFont(nullptr), 1559 fFontSize(12.0f), 1560 dwLayoutStyles(0), 1561 iCharRotation(0), 1562 iBidiLevel(0), 1563 pRect(nullptr), 1564 wLineBreakChar(L'\n'), 1565 iHorizontalScale(100), 1566 iVerticalScale(100) {} 1567 1568FX_RTFTEXTOBJ::~FX_RTFTEXTOBJ() {} 1569