blob: 005387f83a6437649c574213e01d0d052266b650 [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) {
dsinclair43854a52016-04-27 12:26:00 -070021 ASSERT(pDevice);
dsinclairacd0d592016-04-21 11:06:27 -070022
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}
dsinclairfe433f12016-06-06 12:03:31 -070039void CFDE_RenderDevice::SaveState() {
Dan Sinclair1770c022016-03-14 14:14:16 -040040 m_pDevice->SaveState();
Dan Sinclair1770c022016-03-14 14:14:16 -040041}
dsinclairfe433f12016-06-06 12:03:31 -070042void CFDE_RenderDevice::RestoreState() {
thestig41846a02016-05-26 10:45:30 -070043 m_pDevice->RestoreState(false);
Dan Sinclair1770c022016-03-14 14:14:16 -040044 const FX_RECT& rt = m_pDevice->GetClipBox();
45 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
46 (FX_FLOAT)rt.Height());
47}
dsinclairacd0d592016-04-21 11:06:27 -070048FX_BOOL CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) {
Dan Sinclair1770c022016-03-14 14:14:16 -040049 m_rtClip = rtClip;
50 return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left),
51 (int32_t)FXSYS_floor(rtClip.top),
52 (int32_t)FXSYS_ceil(rtClip.right()),
53 (int32_t)FXSYS_ceil(rtClip.bottom())));
54}
dsinclairacd0d592016-04-21 11:06:27 -070055const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
Dan Sinclair1770c022016-03-14 14:14:16 -040056 return m_rtClip;
57}
dsinclairacd0d592016-04-21 11:06:27 -070058FX_BOOL CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
Dan Sinclair1770c022016-03-14 14:14:16 -040059 return FALSE;
60}
dsinclairacd0d592016-04-21 11:06:27 -070061CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040062 return NULL;
63}
dsinclairacd0d592016-04-21 11:06:27 -070064FX_FLOAT CFDE_RenderDevice::GetDpiX() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040065 return 96;
66}
dsinclairacd0d592016-04-21 11:06:27 -070067FX_FLOAT CFDE_RenderDevice::GetDpiY() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040068 return 96;
69}
dsinclairacd0d592016-04-21 11:06:27 -070070FX_BOOL CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib,
71 const CFX_RectF* pSrcRect,
72 const CFX_RectF& dstRect,
73 const CFX_Matrix* pImgMatrix,
74 const CFX_Matrix* pDevMatrix) {
dsinclair43854a52016-04-27 12:26:00 -070075 ASSERT(pDib != NULL);
Dan Sinclair1770c022016-03-14 14:14:16 -040076 CFX_RectF srcRect;
77 if (pSrcRect) {
78 srcRect = *pSrcRect;
79 } else {
80 srcRect.Set(0, 0, (FX_FLOAT)pDib->GetWidth(), (FX_FLOAT)pDib->GetHeight());
81 }
82 if (srcRect.IsEmpty()) {
83 return FALSE;
84 }
85 CFX_Matrix dib2fxdev;
86 if (pImgMatrix) {
87 dib2fxdev = *pImgMatrix;
88 } else {
89 dib2fxdev.SetIdentity();
90 }
91 dib2fxdev.a = dstRect.width;
92 dib2fxdev.d = -dstRect.height;
93 dib2fxdev.e = dstRect.left;
94 dib2fxdev.f = dstRect.bottom();
95 if (pDevMatrix) {
96 dib2fxdev.Concat(*pDevMatrix);
97 }
98 void* handle = NULL;
99 m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
100 handle);
101 while (m_pDevice->ContinueDIBits(handle, NULL)) {
102 }
103 m_pDevice->CancelDIBits(handle);
104 return handle != NULL;
105}
dsinclairacd0d592016-04-21 11:06:27 -0700106FX_BOOL CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
tsepezb71dc762016-06-03 14:04:19 -0700107 IFGAS_Font* pFont,
dsinclairacd0d592016-04-21 11:06:27 -0700108 const FXTEXT_CHARPOS* pCharPos,
109 int32_t iCount,
110 FX_FLOAT fFontSize,
111 const CFX_Matrix* pMatrix) {
tsepez48ddd862016-06-06 10:51:58 -0700112 ASSERT(pBrush && pFont && pCharPos && iCount > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400113 CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
tsepez48ddd862016-06-06 10:51:58 -0700114 CFX_Font* pFxFont = pFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700115 FX_ARGB argb = pBrush->GetColor();
116 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
117 !pFxFont->IsItalic()) {
118 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
119 FX_FLOAT* pAM;
120 for (int32_t i = 0; i < iCount; ++i) {
121 static const FX_FLOAT mc = 0.267949f;
122 pAM = pCP->m_AdjustMatrix;
123 pAM[2] = mc * pAM[0] + pAM[2];
124 pAM[3] = mc * pAM[1] + pAM[3];
125 pCP++;
126 }
127 }
128 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
tsepezb71dc762016-06-03 14:04:19 -0700129 IFGAS_Font* pCurFont = NULL;
130 IFGAS_Font* pSTFont = NULL;
dsinclaira5c13232016-04-12 13:19:36 -0700131 FXTEXT_CHARPOS* pCurCP = NULL;
132 int32_t iCurCount = 0;
133
Dan Sinclair1770c022016-03-14 14:14:16 -0400134#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700135 uint32_t dwFontStyle = pFont->GetFontStyles();
136 CFX_Font FxFont;
137 CFX_SubstFont SubstFxFont;
138 FxFont.SetSubstFont(&SubstFxFont);
139 SubstFxFont.m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
140 SubstFxFont.m_WeightCJK = SubstFxFont.m_Weight;
141 SubstFxFont.m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
142 SubstFxFont.m_bItlicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
Dan Sinclair1770c022016-03-14 14:14:16 -0400143#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700144
145 for (int32_t i = 0; i < iCount; ++i) {
146 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
147 pCP->m_GlyphIndex &= 0x00FFFFFF;
148 pCP->m_bFontStyle = FALSE;
149 if (pCurFont != pSTFont) {
tsepez48ddd862016-06-06 10:51:58 -0700150 if (pCurFont) {
151 pFxFont = pCurFont->GetDevFont();
Dan Sinclair1770c022016-03-14 14:14:16 -0400152#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
153 FxFont.SetFace(pFxFont->GetFace());
dsinclaira5c13232016-04-12 13:19:36 -0700154 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, pCache,
155 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
156 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400157#else
dsinclaira5c13232016-04-12 13:19:36 -0700158 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
159 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
160 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400161#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
162 }
dsinclaira5c13232016-04-12 13:19:36 -0700163 pCurFont = pSTFont;
164 pCurCP = pCP;
165 iCurCount = 1;
166 } else {
167 iCurCount++;
168 }
169 pCP++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400170 }
tsepez48ddd862016-06-06 10:51:58 -0700171 if (pCurFont && iCurCount) {
172 pFxFont = pCurFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700173#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
174 FxFont.SetFace(pFxFont->GetFace());
175 FX_BOOL bRet = m_pDevice->DrawNormalText(
176 iCurCount, pCurCP, &FxFont, pCache, -fFontSize,
177 (const CFX_Matrix*)pMatrix, argb, FXTEXT_CLEARTYPE);
178 FxFont.SetSubstFont(nullptr);
179 FxFont.SetFace(nullptr);
180 return bRet;
181#else
182 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
183 -fFontSize, (const CFX_Matrix*)pMatrix,
184 argb, FXTEXT_CLEARTYPE);
185#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
186 }
187
188#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
189 FxFont.SetSubstFont(nullptr);
190 FxFont.SetFace(nullptr);
191#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
192
193 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -0400194}
dsinclaira5c13232016-04-12 13:19:36 -0700195
dsinclairacd0d592016-04-21 11:06:27 -0700196FX_BOOL CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
197 FX_FLOAT fPenWidth,
198 const CFX_PointF& pt1,
199 const CFX_PointF& pt2,
200 const CFX_PointF& pt3,
201 const CFX_PointF& pt4,
202 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400203 CFX_PointsF points;
204 points.Add(pt1);
205 points.Add(pt2);
206 points.Add(pt3);
207 points.Add(pt4);
208 CFDE_Path path;
209 path.AddBezier(points);
210 return DrawPath(pPen, fPenWidth, &path, pMatrix);
211}
dsinclairacd0d592016-04-21 11:06:27 -0700212FX_BOOL CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
213 FX_FLOAT fPenWidth,
214 const CFX_PointsF& points,
215 FX_BOOL bClosed,
216 FX_FLOAT fTension,
217 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400218 CFDE_Path path;
219 path.AddCurve(points, bClosed, fTension);
220 return DrawPath(pPen, fPenWidth, &path, pMatrix);
221}
dsinclairacd0d592016-04-21 11:06:27 -0700222FX_BOOL CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
223 FX_FLOAT fPenWidth,
224 const CFX_RectF& rect,
225 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400226 CFDE_Path path;
227 path.AddEllipse(rect);
228 return DrawPath(pPen, fPenWidth, &path, pMatrix);
229}
dsinclairacd0d592016-04-21 11:06:27 -0700230FX_BOOL CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
231 FX_FLOAT fPenWidth,
232 const CFX_PointsF& points,
233 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400234 CFDE_Path path;
235 path.AddLines(points);
236 return DrawPath(pPen, fPenWidth, &path, pMatrix);
237}
dsinclairacd0d592016-04-21 11:06:27 -0700238FX_BOOL CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
239 FX_FLOAT fPenWidth,
240 const CFX_PointF& pt1,
241 const CFX_PointF& pt2,
242 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400243 CFDE_Path path;
244 path.AddLine(pt1, pt2);
245 return DrawPath(pPen, fPenWidth, &path, pMatrix);
246}
dsinclairacd0d592016-04-21 11:06:27 -0700247FX_BOOL CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
248 FX_FLOAT fPenWidth,
249 const CFDE_Path* pPath,
250 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400251 CFDE_Path* pGePath = (CFDE_Path*)pPath;
252 if (pGePath == NULL) {
253 return FALSE;
254 }
255 CFX_GraphStateData graphState;
256 if (!CreatePen(pPen, fPenWidth, graphState)) {
257 return FALSE;
258 }
259 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
260 &graphState, 0, pPen->GetColor(), 0);
261}
dsinclairacd0d592016-04-21 11:06:27 -0700262FX_BOOL CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
263 FX_FLOAT fPenWidth,
264 const CFX_PointsF& points,
265 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400266 CFDE_Path path;
267 path.AddPolygon(points);
268 return DrawPath(pPen, fPenWidth, &path, pMatrix);
269}
dsinclairacd0d592016-04-21 11:06:27 -0700270FX_BOOL CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
271 FX_FLOAT fPenWidth,
272 const CFX_RectF& rect,
273 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400274 CFDE_Path path;
275 path.AddRectangle(rect);
276 return DrawPath(pPen, fPenWidth, &path, pMatrix);
277}
dsinclairacd0d592016-04-21 11:06:27 -0700278FX_BOOL CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
279 const CFX_PointsF& points,
280 FX_FLOAT fTension,
281 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400282 CFDE_Path path;
283 path.AddCurve(points, TRUE, fTension);
284 return FillPath(pBrush, &path, pMatrix);
285}
dsinclairacd0d592016-04-21 11:06:27 -0700286FX_BOOL CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
287 const CFX_RectF& rect,
288 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400289 CFDE_Path path;
290 path.AddEllipse(rect);
291 return FillPath(pBrush, &path, pMatrix);
292}
dsinclairacd0d592016-04-21 11:06:27 -0700293FX_BOOL CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
294 const CFX_PointsF& points,
295 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400296 CFDE_Path path;
297 path.AddPolygon(points);
298 return FillPath(pBrush, &path, pMatrix);
299}
dsinclairacd0d592016-04-21 11:06:27 -0700300FX_BOOL CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
301 const CFX_RectF& rect,
302 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400303 CFDE_Path path;
304 path.AddRectangle(rect);
305 return FillPath(pBrush, &path, pMatrix);
306}
dsinclairacd0d592016-04-21 11:06:27 -0700307FX_BOOL CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
308 FX_FLOAT fPenWidth,
309 CFX_GraphStateData& graphState) {
dsinclaira5c13232016-04-12 13:19:36 -0700310 if (!pPen)
Dan Sinclair1770c022016-03-14 14:14:16 -0400311 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700312
313 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
314 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
Dan Sinclair1770c022016-03-14 14:14:16 -0400315 graphState.m_LineWidth = fPenWidth;
dsinclaira5c13232016-04-12 13:19:36 -0700316 graphState.m_MiterLimit = 10;
317 graphState.m_DashPhase = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400318 return TRUE;
319}
dsinclair25c223d2016-04-12 09:51:45 -0700320
dsinclairacd0d592016-04-21 11:06:27 -0700321FX_BOOL CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
322 const CFDE_Path* pPath,
323 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400324 CFDE_Path* pGePath = (CFDE_Path*)pPath;
dsinclair25c223d2016-04-12 09:51:45 -0700325 if (!pGePath)
Dan Sinclair1770c022016-03-14 14:14:16 -0400326 return FALSE;
dsinclair25c223d2016-04-12 09:51:45 -0700327 if (!pBrush)
Dan Sinclair1770c022016-03-14 14:14:16 -0400328 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700329 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
330 pBrush->GetColor(), 0, FXFILL_WINDING);
Dan Sinclair1770c022016-03-14 14:14:16 -0400331}
dsinclair25c223d2016-04-12 09:51:45 -0700332