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