blob: f99dc6c2019d2c6c25e3fdd2e394a48d1941844b [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}
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) {
dsinclair43854a52016-04-27 12:26:00 -070076 ASSERT(pDib != NULL);
Dan Sinclair1770c022016-03-14 14:14:16 -040077 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) {
dsinclair43854a52016-04-27 12:26:00 -0700113 ASSERT(pBrush != NULL && pFont != NULL && pCharPos != NULL && iCount > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400114 CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
115 CFX_Font* pFxFont = (CFX_Font*)pFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700116
117 FX_ARGB argb = pBrush->GetColor();
118 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
119 !pFxFont->IsItalic()) {
120 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
121 FX_FLOAT* pAM;
122 for (int32_t i = 0; i < iCount; ++i) {
123 static const FX_FLOAT mc = 0.267949f;
124 pAM = pCP->m_AdjustMatrix;
125 pAM[2] = mc * pAM[0] + pAM[2];
126 pAM[3] = mc * pAM[1] + pAM[3];
127 pCP++;
128 }
129 }
130 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
131 IFX_Font* pCurFont = NULL;
132 IFX_Font* pSTFont = NULL;
133 FXTEXT_CHARPOS* pCurCP = NULL;
134 int32_t iCurCount = 0;
135
Dan Sinclair1770c022016-03-14 14:14:16 -0400136#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700137 uint32_t dwFontStyle = pFont->GetFontStyles();
138 CFX_Font FxFont;
139 CFX_SubstFont SubstFxFont;
140 FxFont.SetSubstFont(&SubstFxFont);
141 SubstFxFont.m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
142 SubstFxFont.m_WeightCJK = SubstFxFont.m_Weight;
143 SubstFxFont.m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
144 SubstFxFont.m_bItlicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
Dan Sinclair1770c022016-03-14 14:14:16 -0400145#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700146
147 for (int32_t i = 0; i < iCount; ++i) {
148 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
149 pCP->m_GlyphIndex &= 0x00FFFFFF;
150 pCP->m_bFontStyle = FALSE;
151 if (pCurFont != pSTFont) {
152 if (pCurFont != NULL) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400153 pFxFont = (CFX_Font*)pCurFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700154
Dan Sinclair1770c022016-03-14 14:14:16 -0400155#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
156 FxFont.SetFace(pFxFont->GetFace());
dsinclaira5c13232016-04-12 13:19:36 -0700157 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, pCache,
158 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
159 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400160#else
dsinclaira5c13232016-04-12 13:19:36 -0700161 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
162 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
163 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400164#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
165 }
dsinclaira5c13232016-04-12 13:19:36 -0700166 pCurFont = pSTFont;
167 pCurCP = pCP;
168 iCurCount = 1;
169 } else {
170 iCurCount++;
171 }
172 pCP++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400173 }
dsinclaira5c13232016-04-12 13:19:36 -0700174 if (pCurFont != NULL && iCurCount) {
175 pFxFont = (CFX_Font*)pCurFont->GetDevFont();
176
177#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
178 FxFont.SetFace(pFxFont->GetFace());
179 FX_BOOL bRet = m_pDevice->DrawNormalText(
180 iCurCount, pCurCP, &FxFont, pCache, -fFontSize,
181 (const CFX_Matrix*)pMatrix, argb, FXTEXT_CLEARTYPE);
182 FxFont.SetSubstFont(nullptr);
183 FxFont.SetFace(nullptr);
184 return bRet;
185#else
186 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
187 -fFontSize, (const CFX_Matrix*)pMatrix,
188 argb, FXTEXT_CLEARTYPE);
189#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
190 }
191
192#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
193 FxFont.SetSubstFont(nullptr);
194 FxFont.SetFace(nullptr);
195#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
196
197 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -0400198}
dsinclaira5c13232016-04-12 13:19:36 -0700199
dsinclairacd0d592016-04-21 11:06:27 -0700200FX_BOOL CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
201 FX_FLOAT fPenWidth,
202 const CFX_PointF& pt1,
203 const CFX_PointF& pt2,
204 const CFX_PointF& pt3,
205 const CFX_PointF& pt4,
206 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400207 CFX_PointsF points;
208 points.Add(pt1);
209 points.Add(pt2);
210 points.Add(pt3);
211 points.Add(pt4);
212 CFDE_Path path;
213 path.AddBezier(points);
214 return DrawPath(pPen, fPenWidth, &path, pMatrix);
215}
dsinclairacd0d592016-04-21 11:06:27 -0700216FX_BOOL CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
217 FX_FLOAT fPenWidth,
218 const CFX_PointsF& points,
219 FX_BOOL bClosed,
220 FX_FLOAT fTension,
221 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400222 CFDE_Path path;
223 path.AddCurve(points, bClosed, fTension);
224 return DrawPath(pPen, fPenWidth, &path, pMatrix);
225}
dsinclairacd0d592016-04-21 11:06:27 -0700226FX_BOOL CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
227 FX_FLOAT fPenWidth,
228 const CFX_RectF& rect,
229 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400230 CFDE_Path path;
231 path.AddEllipse(rect);
232 return DrawPath(pPen, fPenWidth, &path, pMatrix);
233}
dsinclairacd0d592016-04-21 11:06:27 -0700234FX_BOOL CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
235 FX_FLOAT fPenWidth,
236 const CFX_PointsF& points,
237 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400238 CFDE_Path path;
239 path.AddLines(points);
240 return DrawPath(pPen, fPenWidth, &path, pMatrix);
241}
dsinclairacd0d592016-04-21 11:06:27 -0700242FX_BOOL CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
243 FX_FLOAT fPenWidth,
244 const CFX_PointF& pt1,
245 const CFX_PointF& pt2,
246 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400247 CFDE_Path path;
248 path.AddLine(pt1, pt2);
249 return DrawPath(pPen, fPenWidth, &path, pMatrix);
250}
dsinclairacd0d592016-04-21 11:06:27 -0700251FX_BOOL CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
252 FX_FLOAT fPenWidth,
253 const CFDE_Path* pPath,
254 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400255 CFDE_Path* pGePath = (CFDE_Path*)pPath;
256 if (pGePath == NULL) {
257 return FALSE;
258 }
259 CFX_GraphStateData graphState;
260 if (!CreatePen(pPen, fPenWidth, graphState)) {
261 return FALSE;
262 }
263 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
264 &graphState, 0, pPen->GetColor(), 0);
265}
dsinclairacd0d592016-04-21 11:06:27 -0700266FX_BOOL CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
267 FX_FLOAT fPenWidth,
268 const CFX_PointsF& points,
269 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400270 CFDE_Path path;
271 path.AddPolygon(points);
272 return DrawPath(pPen, fPenWidth, &path, pMatrix);
273}
dsinclairacd0d592016-04-21 11:06:27 -0700274FX_BOOL CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
275 FX_FLOAT fPenWidth,
276 const CFX_RectF& rect,
277 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400278 CFDE_Path path;
279 path.AddRectangle(rect);
280 return DrawPath(pPen, fPenWidth, &path, pMatrix);
281}
dsinclairacd0d592016-04-21 11:06:27 -0700282FX_BOOL CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
283 const CFX_PointsF& points,
284 FX_FLOAT fTension,
285 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400286 CFDE_Path path;
287 path.AddCurve(points, TRUE, fTension);
288 return FillPath(pBrush, &path, pMatrix);
289}
dsinclairacd0d592016-04-21 11:06:27 -0700290FX_BOOL CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
291 const CFX_RectF& rect,
292 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400293 CFDE_Path path;
294 path.AddEllipse(rect);
295 return FillPath(pBrush, &path, pMatrix);
296}
dsinclairacd0d592016-04-21 11:06:27 -0700297FX_BOOL CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
298 const CFX_PointsF& points,
299 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400300 CFDE_Path path;
301 path.AddPolygon(points);
302 return FillPath(pBrush, &path, pMatrix);
303}
dsinclairacd0d592016-04-21 11:06:27 -0700304FX_BOOL CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
305 const CFX_RectF& rect,
306 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400307 CFDE_Path path;
308 path.AddRectangle(rect);
309 return FillPath(pBrush, &path, pMatrix);
310}
dsinclairacd0d592016-04-21 11:06:27 -0700311FX_BOOL CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
312 FX_FLOAT fPenWidth,
313 CFX_GraphStateData& graphState) {
dsinclaira5c13232016-04-12 13:19:36 -0700314 if (!pPen)
Dan Sinclair1770c022016-03-14 14:14:16 -0400315 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700316
317 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
318 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
Dan Sinclair1770c022016-03-14 14:14:16 -0400319 graphState.m_LineWidth = fPenWidth;
dsinclaira5c13232016-04-12 13:19:36 -0700320 graphState.m_MiterLimit = 10;
321 graphState.m_DashPhase = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400322 return TRUE;
323}
dsinclair25c223d2016-04-12 09:51:45 -0700324
dsinclairacd0d592016-04-21 11:06:27 -0700325FX_BOOL CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
326 const CFDE_Path* pPath,
327 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400328 CFDE_Path* pGePath = (CFDE_Path*)pPath;
dsinclair25c223d2016-04-12 09:51:45 -0700329 if (!pGePath)
Dan Sinclair1770c022016-03-14 14:14:16 -0400330 return FALSE;
dsinclair25c223d2016-04-12 09:51:45 -0700331 if (!pBrush)
Dan Sinclair1770c022016-03-14 14:14:16 -0400332 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700333 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
334 pBrush->GetColor(), 0, FXFILL_WINDING);
Dan Sinclair1770c022016-03-14 14:14:16 -0400335}
dsinclair25c223d2016-04-12 09:51:45 -0700336