1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include <algorithm> 8 9 #include "xfa/src/foxitlib.h" 10 #include "xfa/src/fee/include/ifde_txtedtbuf.h" 11 #include "xfa/src/fee/include/ifde_txtedtengine.h" 12 #include "xfa/src/fee/include/ifde_txtedtpage.h" 13 #include "xfa/src/fee/include/fx_wordbreak.h" 14 #include "fde_txtedtpage.h" 15 #include "fde_txtedtengine.h" 16 #include "fde_txtedtparag.h" 17 #include "fde_txtedtbuf.h" 18 #define FDE_TXTEDT_TOLERANCE 0.1f 19 IFDE_TxtEdtPage* IFDE_TxtEdtPage::Create(IFDE_TxtEdtEngine* pEngine, 20 int32_t nIndex) { 21 return (IFDE_TxtEdtPage*)new CFDE_TxtEdtPage(pEngine, nIndex); 22 } 23 CFDE_TxtEdtTextSet::CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage) 24 : m_pPage(pPage) {} 25 CFDE_TxtEdtTextSet::~CFDE_TxtEdtTextSet() {} 26 FDE_VISUALOBJTYPE CFDE_TxtEdtTextSet::GetType() { 27 return FDE_VISUALOBJ_Text; 28 } 29 FX_BOOL CFDE_TxtEdtTextSet::GetBBox(FDE_HVISUALOBJ hVisualObj, 30 CFX_RectF& bbox) { 31 return FALSE; 32 } 33 FX_BOOL CFDE_TxtEdtTextSet::GetMatrix(FDE_HVISUALOBJ hVisualObj, 34 CFX_Matrix& matrix) { 35 return FALSE; 36 } 37 FX_BOOL CFDE_TxtEdtTextSet::GetRect(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) { 38 rt = ((FDE_LPTEXTEDITPIECE)(hVisualObj))->rtPiece; 39 return TRUE; 40 } 41 FX_BOOL CFDE_TxtEdtTextSet::GetClip(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) { 42 return FALSE; 43 } 44 int32_t CFDE_TxtEdtTextSet::GetString(FDE_HVISUALOBJ hText, 45 CFX_WideString& wsText) { 46 FDE_LPTEXTEDITPIECE pPiece = (FDE_LPTEXTEDITPIECE)hText; 47 FX_WCHAR* pBuffer = wsText.GetBuffer(pPiece->nCount); 48 for (int32_t i = 0; i < pPiece->nCount; i++) { 49 pBuffer[i] = m_pPage->GetChar((void*)hText, i); 50 } 51 wsText.ReleaseBuffer(pPiece->nCount); 52 return pPiece->nCount; 53 } 54 IFX_Font* CFDE_TxtEdtTextSet::GetFont(FDE_HVISUALOBJ hText) { 55 return m_pPage->GetEngine()->GetEditParams()->pFont; 56 } 57 FX_FLOAT CFDE_TxtEdtTextSet::GetFontSize(FDE_HVISUALOBJ hText) { 58 return m_pPage->GetEngine()->GetEditParams()->fFontSize; 59 } 60 FX_ARGB CFDE_TxtEdtTextSet::GetFontColor(FDE_HVISUALOBJ hText) { 61 return m_pPage->GetEngine()->GetEditParams()->dwFontColor; 62 } 63 int32_t CFDE_TxtEdtTextSet::GetDisplayPos(FDE_HVISUALOBJ hText, 64 FXTEXT_CHARPOS* pCharPos, 65 FX_BOOL bCharCode, 66 CFX_WideString* pWSForms) { 67 if (hText == NULL) { 68 return 0; 69 } 70 FDE_LPTEXTEDITPIECE pPiece = (FDE_LPTEXTEDITPIECE)hText; 71 int32_t nLength = pPiece->nCount; 72 if (nLength < 1) { 73 return 0; 74 } 75 CFDE_TxtEdtEngine* pEngine = (CFDE_TxtEdtEngine*)(m_pPage->GetEngine()); 76 const FDE_TXTEDTPARAMS* pTextParams = pEngine->GetEditParams(); 77 IFX_TxtBreak* pBreak = pEngine->GetTextBreak(); 78 FX_DWORD dwLayoutStyle = pBreak->GetLayoutStyles(); 79 FX_TXTRUN tr; 80 tr.pAccess = m_pPage; 81 tr.pIdentity = (void*)hText; 82 tr.pStr = NULL; 83 tr.pWidths = NULL; 84 tr.iLength = nLength; 85 tr.pFont = pTextParams->pFont; 86 tr.fFontSize = pTextParams->fFontSize; 87 tr.dwStyles = dwLayoutStyle; 88 tr.iCharRotation = pTextParams->nCharRotation; 89 tr.dwCharStyles = pPiece->dwCharStyles; 90 tr.pRect = &(pPiece->rtPiece); 91 tr.wLineBreakChar = pTextParams->wLineBreakChar; 92 return pBreak->GetDisplayPos(&tr, pCharPos, bCharCode, pWSForms); 93 } 94 int32_t CFDE_TxtEdtTextSet::GetCharRects(FDE_HVISUALOBJ hText, 95 CFX_RectFArray& rtArray) { 96 return GetCharRects_Impl(hText, rtArray); 97 } 98 int32_t CFDE_TxtEdtTextSet::GetCharRects_Impl(FDE_HVISUALOBJ hText, 99 CFX_RectFArray& rtArray, 100 FX_BOOL bBBox) { 101 if (hText == NULL) { 102 return 0; 103 } 104 FDE_LPTEXTEDITPIECE pPiece = (FDE_LPTEXTEDITPIECE)hText; 105 CFDE_TxtEdtEngine* pEngine = (CFDE_TxtEdtEngine*)(m_pPage->GetEngine()); 106 int32_t nLength = pPiece->nCount; 107 if (nLength < 1) { 108 return 0; 109 } 110 const FDE_TXTEDTPARAMS* pTextParams = pEngine->GetEditParams(); 111 FX_DWORD dwLayoutStyle = pEngine->GetTextBreak()->GetLayoutStyles(); 112 FX_TXTRUN tr; 113 tr.pAccess = m_pPage; 114 tr.pIdentity = (void*)hText; 115 tr.pStr = NULL; 116 tr.pWidths = NULL; 117 tr.iLength = nLength; 118 tr.pFont = pTextParams->pFont; 119 tr.fFontSize = pTextParams->fFontSize; 120 tr.dwStyles = dwLayoutStyle; 121 tr.iCharRotation = pTextParams->nCharRotation; 122 tr.dwCharStyles = pPiece->dwCharStyles; 123 tr.pRect = &(pPiece->rtPiece); 124 tr.wLineBreakChar = pTextParams->wLineBreakChar; 125 return pEngine->GetTextBreak()->GetCharRects(&tr, rtArray, bBBox); 126 } 127 CFDE_TxtEdtPage::CFDE_TxtEdtPage(IFDE_TxtEdtEngine* pEngine, int32_t nPageIndex) 128 : m_pIter(nullptr), 129 m_pTextSet(nullptr), 130 m_pBgnParag(nullptr), 131 m_pEndParag(nullptr), 132 m_nRefCount(0), 133 m_nPageStart(-1), 134 m_nCharCount(0), 135 m_nPageIndex(nPageIndex), 136 m_bLoaded(FALSE), 137 m_pCharWidth(nullptr) { 138 FXSYS_memset(&m_rtPage, 0, sizeof(CFX_RectF)); 139 FXSYS_memset(&m_rtPageMargin, 0, sizeof(CFX_RectF)); 140 FXSYS_memset(&m_rtPageContents, 0, sizeof(CFX_RectF)); 141 FXSYS_memset(&m_rtPageCanvas, 0, sizeof(CFX_RectF)); 142 m_pEditEngine = (CFDE_TxtEdtEngine*)pEngine; 143 } 144 CFDE_TxtEdtPage::~CFDE_TxtEdtPage() { 145 m_PieceMassArr.RemoveAll(TRUE); 146 if (m_pTextSet) { 147 delete m_pTextSet; 148 m_pTextSet = NULL; 149 } 150 if (m_pCharWidth) { 151 delete[] m_pCharWidth; 152 m_pCharWidth = NULL; 153 } 154 if (m_pIter != NULL) { 155 m_pIter->Release(); 156 m_pIter = NULL; 157 } 158 } 159 void CFDE_TxtEdtPage::Release() { 160 delete this; 161 } 162 IFDE_TxtEdtEngine* CFDE_TxtEdtPage::GetEngine() const { 163 return (IFDE_TxtEdtEngine*)m_pEditEngine; 164 } 165 FDE_VISUALOBJTYPE CFDE_TxtEdtPage::GetType() { 166 return FDE_VISUALOBJ_Text; 167 } 168 FX_BOOL CFDE_TxtEdtPage::GetBBox(FDE_HVISUALOBJ hVisualObj, CFX_RectF& bbox) { 169 return FALSE; 170 } 171 FX_BOOL CFDE_TxtEdtPage::GetMatrix(FDE_HVISUALOBJ hVisualObj, 172 CFX_Matrix& matrix) { 173 return FALSE; 174 } 175 FX_BOOL CFDE_TxtEdtPage::GetRect(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) { 176 return FALSE; 177 } 178 FX_BOOL CFDE_TxtEdtPage::GetClip(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) { 179 return FALSE; 180 } 181 int32_t CFDE_TxtEdtPage::GetCharRect(int32_t nIndex, 182 CFX_RectF& rect, 183 FX_BOOL bBBox) const { 184 FXSYS_assert(m_nRefCount > 0); 185 FXSYS_assert(nIndex >= 0 && nIndex < m_nCharCount); 186 if (m_nRefCount < 1) { 187 return 0; 188 } 189 int32_t nCount = m_PieceMassArr.GetSize(); 190 for (int32_t i = 0; i < nCount; i++) { 191 const FDE_LPTEXTEDITPIECE pPiece = m_PieceMassArr.GetPtrAt(i); 192 if (nIndex >= pPiece->nStart && 193 nIndex < (pPiece->nStart + pPiece->nCount)) { 194 CFX_RectFArray rectArr; 195 if (bBBox) { 196 m_pTextSet->GetCharRects_Impl((FDE_HVISUALOBJ)pPiece, rectArr, bBBox); 197 } else { 198 m_pTextSet->GetCharRects((FDE_HVISUALOBJ)pPiece, rectArr); 199 } 200 rect = rectArr[nIndex - pPiece->nStart]; 201 return pPiece->nBidiLevel; 202 } 203 } 204 FXSYS_assert(0); 205 return 0; 206 } 207 int32_t CFDE_TxtEdtPage::GetCharIndex(const CFX_PointF& fPoint, 208 FX_BOOL& bBefore) { 209 FX_BOOL bVertical = m_pEditEngine->GetEditParams()->dwLayoutStyles & 210 FDE_TEXTEDITLAYOUT_DocVertical; 211 CFX_PointF ptF = fPoint; 212 NormalizePt2Rect(ptF, m_rtPageContents, FDE_TXTEDT_TOLERANCE); 213 int32_t nCount = m_PieceMassArr.GetSize(); 214 CFX_RectF rtLine; 215 int32_t nBgn = 0; 216 int32_t nEnd = 0; 217 FX_BOOL bInLine = FALSE; 218 int32_t i = 0; 219 for (i = 0; i < nCount; i++) { 220 const FDE_LPTEXTEDITPIECE pPiece = m_PieceMassArr.GetPtrAt(i); 221 if (!bInLine && (bVertical ? (pPiece->rtPiece.left <= ptF.x && 222 pPiece->rtPiece.right() > ptF.x) 223 : (pPiece->rtPiece.top <= ptF.y && 224 pPiece->rtPiece.bottom() > ptF.y))) { 225 nBgn = nEnd = i; 226 rtLine = pPiece->rtPiece; 227 bInLine = TRUE; 228 } else if (bInLine) { 229 if (bVertical ? (!(pPiece->rtPiece.left <= ptF.x && 230 pPiece->rtPiece.right() > ptF.x)) 231 : (pPiece->rtPiece.bottom() <= ptF.y || 232 pPiece->rtPiece.top > ptF.y)) { 233 nEnd = i - 1; 234 break; 235 } else { 236 rtLine.Union(pPiece->rtPiece); 237 } 238 } 239 } 240 NormalizePt2Rect(ptF, rtLine, FDE_TXTEDT_TOLERANCE); 241 int32_t nCaret = 0; 242 FDE_LPTEXTEDITPIECE pPiece = NULL; 243 for (i = nBgn; i <= nEnd; i++) { 244 pPiece = m_PieceMassArr.GetPtrAt(i); 245 nCaret = m_nPageStart + pPiece->nStart; 246 if (pPiece->rtPiece.Contains(ptF)) { 247 CFX_RectFArray rectArr; 248 m_pTextSet->GetCharRects((FDE_HVISUALOBJ)pPiece, rectArr); 249 int32_t nRtCount = rectArr.GetSize(); 250 for (int32_t j = 0; j < nRtCount; j++) { 251 if (rectArr[j].Contains(ptF)) { 252 nCaret = m_nPageStart + pPiece->nStart + j; 253 if (nCaret >= m_pEditEngine->GetTextBufLength()) { 254 bBefore = TRUE; 255 return m_pEditEngine->GetTextBufLength(); 256 } 257 FX_WCHAR wChar = m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret); 258 if (wChar == L'\n' || wChar == L'\r') { 259 if (wChar == L'\n') { 260 if (m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret - 1) == 261 L'\r') { 262 nCaret--; 263 } 264 } 265 bBefore = TRUE; 266 return nCaret; 267 } 268 if (bVertical 269 ? (ptF.y > ((rectArr[j].top + rectArr[j].bottom()) / 2)) 270 : (ptF.x > ((rectArr[j].left + rectArr[j].right()) / 2))) { 271 bBefore = FX_IsOdd(pPiece->nBidiLevel); 272 } else { 273 bBefore = !FX_IsOdd(pPiece->nBidiLevel); 274 } 275 return nCaret; 276 } 277 } 278 } 279 } 280 bBefore = TRUE; 281 return nCaret; 282 } 283 int32_t CFDE_TxtEdtPage::GetCharStart() const { 284 return m_nPageStart; 285 } 286 int32_t CFDE_TxtEdtPage::GetCharCount() const { 287 return m_nCharCount; 288 } 289 int32_t CFDE_TxtEdtPage::GetDisplayPos(const CFX_RectF& rtClip, 290 FXTEXT_CHARPOS*& pCharPos, 291 FX_LPRECTF pBBox) const { 292 pCharPos = FX_Alloc(FXTEXT_CHARPOS, m_nCharCount); 293 int32_t nCharPosCount = 0; 294 FDE_HVISUALOBJ hVisualObj = NULL; 295 int32_t nVisualObjCount = m_PieceMassArr.GetSize(); 296 FXTEXT_CHARPOS* pos = pCharPos; 297 CFX_RectF rtObj; 298 for (int32_t i = 0; i < nVisualObjCount; i++) { 299 hVisualObj = (FDE_HVISUALOBJ)m_PieceMassArr.GetPtrAt(i); 300 m_pTextSet->GetRect(hVisualObj, rtObj); 301 if (!rtClip.IntersectWith(rtObj)) { 302 continue; 303 } 304 int32_t nCount = m_pTextSet->GetDisplayPos(hVisualObj, pos, FALSE); 305 nCharPosCount += nCount; 306 pos += nCount; 307 } 308 if ((nCharPosCount * 5) < (m_nCharCount << 2)) { 309 FXTEXT_CHARPOS* pTemp = FX_Alloc(FXTEXT_CHARPOS, nCharPosCount); 310 FXSYS_memcpy(pTemp, pCharPos, sizeof(FXTEXT_CHARPOS) * nCharPosCount); 311 FX_Free(pCharPos); 312 pCharPos = pTemp; 313 } 314 return nCharPosCount; 315 } 316 void CFDE_TxtEdtPage::CalcRangeRectArray(int32_t nStart, 317 int32_t nCount, 318 CFX_RectFArray& RectFArr) const { 319 int32_t nPieceCount = m_PieceMassArr.GetSize(); 320 int32_t nEnd = nStart + nCount - 1; 321 FX_BOOL bInRange = FALSE; 322 for (int32_t i = 0; i < nPieceCount; i++) { 323 FDE_LPTEXTEDITPIECE piece = m_PieceMassArr.GetPtrAt(i); 324 if (!bInRange) { 325 if (nStart >= piece->nStart && nStart < (piece->nStart + piece->nCount)) { 326 int32_t nRangeEnd = piece->nCount - 1; 327 FX_BOOL bEnd = FALSE; 328 if (nEnd >= piece->nStart && nEnd < (piece->nStart + piece->nCount)) { 329 nRangeEnd = nEnd - piece->nStart; 330 bEnd = TRUE; 331 } 332 CFX_RectFArray rcArr; 333 m_pTextSet->GetCharRects((FDE_HVISUALOBJ)piece, rcArr); 334 CFX_RectF rectPiece = rcArr[nStart - piece->nStart]; 335 rectPiece.Union(rcArr[nRangeEnd]); 336 RectFArr.Add(rectPiece); 337 if (bEnd) { 338 return; 339 } 340 bInRange = TRUE; 341 } 342 } else { 343 if (nEnd >= piece->nStart && nEnd < (piece->nStart + piece->nCount)) { 344 CFX_RectFArray rcArr; 345 m_pTextSet->GetCharRects((FDE_HVISUALOBJ)piece, rcArr); 346 CFX_RectF rectPiece = rcArr[0]; 347 rectPiece.Union(rcArr[nEnd - piece->nStart]); 348 RectFArr.Add(rectPiece); 349 return; 350 } 351 RectFArr.Add(piece->rtPiece); 352 } 353 } 354 return; 355 } 356 int32_t CFDE_TxtEdtPage::SelectWord(const CFX_PointF& fPoint, int32_t& nCount) { 357 if (m_nRefCount < 0) { 358 return -1; 359 } 360 IFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf(); 361 FX_BOOL bBefore; 362 int32_t nIndex = GetCharIndex(fPoint, bBefore); 363 if (nIndex == m_pEditEngine->GetTextBufLength()) { 364 nIndex = m_pEditEngine->GetTextBufLength() - 1; 365 } 366 if (nIndex < 0) { 367 return -1; 368 } 369 IFX_WordBreak* pIter = FX_WordBreak_Create(); 370 pIter->Attach(new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)pBuf)); 371 pIter->SetAt(nIndex); 372 nCount = pIter->GetWordLength(); 373 int32_t nRet = pIter->GetWordPos(); 374 pIter->Release(); 375 return nRet; 376 } 377 FX_BOOL CFDE_TxtEdtPage::IsLoaded(FX_LPCRECTF pClipBox) { 378 return m_bLoaded; 379 } 380 int32_t CFDE_TxtEdtPage::LoadPage(FX_LPCRECTF pClipBox, IFX_Pause* pPause) { 381 if (m_nRefCount > 0) { 382 m_nRefCount++; 383 return m_nRefCount; 384 } 385 IFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf(); 386 const FDE_TXTEDTPARAMS* pParams = m_pEditEngine->GetEditParams(); 387 if (m_pIter != NULL) { 388 m_pIter->Release(); 389 } 390 FX_WCHAR wcAlias = 0; 391 if (pParams->dwMode & FDE_TEXTEDITMODE_Password) { 392 wcAlias = m_pEditEngine->GetAliasChar(); 393 } 394 m_pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)pBuf, wcAlias); 395 IFX_TxtBreak* pBreak = m_pEditEngine->GetTextBreak(); 396 pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 397 pBreak->ClearBreakPieces(); 398 int32_t nPageLineCount = m_pEditEngine->GetPageLineCount(); 399 int32_t nStartLine = nPageLineCount * m_nPageIndex; 400 int32_t nEndLine = std::min((nStartLine + nPageLineCount - 1), 401 (m_pEditEngine->GetLineCount() - 1)); 402 int32_t nPageStart, nPageEnd, nTemp, nBgnParag, nStartLineInParag, nEndParag, 403 nEndLineInParag; 404 nBgnParag = m_pEditEngine->Line2Parag(0, 0, nStartLine, nStartLineInParag); 405 m_pBgnParag = (CFDE_TxtEdtParag*)m_pEditEngine->GetParag(nBgnParag); 406 m_pBgnParag->LoadParag(); 407 m_pBgnParag->GetLineRange(nStartLine - nStartLineInParag, nPageStart, nTemp); 408 nEndParag = m_pEditEngine->Line2Parag(nBgnParag, nStartLineInParag, nEndLine, 409 nEndLineInParag); 410 m_pEndParag = (CFDE_TxtEdtParag*)m_pEditEngine->GetParag(nEndParag); 411 m_pEndParag->LoadParag(); 412 m_pEndParag->GetLineRange(nEndLine - nEndLineInParag, nPageEnd, nTemp); 413 nPageEnd += (nTemp - 1); 414 FX_BOOL bVertial = pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical; 415 FX_BOOL bLineReserve = 416 pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve; 417 FX_FLOAT fLineStart = 418 bVertial 419 ? (bLineReserve ? (pParams->fPlateWidth - pParams->fLineSpace) : 0.0f) 420 : 0.0f; 421 FX_FLOAT fLineStep = 422 (bVertial && bLineReserve) ? (-pParams->fLineSpace) : pParams->fLineSpace; 423 FX_FLOAT fLinePos = fLineStart; 424 if (m_pTextSet == NULL) { 425 m_pTextSet = new CFDE_TxtEdtTextSet(this); 426 } 427 m_PieceMassArr.RemoveAll(TRUE); 428 FX_DWORD dwBreakStatus = FX_TXTBREAK_None; 429 int32_t nPieceStart = 0; 430 if (m_pCharWidth != NULL) { 431 delete[] m_pCharWidth; 432 } 433 m_pCharWidth = new int32_t[nPageEnd - nPageStart + 1]; 434 pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 435 pBreak->ClearBreakPieces(); 436 m_nPageStart = nPageStart; 437 m_nCharCount = nPageEnd - nPageStart + 1; 438 FX_BOOL bReload = FALSE; 439 FX_FLOAT fDefCharWidth = 0; 440 IFX_CharIter* pIter = m_pIter->Clone(); 441 pIter->SetAt(nPageStart); 442 m_pIter->SetAt(nPageStart); 443 FX_BOOL bFirstPiece = TRUE; 444 do { 445 if (bReload) { 446 dwBreakStatus = pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 447 } else { 448 FX_WCHAR wAppend = pIter->GetChar(); 449 dwBreakStatus = pBreak->AppendChar(wAppend); 450 } 451 if (pIter->GetAt() == nPageEnd && dwBreakStatus < FX_TXTBREAK_LineBreak) { 452 dwBreakStatus = pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 453 } 454 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { 455 int32_t nPieceCount = pBreak->CountBreakPieces(); 456 for (int32_t j = 0; j < nPieceCount; j++) { 457 const CFX_TxtPiece* pPiece = pBreak->GetBreakPiece(j); 458 FDE_TEXTEDITPIECE TxtEdtPiece; 459 FXSYS_memset(&TxtEdtPiece, 0, sizeof(FDE_TEXTEDITPIECE)); 460 TxtEdtPiece.nBidiLevel = pPiece->m_iBidiLevel; 461 TxtEdtPiece.nCount = pPiece->GetLength(); 462 TxtEdtPiece.nStart = nPieceStart; 463 TxtEdtPiece.dwCharStyles = pPiece->m_dwCharStyles; 464 if (FX_IsOdd(pPiece->m_iBidiLevel)) { 465 TxtEdtPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; 466 } 467 FX_FLOAT fParaBreakWidth = 0.0f; 468 if (pPiece->m_dwStatus > FX_TXTBREAK_PieceBreak) { 469 FX_WCHAR wRtChar = pParams->wLineBreakChar; 470 if (TxtEdtPiece.nCount >= 2) { 471 FX_WCHAR wChar = pBuf->GetCharByIndex( 472 m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1); 473 FX_WCHAR wCharPre = pBuf->GetCharByIndex( 474 m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 2); 475 if (wChar == wRtChar) { 476 fParaBreakWidth += fDefCharWidth; 477 } 478 if (wCharPre == wRtChar) { 479 fParaBreakWidth += fDefCharWidth; 480 } 481 } else if (TxtEdtPiece.nCount >= 1) { 482 FX_WCHAR wChar = pBuf->GetCharByIndex( 483 m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1); 484 if (wChar == wRtChar) { 485 fParaBreakWidth += fDefCharWidth; 486 } 487 } 488 } 489 if (pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { 490 TxtEdtPiece.rtPiece.left = fLinePos; 491 TxtEdtPiece.rtPiece.top = (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; 492 TxtEdtPiece.rtPiece.width = pParams->fLineSpace; 493 TxtEdtPiece.rtPiece.height = 494 (FX_FLOAT)pPiece->m_iWidth / 20000.0f + fParaBreakWidth; 495 } else { 496 TxtEdtPiece.rtPiece.left = (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; 497 TxtEdtPiece.rtPiece.top = fLinePos; 498 TxtEdtPiece.rtPiece.width = 499 (FX_FLOAT)pPiece->m_iWidth / 20000.0f + fParaBreakWidth; 500 TxtEdtPiece.rtPiece.height = pParams->fLineSpace; 501 } 502 if (bFirstPiece) { 503 m_rtPageContents = TxtEdtPiece.rtPiece; 504 bFirstPiece = FALSE; 505 } else { 506 m_rtPageContents.Union(TxtEdtPiece.rtPiece); 507 } 508 nPieceStart += TxtEdtPiece.nCount; 509 m_PieceMassArr.Add(TxtEdtPiece); 510 for (int32_t k = 0; k < TxtEdtPiece.nCount; k++) { 511 CFX_Char* ptc = pPiece->GetCharPtr(k); 512 m_pCharWidth[TxtEdtPiece.nStart + k] = ptc->m_iCharWidth; 513 } 514 } 515 fLinePos += fLineStep; 516 pBreak->ClearBreakPieces(); 517 } 518 if (pIter->GetAt() == nPageEnd && dwBreakStatus == FX_TXTBREAK_LineBreak) { 519 bReload = TRUE; 520 pIter->Next(TRUE); 521 } 522 } while (pIter->Next(FALSE) && (pIter->GetAt() <= nPageEnd)); 523 if (m_rtPageContents.left != 0) { 524 FX_FLOAT fDelta = 0.0f; 525 if (m_rtPageContents.width < pParams->fPlateWidth) { 526 if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Right) { 527 fDelta = pParams->fPlateWidth - m_rtPageContents.width; 528 } else if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Center) { 529 if ((pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) && 530 m_nCharCount > 1) { 531 int32_t nCount = m_nCharCount - 1; 532 int32_t n = (m_pEditEngine->m_nLimit - nCount) / 2; 533 fDelta = (m_rtPageContents.width / nCount) * n; 534 } else { 535 fDelta = (pParams->fPlateWidth - m_rtPageContents.width) / 2; 536 } 537 } 538 } 539 FX_FLOAT fOffset = m_rtPageContents.left - fDelta; 540 int32_t nCount = m_PieceMassArr.GetSize(); 541 for (int32_t i = 0; i < nCount; i++) { 542 FDE_LPTEXTEDITPIECE pPiece = m_PieceMassArr.GetPtrAt(i); 543 pPiece->rtPiece.Offset(-fOffset, 0.0f); 544 } 545 m_rtPageContents.Offset(-fOffset, 0.0f); 546 } 547 if (m_pEditEngine->GetEditParams()->dwLayoutStyles & 548 FDE_TEXTEDITLAYOUT_LastLineHeight) { 549 m_rtPageContents.height -= pParams->fLineSpace - pParams->fFontSize; 550 int32_t nCount = m_PieceMassArr.GetSize(); 551 FDE_LPTEXTEDITPIECE pPiece = m_PieceMassArr.GetPtrAt(nCount - 1); 552 pPiece->rtPiece.height = pParams->fFontSize; 553 } 554 pIter->Release(); 555 m_nRefCount = 1; 556 m_bLoaded = TRUE; 557 return 0; 558 } 559 void CFDE_TxtEdtPage::UnloadPage(FX_LPCRECTF pClipBox) { 560 FXSYS_assert(m_nRefCount > 0); 561 m_nRefCount--; 562 if (m_nRefCount == 0) { 563 m_PieceMassArr.RemoveAll(); 564 if (m_pTextSet) { 565 delete m_pTextSet; 566 m_pTextSet = NULL; 567 } 568 if (m_pCharWidth) { 569 delete[] m_pCharWidth; 570 m_pCharWidth = NULL; 571 } 572 if (m_pBgnParag) { 573 m_pBgnParag->UnloadParag(); 574 } 575 if (m_pEndParag) { 576 m_pEndParag->UnloadParag(); 577 } 578 if (m_pIter) { 579 m_pIter->Release(); 580 m_pIter = NULL; 581 } 582 m_pBgnParag = NULL; 583 m_pEndParag = NULL; 584 } 585 return; 586 } 587 const CFX_RectF& CFDE_TxtEdtPage::GetContentsBox() { 588 return m_rtPageContents; 589 } 590 FX_POSITION CFDE_TxtEdtPage::GetFirstPosition(FDE_HVISUALOBJ hCanvas) { 591 if (m_PieceMassArr.GetSize() < 1) { 592 return NULL; 593 } 594 return (FX_POSITION)1; 595 } 596 FDE_HVISUALOBJ CFDE_TxtEdtPage::GetNext(FDE_HVISUALOBJ hCanvas, 597 FX_POSITION& pos, 598 IFDE_VisualSet*& pVisualSet) { 599 if (m_pTextSet == NULL) { 600 pos = NULL; 601 return NULL; 602 } 603 int32_t nPos = (int32_t)(uintptr_t)pos; 604 pVisualSet = m_pTextSet; 605 if (nPos + 1 > m_PieceMassArr.GetSize()) { 606 pos = NULL; 607 } else { 608 pos = (FX_POSITION)(uintptr_t)(nPos + 1); 609 } 610 return (FDE_HVISUALOBJ)(m_PieceMassArr.GetPtrAt(nPos - 1)); 611 } 612 FDE_HVISUALOBJ CFDE_TxtEdtPage::GetParentCanvas(FDE_HVISUALOBJ hCanvas, 613 IFDE_VisualSet*& pVisualSet) { 614 return NULL; 615 } 616 FX_WCHAR CFDE_TxtEdtPage::GetChar(void* pIdentity, int32_t index) const { 617 int32_t nIndex = 618 m_nPageStart + ((FDE_LPTEXTEDITPIECE)pIdentity)->nStart + index; 619 if (nIndex != m_pIter->GetAt()) { 620 m_pIter->SetAt(nIndex); 621 } 622 FX_WCHAR wChar = m_pIter->GetChar(); 623 m_pIter->Next(); 624 return wChar; 625 } 626 int32_t CFDE_TxtEdtPage::GetWidth(void* pIdentity, int32_t index) const { 627 int32_t nWidth = 628 m_pCharWidth[((FDE_LPTEXTEDITPIECE)pIdentity)->nStart + index]; 629 return nWidth; 630 } 631 void CFDE_TxtEdtPage::NormalizePt2Rect(CFX_PointF& ptF, 632 const CFX_RectF& rtF, 633 FX_FLOAT fTolerance) const { 634 if (rtF.Contains(ptF.x, ptF.y)) { 635 return; 636 } 637 if (ptF.x < rtF.left) { 638 ptF.x = rtF.left; 639 } else if (ptF.x >= rtF.right()) { 640 ptF.x = rtF.right() - fTolerance; 641 } 642 if (ptF.y < rtF.top) { 643 ptF.y = rtF.top; 644 } else if (ptF.y >= rtF.bottom()) { 645 ptF.y = rtF.bottom() - fTolerance; 646 } 647 } 648