Fix warnings in android build, fix font rendering issue, fix issue 357588: wrong...
[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 FX_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 = NULL;
255         pCurrElm = FX_NEW CPDF_AutoReflowElement(LayoutParagraph, pParent);
256         if(pCurrElm->GetType() == LayoutParagraph && plastCell) {
257             int SpaceBefore = 0;
258             if(pCell->m_CellWritingMode != plastCell->m_CellWritingMode ) {
259                 SpaceBefore = 20;
260             } else if(pCell->m_CellWritingMode == WritingMode_LRTB) {
261                 SpaceBefore = plastCell->m_BBox.bottom - pCell->m_BBox.top;
262             } else if(pCell->m_CellWritingMode == WritingMode_TBRL) {
263                 SpaceBefore = plastCell->m_BBox.left - pCell->m_BBox.right;
264             }
265             if(SpaceBefore > 0) {
266                 pCurrElm->m_SpaceBefore = SpaceBefore > 50 ? 50.0f : SpaceBefore;
267             }
268         }
269         AddObjectArray(pCurrElm, pCell->m_ObjList);
270         plastCell = pCell;
271     }
272 }
273 void CPDF_AutoReflowLayoutProvider::GenerateParagraph(CFX_PtrArray& cellArray)
274 {
275     int count = cellArray.GetSize();
276     if(count <= 1) {
277         return;
278     }
279     CRF_CELL* plastCell = (CRF_CELL*)cellArray.GetAt(0);
280     if(plastCell->m_BBox.Height() > plastCell->m_BBox.Width()) {
281         m_WritingMode = WritingMode_TBRL;
282     } else {
283         m_WritingMode = WritingMode_LRTB;
284     }
285     FX_BOOL bEnforce = FALSE;
286     int i = 0;
287     for(i = 1; i < count; i++) {
288         CRF_CELL* pCell = (CRF_CELL*)cellArray.GetAt(i);
289         if(!pCell) {
290             continue;
291         }
292         int c = pCell->m_ObjList.GetCount();
293         FX_BOOL bMerge = FALSE;
294         FX_POSITION pos1 = plastCell->m_ObjList.GetTailPosition();
295         CPDF_PageObject* pLastObj = (CPDF_PageObject*)plastCell->m_ObjList.GetPrev(pos1);
296         pos1 = pCell->m_ObjList.GetHeadPosition();
297         CPDF_PageObject* pCurObj = (CPDF_PageObject*)pCell->m_ObjList.GetNext(pos1);
298         int WritingMode = GetRectEnd(pCell->m_BBox);
299         if(pCell->m_CellWritingMode == WritingMode_UNKNOW) {
300             if(pCell->m_BBox.Height() > pCell->m_BBox.Width()) {
301                 pCell->m_CellWritingMode = WritingMode_TBRL;
302             } else {
303                 pCell->m_CellWritingMode = WritingMode_LRTB;
304             }
305         }
306         WritingMode = pCell->m_CellWritingMode;
307         if(WritingMode == WritingMode_LRTB && (m_Style.m_Language & LP_Lang_ChinesePRC || m_Style.m_Language & LP_Lang_ChineseTaiwan
308                                                || m_Style.m_Language & LP_Lang_Japanese || m_Style.m_Language & LP_Lang_Korean)) {
309             if(pCurObj->m_Type == PDFPAGE_TEXT) {
310                 CPDF_TextObject* pText;
311                 pText = (CPDF_TextObject*)pCurObj;
312                 if(pText->CountItems()) {
313                     CPDF_TextObjectItem item;
314                     pText->GetItemInfo(0, &item);
315                     CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
316                     FX_WCHAR unicode = str.GetAt(0);
317                     if(unicode == 32) {
318                         plastCell = pCell;
319                         bMerge = FALSE;
320                         bEnforce = FALSE;
321                         continue;
322                     }
323                 }
324             }
325         }
326         if(m_WritingMode == WritingMode) {
327             if(bEnforce) {
328                 bMerge = FALSE;
329                 bEnforce = FALSE;
330                 if(pCurObj->m_Type == PDFPAGE_TEXT) {
331                     CPDF_TextObject* pText;
332                     pText = (CPDF_TextObject*)pCurObj;
333                     if(pText->CountItems()) {
334                         CPDF_TextObjectItem item;
335                         pText->GetItemInfo(0, &item);
336                         CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
337                         FX_WCHAR unicode = str.GetAt(0);
338                         if(unicode > 96 && unicode < 123) {
339                             bMerge = TRUE;
340                         }
341                     }
342                 } else {
343                     CPDF_ImageObject* pImage = (CPDF_ImageObject*)pCurObj;
344                     FX_RECT imageBBox = pImage->GetBBox(&m_PDFDisplayMatrix);
345                     if(GetRectEnd(plastCell->m_BBox) - GetRectEnd(pCell->m_BBox) < GetRectWidth(imageBBox)) {
346                         bMerge = TRUE;
347                     }
348                 }
349             } else {
350                 if(!approachto(GetRectStart(pCell->m_BBox), GetRectStart(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) / 4)) {
351                     if(approachto(GetRectStart(plastCell->m_BBox), GetRectStart(pCell->m_BBox), GetRectHeight(pCell->m_BBox) * 2.3) &&
352                             GetRectStart(plastCell->m_BBox) - GetRectStart(pCell->m_BBox) > 0) {
353                         if(pCurObj->m_Type == PDFPAGE_TEXT || pLastObj->m_Type == PDFPAGE_TEXT) {
354                             CPDF_TextObject* pText;
355                             if(pCurObj->m_Type == PDFPAGE_TEXT) {
356                                 pText = (CPDF_TextObject*)pCurObj;
357                             } else {
358                                 pText = (CPDF_TextObject*)pLastObj;
359                             }
360                             CPDF_TextObjectItem item;
361                             pText->GetItemInfo(0, &item);
362                             CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
363                             FX_WCHAR unicode = str.GetAt(0);
364                             if(unicode > 255) {
365                                 bMerge = TRUE;
366                             }
367                         }
368                     }
369                 } else if(!approachto(GetRectEnd(pCell->m_BBox), GetRectEnd(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) * 3)) {
370                     FX_RECT rect = pLastObj->GetBBox(&m_PDFDisplayMatrix);
371                     if(approachto(GetRectStart(pCell->m_BBox), GetRectStart(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) / 4)) {
372                         if(GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) > 0) {
373                             bMerge = TRUE;
374                             bEnforce = TRUE;
375                         } else if(GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) <= 0 &&
376                                   GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) > GetRectHeight(pCell->m_BBox) * -3) {
377                             if(pCurObj->m_Type == PDFPAGE_TEXT) {
378                                 CPDF_TextObject* pText = (CPDF_TextObject*)pCurObj;
379                                 CPDF_TextObjectItem item;
380                                 pText->GetItemInfo(0, &item);
381                                 CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
382                                 FX_WCHAR unicode = str.GetAt(0);
383                                 if(unicode > 96 && unicode < 123) {
384                                     bMerge = TRUE;
385                                 }
386                             }
387                         }
388                     }
389                 } else {
390                     bMerge = TRUE;
391                 }
392             }
393         } else {
394             m_WritingMode = WritingMode;
395             bEnforce = FALSE;
396         }
397         if(bMerge) {
398             if(GetRectEnd(plastCell->m_BBox) - GetRectEnd(pCell->m_BBox) > 30) {
399                 bEnforce = TRUE;
400             }
401             FX_POSITION pos = pCell->m_ObjList.GetHeadPosition();
402             while(pos) {
403                 plastCell->m_ObjList.AddTail(pCell->m_ObjList.GetNext(pos));
404             }
405             plastCell->m_BBox.Union(pCell->m_BBox);
406             pCell->m_ObjList.RemoveAll();
407             delete pCell;
408             cellArray.RemoveAt(i);
409             i--;
410             count--;
411         } else {
412             plastCell = pCell;
413         }
414     }
415 }
416 void CPDF_AutoReflowLayoutProvider::ProcessObj(CFX_PtrArray& cellArray, CPDF_PageObject* pObj, CFX_AffineMatrix matrix)
417 {
418 }
419 FX_INT32 CPDF_AutoReflowLayoutProvider::LogicPreObj(CPDF_PageObject* pObj)
420 {
421     CPDF_PageObject* pPreObj = m_pPreObj;
422     m_pPreObj = pObj;
423     if(!pPreObj) {
424         return 0;
425     }
426     if(pPreObj->m_Type != pObj->m_Type) {
427         return 0;
428     }
429     CFX_FloatRect rcCurObj(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
430     CFX_FloatRect rcPreObj(pPreObj->m_Left, pPreObj->m_Bottom, pPreObj->m_Right, pPreObj->m_Top);
431     if(pObj->m_Type == PDFPAGE_IMAGE) {
432         if(rcPreObj.Contains(rcCurObj)) {
433             return 2;
434         }
435         if(rcCurObj.Contains(rcPreObj)) {
436             return 2;
437         }
438         return 0;
439     }
440     if(pObj->m_Type == PDFPAGE_TEXT) {
441         if(!((rcPreObj.bottom > rcCurObj.top) || (rcPreObj.top < rcCurObj.bottom))) {
442             FX_FLOAT height = FX_MIN(rcPreObj.Height(), rcCurObj.Height());
443             if((rcCurObj.left - rcPreObj.right) > height / 3) {
444                 return 3;
445             }
446         }
447         if(FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) >= 2 || FXSYS_fabs(rcPreObj.Height() - rcCurObj.Height()) >= 2 ) {
448             return 0;
449         }
450         CPDF_TextObject* pPreTextObj = (CPDF_TextObject*)pPreObj;
451         CPDF_TextObject* pCurTextObj = (CPDF_TextObject*)pObj;
452         int nPreCount = pPreTextObj->CountItems();
453         int nCurCount = pCurTextObj->CountItems();
454         if (nPreCount != nCurCount) {
455             return 0;
456         }
457         FX_BOOL bSame = TRUE;
458         for (int i = 0; i < nPreCount; i++) {
459             CPDF_TextObjectItem itemPer, itemCur;
460             pPreTextObj->GetItemInfo(i, &itemPer);
461             pCurTextObj->GetItemInfo(i, &itemCur);
462             if (itemCur.m_CharCode != itemPer.m_CharCode) {
463                 return 0;
464             }
465             if (itemCur.m_OriginX != itemPer.m_OriginX) {
466                 bSame = FALSE;
467             }
468             if (itemCur.m_OriginY != itemPer.m_OriginY) {
469                 bSame = FALSE;
470             }
471         }
472         if(rcPreObj.left == rcCurObj.left && rcPreObj.top == rcCurObj.top) {
473             return 1;
474         }
475         if(FXSYS_fabs(rcPreObj.left - rcCurObj.left) < rcPreObj.Width() / 3
476                 && FXSYS_fabs(rcPreObj.top - rcCurObj.top) < rcPreObj.Height() / 3) {
477             return 2;
478         }
479     }
480     return 0;
481 }
482 void CPDF_AutoReflowLayoutProvider::GenerateLine(CFX_PtrArray& cellArray)
483 {
484     CRF_CELL* pCell = NULL;
485     CFX_AffineMatrix matrix;
486     FX_POSITION pos = m_pPDFPage->GetFirstObjectPosition();
487     if(!pos) {
488         return;
489     }
490     FX_FLOAT PDFWidth = m_pPDFPage->GetPageWidth();
491     FX_FLOAT PDFHeight = m_pPDFPage->GetPageHeight();
492     m_pPDFPage->GetDisplayMatrix(m_PDFDisplayMatrix, 0, 0, (int)PDFWidth, (int)PDFHeight, 0);
493     CPDF_PageObject* pPerObj = NULL;
494     int a = 0;
495     CFX_FloatRect pageBBox = m_pPDFPage->m_BBox;
496     FX_FLOAT PrevX = 0 , PrevY = 0, PosX, PosY;
497     while(pos) {
498         CPDF_PageObject* pObj = m_pPDFPage->GetNextObject(pos);
499         if(!pObj || pObj->m_Type == PDFPAGE_PATH) {
500             continue;
501         }
502         int logic = LogicPreObj(pObj);
503         if(logic == 2) {
504             if(pCell) {
505                 pCell->m_ObjList.SetAt(pCell->m_ObjList.GetTailPosition(), pObj);
506             }
507             continue;
508         }
509         if (pObj->m_Type == PDFPAGE_TEXT) {
510             CPDF_TextObject* pTextObj = (CPDF_TextObject*)pObj;
511             int textmode = pTextObj->m_TextState.GetObject()->m_TextMode;
512             if(m_Style.m_bIgnoreInvisibleText && pTextObj->m_TextState.GetObject()->m_TextMode == 3) {
513                 continue;
514             }
515             PosX = pTextObj->GetPosX();
516             PosY = pTextObj->GetPosY();
517             m_PDFDisplayMatrix.Transform(PosX, PosY);
518         } else {
519             PosX = 0;
520             PosY = 0;
521         }
522         FX_BOOL bNewLine = TRUE;
523         FX_RECT ObjBBox = pObj->GetBBox(&m_PDFDisplayMatrix);
524         if(ObjBBox.left > PDFWidth || ObjBBox.right < 0 ||
525                 ObjBBox.bottom < 0 || ObjBBox.top > PDFHeight) {
526             continue;
527         }
528         if(ObjBBox.IsEmpty()) {
529             continue;
530         }
531         a++;
532         if(!pCell) {
533             bNewLine = TRUE;
534             m_WritingMode = GetWritingMode(NULL, pObj);
535         } else {
536             int WritingMode = GetWritingMode(pPerObj, pObj);
537             if(m_WritingMode == WritingMode || m_WritingMode == WritingMode_UNKNOW || WritingMode == WritingMode_UNKNOW) {
538                 if(WritingMode != WritingMode_UNKNOW) {
539                     m_WritingMode = WritingMode;
540                 }
541                 if(m_WritingMode == WritingMode_TBRL) {
542                     if(!(GetRectBottom(ObjBBox) > GetRectTop(pCell->m_BBox) ||
543                             GetRectTop(ObjBBox) < GetRectBottom(pCell->m_BBox))) {
544                         bNewLine = FALSE;
545                     }
546                 } else {
547                     if(!(GetRectBottom(ObjBBox) < GetRectTop(pCell->m_BBox) ||
548                             GetRectTop(ObjBBox) > GetRectBottom(pCell->m_BBox))) {
549                         bNewLine = FALSE;
550                     }
551                     if (pObj->m_Type == PDFPAGE_TEXT) {
552                         if(FXSYS_fabs(PrevY - PosY) < 1 ) {
553                             bNewLine = FALSE;
554                         }
555                     }
556                 }
557             } else {
558                 m_WritingMode = WritingMode;
559             }
560         }
561         pPerObj = pObj;
562         if(bNewLine) {
563             int c = pCell ? pCell->m_ObjList.GetCount() : 0;
564             pCell = FX_NEW CRF_CELL;
565             pCell->m_CellWritingMode = m_WritingMode;
566             pCell->m_BBox = ObjBBox;
567             if(pObj->m_Type == PDFPAGE_TEXT) {
568                 FX_FLOAT x = ((CPDF_TextObject*)pObj)->GetPosX(), y = ((CPDF_TextObject*)pObj)->GetPosY();
569                 m_PDFDisplayMatrix.Transform(x, y);
570                 if(x < ObjBBox.left) {
571                     pCell->m_BBox.left = (int)x;
572                 }
573             }
574             pCell->m_ObjList.AddTail(pObj);
575             cellArray.Add(pCell);
576         } else {
577             pCell->m_ObjList.AddTail(pObj);
578             pCell->m_BBox.Union(ObjBBox);
579         }
580         PrevX = PosX;
581         PrevY = PosY;
582     }
583 }
584 FX_FLOAT CPDF_AutoReflowLayoutProvider::GetLayoutOrderHeight(CPDF_PageObject* pCurObj)
585 {
586     CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top);
587     if (m_WritingMode == WritingMode_TBRL) {
588         return rcCurObj.Width();
589     }
590     return rcCurObj.Height();
591 }
592 FX_FLOAT CPDF_AutoReflowLayoutProvider::GetLayoutOrderWidth(CPDF_PageObject* pCurObj)
593 {
594     CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top);
595     if (m_WritingMode == WritingMode_TBRL) {
596         return rcCurObj.Height();
597     }
598     return rcCurObj.Width();
599 }
600 int CPDF_AutoReflowLayoutProvider:: GetRectWidth(FX_RECT rect)
601 {
602     if(m_WritingMode == WritingMode_TBRL) {
603         return rect.Height();
604     }
605     return rect.Width();
606 }
607 int CPDF_AutoReflowLayoutProvider:: GetRectHeight(FX_RECT rect)
608 {
609     if(m_WritingMode == WritingMode_TBRL) {
610         return rect.Width();
611     }
612     return rect.Height();
613 }
614 int CPDF_AutoReflowLayoutProvider:: GetRectStart(FX_RECT rect)
615 {
616     if(m_WritingMode == WritingMode_TBRL) {
617         return rect.top;
618     }
619     return rect.left;
620 }
621 int CPDF_AutoReflowLayoutProvider:: GetRectEnd(FX_RECT rect)
622 {
623     if(m_WritingMode == WritingMode_TBRL) {
624         return rect.bottom;
625     }
626     return rect.right;
627 }
628 int CPDF_AutoReflowLayoutProvider:: GetRectTop(FX_RECT rect)
629 {
630     if(m_WritingMode == WritingMode_TBRL) {
631         return rect.right;
632     }
633     return rect.top;
634 }
635 int CPDF_AutoReflowLayoutProvider:: GetRectBottom(FX_RECT rect)
636 {
637     if(m_WritingMode == WritingMode_TBRL) {
638         return rect.left;
639     }
640     return rect.bottom;
641 }
642 int CPDF_AutoReflowLayoutProvider::GetWritingMode(CPDF_PageObject* pPreObj, CPDF_PageObject* pCurObj)
643 {
644     CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top);
645     if(pCurObj->m_Type == PDFPAGE_TEXT) {
646         CPDF_TextObject* ptextObj = (CPDF_TextObject* )pCurObj;
647         int count = ptextObj->CountItems();
648         if(count > 1) {
649             CPDF_TextObjectItem Item1, Item2;
650             ptextObj->GetItemInfo(0, &Item1);
651             ptextObj->GetItemInfo(count - 1, &Item2);
652             if(Item2.m_CharCode == -1 && count > 2) {
653                 ptextObj->GetItemInfo(2, &Item2);
654             }
655             CFX_AffineMatrix textMatrix;
656             ptextObj->GetTextMatrix(&textMatrix);
657             textMatrix.Transform(Item1.m_OriginX, Item1.m_OriginY);
658             textMatrix.Transform(Item2.m_OriginX, Item2.m_OriginY);
659             FX_FLOAT dx = FXSYS_fabs(Item1.m_OriginX - Item2.m_OriginX);
660             FX_FLOAT dy = FXSYS_fabs(Item1.m_OriginY - Item2.m_OriginY);
661             return dx >= dy ? WritingMode_LRTB : WritingMode_TBRL;
662         } else {
663             if(m_WritingMode != WritingMode_UNKNOW) {
664                 return m_WritingMode;
665             }
666         }
667     }
668     if(pPreObj) {
669         FX_FLOAT threshold = rcCurObj.Width() / 4;
670         if(m_WritingMode == WritingMode_LRTB) {
671             if(FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) < threshold * 2
672                     && FXSYS_fabs(pPreObj->m_Top - pCurObj->m_Top) < threshold * 2) {
673                 return m_WritingMode;
674             }
675             FX_FLOAT mid = (pCurObj->m_Bottom + pCurObj->m_Top) / 2;
676             if(mid > pPreObj->m_Bottom && mid < pPreObj->m_Top && pCurObj->m_Right > pPreObj->m_Right) {
677                 return m_WritingMode;
678             }
679         } else if(m_WritingMode == WritingMode_TBRL) {
680             if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) < threshold * 2
681                     && FXSYS_fabs(pPreObj->m_Right - pCurObj->m_Right) < threshold * 2) {
682                 return m_WritingMode;
683             }
684             FX_FLOAT mid = (pCurObj->m_Right + pCurObj->m_Left) / 2;
685             if(mid > pPreObj->m_Left && mid < pPreObj->m_Right && pCurObj->m_Bottom < pPreObj->m_Bottom) {
686                 return m_WritingMode;
687             }
688         }
689         if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) < threshold &&
690                 FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) > threshold * 2) {
691             return WritingMode_TBRL;
692         }
693         if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) > threshold &&
694                 FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) < threshold * 2) {
695             return WritingMode_LRTB;
696         }
697         int count = 0;
698         if(pPreObj->m_Type == PDFPAGE_TEXT) {
699             CPDF_TextObject* ptextObj = (CPDF_TextObject* )pCurObj;
700             count = ptextObj->CountItems();
701         }
702         if(pPreObj->m_Type != PDFPAGE_TEXT || count == 1) {
703             if(pCurObj->m_Left > pPreObj->m_Right) {
704                 FX_FLOAT mid = (pCurObj->m_Top + pCurObj->m_Bottom) / 2;
705                 if(mid < pPreObj->m_Top && mid > pPreObj->m_Bottom) {
706                     return WritingMode_LRTB;
707                 }
708             }
709             if(pCurObj->m_Top < pPreObj->m_Bottom) {
710                 FX_FLOAT mid = (pCurObj->m_Left + pCurObj->m_Right) / 2;
711                 if(mid < pPreObj->m_Right && mid > pPreObj->m_Left) {
712                     return WritingMode_TBRL;
713                 }
714             }
715         }
716     }
717     return WritingMode_UNKNOW;
718 }
719 LayoutStatus CPDF_AutoReflowLayoutProvider::StartLoad(IFX_Pause* pPause)
720 {
721     m_pPause = pPause;
722     m_pRoot = FX_NEW CPDF_AutoReflowElement(LayoutDocument);
723     if(!m_pRoot) {
724         return LayoutError;
725     }
726     m_Step = 0;
727     return Continue();
728 }
729 LayoutStatus CPDF_AutoReflowLayoutProvider::Continue()
730 {
731     GenerateStructTree();
732     return m_Status;
733 }
734 int     CPDF_AutoReflowLayoutProvider::GetPosition()
735 {
736     if(m_Step == 0) {
737         return 0;
738     } else {
739         return m_Step * 100 / AUTOREFLOW_STEP_REMOVEDATA;
740     }
741 }
742 FX_FLOAT CPDF_AutoReflowLayoutProvider::GetObjMinCell(CPDF_PageObject* pObj)
743 {
744     if(!pObj) {
745         return 0;
746     }
747     if(pObj->m_Type != PDFPAGE_TEXT) {
748         CFX_AffineMatrix matrix;
749         FX_RECT rect = pObj->GetBBox(&matrix);
750         return (FX_FLOAT)(rect.Width());
751     }
752     CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj;
753     int count = pTextObj->CountItems();
754     for(int i = 0; i < count; i++) {
755         CPDF_TextObjectItem Item;
756         pTextObj->GetItemInfo(i, &Item);
757         if(Item.m_CharCode == -1) {
758             continue;
759         }
760         if((Item.m_CharCode > 47 && Item.m_CharCode < 58) || (Item.m_CharCode > 64 && Item.m_CharCode < 91)
761                 || (Item.m_CharCode > 96 && Item.m_CharCode < 123)) {
762             continue;
763         }
764         if(Item.m_CharCode > 127 || (Item.m_CharCode > 32 && Item.m_CharCode < 35) || Item.m_CharCode == 37 ||
765                 (Item.m_CharCode > 38 && Item.m_CharCode < 42) || Item.m_CharCode == 44 || Item.m_CharCode == 46 ||
766                 Item.m_CharCode == 58 || Item.m_CharCode == 59 || Item.m_CharCode == 63 || Item.m_CharCode == 93) {
767             if(i == count - 1) {
768                 CFX_AffineMatrix matrix;
769                 FX_RECT rect = pObj->GetBBox(&matrix);
770                 return (FX_FLOAT)(rect.Width());
771             } else {
772                 pTextObj->GetItemInfo(i + 1, &Item);
773                 return Item.m_OriginX;
774             }
775         }
776         return Item.m_OriginX;
777     }
778     CFX_AffineMatrix matrix;
779     FX_RECT rect = pObj->GetBBox(&matrix);
780     return (FX_FLOAT)(rect.Width());
781 }