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