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