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