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"
10IPDF_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}
22CPDF_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}
37CPDF_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}
50void 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}
65void 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}
130LayoutStatus 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}
146LayoutStatus 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}
157int CPDF_LayoutProcessor_Reflow::GetPosition()
158{
159    return m_PausePosition;
160}
161FX_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}
183FX_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}
210void 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}
321CFX_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}
352FX_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}
377FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,
378                        FX_FLOAT& interlow, FX_FLOAT& interhigh);
379FX_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}
410FX_INT32 IsCanMergeParagraph(IPDF_LayoutElement* pPrevElement, IPDF_LayoutElement* pNextElement)
411{
412    FX_INT32 analogial = 100;
413    FX_INT32 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        FX_INT32 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    FX_INT32 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}
518void 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        FX_INT32 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        FX_INT32 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}
714FX_INT32 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}
759FX_FLOAT	CPDF_LayoutProcessor_Reflow::ConverWidth(FX_FLOAT width)
760{
761    return width;
762}
763void 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}
796void 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}
806void 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}
820void 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}
831void CPDF_LayoutProcessor_Reflow::UpdateCurrLine()
832{
833}
834void 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}
849void 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}
857FX_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}
910CRF_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}
943int 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}
961void 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}
1125FX_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}
1137FX_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}
1171int 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}
1213FX_INT32 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}
1304FX_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}
1341void 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    FX_INT32 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}
1519void 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            FX_INT32 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}
1558void CPDF_LayoutProcessor_Reflow::ProcessPathObject(CPDF_PathObject *pObj, FX_FLOAT reflowWidth)
1559{
1560}
1561