fde_gedevice.cpp revision 33357cad1fd1321a2b38d2963e2585f27ce980a2
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
21CFDE_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
32CFDE_RenderDevice::~CFDE_RenderDevice() {
33  if (m_bOwnerDevice)
34    delete m_pDevice;
35}
36
37int32_t CFDE_RenderDevice::GetWidth() const {
38  return m_pDevice->GetWidth();
39}
40
41int32_t CFDE_RenderDevice::GetHeight() const {
42  return m_pDevice->GetHeight();
43}
44
45void CFDE_RenderDevice::SaveState() {
46  m_pDevice->SaveState();
47}
48
49void 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
57bool 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
65const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
66  return m_rtClip;
67}
68
69bool CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
70  return false;
71}
72
73CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
74  return nullptr;
75}
76
77FX_FLOAT CFDE_RenderDevice::GetDpiX() const {
78  return 96;
79}
80
81FX_FLOAT CFDE_RenderDevice::GetDpiY() const {
82  return 96;
83}
84
85bool 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
123bool 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
207bool 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
224bool 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
235bool 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
244bool 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
253bool 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
263bool 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
279bool 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
288bool 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
297bool 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
306bool 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
314bool 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
322bool 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
330bool 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
344bool 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