Home | History | Annotate | Download | only in reflow
      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 FX_INT32 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 }
    778