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