Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / reflow / autoreflow.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 "autoreflow.h"
8 #define approachto(a,b,c) (FXSYS_fabs((float)((a)-(b)))>(c) ? 0 : 1)
9 int FPDF_ProcessInterObj(const CPDF_PageObject* pPrevObj, const CPDF_PageObject* pObj)
10 {
11     CFX_AffineMatrix matrix;
12     FX_RECT PreRect = pPrevObj->GetBBox(&matrix);
13     FX_RECT rect = pObj->GetBBox(&matrix);
14     int flag = 0;
15     if(PreRect.top > rect.bottom) {
16         flag = 0;
17     } else if(rect.top > PreRect.bottom) {
18         flag = 1;
19     } else if(PreRect.right < rect.left) {
20         flag = 0;
21     } else if(PreRect.left > rect.right) {
22         flag = 1;
23     } else if(pObj->m_Type != PDFPAGE_TEXT) {
24         flag = 1;
25     } else if(pPrevObj->m_Type != PDFPAGE_TEXT) {
26         flag = 0;
27     } else {
28         if((PreRect.top < rect.top && PreRect.bottom > rect.bottom) ||
29                 (PreRect.top > rect.top && PreRect.bottom < rect.bottom)) {
30             if(PreRect.left > rect.left) {
31                 flag = 1;
32             } else {
33                 flag = 0;
34             }
35         } else {
36             CPDF_TextObject* pPrevTextObj = (CPDF_TextObject* )pPrevObj;
37             CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj;
38             CPDF_TextObjectItem item, prevItem;
39             pPrevTextObj->GetItemInfo(0, &prevItem);
40             pTextObj->GetItemInfo(0, &item);
41             CFX_AffineMatrix TextMatrix;
42             pTextObj->GetTextMatrix(&TextMatrix);
43             FX_FLOAT originX, originY, prevOriginX, preOriginY;
44             TextMatrix.Transform(item.m_OriginX, item.m_OriginY, originX, originY);
45             pPrevTextObj->GetTextMatrix(&TextMatrix);
46             TextMatrix.Transform(prevItem.m_OriginX, prevItem.m_OriginY, prevOriginX, preOriginY);
47             if(preOriginY > originY) {
48                 flag = 0;
49             } else {
50                 flag = 1;
51             }
52         }
53     }
54     return flag;
55 }
56 void CPDF_AutoReflowLayoutProvider::Conver2AppreceOrder(const CPDF_PageObjects* pStreamOrderObjs, CPDF_PageObjects* pAppraceOrderObjs)
57 {
58     FX_POSITION pos = pStreamOrderObjs->GetFirstObjectPosition();
59     CFX_AffineMatrix matrix;
60     while(pos) {
61         CPDF_PageObject* pObj = pStreamOrderObjs->GetNextObject(pos);
62         CFX_AffineMatrix matrix;
63         if(pObj->m_Type != PDFPAGE_TEXT) {
64             continue;
65         }
66         FX_POSITION pos1 = pAppraceOrderObjs->GetLastObjectPosition();
67         while(pos1) {
68             CPDF_PageObject* pTempObj = pAppraceOrderObjs->GetPrevObject(pos1);
69             if(FPDF_ProcessInterObj(pObj, pTempObj) == 1) {
70                 if(!pos1) {
71                     pos1 = pAppraceOrderObjs->GetFirstObjectPosition();
72                 } else {
73                     pAppraceOrderObjs->GetNextObject(pos1);
74                 }
75                 break;
76             }
77         }
78         pAppraceOrderObjs->InsertObject(pos1, pObj);
79     }
80     pos = pStreamOrderObjs->GetFirstObjectPosition();
81     while(pos) {
82         CPDF_PageObject* pObj = pStreamOrderObjs->GetNextObject(pos);
83         if(pObj->m_Type != PDFPAGE_IMAGE) {
84             continue;
85         }
86         FX_POSITION pos1 = pAppraceOrderObjs->GetLastObjectPosition();
87         while(pos1) {
88             CPDF_PageObject* pTempObj = pAppraceOrderObjs->GetPrevObject(pos1);
89             if(FPDF_ProcessInterObj(pObj, pTempObj) == 1) {
90                 if(!pos1) {
91                     pos1 = pAppraceOrderObjs->GetFirstObjectPosition();
92                 } else {
93                     pAppraceOrderObjs->GetNextObject(pos1);
94                 }
95                 break;
96             }
97         }
98         pAppraceOrderObjs->InsertObject(pos1, pObj);
99     }
100 }
101 IPDF_LayoutProvider* IPDF_LayoutProvider::Create_LayoutProvider_AutoReflow(CPDF_PageObjects* pPage, FX_BOOL bReadOrder)
102 {
103     return new CPDF_AutoReflowLayoutProvider(pPage, bReadOrder);
104 }
105 CPDF_AutoReflowElement::CPDF_AutoReflowElement(LayoutType layoutType , CPDF_AutoReflowElement* pParent)
106 {
107     m_ElmType = layoutType;
108     m_pParentElm = pParent;
109     if(pParent) {
110         pParent->m_ChildArray.Add(this);
111     }
112     m_SpaceBefore = 0;
113 }
114 CPDF_AutoReflowElement::~CPDF_AutoReflowElement()
115 {
116     m_ChildArray.RemoveAll();
117     m_ObjArray.RemoveAll();
118 }
119 int     CPDF_AutoReflowElement::CountAttrValues(LayoutAttr attr_type)
120 {
121     return 1;
122 }
123 LayoutEnum CPDF_AutoReflowElement::GetEnumAttr(LayoutAttr attr_type, int index )
124 {
125     return LayoutInvalid;
126 }
127 FX_FLOAT        CPDF_AutoReflowElement::GetNumberAttr(LayoutAttr attr_type, int index )
128 {
129     switch (attr_type) {
130         case LayoutSpaceBefore:
131             return m_SpaceBefore;
132         default:
133             return 0;
134     }
135 }
136 FX_COLORREF     CPDF_AutoReflowElement::GetColorAttr(LayoutAttr attr_type, int index )
137 {
138     return 0;
139 }
140 #define WritingMode_UNKNOW      0
141 #define WritingMode_LRTB        1
142 #define WritingMode_RLTB        2
143 #define WritingMode_TBRL        3
144 CPDF_AutoReflowLayoutProvider::CPDF_AutoReflowLayoutProvider(CPDF_PageObjects* pPage, FX_BOOL bReadOrder)
145 {
146     m_pPDFPage = (CPDF_Page*)pPage;
147     FX_FLOAT width = m_pPDFPage->GetPageWidth();
148     FX_FLOAT height = m_pPDFPage->GetPageHeight();
149     m_pPDFPage->GetDisplayMatrix(m_PDFDisplayMatrix, 0, 0, (int)(m_pPDFPage->GetPageWidth()), (int)(m_pPDFPage->GetPageHeight()), 0);
150     m_bReadOrder = bReadOrder;
151     m_Status = LayoutReady;
152     m_pRoot = NULL;
153     m_pCurrElm = NULL;
154     m_pPreObj = NULL;
155     m_Step = 0;
156     m_WritingMode = WritingMode_UNKNOW;
157 }
158 CPDF_AutoReflowLayoutProvider::~CPDF_AutoReflowLayoutProvider()
159 {
160     m_pPDFPage = NULL;
161     ReleaseElm(m_pRoot);
162 }
163 void CPDF_AutoReflowLayoutProvider::ReleaseElm(CPDF_AutoReflowElement*& pElm, FX_BOOL bReleaseChildren)
164 {
165     if(bReleaseChildren) {
166         int count = pElm->CountChildren();
167         for(int i = 0; i < count; i++) {
168             CPDF_AutoReflowElement* pChild = (CPDF_AutoReflowElement*)pElm->GetChild(i);
169             ReleaseElm(pChild);
170         }
171     }
172     delete pElm;
173     pElm = NULL;
174 }
175 void CPDF_AutoReflowLayoutProvider::AddObjectArray(CPDF_AutoReflowElement* pElm, CFX_PtrList& ObjList)
176 {
177     if(!pElm) {
178         return;
179     }
180     FX_POSITION pos = ObjList.GetHeadPosition();
181     while (pos) {
182         pElm->m_ObjArray.Add((CPDF_PageObject*)ObjList.GetNext(pos));
183     }
184 }
185 void CPDF_AutoReflowLayoutProvider::GenerateStructTree()
186 {
187     if (m_Step < AUTOREFLOW_STEP_GENERATELINE) {
188         GenerateLine(m_cellArray);
189         if(m_cellArray.GetSize() == 0) {
190             m_Status = LayoutError;
191             return;
192         }
193         if(m_pPause && m_pPause->NeedToPauseNow()) {
194             m_Step = AUTOREFLOW_STEP_GENERATELINE;
195             m_Status = LayoutToBeContinued;
196             return;
197         }
198     }
199     if (m_Step < AUTOREFLOW_STEP_GENERATEParagraph) {
200         GenerateParagraph(m_cellArray);
201         if(m_pPause && m_pPause->NeedToPauseNow()) {
202             m_Step = AUTOREFLOW_STEP_GENERATEParagraph;
203             m_Status = LayoutToBeContinued;
204             return;
205         }
206     }
207     if (m_Step < AUTOREFLOW_STEP_CREATEELEMENT) {
208         CreateElement();
209         if(m_pPause && m_pPause->NeedToPauseNow()) {
210             m_Step = AUTOREFLOW_STEP_CREATEELEMENT;
211             m_Status = LayoutToBeContinued;
212             return;
213         }
214     }
215     if (m_Step < AUTOREFLOW_STEP_REMOVEDATA) {
216         int count = m_cellArray.GetSize();
217         for(int i = 0; i < count; i++) {
218             CRF_CELL* pCell = (CRF_CELL*)m_cellArray.GetAt(i);
219             if(pCell) {
220                 pCell->m_ObjList.RemoveAll();
221                 delete pCell;
222             }
223         }
224         m_cellArray.RemoveAll();
225         if(m_pPause && m_pPause->NeedToPauseNow()) {
226             m_Step = AUTOREFLOW_STEP_REMOVEDATA;
227             m_Status = LayoutToBeContinued;
228             return;
229         }
230     }
231     m_Step = AUTOREFLOW_STEP_REMOVEDATA;
232     m_Status = LayoutFinished;
233     return;
234 }
235 void CPDF_AutoReflowLayoutProvider::CreateElement()
236 {
237     int count = m_cellArray.GetSize();
238     CRF_CELL* plastCell = NULL;
239     CRF_CELL* pCell = NULL;
240     CRF_CELL* pNextCell = NULL;
241     CPDF_AutoReflowElement* pParent = m_pRoot;
242     CPDF_AutoReflowElement* pCurrElm = NULL;
243     int i;
244     for(i = 0; i < count; i++) {
245         pCell = (CRF_CELL*)m_cellArray.GetAt(i);
246         if(!pCell) {
247             continue;
248         }
249         if(i < count - 1) {
250             pNextCell = (CRF_CELL*)m_cellArray.GetAt(i + 1);
251         } else {
252             pNextCell = NULL;
253         }
254         pCurrElm = new CPDF_AutoReflowElement(LayoutParagraph, pParent);
255         if(pCurrElm->GetType() == LayoutParagraph && plastCell) {
256             int SpaceBefore = 0;
257             if(pCell->m_CellWritingMode != plastCell->m_CellWritingMode ) {
258                 SpaceBefore = 20;
259             } else if(pCell->m_CellWritingMode == WritingMode_LRTB) {
260                 SpaceBefore = plastCell->m_BBox.bottom - pCell->m_BBox.top;
261             } else if(pCell->m_CellWritingMode == WritingMode_TBRL) {
262                 SpaceBefore = plastCell->m_BBox.left - pCell->m_BBox.right;
263             }
264             if(SpaceBefore > 0) {
265                 pCurrElm->m_SpaceBefore = SpaceBefore > 50 ? 50.0f : SpaceBefore;
266             }
267         }
268         AddObjectArray(pCurrElm, pCell->m_ObjList);
269         plastCell = pCell;
270     }
271 }
272 void CPDF_AutoReflowLayoutProvider::GenerateParagraph(CFX_PtrArray& cellArray)
273 {
274     int count = cellArray.GetSize();
275     if(count <= 1) {
276         return;
277     }
278     CRF_CELL* plastCell = (CRF_CELL*)cellArray.GetAt(0);
279     if(plastCell->m_BBox.Height() > plastCell->m_BBox.Width()) {
280         m_WritingMode = WritingMode_TBRL;
281     } else {
282         m_WritingMode = WritingMode_LRTB;
283     }
284     FX_BOOL bEnforce = FALSE;
285     int i = 0;
286     for(i = 1; i < count; i++) {
287         CRF_CELL* pCell = (CRF_CELL*)cellArray.GetAt(i);
288         if(!pCell) {
289             continue;
290         }
291         int c = pCell->m_ObjList.GetCount();
292         FX_BOOL bMerge = FALSE;
293         FX_POSITION pos1 = plastCell->m_ObjList.GetTailPosition();
294         CPDF_PageObject* pLastObj = (CPDF_PageObject*)plastCell->m_ObjList.GetPrev(pos1);
295         pos1 = pCell->m_ObjList.GetHeadPosition();
296         CPDF_PageObject* pCurObj = (CPDF_PageObject*)pCell->m_ObjList.GetNext(pos1);
297         int WritingMode = GetRectEnd(pCell->m_BBox);
298         if(pCell->m_CellWritingMode == WritingMode_UNKNOW) {
299             if(pCell->m_BBox.Height() > pCell->m_BBox.Width()) {
300                 pCell->m_CellWritingMode = WritingMode_TBRL;
301             } else {
302                 pCell->m_CellWritingMode = WritingMode_LRTB;
303             }
304         }
305         WritingMode = pCell->m_CellWritingMode;
306         if(WritingMode == WritingMode_LRTB && (m_Style.m_Language & LP_Lang_ChinesePRC || m_Style.m_Language & LP_Lang_ChineseTaiwan
307                                                || m_Style.m_Language & LP_Lang_Japanese || m_Style.m_Language & LP_Lang_Korean)) {
308             if(pCurObj->m_Type == PDFPAGE_TEXT) {
309                 CPDF_TextObject* pText;
310                 pText = (CPDF_TextObject*)pCurObj;
311                 if(pText->CountItems()) {
312                     CPDF_TextObjectItem item;
313                     pText->GetItemInfo(0, &item);
314                     CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
315                     FX_WCHAR unicode = str.GetAt(0);
316                     if(unicode == 32) {
317                         plastCell = pCell;
318                         bMerge = FALSE;
319                         bEnforce = FALSE;
320                         continue;
321                     }
322                 }
323             }
324         }
325         if(m_WritingMode == WritingMode) {
326             if(bEnforce) {
327                 bMerge = FALSE;
328                 bEnforce = FALSE;
329                 if(pCurObj->m_Type == PDFPAGE_TEXT) {
330                     CPDF_TextObject* pText;
331                     pText = (CPDF_TextObject*)pCurObj;
332                     if(pText->CountItems()) {
333                         CPDF_TextObjectItem item;
334                         pText->GetItemInfo(0, &item);
335                         CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
336                         FX_WCHAR unicode = str.GetAt(0);
337                         if(unicode > 96 && unicode < 123) {
338                             bMerge = TRUE;
339                         }
340                     }
341                 } else {
342                     CPDF_ImageObject* pImage = (CPDF_ImageObject*)pCurObj;
343                     FX_RECT imageBBox = pImage->GetBBox(&m_PDFDisplayMatrix);
344                     if(GetRectEnd(plastCell->m_BBox) - GetRectEnd(pCell->m_BBox) < GetRectWidth(imageBBox)) {
345                         bMerge = TRUE;
346                     }
347                 }
348             } else {
349                 if(!approachto(GetRectStart(pCell->m_BBox), GetRectStart(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) / 4)) {
350                     if(approachto(GetRectStart(plastCell->m_BBox), GetRectStart(pCell->m_BBox), GetRectHeight(pCell->m_BBox) * 2.3) &&
351                             GetRectStart(plastCell->m_BBox) - GetRectStart(pCell->m_BBox) > 0) {
352                         if(pCurObj->m_Type == PDFPAGE_TEXT || pLastObj->m_Type == PDFPAGE_TEXT) {
353                             CPDF_TextObject* pText;
354                             if(pCurObj->m_Type == PDFPAGE_TEXT) {
355                                 pText = (CPDF_TextObject*)pCurObj;
356                             } else {
357                                 pText = (CPDF_TextObject*)pLastObj;
358                             }
359                             CPDF_TextObjectItem item;
360                             pText->GetItemInfo(0, &item);
361                             CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
362                             FX_WCHAR unicode = str.GetAt(0);
363                             if(unicode > 255) {
364                                 bMerge = TRUE;
365                             }
366                         }
367                     }
368                 } else if(!approachto(GetRectEnd(pCell->m_BBox), GetRectEnd(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) * 3)) {
369                     FX_RECT rect = pLastObj->GetBBox(&m_PDFDisplayMatrix);
370                     if(approachto(GetRectStart(pCell->m_BBox), GetRectStart(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) / 4)) {
371                         if(GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) > 0) {
372                             bMerge = TRUE;
373                             bEnforce = TRUE;
374                         } else if(GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) <= 0 &&
375                                   GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) > GetRectHeight(pCell->m_BBox) * -3) {
376                             if(pCurObj->m_Type == PDFPAGE_TEXT) {
377                                 CPDF_TextObject* pText = (CPDF_TextObject*)pCurObj;
378                                 CPDF_TextObjectItem item;
379                                 pText->GetItemInfo(0, &item);
380                                 CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
381                                 FX_WCHAR unicode = str.GetAt(0);
382                                 if(unicode > 96 && unicode < 123) {
383                                     bMerge = TRUE;
384                                 }
385                             }
386                         }
387                     }
388                 } else {
389                     bMerge = TRUE;
390                 }
391             }
392         } else {
393             m_WritingMode = WritingMode;
394             bEnforce = FALSE;
395         }
396         if(bMerge) {
397             if(GetRectEnd(plastCell->m_BBox) - GetRectEnd(pCell->m_BBox) > 30) {
398                 bEnforce = TRUE;
399             }
400             FX_POSITION pos = pCell->m_ObjList.GetHeadPosition();
401             while(pos) {
402                 plastCell->m_ObjList.AddTail(pCell->m_ObjList.GetNext(pos));
403             }
404             plastCell->m_BBox.Union(pCell->m_BBox);
405             pCell->m_ObjList.RemoveAll();
406             delete pCell;
407             cellArray.RemoveAt(i);
408             i--;
409             count--;
410         } else {
411             plastCell = pCell;
412         }
413     }
414 }
415 void CPDF_AutoReflowLayoutProvider::ProcessObj(CFX_PtrArray& cellArray, CPDF_PageObject* pObj, CFX_AffineMatrix matrix)
416 {
417 }
418 int32_t CPDF_AutoReflowLayoutProvider::LogicPreObj(CPDF_PageObject* pObj)
419 {
420     CPDF_PageObject* pPreObj = m_pPreObj;
421     m_pPreObj = pObj;
422     if(!pPreObj) {
423         return 0;
424     }
425     if(pPreObj->m_Type != pObj->m_Type) {
426         return 0;
427     }
428     CFX_FloatRect rcCurObj(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
429     CFX_FloatRect rcPreObj(pPreObj->m_Left, pPreObj->m_Bottom, pPreObj->m_Right, pPreObj->m_Top);
430     if(pObj->m_Type == PDFPAGE_IMAGE) {
431         if(rcPreObj.Contains(rcCurObj)) {
432             return 2;
433         }
434         if(rcCurObj.Contains(rcPreObj)) {
435             return 2;
436         }
437         return 0;
438     }
439     if(pObj->m_Type == PDFPAGE_TEXT) {
440         if(!((rcPreObj.bottom > rcCurObj.top) || (rcPreObj.top < rcCurObj.bottom))) {
441             FX_FLOAT height = FX_MIN(rcPreObj.Height(), rcCurObj.Height());
442             if((rcCurObj.left - rcPreObj.right) > height / 3) {
443                 return 3;
444             }
445         }
446         if(FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) >= 2 || FXSYS_fabs(rcPreObj.Height() - rcCurObj.Height()) >= 2 ) {
447             return 0;
448         }
449         CPDF_TextObject* pPreTextObj = (CPDF_TextObject*)pPreObj;
450         CPDF_TextObject* pCurTextObj = (CPDF_TextObject*)pObj;
451         int nPreCount = pPreTextObj->CountItems();
452         int nCurCount = pCurTextObj->CountItems();
453         if (nPreCount != nCurCount) {
454             return 0;
455         }
456         FX_BOOL bSame = TRUE;
457         for (int i = 0; i < nPreCount; i++) {
458             CPDF_TextObjectItem itemPer, itemCur;
459             pPreTextObj->GetItemInfo(i, &itemPer);
460             pCurTextObj->GetItemInfo(i, &itemCur);
461             if (itemCur.m_CharCode != itemPer.m_CharCode) {
462                 return 0;
463             }
464             if (itemCur.m_OriginX != itemPer.m_OriginX) {
465                 bSame = FALSE;
466             }
467             if (itemCur.m_OriginY != itemPer.m_OriginY) {
468                 bSame = FALSE;
469             }
470         }
471         if(rcPreObj.left == rcCurObj.left && rcPreObj.top == rcCurObj.top) {
472             return 1;
473         }
474         if(FXSYS_fabs(rcPreObj.left - rcCurObj.left) < rcPreObj.Width() / 3
475                 && FXSYS_fabs(rcPreObj.top - rcCurObj.top) < rcPreObj.Height() / 3) {
476             return 2;
477         }
478     }
479     return 0;
480 }
481 void CPDF_AutoReflowLayoutProvider::GenerateLine(CFX_PtrArray& cellArray)
482 {
483     CRF_CELL* pCell = NULL;
484     CFX_AffineMatrix matrix;
485     FX_POSITION pos = m_pPDFPage->GetFirstObjectPosition();
486     if(!pos) {
487         return;
488     }
489     FX_FLOAT PDFWidth = m_pPDFPage->GetPageWidth();
490     FX_FLOAT PDFHeight = m_pPDFPage->GetPageHeight();
491     m_pPDFPage->GetDisplayMatrix(m_PDFDisplayMatrix, 0, 0, (int)PDFWidth, (int)PDFHeight, 0);
492     CPDF_PageObject* pPerObj = NULL;
493     int a = 0;
494     CFX_FloatRect pageBBox = m_pPDFPage->m_BBox;
495     FX_FLOAT PrevX = 0 , PrevY = 0, PosX, PosY;
496     while(pos) {
497         CPDF_PageObject* pObj = m_pPDFPage->GetNextObject(pos);
498         if(!pObj || pObj->m_Type == PDFPAGE_PATH) {
499             continue;
500         }
501         int logic = LogicPreObj(pObj);
502         if(logic == 2) {
503             if(pCell) {
504                 pCell->m_ObjList.SetAt(pCell->m_ObjList.GetTailPosition(), pObj);
505             }
506             continue;
507         }
508         if (pObj->m_Type == PDFPAGE_TEXT) {
509             CPDF_TextObject* pTextObj = (CPDF_TextObject*)pObj;
510             int textmode = pTextObj->m_TextState.GetObject()->m_TextMode;
511             if(m_Style.m_bIgnoreInvisibleText && pTextObj->m_TextState.GetObject()->m_TextMode == 3) {
512                 continue;
513             }
514             PosX = pTextObj->GetPosX();
515             PosY = pTextObj->GetPosY();
516             m_PDFDisplayMatrix.Transform(PosX, PosY);
517         } else {
518             PosX = 0;
519             PosY = 0;
520         }
521         FX_BOOL bNewLine = TRUE;
522         FX_RECT ObjBBox = pObj->GetBBox(&m_PDFDisplayMatrix);
523         if(ObjBBox.left > PDFWidth || ObjBBox.right < 0 ||
524                 ObjBBox.bottom < 0 || ObjBBox.top > PDFHeight) {
525             continue;
526         }
527         if(ObjBBox.IsEmpty()) {
528             continue;
529         }
530         a++;
531         if(!pCell) {
532             bNewLine = TRUE;
533             m_WritingMode = GetWritingMode(NULL, pObj);
534         } else {
535             int WritingMode = GetWritingMode(pPerObj, pObj);
536             if(m_WritingMode == WritingMode || m_WritingMode == WritingMode_UNKNOW || WritingMode == WritingMode_UNKNOW) {
537                 if(WritingMode != WritingMode_UNKNOW) {
538                     m_WritingMode = WritingMode;
539                 }
540                 if(m_WritingMode == WritingMode_TBRL) {
541                     if(!(GetRectBottom(ObjBBox) > GetRectTop(pCell->m_BBox) ||
542                             GetRectTop(ObjBBox) < GetRectBottom(pCell->m_BBox))) {
543                         bNewLine = FALSE;
544                     }
545                 } else {
546                     if(!(GetRectBottom(ObjBBox) < GetRectTop(pCell->m_BBox) ||
547                             GetRectTop(ObjBBox) > GetRectBottom(pCell->m_BBox))) {
548                         bNewLine = FALSE;
549                     }
550                     if (pObj->m_Type == PDFPAGE_TEXT) {
551                         if(FXSYS_fabs(PrevY - PosY) < 1 ) {
552                             bNewLine = FALSE;
553                         }
554                     }
555                 }
556             } else {
557                 m_WritingMode = WritingMode;
558             }
559         }
560         pPerObj = pObj;
561         if(bNewLine) {
562             int c = pCell ? pCell->m_ObjList.GetCount() : 0;
563             pCell = new CRF_CELL;
564             pCell->m_CellWritingMode = m_WritingMode;
565             pCell->m_BBox = ObjBBox;
566             if(pObj->m_Type == PDFPAGE_TEXT) {
567                 FX_FLOAT x = ((CPDF_TextObject*)pObj)->GetPosX(), y = ((CPDF_TextObject*)pObj)->GetPosY();
568                 m_PDFDisplayMatrix.Transform(x, y);
569                 if(x < ObjBBox.left) {
570                     pCell->m_BBox.left = (int)x;
571                 }
572             }
573             pCell->m_ObjList.AddTail(pObj);
574             cellArray.Add(pCell);
575         } else {
576             pCell->m_ObjList.AddTail(pObj);
577             pCell->m_BBox.Union(ObjBBox);
578         }
579         PrevX = PosX;
580         PrevY = PosY;
581     }
582 }
583 FX_FLOAT CPDF_AutoReflowLayoutProvider::GetLayoutOrderHeight(CPDF_PageObject* pCurObj)
584 {
585     CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top);
586     if (m_WritingMode == WritingMode_TBRL) {
587         return rcCurObj.Width();
588     }
589     return rcCurObj.Height();
590 }
591 FX_FLOAT CPDF_AutoReflowLayoutProvider::GetLayoutOrderWidth(CPDF_PageObject* pCurObj)
592 {
593     CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top);
594     if (m_WritingMode == WritingMode_TBRL) {
595         return rcCurObj.Height();
596     }
597     return rcCurObj.Width();
598 }
599 int CPDF_AutoReflowLayoutProvider:: GetRectWidth(FX_RECT rect)
600 {
601     if(m_WritingMode == WritingMode_TBRL) {
602         return rect.Height();
603     }
604     return rect.Width();
605 }
606 int CPDF_AutoReflowLayoutProvider:: GetRectHeight(FX_RECT rect)
607 {
608     if(m_WritingMode == WritingMode_TBRL) {
609         return rect.Width();
610     }
611     return rect.Height();
612 }
613 int CPDF_AutoReflowLayoutProvider:: GetRectStart(FX_RECT rect)
614 {
615     if(m_WritingMode == WritingMode_TBRL) {
616         return rect.top;
617     }
618     return rect.left;
619 }
620 int CPDF_AutoReflowLayoutProvider:: GetRectEnd(FX_RECT rect)
621 {
622     if(m_WritingMode == WritingMode_TBRL) {
623         return rect.bottom;
624     }
625     return rect.right;
626 }
627 int CPDF_AutoReflowLayoutProvider:: GetRectTop(FX_RECT rect)
628 {
629     if(m_WritingMode == WritingMode_TBRL) {
630         return rect.right;
631     }
632     return rect.top;
633 }
634 int CPDF_AutoReflowLayoutProvider:: GetRectBottom(FX_RECT rect)
635 {
636     if(m_WritingMode == WritingMode_TBRL) {
637         return rect.left;
638     }
639     return rect.bottom;
640 }
641 int CPDF_AutoReflowLayoutProvider::GetWritingMode(CPDF_PageObject* pPreObj, CPDF_PageObject* pCurObj)
642 {
643     CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top);
644     if(pCurObj->m_Type == PDFPAGE_TEXT) {
645         CPDF_TextObject* ptextObj = (CPDF_TextObject* )pCurObj;
646         int count = ptextObj->CountItems();
647         if(count > 1) {
648             CPDF_TextObjectItem Item1, Item2;
649             ptextObj->GetItemInfo(0, &Item1);
650             ptextObj->GetItemInfo(count - 1, &Item2);
651             if(Item2.m_CharCode == -1 && count > 2) {
652                 ptextObj->GetItemInfo(2, &Item2);
653             }
654             CFX_AffineMatrix textMatrix;
655             ptextObj->GetTextMatrix(&textMatrix);
656             textMatrix.Transform(Item1.m_OriginX, Item1.m_OriginY);
657             textMatrix.Transform(Item2.m_OriginX, Item2.m_OriginY);
658             FX_FLOAT dx = FXSYS_fabs(Item1.m_OriginX - Item2.m_OriginX);
659             FX_FLOAT dy = FXSYS_fabs(Item1.m_OriginY - Item2.m_OriginY);
660             return dx >= dy ? WritingMode_LRTB : WritingMode_TBRL;
661         } else {
662             if(m_WritingMode != WritingMode_UNKNOW) {
663                 return m_WritingMode;
664             }
665         }
666     }
667     if(pPreObj) {
668         FX_FLOAT threshold = rcCurObj.Width() / 4;
669         if(m_WritingMode == WritingMode_LRTB) {
670             if(FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) < threshold * 2
671                     && FXSYS_fabs(pPreObj->m_Top - pCurObj->m_Top) < threshold * 2) {
672                 return m_WritingMode;
673             }
674             FX_FLOAT mid = (pCurObj->m_Bottom + pCurObj->m_Top) / 2;
675             if(mid > pPreObj->m_Bottom && mid < pPreObj->m_Top && pCurObj->m_Right > pPreObj->m_Right) {
676                 return m_WritingMode;
677             }
678         } else if(m_WritingMode == WritingMode_TBRL) {
679             if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) < threshold * 2
680                     && FXSYS_fabs(pPreObj->m_Right - pCurObj->m_Right) < threshold * 2) {
681                 return m_WritingMode;
682             }
683             FX_FLOAT mid = (pCurObj->m_Right + pCurObj->m_Left) / 2;
684             if(mid > pPreObj->m_Left && mid < pPreObj->m_Right && pCurObj->m_Bottom < pPreObj->m_Bottom) {
685                 return m_WritingMode;
686             }
687         }
688         if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) < threshold &&
689                 FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) > threshold * 2) {
690             return WritingMode_TBRL;
691         }
692         if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) > threshold &&
693                 FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) < threshold * 2) {
694             return WritingMode_LRTB;
695         }
696         int count = 0;
697         if(pPreObj->m_Type == PDFPAGE_TEXT) {
698             CPDF_TextObject* ptextObj = (CPDF_TextObject* )pCurObj;
699             count = ptextObj->CountItems();
700         }
701         if(pPreObj->m_Type != PDFPAGE_TEXT || count == 1) {
702             if(pCurObj->m_Left > pPreObj->m_Right) {
703                 FX_FLOAT mid = (pCurObj->m_Top + pCurObj->m_Bottom) / 2;
704                 if(mid < pPreObj->m_Top && mid > pPreObj->m_Bottom) {
705                     return WritingMode_LRTB;
706                 }
707             }
708             if(pCurObj->m_Top < pPreObj->m_Bottom) {
709                 FX_FLOAT mid = (pCurObj->m_Left + pCurObj->m_Right) / 2;
710                 if(mid < pPreObj->m_Right && mid > pPreObj->m_Left) {
711                     return WritingMode_TBRL;
712                 }
713             }
714         }
715     }
716     return WritingMode_UNKNOW;
717 }
718 LayoutStatus CPDF_AutoReflowLayoutProvider::StartLoad(IFX_Pause* pPause)
719 {
720     m_pPause = pPause;
721     m_pRoot = new CPDF_AutoReflowElement(LayoutDocument);
722     m_Step = 0;
723     return Continue();
724 }
725 LayoutStatus CPDF_AutoReflowLayoutProvider::Continue()
726 {
727     GenerateStructTree();
728     return m_Status;
729 }
730 int     CPDF_AutoReflowLayoutProvider::GetPosition()
731 {
732     if(m_Step == 0) {
733         return 0;
734     } else {
735         return m_Step * 100 / AUTOREFLOW_STEP_REMOVEDATA;
736     }
737 }
738 FX_FLOAT CPDF_AutoReflowLayoutProvider::GetObjMinCell(CPDF_PageObject* pObj)
739 {
740     if(!pObj) {
741         return 0;
742     }
743     if(pObj->m_Type != PDFPAGE_TEXT) {
744         CFX_AffineMatrix matrix;
745         FX_RECT rect = pObj->GetBBox(&matrix);
746         return (FX_FLOAT)(rect.Width());
747     }
748     CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj;
749     int count = pTextObj->CountItems();
750     for(int i = 0; i < count; i++) {
751         CPDF_TextObjectItem Item;
752         pTextObj->GetItemInfo(i, &Item);
753         if(Item.m_CharCode == -1) {
754             continue;
755         }
756         if((Item.m_CharCode > 47 && Item.m_CharCode < 58) || (Item.m_CharCode > 64 && Item.m_CharCode < 91)
757                 || (Item.m_CharCode > 96 && Item.m_CharCode < 123)) {
758             continue;
759         }
760         if(Item.m_CharCode > 127 || (Item.m_CharCode > 32 && Item.m_CharCode < 35) || Item.m_CharCode == 37 ||
761                 (Item.m_CharCode > 38 && Item.m_CharCode < 42) || Item.m_CharCode == 44 || Item.m_CharCode == 46 ||
762                 Item.m_CharCode == 58 || Item.m_CharCode == 59 || Item.m_CharCode == 63 || Item.m_CharCode == 93) {
763             if(i == count - 1) {
764                 CFX_AffineMatrix matrix;
765                 FX_RECT rect = pObj->GetBBox(&matrix);
766                 return (FX_FLOAT)(rect.Width());
767             } else {
768                 pTextObj->GetItemInfo(i + 1, &Item);
769                 return Item.m_OriginX;
770             }
771         }
772         return Item.m_OriginX;
773     }
774     CFX_AffineMatrix matrix;
775     FX_RECT rect = pObj->GetBBox(&matrix);
776     return (FX_FLOAT)(rect.Width());
777 }