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 = new CPDF_LayoutProcessor_Reflow();
16    pReflowEngine->Init(TopIndent, fWidth, fHeight, (CPDF_ReflowedPage*)pReflowedPage, flags, lineSpace);
17    return pReflowEngine;
18}
19CPDF_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}
34CPDF_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}
47void 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}
62void 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}
127LayoutStatus 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}
143LayoutStatus 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}
154int CPDF_LayoutProcessor_Reflow::GetPosition()
155{
156    return m_PausePosition;
157}
158FX_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}
180FX_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}
207void 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_memset32(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_memset32(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}
318CFX_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}
349FX_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}
374FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2,
375                        FX_FLOAT& interlow, FX_FLOAT& interhigh);
376FX_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}
407FX_INT32 IsCanMergeParagraph(IPDF_LayoutElement* pPrevElement, IPDF_LayoutElement* pNextElement)
408{
409    FX_INT32 analogial = 100;
410    FX_INT32 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        FX_INT32 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    FX_INT32 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}
515void 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        FX_INT32 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_memset32(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        FX_INT32 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}
708FX_INT32 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}
753FX_FLOAT	CPDF_LayoutProcessor_Reflow::ConverWidth(FX_FLOAT width)
754{
755    return width;
756}
757void 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}
787void 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}
797void 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}
811void 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}
822void CPDF_LayoutProcessor_Reflow::UpdateCurrLine()
823{
824}
825void 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}
840void 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}
848FX_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}
901CRF_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}
934int 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}
952void 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}
1116FX_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}
1128FX_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}
1162int 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}
1204FX_INT32 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}
1295FX_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}
1332void 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    FX_INT32 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}
1510void 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            FX_INT32 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}
1549void CPDF_LayoutProcessor_Reflow::ProcessPathObject(CPDF_PathObject *pObj, FX_FLOAT reflowWidth)
1550{
1551}
1552