blob: 15c849f71f7fe38e8b0f0e012900691b1b1fd8c8 [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
npm26b86e62016-08-04 17:22:14 -070011#include "core/fxge/include/cfx_gemodule.h"
npm9ada2d82016-08-10 07:51:38 -070012#include "core/fxge/include/cfx_graphstatedata.h"
13#include "core/fxge/include/cfx_renderdevice.h"
npm81ee14d2016-08-29 09:35:12 -070014#include "core/fxge/include/cfx_substfont.h"
dsinclairacd0d592016-04-21 11:06:27 -070015#include "xfa/fde/cfde_path.h"
dsinclair25c223d2016-04-12 09:51:45 -070016#include "xfa/fde/fde_object.h"
dsinclairacd0d592016-04-21 11:06:27 -070017#include "xfa/fgas/font/fgas_font.h"
thestiga4fdfc52016-06-07 17:33:37 -070018#include "xfa/fgas/font/fgas_gefont.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040019
dsinclairacd0d592016-04-21 11:06:27 -070020CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice,
21 FX_BOOL bOwnerDevice)
Dan Sinclair1770c022016-03-14 14:14:16 -040022 : m_pDevice(pDevice),
23 m_bOwnerDevice(bOwnerDevice),
Dan Sinclair1770c022016-03-14 14:14:16 -040024 m_iCharCount(0) {
dsinclair43854a52016-04-27 12:26:00 -070025 ASSERT(pDevice);
dsinclairacd0d592016-04-21 11:06:27 -070026
Dan Sinclair1770c022016-03-14 14:14:16 -040027 FX_RECT rt = m_pDevice->GetClipBox();
28 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
29 (FX_FLOAT)rt.Height());
30}
dsinclairacd0d592016-04-21 11:06:27 -070031
32CFDE_RenderDevice::~CFDE_RenderDevice() {
Dan Sinclair1770c022016-03-14 14:14:16 -040033 if (m_bOwnerDevice)
34 delete m_pDevice;
35}
dsinclairacd0d592016-04-21 11:06:27 -070036int32_t CFDE_RenderDevice::GetWidth() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040037 return m_pDevice->GetWidth();
38}
dsinclairacd0d592016-04-21 11:06:27 -070039int32_t CFDE_RenderDevice::GetHeight() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040040 return m_pDevice->GetHeight();
41}
dsinclairfe433f12016-06-06 12:03:31 -070042void CFDE_RenderDevice::SaveState() {
Dan Sinclair1770c022016-03-14 14:14:16 -040043 m_pDevice->SaveState();
Dan Sinclair1770c022016-03-14 14:14:16 -040044}
dsinclairfe433f12016-06-06 12:03:31 -070045void CFDE_RenderDevice::RestoreState() {
thestig41846a02016-05-26 10:45:30 -070046 m_pDevice->RestoreState(false);
Dan Sinclair1770c022016-03-14 14:14:16 -040047 const FX_RECT& rt = m_pDevice->GetClipBox();
48 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
49 (FX_FLOAT)rt.Height());
50}
dsinclairacd0d592016-04-21 11:06:27 -070051FX_BOOL CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) {
Dan Sinclair1770c022016-03-14 14:14:16 -040052 m_rtClip = rtClip;
53 return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left),
54 (int32_t)FXSYS_floor(rtClip.top),
55 (int32_t)FXSYS_ceil(rtClip.right()),
56 (int32_t)FXSYS_ceil(rtClip.bottom())));
57}
dsinclairacd0d592016-04-21 11:06:27 -070058const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
Dan Sinclair1770c022016-03-14 14:14:16 -040059 return m_rtClip;
60}
dsinclairacd0d592016-04-21 11:06:27 -070061FX_BOOL CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
Dan Sinclair1770c022016-03-14 14:14:16 -040062 return FALSE;
63}
dsinclairacd0d592016-04-21 11:06:27 -070064CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
thestigcfb77cc2016-06-10 12:21:53 -070065 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -040066}
dsinclairacd0d592016-04-21 11:06:27 -070067FX_FLOAT CFDE_RenderDevice::GetDpiX() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040068 return 96;
69}
dsinclairacd0d592016-04-21 11:06:27 -070070FX_FLOAT CFDE_RenderDevice::GetDpiY() const {
Dan Sinclair1770c022016-03-14 14:14:16 -040071 return 96;
72}
dsinclairacd0d592016-04-21 11:06:27 -070073FX_BOOL CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib,
74 const CFX_RectF* pSrcRect,
75 const CFX_RectF& dstRect,
76 const CFX_Matrix* pImgMatrix,
77 const CFX_Matrix* pDevMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -040078 CFX_RectF srcRect;
79 if (pSrcRect) {
80 srcRect = *pSrcRect;
81 } else {
82 srcRect.Set(0, 0, (FX_FLOAT)pDib->GetWidth(), (FX_FLOAT)pDib->GetHeight());
83 }
84 if (srcRect.IsEmpty()) {
85 return FALSE;
86 }
87 CFX_Matrix dib2fxdev;
88 if (pImgMatrix) {
89 dib2fxdev = *pImgMatrix;
90 } else {
91 dib2fxdev.SetIdentity();
92 }
93 dib2fxdev.a = dstRect.width;
94 dib2fxdev.d = -dstRect.height;
95 dib2fxdev.e = dstRect.left;
96 dib2fxdev.f = dstRect.bottom();
97 if (pDevMatrix) {
98 dib2fxdev.Concat(*pDevMatrix);
99 }
thestigcfb77cc2016-06-10 12:21:53 -0700100 void* handle = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400101 m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
102 handle);
thestigcfb77cc2016-06-10 12:21:53 -0700103 while (m_pDevice->ContinueDIBits(handle, nullptr)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400104 }
105 m_pDevice->CancelDIBits(handle);
thestigcfb77cc2016-06-10 12:21:53 -0700106 return !!handle;
Dan Sinclair1770c022016-03-14 14:14:16 -0400107}
dsinclairacd0d592016-04-21 11:06:27 -0700108FX_BOOL CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
thestiga4fdfc52016-06-07 17:33:37 -0700109 CFGAS_GEFont* pFont,
dsinclairacd0d592016-04-21 11:06:27 -0700110 const FXTEXT_CHARPOS* pCharPos,
111 int32_t iCount,
112 FX_FLOAT fFontSize,
113 const CFX_Matrix* pMatrix) {
tsepez48ddd862016-06-06 10:51:58 -0700114 ASSERT(pBrush && pFont && pCharPos && iCount > 0);
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;
dsinclair85d1f2c2016-06-23 12:40:16 -0700130 CFGAS_GEFont* pCurFont = nullptr;
131 CFGAS_GEFont* pSTFont = nullptr;
132 FXTEXT_CHARPOS* pCurCP = nullptr;
dsinclaira5c13232016-04-12 13:19:36 -0700133 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;
weili9b671ac2016-07-25 07:40:27 -0700138 CFX_SubstFont* SubstFxFont = new CFX_SubstFont();
139 FxFont.SetSubstFont(std::unique_ptr<CFX_SubstFont>(SubstFxFont));
140 SubstFxFont->m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
141 SubstFxFont->m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
142 SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight;
143 SubstFxFont->m_bItalicCJK = !!(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;
thestigec51ac32016-06-20 10:38:52 -0700149 pCP->m_bFontStyle = false;
dsinclaira5c13232016-04-12 13:19:36 -0700150 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());
art-snake9972ff92016-09-20 07:46:25 -0700155 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize,
156 (const CFX_Matrix*)pMatrix, argb,
dsinclaira5c13232016-04-12 13:19:36 -0700157 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400158#else
art-snake9972ff92016-09-20 07:46:25 -0700159 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
160 (const CFX_Matrix*)pMatrix, argb,
dsinclaira5c13232016-04-12 13:19:36 -0700161 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(
art-snake9972ff92016-09-20 07:46:25 -0700177 iCurCount, pCurCP, &FxFont, -fFontSize, (const CFX_Matrix*)pMatrix,
178 argb, FXTEXT_CLEARTYPE);
dsinclaira5c13232016-04-12 13:19:36 -0700179 FxFont.SetFace(nullptr);
180 return bRet;
181#else
art-snake9972ff92016-09-20 07:46:25 -0700182 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
183 (const CFX_Matrix*)pMatrix, argb,
184 FXTEXT_CLEARTYPE);
dsinclaira5c13232016-04-12 13:19:36 -0700185#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
186 }
187
188#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700189 FxFont.SetFace(nullptr);
190#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
191
192 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -0400193}
dsinclaira5c13232016-04-12 13:19:36 -0700194
dsinclairacd0d592016-04-21 11:06:27 -0700195FX_BOOL CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
196 FX_FLOAT fPenWidth,
197 const CFX_PointF& pt1,
198 const CFX_PointF& pt2,
199 const CFX_PointF& pt3,
200 const CFX_PointF& pt4,
201 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400202 CFX_PointsF points;
203 points.Add(pt1);
204 points.Add(pt2);
205 points.Add(pt3);
206 points.Add(pt4);
207 CFDE_Path path;
208 path.AddBezier(points);
209 return DrawPath(pPen, fPenWidth, &path, pMatrix);
210}
dsinclairacd0d592016-04-21 11:06:27 -0700211FX_BOOL CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
212 FX_FLOAT fPenWidth,
213 const CFX_PointsF& points,
214 FX_BOOL bClosed,
215 FX_FLOAT fTension,
216 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400217 CFDE_Path path;
218 path.AddCurve(points, bClosed, fTension);
219 return DrawPath(pPen, fPenWidth, &path, pMatrix);
220}
dsinclairacd0d592016-04-21 11:06:27 -0700221FX_BOOL CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
222 FX_FLOAT fPenWidth,
223 const CFX_RectF& rect,
224 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400225 CFDE_Path path;
226 path.AddEllipse(rect);
227 return DrawPath(pPen, fPenWidth, &path, pMatrix);
228}
dsinclairacd0d592016-04-21 11:06:27 -0700229FX_BOOL CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
230 FX_FLOAT fPenWidth,
231 const CFX_PointsF& points,
232 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400233 CFDE_Path path;
234 path.AddLines(points);
235 return DrawPath(pPen, fPenWidth, &path, pMatrix);
236}
dsinclairacd0d592016-04-21 11:06:27 -0700237FX_BOOL CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
238 FX_FLOAT fPenWidth,
239 const CFX_PointF& pt1,
240 const CFX_PointF& pt2,
241 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400242 CFDE_Path path;
243 path.AddLine(pt1, pt2);
244 return DrawPath(pPen, fPenWidth, &path, pMatrix);
245}
dsinclairacd0d592016-04-21 11:06:27 -0700246FX_BOOL CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
247 FX_FLOAT fPenWidth,
248 const CFDE_Path* pPath,
249 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400250 CFDE_Path* pGePath = (CFDE_Path*)pPath;
thestigcfb77cc2016-06-10 12:21:53 -0700251 if (!pGePath)
Dan Sinclair1770c022016-03-14 14:14:16 -0400252 return FALSE;
thestigcfb77cc2016-06-10 12:21:53 -0700253
Dan Sinclair1770c022016-03-14 14:14:16 -0400254 CFX_GraphStateData graphState;
255 if (!CreatePen(pPen, fPenWidth, graphState)) {
256 return FALSE;
257 }
258 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
259 &graphState, 0, pPen->GetColor(), 0);
260}
dsinclairacd0d592016-04-21 11:06:27 -0700261FX_BOOL CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
262 FX_FLOAT fPenWidth,
263 const CFX_PointsF& points,
264 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400265 CFDE_Path path;
266 path.AddPolygon(points);
267 return DrawPath(pPen, fPenWidth, &path, pMatrix);
268}
dsinclairacd0d592016-04-21 11:06:27 -0700269FX_BOOL CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
270 FX_FLOAT fPenWidth,
271 const CFX_RectF& rect,
272 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400273 CFDE_Path path;
274 path.AddRectangle(rect);
275 return DrawPath(pPen, fPenWidth, &path, pMatrix);
276}
dsinclairacd0d592016-04-21 11:06:27 -0700277FX_BOOL CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
278 const CFX_PointsF& points,
279 FX_FLOAT fTension,
280 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 CFDE_Path path;
282 path.AddCurve(points, TRUE, fTension);
283 return FillPath(pBrush, &path, pMatrix);
284}
dsinclairacd0d592016-04-21 11:06:27 -0700285FX_BOOL CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
286 const CFX_RectF& rect,
287 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400288 CFDE_Path path;
289 path.AddEllipse(rect);
290 return FillPath(pBrush, &path, pMatrix);
291}
dsinclairacd0d592016-04-21 11:06:27 -0700292FX_BOOL CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
293 const CFX_PointsF& points,
294 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400295 CFDE_Path path;
296 path.AddPolygon(points);
297 return FillPath(pBrush, &path, pMatrix);
298}
dsinclairacd0d592016-04-21 11:06:27 -0700299FX_BOOL CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
300 const CFX_RectF& rect,
301 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400302 CFDE_Path path;
303 path.AddRectangle(rect);
304 return FillPath(pBrush, &path, pMatrix);
305}
dsinclairacd0d592016-04-21 11:06:27 -0700306FX_BOOL CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
307 FX_FLOAT fPenWidth,
308 CFX_GraphStateData& graphState) {
dsinclaira5c13232016-04-12 13:19:36 -0700309 if (!pPen)
Dan Sinclair1770c022016-03-14 14:14:16 -0400310 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700311
312 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
313 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
Dan Sinclair1770c022016-03-14 14:14:16 -0400314 graphState.m_LineWidth = fPenWidth;
dsinclaira5c13232016-04-12 13:19:36 -0700315 graphState.m_MiterLimit = 10;
316 graphState.m_DashPhase = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400317 return TRUE;
318}
dsinclair25c223d2016-04-12 09:51:45 -0700319
dsinclairacd0d592016-04-21 11:06:27 -0700320FX_BOOL CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
321 const CFDE_Path* pPath,
322 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400323 CFDE_Path* pGePath = (CFDE_Path*)pPath;
dsinclair25c223d2016-04-12 09:51:45 -0700324 if (!pGePath)
Dan Sinclair1770c022016-03-14 14:14:16 -0400325 return FALSE;
dsinclair25c223d2016-04-12 09:51:45 -0700326 if (!pBrush)
Dan Sinclair1770c022016-03-14 14:14:16 -0400327 return FALSE;
dsinclaira5c13232016-04-12 13:19:36 -0700328 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
329 pBrush->GetColor(), 0, FXFILL_WINDING);
Dan Sinclair1770c022016-03-14 14:14:16 -0400330}
dsinclair25c223d2016-04-12 09:51:45 -0700331