Fix all remaining instances of FX_NEW.
[pdfium.git] / core / src / reflow / reflowedtextpage.cpp
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 "reflowedtextpage.h"
10
11 IPDF_TextPage*  IPDF_TextPage::CreateReflowTextPage(IPDF_ReflowedPage* pRefPage)
12 {
13     return new CRF_TextPage(pRefPage);
14 }
15 CRF_TextPage::CRF_TextPage(IPDF_ReflowedPage* pRefPage)
16 {
17     m_pRefPage = (CPDF_ReflowedPage*)(pRefPage);
18     m_pDataList = NULL;
19     m_CountBSArray = NULL;
20 }
21 CRF_TextPage::~CRF_TextPage()
22 {
23     if(m_pDataList) {
24         delete m_pDataList;
25         m_pDataList = NULL;
26     }
27     if(m_CountBSArray) {
28         delete m_CountBSArray;
29         m_CountBSArray = NULL;
30     }
31 }
32 FX_BOOL CRF_TextPage::ParseTextPage()
33 {
34     if(!m_pRefPage) {
35         return FALSE;
36     }
37     int count = m_pRefPage->m_pReflowed->GetSize();
38     m_pDataList = new CRF_CharDataPtrArray(std::min(count, 500));
39     for(int i = 0; i < count; i++) {
40         CRF_Data* pData = (*(m_pRefPage->m_pReflowed))[i];
41         if(pData->GetType() == CRF_Data::Text) {
42             m_pDataList->Add((CRF_CharData*)pData);
43         }
44     }
45     m_CountBSArray = new CFX_CountBSINT32Array(20);
46     return TRUE;
47 }
48 FX_BOOL CRF_TextPage::IsParsered() const
49 {
50     if(m_pDataList) {
51         return TRUE;
52     }
53     return FALSE;
54 }
55 int CRF_TextPage::CharIndexFromTextIndex(int TextIndex) const
56 {
57     return TextIndex;
58 }
59 int CRF_TextPage::TextIndexFromCharIndex(int CharIndex) const
60 {
61     return CharIndex;
62 }
63
64 int     CRF_TextPage::CountChars() const
65 {
66     if (NULL == m_pDataList) {
67         return -1;
68     }
69     return m_pDataList->GetSize();
70 }
71 void CRF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO & info) const
72 {
73     if(index >= CountChars() || index < 0 || !m_pDataList) {
74         return;
75     }
76     CRF_CharData* pData = (*m_pDataList)[index];
77     FX_FLOAT ReltiveCorddDs = pData->m_pCharState->m_fDescent;
78     FX_FLOAT ReltiveCorddAs = pData->m_pCharState->m_fAscent;
79     info.m_Flag         = CHAR_NORMAL;
80     info.m_pTextObj     = pData->m_pCharState->m_pTextObj;
81     info.m_OriginX      = pData->m_PosX;
82     info.m_OriginY      = pData->m_PosY - ReltiveCorddDs;
83     info.m_FontSize     = pData->m_pCharState->m_fFontSize;
84     CFX_FloatRect FloatRectTmp(pData->m_PosX, pData->m_PosY, pData->m_PosX + pData->m_Width, pData->m_PosY + ReltiveCorddAs - ReltiveCorddDs);
85     info.m_CharBox      = FloatRectTmp;
86     CFX_WideString str = pData->m_pCharState->m_pFont->UnicodeFromCharCode(pData->m_CharCode);
87     if(!str.IsEmpty()) {
88         info.m_Unicode  = str.GetAt(0);
89     } else {
90         info.m_Unicode = -1;
91     }
92     info.m_Charcode = (FX_WCHAR)pData->m_CharCode;
93     info.m_Matrix = CFX_Matrix(1, 0, 0, 1, 0, 0);
94 }
95 extern FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2, FX_FLOAT& interlow, FX_FLOAT& interhigh);
96 inline FX_BOOL _IsInsameline(const CFX_FloatRect& rectA, const CFX_FloatRect& rectB)
97 {
98     if((rectA.top >= rectB.bottom && rectB.top >= rectA.bottom)) {
99         return TRUE;
100     } else {
101         return FALSE;
102     }
103 }
104 inline FX_BOOL _IsIntersect(const CFX_FloatRect& rectA, const CFX_FloatRect& rectB)
105 {
106     FX_FLOAT interlow = .0f, interhigh = .0f;
107     if(GetIntersection(rectA.bottom, rectA.top, rectB.bottom, rectB.top, interlow, interhigh)) {
108         if(GetIntersection(rectA.left, rectA.right, rectB.left, rectB.right, interlow, interhigh)) {
109             return TRUE;
110         } else {
111             return FALSE;
112         }
113     }
114     return FALSE;
115 }
116 void CRF_TextPage::GetRectArray(int start, int nCount, CFX_RectArray& rectArray) const
117 {
118     int indexlen = start + nCount;
119     FPDF_CHAR_INFO info;
120     FX_BOOL bstart = TRUE;
121     CFX_FloatRect recttmp;
122     int i;
123     for(i = start; i < indexlen; i++) {
124         GetCharInfo(i, info);
125         if(bstart) {
126             recttmp = info.m_CharBox;
127             bstart = FALSE;
128         } else if(_IsInsameline(recttmp, info.m_CharBox)) {
129             recttmp.right = info.m_CharBox.right;
130             if(info.m_CharBox.top > recttmp.top) {
131                 recttmp.top = info.m_CharBox.top;
132             }
133             if(info.m_CharBox.bottom < recttmp.bottom) {
134                 recttmp.bottom = info.m_CharBox.bottom;
135             }
136         } else {
137             rectArray.Add(recttmp);
138             recttmp = info.m_CharBox;
139         }
140     }
141     rectArray.Add(recttmp);
142 }
143 inline FX_FLOAT _GetDistance(CFX_FloatRect floatRect, CPDF_Point point)
144 {
145     if(floatRect.right < point.x && floatRect.bottom > point.y) {
146         return FXSYS_sqrt(FXSYS_pow(point.x - floatRect.right, 2) + FXSYS_pow(floatRect.bottom - point.y, 2));
147     }
148     if (floatRect.right < point.x && floatRect.top < point.y) {
149         return FXSYS_sqrt(FXSYS_pow(point.x - floatRect.right, 2) + FXSYS_pow(point.y - floatRect.top, 2));
150     }
151     if(floatRect.left > point.x && floatRect.bottom > point.y) {
152         return FXSYS_sqrt(FXSYS_pow(floatRect.bottom - point.y, 2) + FXSYS_pow(floatRect.left - point.x, 2));
153     }
154     if((floatRect.right > point.x || FXSYS_fabs(floatRect.right - point.x) <= 0.0001f) &&
155             (floatRect.left < point.x || FXSYS_fabs(floatRect.left - point.x) <= 0.0001f) && floatRect.bottom > point.y) {
156         return FXSYS_fabs(floatRect.bottom - point.y);
157     }
158     if(floatRect.left > point.x && (floatRect.bottom < point.y || FXSYS_fabs(floatRect.bottom - point.y) <= 0.0001f) &&
159             (floatRect.top > point.y || FXSYS_fabs(floatRect.top - point.y) <= 0.0001f)) {
160         return FXSYS_fabs(floatRect.left - point.x);
161     }
162     if(floatRect.left > point.x && floatRect.top < point.y) {
163         return FXSYS_sqrt(FXSYS_pow(floatRect.left - point.x, 2) + FXSYS_pow(point.y - floatRect.top, 2));
164     }
165     if ((floatRect.left < point.x || FXSYS_fabs(floatRect.left - point.x) <= 0.0001f) &&
166             (floatRect.right > point.x || FXSYS_fabs(floatRect.right - point.x) <= 0.0001f) && floatRect.top < point.y) {
167         return FXSYS_fabs(point.y - floatRect.top);
168     }
169     if(floatRect.right < point.x && (floatRect.top > point.y || FXSYS_fabs(floatRect.top - point.y) <= 0.0001f) &&
170             (floatRect.bottom < point.y || FXSYS_fabs(floatRect.bottom - point.y) <= 0.0001f)) {
171         return point.x - floatRect.right;
172     }
173     return .0f;
174 }
175 int CRF_TextPage::GetIndexAtPos(CPDF_Point point, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const
176 {
177     int index = -1, i = 0, j = 0;
178     FPDF_CHAR_INFO info;
179     CFX_FloatRect rectTmp;
180     FX_FLOAT MinDistance = 1000, DistanceTmp = 0;
181     FX_FLOAT rect_bottom = point.x - xTorelance;
182     CFX_FloatRect TorelanceRect(rect_bottom <= 0 ? 0 : rect_bottom, point.y - yTorelance, point.x + xTorelance, point.y + yTorelance);
183     int count = CountChars();
184     for(i = 0; i < count; i++) {
185         GetCharInfo(i, info);
186         rectTmp = info.m_CharBox;
187         if(rectTmp.Contains(point.x, point.y)) {
188             index = i;
189             break;
190         } else if(_IsIntersect(rectTmp, TorelanceRect)) {
191             DistanceTmp = _GetDistance(rectTmp, point);
192             if(DistanceTmp < MinDistance) {
193                 MinDistance = DistanceTmp;
194                 index = i;
195             }
196         }
197     }
198     return index;
199 }
200 int CRF_TextPage::GetIndexAtPos(FX_FLOAT x, FX_FLOAT y, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const
201 {
202     int index = 0;
203     CPDF_Point point(x, y);
204     if((index = GetIndexAtPos(point, xTorelance, yTorelance)) < 0) {
205         return -1;
206     } else {
207         return index;
208     }
209 }
210 int CRF_TextPage::GetOrderByDirection(int index, int direction) const
211 {
212     return -1;
213 }
214 CFX_WideString CRF_TextPage::GetTextByRect(CFX_FloatRect rect) const
215 {
216     int count;
217     FPDF_CHAR_INFO info;
218     CFX_WideString str;
219     CFX_FloatRect  Recttmp;
220     FX_BOOL bstart = TRUE;
221     count = CountChars();
222     if(rect.IsEmpty()) {
223         return L"";
224     }
225     for(int i = 0; i < count; i++) {
226         GetCharInfo(i, info);
227         if(_IsIntersect(rect, info.m_CharBox)) {
228             if(bstart) {
229                 Recttmp = info.m_CharBox;
230                 str += info.m_Unicode;
231                 bstart = FALSE;
232             } else if(_IsInsameline(Recttmp, info.m_CharBox)) {
233                 str += info.m_Unicode;
234             } else {
235                 str += L"\r\n";
236                 Recttmp = info.m_CharBox;
237                 str += info.m_Unicode;
238             }
239         }
240     }
241     if(str.IsEmpty()) {
242         return L"";
243     } else {
244         return str;
245     }
246 }
247 void CRF_TextPage::GetRectsArrayByRect(CFX_FloatRect rect, CFX_RectArray& resRectArray) const
248 {
249     int count, i;
250     FX_BOOL bstart = TRUE;
251     FPDF_CHAR_INFO info;
252     CFX_FloatRect recttmp;
253     count = CountChars();
254     for(i = 0; i < count; i++) {
255         GetCharInfo(i, info);
256         if(_IsIntersect(rect, info.m_CharBox)) {
257             if(bstart) {
258                 recttmp = info.m_CharBox;
259                 bstart = FALSE;
260             } else if(_IsInsameline(recttmp, info.m_CharBox)) {
261                 recttmp.right = info.m_CharBox.right;
262                 if(info.m_CharBox.top > recttmp.top) {
263                     recttmp.top = info.m_CharBox.top;
264                 }
265                 if(info.m_CharBox.bottom < recttmp.bottom) {
266                     recttmp.bottom = info.m_CharBox.bottom;
267                 }
268             } else {
269                 resRectArray.Add(recttmp);
270                 recttmp = info.m_CharBox;
271             }
272         }
273     }
274     resRectArray.Add(recttmp);
275 }
276 int CRF_TextPage::CountRects(int start, int nCount)
277 {
278     m_rectArray.RemoveAll();
279     GetRectArray(start, nCount, m_rectArray);
280     return m_rectArray.GetSize();
281 }
282 void CRF_TextPage::GetRect(int rectIndex, FX_FLOAT& left, FX_FLOAT& top, FX_FLOAT& right, FX_FLOAT &bottom) const
283 {
284     if(m_rectArray.GetSize() <= rectIndex) {
285         return;
286     }
287     left   = m_rectArray[rectIndex].left;
288     top    = m_rectArray[rectIndex].top;
289     right  = m_rectArray[rectIndex].right;
290     bottom = m_rectArray[rectIndex].bottom;
291 }
292 FX_BOOL CRF_TextPage::GetBaselineRotate(int rectIndex, int& Rotate)
293 {
294     Rotate = 0;
295     return TRUE;
296 }
297 FX_BOOL CRF_TextPage::GetBaselineRotate(CFX_FloatRect rect, int& Rotate)
298 {
299     Rotate = 0;
300     return TRUE;
301 }
302 int CRF_TextPage::CountBoundedSegments(FX_FLOAT left, FX_FLOAT top, FX_FLOAT right, FX_FLOAT bottom, FX_BOOL bContains)
303 {
304     if (!m_CountBSArray) {
305         return -1;
306     }
307     m_CountBSArray->RemoveAll();
308     CFX_FloatRect floatrect(left, bottom, right, top);
309     int totalcount, i, j = 0, counttmp = 0;
310     FX_BOOL bstart = TRUE;
311     FPDF_CHAR_INFO info;
312     CFX_FloatRect recttmp;
313     totalcount = CountChars();
314     for(i = 0; i < totalcount; i++) {
315         GetCharInfo(i, info);
316         if(_IsIntersect(floatrect, info.m_CharBox)) {
317             if(bstart) {
318                 m_CountBSArray->Add(i);
319                 counttmp = 1;
320                 recttmp = info.m_CharBox;
321                 bstart = FALSE;
322             } else if(_IsInsameline(recttmp, info.m_CharBox)) {
323                 recttmp.right = info.m_CharBox.right;
324                 if(info.m_CharBox.top > recttmp.top) {
325                     recttmp.top = info.m_CharBox.top;
326                 }
327                 if(info.m_CharBox.bottom < recttmp.bottom) {
328                     recttmp.bottom = info.m_CharBox.bottom;
329                 }
330                 counttmp ++;
331             } else {
332                 m_CountBSArray->Add(counttmp);
333                 m_CountBSArray->Add(i);
334                 counttmp = 1;
335                 j++;
336                 recttmp = info.m_CharBox;
337             }
338         }
339     }
340     m_CountBSArray->Add(counttmp);
341     j++;
342     return j;
343 }
344 void CRF_TextPage::GetBoundedSegment(int index, int& start, int& count) const
345 {
346     if (!m_CountBSArray) {
347         return;
348     }
349     if(m_CountBSArray->GetSize() <= index * 2) {
350         start = 0;
351         count = 0;
352         return;
353     }
354     start = *(int *)m_CountBSArray->GetAt(index * 2);
355     count = *(int *)m_CountBSArray->GetAt(index * 2 + 1);
356 }
357
358 int CRF_TextPage::GetWordBreak(int index, int direction) const
359 {
360     return -1;
361 }
362 CFX_WideString CRF_TextPage::GetPageText(int start, int nCount ) const
363 {
364     if(nCount == -1) {
365         nCount = CountChars();
366         start = 0;
367     } else if(nCount < 1) {
368         return L"";
369     } else if(start >= CountChars()) {
370         return L"";
371     }
372     int i, index = start + nCount;
373     FPDF_CHAR_INFO info;
374     CFX_WideString str;
375     CFX_FloatRect recttmp;
376     FX_BOOL bstart = TRUE;
377     for(i = start; i < index; i++) {
378         GetCharInfo(i, info);
379         if(bstart) {
380             recttmp = info.m_CharBox;
381             str += info.m_Unicode;
382             bstart = FALSE;
383         } else if (_IsInsameline(recttmp, info.m_CharBox)) {
384             str += info.m_Unicode;
385         } else {
386             str += L"\r\n";
387             recttmp = info.m_CharBox;
388             str += info.m_Unicode;
389         }
390     }
391     if(str.IsEmpty()) {
392         return L"";
393     }
394     return str;
395 }