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 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 }
    782