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