// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "autoreflow.h" #define approachto(a,b,c) (FXSYS_fabs((float)((a)-(b)))>(c) ? 0 : 1) int FPDF_ProcessInterObj(const CPDF_PageObject* pPrevObj, const CPDF_PageObject* pObj) { CFX_AffineMatrix matrix; FX_RECT PreRect = pPrevObj->GetBBox(&matrix); FX_RECT rect = pObj->GetBBox(&matrix); int flag = 0; if(PreRect.top > rect.bottom) { flag = 0; } else if(rect.top > PreRect.bottom) { flag = 1; } else if(PreRect.right < rect.left) { flag = 0; } else if(PreRect.left > rect.right) { flag = 1; } else if(pObj->m_Type != PDFPAGE_TEXT) { flag = 1; } else if(pPrevObj->m_Type != PDFPAGE_TEXT) { flag = 0; } else { if((PreRect.top < rect.top && PreRect.bottom > rect.bottom) || (PreRect.top > rect.top && PreRect.bottom < rect.bottom)) { if(PreRect.left > rect.left) { flag = 1; } else { flag = 0; } } else { CPDF_TextObject* pPrevTextObj = (CPDF_TextObject* )pPrevObj; CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj; CPDF_TextObjectItem item, prevItem; pPrevTextObj->GetItemInfo(0, &prevItem); pTextObj->GetItemInfo(0, &item); CFX_AffineMatrix TextMatrix; pTextObj->GetTextMatrix(&TextMatrix); FX_FLOAT originX, originY, prevOriginX, preOriginY; TextMatrix.Transform(item.m_OriginX, item.m_OriginY, originX, originY); pPrevTextObj->GetTextMatrix(&TextMatrix); TextMatrix.Transform(prevItem.m_OriginX, prevItem.m_OriginY, prevOriginX, preOriginY); if(preOriginY > originY) { flag = 0; } else { flag = 1; } } } return flag; } void CPDF_AutoReflowLayoutProvider::Conver2AppreceOrder(const CPDF_PageObjects* pStreamOrderObjs, CPDF_PageObjects* pAppraceOrderObjs) { FX_POSITION pos = pStreamOrderObjs->GetFirstObjectPosition(); CFX_AffineMatrix matrix; while(pos) { CPDF_PageObject* pObj = pStreamOrderObjs->GetNextObject(pos); CFX_AffineMatrix matrix; if(pObj->m_Type != PDFPAGE_TEXT) { continue; } FX_POSITION pos1 = pAppraceOrderObjs->GetLastObjectPosition(); while(pos1) { CPDF_PageObject* pTempObj = pAppraceOrderObjs->GetPrevObject(pos1); if(FPDF_ProcessInterObj(pObj, pTempObj) == 1) { if(!pos1) { pos1 = pAppraceOrderObjs->GetFirstObjectPosition(); } else { pAppraceOrderObjs->GetNextObject(pos1); } break; } } pAppraceOrderObjs->InsertObject(pos1, pObj); } pos = pStreamOrderObjs->GetFirstObjectPosition(); while(pos) { CPDF_PageObject* pObj = pStreamOrderObjs->GetNextObject(pos); if(pObj->m_Type != PDFPAGE_IMAGE) { continue; } FX_POSITION pos1 = pAppraceOrderObjs->GetLastObjectPosition(); while(pos1) { CPDF_PageObject* pTempObj = pAppraceOrderObjs->GetPrevObject(pos1); if(FPDF_ProcessInterObj(pObj, pTempObj) == 1) { if(!pos1) { pos1 = pAppraceOrderObjs->GetFirstObjectPosition(); } else { pAppraceOrderObjs->GetNextObject(pos1); } break; } } pAppraceOrderObjs->InsertObject(pos1, pObj); } } IPDF_LayoutProvider* IPDF_LayoutProvider::Create_LayoutProvider_AutoReflow(CPDF_PageObjects* pPage, FX_BOOL bReadOrder) { return new CPDF_AutoReflowLayoutProvider(pPage, bReadOrder); } CPDF_AutoReflowElement::CPDF_AutoReflowElement(LayoutType layoutType , CPDF_AutoReflowElement* pParent) { m_ElmType = layoutType; m_pParentElm = pParent; if(pParent) { pParent->m_ChildArray.Add(this); } m_SpaceBefore = 0; } CPDF_AutoReflowElement::~CPDF_AutoReflowElement() { m_ChildArray.RemoveAll(); m_ObjArray.RemoveAll(); } int CPDF_AutoReflowElement::CountAttrValues(LayoutAttr attr_type) { return 1; } LayoutEnum CPDF_AutoReflowElement::GetEnumAttr(LayoutAttr attr_type, int index ) { return LayoutInvalid; } FX_FLOAT CPDF_AutoReflowElement::GetNumberAttr(LayoutAttr attr_type, int index ) { switch (attr_type) { case LayoutSpaceBefore: return m_SpaceBefore; default: return 0; } } FX_COLORREF CPDF_AutoReflowElement::GetColorAttr(LayoutAttr attr_type, int index ) { return 0; } #define WritingMode_UNKNOW 0 #define WritingMode_LRTB 1 #define WritingMode_RLTB 2 #define WritingMode_TBRL 3 CPDF_AutoReflowLayoutProvider::CPDF_AutoReflowLayoutProvider(CPDF_PageObjects* pPage, FX_BOOL bReadOrder) { m_pPDFPage = (CPDF_Page*)pPage; FX_FLOAT width = m_pPDFPage->GetPageWidth(); FX_FLOAT height = m_pPDFPage->GetPageHeight(); m_pPDFPage->GetDisplayMatrix(m_PDFDisplayMatrix, 0, 0, (int)(m_pPDFPage->GetPageWidth()), (int)(m_pPDFPage->GetPageHeight()), 0); m_bReadOrder = bReadOrder; m_Status = LayoutReady; m_pRoot = NULL; m_pCurrElm = NULL; m_pPreObj = NULL; m_Step = 0; m_WritingMode = WritingMode_UNKNOW; } CPDF_AutoReflowLayoutProvider::~CPDF_AutoReflowLayoutProvider() { m_pPDFPage = NULL; ReleaseElm(m_pRoot); } void CPDF_AutoReflowLayoutProvider::ReleaseElm(CPDF_AutoReflowElement*& pElm, FX_BOOL bReleaseChildren) { if(bReleaseChildren) { int count = pElm->CountChildren(); for(int i = 0; i < count; i++) { CPDF_AutoReflowElement* pChild = (CPDF_AutoReflowElement*)pElm->GetChild(i); ReleaseElm(pChild); } } delete pElm; pElm = NULL; } void CPDF_AutoReflowLayoutProvider::AddObjectArray(CPDF_AutoReflowElement* pElm, CFX_PtrList& ObjList) { if(!pElm) { return; } FX_POSITION pos = ObjList.GetHeadPosition(); while (pos) { pElm->m_ObjArray.Add((CPDF_PageObject*)ObjList.GetNext(pos)); } } void CPDF_AutoReflowLayoutProvider::GenerateStructTree() { if (m_Step < AUTOREFLOW_STEP_GENERATELINE) { GenerateLine(m_cellArray); if(m_cellArray.GetSize() == 0) { m_Status = LayoutError; return; } if(m_pPause && m_pPause->NeedToPauseNow()) { m_Step = AUTOREFLOW_STEP_GENERATELINE; m_Status = LayoutToBeContinued; return; } } if (m_Step < AUTOREFLOW_STEP_GENERATEParagraph) { GenerateParagraph(m_cellArray); if(m_pPause && m_pPause->NeedToPauseNow()) { m_Step = AUTOREFLOW_STEP_GENERATEParagraph; m_Status = LayoutToBeContinued; return; } } if (m_Step < AUTOREFLOW_STEP_CREATEELEMENT) { CreateElement(); if(m_pPause && m_pPause->NeedToPauseNow()) { m_Step = AUTOREFLOW_STEP_CREATEELEMENT; m_Status = LayoutToBeContinued; return; } } if (m_Step < AUTOREFLOW_STEP_REMOVEDATA) { int count = m_cellArray.GetSize(); for(int i = 0; i < count; i++) { CRF_CELL* pCell = (CRF_CELL*)m_cellArray.GetAt(i); if(pCell) { pCell->m_ObjList.RemoveAll(); delete pCell; } } m_cellArray.RemoveAll(); if(m_pPause && m_pPause->NeedToPauseNow()) { m_Step = AUTOREFLOW_STEP_REMOVEDATA; m_Status = LayoutToBeContinued; return; } } m_Step = AUTOREFLOW_STEP_REMOVEDATA; m_Status = LayoutFinished; return; } void CPDF_AutoReflowLayoutProvider::CreateElement() { int count = m_cellArray.GetSize(); CRF_CELL* plastCell = NULL; CRF_CELL* pCell = NULL; CRF_CELL* pNextCell = NULL; CPDF_AutoReflowElement* pParent = m_pRoot; CPDF_AutoReflowElement* pCurrElm = NULL; int i; for(i = 0; i < count; i++) { pCell = (CRF_CELL*)m_cellArray.GetAt(i); if(!pCell) { continue; } if(i < count - 1) { pNextCell = (CRF_CELL*)m_cellArray.GetAt(i + 1); } else { pNextCell = NULL; } pCurrElm = new CPDF_AutoReflowElement(LayoutParagraph, pParent); if(pCurrElm->GetType() == LayoutParagraph && plastCell) { int SpaceBefore = 0; if(pCell->m_CellWritingMode != plastCell->m_CellWritingMode ) { SpaceBefore = 20; } else if(pCell->m_CellWritingMode == WritingMode_LRTB) { SpaceBefore = plastCell->m_BBox.bottom - pCell->m_BBox.top; } else if(pCell->m_CellWritingMode == WritingMode_TBRL) { SpaceBefore = plastCell->m_BBox.left - pCell->m_BBox.right; } if(SpaceBefore > 0) { pCurrElm->m_SpaceBefore = SpaceBefore > 50 ? 50.0f : SpaceBefore; } } AddObjectArray(pCurrElm, pCell->m_ObjList); plastCell = pCell; } } void CPDF_AutoReflowLayoutProvider::GenerateParagraph(CFX_PtrArray& cellArray) { int count = cellArray.GetSize(); if(count <= 1) { return; } CRF_CELL* plastCell = (CRF_CELL*)cellArray.GetAt(0); if(plastCell->m_BBox.Height() > plastCell->m_BBox.Width()) { m_WritingMode = WritingMode_TBRL; } else { m_WritingMode = WritingMode_LRTB; } FX_BOOL bEnforce = FALSE; int i = 0; for(i = 1; i < count; i++) { CRF_CELL* pCell = (CRF_CELL*)cellArray.GetAt(i); if(!pCell) { continue; } int c = pCell->m_ObjList.GetCount(); FX_BOOL bMerge = FALSE; FX_POSITION pos1 = plastCell->m_ObjList.GetTailPosition(); CPDF_PageObject* pLastObj = (CPDF_PageObject*)plastCell->m_ObjList.GetPrev(pos1); pos1 = pCell->m_ObjList.GetHeadPosition(); CPDF_PageObject* pCurObj = (CPDF_PageObject*)pCell->m_ObjList.GetNext(pos1); int WritingMode = GetRectEnd(pCell->m_BBox); if(pCell->m_CellWritingMode == WritingMode_UNKNOW) { if(pCell->m_BBox.Height() > pCell->m_BBox.Width()) { pCell->m_CellWritingMode = WritingMode_TBRL; } else { pCell->m_CellWritingMode = WritingMode_LRTB; } } WritingMode = pCell->m_CellWritingMode; if(WritingMode == WritingMode_LRTB && (m_Style.m_Language & LP_Lang_ChinesePRC || m_Style.m_Language & LP_Lang_ChineseTaiwan || m_Style.m_Language & LP_Lang_Japanese || m_Style.m_Language & LP_Lang_Korean)) { if(pCurObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* pText; pText = (CPDF_TextObject*)pCurObj; if(pText->CountItems()) { CPDF_TextObjectItem item; pText->GetItemInfo(0, &item); CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode); FX_WCHAR unicode = str.GetAt(0); if(unicode == 32) { plastCell = pCell; bMerge = FALSE; bEnforce = FALSE; continue; } } } } if(m_WritingMode == WritingMode) { if(bEnforce) { bMerge = FALSE; bEnforce = FALSE; if(pCurObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* pText; pText = (CPDF_TextObject*)pCurObj; if(pText->CountItems()) { CPDF_TextObjectItem item; pText->GetItemInfo(0, &item); CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode); FX_WCHAR unicode = str.GetAt(0); if(unicode > 96 && unicode < 123) { bMerge = TRUE; } } } else { CPDF_ImageObject* pImage = (CPDF_ImageObject*)pCurObj; FX_RECT imageBBox = pImage->GetBBox(&m_PDFDisplayMatrix); if(GetRectEnd(plastCell->m_BBox) - GetRectEnd(pCell->m_BBox) < GetRectWidth(imageBBox)) { bMerge = TRUE; } } } else { if(!approachto(GetRectStart(pCell->m_BBox), GetRectStart(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) / 4)) { if(approachto(GetRectStart(plastCell->m_BBox), GetRectStart(pCell->m_BBox), GetRectHeight(pCell->m_BBox) * 2.3) && GetRectStart(plastCell->m_BBox) - GetRectStart(pCell->m_BBox) > 0) { if(pCurObj->m_Type == PDFPAGE_TEXT || pLastObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* pText; if(pCurObj->m_Type == PDFPAGE_TEXT) { pText = (CPDF_TextObject*)pCurObj; } else { pText = (CPDF_TextObject*)pLastObj; } CPDF_TextObjectItem item; pText->GetItemInfo(0, &item); CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode); FX_WCHAR unicode = str.GetAt(0); if(unicode > 255) { bMerge = TRUE; } } } } else if(!approachto(GetRectEnd(pCell->m_BBox), GetRectEnd(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) * 3)) { FX_RECT rect = pLastObj->GetBBox(&m_PDFDisplayMatrix); if(approachto(GetRectStart(pCell->m_BBox), GetRectStart(plastCell->m_BBox), GetRectHeight(pCell->m_BBox) / 4)) { if(GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) > 0) { bMerge = TRUE; bEnforce = TRUE; } else if(GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) <= 0 && GetRectEnd(rect) - GetRectEnd(pCell->m_BBox) > GetRectHeight(pCell->m_BBox) * -3) { if(pCurObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* pText = (CPDF_TextObject*)pCurObj; CPDF_TextObjectItem item; pText->GetItemInfo(0, &item); CFX_WideString str = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode); FX_WCHAR unicode = str.GetAt(0); if(unicode > 96 && unicode < 123) { bMerge = TRUE; } } } } } else { bMerge = TRUE; } } } else { m_WritingMode = WritingMode; bEnforce = FALSE; } if(bMerge) { if(GetRectEnd(plastCell->m_BBox) - GetRectEnd(pCell->m_BBox) > 30) { bEnforce = TRUE; } FX_POSITION pos = pCell->m_ObjList.GetHeadPosition(); while(pos) { plastCell->m_ObjList.AddTail(pCell->m_ObjList.GetNext(pos)); } plastCell->m_BBox.Union(pCell->m_BBox); pCell->m_ObjList.RemoveAll(); delete pCell; cellArray.RemoveAt(i); i--; count--; } else { plastCell = pCell; } } } void CPDF_AutoReflowLayoutProvider::ProcessObj(CFX_PtrArray& cellArray, CPDF_PageObject* pObj, CFX_AffineMatrix matrix) { } FX_INT32 CPDF_AutoReflowLayoutProvider::LogicPreObj(CPDF_PageObject* pObj) { CPDF_PageObject* pPreObj = m_pPreObj; m_pPreObj = pObj; if(!pPreObj) { return 0; } if(pPreObj->m_Type != pObj->m_Type) { return 0; } CFX_FloatRect rcCurObj(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top); CFX_FloatRect rcPreObj(pPreObj->m_Left, pPreObj->m_Bottom, pPreObj->m_Right, pPreObj->m_Top); if(pObj->m_Type == PDFPAGE_IMAGE) { if(rcPreObj.Contains(rcCurObj)) { return 2; } if(rcCurObj.Contains(rcPreObj)) { return 2; } return 0; } if(pObj->m_Type == PDFPAGE_TEXT) { if(!((rcPreObj.bottom > rcCurObj.top) || (rcPreObj.top < rcCurObj.bottom))) { FX_FLOAT height = FX_MIN(rcPreObj.Height(), rcCurObj.Height()); if((rcCurObj.left - rcPreObj.right) > height / 3) { return 3; } } if(FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) >= 2 || FXSYS_fabs(rcPreObj.Height() - rcCurObj.Height()) >= 2 ) { return 0; } CPDF_TextObject* pPreTextObj = (CPDF_TextObject*)pPreObj; CPDF_TextObject* pCurTextObj = (CPDF_TextObject*)pObj; int nPreCount = pPreTextObj->CountItems(); int nCurCount = pCurTextObj->CountItems(); if (nPreCount != nCurCount) { return 0; } FX_BOOL bSame = TRUE; for (int i = 0; i < nPreCount; i++) { CPDF_TextObjectItem itemPer, itemCur; pPreTextObj->GetItemInfo(i, &itemPer); pCurTextObj->GetItemInfo(i, &itemCur); if (itemCur.m_CharCode != itemPer.m_CharCode) { return 0; } if (itemCur.m_OriginX != itemPer.m_OriginX) { bSame = FALSE; } if (itemCur.m_OriginY != itemPer.m_OriginY) { bSame = FALSE; } } if(rcPreObj.left == rcCurObj.left && rcPreObj.top == rcCurObj.top) { return 1; } if(FXSYS_fabs(rcPreObj.left - rcCurObj.left) < rcPreObj.Width() / 3 && FXSYS_fabs(rcPreObj.top - rcCurObj.top) < rcPreObj.Height() / 3) { return 2; } } return 0; } void CPDF_AutoReflowLayoutProvider::GenerateLine(CFX_PtrArray& cellArray) { CRF_CELL* pCell = NULL; CFX_AffineMatrix matrix; FX_POSITION pos = m_pPDFPage->GetFirstObjectPosition(); if(!pos) { return; } FX_FLOAT PDFWidth = m_pPDFPage->GetPageWidth(); FX_FLOAT PDFHeight = m_pPDFPage->GetPageHeight(); m_pPDFPage->GetDisplayMatrix(m_PDFDisplayMatrix, 0, 0, (int)PDFWidth, (int)PDFHeight, 0); CPDF_PageObject* pPerObj = NULL; int a = 0; CFX_FloatRect pageBBox = m_pPDFPage->m_BBox; FX_FLOAT PrevX = 0 , PrevY = 0, PosX, PosY; while(pos) { CPDF_PageObject* pObj = m_pPDFPage->GetNextObject(pos); if(!pObj || pObj->m_Type == PDFPAGE_PATH) { continue; } int logic = LogicPreObj(pObj); if(logic == 2) { if(pCell) { pCell->m_ObjList.SetAt(pCell->m_ObjList.GetTailPosition(), pObj); } continue; } if (pObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* pTextObj = (CPDF_TextObject*)pObj; int textmode = pTextObj->m_TextState.GetObject()->m_TextMode; if(m_Style.m_bIgnoreInvisibleText && pTextObj->m_TextState.GetObject()->m_TextMode == 3) { continue; } PosX = pTextObj->GetPosX(); PosY = pTextObj->GetPosY(); m_PDFDisplayMatrix.Transform(PosX, PosY); } else { PosX = 0; PosY = 0; } FX_BOOL bNewLine = TRUE; FX_RECT ObjBBox = pObj->GetBBox(&m_PDFDisplayMatrix); if(ObjBBox.left > PDFWidth || ObjBBox.right < 0 || ObjBBox.bottom < 0 || ObjBBox.top > PDFHeight) { continue; } if(ObjBBox.IsEmpty()) { continue; } a++; if(!pCell) { bNewLine = TRUE; m_WritingMode = GetWritingMode(NULL, pObj); } else { int WritingMode = GetWritingMode(pPerObj, pObj); if(m_WritingMode == WritingMode || m_WritingMode == WritingMode_UNKNOW || WritingMode == WritingMode_UNKNOW) { if(WritingMode != WritingMode_UNKNOW) { m_WritingMode = WritingMode; } if(m_WritingMode == WritingMode_TBRL) { if(!(GetRectBottom(ObjBBox) > GetRectTop(pCell->m_BBox) || GetRectTop(ObjBBox) < GetRectBottom(pCell->m_BBox))) { bNewLine = FALSE; } } else { if(!(GetRectBottom(ObjBBox) < GetRectTop(pCell->m_BBox) || GetRectTop(ObjBBox) > GetRectBottom(pCell->m_BBox))) { bNewLine = FALSE; } if (pObj->m_Type == PDFPAGE_TEXT) { if(FXSYS_fabs(PrevY - PosY) < 1 ) { bNewLine = FALSE; } } } } else { m_WritingMode = WritingMode; } } pPerObj = pObj; if(bNewLine) { int c = pCell ? pCell->m_ObjList.GetCount() : 0; pCell = new CRF_CELL; pCell->m_CellWritingMode = m_WritingMode; pCell->m_BBox = ObjBBox; if(pObj->m_Type == PDFPAGE_TEXT) { FX_FLOAT x = ((CPDF_TextObject*)pObj)->GetPosX(), y = ((CPDF_TextObject*)pObj)->GetPosY(); m_PDFDisplayMatrix.Transform(x, y); if(x < ObjBBox.left) { pCell->m_BBox.left = (int)x; } } pCell->m_ObjList.AddTail(pObj); cellArray.Add(pCell); } else { pCell->m_ObjList.AddTail(pObj); pCell->m_BBox.Union(ObjBBox); } PrevX = PosX; PrevY = PosY; } } FX_FLOAT CPDF_AutoReflowLayoutProvider::GetLayoutOrderHeight(CPDF_PageObject* pCurObj) { CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top); if (m_WritingMode == WritingMode_TBRL) { return rcCurObj.Width(); } return rcCurObj.Height(); } FX_FLOAT CPDF_AutoReflowLayoutProvider::GetLayoutOrderWidth(CPDF_PageObject* pCurObj) { CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top); if (m_WritingMode == WritingMode_TBRL) { return rcCurObj.Height(); } return rcCurObj.Width(); } int CPDF_AutoReflowLayoutProvider:: GetRectWidth(FX_RECT rect) { if(m_WritingMode == WritingMode_TBRL) { return rect.Height(); } return rect.Width(); } int CPDF_AutoReflowLayoutProvider:: GetRectHeight(FX_RECT rect) { if(m_WritingMode == WritingMode_TBRL) { return rect.Width(); } return rect.Height(); } int CPDF_AutoReflowLayoutProvider:: GetRectStart(FX_RECT rect) { if(m_WritingMode == WritingMode_TBRL) { return rect.top; } return rect.left; } int CPDF_AutoReflowLayoutProvider:: GetRectEnd(FX_RECT rect) { if(m_WritingMode == WritingMode_TBRL) { return rect.bottom; } return rect.right; } int CPDF_AutoReflowLayoutProvider:: GetRectTop(FX_RECT rect) { if(m_WritingMode == WritingMode_TBRL) { return rect.right; } return rect.top; } int CPDF_AutoReflowLayoutProvider:: GetRectBottom(FX_RECT rect) { if(m_WritingMode == WritingMode_TBRL) { return rect.left; } return rect.bottom; } int CPDF_AutoReflowLayoutProvider::GetWritingMode(CPDF_PageObject* pPreObj, CPDF_PageObject* pCurObj) { CFX_FloatRect rcCurObj(pCurObj->m_Left, pCurObj->m_Bottom, pCurObj->m_Right, pCurObj->m_Top); if(pCurObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* ptextObj = (CPDF_TextObject* )pCurObj; int count = ptextObj->CountItems(); if(count > 1) { CPDF_TextObjectItem Item1, Item2; ptextObj->GetItemInfo(0, &Item1); ptextObj->GetItemInfo(count - 1, &Item2); if(Item2.m_CharCode == -1 && count > 2) { ptextObj->GetItemInfo(2, &Item2); } CFX_AffineMatrix textMatrix; ptextObj->GetTextMatrix(&textMatrix); textMatrix.Transform(Item1.m_OriginX, Item1.m_OriginY); textMatrix.Transform(Item2.m_OriginX, Item2.m_OriginY); FX_FLOAT dx = FXSYS_fabs(Item1.m_OriginX - Item2.m_OriginX); FX_FLOAT dy = FXSYS_fabs(Item1.m_OriginY - Item2.m_OriginY); return dx >= dy ? WritingMode_LRTB : WritingMode_TBRL; } else { if(m_WritingMode != WritingMode_UNKNOW) { return m_WritingMode; } } } if(pPreObj) { FX_FLOAT threshold = rcCurObj.Width() / 4; if(m_WritingMode == WritingMode_LRTB) { if(FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) < threshold * 2 && FXSYS_fabs(pPreObj->m_Top - pCurObj->m_Top) < threshold * 2) { return m_WritingMode; } FX_FLOAT mid = (pCurObj->m_Bottom + pCurObj->m_Top) / 2; if(mid > pPreObj->m_Bottom && mid < pPreObj->m_Top && pCurObj->m_Right > pPreObj->m_Right) { return m_WritingMode; } } else if(m_WritingMode == WritingMode_TBRL) { if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) < threshold * 2 && FXSYS_fabs(pPreObj->m_Right - pCurObj->m_Right) < threshold * 2) { return m_WritingMode; } FX_FLOAT mid = (pCurObj->m_Right + pCurObj->m_Left) / 2; if(mid > pPreObj->m_Left && mid < pPreObj->m_Right && pCurObj->m_Bottom < pPreObj->m_Bottom) { return m_WritingMode; } } if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) < threshold && FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) > threshold * 2) { return WritingMode_TBRL; } if(FXSYS_fabs(pPreObj->m_Left - pCurObj->m_Left) > threshold && FXSYS_fabs(pPreObj->m_Bottom - pCurObj->m_Bottom) < threshold * 2) { return WritingMode_LRTB; } int count = 0; if(pPreObj->m_Type == PDFPAGE_TEXT) { CPDF_TextObject* ptextObj = (CPDF_TextObject* )pCurObj; count = ptextObj->CountItems(); } if(pPreObj->m_Type != PDFPAGE_TEXT || count == 1) { if(pCurObj->m_Left > pPreObj->m_Right) { FX_FLOAT mid = (pCurObj->m_Top + pCurObj->m_Bottom) / 2; if(mid < pPreObj->m_Top && mid > pPreObj->m_Bottom) { return WritingMode_LRTB; } } if(pCurObj->m_Top < pPreObj->m_Bottom) { FX_FLOAT mid = (pCurObj->m_Left + pCurObj->m_Right) / 2; if(mid < pPreObj->m_Right && mid > pPreObj->m_Left) { return WritingMode_TBRL; } } } } return WritingMode_UNKNOW; } LayoutStatus CPDF_AutoReflowLayoutProvider::StartLoad(IFX_Pause* pPause) { m_pPause = pPause; m_pRoot = new CPDF_AutoReflowElement(LayoutDocument); m_Step = 0; return Continue(); } LayoutStatus CPDF_AutoReflowLayoutProvider::Continue() { GenerateStructTree(); return m_Status; } int CPDF_AutoReflowLayoutProvider::GetPosition() { if(m_Step == 0) { return 0; } else { return m_Step * 100 / AUTOREFLOW_STEP_REMOVEDATA; } } FX_FLOAT CPDF_AutoReflowLayoutProvider::GetObjMinCell(CPDF_PageObject* pObj) { if(!pObj) { return 0; } if(pObj->m_Type != PDFPAGE_TEXT) { CFX_AffineMatrix matrix; FX_RECT rect = pObj->GetBBox(&matrix); return (FX_FLOAT)(rect.Width()); } CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj; int count = pTextObj->CountItems(); for(int i = 0; i < count; i++) { CPDF_TextObjectItem Item; pTextObj->GetItemInfo(i, &Item); if(Item.m_CharCode == -1) { continue; } if((Item.m_CharCode > 47 && Item.m_CharCode < 58) || (Item.m_CharCode > 64 && Item.m_CharCode < 91) || (Item.m_CharCode > 96 && Item.m_CharCode < 123)) { continue; } if(Item.m_CharCode > 127 || (Item.m_CharCode > 32 && Item.m_CharCode < 35) || Item.m_CharCode == 37 || (Item.m_CharCode > 38 && Item.m_CharCode < 42) || Item.m_CharCode == 44 || Item.m_CharCode == 46 || Item.m_CharCode == 58 || Item.m_CharCode == 59 || Item.m_CharCode == 63 || Item.m_CharCode == 93) { if(i == count - 1) { CFX_AffineMatrix matrix; FX_RECT rect = pObj->GetBBox(&matrix); return (FX_FLOAT)(rect.Width()); } else { pTextObj->GetItemInfo(i + 1, &Item); return Item.m_OriginX; } } return Item.m_OriginX; } CFX_AffineMatrix matrix; FX_RECT rect = pObj->GetBBox(&matrix); return (FX_FLOAT)(rect.Width()); }