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