blob: 314d17cdc18ae75012629ff9ae54313eaf34933d [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
dsinclair74a34fc2016-09-29 16:41:42 -070011#include "core/fxge/cfx_gemodule.h"
12#include "core/fxge/cfx_graphstatedata.h"
13#include "core/fxge/cfx_renderdevice.h"
14#include "core/fxge/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,
tsepezd19e9122016-11-02 15:43:18 -070021 bool bOwnerDevice)
22 : m_pDevice(pDevice), m_bOwnerDevice(bOwnerDevice), m_iCharCount(0) {
dsinclair43854a52016-04-27 12:26:00 -070023 ASSERT(pDevice);
dsinclairacd0d592016-04-21 11:06:27 -070024
Dan Sinclair1770c022016-03-14 14:14:16 -040025 FX_RECT rt = m_pDevice->GetClipBox();
26 m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
27 (FX_FLOAT)rt.Height());
28}
dsinclairacd0d592016-04-21 11:06:27 -070029
30CFDE_RenderDevice::~CFDE_RenderDevice() {
Dan Sinclair1770c022016-03-14 14:14:16 -040031 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}
tsepezd19e9122016-11-02 15:43:18 -070049bool 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}
tsepezd19e9122016-11-02 15:43:18 -070059bool CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
60 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040061}
dsinclairacd0d592016-04-21 11:06:27 -070062CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
thestigcfb77cc2016-06-10 12:21:53 -070063 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -040064}
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}
tsepezd19e9122016-11-02 15:43:18 -070071bool 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 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()) {
tsepezd19e9122016-11-02 15:43:18 -070083 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040084 }
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 }
thestigcfb77cc2016-06-10 12:21:53 -070098 void* handle = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -040099 m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
100 handle);
thestigcfb77cc2016-06-10 12:21:53 -0700101 while (m_pDevice->ContinueDIBits(handle, nullptr)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400102 }
103 m_pDevice->CancelDIBits(handle);
thestigcfb77cc2016-06-10 12:21:53 -0700104 return !!handle;
Dan Sinclair1770c022016-03-14 14:14:16 -0400105}
tsepezd19e9122016-11-02 15:43:18 -0700106bool CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
107 CFGAS_GEFont* pFont,
108 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);
tsepez48ddd862016-06-06 10:51:58 -0700113 CFX_Font* pFxFont = pFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700114 FX_ARGB argb = pBrush->GetColor();
115 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
116 !pFxFont->IsItalic()) {
117 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
118 FX_FLOAT* pAM;
119 for (int32_t i = 0; i < iCount; ++i) {
120 static const FX_FLOAT mc = 0.267949f;
121 pAM = pCP->m_AdjustMatrix;
122 pAM[2] = mc * pAM[0] + pAM[2];
123 pAM[3] = mc * pAM[1] + pAM[3];
124 pCP++;
125 }
126 }
127 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
dsinclair85d1f2c2016-06-23 12:40:16 -0700128 CFGAS_GEFont* pCurFont = nullptr;
129 CFGAS_GEFont* pSTFont = nullptr;
130 FXTEXT_CHARPOS* pCurCP = nullptr;
dsinclaira5c13232016-04-12 13:19:36 -0700131 int32_t iCurCount = 0;
132
Dan Sinclair1770c022016-03-14 14:14:16 -0400133#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700134 uint32_t dwFontStyle = pFont->GetFontStyles();
135 CFX_Font FxFont;
weili9b671ac2016-07-25 07:40:27 -0700136 CFX_SubstFont* SubstFxFont = new CFX_SubstFont();
137 FxFont.SetSubstFont(std::unique_ptr<CFX_SubstFont>(SubstFxFont));
138 SubstFxFont->m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
139 SubstFxFont->m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
140 SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight;
141 SubstFxFont->m_bItalicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
Dan Sinclair1770c022016-03-14 14:14:16 -0400142#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700143
144 for (int32_t i = 0; i < iCount; ++i) {
145 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
146 pCP->m_GlyphIndex &= 0x00FFFFFF;
thestigec51ac32016-06-20 10:38:52 -0700147 pCP->m_bFontStyle = false;
dsinclaira5c13232016-04-12 13:19:36 -0700148 if (pCurFont != pSTFont) {
tsepez48ddd862016-06-06 10:51:58 -0700149 if (pCurFont) {
150 pFxFont = pCurFont->GetDevFont();
Dan Sinclair1770c022016-03-14 14:14:16 -0400151#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
152 FxFont.SetFace(pFxFont->GetFace());
art-snake9972ff92016-09-20 07:46:25 -0700153 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize,
154 (const CFX_Matrix*)pMatrix, argb,
dsinclaira5c13232016-04-12 13:19:36 -0700155 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400156#else
art-snake9972ff92016-09-20 07:46:25 -0700157 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
158 (const CFX_Matrix*)pMatrix, argb,
dsinclaira5c13232016-04-12 13:19:36 -0700159 FXTEXT_CLEARTYPE);
Dan Sinclair1770c022016-03-14 14:14:16 -0400160#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
161 }
dsinclaira5c13232016-04-12 13:19:36 -0700162 pCurFont = pSTFont;
163 pCurCP = pCP;
164 iCurCount = 1;
165 } else {
166 iCurCount++;
167 }
168 pCP++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400169 }
tsepez48ddd862016-06-06 10:51:58 -0700170 if (pCurFont && iCurCount) {
171 pFxFont = pCurFont->GetDevFont();
dsinclaira5c13232016-04-12 13:19:36 -0700172#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
173 FxFont.SetFace(pFxFont->GetFace());
tsepezd19e9122016-11-02 15:43:18 -0700174 bool bRet = m_pDevice->DrawNormalText(
art-snake9972ff92016-09-20 07:46:25 -0700175 iCurCount, pCurCP, &FxFont, -fFontSize, (const CFX_Matrix*)pMatrix,
176 argb, FXTEXT_CLEARTYPE);
dsinclaira5c13232016-04-12 13:19:36 -0700177 FxFont.SetFace(nullptr);
178 return bRet;
179#else
art-snake9972ff92016-09-20 07:46:25 -0700180 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
181 (const CFX_Matrix*)pMatrix, argb,
182 FXTEXT_CLEARTYPE);
dsinclaira5c13232016-04-12 13:19:36 -0700183#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
184 }
185
186#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
dsinclaira5c13232016-04-12 13:19:36 -0700187 FxFont.SetFace(nullptr);
188#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
189
tsepezd19e9122016-11-02 15:43:18 -0700190 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400191}
dsinclaira5c13232016-04-12 13:19:36 -0700192
tsepezd19e9122016-11-02 15:43:18 -0700193bool CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
194 FX_FLOAT fPenWidth,
195 const CFX_PointF& pt1,
196 const CFX_PointF& pt2,
197 const CFX_PointF& pt3,
198 const CFX_PointF& pt4,
199 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400200 CFX_PointsF points;
201 points.Add(pt1);
202 points.Add(pt2);
203 points.Add(pt3);
204 points.Add(pt4);
205 CFDE_Path path;
206 path.AddBezier(points);
207 return DrawPath(pPen, fPenWidth, &path, pMatrix);
208}
tsepezd19e9122016-11-02 15:43:18 -0700209bool CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
210 FX_FLOAT fPenWidth,
211 const CFX_PointsF& points,
212 bool bClosed,
213 FX_FLOAT fTension,
214 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400215 CFDE_Path path;
216 path.AddCurve(points, bClosed, fTension);
217 return DrawPath(pPen, fPenWidth, &path, pMatrix);
218}
tsepezd19e9122016-11-02 15:43:18 -0700219bool CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
220 FX_FLOAT fPenWidth,
221 const CFX_RectF& rect,
222 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400223 CFDE_Path path;
224 path.AddEllipse(rect);
225 return DrawPath(pPen, fPenWidth, &path, pMatrix);
226}
tsepezd19e9122016-11-02 15:43:18 -0700227bool CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
228 FX_FLOAT fPenWidth,
229 const CFX_PointsF& points,
230 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400231 CFDE_Path path;
232 path.AddLines(points);
233 return DrawPath(pPen, fPenWidth, &path, pMatrix);
234}
tsepezd19e9122016-11-02 15:43:18 -0700235bool CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
236 FX_FLOAT fPenWidth,
237 const CFX_PointF& pt1,
238 const CFX_PointF& pt2,
239 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400240 CFDE_Path path;
241 path.AddLine(pt1, pt2);
242 return DrawPath(pPen, fPenWidth, &path, pMatrix);
243}
tsepezd19e9122016-11-02 15:43:18 -0700244bool CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
245 FX_FLOAT fPenWidth,
246 const CFDE_Path* pPath,
247 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400248 CFDE_Path* pGePath = (CFDE_Path*)pPath;
thestigcfb77cc2016-06-10 12:21:53 -0700249 if (!pGePath)
tsepezd19e9122016-11-02 15:43:18 -0700250 return false;
thestigcfb77cc2016-06-10 12:21:53 -0700251
Dan Sinclair1770c022016-03-14 14:14:16 -0400252 CFX_GraphStateData graphState;
253 if (!CreatePen(pPen, fPenWidth, graphState)) {
tsepezd19e9122016-11-02 15:43:18 -0700254 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400255 }
256 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
257 &graphState, 0, pPen->GetColor(), 0);
258}
tsepezd19e9122016-11-02 15:43:18 -0700259bool CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
260 FX_FLOAT fPenWidth,
261 const CFX_PointsF& points,
262 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400263 CFDE_Path path;
264 path.AddPolygon(points);
265 return DrawPath(pPen, fPenWidth, &path, pMatrix);
266}
tsepezd19e9122016-11-02 15:43:18 -0700267bool CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
268 FX_FLOAT fPenWidth,
269 const CFX_RectF& rect,
270 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400271 CFDE_Path path;
272 path.AddRectangle(rect);
273 return DrawPath(pPen, fPenWidth, &path, pMatrix);
274}
tsepezd19e9122016-11-02 15:43:18 -0700275bool CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
276 const CFX_PointsF& points,
277 FX_FLOAT fTension,
278 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400279 CFDE_Path path;
tsepezd19e9122016-11-02 15:43:18 -0700280 path.AddCurve(points, true, fTension);
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 return FillPath(pBrush, &path, pMatrix);
282}
tsepezd19e9122016-11-02 15:43:18 -0700283bool CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
284 const CFX_RectF& rect,
285 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400286 CFDE_Path path;
287 path.AddEllipse(rect);
288 return FillPath(pBrush, &path, pMatrix);
289}
tsepezd19e9122016-11-02 15:43:18 -0700290bool CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
291 const CFX_PointsF& points,
292 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400293 CFDE_Path path;
294 path.AddPolygon(points);
295 return FillPath(pBrush, &path, pMatrix);
296}
tsepezd19e9122016-11-02 15:43:18 -0700297bool CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
298 const CFX_RectF& rect,
299 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400300 CFDE_Path path;
301 path.AddRectangle(rect);
302 return FillPath(pBrush, &path, pMatrix);
303}
tsepezd19e9122016-11-02 15:43:18 -0700304bool CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
305 FX_FLOAT fPenWidth,
306 CFX_GraphStateData& graphState) {
dsinclaira5c13232016-04-12 13:19:36 -0700307 if (!pPen)
tsepezd19e9122016-11-02 15:43:18 -0700308 return false;
dsinclaira5c13232016-04-12 13:19:36 -0700309
310 graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
311 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
Dan Sinclair1770c022016-03-14 14:14:16 -0400312 graphState.m_LineWidth = fPenWidth;
dsinclaira5c13232016-04-12 13:19:36 -0700313 graphState.m_MiterLimit = 10;
314 graphState.m_DashPhase = 0;
tsepezd19e9122016-11-02 15:43:18 -0700315 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400316}
dsinclair25c223d2016-04-12 09:51:45 -0700317
tsepezd19e9122016-11-02 15:43:18 -0700318bool CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
319 const CFDE_Path* pPath,
320 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400321 CFDE_Path* pGePath = (CFDE_Path*)pPath;
dsinclair25c223d2016-04-12 09:51:45 -0700322 if (!pGePath)
tsepezd19e9122016-11-02 15:43:18 -0700323 return false;
dsinclair25c223d2016-04-12 09:51:45 -0700324 if (!pBrush)
tsepezd19e9122016-11-02 15:43:18 -0700325 return false;
dsinclaira5c13232016-04-12 13:19:36 -0700326 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
327 pBrush->GetColor(), 0, FXFILL_WINDING);
Dan Sinclair1770c022016-03-14 14:14:16 -0400328}
dsinclair25c223d2016-04-12 09:51:45 -0700329