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)
FPDF_ProcessInterObj(const CPDF_PageObject * pPrevObj,const CPDF_PageObject * pObj)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 }
Conver2AppreceOrder(const CPDF_PageObjects * pStreamOrderObjs,CPDF_PageObjects * pAppraceOrderObjs)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 }
Create_LayoutProvider_AutoReflow(CPDF_PageObjects * pPage,FX_BOOL bReadOrder)101 IPDF_LayoutProvider* IPDF_LayoutProvider::Create_LayoutProvider_AutoReflow(CPDF_PageObjects* pPage, FX_BOOL bReadOrder)
102 {
103 return new CPDF_AutoReflowLayoutProvider(pPage, bReadOrder);
104 }
CPDF_AutoReflowElement(LayoutType layoutType,CPDF_AutoReflowElement * pParent)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 }
~CPDF_AutoReflowElement()114 CPDF_AutoReflowElement::~CPDF_AutoReflowElement()
115 {
116 m_ChildArray.RemoveAll();
117 m_ObjArray.RemoveAll();
118 }
CountAttrValues(LayoutAttr attr_type)119 int CPDF_AutoReflowElement::CountAttrValues(LayoutAttr attr_type)
120 {
121 return 1;
122 }
GetEnumAttr(LayoutAttr attr_type,int index)123 LayoutEnum CPDF_AutoReflowElement::GetEnumAttr(LayoutAttr attr_type, int index )
124 {
125 return LayoutInvalid;
126 }
GetNumberAttr(LayoutAttr attr_type,int index)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 }
GetColorAttr(LayoutAttr attr_type,int index)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
CPDF_AutoReflowLayoutProvider(CPDF_PageObjects * pPage,FX_BOOL bReadOrder)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 }
~CPDF_AutoReflowLayoutProvider()158 CPDF_AutoReflowLayoutProvider::~CPDF_AutoReflowLayoutProvider()
159 {
160 m_pPDFPage = NULL;
161 ReleaseElm(m_pRoot);
162 }
ReleaseElm(CPDF_AutoReflowElement * & pElm,FX_BOOL bReleaseChildren)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 }
AddObjectArray(CPDF_AutoReflowElement * pElm,CFX_PtrList & ObjList)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 }
GenerateStructTree()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 }
CreateElement()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 }
GenerateParagraph(CFX_PtrArray & cellArray)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 }
ProcessObj(CFX_PtrArray & cellArray,CPDF_PageObject * pObj,CFX_AffineMatrix matrix)415 void CPDF_AutoReflowLayoutProvider::ProcessObj(CFX_PtrArray& cellArray, CPDF_PageObject* pObj, CFX_AffineMatrix matrix)
416 {
417 }
LogicPreObj(CPDF_PageObject * pObj)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 }
GenerateLine(CFX_PtrArray & cellArray)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 }
GetLayoutOrderHeight(CPDF_PageObject * pCurObj)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 }
GetLayoutOrderWidth(CPDF_PageObject * pCurObj)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 }
GetRectWidth(FX_RECT rect)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 }
GetRectHeight(FX_RECT rect)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 }
GetRectStart(FX_RECT rect)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 }
GetRectEnd(FX_RECT rect)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 }
GetRectTop(FX_RECT rect)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 }
GetRectBottom(FX_RECT rect)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 }
GetWritingMode(CPDF_PageObject * pPreObj,CPDF_PageObject * pCurObj)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 }
StartLoad(IFX_Pause * pPause)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 }
Continue()725 LayoutStatus CPDF_AutoReflowLayoutProvider::Continue()
726 {
727 GenerateStructTree();
728 return m_Status;
729 }
GetPosition()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 }
GetObjMinCell(CPDF_PageObject * pObj)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