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
Create(IFDE_TxtEdtEngine * pEngine,int32_t nIndex)19 IFDE_TxtEdtPage* IFDE_TxtEdtPage::Create(IFDE_TxtEdtEngine* pEngine,
20                                          int32_t nIndex) {
21   return (IFDE_TxtEdtPage*)new CFDE_TxtEdtPage(pEngine, nIndex);
22 }
CFDE_TxtEdtTextSet(CFDE_TxtEdtPage * pPage)23 CFDE_TxtEdtTextSet::CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage)
24     : m_pPage(pPage) {}
~CFDE_TxtEdtTextSet()25 CFDE_TxtEdtTextSet::~CFDE_TxtEdtTextSet() {}
GetType()26 FDE_VISUALOBJTYPE CFDE_TxtEdtTextSet::GetType() {
27   return FDE_VISUALOBJ_Text;
28 }
GetBBox(FDE_HVISUALOBJ hVisualObj,CFX_RectF & bbox)29 FX_BOOL CFDE_TxtEdtTextSet::GetBBox(FDE_HVISUALOBJ hVisualObj,
30                                     CFX_RectF& bbox) {
31   return FALSE;
32 }
GetMatrix(FDE_HVISUALOBJ hVisualObj,CFX_Matrix & matrix)33 FX_BOOL CFDE_TxtEdtTextSet::GetMatrix(FDE_HVISUALOBJ hVisualObj,
34                                       CFX_Matrix& matrix) {
35   return FALSE;
36 }
GetRect(FDE_HVISUALOBJ hVisualObj,CFX_RectF & rt)37 FX_BOOL CFDE_TxtEdtTextSet::GetRect(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) {
38   rt = ((FDE_LPTEXTEDITPIECE)(hVisualObj))->rtPiece;
39   return TRUE;
40 }
GetClip(FDE_HVISUALOBJ hVisualObj,CFX_RectF & rt)41 FX_BOOL CFDE_TxtEdtTextSet::GetClip(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) {
42   return FALSE;
43 }
GetString(FDE_HVISUALOBJ hText,CFX_WideString & wsText)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 }
GetFont(FDE_HVISUALOBJ hText)54 IFX_Font* CFDE_TxtEdtTextSet::GetFont(FDE_HVISUALOBJ hText) {
55   return m_pPage->GetEngine()->GetEditParams()->pFont;
56 }
GetFontSize(FDE_HVISUALOBJ hText)57 FX_FLOAT CFDE_TxtEdtTextSet::GetFontSize(FDE_HVISUALOBJ hText) {
58   return m_pPage->GetEngine()->GetEditParams()->fFontSize;
59 }
GetFontColor(FDE_HVISUALOBJ hText)60 FX_ARGB CFDE_TxtEdtTextSet::GetFontColor(FDE_HVISUALOBJ hText) {
61   return m_pPage->GetEngine()->GetEditParams()->dwFontColor;
62 }
GetDisplayPos(FDE_HVISUALOBJ hText,FXTEXT_CHARPOS * pCharPos,FX_BOOL bCharCode,CFX_WideString * pWSForms)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 }
GetCharRects(FDE_HVISUALOBJ hText,CFX_RectFArray & rtArray)94 int32_t CFDE_TxtEdtTextSet::GetCharRects(FDE_HVISUALOBJ hText,
95                                          CFX_RectFArray& rtArray) {
96   return GetCharRects_Impl(hText, rtArray);
97 }
GetCharRects_Impl(FDE_HVISUALOBJ hText,CFX_RectFArray & rtArray,FX_BOOL bBBox)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 }
CFDE_TxtEdtPage(IFDE_TxtEdtEngine * pEngine,int32_t nPageIndex)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 }
~CFDE_TxtEdtPage()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 }
Release()159 void CFDE_TxtEdtPage::Release() {
160   delete this;
161 }
GetEngine() const162 IFDE_TxtEdtEngine* CFDE_TxtEdtPage::GetEngine() const {
163   return (IFDE_TxtEdtEngine*)m_pEditEngine;
164 }
GetType()165 FDE_VISUALOBJTYPE CFDE_TxtEdtPage::GetType() {
166   return FDE_VISUALOBJ_Text;
167 }
GetBBox(FDE_HVISUALOBJ hVisualObj,CFX_RectF & bbox)168 FX_BOOL CFDE_TxtEdtPage::GetBBox(FDE_HVISUALOBJ hVisualObj, CFX_RectF& bbox) {
169   return FALSE;
170 }
GetMatrix(FDE_HVISUALOBJ hVisualObj,CFX_Matrix & matrix)171 FX_BOOL CFDE_TxtEdtPage::GetMatrix(FDE_HVISUALOBJ hVisualObj,
172                                    CFX_Matrix& matrix) {
173   return FALSE;
174 }
GetRect(FDE_HVISUALOBJ hVisualObj,CFX_RectF & rt)175 FX_BOOL CFDE_TxtEdtPage::GetRect(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) {
176   return FALSE;
177 }
GetClip(FDE_HVISUALOBJ hVisualObj,CFX_RectF & rt)178 FX_BOOL CFDE_TxtEdtPage::GetClip(FDE_HVISUALOBJ hVisualObj, CFX_RectF& rt) {
179   return FALSE;
180 }
GetCharRect(int32_t nIndex,CFX_RectF & rect,FX_BOOL bBBox) const181 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 }
GetCharIndex(const CFX_PointF & fPoint,FX_BOOL & bBefore)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 }
GetCharStart() const283 int32_t CFDE_TxtEdtPage::GetCharStart() const {
284   return m_nPageStart;
285 }
GetCharCount() const286 int32_t CFDE_TxtEdtPage::GetCharCount() const {
287   return m_nCharCount;
288 }
GetDisplayPos(const CFX_RectF & rtClip,FXTEXT_CHARPOS * & pCharPos,FX_LPRECTF pBBox) const289 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 }
CalcRangeRectArray(int32_t nStart,int32_t nCount,CFX_RectFArray & RectFArr) const316 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 }
SelectWord(const CFX_PointF & fPoint,int32_t & nCount)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 }
IsLoaded(FX_LPCRECTF pClipBox)377 FX_BOOL CFDE_TxtEdtPage::IsLoaded(FX_LPCRECTF pClipBox) {
378   return m_bLoaded;
379 }
LoadPage(FX_LPCRECTF pClipBox,IFX_Pause * pPause)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 }
UnloadPage(FX_LPCRECTF pClipBox)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 }
GetContentsBox()587 const CFX_RectF& CFDE_TxtEdtPage::GetContentsBox() {
588   return m_rtPageContents;
589 }
GetFirstPosition(FDE_HVISUALOBJ hCanvas)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 }
GetNext(FDE_HVISUALOBJ hCanvas,FX_POSITION & pos,IFDE_VisualSet * & pVisualSet)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 }
GetParentCanvas(FDE_HVISUALOBJ hCanvas,IFDE_VisualSet * & pVisualSet)612 FDE_HVISUALOBJ CFDE_TxtEdtPage::GetParentCanvas(FDE_HVISUALOBJ hCanvas,
613                                                 IFDE_VisualSet*& pVisualSet) {
614   return NULL;
615 }
GetChar(void * pIdentity,int32_t index) const616 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 }
GetWidth(void * pIdentity,int32_t index) const626 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 }
NormalizePt2Rect(CFX_PointF & ptF,const CFX_RectF & rtF,FX_FLOAT fTolerance) const631 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