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"
9CPDF_ProgressiveReflowPageParser::CPDF_ProgressiveReflowPageParser()
10{
11    m_nObjProcessed = 0;
12    m_pReflowEngine = NULL;
13    m_pProvider = NULL;
14}
15CPDF_ProgressiveReflowPageParser::~CPDF_ProgressiveReflowPageParser()
16{
17    if(m_pProvider) {
18        delete m_pProvider;
19    }
20    m_pProvider = NULL;
21    if(m_pReflowEngine) {
22        delete m_pReflowEngine;
23    }
24    m_pReflowEngine = NULL;
25}
26void CPDF_ProgressiveReflowPageParser::Init()
27{
28    m_Status = Ready;
29}
30CPDF_ReflowedPage::CPDF_ReflowedPage(CFX_GrowOnlyPool*	pMemoryPool)
31{
32    m_PageWidth = 0;
33    m_PageHeight = 0;
34    m_bWaiting = TRUE;
35    if(pMemoryPool) {
36        m_pMemoryPool = pMemoryPool;
37        m_bCreateMemoryPool = FALSE;
38    } else {
39        m_pMemoryPool = FX_NEW CFX_GrowOnlyPool;
40        m_bCreateMemoryPool = TRUE;
41    }
42    m_pCharState = FX_NEW CRF_CharStateArray(10);
43    m_pReflowed = FX_NEW CRF_DataPtrArray(500);
44    m_pPageInfos = NULL;
45}
46CPDF_ReflowedPage::~CPDF_ReflowedPage()
47{
48    if (m_pReflowed) {
49        for(int i = 0; i < m_pReflowed->GetSize(); i++) {
50            CRF_Data* pData = (*m_pReflowed)[i];
51            if(pData->m_Type == CRF_Data::Image) {
52                delete ((CRF_ImageData*)pData)->m_pBitmap;
53            }
54        }
55        m_pReflowed->RemoveAll();
56        delete m_pReflowed;
57    }
58    m_pReflowed = NULL;
59    if (m_pCharState) {
60        m_pCharState->RemoveAll();
61        delete m_pCharState;
62    }
63    m_pCharState = NULL;
64    if(m_bCreateMemoryPool && m_pMemoryPool) {
65        m_pMemoryPool->FreeAll();
66    }
67    if (m_pMemoryPool) {
68        delete m_pMemoryPool;
69    }
70    m_pMemoryPool = NULL;
71    m_pPDFPage = NULL;
72    if (m_pPageInfos) {
73        ReleasePageObjsMemberShip();
74    }
75}
76FX_BOOL CPDF_ReflowedPage::RetainPageObjsMemberShip()
77{
78    if (NULL == m_pPDFPage) {
79        return FALSE;
80    }
81    if (NULL == m_pPageInfos) {
82        m_pPageInfos = FX_NEW CFX_MapPtrToPtr();
83    } else {
84        return TRUE;
85    }
86    FX_POSITION	pos = m_pPDFPage->GetFirstObjectPosition();
87    if (!pos)	{
88        return FALSE;
89    }
90    CPDF_PageObject* pPageObj = NULL;
91    while (pos) {
92        pPageObj = m_pPDFPage->GetNextObject(pos);
93        MarkPageObjMemberShip(pPageObj, NULL);
94        pPageObj = NULL;
95    }
96    return TRUE;
97}
98void CPDF_ReflowedPage::MarkPageObjMemberShip(CPDF_PageObject* pObj, CRF_PageInfo* pParent)
99{
100    if (NULL == m_pPageInfos) {
101        return;
102    }
103    CRF_PageInfo* pPageInfo = FX_NEW CRF_PageInfo(pObj, pParent);
104    if (NULL == pPageInfo) {
105        return;
106    }
107    m_pPageInfos->SetAt(pObj, pPageInfo);
108    if (PDFPAGE_FORM != pObj->m_Type) {
109        return;
110    }
111    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj;
112    FX_POSITION	pos;
113    pos = pFormObj->m_pForm->GetFirstObjectPosition();
114    if (!pos)	{
115        return;
116    }
117    CPDF_PageObject* pPageObj = NULL;
118    while (pos) {
119        pPageObj = pFormObj->m_pForm->GetNextObject(pos);
120        MarkPageObjMemberShip(pPageObj, pPageInfo);
121        pPageObj = NULL;
122    }
123}
124void CPDF_ReflowedPage::ReleasePageObjsMemberShip()
125{
126    if (NULL == m_pPageInfos) {
127        return;
128    }
129    CPDF_PageObject* pPageObj = NULL;
130    CRF_PageInfo* pPageInfo = NULL;
131    FX_POSITION pos = m_pPageInfos->GetStartPosition();
132    while (pos) {
133        m_pPageInfos->GetNextAssoc(pos, (void*&)pPageObj, (void*&)pPageInfo);
134        delete pPageInfo;
135    }
136    m_pPageInfos->RemoveAll();
137    delete m_pPageInfos;
138    m_pPageInfos = NULL;
139}
140CPDF_Dictionary* CPDF_ReflowedPage::GetFormResDict(CPDF_PageObject* pObj)
141{
142    if (NULL == m_pPageInfos) {
143        return NULL;
144    }
145    if (FALSE == RetainPageObjsMemberShip()) {
146        return NULL;
147    }
148    CRF_PageInfo* pPageInfo = (CRF_PageInfo*)m_pPageInfos->GetValueAt(pObj);
149    if (NULL == pPageInfo) {
150        return NULL;
151    }
152    return pPageInfo->GetFormDict();
153}
154void CPDF_ReflowedPage::GetDisplayMatrix(CFX_AffineMatrix& matrix, FX_INT32 xPos, FX_INT32 yPos, FX_INT32 xSize, FX_INT32 ySize, FX_INT32 iRotate, const CFX_AffineMatrix* pPageMatrix)
155{
156    CFX_AffineMatrix display_matrix;
157    if(m_PageHeight == 0) {
158        matrix.Set(1, 0, 0, -1, 0, 0);
159        return;
160    }
161    FX_INT32 x0, y0, x1, y1, x2, y2;
162    iRotate %= 4;
163    switch (iRotate) {
164        case 0:
165            x0 = xPos;
166            y0 = yPos;
167            x1 = xPos;
168            y1 = yPos + ySize;
169            x2 = xPos + xSize;
170            y2 = yPos;
171            break;
172        case 3:
173            x0 = xPos;
174            y0 = ySize + yPos;
175            x1 =  xPos + xSize;
176            y1 = yPos + ySize;
177            x2 = xPos;
178            y2 = yPos;
179            break;
180        case 2:
181            x0 = xSize + xPos;
182            y0 = ySize + yPos;
183            x1 = xSize + xPos ;
184            y1 = yPos;
185            x2 = xPos;
186            y2 =  ySize + yPos;
187            break;
188        case 1:
189            x0 = xPos + xSize;
190            y0 = yPos;
191            x1 = xPos;
192            y1 = yPos;
193            x2 = xPos + xSize;
194            y2 = yPos + ySize;
195            break;
196    }
197    display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth),
198                       FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth),
199                       FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight),
200                       FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight),
201                       (FX_FLOAT)(x0), (FX_FLOAT)(y0));
202    matrix.Set(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
203    matrix.Concat(display_matrix);
204    return;
205}
206FX_FLOAT CPDF_ReflowedPage::GetPageHeight()
207{
208    return m_PageHeight;
209}
210void CPDF_ReflowedPage::FocusGetData(const CFX_AffineMatrix matrix, FX_INT32 x, FX_INT32 y, CFX_ByteString& str)
211{
212    if (NULL == m_pReflowed) {
213        return;
214    }
215    CFX_AffineMatrix revMatrix;
216    revMatrix.SetReverse(matrix);
217    FX_FLOAT x1, y1;
218    revMatrix.Transform((float)x, (float)y, x1, y1);
219    int count = m_pReflowed->GetSize();
220    FX_FLOAT dx = 1000, dy = 1000;
221    FX_INT32 pos = 0;
222    FX_INT32 i;
223    for(i = 0; i < count; i++) {
224        CRF_Data* pData = (*m_pReflowed)[i];
225        FX_FLOAT tempdy = FXSYS_fabs(pData->m_PosY - y1);
226        if(FXSYS_fabs(tempdy - dy) < 1) {
227            continue;
228        }
229        CFX_FloatRect rect (0, pData->m_PosY + pData->m_Height, this->m_PageWidth, pData->m_PosY);
230        if(rect.Contains(x1, y1)) {
231            pos = i;
232            dx = 0;
233            dy = 0;
234            break;
235        } else if(tempdy < dy) {
236            dy = tempdy;
237            dx = FXSYS_fabs(pData->m_PosX - x1);
238            pos = i;
239        } else if (tempdy == dy) {
240            FX_FLOAT tempdx = FXSYS_fabs(pData->m_PosX - x1);
241            if(tempdx < dx) {
242                dx = tempdx;
243                pos = i;
244            }
245        } else if (tempdy > dy) {
246            break;
247        }
248    }
249    if(dx != 0 || dy != 0) {
250        count = count < (pos + 10) ? count : (pos + 10);
251        for(i = 0 > (pos - 10) ? 0 : (pos - 10); i < count; i++) {
252            CRF_Data* pData = (*m_pReflowed)[i];
253            FX_FLOAT tempdy = FXSYS_fabs(pData->m_PosY - y1);
254            if(tempdy < dy) {
255                dy = tempdy;
256                dx = FXSYS_fabs(pData->m_PosX - x1);
257                pos = i;
258            } else if (tempdy == dy) {
259                FX_FLOAT tempdx = FXSYS_fabs(pData->m_PosX - x1);
260                if(tempdx < dx) {
261                    dx = tempdx;
262                    pos = i;
263                }
264            }
265        }
266    }
267    str.Format("%d", pos);
268}
269FX_BOOL CPDF_ReflowedPage::FocusGetPosition(const CFX_AffineMatrix matrix, CFX_ByteString str, FX_INT32& x, FX_INT32& y)
270{
271    if (NULL == m_pReflowed) {
272        return FALSE;
273    }
274    FX_INT32 pos = FXSYS_atoi(str);
275    if(pos < 0 || pos >= m_pReflowed->GetSize()) {
276        return FALSE;
277    }
278    CRF_Data* pData = (*m_pReflowed)[pos];
279    FX_FLOAT x1, y1;
280    matrix.Transform(pData->m_PosX, pData->m_PosY + pData->m_Height, x1, y1);
281    x = (int)x1;
282    y = (int)y1;
283    return TRUE;
284}
285int CPDF_ProgressiveReflowPageParser::GetPosition()
286{
287    if(!m_pProvider) {
288        return 0;
289    }
290    if(!m_pReflowEngine) {
291        return m_pProvider->GetPosition() / 2;
292    }
293    return m_pProvider->GetPosition() / 2 + m_pReflowEngine->GetPosition() / 2;
294}
295void CPDF_ProgressiveReflowPageParser::Continue(IFX_Pause* pPause)
296{
297    if (NULL == m_pReflowPage) {
298        return;
299    }
300    if(m_Status != ToBeContinued) {
301        return;
302    }
303    m_pPause = pPause;
304    if(m_pReflowEngine) {
305        if(m_pReflowEngine->Continue() != LayoutToBeContinued) {
306            m_Status = Done;
307        }
308    } else {
309        if(m_pProvider->Continue() == LayoutFinished) {
310            m_pReflowEngine = IPDF_LayoutProcessor::Create_LayoutProcessor_Reflow(m_TopIndent, m_ReflowedWidth, m_fScreenHeight, m_pReflowPage, m_flags, m_ParseStyle.m_LineSpace);
311            CFX_AffineMatrix matrix;
312            m_pPDFPage->GetDisplayMatrix(matrix, 0, 0, (int)(m_pPDFPage->GetPageWidth()), (int)(m_pPDFPage->GetPageHeight()), 0);
313            if(m_pReflowEngine->StartProcess(m_pProvider->GetRoot(), m_pPause, &matrix) != LayoutToBeContinued) {
314                m_Status = Done;
315            }
316        }
317    }
318    if(m_TopIndent && m_Status == Done) {
319        m_pReflowPage->m_PageHeight -= m_TopIndent;
320    }
321}
322void CPDF_ProgressiveReflowPageParser::Clear()
323{
324    this->Init();
325    return;
326}
327FX_BOOL IPDF_ProgressiveReflowPageParser::IsTaggedPage(CPDF_PageObjects*pPage)
328{
329    if(!pPage) {
330        return FALSE;
331    }
332    CPDF_StructTree* pPageTree = CPDF_StructTree::LoadPage(pPage->m_pDocument, pPage->m_pFormDict);
333    if(pPageTree) {
334        int count = pPageTree->CountTopElements();
335        if(count) {
336            for(int i = 0; i < count; i++) {
337                CPDF_StructElement* pElm = pPageTree->GetTopElement(i);
338                if(pElm) {
339                    delete pPageTree;
340                    pPageTree = NULL;
341                    return TRUE;
342                }
343            }
344        }
345        delete pPageTree;
346        pPageTree = NULL;
347        return FALSE;
348    }
349    return FALSE;
350}
351void CPDF_ProgressiveReflowPageParser::Start(IPDF_ReflowedPage* pReflowPage, CPDF_Page* pPage, FX_FLOAT topIndent, FX_FLOAT fWidth, FX_FLOAT fHeight, IFX_Pause* pPause, int flags)
352{
353    if (NULL == pReflowPage) {
354        m_Status = Failed;
355        return;
356    }
357    m_flags = flags;
358    m_pReflowPage = (CPDF_ReflowedPage*)pReflowPage;
359    m_pReflowPage->m_pPDFPage = pPage;
360    m_pReflowPage->ReleasePageObjsMemberShip();
361    m_pPDFPage = pPage;
362    m_TopIndent = topIndent;
363    m_pPause = pPause;
364    m_fScreenHeight = fHeight;
365    m_ReflowedWidth = fWidth;
366    m_pProvider = IPDF_LayoutProvider::Create_LayoutProvider_TaggedPDF(m_pPDFPage);
367    LayoutStatus status = m_pProvider->StartLoad(pPause);
368    if(status == LayoutError) {
369        delete m_pProvider;
370        m_pProvider = IPDF_LayoutProvider::Create_LayoutProvider_AutoReflow(m_pPDFPage, m_flags & RF_PARSER_READERORDER);
371        if (NULL == m_pProvider) {
372            m_Status = Failed;
373            return;
374        }
375        status = m_pProvider->StartLoad(pPause);
376    }
377    if(status == LayoutError) {
378        delete m_pProvider;
379        m_pProvider = NULL;
380        m_Status = Failed;
381        return;
382    }
383    if(status == LayoutToBeContinued) {
384        m_Status = ToBeContinued;
385    } else if (status == LayoutFinished) {
386        m_pReflowEngine = IPDF_LayoutProcessor::Create_LayoutProcessor_Reflow(topIndent, fWidth, fHeight, pReflowPage, m_flags, m_ParseStyle.m_LineSpace);
387        if(NULL == m_pReflowEngine) {
388            delete m_pProvider;
389            m_pProvider = NULL;
390            m_Status = Failed;
391            return;
392        }
393        CFX_AffineMatrix matrix;
394        pPage->GetDisplayMatrix(matrix, 0, 0, (int)(pPage->GetPageWidth()), (int)(pPage->GetPageHeight()), 0);
395        CFX_AffineMatrix matrix1 = pPage->GetPageMatrix();
396        if((status = m_pReflowEngine->StartProcess(m_pProvider->GetRoot(), pPause, &matrix)) != LayoutToBeContinued) {
397            delete m_pReflowEngine;
398            m_pReflowEngine = NULL;
399            m_Status = Done;
400        } else {
401            m_Status = ToBeContinued;
402        }
403    }
404    if(status != LayoutToBeContinued) {
405        delete m_pProvider;
406        m_pProvider = NULL;
407    }
408    if(m_TopIndent && m_Status == Done) {
409        m_pReflowPage->m_PageHeight -= m_TopIndent;
410    }
411    return;
412}
413CPDF_ProgressiveReflowPageRender::~CPDF_ProgressiveReflowPageRender()
414{
415    if(m_pDisplayMatrix) {
416        delete m_pDisplayMatrix;
417    }
418    m_pDisplayMatrix = NULL;
419}
420CPDF_ProgressiveReflowPageRender::CPDF_ProgressiveReflowPageRender()
421{
422    m_Status = Ready;
423    m_pReflowPage = NULL;
424    m_pDisplayMatrix = NULL;
425    m_CurrNum = 0;
426    m_pFontEncoding = NULL;
427    m_DisplayColor = -1;
428}
429static FX_FLOAT _CIDTransformToFloat(FX_BYTE ch)
430{
431    if (ch < 128) {
432        return ch * 1.0f / 127;
433    }
434    return (-255 + ch) * 1.0f / 127;
435}
436int	CPDF_ProgressiveReflowPageRender::GetPosition()
437{
438    if(m_CurrNum == 0 || NULL == m_pReflowPage) {
439        return 0;
440    }
441    int size = m_pReflowPage->m_pReflowed->GetSize();
442    if(size == 0 || m_CurrNum >= size) {
443        return 100;
444    }
445    return (int)(m_CurrNum * 100 / size);
446}
447void CPDF_ProgressiveReflowPageRender::Display(IFX_Pause* pPause)
448{
449    if (NULL == m_pReflowPage) {
450        m_Status = Done;
451        return;
452    }
453    FX_RECT clipBox = m_pFXDevice->GetClipBox();
454    int size = m_pReflowPage->m_pReflowed->GetSize();
455    if (size < 1 || NULL == m_pDisplayMatrix) {
456        m_Status = Done;
457        return;
458    }
459    for(int i = m_CurrNum; i < size; i++) {
460        CRF_Data* pData = (*m_pReflowPage->m_pReflowed)[i];
461        if(!pData) {
462            continue;
463        }
464        CFX_FloatRect rect (pData->m_PosX, pData->m_PosY + pData->m_Height, pData->m_PosX + pData->m_Width, pData->m_PosY);
465        m_pDisplayMatrix->TransformRect(rect);
466        if(rect.left > clipBox.right || rect.right < clipBox.left || rect.bottom > clipBox.bottom || rect.top < clipBox.top) {
467            continue;
468        }
469        if(pData->GetType() == CRF_Data::Text) {
470            CRF_CharData* pCharData = (CRF_CharData*)pData;
471            CPDF_Font* pPDFFont = pCharData->m_pCharState->m_pFont;
472            if(pPDFFont->GetFontType() == PDFFONT_TYPE3) {
473                continue;
474            }
475            FX_FLOAT x = pData->m_PosX, y = pData->m_PosY - pCharData->m_pCharState->m_fDescent;
476            FXTEXT_CHARPOS charpos ;
477            charpos.m_GlyphIndex = pPDFFont->GlyphFromCharCode(pCharData->m_CharCode);
478            charpos.m_FontCharWidth = pPDFFont->m_Font.GetGlyphWidth(charpos.m_GlyphIndex);
479            charpos.m_OriginX       = x;
480            charpos.m_OriginY       = y;
481            FX_FLOAT charW = pData->m_Width * 1000 / pData->m_Height;
482            if(charW != charpos.m_FontCharWidth) {
483                charpos.m_bGlyphAdjust  = TRUE;
484                charpos.m_AdjustMatrix[0] = charW / charpos.m_FontCharWidth;
485                charpos.m_AdjustMatrix[1] = 0;
486                charpos.m_AdjustMatrix[2] = 0;
487                charpos.m_AdjustMatrix[3] = 1;
488            } else {
489                charpos.m_bGlyphAdjust  = FALSE;
490            }
491            FX_BOOL bRet = FALSE;
492            if(m_DisplayColor == -1)
493                bRet = m_pFXDevice->DrawNormalText(1, &charpos, &(pPDFFont->m_Font),
494                                                   NULL, pCharData->m_pCharState->m_fFontSize,
495                                                   m_pDisplayMatrix, pCharData->m_pCharState->m_Color + 0xff000000, FXTEXT_CLEARTYPE);
496            else
497                bRet = m_pFXDevice->DrawNormalText(1, &charpos, &(pPDFFont->m_Font),
498                                                   NULL, pCharData->m_pCharState->m_fFontSize, m_pDisplayMatrix, m_DisplayColor, FXTEXT_CLEARTYPE);
499        } else if(pData->GetType() == CRF_Data::Image) {
500            CRF_ImageData* pImageData = (CRF_ImageData*)pData;
501            if(!pImageData->m_pBitmap) {
502                continue;
503            }
504            int left = 0, top = 0;
505            CFX_DIBitmap* pDiBmp = NULL;
506            CFX_DIBSource* pDispSource = pImageData->m_pBitmap;
507            if(pImageData->m_Matrix.d < 0) {
508                CFX_AffineMatrix matrix(pImageData->m_Matrix.a, 0, 0, -pImageData->m_Matrix.d, 0, 0);
509                int left, top;
510                pDiBmp = pImageData->m_pBitmap->TransformTo(&matrix, left, top);
511                pDispSource = pDiBmp;
512            }
513            if (NULL == pDispSource) {
514                continue;
515            }
516            if (pDispSource->GetFormat() == FXDIB_1bppMask || pDispSource->GetFormat() == FXDIB_8bppMask) {
517                m_pFXDevice->StretchBitMask(pDispSource, (int)(rect.left + 0.5), (int)(rect.bottom + 0.5), (int)(rect.Width() + 0.5), (int)(rect.Height() + 0.5), 0xff000000);
518            } else {
519                m_pFXDevice->StretchDIBits(pDispSource, (int)(rect.left + 0.5), (int)(rect.bottom + 0.5), (int)(rect.Width() + 0.5), (int)(rect.Height() + 0.5));
520            }
521            if(m_pFXDevice->GetBitmap() && m_pFXDevice->GetBitmap()->GetFormat() == FXDIB_8bppRgb &&
522                    m_pFXDevice->GetBitmap()->GetPalette() == NULL) {
523                int nPalette = 0;
524                switch(m_DitherBits) {
525                    case 0:
526                        nPalette = 0;
527                        break;
528                    case 1:
529                        nPalette = 2;
530                        break;
531                    case 2:
532                        nPalette = 4;
533                        break;
534                    case 3:
535                        nPalette = 8;
536                        break;
537                    case 4:
538                        nPalette = 16;
539                        break;
540                    case 5:
541                        nPalette = 32;
542                        break;
543                    case 6:
544                        nPalette = 64;
545                        break;
546                    case 7:
547                        nPalette = 128;
548                        break;
549                    default:
550                        nPalette = 256;
551                        break;
552                }
553                if(nPalette >= 2) {
554                    FX_ARGB * palette = FX_Alloc(FX_ARGB, nPalette);
555                    nPalette --;
556                    palette[0] = 0;
557                    palette[nPalette] = 255;
558                    FX_FLOAT Dither = (FX_FLOAT)255 / (nPalette);
559                    for(int i = 1; i < nPalette; i++) {
560                        palette[i] = (FX_ARGB)(Dither * i + 0.5);
561                    }
562                    FX_RECT tmpRect = rect.GetOutterRect();
563                    m_pFXDevice->GetBitmap()->DitherFS(palette, nPalette + 1, &tmpRect);
564                    FX_Free (palette);
565                }
566            }
567            if(pDiBmp) {
568                delete pDiBmp;
569            }
570        } else if(pData->GetType() == CRF_Data::Path) {
571        }
572        if(!(i % 10)) {
573            if(pPause && pPause->NeedToPauseNow()) {
574                i++;
575                m_CurrNum = i;
576                m_Status = ToBeContinued;
577                return;
578            }
579        }
580    }
581    m_CurrNum = size;
582    m_Status = Done;
583}
584void CPDF_ProgressiveReflowPageRender::Start(IPDF_ReflowedPage* pReflowPage, CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pMatrix, IFX_Pause* pPause, int DitherBits)
585{
586    if(!pReflowPage || !pDevice || !pMatrix) {
587        m_Status = Failed;
588        return;
589    }
590    m_DitherBits = DitherBits;
591    m_Status = Ready;
592    m_CurrNum = 0;
593    m_pReflowPage = (CPDF_ReflowedPage*)pReflowPage;
594    m_pFXDevice = pDevice;
595    if(NULL == m_pDisplayMatrix) {
596        m_pDisplayMatrix = FX_NEW CFX_AffineMatrix;
597    }
598    if (m_pDisplayMatrix) {
599        m_pDisplayMatrix->Copy(*pMatrix);
600    }
601    m_Status = ToBeContinued;
602    Display(pPause);
603}
604void CPDF_ProgressiveReflowPageRender::Continue(IFX_Pause* pPause)
605{
606    Display(pPause);
607}
608void CPDF_ProgressiveReflowPageRender::SetDisplayColor(FX_COLORREF color)
609{
610    m_DisplayColor = color;
611}
612void CPDF_ProgressiveReflowPageRender::Clear()
613{
614    if (m_pDisplayMatrix) {
615        delete m_pDisplayMatrix;
616    }
617    m_pDisplayMatrix = NULL;
618    m_pReflowPage = NULL;
619    m_pFXDevice = NULL;
620    m_CurrNum = 0;
621    m_Status = Ready;
622}
623