blob: 03065d751cf559d4b78a987fa6614d63efc07c35 [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"
thestiga4fdfc52016-06-07 17:33:37 -070014#include "xfa/fgas/font/fgas_gefont.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040015
dsinclairacd0d592016-04-21 11:06:27 -070016CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice,
17 FX_BOOL bOwnerDevice)
Dan Sinclair1770c022016-03-14 14:14:16 -040018 : m_pDevice(pDevice),
19 m_bOwnerDevice(bOwnerDevice),
dsinclairacd0d592016-04-21 11:06:27 -070020 m_pCharPos(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040021 m_iCharCount(0) {
dsinclair43854a52016-04-27 12:26:00 -070022 ASSERT(pDevice);
dsinclairacd0d592016-04-21 11:06:27 -070023
Dan Sinclair1770c022016-03-14 14:14:16 -040024 FX_RECT rt = m_pDevice->GetClipBox();
25 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
26 (FX_FLOAT)rt.Height());
27}
dsinclairacd0d592016-04-21 11:06:27 -070028
29CFDE_RenderDevice::~CFDE_RenderDevice() {
Dan Sinclair1770c022016-03-14 14:14:16 -040030 FX_Free(m_pCharPos);
31 if (m_bOwnerDevice)
32 delete m_pDevice;
33}
dsinclairacd0d592016-04-21 11:06:27 -070034int32_t CFDE_RenderDevice::GetWidth() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040035 return m_pDevice->GetWidth();
36}
dsinclairacd0d592016-04-21 11:06:27 -070037int32_t CFDE_RenderDevice::GetHeight() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040038 return m_pDevice->GetHeight();
39}
dsinclairfe433f12016-06-06 12:03:31 -070040void CFDE_RenderDevice::SaveState() {
Dan Sinclair1770c022016-03-14 14:14:16 -040041 m_pDevice->SaveState();
Dan Sinclair1770c022016-03-14 14:14:16 -040042}
dsinclairfe433f12016-06-06 12:03:31 -070043void CFDE_RenderDevice::RestoreState() {
thestig41846a02016-05-26 10:45:30 -070044 m_pDevice->RestoreState(false);
Dan Sinclair1770c022016-03-14 14:14:16 -040045 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,
thestiga4fdfc52016-06-07 17:33:37 -0700108 CFGAS_GEFont* pFont,
dsinclairacd0d592016-04-21 11:06:27 -0700109 const FXTEXT_CHARPOS* pCharPos,
110 int32_t iCount,
111 FX_FLOAT fFontSize,
112 const CFX_Matrix* pMatrix) {
tsepez48ddd862016-06-06 10:51:58 -0700113 ASSERT(pBrush && pFont && pCharPos && iCount > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400114 CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
tsepez48ddd862016-06-06 10:51:58 -0700115 CFX_Font* pFxFont = pFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700116 FX_ARGB argb = pBrush->GetColor();
117 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
118 !pFxFont->IsItalic()) {
119 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
120 FX_FLOAT* pAM;
121 for (int32_t i = 0; i < iCount; ++i) {
122 static const FX_FLOAT mc = 0.267949f;
123 pAM = pCP->m_AdjustMatrix;
124 pAM[2] = mc * pAM[0] + pAM[2];
125 pAM[3] = mc * pAM[1] + pAM[3];
126 pCP++;
127 }
128 }
129 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
thestiga4fdfc52016-06-07 17:33:37 -0700130 CFGAS_GEFont* pCurFont = NULL;
131 CFGAS_GEFont* pSTFont = NULL;
dsinclaira5c13232016-04-12 13:19:36 -0700132 FXTEXT_CHARPOS* pCurCP = NULL;
133 int32_t iCurCount = 0;
134
Dan Sinclair1770c022016-03-14 14:14:16 -0400135#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700136 uint32_t dwFontStyle = pFont->GetFontStyles();
137 CFX_Font FxFont;
138 CFX_SubstFont SubstFxFont;
139 FxFont.SetSubstFont(&SubstFxFont);
140 SubstFxFont.m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
141 SubstFxFont.m_WeightCJK = SubstFxFont.m_Weight;
142 SubstFxFont.m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
143 SubstFxFont.m_bItlicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
Dan Sinclair1770c022016-03-14 14:14:16 -0400144#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700145
146 for (int32_t i = 0; i < iCount; ++i) {
147 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
148 pCP->m_GlyphIndex &= 0x00FFFFFF;
149 pCP->m_bFontStyle = FALSE;
150 if (pCurFont != pSTFont) {
tsepez48ddd862016-06-06 10:51:58 -0700151 if (pCurFont) {
152 pFxFont = pCurFont->GetDevFont();
Dan Sinclair1770c022016-03-14 14:14:16 -0400153#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
154 FxFont.SetFace(pFxFont->GetFace());
dsinclaira5c13232016-04-12 13:19:36 -0700155 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, pCache,
156 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
157 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400158#else
dsinclaira5c13232016-04-12 13:19:36 -0700159 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
160 -fFontSize, (const CFX_Matrix*)pMatrix, argb,
161 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400162#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
163 }
dsinclaira5c13232016-04-12 13:19:36 -0700164 pCurFont = pSTFont;
165 pCurCP = pCP;
166 iCurCount = 1;
167 } else {
168 iCurCount++;
169 }
170 pCP++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400171 }
tsepez48ddd862016-06-06 10:51:58 -0700172 if (pCurFont && iCurCount) {
173 pFxFont = pCurFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700174#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
175 FxFont.SetFace(pFxFont->GetFace());
176 FX_BOOL bRet = m_pDevice->DrawNormalText(
177 iCurCount, pCurCP, &FxFont, pCache, -fFontSize,
178 (const CFX_Matrix*)pMatrix, argb, FXTEXT_CLEARTYPE);
179 FxFont.SetSubstFont(nullptr);
180 FxFont.SetFace(nullptr);
181 return bRet;
182#else
183 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
184 -fFontSize, (const CFX_Matrix*)pMatrix,
185 argb, FXTEXT_CLEARTYPE);
186#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
187 }
188
189#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
190 FxFont.SetSubstFont(nullptr);
191 FxFont.SetFace(nullptr);
192#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
193
194 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -0400195}
dsinclaira5c13232016-04-12 13:19:36 -0700196
dsinclairacd0d592016-04-21 11:06:27 -0700197FX_BOOL CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
198 FX_FLOAT fPenWidth,
199 const CFX_PointF& pt1,
200 const CFX_PointF& pt2,
201 const CFX_PointF& pt3,
202 const CFX_PointF& pt4,
203 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400204 CFX_PointsF points;
205 points.Add(pt1);
206 points.Add(pt2);
207 points.Add(pt3);
208 points.Add(pt4);
209 CFDE_Path path;
210 path.AddBezier(points);
211 return DrawPath(pPen, fPenWidth, &path, pMatrix);
212}
dsinclairacd0d592016-04-21 11:06:27 -0700213FX_BOOL CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
214 FX_FLOAT fPenWidth,
215 const CFX_PointsF& points,
216 FX_BOOL bClosed,
217 FX_FLOAT fTension,
218 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400219 CFDE_Path path;
220 path.AddCurve(points, bClosed, fTension);
221 return DrawPath(pPen, fPenWidth, &path, pMatrix);
222}
dsinclairacd0d592016-04-21 11:06:27 -0700223FX_BOOL CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
224 FX_FLOAT fPenWidth,
225 const CFX_RectF& rect,
226 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400227 CFDE_Path path;
228 path.AddEllipse(rect);
229 return DrawPath(pPen, fPenWidth, &path, pMatrix);
230}
dsinclairacd0d592016-04-21 11:06:27 -0700231FX_BOOL CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
232 FX_FLOAT fPenWidth,
233 const CFX_PointsF& points,
234 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400235 CFDE_Path path;
236 path.AddLines(points);
237 return DrawPath(pPen, fPenWidth, &path, pMatrix);
238}
dsinclairacd0d592016-04-21 11:06:27 -0700239FX_BOOL CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
240 FX_FLOAT fPenWidth,
241 const CFX_PointF& pt1,
242 const CFX_PointF& pt2,
243 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400244 CFDE_Path path;
245 path.AddLine(pt1, pt2);
246 return DrawPath(pPen, fPenWidth, &path, pMatrix);
247}
dsinclairacd0d592016-04-21 11:06:27 -0700248FX_BOOL CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
249 FX_FLOAT fPenWidth,
250 const CFDE_Path* pPath,
251 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400252 CFDE_Path* pGePath = (CFDE_Path*)pPath;
253 if (pGePath == NULL) {
254 return FALSE;
255 }
256 CFX_GraphStateData graphState;
257 if (!CreatePen(pPen, fPenWidth, graphState)) {
258 return FALSE;
259 }
260 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
261 &graphState, 0, pPen->GetColor(), 0);
262}
dsinclairacd0d592016-04-21 11:06:27 -0700263FX_BOOL CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
264 FX_FLOAT fPenWidth,
265 const CFX_PointsF& points,
266 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400267 CFDE_Path path;
268 path.AddPolygon(points);
269 return DrawPath(pPen, fPenWidth, &path, pMatrix);
270}
dsinclairacd0d592016-04-21 11:06:27 -0700271FX_BOOL CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
272 FX_FLOAT fPenWidth,
273 const CFX_RectF& rect,
274 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400275 CFDE_Path path;
276 path.AddRectangle(rect);
277 return DrawPath(pPen, fPenWidth, &path, pMatrix);
278}
dsinclairacd0d592016-04-21 11:06:27 -0700279FX_BOOL CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
280 const CFX_PointsF& points,
281 FX_FLOAT fTension,
282 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400283 CFDE_Path path;
284 path.AddCurve(points, TRUE, fTension);
285 return FillPath(pBrush, &path, pMatrix);
286}
dsinclairacd0d592016-04-21 11:06:27 -0700287FX_BOOL CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
288 const CFX_RectF& rect,
289 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400290 CFDE_Path path;
291 path.AddEllipse(rect);
292 return FillPath(pBrush, &path, pMatrix);
293}
dsinclairacd0d592016-04-21 11:06:27 -0700294FX_BOOL CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
295 const CFX_PointsF& points,
296 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400297 CFDE_Path path;
298 path.AddPolygon(points);
299 return FillPath(pBrush, &path, pMatrix);
300}
dsinclairacd0d592016-04-21 11:06:27 -0700301FX_BOOL CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
302 const CFX_RectF& rect,
303 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400304 CFDE_Path path;
305 path.AddRectangle(rect);
306 return FillPath(pBrush, &path, pMatrix);
307}
dsinclairacd0d592016-04-21 11:06:27 -0700308FX_BOOL CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
309 FX_FLOAT fPenWidth,
310 CFX_GraphStateData& graphState) {
dsinclaira5c13232016-04-12 13:19:36 -0700311 if (!pPen)
Dan Sinclair1770c022016-03-14 14:14:16 -0400312 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700313
314 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
315 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
Dan Sinclair1770c022016-03-14 14:14:16 -0400316 graphState.m_LineWidth = fPenWidth;
dsinclaira5c13232016-04-12 13:19:36 -0700317 graphState.m_MiterLimit = 10;
318 graphState.m_DashPhase = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400319 return TRUE;
320}
dsinclair25c223d2016-04-12 09:51:45 -0700321
dsinclairacd0d592016-04-21 11:06:27 -0700322FX_BOOL CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
323 const CFDE_Path* pPath,
324 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400325 CFDE_Path* pGePath = (CFDE_Path*)pPath;
dsinclair25c223d2016-04-12 09:51:45 -0700326 if (!pGePath)
Dan Sinclair1770c022016-03-14 14:14:16 -0400327 return FALSE;
dsinclair25c223d2016-04-12 09:51:45 -0700328 if (!pBrush)
Dan Sinclair1770c022016-03-14 14:14:16 -0400329 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700330 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
331 pBrush->GetColor(), 0, FXFILL_WINDING);
Dan Sinclair1770c022016-03-14 14:14:16 -0400332}
dsinclair25c223d2016-04-12 09:51:45 -0700333