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)
9int 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}
56void 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}
101IPDF_LayoutProvider* IPDF_LayoutProvider::Create_LayoutProvider_AutoReflow(CPDF_PageObjects* pPage, FX_BOOL bReadOrder)
102{
103    return FX_NEW CPDF_AutoReflowLayoutProvider(pPage, bReadOrder);
104}
105CPDF_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}
114CPDF_AutoReflowElement::~CPDF_AutoReflowElement()
115{
116    m_ChildArray.RemoveAll();
117    m_ObjArray.RemoveAll();
118}
119int	CPDF_AutoReflowElement::CountAttrValues(LayoutAttr attr_type)
120{
121    return 1;
122}
123LayoutEnum CPDF_AutoReflowElement::GetEnumAttr(LayoutAttr attr_type, int index )
124{
125    return LayoutInvalid;
126}
127FX_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}
136FX_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
144CPDF_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}
158CPDF_AutoReflowLayoutProvider::~CPDF_AutoReflowLayoutProvider()
159{
160    m_pPDFPage = NULL;
161    ReleaseElm(m_pRoot);
162}
163void 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}
175void 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}
185void 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}
235void 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}
273void 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}
416void CPDF_AutoReflowLayoutProvider::ProcessObj(CFX_PtrArray& cellArray, CPDF_PageObject* pObj, CFX_AffineMatrix matrix)
417{
418}
419FX_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}
482void 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}
584FX_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}
592FX_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}
600int CPDF_AutoReflowLayoutProvider:: GetRectWidth(FX_RECT rect)
601{
602    if(m_WritingMode == WritingMode_TBRL) {
603        return rect.Height();
604    }
605    return rect.Width();
606}
607int CPDF_AutoReflowLayoutProvider:: GetRectHeight(FX_RECT rect)
608{
609    if(m_WritingMode == WritingMode_TBRL) {
610        return rect.Width();
611    }
612    return rect.Height();
613}
614int CPDF_AutoReflowLayoutProvider:: GetRectStart(FX_RECT rect)
615{
616    if(m_WritingMode == WritingMode_TBRL) {
617        return rect.top;
618    }
619    return rect.left;
620}
621int CPDF_AutoReflowLayoutProvider:: GetRectEnd(FX_RECT rect)
622{
623    if(m_WritingMode == WritingMode_TBRL) {
624        return rect.bottom;
625    }
626    return rect.right;
627}
628int CPDF_AutoReflowLayoutProvider:: GetRectTop(FX_RECT rect)
629{
630    if(m_WritingMode == WritingMode_TBRL) {
631        return rect.right;
632    }
633    return rect.top;
634}
635int CPDF_AutoReflowLayoutProvider:: GetRectBottom(FX_RECT rect)
636{
637    if(m_WritingMode == WritingMode_TBRL) {
638        return rect.left;
639    }
640    return rect.bottom;
641}
642int 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}
719LayoutStatus 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}
729LayoutStatus CPDF_AutoReflowLayoutProvider::Continue()
730{
731    GenerateStructTree();
732    return m_Status;
733}
734int	CPDF_AutoReflowLayoutProvider::GetPosition()
735{
736    if(m_Step == 0) {
737        return 0;
738    } else {
739        return m_Step * 100 / AUTOREFLOW_STEP_REMOVEDATA;
740    }
741}
742FX_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}
782