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/fde/fde_gedevice.h"
8
9 #include <algorithm>
10 #include <memory>
11
12 #include "core/fxge/cfx_gemodule.h"
13 #include "core/fxge/cfx_graphstatedata.h"
14 #include "core/fxge/cfx_renderdevice.h"
15 #include "core/fxge/cfx_substfont.h"
16 #include "xfa/fde/cfde_path.h"
17 #include "xfa/fde/fde_object.h"
18 #include "xfa/fgas/font/cfgas_fontmgr.h"
19 #include "xfa/fgas/font/cfgas_gefont.h"
20
CFDE_RenderDevice(CFX_RenderDevice * pDevice,bool bOwnerDevice)21 CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice,
22 bool bOwnerDevice)
23 : m_pDevice(pDevice), m_bOwnerDevice(bOwnerDevice), m_iCharCount(0) {
24 ASSERT(pDevice);
25
26 FX_RECT rt = m_pDevice->GetClipBox();
27 m_rtClip = CFX_RectF(
28 static_cast<FX_FLOAT>(rt.left), static_cast<FX_FLOAT>(rt.top),
29 static_cast<FX_FLOAT>(rt.Width()), static_cast<FX_FLOAT>(rt.Height()));
30 }
31
~CFDE_RenderDevice()32 CFDE_RenderDevice::~CFDE_RenderDevice() {
33 if (m_bOwnerDevice)
34 delete m_pDevice;
35 }
36
GetWidth() const37 int32_t CFDE_RenderDevice::GetWidth() const {
38 return m_pDevice->GetWidth();
39 }
40
GetHeight() const41 int32_t CFDE_RenderDevice::GetHeight() const {
42 return m_pDevice->GetHeight();
43 }
44
SaveState()45 void CFDE_RenderDevice::SaveState() {
46 m_pDevice->SaveState();
47 }
48
RestoreState()49 void CFDE_RenderDevice::RestoreState() {
50 m_pDevice->RestoreState(false);
51 const FX_RECT& rt = m_pDevice->GetClipBox();
52 m_rtClip = CFX_RectF(
53 static_cast<FX_FLOAT>(rt.left), static_cast<FX_FLOAT>(rt.top),
54 static_cast<FX_FLOAT>(rt.Width()), static_cast<FX_FLOAT>(rt.Height()));
55 }
56
SetClipRect(const CFX_RectF & rtClip)57 bool CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) {
58 m_rtClip = rtClip;
59 return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left),
60 (int32_t)FXSYS_floor(rtClip.top),
61 (int32_t)FXSYS_ceil(rtClip.right()),
62 (int32_t)FXSYS_ceil(rtClip.bottom())));
63 }
64
GetClipRect()65 const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
66 return m_rtClip;
67 }
68
SetClipPath(const CFDE_Path * pClip)69 bool CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
70 return false;
71 }
72
GetClipPath() const73 CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
74 return nullptr;
75 }
76
GetDpiX() const77 FX_FLOAT CFDE_RenderDevice::GetDpiX() const {
78 return 96;
79 }
80
GetDpiY() const81 FX_FLOAT CFDE_RenderDevice::GetDpiY() const {
82 return 96;
83 }
84
DrawImage(CFX_DIBSource * pDib,const CFX_RectF * pSrcRect,const CFX_RectF & dstRect,const CFX_Matrix * pImgMatrix,const CFX_Matrix * pDevMatrix)85 bool CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib,
86 const CFX_RectF* pSrcRect,
87 const CFX_RectF& dstRect,
88 const CFX_Matrix* pImgMatrix,
89 const CFX_Matrix* pDevMatrix) {
90 CFX_RectF srcRect;
91 if (pSrcRect) {
92 srcRect = *pSrcRect;
93 } else {
94 srcRect = CFX_RectF(0, 0, static_cast<FX_FLOAT>(pDib->GetWidth()),
95 static_cast<FX_FLOAT>(pDib->GetHeight()));
96 }
97
98 if (srcRect.IsEmpty())
99 return false;
100
101 CFX_Matrix dib2fxdev;
102 if (pImgMatrix) {
103 dib2fxdev = *pImgMatrix;
104 } else {
105 dib2fxdev.SetIdentity();
106 }
107 dib2fxdev.a = dstRect.width;
108 dib2fxdev.d = -dstRect.height;
109 dib2fxdev.e = dstRect.left;
110 dib2fxdev.f = dstRect.bottom();
111 if (pDevMatrix) {
112 dib2fxdev.Concat(*pDevMatrix);
113 }
114 void* handle = nullptr;
115 m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
116 handle);
117 while (m_pDevice->ContinueDIBits(handle, nullptr)) {
118 }
119 m_pDevice->CancelDIBits(handle);
120 return !!handle;
121 }
122
DrawString(CFDE_Brush * pBrush,const CFX_RetainPtr<CFGAS_GEFont> & pFont,const FXTEXT_CHARPOS * pCharPos,int32_t iCount,FX_FLOAT fFontSize,const CFX_Matrix * pMatrix)123 bool CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
124 const CFX_RetainPtr<CFGAS_GEFont>& pFont,
125 const FXTEXT_CHARPOS* pCharPos,
126 int32_t iCount,
127 FX_FLOAT fFontSize,
128 const CFX_Matrix* pMatrix) {
129 ASSERT(pBrush && pFont && pCharPos && iCount > 0);
130 CFX_Font* pFxFont = pFont->GetDevFont();
131 FX_ARGB argb = pBrush->GetColor();
132 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
133 !pFxFont->IsItalic()) {
134 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
135 FX_FLOAT* pAM;
136 for (int32_t i = 0; i < iCount; ++i) {
137 static const FX_FLOAT mc = 0.267949f;
138 pAM = pCP->m_AdjustMatrix;
139 pAM[2] = mc * pAM[0] + pAM[2];
140 pAM[3] = mc * pAM[1] + pAM[3];
141 pCP++;
142 }
143 }
144 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
145 CFX_RetainPtr<CFGAS_GEFont> pCurFont;
146 CFX_RetainPtr<CFGAS_GEFont> pSTFont;
147 FXTEXT_CHARPOS* pCurCP = nullptr;
148 int32_t iCurCount = 0;
149
150 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
151 uint32_t dwFontStyle = pFont->GetFontStyles();
152 CFX_Font FxFont;
153 CFX_SubstFont* SubstFxFont = new CFX_SubstFont();
154 FxFont.SetSubstFont(std::unique_ptr<CFX_SubstFont>(SubstFxFont));
155 SubstFxFont->m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
156 SubstFxFont->m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
157 SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight;
158 SubstFxFont->m_bItalicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
159 #endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
160
161 for (int32_t i = 0; i < iCount; ++i) {
162 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
163 pCP->m_GlyphIndex &= 0x00FFFFFF;
164 pCP->m_bFontStyle = false;
165 if (pCurFont != pSTFont) {
166 if (pCurFont) {
167 pFxFont = pCurFont->GetDevFont();
168 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
169 FxFont.SetFace(pFxFont->GetFace());
170 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize,
171 pMatrix, argb, FXTEXT_CLEARTYPE);
172 #else
173 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
174 pMatrix, argb, FXTEXT_CLEARTYPE);
175 #endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
176 }
177 pCurFont = pSTFont;
178 pCurCP = pCP;
179 iCurCount = 1;
180 } else {
181 iCurCount++;
182 }
183 pCP++;
184 }
185 if (pCurFont && iCurCount) {
186 pFxFont = pCurFont->GetDevFont();
187 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
188 FxFont.SetFace(pFxFont->GetFace());
189 bool bRet =
190 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize,
191 pMatrix, argb, FXTEXT_CLEARTYPE);
192 FxFont.SetFace(nullptr);
193 return bRet;
194 #else
195 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
196 pMatrix, argb, FXTEXT_CLEARTYPE);
197 #endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
198 }
199
200 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
201 FxFont.SetFace(nullptr);
202 #endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
203
204 return true;
205 }
206
DrawBezier(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const CFX_PointF & pt1,const CFX_PointF & pt2,const CFX_PointF & pt3,const CFX_PointF & pt4,const CFX_Matrix * pMatrix)207 bool CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
208 FX_FLOAT fPenWidth,
209 const CFX_PointF& pt1,
210 const CFX_PointF& pt2,
211 const CFX_PointF& pt3,
212 const CFX_PointF& pt4,
213 const CFX_Matrix* pMatrix) {
214 std::vector<CFX_PointF> points;
215 points.push_back(pt1);
216 points.push_back(pt2);
217 points.push_back(pt3);
218 points.push_back(pt4);
219 CFDE_Path path;
220 path.AddBezier(points);
221 return DrawPath(pPen, fPenWidth, &path, pMatrix);
222 }
223
DrawCurve(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const std::vector<CFX_PointF> & points,bool bClosed,FX_FLOAT fTension,const CFX_Matrix * pMatrix)224 bool CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
225 FX_FLOAT fPenWidth,
226 const std::vector<CFX_PointF>& points,
227 bool bClosed,
228 FX_FLOAT fTension,
229 const CFX_Matrix* pMatrix) {
230 CFDE_Path path;
231 path.AddCurve(points, bClosed, fTension);
232 return DrawPath(pPen, fPenWidth, &path, pMatrix);
233 }
234
DrawEllipse(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const CFX_RectF & rect,const CFX_Matrix * pMatrix)235 bool CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
236 FX_FLOAT fPenWidth,
237 const CFX_RectF& rect,
238 const CFX_Matrix* pMatrix) {
239 CFDE_Path path;
240 path.AddEllipse(rect);
241 return DrawPath(pPen, fPenWidth, &path, pMatrix);
242 }
243
DrawLines(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const std::vector<CFX_PointF> & points,const CFX_Matrix * pMatrix)244 bool CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
245 FX_FLOAT fPenWidth,
246 const std::vector<CFX_PointF>& points,
247 const CFX_Matrix* pMatrix) {
248 CFDE_Path path;
249 path.AddLines(points);
250 return DrawPath(pPen, fPenWidth, &path, pMatrix);
251 }
252
DrawLine(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const CFX_PointF & pt1,const CFX_PointF & pt2,const CFX_Matrix * pMatrix)253 bool CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
254 FX_FLOAT fPenWidth,
255 const CFX_PointF& pt1,
256 const CFX_PointF& pt2,
257 const CFX_Matrix* pMatrix) {
258 CFDE_Path path;
259 path.AddLine(pt1, pt2);
260 return DrawPath(pPen, fPenWidth, &path, pMatrix);
261 }
262
DrawPath(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const CFDE_Path * pPath,const CFX_Matrix * pMatrix)263 bool CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
264 FX_FLOAT fPenWidth,
265 const CFDE_Path* pPath,
266 const CFX_Matrix* pMatrix) {
267 CFDE_Path* pGePath = (CFDE_Path*)pPath;
268 if (!pGePath)
269 return false;
270
271 CFX_GraphStateData graphState;
272 if (!CreatePen(pPen, fPenWidth, graphState)) {
273 return false;
274 }
275 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
276 &graphState, 0, pPen->GetColor(), 0);
277 }
278
DrawPolygon(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const std::vector<CFX_PointF> & points,const CFX_Matrix * pMatrix)279 bool CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
280 FX_FLOAT fPenWidth,
281 const std::vector<CFX_PointF>& points,
282 const CFX_Matrix* pMatrix) {
283 CFDE_Path path;
284 path.AddPolygon(points);
285 return DrawPath(pPen, fPenWidth, &path, pMatrix);
286 }
287
DrawRectangle(CFDE_Pen * pPen,FX_FLOAT fPenWidth,const CFX_RectF & rect,const CFX_Matrix * pMatrix)288 bool CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
289 FX_FLOAT fPenWidth,
290 const CFX_RectF& rect,
291 const CFX_Matrix* pMatrix) {
292 CFDE_Path path;
293 path.AddRectangle(rect);
294 return DrawPath(pPen, fPenWidth, &path, pMatrix);
295 }
296
FillClosedCurve(CFDE_Brush * pBrush,const std::vector<CFX_PointF> & points,FX_FLOAT fTension,const CFX_Matrix * pMatrix)297 bool CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
298 const std::vector<CFX_PointF>& points,
299 FX_FLOAT fTension,
300 const CFX_Matrix* pMatrix) {
301 CFDE_Path path;
302 path.AddCurve(points, true, fTension);
303 return FillPath(pBrush, &path, pMatrix);
304 }
305
FillEllipse(CFDE_Brush * pBrush,const CFX_RectF & rect,const CFX_Matrix * pMatrix)306 bool CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
307 const CFX_RectF& rect,
308 const CFX_Matrix* pMatrix) {
309 CFDE_Path path;
310 path.AddEllipse(rect);
311 return FillPath(pBrush, &path, pMatrix);
312 }
313
FillPolygon(CFDE_Brush * pBrush,const std::vector<CFX_PointF> & points,const CFX_Matrix * pMatrix)314 bool CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
315 const std::vector<CFX_PointF>& points,
316 const CFX_Matrix* pMatrix) {
317 CFDE_Path path;
318 path.AddPolygon(points);
319 return FillPath(pBrush, &path, pMatrix);
320 }
321
FillRectangle(CFDE_Brush * pBrush,const CFX_RectF & rect,const CFX_Matrix * pMatrix)322 bool CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
323 const CFX_RectF& rect,
324 const CFX_Matrix* pMatrix) {
325 CFDE_Path path;
326 path.AddRectangle(rect);
327 return FillPath(pBrush, &path, pMatrix);
328 }
329
CreatePen(CFDE_Pen * pPen,FX_FLOAT fPenWidth,CFX_GraphStateData & graphState)330 bool CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
331 FX_FLOAT fPenWidth,
332 CFX_GraphStateData& graphState) {
333 if (!pPen)
334 return false;
335
336 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
337 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
338 graphState.m_LineWidth = fPenWidth;
339 graphState.m_MiterLimit = 10;
340 graphState.m_DashPhase = 0;
341 return true;
342 }
343
FillPath(CFDE_Brush * pBrush,const CFDE_Path * pPath,const CFX_Matrix * pMatrix)344 bool CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
345 const CFDE_Path* pPath,
346 const CFX_Matrix* pMatrix) {
347 CFDE_Path* pGePath = (CFDE_Path*)pPath;
348 if (!pGePath)
349 return false;
350 if (!pBrush)
351 return false;
352 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
353 pBrush->GetColor(), 0, FXFILL_WINDING);
354 }
355
356