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 "xfa/src/foxitlib.h"
8 #include "fde_render.h"
FDE_GetPageMatrix(CFX_Matrix & pageMatrix,const CFX_RectF & docPageRect,const CFX_Rect & devicePageRect,int32_t iRotate,FX_DWORD dwCoordinatesType)9 void FDE_GetPageMatrix(CFX_Matrix& pageMatrix,
10                        const CFX_RectF& docPageRect,
11                        const CFX_Rect& devicePageRect,
12                        int32_t iRotate,
13                        FX_DWORD dwCoordinatesType) {
14   FXSYS_assert(iRotate >= 0 && iRotate <= 3);
15   FX_BOOL bFlipX = (dwCoordinatesType & 0x01) != 0;
16   FX_BOOL bFlipY = (dwCoordinatesType & 0x02) != 0;
17   CFX_Matrix m;
18   m.Set((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0);
19   if (iRotate == 0 || iRotate == 2) {
20     m.a *= (FX_FLOAT)devicePageRect.width / docPageRect.width;
21     m.d *= (FX_FLOAT)devicePageRect.height / docPageRect.height;
22   } else {
23     m.a *= (FX_FLOAT)devicePageRect.height / docPageRect.width;
24     m.d *= (FX_FLOAT)devicePageRect.width / docPageRect.height;
25   }
26   m.Rotate(iRotate * 1.57079632675f);
27   switch (iRotate) {
28     case 0:
29       m.e = bFlipX ? (FX_FLOAT)devicePageRect.right()
30                    : (FX_FLOAT)devicePageRect.left;
31       m.f = bFlipY ? (FX_FLOAT)devicePageRect.bottom()
32                    : (FX_FLOAT)devicePageRect.top;
33       break;
34     case 1:
35       m.e = bFlipY ? (FX_FLOAT)devicePageRect.left
36                    : (FX_FLOAT)devicePageRect.right();
37       m.f = bFlipX ? (FX_FLOAT)devicePageRect.bottom()
38                    : (FX_FLOAT)devicePageRect.top;
39       break;
40     case 2:
41       m.e = bFlipX ? (FX_FLOAT)devicePageRect.left
42                    : (FX_FLOAT)devicePageRect.right();
43       m.f = bFlipY ? (FX_FLOAT)devicePageRect.top
44                    : (FX_FLOAT)devicePageRect.bottom();
45       break;
46     case 3:
47       m.e = bFlipY ? (FX_FLOAT)devicePageRect.right()
48                    : (FX_FLOAT)devicePageRect.left;
49       m.f = bFlipX ? (FX_FLOAT)devicePageRect.top
50                    : (FX_FLOAT)devicePageRect.bottom();
51       break;
52     default:
53       break;
54   }
55   pageMatrix = m;
56 }
Create()57 IFDE_RenderContext* IFDE_RenderContext::Create() {
58   return new CFDE_RenderContext;
59 }
CFDE_RenderContext()60 CFDE_RenderContext::CFDE_RenderContext()
61     : CFX_ThreadLock(),
62       m_eStatus(FDE_RENDERSTATUS_Reset),
63       m_pRenderDevice(NULL),
64       m_pSolidBrush(NULL),
65       m_Transform(),
66       m_pCharPos(NULL),
67       m_iCharPosCount(0),
68       m_pIterator(NULL) {
69   m_Transform.SetIdentity();
70 }
~CFDE_RenderContext()71 CFDE_RenderContext::~CFDE_RenderContext() {
72   StopRender();
73 }
StartRender(IFDE_RenderDevice * pRenderDevice,IFDE_CanvasSet * pCanvasSet,const CFX_Matrix & tmDoc2Device)74 FX_BOOL CFDE_RenderContext::StartRender(IFDE_RenderDevice* pRenderDevice,
75                                         IFDE_CanvasSet* pCanvasSet,
76                                         const CFX_Matrix& tmDoc2Device) {
77   if (m_pRenderDevice != NULL) {
78     return FALSE;
79   }
80   if (pRenderDevice == NULL) {
81     return FALSE;
82   }
83   if (pCanvasSet == NULL) {
84     return FALSE;
85   }
86   Lock();
87   m_eStatus = FDE_RENDERSTATUS_Paused;
88   m_pRenderDevice = pRenderDevice;
89   m_Transform = tmDoc2Device;
90   if (m_pIterator == NULL) {
91     m_pIterator = IFDE_VisualSetIterator::Create();
92     FXSYS_assert(m_pIterator != NULL);
93   }
94   FX_BOOL bAttach =
95       m_pIterator->AttachCanvas(pCanvasSet) && m_pIterator->FilterObjects();
96   Unlock();
97   return bAttach;
98 }
DoRender(IFX_Pause * pPause)99 FDE_RENDERSTATUS CFDE_RenderContext::DoRender(IFX_Pause* pPause) {
100   if (m_pRenderDevice == NULL) {
101     return FDE_RENDERSTATUS_Failed;
102   }
103   if (m_pIterator == NULL) {
104     return FDE_RENDERSTATUS_Failed;
105   }
106   Lock();
107   FDE_RENDERSTATUS eStatus = FDE_RENDERSTATUS_Paused;
108   CFX_Matrix rm;
109   rm.SetReverse(m_Transform);
110   CFX_RectF rtDocClip = m_pRenderDevice->GetClipRect();
111   if (rtDocClip.IsEmpty()) {
112     rtDocClip.left = rtDocClip.top = 0;
113     rtDocClip.width = (FX_FLOAT)m_pRenderDevice->GetWidth();
114     rtDocClip.height = (FX_FLOAT)m_pRenderDevice->GetHeight();
115   }
116   rm.TransformRect(rtDocClip);
117   IFDE_VisualSet* pVisualSet;
118   FDE_HVISUALOBJ hVisualObj;
119   CFX_RectF rtObj;
120   int32_t iCount = 0;
121   while (TRUE) {
122     hVisualObj = m_pIterator->GetNext(pVisualSet);
123     if (hVisualObj == NULL || pVisualSet == NULL) {
124       eStatus = FDE_RENDERSTATUS_Done;
125       break;
126     }
127     rtObj.Empty();
128     pVisualSet->GetRect(hVisualObj, rtObj);
129     if (!rtDocClip.IntersectWith(rtObj)) {
130       continue;
131     }
132     switch (pVisualSet->GetType()) {
133       case FDE_VISUALOBJ_Text:
134         RenderText((IFDE_TextSet*)pVisualSet, hVisualObj);
135         iCount += 5;
136         break;
137       case FDE_VISUALOBJ_Path:
138         RenderPath((IFDE_PathSet*)pVisualSet, hVisualObj);
139         iCount += 20;
140         break;
141       case FDE_VISUALOBJ_Widget:
142         iCount += 10;
143         break;
144       case FDE_VISUALOBJ_Canvas:
145         FXSYS_assert(FALSE);
146         break;
147       default:
148         break;
149     }
150     if (iCount >= 100 && pPause != NULL && pPause->NeedToPauseNow()) {
151       eStatus = FDE_RENDERSTATUS_Paused;
152       break;
153     }
154   }
155   Unlock();
156   return m_eStatus = eStatus;
157 }
StopRender()158 void CFDE_RenderContext::StopRender() {
159   Lock();
160   m_eStatus = FDE_RENDERSTATUS_Reset;
161   m_pRenderDevice = nullptr;
162   m_Transform.SetIdentity();
163   if (m_pIterator) {
164     m_pIterator->Release();
165     m_pIterator = nullptr;
166   }
167   if (m_pSolidBrush) {
168     m_pSolidBrush->Release();
169     m_pSolidBrush = nullptr;
170   }
171   FX_Free(m_pCharPos);
172   m_pCharPos = nullptr;
173   m_iCharPosCount = 0;
174   Unlock();
175 }
RenderText(IFDE_TextSet * pTextSet,FDE_HVISUALOBJ hText)176 void CFDE_RenderContext::RenderText(IFDE_TextSet* pTextSet,
177                                     FDE_HVISUALOBJ hText) {
178   FXSYS_assert(m_pRenderDevice != NULL);
179   FXSYS_assert(pTextSet != NULL && hText != NULL);
180   IFX_Font* pFont = pTextSet->GetFont(hText);
181   if (pFont == NULL) {
182     return;
183   }
184   int32_t iCount = pTextSet->GetDisplayPos(hText, NULL, FALSE);
185   if (iCount < 1) {
186     return;
187   }
188   if (m_pSolidBrush == NULL) {
189     m_pSolidBrush = (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid);
190     if (m_pSolidBrush == NULL) {
191       return;
192     }
193   }
194   if (m_pCharPos == NULL) {
195     m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, iCount);
196   } else if (m_iCharPosCount < iCount) {
197     m_pCharPos = FX_Realloc(FXTEXT_CHARPOS, m_pCharPos, iCount);
198   }
199   if (m_iCharPosCount < iCount) {
200     m_iCharPosCount = iCount;
201   }
202   iCount = pTextSet->GetDisplayPos(hText, m_pCharPos, FALSE);
203   FX_FLOAT fFontSize = pTextSet->GetFontSize(hText);
204   FX_ARGB dwColor = pTextSet->GetFontColor(hText);
205   m_pSolidBrush->SetColor(dwColor);
206   FDE_HDEVICESTATE hState;
207   FX_BOOL bClip = ApplyClip(pTextSet, hText, hState);
208   m_pRenderDevice->DrawString(m_pSolidBrush, pFont, m_pCharPos, iCount,
209                               fFontSize, &m_Transform);
210   if (bClip) {
211     RestoreClip(hState);
212   }
213 }
RenderPath(IFDE_PathSet * pPathSet,FDE_HVISUALOBJ hPath)214 void CFDE_RenderContext::RenderPath(IFDE_PathSet* pPathSet,
215                                     FDE_HVISUALOBJ hPath) {
216   FXSYS_assert(m_pRenderDevice != NULL);
217   FXSYS_assert(pPathSet != NULL && hPath != NULL);
218   IFDE_Path* pPath = pPathSet->GetPath(hPath);
219   if (pPath == NULL) {
220     return;
221   }
222   FDE_HDEVICESTATE hState;
223   FX_BOOL bClip = ApplyClip(pPathSet, hPath, hState);
224   int32_t iRenderMode = pPathSet->GetRenderMode(hPath);
225   if (iRenderMode & FDE_PATHRENDER_Stroke) {
226     IFDE_Pen* pPen = pPathSet->GetPen(hPath);
227     FX_FLOAT fWidth = pPathSet->GetPenWidth(hPath);
228     if (pPen != NULL && fWidth > 0) {
229       m_pRenderDevice->DrawPath(pPen, fWidth, pPath, &m_Transform);
230     }
231   }
232   if (iRenderMode & FDE_PATHRENDER_Fill) {
233     IFDE_Brush* pBrush = pPathSet->GetBrush(hPath);
234     if (pBrush != NULL) {
235       m_pRenderDevice->FillPath(pBrush, pPath, &m_Transform);
236     }
237   }
238   if (bClip) {
239     RestoreClip(hState);
240   }
241 }
ApplyClip(IFDE_VisualSet * pVisualSet,FDE_HVISUALOBJ hObj,FDE_HDEVICESTATE & hState)242 FX_BOOL CFDE_RenderContext::ApplyClip(IFDE_VisualSet* pVisualSet,
243                                       FDE_HVISUALOBJ hObj,
244                                       FDE_HDEVICESTATE& hState) {
245   CFX_RectF rtClip;
246   if (!pVisualSet->GetClip(hObj, rtClip)) {
247     return FALSE;
248   }
249   CFX_RectF rtObj;
250   pVisualSet->GetRect(hObj, rtObj);
251   rtClip.Offset(rtObj.left, rtObj.top);
252   m_Transform.TransformRect(rtClip);
253   const CFX_RectF& rtDevClip = m_pRenderDevice->GetClipRect();
254   rtClip.Intersect(rtDevClip);
255   hState = m_pRenderDevice->SaveState();
256   return m_pRenderDevice->SetClipRect(rtClip);
257 }
RestoreClip(FDE_HDEVICESTATE hState)258 void CFDE_RenderContext::RestoreClip(FDE_HDEVICESTATE hState) {
259   m_pRenderDevice->RestoreState(hState);
260 }
261