• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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