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 FX_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 = 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 }
GenerateParagraph(CFX_PtrArray & cellArray)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 }
ProcessObj(CFX_PtrArray & cellArray,CPDF_PageObject * pObj,CFX_AffineMatrix matrix)416 void CPDF_AutoReflowLayoutProvider::ProcessObj(CFX_PtrArray& cellArray, CPDF_PageObject* pObj, CFX_AffineMatrix matrix)
417 {
418 }
LogicPreObj(CPDF_PageObject * pObj)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 }
GenerateLine(CFX_PtrArray & cellArray)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 }
GetLayoutOrderHeight(CPDF_PageObject * pCurObj)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 }
GetLayoutOrderWidth(CPDF_PageObject * pCurObj)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 }
GetRectWidth(FX_RECT rect)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 }
GetRectHeight(FX_RECT rect)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 }
GetRectStart(FX_RECT rect)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 }
GetRectEnd(FX_RECT rect)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 }
GetRectTop(FX_RECT rect)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 }
GetRectBottom(FX_RECT rect)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 }
GetWritingMode(CPDF_PageObject * pPreObj,CPDF_PageObject * pCurObj)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 }
StartLoad(IFX_Pause * pPause)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 }
Continue()729 LayoutStatus CPDF_AutoReflowLayoutProvider::Continue()
730 {
731 GenerateStructTree();
732 return m_Status;
733 }
GetPosition()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 }
GetObjMinCell(CPDF_PageObject * pObj)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