Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / reflow / layoutprocessor_reflow.cpp
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 "../../include/reflow/reflowengine.h"
8 #include "reflowedpage.h"
9 #include "layoutprovider_taggedpdf.h"
10 IPDF_LayoutProcessor* IPDF_LayoutProcessor::Create_LayoutProcessor_Reflow(FX_FLOAT TopIndent, FX_FLOAT fWidth, FX_FLOAT fHeight, void* pReflowedPage, int flags, FX_FLOAT lineSpace )
11 {
12     if(pReflowedPage == NULL || fWidth <= 20) {
13         return NULL;
14     }
15     CPDF_LayoutProcessor_Reflow* pReflowEngine = FX_NEW CPDF_LayoutProcessor_Reflow();
16     if (NULL == pReflowEngine) {
17         return NULL;
18     }
19     pReflowEngine->Init(TopIndent, fWidth, fHeight, (CPDF_ReflowedPage*)pReflowedPage, flags, lineSpace);
20     return pReflowEngine;
21 }
22 CPDF_LayoutProcessor_Reflow::CPDF_LayoutProcessor_Reflow()
23 {
24     m_pPause = NULL;
25     m_pLayoutElement = NULL;
26     m_fRefWidth = 0;
27     m_fRefWidth = 0;
28     m_fCurrLineWidth = 0;
29     m_fCurrLineHeight = 0;
30     m_bIllustration = FALSE;
31     m_pPreObj = NULL;
32     m_pCurrLine = FX_NEW CRF_DataPtrArray(50);
33     m_pTempLine = FX_NEW CRF_DataPtrArray(50);
34     m_StartIndent = 0;
35     m_PausePosition = 0;
36 }
37 CPDF_LayoutProcessor_Reflow::~CPDF_LayoutProcessor_Reflow()
38 {
39     if (m_pCurrLine) {
40         m_pCurrLine->RemoveAll();
41         delete m_pCurrLine;
42     }
43     m_pCurrLine = NULL;
44     if (m_pTempLine) {
45         m_pTempLine->RemoveAll();
46         delete m_pTempLine;
47     }
48     m_pTempLine = NULL;
49 }
50 void CPDF_LayoutProcessor_Reflow::Init(FX_FLOAT TopIndent, FX_FLOAT fWidth, FX_FLOAT fHeight, CPDF_ReflowedPage* pReflowedPage, int flags, FX_FLOAT lineSpace)
51 {
52     m_pLayoutElement = NULL;
53     m_TopIndent = TopIndent;
54     m_Status = LayoutReady;
55     m_flags = flags;
56     m_pReflowedPage = pReflowedPage;
57     m_fScreenHeight = fHeight;
58     m_fRefWidth = fWidth;
59     m_fCurrLineHeight = 0;
60     m_fCurrLineWidth = 0;
61     m_fLineSpace = lineSpace;
62     pReflowedPage->m_PageWidth = fWidth;
63     pReflowedPage->m_PageHeight = TopIndent;
64 }
65 void CPDF_LayoutProcessor_Reflow::FitPageMode()
66 {
67     if(m_flags & RF_PARSER_PAGEMODE && m_fScreenHeight > 20) {
68         float fitPageHeight = m_fScreenHeight;
69         CPDF_ReflowedPage* pRFPage = m_pReflowedPage;
70         int count = pRFPage->m_pReflowed->GetSize();
71         CFX_WordArray dy;
72         dy.Add(0);
73         int pos = 0;
74         int screenCount = 1;
75         FX_FLOAT h = pRFPage->GetPageHeight();
76         while (h > screenCount * fitPageHeight) {
77             FX_FLOAT tempPageHeight = screenCount * fitPageHeight;
78             int j = 0;
79             FX_FLOAT tempDy = 0;
80             for(int i = 0; i < count; i++) {
81                 CRF_Data* pData = (*pRFPage->m_pReflowed)[i];
82                 FX_FLOAT posY;
83                 posY = pData->m_PosY;
84                 if(FXSYS_fabs(posY) > tempPageHeight &&
85                         FXSYS_fabs(posY + pData->m_Height) < tempPageHeight) {
86                     if(j == 0) {
87                         j = i;
88                     }
89                     if(pData->m_Height > fitPageHeight) {
90                         FX_FLOAT zoom;
91                         FX_FLOAT spaceh = screenCount * fitPageHeight + posY + pData->m_Height;
92                         if(spaceh < fitPageHeight / 3 * 2) {
93                             spaceh = fitPageHeight;
94                         }
95                         zoom = spaceh / pData->m_Height;
96                         tempDy = spaceh - pData->m_Height;
97                         pData->m_Height = spaceh;
98                         pData->m_Width *= zoom;
99                         break;
100                     }
101                     FX_FLOAT dy = pData->m_PosY + pData->m_Height + tempPageHeight;
102                     if(dy > tempDy) {
103                         tempDy = dy;
104                     }
105                 } else if(FXSYS_fabs(posY + pData->m_Height) > tempPageHeight) {
106                     break;
107                 }
108             }
109             for(; j < count; j++) {
110                 CRF_Data* pData = (*pRFPage->m_pReflowed)[j];
111                 FX_FLOAT posY;
112                 posY = pData->m_PosY;
113                 if(FXSYS_fabs(posY) > tempPageHeight ) {
114                     pData->m_PosY -= tempDy;
115                 }
116                 if(pData->m_Height >= fitPageHeight) {
117                     pData->m_Height = fitPageHeight - 1;
118                     if(pData->GetType() == CRF_Data::Text) {
119                         CRF_CharData* pCharData = (CRF_CharData*)pData;
120                         pCharData->m_pCharState->m_fFontSize = pData->m_Height;
121                     }
122                 }
123             }
124             pRFPage->m_PageHeight += tempDy;
125             h += tempDy;
126             screenCount++;
127         }
128     }
129 }
130 LayoutStatus CPDF_LayoutProcessor_Reflow::StartProcess(IPDF_LayoutElement* pElement, IFX_Pause* pPause, const CFX_AffineMatrix* pPDFMatrix)
131 {
132     if(!pElement) {
133         return LayoutError;
134     }
135     m_pPause = pPause;
136     m_PDFMatrix = *pPDFMatrix;
137     m_pRootElement = pElement;
138     ProcessElement(m_pRootElement, m_fRefWidth);
139     if(m_Status == LayoutToBeContinued) {
140         return LayoutToBeContinued;
141     }
142     m_Status = LayoutFinished;
143     FitPageMode();
144     return LayoutFinished;
145 }
146 LayoutStatus CPDF_LayoutProcessor_Reflow::Continue()
147 {
148     int size = m_pReflowedPage->m_pReflowed->GetSize();
149     ProcessElement(m_pRootElement, m_CurrRefWidth);
150     size = m_pReflowedPage->m_pReflowed->GetSize();
151     if(m_Status == LayoutReady) {
152         m_Status = LayoutFinished;
153         FitPageMode();
154     }
155     return m_Status;
156 }
157 int CPDF_LayoutProcessor_Reflow::GetPosition()
158 {
159     return m_PausePosition;
160 }
161 FX_BOOL CPDF_LayoutProcessor_Reflow::IsCanBreakAfter(FX_DWORD unicode)
162 {
163     if(unicode == -1) {
164         return FALSE;
165     }
166     switch(unicode) {
167         case 40:
168         case 91:
169         case 123:
170             return FALSE;
171     }
172     if(unicode >= 256) {
173         return TRUE;
174     } else if(unicode >= 48 && unicode <= 57) {
175         return FALSE;
176     } else if(unicode >= 64 && unicode <= 90) {
177         return FALSE;
178     } else if(unicode >= 97 && unicode <= 122) {
179         return FALSE;
180     }
181     return TRUE;
182 }
183 FX_BOOL CPDF_LayoutProcessor_Reflow::IsCanBreakBefore(FX_DWORD unicode)
184 {
185     if(unicode == -1) {
186         return FALSE;
187     }
188     switch(unicode) {
189         case 33:
190         case 41:
191         case 44:
192         case 46:
193         case 59:
194         case 63:
195         case 93:
196         case 125:
197             return FALSE;
198     }
199     if(unicode >= 256) {
200         return TRUE;
201     } else if(unicode >= 48 && unicode <= 57) {
202         return FALSE;
203     } else if(unicode >= 64 && unicode <= 90) {
204         return FALSE;
205     } else if(unicode >= 97 && unicode <= 122) {
206         return FALSE;
207     }
208     return TRUE;
209 }
210 void CPDF_LayoutProcessor_Reflow::ProcessTable(FX_FLOAT dx)
211 {
212     if(m_pReflowedPage->m_pReflowed->GetSize() == 0) {
213         return;
214     }
215     CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1);
216     int rowCount = pTable->m_nCell.GetSize();
217     int n = 0;
218     FX_FLOAT* dyRow = FX_Alloc(FX_FLOAT, rowCount + 1);
219     FXSYS_memset32(dyRow, 0, sizeof(FX_FLOAT) * (rowCount + 1));
220     dyRow[0] = 0 ;
221     dyRow[0] = - pTable->m_ReflowPageHeight;
222     int tableColCount = 0;
223     int i;
224     for(i = 0; i < rowCount; i++) {
225         int colCount = pTable->m_nCell.GetAt(i);
226         if(colCount > tableColCount) {
227             tableColCount = colCount;
228         }
229     }
230     int cellCount = tableColCount * rowCount;
231     RF_TableCell** pVirtualTable = FX_Alloc(RF_TableCell*, cellCount);
232     FXSYS_memset32(pVirtualTable, 0, sizeof(RF_TableCell*) * cellCount);
233     for(i = 0; i < rowCount; i++) {
234         int colCount = pTable->m_nCell.GetAt(i);
235         FX_FLOAT rowWidth = 0;
236         int j = 0;
237         int s = pTable->m_pCellArray.GetSize();
238         for(j = 0; j < colCount; j++) {
239             RF_TableCell* pCell = (RF_TableCell*)pTable->m_pCellArray.GetAt(n++);
240             if(pCell->m_EndPos < pCell->m_BeginPos) {
241                 continue;
242             }
243             int pos = i * tableColCount;
244             while(pos < cellCount && pVirtualTable[pos] != NULL) {
245                 pos++;
246             }
247             if(pos >= (i + 1) * tableColCount) {
248                 pos = i * tableColCount + j;
249             }
250             int RowSpan = pCell->m_RowSpan;
251             int ColSpan = pCell->m_ColSpan;
252             if(RowSpan + i > rowCount) {
253                 RowSpan = rowCount - i;
254             }
255             if(ColSpan + j > colCount) {
256                 ColSpan = colCount - j;
257             }
258             for(int m = 0; m < RowSpan; m++) {
259                 for(int nn = 0; nn < ColSpan; nn++) {
260                     if(pos + nn >= cellCount) {
261                         break;
262                     }
263                     pVirtualTable[pos + nn] = pCell;
264                 }
265                 pos += tableColCount;
266             }
267             FX_FLOAT dxCell = dx;
268             for(pos = i * tableColCount; pVirtualTable[pos] != pCell && pos < cellCount; pos++) {
269                 dxCell += (pVirtualTable[pos])->m_MaxWidth;
270             }
271             CRF_Data* pData = (*m_pReflowedPage->m_pReflowed)[pCell->m_BeginPos];
272             FX_FLOAT dy = dyRow[i] - pData->m_Height - pData->m_PosY;
273             CFX_AffineMatrix matrix(1, 0, 0, 1, dxCell, dy);
274             Transform(&matrix, m_pReflowedPage->m_pReflowed, pCell->m_BeginPos, pCell->m_EndPos - pCell->m_BeginPos + 1);
275             if(pCell->m_RowSpan + i <= rowCount) {
276                 if(FXSYS_fabs(dyRow[pCell->m_RowSpan + i]) < FXSYS_fabs(dyRow[i] - pCell->m_CellHeight)) {
277                     dyRow[pCell->m_RowSpan + i] = dyRow[i] - pCell->m_CellHeight;
278                 }
279             }
280         }
281     }
282     n = 0;
283     for(i = 0; i < rowCount; i++) {
284         int colCount = pTable->m_nCell.GetAt(i);
285         for(int j = 0; j < colCount; j++) {
286             RF_TableCell* pCell = (RF_TableCell*)pTable->m_pCellArray.GetAt(n++);
287             switch(pCell->m_BlockAlign) {
288                 case LayoutAfter: {
289                         FX_FLOAT dy = dyRow[i + pCell->m_RowSpan] - pCell->m_CellHeight - dyRow[i];
290                         CFX_AffineMatrix matrix(1, 0, 0, 1, 0, dy);
291                         Transform(&matrix, m_pReflowedPage->m_pReflowed, pCell->m_BeginPos, pCell->m_EndPos - pCell->m_BeginPos + 1);
292                     }
293                     break;
294                 case LayoutMiddle:
295                 case LayoutJustify: {
296                         FX_FLOAT dy = (dyRow[i + pCell->m_RowSpan] + pCell->m_CellHeight - dyRow[i]) / 2;
297                         CFX_AffineMatrix matrix(1, 0, 0, 1, 0, dy);
298                         Transform(&matrix, m_pReflowedPage->m_pReflowed, pCell->m_BeginPos, pCell->m_EndPos - pCell->m_BeginPos + 1);
299                         break;
300                     }
301                 default:
302                     break;
303             }
304         }
305     }
306     CRF_Data* pData = (*m_pReflowedPage->m_pReflowed)[m_pReflowedPage->m_pReflowed->GetSize() - 1];
307     m_pReflowedPage->m_PageHeight = - dyRow[rowCount] + pData->m_Height;
308     FX_Free(pVirtualTable);
309     FX_Free(dyRow);
310     int size = pTable->m_pCellArray.GetSize();
311     for(i = 0; i < size; i++) {
312         RF_TableCell* pCell = pTable->m_pCellArray.GetAt(i);
313         FX_Free(pCell);
314     }
315     pTable->m_pCellArray.RemoveAll();
316     pTable->m_nCell.RemoveAll();
317     int s = sizeof(CRF_Table);
318     delete pTable;
319     m_TableArray.RemoveAt(m_TableArray.GetSize() - 1);
320 }
321 CFX_FloatRect CPDF_LayoutProcessor_Reflow::GetElmBBox(IPDF_LayoutElement* pElement)
322 {
323     CFX_FloatRect rect;
324     int objCount = pElement->CountObjects();
325     int count = pElement->CountChildren();
326     if(objCount == 0 && count == 0) {
327         return rect;
328     }
329     CFX_AffineMatrix matrix;
330     int i;
331     for(i = 0; i < objCount; i++) {
332         CPDF_PageObject* pObj = pElement->GetObject(0);
333         if(!pObj) {
334             continue;
335         }
336         if( rect.Height() == 0 ) {
337             rect = pObj->GetBBox(&matrix);
338         } else {
339             rect.Union(pObj->GetBBox(&matrix));
340         }
341     }
342     for(i = 0; i < count; i++) {
343         IPDF_LayoutElement* pChildElement = pElement->GetChild(i);
344         if( rect.Height() == 0 ) {
345             rect = GetElmBBox(pChildElement);
346         } else {
347             rect.Union(GetElmBBox(pChildElement));
348         }
349     }
350     return rect;
351 }
352 FX_FLOAT CPDF_LayoutProcessor_Reflow::GetElmWidth(IPDF_LayoutElement* pElement)
353 {
354     if(!pElement) {
355         return 0;
356     }
357     LayoutType layoutType = pElement->GetType();
358     FX_FLOAT width = 0;
359     if(layoutType == LayoutTable || layoutType == LayoutTableDataCell || layoutType == LayoutTableHeaderCell) {
360         width = pElement->GetNumberAttr(LayoutWidth);
361         if(width > 0) {
362             return width;
363         }
364     } else if( layoutType == LayoutTableRow) {
365         int count = pElement->CountChildren();
366         for(int i = 0; i < count; i++) {
367             IPDF_LayoutElement* pElm = pElement->GetChild(i);
368             width += pElm->GetNumberAttr(LayoutWidth);
369         }
370         if(width > 0) {
371             return width;
372         }
373     }
374     CFX_FloatRect rect = GetElmBBox(pElement);
375     return rect.Width();
376 }
377 FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,
378                         FX_FLOAT& interlow, FX_FLOAT& interhigh);
379 FX_BOOL IsSameLine(FX_BOOL bHorizontal, CFX_FloatRect Rect1, CFX_FloatRect Rect2)
380 {
381     if(bHorizontal) {
382         FX_FLOAT inter_top, inter_bottom;
383         if (!GetIntersection(Rect1.bottom, Rect1.top, Rect2.bottom, Rect2.top,
384                              inter_bottom, inter_top)) {
385             return FALSE;
386         }
387         FX_FLOAT lineHeight = Rect1.top - Rect1.bottom;
388         if(lineHeight > 20 && lineHeight > Rect2.Height() * 2) {
389             return FALSE;
390         }
391         if(lineHeight > 5 && Rect2.Height() / 2 > lineHeight) {
392             return FALSE;
393         }
394         FX_FLOAT inter_h = inter_top - inter_bottom;
395         if (inter_h < (lineHeight) / 2 && inter_h < Rect2.Height() / 2) {
396             return FALSE;
397         }
398     } else {
399         FX_FLOAT inter_left, inter_right;
400         if(!GetIntersection(Rect1.left, Rect1.right, Rect2.left, Rect2.right, inter_left, inter_right)) {
401             return FALSE;
402         }
403         FX_FLOAT inter_w = inter_right - inter_left;
404         if (inter_w < (Rect1.right - Rect1.left) / 2 && inter_w < (Rect2.right - Rect2.left) / 2) {
405             return FALSE;
406         }
407     }
408     return TRUE;
409 }
410 int32_t IsCanMergeParagraph(IPDF_LayoutElement* pPrevElement, IPDF_LayoutElement* pNextElement)
411 {
412     int32_t analogial = 100;
413     int32_t nPrevObj = pPrevElement->CountObjects(), i;
414     CPDF_PageObject* pPrevObj = NULL;
415     CFX_FloatRect prevRect, rect;
416     CFX_PtrArray prevLine, line;
417     FX_BOOL bParagraphStart = FALSE;
418     for(i = 0; i < nPrevObj; i++) {
419         CPDF_PageObject* pObj = pPrevElement->GetObject(i);
420         if(!pPrevObj) {
421             pPrevObj = pObj;
422             rect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
423             line.Add(pObj);
424             continue;
425         }
426         CFX_FloatRect objRect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
427         if(IsSameLine(TRUE, rect, objRect)) {
428             line.Add(pObj);
429             rect.Union(objRect);
430         } else {
431             prevLine.RemoveAll();
432             prevLine.Append(line);
433             prevRect = rect;
434             line.RemoveAll();
435             line.Add(pObj);
436             rect = objRect;
437             if(!bParagraphStart) {
438                 if (prevRect.left > rect.left + rect.Height() * 1.5) {
439                     bParagraphStart = TRUE;
440                 }
441             }
442         }
443     }
444     if(prevLine.GetSize()) {
445         if(FXSYS_fabs(rect.right - prevRect.right) > rect.Height()) {
446             analogial -= 50;
447         }
448     }
449     CPDF_PageObject* pObj = pPrevElement->GetObject(nPrevObj - 1);
450     if(pObj->m_Type == PDFPAGE_TEXT) {
451         CPDF_TextObject* pText = (CPDF_TextObject*)pObj;
452         int32_t nItem = pText->CountItems();
453         CPDF_TextObjectItem item;
454         pText->GetItemInfo(nItem - 1, &item);
455         CFX_WideString wStr = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode);
456         if(wStr.IsEmpty()) {
457             wStr = (FX_WCHAR)item.m_CharCode;
458         }
459         FX_WCHAR wch = wStr.GetAt(wStr.GetLength() - 1);
460         switch(wch) {
461             case '.':
462             case 12290:
463             case 65311:
464             case 63:
465             case 33:
466             case 65281:
467                 analogial -= 50;
468                 break;
469         }
470     }
471     prevLine.RemoveAll();
472     prevLine.Append(line);
473     line.RemoveAll();
474     int32_t nNextObj = pNextElement->CountObjects();
475     pPrevObj = NULL;
476     FX_BOOL bFirst = TRUE;
477     for(i = 0; i < nNextObj; i++) {
478         CPDF_PageObject* pObj = pNextElement->GetObject(i);
479         if(!pPrevObj) {
480             pPrevObj = pObj;
481             rect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
482             line.Add(pObj);
483             continue;
484         }
485         CFX_FloatRect objRect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
486         if(IsSameLine(TRUE, rect, objRect)) {
487             line.Add(pObj);
488             rect.Union(objRect);
489         } else {
490             if(FXSYS_fabs(rect.right - prevRect.right) < rect.Height() && FXSYS_fabs(rect.left - prevRect.left) < rect.Height()) {
491                 analogial += 50;
492             }
493             prevLine.RemoveAll();
494             prevLine.Append(line);
495             prevRect = rect;
496             line.RemoveAll();
497             line.Add(pObj);
498             rect = objRect;
499             if(!bFirst) {
500                 break;
501             }
502             bFirst = FALSE;
503         }
504     }
505     if(prevLine.GetSize()) {
506         if(bParagraphStart) {
507             if(prevRect.left - rect.left > rect.Height() && prevRect.left - rect.left < rect.Height() * 3) {
508                 analogial -= 50;
509             }
510         } else {
511             if(FXSYS_fabs(prevRect.left - rect.left) < rect.Height()) {
512                 analogial -= 50;
513             }
514         }
515     }
516     return analogial;
517 }
518 void CPDF_LayoutProcessor_Reflow::ProcessElement(IPDF_LayoutElement* pElement, FX_FLOAT reflowWidth)
519 {
520     if(pElement == NULL) {
521         return;
522     }
523     if(m_Status == LayoutReady) {
524         LayoutType layoutType = pElement->GetType();
525         int32_t ElementType = GetElementTypes(layoutType);
526         switch(ElementType) {
527             case SST_IE:
528                 m_bIllustration = TRUE;
529                 break;
530             case SST_BLSE:
531                 FinishedCurrLine();
532                 FX_FLOAT StartIndent = 0;
533                 if(IPDF_LayoutElement* pParent = pElement->GetParent()) {
534                     StartIndent = pParent->GetNumberAttr(LayoutStartIndent);
535                 }
536                 FX_FLOAT currStartIndent = pElement->GetNumberAttr(LayoutStartIndent);
537                 m_StartIndent = ConverWidth(currStartIndent);
538                 FX_FLOAT width = reflowWidth;
539                 if(StartIndent != currStartIndent) {
540                     reflowWidth -= m_StartIndent;
541                 }
542                 FX_FLOAT spaceBefore = pElement->GetNumberAttr(LayoutSpaceBefore);
543                 m_pReflowedPage->m_PageHeight += spaceBefore;
544                 m_TextAlign = pElement->GetEnumAttr(LayoutTextAlign);
545                 if(IPDF_LayoutElement* pParent = pElement->GetParent()) {
546                     StartIndent = pParent->GetNumberAttr(LayoutEndIndent);
547                     FX_FLOAT currEndIndent = pElement->GetNumberAttr(LayoutEndIndent);
548                     if(StartIndent != currStartIndent) {
549                         reflowWidth -= ConverWidth(currEndIndent);
550                     }
551                 }
552                 if(reflowWidth * 2 < width) {
553                     reflowWidth = width;
554                     m_StartIndent = 0;
555                 }
556                 break;
557         }
558         switch(layoutType) {
559             case LayoutTable: {
560                     CRF_Table* pTable = FX_NEW CRF_Table;
561                     if (NULL == pTable) {
562                         break;
563                     }
564                     m_TableArray.Add(pTable);
565                     pTable->m_ReflowPageHeight = m_pReflowedPage->m_PageHeight;
566                     pTable->m_TableWidth = GetElmWidth(pElement);
567                     break;
568                 }
569             case LayoutTableRow: {
570                     if(!m_TableArray.GetSize()) {
571                         break;
572                     }
573                     int count = pElement->CountChildren();
574                     CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1);
575                     int f = 0;
576                     for(int i = 0; i < count; i++) {
577                         IPDF_LayoutElement* pChildElement = pElement->GetChild(i);
578                         LayoutType type = pChildElement->GetType();
579                         if(type == LayoutTableDataCell || type == LayoutTableHeaderCell) {
580                             f++;
581                         }
582                     }
583                     pTable->m_nCell.Add(f);
584                     break;
585                 }
586             case LayoutTableDataCell:
587             case LayoutTableHeaderCell: {
588                     if(!m_TableArray.GetSize()) {
589                         break;
590                     }
591                     RF_TableCell* pCell = FX_Alloc(RF_TableCell, 1);
592                     FXSYS_memset32(pCell, 0 , sizeof(RF_TableCell));
593                     CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1);
594                     int pos = pTable->m_nCell.GetSize() - 1;
595                     pCell->m_BeginPos = m_pReflowedPage->m_pReflowed->GetSize();
596                     FX_FLOAT cellWidth = pElement->GetNumberAttr(LayoutWidth);
597                     if(cellWidth == 0 || pCell->m_MaxWidth > pTable->m_TableWidth) {
598                         CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1);
599                         pCell->m_MaxWidth = reflowWidth / pTable->m_nCell.GetAt(pTable->m_nCell.GetSize() - 1);
600                     } else {
601                         pCell->m_MaxWidth = pElement->GetNumberAttr(LayoutWidth) * reflowWidth / pTable->m_TableWidth;
602                     }
603                     pCell->m_ColSpan = (int)(pElement->GetNumberAttr(LayoutColSpan));
604                     pCell->m_RowSpan = (int)(pElement->GetNumberAttr(LayoutRowSpan));
605                     if(!pCell->m_ColSpan) {
606                         pCell->m_ColSpan = 1;
607                     }
608                     if(!pCell->m_RowSpan ) {
609                         pCell->m_RowSpan = 1;
610                     }
611                     pCell->m_BlockAlign = pElement->GetEnumAttr(LayoutBlockAlign);
612                     m_TextAlign = pElement->GetEnumAttr(LayoutInlineAlign);
613                     pCell->m_PosX = 0;
614                     pCell->m_PosY = 0;
615                     reflowWidth = pCell->m_MaxWidth;
616                     pTable->m_pCellArray.Add(pCell);
617                     break;
618                 }
619             default:
620                 break;
621         }
622         m_fLineHeight = pElement->GetNumberAttr(LayoutLineHeight);
623         int ReflowedSize = m_pReflowedPage->m_pReflowed->GetSize();
624         if(pElement->CountObjects()) {
625             ProcessObjs(pElement, reflowWidth);
626         }
627     }
628     int count = pElement->CountChildren();
629     for(int i = 0; i < count; i++) {
630         IPDF_LayoutElement* pChildElement = pElement->GetChild(i);
631         ProcessElement(pChildElement, reflowWidth);
632         if(m_pPause && m_pRootElement == pElement && m_Status != LayoutToBeContinued ) {
633             if(m_pPause->NeedToPauseNow()) {
634                 m_pLayoutElement = pChildElement;
635                 m_Status = LayoutToBeContinued;
636                 m_CurrRefWidth = reflowWidth;
637                 m_PausePosition = (i + 1) * 100 / (count + 1);
638                 return ;
639             }
640         }
641         if(m_Status == LayoutToBeContinued && m_pLayoutElement == pChildElement) {
642             m_Status = LayoutReady;
643         }
644     }
645     if(m_Status == LayoutReady) {
646         FX_FLOAT dx = 0;
647         LayoutType layoutType = pElement->GetType();
648         int32_t ElementType = GetElementTypes(layoutType);
649         switch(ElementType) {
650             case SST_IE:
651                 m_bIllustration = FALSE;
652                 FinishedCurrLine();
653                 break;
654             case SST_BLSE:
655                 FinishedCurrLine();
656                 FX_FLOAT StartIndent = 0;
657                 if(IPDF_LayoutElement* pParent = pElement->GetParent()) {
658                     StartIndent = pParent->GetNumberAttr(LayoutStartIndent);
659                 }
660                 FX_FLOAT currStartIndent = pElement->GetNumberAttr(LayoutStartIndent);
661                 if(StartIndent != currStartIndent) {
662                     reflowWidth += ConverWidth(currStartIndent);
663                     dx += ConverWidth(currStartIndent);
664                 }
665                 FX_FLOAT spaceAfter = pElement->GetNumberAttr(LayoutSpaceAfter);
666                 m_pReflowedPage->m_PageHeight += spaceAfter;
667                 break;
668         }
669         switch(layoutType) {
670             case LayoutTableDataCell:
671             case LayoutTableHeaderCell: {
672                     if(!m_TableArray.GetSize()) {
673                         break;
674                     }
675                     CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1);
676                     RF_TableCell* pCell = pTable->m_pCellArray.GetAt(pTable->m_pCellArray.GetSize() - 1);
677                     pCell->m_EndPos = m_pReflowedPage->m_pReflowed->GetSize() - 1;
678                     if(pCell->m_EndPos < pCell->m_BeginPos) {
679                         pCell->m_CellHeight = 0;
680                     } else {
681                         CRF_Data* pBeginData = (*m_pReflowedPage->m_pReflowed)[pCell->m_BeginPos];
682                         CRF_Data* pEndData = (*m_pReflowedPage->m_pReflowed)[pCell->m_EndPos];
683                         pCell->m_CellHeight = pBeginData->m_Height > pEndData->m_Height ? pBeginData->m_Height : pEndData->m_Height;
684                         pCell->m_CellHeight -= pEndData->m_PosY - pBeginData->m_PosY;
685                     }
686                     break;
687                 }
688             case LayoutTableRow: {
689                     if(!m_TableArray.GetSize()) {
690                         break;
691                     }
692                     CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1);
693                     if(pTable->m_nCol == 0) {
694                         pTable->m_nCol = pTable->m_pCellArray.GetSize();
695                     }
696                     break;
697                 }
698             case LayoutTable: {
699                     ProcessTable(dx);
700                     break;
701                 }
702             default:
703                 if(dx) {
704                     CFX_AffineMatrix matrix(1, 0, 0, 1, dx, 0);
705                     int ReflowedSize = m_pReflowedPage->m_pReflowed->GetSize();
706                     Transform(&matrix, m_pReflowedPage->m_pReflowed, ReflowedSize, m_pReflowedPage->m_pReflowed->GetSize() - ReflowedSize);
707                 }
708         }
709     }
710     if(m_pRootElement == pElement) {
711         m_PausePosition = 100;
712     }
713 }
714 int32_t CPDF_LayoutProcessor_Reflow::GetElementTypes(LayoutType layoutType)
715 {
716     switch(layoutType) {
717         case LayoutParagraph:
718         case LayoutHeading:
719         case LayoutHeading1:
720         case LayoutHeading2:
721         case LayoutHeading3:
722         case LayoutHeading4:
723         case LayoutHeading5:
724         case LayoutHeading6:
725         case LayoutList:
726         case LayoutListItem:
727         case LayoutListLabel:
728         case LayoutListBody:
729         case LayoutTable:
730         case LayoutTableHeaderCell:
731         case LayoutTableDataCell:
732         case LayoutTableRow:
733         case LayoutTableHeaderGroup:
734         case LayoutTableBodyGroup:
735         case LayoutTableFootGroup:
736         case LayoutTOCI:
737         case LayoutCaption:
738             return SST_BLSE;
739         case LayoutFigure:
740         case LayoutFormula:
741         case LayoutForm:
742             return SST_IE;
743         case LayoutSpan:
744         case LayoutQuote:
745         case LayoutNote:
746         case LayoutReference:
747         case LayoutBibEntry:
748         case LayoutCode:
749         case LayoutLink:
750         case LayoutAnnot:
751         case LayoutRuby:
752         case LayoutWarichu:
753             return SST_ILSE;
754         default:
755             return SST_GE;
756     }
757     return FALSE;
758 }
759 FX_FLOAT        CPDF_LayoutProcessor_Reflow::ConverWidth(FX_FLOAT width)
760 {
761     return width;
762 }
763 void CPDF_LayoutProcessor_Reflow::ProcessObject(CPDF_PageObject* pObj, FX_FLOAT reflowWidth, CFX_AffineMatrix objMatrix)
764 {
765     if(!pObj) {
766         return;
767     }
768     if(pObj->m_Type == PDFPAGE_TEXT) {
769         ProcessTextObject( (CPDF_TextObject *)pObj, reflowWidth, objMatrix);
770     } else if(pObj->m_Type == PDFPAGE_IMAGE) {
771         if(!(m_flags & RF_PARSER_IMAGE)) {
772             return;
773         }
774         CPDF_PageObjects* pObjs = FX_NEW CPDF_PageObjects(FALSE);
775         if (NULL == pObjs) {
776             return;
777         }
778         FX_POSITION pos = pObjs->GetLastObjectPosition();
779         pos = pObjs->InsertObject(pos, pObj);
780         CFX_AffineMatrix matrix;
781         FX_RECT rect = pObj->GetBBox(&matrix);
782         CPDF_ImageObject* ImageObj = (CPDF_ImageObject*)pObj;
783         ProcessUnitaryObjs(pObjs, reflowWidth, objMatrix);
784         delete pObjs;
785     } else if(pObj->m_Type == PDFPAGE_PATH) {
786     } else if(pObj->m_Type == PDFPAGE_FORM) {
787         CPDF_FormObject* pForm = (CPDF_FormObject*)pObj;
788         FX_POSITION pos = pForm->m_pForm->GetFirstObjectPosition();
789         objMatrix.Concat(pForm->m_FormMatrix);
790         while (pos) {
791             CPDF_PageObject* pObj1 = pForm->m_pForm->GetNextObject(pos);
792             ProcessObject(pObj1, reflowWidth, objMatrix);
793         }
794     }
795 }
796 void CPDF_LayoutProcessor_Reflow::ProcessObjs(IPDF_LayoutElement* pElement, FX_FLOAT reflowWidth)
797 {
798     m_fCurrMaxWidth = reflowWidth;
799     int ObjCount = pElement->CountObjects();
800     for(int i = 0; i < ObjCount; i++) {
801         CPDF_PageObject* pObj = pElement->GetObject(i);
802         ProcessObject(pObj, reflowWidth, m_PDFMatrix);
803         continue;
804     }
805 }
806 void CPDF_LayoutProcessor_Reflow::AddTemp2CurrLine(int begin, int count)
807 {
808     if(begin < 0 || count <= 0 || !m_pReflowedPage || !m_pReflowedPage->m_pReflowed || !m_pTempLine) {
809         return;
810     } else {
811         count += begin;
812     }
813     int size = m_pReflowedPage->m_pReflowed->GetSize();
814     int temps = m_pTempLine->GetSize();
815     for(int i = begin; i < count; i++) {
816         CRF_Data* pData = (*m_pTempLine)[i];
817         AddData2CurrLine(pData);
818     }
819 }
820 void CPDF_LayoutProcessor_Reflow::AddData2CurrLine(CRF_Data* pData)
821 {
822     if(pData == NULL || m_pCurrLine == NULL) {
823         return;
824     }
825     m_pCurrLine->Add(pData);
826     m_fCurrLineWidth = pData->m_PosX + pData->m_Width;
827     if(pData->m_Height > m_fCurrLineHeight) {
828         m_fCurrLineHeight = pData->m_Height;
829     }
830 }
831 void CPDF_LayoutProcessor_Reflow::UpdateCurrLine()
832 {
833 }
834 void CPDF_LayoutProcessor_Reflow::Transform(const CFX_AffineMatrix* pMatrix, CRF_DataPtrArray* pDataArray, int beginPos, int count)
835 {
836     if (!pDataArray) {
837         return;
838     }
839     if(count == 0) {
840         count = pDataArray->GetSize();
841     } else {
842         count += beginPos;
843     }
844     for(int i = beginPos; i < count; i++) {
845         CRF_Data* pData = (*pDataArray)[i];
846         Transform(pMatrix, pData);
847     }
848 }
849 void CPDF_LayoutProcessor_Reflow::Transform(const CFX_AffineMatrix* pMatrix, CRF_Data* pData)
850 {
851     if(pData->GetType() == CRF_Data::Path) {
852         CRF_PathData* pPathData = (CRF_PathData*)pData;
853         pPathData->m_pPath2Device.Concat(*pMatrix);
854     }
855     pMatrix->Transform(pData->m_PosX, pData->m_PosY, pData->m_PosX, pData->m_PosY);
856 }
857 FX_BOOL CPDF_LayoutProcessor_Reflow::FinishedCurrLine()
858 {
859     if (NULL == m_pCurrLine) {
860         return FALSE;
861     }
862     int count = m_pCurrLine->GetSize();
863     if(count == 0) {
864         return FALSE;
865     }
866     if(m_fLineHeight > m_fCurrLineHeight) {
867         m_fCurrLineHeight = m_fLineHeight;
868     } else {
869         m_fCurrLineHeight += 2;
870     }
871     if(m_pReflowedPage->m_pReflowed->GetSize() > 0) {
872         m_fCurrLineHeight += m_fLineSpace;
873     }
874     FX_FLOAT height = m_pReflowedPage->m_PageHeight + m_fCurrLineHeight;
875     FX_FLOAT lineHeight = m_fLineHeight;
876     if(lineHeight == 0) {
877         lineHeight = m_fCurrLineHeight;
878     }
879     FX_FLOAT dx = 0;
880     switch(m_TextAlign) {
881         case LayoutCenter:
882             dx = (m_fCurrMaxWidth - m_fCurrLineWidth) / 2;
883             break;
884         case LayoutEnd:
885             dx = m_fCurrMaxWidth - m_fCurrLineWidth;
886             break;
887         case LayoutJustify:
888             break;
889         default:
890             break;
891     }
892     FX_FLOAT dy = - height;
893     int refedSize = m_pReflowedPage->m_pReflowed->GetSize();
894     if(count == 13) {
895         int a = 0;
896     }
897     for(int i = 0; i < count; i++) {
898         CRF_Data* pData = (*m_pCurrLine)[i];
899         m_pReflowedPage->m_pReflowed->Add(pData);
900         FX_FLOAT x = m_StartIndent + dx * (m_TextAlign == LayoutJustify ? i + 1 : 1);
901         CFX_AffineMatrix matrix(1, 0, 0, 1, x, dy);
902         Transform(&matrix, pData);
903     }
904     m_pCurrLine->RemoveAll();
905     m_fCurrLineWidth = 0;
906     m_pReflowedPage->m_PageHeight += m_fCurrLineHeight;
907     m_fCurrLineHeight = 0;
908     return TRUE;
909 }
910 CRF_CharState* CPDF_LayoutProcessor_Reflow::GetCharState(CPDF_TextObject* pObj, CPDF_Font* pFont, FX_FLOAT fHeight, FX_ARGB color)
911 {
912     if (NULL == m_pReflowedPage->m_pCharState) {
913         return NULL;
914     }
915     int count = m_pReflowedPage->m_pCharState->GetSize();
916     for(int i = count - 1; i >= 0; i--) {
917         CRF_CharState* pState = (CRF_CharState*)m_pReflowedPage->m_pCharState->GetAt(i);
918         if(pState->m_Color == color && pState->m_fFontSize == fHeight && pState->m_pFont == pFont && pState->m_pTextObj == pObj) {
919             return pState;
920         }
921     }
922     CRF_CharState pState;
923     pState.m_pTextObj = pObj;
924     pState.m_Color = color;
925     pState.m_pFont = pFont;
926     pState.m_fFontSize = fHeight;
927     int ascent = pFont->GetTypeAscent();
928     int descent = pFont->GetTypeDescent();
929     pState.m_fAscent = ascent * fHeight / (ascent - descent);
930     if(descent == 0) {
931         pState.m_fDescent = 0;
932     } else {
933         pState.m_fDescent = descent * fHeight / (ascent - descent);
934     }
935     pState.m_bVert = FALSE;
936     CPDF_CIDFont *pCIDFont = pFont->GetCIDFont();
937     if(pCIDFont) {
938         pState.m_bVert = pCIDFont->IsVertWriting();
939     }
940     m_pReflowedPage->m_pCharState->Add(pState);
941     return (CRF_CharState*)m_pReflowedPage->m_pCharState->GetAt(count);
942 }
943 int CPDF_LayoutProcessor_Reflow::GetCharWidth(FX_DWORD charCode, CPDF_Font* pFont) const
944 {
945     if(charCode == -1) {
946         return 0;
947     }
948     int w = pFont->GetCharWidthF(charCode);
949     if(w == 0) {
950         CFX_ByteString str;
951         pFont->AppendChar(str, charCode);
952         w = pFont->GetStringWidth(str, 1);
953         if(w == 0) {
954             FX_RECT BBox;
955             pFont->GetCharBBox(charCode, BBox);
956             w = BBox.right - BBox.left;
957         }
958     }
959     return w;
960 }
961 void CPDF_LayoutProcessor_Reflow::CreateRFData(CPDF_PageObject* pObj, CFX_AffineMatrix* pObjMatrix)
962 {
963     if (NULL == m_pReflowedPage->m_pMemoryPool) {
964         return;
965     }
966     if(pObj->m_Type == PDFPAGE_TEXT) {
967         CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj;
968         int count = pTextObj->CountItems();
969         if(!count) {
970             return;
971         }
972         if(count == 1) {
973             CPDF_TextObjectItem Item;
974             pTextObj->GetItemInfo(0, &Item);
975             if(Item.m_CharCode == 49) {
976                 int a = 0;
977             }
978         }
979         CPDF_Font * pFont = pTextObj->GetFont();
980         FX_FLOAT fs = pTextObj->GetFontSize();
981         FX_FLOAT* pmatrix = pTextObj->m_TextState.GetMatrix();
982         FX_FLOAT matrix1 = pmatrix[1];
983         if(pmatrix[2] == 0) {
984             matrix1 = 0;
985         }
986         CFX_AffineMatrix textMatrix(pmatrix[0], matrix1, pmatrix[2], pmatrix[3], 0, 0);
987         FX_FLOAT height = FXSYS_fabs(textMatrix.TransformDistance(fs));
988         if(pObjMatrix) {
989             height = FXSYS_fabs(pObjMatrix->TransformDistance(height));
990         }
991         int r = 0, g = 0, b = 0;
992         pTextObj->m_ColorState.GetFillColor()->GetRGB(r, g, b);
993         FX_ARGB col = r * 0x10000;
994         col += g * 0x100;
995         col += b;
996         CRF_CharState* pState = GetCharState(pTextObj, pFont, height, col);
997         FX_FLOAT dx = 0, dy = 0;
998         FX_RECT ObjBBox;
999         if(pObjMatrix) {
1000             ObjBBox = pTextObj->GetBBox(pObjMatrix);
1001             dx = (float)ObjBBox.left;
1002             dy = (float)ObjBBox.bottom;
1003         } else {
1004             CFX_AffineMatrix matrix;
1005             ObjBBox = pTextObj->GetBBox(&matrix);
1006         }
1007         FX_FLOAT objWidth = 0;
1008         CFX_ByteString str;
1009         FX_BOOL bOrder = TRUE;
1010         CFX_PtrArray tempArray;
1011         int i = 0;
1012         CPDF_TextObjectItem Item;
1013         pTextObj->GetItemInfo(i, &Item);
1014         dx = Item.m_OriginX;
1015         dy = Item.m_OriginY;
1016         textMatrix.Transform(Item.m_OriginX, Item.m_OriginY, dx, dy);
1017         CRF_CharData* pLastData = NULL;
1018         FX_FLOAT horzScale = pTextObj->m_TextState.GetFontSizeV() / pTextObj->m_TextState.GetFontSizeH();
1019         while(i < count) {
1020             pTextObj->GetItemInfo(i, &Item);
1021             if(Item.m_CharCode == -1) {
1022                 i++;
1023                 continue;
1024             }
1025             FX_FLOAT OriginX, OriginY;
1026             textMatrix.Transform(Item.m_OriginX, Item.m_OriginY, OriginX, OriginY);
1027             CRF_CharData* pData = (CRF_CharData*)m_pReflowedPage->m_pMemoryPool->Alloc(sizeof(CRF_CharData));
1028             if (NULL == pData) {
1029                 continue;
1030             }
1031             pData->m_Type = CRF_Data::Text;
1032             if(FXSYS_fabs(OriginY - dy) > FXSYS_fabs(OriginX - dx)) {
1033                 pData->m_PosY = dy;
1034                 pData->m_PosX = pLastData->m_PosX + pLastData->m_Width + textMatrix.TransformDistance(pTextObj->m_TextState.GetObject()->m_CharSpace);
1035             } else {
1036                 pData->m_PosY = OriginY;
1037                 pData->m_PosX = OriginX;
1038             }
1039             int size = tempArray.GetSize();
1040             if(size && pData->m_PosX < pLastData->m_PosX ) {
1041                 for (int j = 0; j < size; j++) {
1042                     CRF_CharData* pData1 = (CRF_CharData*)tempArray.GetAt(j);
1043                     if(pData1->m_PosX > pData->m_PosX) {
1044                         tempArray.InsertAt(j, pData);
1045                         break;
1046                     }
1047                 }
1048             } else {
1049                 tempArray.Add(pData);
1050             }
1051             pLastData = pData;
1052             pData->m_CharCode = Item.m_CharCode;
1053             pData->m_Height = FXSYS_fabs(height);
1054             int w = GetCharWidth(Item.m_CharCode, pFont);
1055             pData->m_Width = FXSYS_fabs(fs * textMatrix.TransformDistance((FX_FLOAT)w) / 1000);
1056             if(horzScale) {
1057                 pData->m_Width /= horzScale;
1058             }
1059             pData->m_pCharState = pState;
1060             i++;
1061         }
1062         count = tempArray.GetSize();
1063         for (int j = 0; j < count; j++) {
1064             CRF_CharData* pData = (CRF_CharData*)tempArray.GetAt(j);
1065             if (m_pTempLine) {
1066                 m_pTempLine->Add(pData);
1067             }
1068         }
1069         tempArray.RemoveAll();
1070     } else if(pObj->m_Type == PDFPAGE_IMAGE) {
1071         CPDF_ImageObject* pImageObj = (CPDF_ImageObject* )pObj;
1072         CRF_ImageData* pRFImage = (CRF_ImageData*)m_pReflowedPage->m_pMemoryPool->Alloc(sizeof(CRF_ImageData));
1073         if (NULL == pRFImage) {
1074             return;
1075         }
1076         pRFImage->m_pBitmap = NULL;
1077         pRFImage->m_Type = CRF_Data::Image;
1078         if (m_pTempLine) {
1079             m_pTempLine->Add(pRFImage);
1080         }
1081         CPDF_Image *pImage = pImageObj->m_pImage;
1082         if (!pImage->m_pDIBSource || !pImage->m_pMask) {
1083             if(pImage->StartLoadDIBSource(m_pReflowedPage->GetFormResDict(pImageObj), m_pReflowedPage->m_pPDFPage->m_pResources, 0, 0, TRUE)) {
1084                 pImage->Continue(NULL);
1085             }
1086         }
1087         CFX_DIBSource* pDibSource = pImage->DetachBitmap();
1088         if (pDibSource) {
1089             pRFImage->m_pBitmap = pDibSource->Clone();
1090             delete pDibSource;
1091         }
1092         CFX_DIBSource* pMask = pImage->DetachMask();
1093         if (pMask) {
1094             if (!pMask->IsAlphaMask()) {
1095                 CFX_DIBitmap* pMaskBmp = pMask->Clone();
1096                 pMaskBmp->ConvertFormat(FXDIB_8bppMask);
1097                 pRFImage->m_pBitmap->MultiplyAlpha(pMaskBmp);
1098                 delete pMaskBmp;
1099             } else {
1100                 pRFImage->m_pBitmap->MultiplyAlpha(pMask);
1101             }
1102             delete pMask;
1103         }
1104         CFX_FloatRect ObjBBox;
1105         if(pObjMatrix) {
1106             ObjBBox = pImageObj->GetBBox(pObjMatrix);
1107         } else {
1108             CFX_AffineMatrix matrix;
1109             ObjBBox = pImageObj->GetBBox(&matrix);
1110         }
1111         pRFImage->m_Width = ObjBBox.Width();
1112         pRFImage->m_Height = ObjBBox.Height();
1113         pRFImage->m_PosX = 0;
1114         pRFImage->m_PosY = 0;
1115         CFX_AffineMatrix matrix(1, 0, 0, -1, 0, 0);
1116         matrix.Concat(pImageObj->m_Matrix);
1117         matrix.Concat(*pObjMatrix);
1118         pRFImage->m_Matrix.Set(matrix.a == 0 ? 0 : matrix.a / FXSYS_fabs(matrix.a),
1119                                matrix.b == 0 ? 0 : matrix.b / FXSYS_fabs(matrix.b),
1120                                matrix.c == 0 ? 0 : matrix.c / FXSYS_fabs(matrix.c),
1121                                matrix.d == 0 ? 0 : matrix.d / FXSYS_fabs(matrix.d), 0, 0);
1122     } else if(pObj->m_Type == PDFPAGE_PATH) {
1123     }
1124 }
1125 FX_FLOAT CPDF_LayoutProcessor_Reflow:: GetDatasWidth(int beginPos, int endpos)
1126 {
1127     if(endpos < beginPos || !m_pTempLine) {
1128         return 0;
1129     }
1130     if(endpos > m_pTempLine->GetSize() - 1) {
1131         endpos = m_pTempLine->GetSize() - 1;
1132     }
1133     CRF_Data* pBeginData = (*m_pTempLine)[beginPos];
1134     CRF_Data* pEndData = (*m_pTempLine)[endpos];
1135     return pEndData->m_PosX - pBeginData->m_PosX + pEndData->m_Width;
1136 }
1137 FX_WCHAR CPDF_LayoutProcessor_Reflow::GetPreChar()
1138 {
1139     if (NULL == m_pCurrLine) {
1140         return -1;
1141     }
1142     int index = m_pCurrLine->GetSize() - 1;
1143     CRF_CharData* pCharData = NULL;
1144     while (index >= 0 && !pCharData) {
1145         CRF_Data* pData = (*m_pCurrLine)[index];
1146         if(pData->GetType() == CRF_Data::Text) {
1147             pCharData = (CRF_CharData*)pData;
1148         } else {
1149             return -1;
1150         }
1151         index --;
1152     }
1153     if(m_pReflowedPage) {
1154         index = m_pReflowedPage->m_pReflowed->GetSize() - 1;
1155     }
1156     while(!pCharData && index >= 0) {
1157         CRF_Data* pData = (*m_pReflowedPage->m_pReflowed)[index];
1158         if(pData->GetType() == CRF_Data::Text) {
1159             pCharData = (CRF_CharData*)pData;
1160         } else {
1161             return -1;
1162         }
1163         index --;
1164     }
1165     if(pCharData) {
1166         CFX_WideString str = pCharData->m_pCharState->m_pFont->UnicodeFromCharCode(pCharData->m_CharCode);
1167         return str.GetAt(0);
1168     }
1169     return -1;
1170 }
1171 int CPDF_LayoutProcessor_Reflow::ProcessInsertObject(CPDF_TextObject* pObj, CFX_AffineMatrix formMatrix)
1172 {
1173     if(!pObj || !m_pPreObj || !m_pCurrLine) {
1174         return 0;
1175     }
1176     if(m_pCurrLine->GetSize() == 0) {
1177         return 0;
1178     }
1179     CPDF_TextObjectItem item;
1180     int nItem = m_pPreObj->CountItems();
1181     m_pPreObj->GetItemInfo(nItem - 1, &item);
1182     FX_FLOAT last_pos = item.m_OriginX;
1183     FX_FLOAT last_width = GetCharWidth(item.m_CharCode, m_pPreObj->GetFont()) * m_pPreObj->GetFontSize() / 1000;
1184     last_width = FXSYS_fabs(last_width);
1185     pObj->GetItemInfo(0, &item);
1186     FX_FLOAT this_width = GetCharWidth(item.m_CharCode, pObj->GetFont()) * pObj->GetFontSize() / 1000;
1187     this_width = FXSYS_fabs(this_width);
1188     FX_FLOAT threshold = last_width > this_width ? last_width / 4 : this_width / 4;
1189     CFX_AffineMatrix prev_matrix, prev_reverse;
1190     m_pPreObj->GetTextMatrix(&prev_matrix);
1191     prev_matrix.Concat(m_perMatrix);
1192     prev_reverse.SetReverse(prev_matrix);
1193     FX_FLOAT x = pObj->GetPosX(), y = pObj->GetPosY();
1194     formMatrix.Transform(x, y);
1195     prev_reverse.Transform(x, y);
1196     FX_WCHAR preChar  = GetPreChar();
1197     CFX_WideString wstrItem = pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode);
1198     FX_WCHAR curChar = wstrItem.GetAt(0);
1199     if (FXSYS_fabs(y) > threshold * 2) {
1200         if (preChar == L'-') {
1201             return 3;
1202         }
1203         if (preChar != L' ') {
1204             return 1;
1205         }
1206         return 2;
1207     }
1208     if ((x - last_pos - last_width) > threshold && curChar != L' ' && preChar != L' ') {
1209         return 1;
1210     }
1211     return 0;
1212 }
1213 int32_t CPDF_LayoutProcessor_Reflow::LogicPreObj(CPDF_TextObject* pObj)
1214 {
1215     CPDF_TextObject* pPreObj = m_pPreObj;
1216     m_pPreObj = pObj;
1217     if(!pObj || !pPreObj) {
1218         return 0;
1219     }
1220     CPDF_TextObjectItem item;
1221     pPreObj->GetItemInfo(pPreObj->CountItems() - 1, &item);
1222     FX_FLOAT last_pos = item.m_OriginX;
1223     FX_FLOAT last_width = pPreObj->GetFont()->GetCharWidthF(item.m_CharCode) * pPreObj->GetFontSize() / 1000;
1224     last_width = FXSYS_fabs(last_width);
1225     pObj->GetItemInfo(0, &item);
1226     FX_FLOAT this_width = pObj->GetFont()->GetCharWidthF(item.m_CharCode) * pObj->GetFontSize() / 1000;
1227     this_width = FXSYS_fabs(this_width);
1228     FX_FLOAT threshold = last_width > this_width ? last_width / 4 : this_width / 4;
1229     CFX_AffineMatrix prev_matrix, prev_reverse;
1230     pPreObj->GetTextMatrix(&prev_matrix);
1231     prev_reverse.SetReverse(prev_matrix);
1232     FX_FLOAT x = pObj->GetPosX(), y = pObj->GetPosY();
1233     prev_reverse.Transform(x, y);
1234     CFX_WideString wstrItem = pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode);
1235     FX_WCHAR curChar = wstrItem.GetAt(0);
1236     if (FXSYS_fabs(y) > threshold * 2) {
1237         return 2;
1238     }
1239     FX_WCHAR preChar = 0;
1240     if (FXSYS_fabs(last_pos + last_width - x) > threshold && curChar != L' ') {
1241         return 1;
1242     }
1243     return 0;
1244     m_pPreObj = pObj;
1245     if(!pPreObj) {
1246         return 0;
1247     }
1248     if(pPreObj->m_Type != pObj->m_Type) {
1249         return 0;
1250     }
1251     CFX_FloatRect rcCurObj(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
1252     CFX_FloatRect rcPreObj(pPreObj->m_Left, pPreObj->m_Bottom, pPreObj->m_Right, pPreObj->m_Top);
1253     if(pObj->m_Type == PDFPAGE_IMAGE) {
1254         if(rcPreObj.Contains(rcCurObj)) {
1255             return 2;
1256         }
1257         if(rcCurObj.Contains(rcPreObj)) {
1258             return 2;
1259         }
1260         return 0;
1261     }
1262     if(pObj->m_Type == PDFPAGE_TEXT) {
1263         if(!((rcPreObj.bottom > rcCurObj.top) || (rcPreObj.top < rcCurObj.bottom))) {
1264             FX_FLOAT height = FX_MIN(rcPreObj.Height(), rcCurObj.Height());
1265             if((rcCurObj.left - rcPreObj.right) > height / 3) {
1266                 return 3;
1267             }
1268         }
1269         if(FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) >= 2 || FXSYS_fabs(rcPreObj.Height() - rcCurObj.Height()) >= 2 ) {
1270             return 0;
1271         }
1272         CPDF_TextObject* pPreTextObj = (CPDF_TextObject*)pPreObj;
1273         CPDF_TextObject* pCurTextObj = (CPDF_TextObject*)pObj;
1274         int nPreCount = pPreTextObj->CountItems();
1275         int nCurCount = pCurTextObj->CountItems();
1276         if (nPreCount != nCurCount) {
1277             return 0;
1278         }
1279         FX_BOOL bSame = TRUE;
1280         for (int i = 0; i < nPreCount; i++) {
1281             CPDF_TextObjectItem itemPer, itemCur;
1282             pPreTextObj->GetItemInfo(i, &itemPer);
1283             pCurTextObj->GetItemInfo(i, &itemCur);
1284             if (itemCur.m_CharCode != itemPer.m_CharCode) {
1285                 return 0;
1286             }
1287             if (itemCur.m_OriginX != itemPer.m_OriginX) {
1288                 bSame = FALSE;
1289             }
1290             if (itemCur.m_OriginY != itemPer.m_OriginY) {
1291                 bSame = FALSE;
1292             }
1293         }
1294         if(rcPreObj.left == rcCurObj.left && rcPreObj.top == rcCurObj.top) {
1295             return 1;
1296         }
1297         if(FXSYS_fabs(rcPreObj.left - rcCurObj.left) < rcPreObj.Width() / 3
1298                 && FXSYS_fabs(rcPreObj.top - rcCurObj.top) < rcPreObj.Height() / 3) {
1299             return 2;
1300         }
1301     }
1302     return 0;
1303 }
1304 FX_BOOL CPDF_LayoutProcessor_Reflow::IsSameTextObject(CPDF_TextObject* pTextObj1, CPDF_TextObject* pTextObj2)
1305 {
1306     if (!pTextObj1 || !pTextObj2) {
1307         return FALSE;
1308     }
1309     CFX_FloatRect rcPreObj(pTextObj2->m_Left, pTextObj2->m_Bottom, pTextObj2->m_Right, pTextObj2->m_Top);
1310     CFX_FloatRect rcCurObj(pTextObj1->m_Left, pTextObj1->m_Bottom, pTextObj1->m_Right, pTextObj1->m_Top);
1311     if (rcPreObj.IsEmpty() && rcCurObj.IsEmpty()) {
1312         return FALSE;
1313     }
1314     if (!rcPreObj.IsEmpty() || !rcCurObj.IsEmpty()) {
1315         rcPreObj.Intersect(rcCurObj);
1316         if (rcPreObj.IsEmpty()) {
1317             return FALSE;
1318         }
1319         if (FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) > rcCurObj.Width() / 2) {
1320             return FALSE;
1321         }
1322         if (pTextObj2->GetFontSize() != pTextObj1->GetFontSize()) {
1323             return FALSE;
1324         }
1325     }
1326     int nPreCount = pTextObj2->CountItems();
1327     int nCurCount = pTextObj1->CountItems();
1328     if (nPreCount != nCurCount) {
1329         return FALSE;
1330     }
1331     for (int i = 0; i < nPreCount; i++) {
1332         CPDF_TextObjectItem itemPer, itemCur;
1333         pTextObj2->GetItemInfo(i, &itemPer);
1334         pTextObj1->GetItemInfo(i, &itemCur);
1335         if (itemCur.m_CharCode != itemPer.m_CharCode) {
1336             return FALSE;
1337         }
1338     }
1339     return TRUE;
1340 }
1341 void CPDF_LayoutProcessor_Reflow::ProcessTextObject(CPDF_TextObject *pTextObj, FX_FLOAT reflowWidth, CFX_AffineMatrix objMatrix)
1342 {
1343     if(reflowWidth < 0 || !m_pCurrLine || !m_pTempLine) {
1344         return;
1345     }
1346     if(IsSameTextObject(pTextObj, m_pPreObj)) {
1347         return;
1348     }
1349     CPDF_PageObject* pPreObj = m_pPreObj;
1350     int32_t logic = ProcessInsertObject(pTextObj, objMatrix);
1351     m_pPreObj = pTextObj;
1352     m_perMatrix.Copy(objMatrix);
1353     int size = m_pTempLine->GetSize();
1354     int curs = m_pCurrLine->GetSize();
1355     CreateRFData(pTextObj);
1356     size = m_pTempLine->GetSize();
1357     int reds = m_pReflowedPage->m_pReflowed->GetSize();
1358     if(size == 0) {
1359         return;
1360     }
1361     if(logic == 1) {
1362         m_fCurrLineWidth += pTextObj->GetBBox(&objMatrix).Height() / 3;
1363     } else if(logic == 3 && curs) {
1364         m_fCurrLineWidth -= (*m_pCurrLine)[curs - 1]->m_Width;
1365         m_pCurrLine->Delete(curs - 1);
1366     }
1367     int beginPos = 0, endPos = m_pTempLine->GetSize() - 1;
1368     while(beginPos <= endPos) {
1369         int tempBeginPos = beginPos;
1370         int tempEndPos = endPos;
1371         FX_FLOAT all_width = GetDatasWidth( beginPos, endPos);
1372         if(all_width < reflowWidth - m_fCurrLineWidth) {
1373             CRF_CharData* pBeginData = (CRF_CharData*)(*m_pTempLine)[beginPos];
1374             CFX_AffineMatrix matrix(1, 0, 0, 1, -pBeginData->m_PosX + m_fCurrLineWidth, -pBeginData->m_PosY);
1375             Transform(&matrix, m_pTempLine, beginPos, endPos - beginPos + 1);
1376             AddTemp2CurrLine(beginPos, endPos - beginPos + 1);
1377             m_pTempLine->RemoveAll();
1378             return;
1379         }
1380         int     midPos ;
1381         if(tempBeginPos >= tempEndPos && tempEndPos != 0) {
1382             midPos = tempEndPos;
1383         } else {
1384             while (tempBeginPos < tempEndPos ) {
1385                 midPos = (tempEndPos - tempBeginPos) / 2 + tempBeginPos;
1386                 if(midPos == tempBeginPos || midPos == tempEndPos) {
1387                     break;
1388                 }
1389                 FX_FLOAT w = GetDatasWidth( beginPos, midPos);
1390                 if(w < reflowWidth - m_fCurrLineWidth) {
1391                     tempBeginPos = midPos;
1392                 } else {
1393                     tempEndPos = midPos;
1394                 }
1395             }
1396             midPos = tempBeginPos;
1397             if(midPos == 0) {
1398                 FX_FLOAT w = GetDatasWidth( beginPos, 1);
1399                 if(w > reflowWidth - m_fCurrLineWidth) {
1400                     midPos = -1;
1401                 }
1402             }
1403         }
1404         if(midPos == -1) {
1405             int count = m_pCurrLine->GetSize();
1406             if(count == 0) {
1407                 midPos = 0;
1408             }
1409         }
1410         int f = -1;
1411         int i = 0;
1412         for(i = midPos; i >= beginPos; i--) {
1413             CRF_CharData* pData = (CRF_CharData*)(*m_pTempLine)[i];
1414             CFX_WideString Wstr = pData->m_pCharState->m_pFont->UnicodeFromCharCode(pData->m_CharCode);
1415             FX_WCHAR cha = Wstr.GetAt(0);
1416             if(i < m_pTempLine->GetSize() - 1) {
1417                 CRF_CharData* pNextData = (CRF_CharData*)(*m_pTempLine)[i + 1];
1418                 if(pNextData->m_PosX - (pData->m_PosX + pData->m_Width) >= pData->m_Height / 4) {
1419                     f = i;
1420                     i++;
1421                 }
1422             }
1423             if(f == -1) {
1424                 if(IsCanBreakAfter((FX_DWORD)cha)) {
1425                     f = i;
1426                     i++;
1427                 } else if(IsCanBreakBefore((FX_DWORD)cha)) {
1428                     f = i - 1;
1429                     if(f < beginPos) {
1430                         f = -1;
1431                     }
1432                 }
1433             }
1434             if(f != -1) {
1435                 CRF_CharData* pBeginData = (CRF_CharData*)(*m_pTempLine)[beginPos];
1436                 CFX_AffineMatrix matrix(1, 0, 0, 1, -pBeginData->m_PosX + m_fCurrLineWidth, -pBeginData->m_PosY);
1437                 Transform(&matrix, m_pTempLine, beginPos, f - beginPos + 1);
1438                 CRF_Data* pData = (*m_pTempLine)[0];
1439                 AddTemp2CurrLine(beginPos, f - beginPos + 1);
1440                 beginPos = i;
1441                 FinishedCurrLine();
1442                 f = 1;
1443                 break;
1444             }
1445         }
1446         if(f == -1 && i < beginPos) {
1447             if( m_pCurrLine->GetSize()) {
1448                 int count = m_pCurrLine->GetSize();
1449                 f = -1;
1450                 for(int i = count - 1; i >= 0; i--) {
1451                     CRF_Data* pData = (*m_pCurrLine)[i];
1452                     if(pData->GetType() != CRF_Data::Text) {
1453                         f = i + 1;
1454                     } else {
1455                         CRF_CharData* pCharData = (CRF_CharData*)pData;
1456                         CFX_WideString Wstr = pCharData->m_pCharState->m_pFont->UnicodeFromCharCode(pCharData->m_CharCode);
1457                         FX_WCHAR cha = Wstr.GetAt(0);
1458                         if(IsCanBreakAfter(cha)) {
1459                             f = i + 1;
1460                             i++;
1461                         } else if(IsCanBreakBefore(cha)) {
1462                             f = i;
1463                         }
1464                         if(f == 0) {
1465                             f = -1;
1466                         }
1467                     }
1468                     if(f != -1) {
1469                         FinishedCurrLine();
1470                         if(f < count) {
1471                             int reflowdCount = m_pReflowedPage->m_pReflowed->GetSize();
1472                             int pos = reflowdCount + f - count;
1473                             CRF_CharData* pData = (CRF_CharData*)(*m_pReflowedPage->m_pReflowed)[pos];
1474                             CFX_AffineMatrix matrix(1, 0, 0, 1, -pData->m_PosX + m_fCurrLineWidth, -pData->m_PosY);
1475                             Transform(&matrix, m_pReflowedPage->m_pReflowed, pos, reflowdCount - pos);
1476                             for(int j = pos; j < reflowdCount; j++) {
1477                                 AddData2CurrLine((*m_pReflowedPage->m_pReflowed)[j]);
1478                             }
1479                             m_pReflowedPage->m_pReflowed->Delete(pos, count - f);
1480                             if(logic == 3) {
1481                                 m_fCurrLineWidth += pTextObj->GetBBox(&objMatrix).Height() / 3;
1482                             }
1483                         }
1484                         break;
1485                     }
1486                 }
1487             }
1488             if(f == -1) {
1489                 CRF_CharData* pData = (CRF_CharData*)(*m_pTempLine)[beginPos];
1490                 CFX_AffineMatrix matrix(1, 0, 0, 1, -pData->m_PosX + m_fCurrLineWidth, -pData->m_PosY);
1491                 if(beginPos == midPos) {
1492                     Transform(&matrix, pData);
1493                     FX_RECT rect;
1494                     pData->m_pCharState->m_pFont->GetFontBBox(rect);
1495                     FX_FLOAT* pmatrix = pTextObj->m_TextState.GetMatrix();
1496                     CFX_AffineMatrix textMatrix(pmatrix[0], pmatrix[1], pmatrix[2], pmatrix[3], 0, 0);
1497                     FX_FLOAT width = pData->m_Height * (rect.right - rect.left) / 1000;
1498                     FX_FLOAT f = (reflowWidth - m_fCurrLineWidth) / width;
1499                     pData->m_PosY *= f;
1500                     pData->m_Width *= f;
1501                     pData->m_Height *= f;
1502                     pData->m_pCharState = GetCharState(pData->m_pCharState->m_pTextObj, pData->m_pCharState->m_pFont, pData->m_Height, pData->m_pCharState->m_Color);
1503                     AddData2CurrLine(pData);
1504                 } else {
1505                     for(int m = beginPos; m <= midPos; m++) {
1506                         CRF_CharData* pData = (CRF_CharData*)(*m_pTempLine)[m];
1507                         Transform(&matrix, pData);
1508                         AddData2CurrLine(pData);
1509                     }
1510                 }
1511                 FinishedCurrLine();
1512                 beginPos = midPos + 1;
1513             }
1514         }
1515     }
1516     m_pTempLine->RemoveAll();
1517     return;
1518 }
1519 void CPDF_LayoutProcessor_Reflow::ProcessUnitaryObjs(CPDF_PageObjects *pObjs, FX_FLOAT reflowWidth, CFX_AffineMatrix objMatrix)
1520 {
1521     if(!pObjs) {
1522         return;
1523     }
1524     CFX_FloatRect ObjBBox = pObjs->CalcBoundingBox();
1525     objMatrix.TransformRect(ObjBBox);
1526     FX_FLOAT ObjWidth = ObjBBox.Width();
1527     FX_FLOAT ObjHeight = ObjBBox.Height();
1528     CFX_AffineMatrix matrix;
1529     if(ObjWidth <= reflowWidth - m_fCurrLineWidth) {
1530         matrix.Set(1, 0, 0, 1, m_fCurrLineWidth , 0);
1531     } else if(ObjWidth <= reflowWidth) {
1532         FinishedCurrLine();
1533         matrix.Set(1, 0, 0, 1, 0, 0);
1534     } else {
1535         FinishedCurrLine();
1536         FX_FLOAT f = reflowWidth / ObjWidth ;
1537         matrix.Set(f, 0, 0, f, 0, 0);
1538     }
1539     CFX_AffineMatrix tempMatrix = matrix;
1540     matrix.Concat(objMatrix);
1541     FX_POSITION pos = pObjs->GetFirstObjectPosition();
1542     while(pos) {
1543         CPDF_PageObject* pObj = pObjs->GetNextObject(pos);
1544         if(pObj->m_Type == PDFPAGE_TEXT) {
1545             int32_t ret = LogicPreObj((CPDF_TextObject*)pObj);
1546             if(ret == 1 || ret == 2) {
1547                 continue;
1548             }
1549         }
1550         CreateRFData(pObj, &matrix);
1551     }
1552     if (m_pTempLine) {
1553         Transform(&tempMatrix, m_pTempLine, 0, m_pTempLine->GetSize());
1554         AddTemp2CurrLine(0, m_pTempLine->GetSize());
1555         m_pTempLine->RemoveAll();
1556     }
1557 }
1558 void CPDF_LayoutProcessor_Reflow::ProcessPathObject(CPDF_PathObject *pObj, FX_FLOAT reflowWidth)
1559 {
1560 }