blob: 49345ffeaa423618ad22ab76960433b2edfa4ce5 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
dsinclairacd0d592016-04-21 11:06:27 -070011#include "xfa/fde/cfde_path.h"
dsinclair25c223d2016-04-12 09:51:45 -070012#include "xfa/fde/fde_object.h"
dsinclairacd0d592016-04-21 11:06:27 -070013#include "xfa/fgas/font/fgas_font.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040014
dsinclairacd0d592016-04-21 11:06:27 -070015CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice,
16 FX_BOOL bOwnerDevice)
Dan Sinclair1770c022016-03-14 14:14:16 -040017 : m_pDevice(pDevice),
18 m_bOwnerDevice(bOwnerDevice),
dsinclairacd0d592016-04-21 11:06:27 -070019 m_pCharPos(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040020 m_iCharCount(0) {
dsinclairacd0d592016-04-21 11:06:27 -070021 FXSYS_assert(pDevice);
22
Dan Sinclair1770c022016-03-14 14:14:16 -040023 FX_RECT rt = m_pDevice->GetClipBox();
24 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
25 (FX_FLOAT)rt.Height());
26}
dsinclairacd0d592016-04-21 11:06:27 -070027
28CFDE_RenderDevice::~CFDE_RenderDevice() {
Dan Sinclair1770c022016-03-14 14:14:16 -040029 FX_Free(m_pCharPos);
30 if (m_bOwnerDevice)
31 delete m_pDevice;
32}
dsinclairacd0d592016-04-21 11:06:27 -070033int32_t CFDE_RenderDevice::GetWidth() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040034 return m_pDevice->GetWidth();
35}
dsinclairacd0d592016-04-21 11:06:27 -070036int32_t CFDE_RenderDevice::GetHeight() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040037 return m_pDevice->GetHeight();
38}
dsinclairacd0d592016-04-21 11:06:27 -070039FDE_HDEVICESTATE CFDE_RenderDevice::SaveState() {
Dan Sinclair1770c022016-03-14 14:14:16 -040040 m_pDevice->SaveState();
41 return NULL;
42}
dsinclairacd0d592016-04-21 11:06:27 -070043void CFDE_RenderDevice::RestoreState(FDE_HDEVICESTATE hState) {
Dan Sinclair1770c022016-03-14 14:14:16 -040044 m_pDevice->RestoreState();
45 const FX_RECT& rt = m_pDevice->GetClipBox();
46 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
47 (FX_FLOAT)rt.Height());
48}
dsinclairacd0d592016-04-21 11:06:27 -070049FX_BOOL CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) {
Dan Sinclair1770c022016-03-14 14:14:16 -040050 m_rtClip = rtClip;
51 return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left),
52 (int32_t)FXSYS_floor(rtClip.top),
53 (int32_t)FXSYS_ceil(rtClip.right()),
54 (int32_t)FXSYS_ceil(rtClip.bottom())));
55}
dsinclairacd0d592016-04-21 11:06:27 -070056const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
Dan Sinclair1770c022016-03-14 14:14:16 -040057 return m_rtClip;
58}
dsinclairacd0d592016-04-21 11:06:27 -070059FX_BOOL CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
Dan Sinclair1770c022016-03-14 14:14:16 -040060 return FALSE;
61}
dsinclairacd0d592016-04-21 11:06:27 -070062CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040063 return NULL;
64}
dsinclairacd0d592016-04-21 11:06:27 -070065FX_FLOAT CFDE_RenderDevice::GetDpiX() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040066 return 96;
67}
dsinclairacd0d592016-04-21 11:06:27 -070068FX_FLOAT CFDE_RenderDevice::GetDpiY() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040069 return 96;
70}
dsinclairacd0d592016-04-21 11:06:27 -070071FX_BOOL CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib,
72 const CFX_RectF* pSrcRect,
73 const CFX_RectF& dstRect,
74 const CFX_Matrix* pImgMatrix,
75 const CFX_Matrix* pDevMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -040076 FXSYS_assert(pDib != NULL);
77 CFX_RectF srcRect;
78 if (pSrcRect) {
79 srcRect = *pSrcRect;
80 } else {
81 srcRect.Set(0, 0, (FX_FLOAT)pDib->GetWidth(), (FX_FLOAT)pDib->GetHeight());
82 }
83 if (srcRect.IsEmpty()) {
84 return FALSE;
85 }
86 CFX_Matrix dib2fxdev;
87 if (pImgMatrix) {
88 dib2fxdev = *pImgMatrix;
89 } else {
90 dib2fxdev.SetIdentity();
91 }
92 dib2fxdev.a = dstRect.width;
93 dib2fxdev.d = -dstRect.height;
94 dib2fxdev.e = dstRect.left;
95 dib2fxdev.f = dstRect.bottom();
96 if (pDevMatrix) {
97 dib2fxdev.Concat(*pDevMatrix);
98 }
99 void* handle = NULL;
100 m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
101 handle);
102 while (m_pDevice->ContinueDIBits(handle, NULL)) {
103 }
104 m_pDevice->CancelDIBits(handle);
105 return handle != NULL;
106}
dsinclairacd0d592016-04-21 11:06:27 -0700107FX_BOOL CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
108 IFX_Font* pFont,
109 const FXTEXT_CHARPOS* pCharPos,
110 int32_t iCount,
111 FX_FLOAT fFontSize,
112 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400113 FXSYS_assert(pBrush != NULL && pFont != NULL && pCharPos != NULL &&
114 iCount > 0);
115 CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
116 CFX_Font* pFxFont = (CFX_Font*)pFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700117
118 FX_ARGB argb = pBrush->GetColor();
119 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
120 !pFxFont->IsItalic()) {
121 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
122 FX_FLOAT* pAM;
123 for (int32_t i = 0; i < iCount; ++i) {
124 static const FX_FLOAT mc = 0.267949f;
125 pAM = pCP->m_AdjustMatrix;
126 pAM[2] = mc * pAM[0] + pAM[2];
127 pAM[3] = mc * pAM[1] + pAM[3];
128 pCP++;
129 }
130 }
131 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
132 IFX_Font* pCurFont = NULL;
133 IFX_Font* pSTFont = NULL;
134 FXTEXT_CHARPOS* pCurCP = NULL;
135 int32_t iCurCount = 0;
136
Dan Sinclair1770c022016-03-14 14:14:16 -0400137#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700138 uint32_t dwFontStyle = pFont->GetFontStyles();
139 CFX_Font FxFont;
140 CFX_SubstFont SubstFxFont;
141 FxFont.SetSubstFont(&SubstFxFont);
142 SubstFxFont.m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
143 SubstFxFont.m_WeightCJK = SubstFxFont.m_Weight;
144 SubstFxFont.m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
145 SubstFxFont.m_bItlicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
Dan Sinclair1770c022016-03-14 14:14:16 -0400146#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700147
148 for (int32_t i = 0; i < iCount; ++i) {
149 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
150 pCP->m_GlyphIndex &= 0x00FFFFFF;
151 pCP->m_bFontStyle = FALSE;
152 if (pCurFont != pSTFont) {
153 if (pCurFont != NULL) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400154 pFxFont = (CFX_Font*)pCurFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700155
Dan Sinclair1770c022016-03-14 14:14:16 -0400156#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
157 FxFont.SetFace(pFxFont->GetFace());
dsinclaira5c13232016-04-12 13:19:36 -0700158 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, pCache,
159 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
160 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400161#else
dsinclaira5c13232016-04-12 13:19:36 -0700162 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
163 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
164 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400165#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
166 }
dsinclaira5c13232016-04-12 13:19:36 -0700167 pCurFont = pSTFont;
168 pCurCP = pCP;
169 iCurCount = 1;
170 } else {
171 iCurCount++;
172 }
173 pCP++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400174 }
dsinclaira5c13232016-04-12 13:19:36 -0700175 if (pCurFont != NULL && iCurCount) {
176 pFxFont = (CFX_Font*)pCurFont->GetDevFont();
177
178#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
179 FxFont.SetFace(pFxFont->GetFace());
180 FX_BOOL bRet = m_pDevice->DrawNormalText(
181 iCurCount, pCurCP, &FxFont, pCache, -fFontSize,
182 (const CFX_Matrix*)pMatrix, argb, FXTEXT_CLEARTYPE);
183 FxFont.SetSubstFont(nullptr);
184 FxFont.SetFace(nullptr);
185 return bRet;
186#else
187 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
188 -fFontSize, (const CFX_Matrix*)pMatrix,
189 argb, FXTEXT_CLEARTYPE);
190#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
191 }
192
193#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
194 FxFont.SetSubstFont(nullptr);
195 FxFont.SetFace(nullptr);
196#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
197
198 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -0400199}
dsinclaira5c13232016-04-12 13:19:36 -0700200
dsinclairacd0d592016-04-21 11:06:27 -0700201FX_BOOL CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
202 FX_FLOAT fPenWidth,
203 const CFX_PointF& pt1,
204 const CFX_PointF& pt2,
205 const CFX_PointF& pt3,
206 const CFX_PointF& pt4,
207 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400208 CFX_PointsF points;
209 points.Add(pt1);
210 points.Add(pt2);
211 points.Add(pt3);
212 points.Add(pt4);
213 CFDE_Path path;
214 path.AddBezier(points);
215 return DrawPath(pPen, fPenWidth, &path, pMatrix);
216}
dsinclairacd0d592016-04-21 11:06:27 -0700217FX_BOOL CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
218 FX_FLOAT fPenWidth,
219 const CFX_PointsF& points,
220 FX_BOOL bClosed,
221 FX_FLOAT fTension,
222 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400223 CFDE_Path path;
224 path.AddCurve(points, bClosed, fTension);
225 return DrawPath(pPen, fPenWidth, &path, pMatrix);
226}
dsinclairacd0d592016-04-21 11:06:27 -0700227FX_BOOL CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
228 FX_FLOAT fPenWidth,
229 const CFX_RectF& rect,
230 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400231 CFDE_Path path;
232 path.AddEllipse(rect);
233 return DrawPath(pPen, fPenWidth, &path, pMatrix);
234}
dsinclairacd0d592016-04-21 11:06:27 -0700235FX_BOOL CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
236 FX_FLOAT fPenWidth,
237 const CFX_PointsF& points,
238 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400239 CFDE_Path path;
240 path.AddLines(points);
241 return DrawPath(pPen, fPenWidth, &path, pMatrix);
242}
dsinclairacd0d592016-04-21 11:06:27 -0700243FX_BOOL CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
244 FX_FLOAT fPenWidth,
245 const CFX_PointF& pt1,
246 const CFX_PointF& pt2,
247 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400248 CFDE_Path path;
249 path.AddLine(pt1, pt2);
250 return DrawPath(pPen, fPenWidth, &path, pMatrix);
251}
dsinclairacd0d592016-04-21 11:06:27 -0700252FX_BOOL CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
253 FX_FLOAT fPenWidth,
254 const CFDE_Path* pPath,
255 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400256 CFDE_Path* pGePath = (CFDE_Path*)pPath;
257 if (pGePath == NULL) {
258 return FALSE;
259 }
260 CFX_GraphStateData graphState;
261 if (!CreatePen(pPen, fPenWidth, graphState)) {
262 return FALSE;
263 }
264 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
265 &graphState, 0, pPen->GetColor(), 0);
266}
dsinclairacd0d592016-04-21 11:06:27 -0700267FX_BOOL CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
268 FX_FLOAT fPenWidth,
269 const CFX_PointsF& points,
270 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400271 CFDE_Path path;
272 path.AddPolygon(points);
273 return DrawPath(pPen, fPenWidth, &path, pMatrix);
274}
dsinclairacd0d592016-04-21 11:06:27 -0700275FX_BOOL CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
276 FX_FLOAT fPenWidth,
277 const CFX_RectF& rect,
278 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400279 CFDE_Path path;
280 path.AddRectangle(rect);
281 return DrawPath(pPen, fPenWidth, &path, pMatrix);
282}
dsinclairacd0d592016-04-21 11:06:27 -0700283FX_BOOL CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
284 const CFX_PointsF& points,
285 FX_FLOAT fTension,
286 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400287 CFDE_Path path;
288 path.AddCurve(points, TRUE, fTension);
289 return FillPath(pBrush, &path, pMatrix);
290}
dsinclairacd0d592016-04-21 11:06:27 -0700291FX_BOOL CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
292 const CFX_RectF& rect,
293 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400294 CFDE_Path path;
295 path.AddEllipse(rect);
296 return FillPath(pBrush, &path, pMatrix);
297}
dsinclairacd0d592016-04-21 11:06:27 -0700298FX_BOOL CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
299 const CFX_PointsF& points,
300 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400301 CFDE_Path path;
302 path.AddPolygon(points);
303 return FillPath(pBrush, &path, pMatrix);
304}
dsinclairacd0d592016-04-21 11:06:27 -0700305FX_BOOL CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
306 const CFX_RectF& rect,
307 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400308 CFDE_Path path;
309 path.AddRectangle(rect);
310 return FillPath(pBrush, &path, pMatrix);
311}
dsinclairacd0d592016-04-21 11:06:27 -0700312FX_BOOL CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
313 FX_FLOAT fPenWidth,
314 CFX_GraphStateData& graphState) {
dsinclaira5c13232016-04-12 13:19:36 -0700315 if (!pPen)
Dan Sinclair1770c022016-03-14 14:14:16 -0400316 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700317
318 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
319 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
Dan Sinclair1770c022016-03-14 14:14:16 -0400320 graphState.m_LineWidth = fPenWidth;
dsinclaira5c13232016-04-12 13:19:36 -0700321 graphState.m_MiterLimit = 10;
322 graphState.m_DashPhase = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400323 return TRUE;
324}
dsinclair25c223d2016-04-12 09:51:45 -0700325
dsinclairacd0d592016-04-21 11:06:27 -0700326FX_BOOL CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
327 const CFDE_Path* pPath,
328 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400329 CFDE_Path* pGePath = (CFDE_Path*)pPath;
dsinclair25c223d2016-04-12 09:51:45 -0700330 if (!pGePath)
Dan Sinclair1770c022016-03-14 14:14:16 -0400331 return FALSE;
dsinclair25c223d2016-04-12 09:51:45 -0700332 if (!pBrush)
Dan Sinclair1770c022016-03-14 14:14:16 -0400333 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700334 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
335 pBrush->GetColor(), 0, FXFILL_WINDING);
Dan Sinclair1770c022016-03-14 14:14:16 -0400336}
dsinclair25c223d2016-04-12 09:51:45 -0700337