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