fde_gedevice.cpp revision 33357cad1fd1321a2b38d2963e2585f27ce980a2
1// 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#include <memory> 11 12#include "core/fxge/cfx_gemodule.h" 13#include "core/fxge/cfx_graphstatedata.h" 14#include "core/fxge/cfx_renderdevice.h" 15#include "core/fxge/cfx_substfont.h" 16#include "xfa/fde/cfde_path.h" 17#include "xfa/fde/fde_object.h" 18#include "xfa/fgas/font/cfgas_fontmgr.h" 19#include "xfa/fgas/font/cfgas_gefont.h" 20 21CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice, 22 bool bOwnerDevice) 23 : m_pDevice(pDevice), m_bOwnerDevice(bOwnerDevice), m_iCharCount(0) { 24 ASSERT(pDevice); 25 26 FX_RECT rt = m_pDevice->GetClipBox(); 27 m_rtClip = CFX_RectF( 28 static_cast<FX_FLOAT>(rt.left), static_cast<FX_FLOAT>(rt.top), 29 static_cast<FX_FLOAT>(rt.Width()), static_cast<FX_FLOAT>(rt.Height())); 30} 31 32CFDE_RenderDevice::~CFDE_RenderDevice() { 33 if (m_bOwnerDevice) 34 delete m_pDevice; 35} 36 37int32_t CFDE_RenderDevice::GetWidth() const { 38 return m_pDevice->GetWidth(); 39} 40 41int32_t CFDE_RenderDevice::GetHeight() const { 42 return m_pDevice->GetHeight(); 43} 44 45void CFDE_RenderDevice::SaveState() { 46 m_pDevice->SaveState(); 47} 48 49void CFDE_RenderDevice::RestoreState() { 50 m_pDevice->RestoreState(false); 51 const FX_RECT& rt = m_pDevice->GetClipBox(); 52 m_rtClip = CFX_RectF( 53 static_cast<FX_FLOAT>(rt.left), static_cast<FX_FLOAT>(rt.top), 54 static_cast<FX_FLOAT>(rt.Width()), static_cast<FX_FLOAT>(rt.Height())); 55} 56 57bool CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) { 58 m_rtClip = rtClip; 59 return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left), 60 (int32_t)FXSYS_floor(rtClip.top), 61 (int32_t)FXSYS_ceil(rtClip.right()), 62 (int32_t)FXSYS_ceil(rtClip.bottom()))); 63} 64 65const CFX_RectF& CFDE_RenderDevice::GetClipRect() { 66 return m_rtClip; 67} 68 69bool CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) { 70 return false; 71} 72 73CFDE_Path* CFDE_RenderDevice::GetClipPath() const { 74 return nullptr; 75} 76 77FX_FLOAT CFDE_RenderDevice::GetDpiX() const { 78 return 96; 79} 80 81FX_FLOAT CFDE_RenderDevice::GetDpiY() const { 82 return 96; 83} 84 85bool CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib, 86 const CFX_RectF* pSrcRect, 87 const CFX_RectF& dstRect, 88 const CFX_Matrix* pImgMatrix, 89 const CFX_Matrix* pDevMatrix) { 90 CFX_RectF srcRect; 91 if (pSrcRect) { 92 srcRect = *pSrcRect; 93 } else { 94 srcRect = CFX_RectF(0, 0, static_cast<FX_FLOAT>(pDib->GetWidth()), 95 static_cast<FX_FLOAT>(pDib->GetHeight())); 96 } 97 98 if (srcRect.IsEmpty()) 99 return false; 100 101 CFX_Matrix dib2fxdev; 102 if (pImgMatrix) { 103 dib2fxdev = *pImgMatrix; 104 } else { 105 dib2fxdev.SetIdentity(); 106 } 107 dib2fxdev.a = dstRect.width; 108 dib2fxdev.d = -dstRect.height; 109 dib2fxdev.e = dstRect.left; 110 dib2fxdev.f = dstRect.bottom(); 111 if (pDevMatrix) { 112 dib2fxdev.Concat(*pDevMatrix); 113 } 114 void* handle = nullptr; 115 m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0, 116 handle); 117 while (m_pDevice->ContinueDIBits(handle, nullptr)) { 118 } 119 m_pDevice->CancelDIBits(handle); 120 return !!handle; 121} 122 123bool CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush, 124 const CFX_RetainPtr<CFGAS_GEFont>& pFont, 125 const FXTEXT_CHARPOS* pCharPos, 126 int32_t iCount, 127 FX_FLOAT fFontSize, 128 const CFX_Matrix* pMatrix) { 129 ASSERT(pBrush && pFont && pCharPos && iCount > 0); 130 CFX_Font* pFxFont = pFont->GetDevFont(); 131 FX_ARGB argb = pBrush->GetColor(); 132 if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 && 133 !pFxFont->IsItalic()) { 134 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos; 135 FX_FLOAT* pAM; 136 for (int32_t i = 0; i < iCount; ++i) { 137 static const FX_FLOAT mc = 0.267949f; 138 pAM = pCP->m_AdjustMatrix; 139 pAM[2] = mc * pAM[0] + pAM[2]; 140 pAM[3] = mc * pAM[1] + pAM[3]; 141 pCP++; 142 } 143 } 144 FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos; 145 CFX_RetainPtr<CFGAS_GEFont> pCurFont; 146 CFX_RetainPtr<CFGAS_GEFont> pSTFont; 147 FXTEXT_CHARPOS* pCurCP = nullptr; 148 int32_t iCurCount = 0; 149 150#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 151 uint32_t dwFontStyle = pFont->GetFontStyles(); 152 CFX_Font FxFont; 153 CFX_SubstFont* SubstFxFont = new CFX_SubstFont(); 154 FxFont.SetSubstFont(std::unique_ptr<CFX_SubstFont>(SubstFxFont)); 155 SubstFxFont->m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400; 156 SubstFxFont->m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0; 157 SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight; 158 SubstFxFont->m_bItalicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic); 159#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 160 161 for (int32_t i = 0; i < iCount; ++i) { 162 pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex); 163 pCP->m_GlyphIndex &= 0x00FFFFFF; 164 pCP->m_bFontStyle = false; 165 if (pCurFont != pSTFont) { 166 if (pCurFont) { 167 pFxFont = pCurFont->GetDevFont(); 168#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 169 FxFont.SetFace(pFxFont->GetFace()); 170 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize, 171 pMatrix, argb, FXTEXT_CLEARTYPE); 172#else 173 m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize, 174 pMatrix, argb, FXTEXT_CLEARTYPE); 175#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 176 } 177 pCurFont = pSTFont; 178 pCurCP = pCP; 179 iCurCount = 1; 180 } else { 181 iCurCount++; 182 } 183 pCP++; 184 } 185 if (pCurFont && iCurCount) { 186 pFxFont = pCurFont->GetDevFont(); 187#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 188 FxFont.SetFace(pFxFont->GetFace()); 189 bool bRet = 190 m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize, 191 pMatrix, argb, FXTEXT_CLEARTYPE); 192 FxFont.SetFace(nullptr); 193 return bRet; 194#else 195 return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize, 196 pMatrix, argb, FXTEXT_CLEARTYPE); 197#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 198 } 199 200#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 201 FxFont.SetFace(nullptr); 202#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 203 204 return true; 205} 206 207bool CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen, 208 FX_FLOAT fPenWidth, 209 const CFX_PointF& pt1, 210 const CFX_PointF& pt2, 211 const CFX_PointF& pt3, 212 const CFX_PointF& pt4, 213 const CFX_Matrix* pMatrix) { 214 std::vector<CFX_PointF> points; 215 points.push_back(pt1); 216 points.push_back(pt2); 217 points.push_back(pt3); 218 points.push_back(pt4); 219 CFDE_Path path; 220 path.AddBezier(points); 221 return DrawPath(pPen, fPenWidth, &path, pMatrix); 222} 223 224bool CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen, 225 FX_FLOAT fPenWidth, 226 const std::vector<CFX_PointF>& points, 227 bool bClosed, 228 FX_FLOAT fTension, 229 const CFX_Matrix* pMatrix) { 230 CFDE_Path path; 231 path.AddCurve(points, bClosed, fTension); 232 return DrawPath(pPen, fPenWidth, &path, pMatrix); 233} 234 235bool CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen, 236 FX_FLOAT fPenWidth, 237 const CFX_RectF& rect, 238 const CFX_Matrix* pMatrix) { 239 CFDE_Path path; 240 path.AddEllipse(rect); 241 return DrawPath(pPen, fPenWidth, &path, pMatrix); 242} 243 244bool CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen, 245 FX_FLOAT fPenWidth, 246 const std::vector<CFX_PointF>& points, 247 const CFX_Matrix* pMatrix) { 248 CFDE_Path path; 249 path.AddLines(points); 250 return DrawPath(pPen, fPenWidth, &path, pMatrix); 251} 252 253bool CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen, 254 FX_FLOAT fPenWidth, 255 const CFX_PointF& pt1, 256 const CFX_PointF& pt2, 257 const CFX_Matrix* pMatrix) { 258 CFDE_Path path; 259 path.AddLine(pt1, pt2); 260 return DrawPath(pPen, fPenWidth, &path, pMatrix); 261} 262 263bool CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen, 264 FX_FLOAT fPenWidth, 265 const CFDE_Path* pPath, 266 const CFX_Matrix* pMatrix) { 267 CFDE_Path* pGePath = (CFDE_Path*)pPath; 268 if (!pGePath) 269 return false; 270 271 CFX_GraphStateData graphState; 272 if (!CreatePen(pPen, fPenWidth, graphState)) { 273 return false; 274 } 275 return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix, 276 &graphState, 0, pPen->GetColor(), 0); 277} 278 279bool CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen, 280 FX_FLOAT fPenWidth, 281 const std::vector<CFX_PointF>& points, 282 const CFX_Matrix* pMatrix) { 283 CFDE_Path path; 284 path.AddPolygon(points); 285 return DrawPath(pPen, fPenWidth, &path, pMatrix); 286} 287 288bool CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen, 289 FX_FLOAT fPenWidth, 290 const CFX_RectF& rect, 291 const CFX_Matrix* pMatrix) { 292 CFDE_Path path; 293 path.AddRectangle(rect); 294 return DrawPath(pPen, fPenWidth, &path, pMatrix); 295} 296 297bool CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush, 298 const std::vector<CFX_PointF>& points, 299 FX_FLOAT fTension, 300 const CFX_Matrix* pMatrix) { 301 CFDE_Path path; 302 path.AddCurve(points, true, fTension); 303 return FillPath(pBrush, &path, pMatrix); 304} 305 306bool CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush, 307 const CFX_RectF& rect, 308 const CFX_Matrix* pMatrix) { 309 CFDE_Path path; 310 path.AddEllipse(rect); 311 return FillPath(pBrush, &path, pMatrix); 312} 313 314bool CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush, 315 const std::vector<CFX_PointF>& points, 316 const CFX_Matrix* pMatrix) { 317 CFDE_Path path; 318 path.AddPolygon(points); 319 return FillPath(pBrush, &path, pMatrix); 320} 321 322bool CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush, 323 const CFX_RectF& rect, 324 const CFX_Matrix* pMatrix) { 325 CFDE_Path path; 326 path.AddRectangle(rect); 327 return FillPath(pBrush, &path, pMatrix); 328} 329 330bool CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen, 331 FX_FLOAT fPenWidth, 332 CFX_GraphStateData& graphState) { 333 if (!pPen) 334 return false; 335 336 graphState.m_LineCap = CFX_GraphStateData::LineCapButt; 337 graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter; 338 graphState.m_LineWidth = fPenWidth; 339 graphState.m_MiterLimit = 10; 340 graphState.m_DashPhase = 0; 341 return true; 342} 343 344bool CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush, 345 const CFDE_Path* pPath, 346 const CFX_Matrix* pMatrix) { 347 CFDE_Path* pGePath = (CFDE_Path*)pPath; 348 if (!pGePath) 349 return false; 350 if (!pBrush) 351 return false; 352 return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr, 353 pBrush->GetColor(), 0, FXFILL_WINDING); 354} 355 356