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/src/foxitlib.h" 8 #include "fde_render.h" 9 void FDE_GetPageMatrix(CFX_Matrix& pageMatrix, 10 const CFX_RectF& docPageRect, 11 const CFX_Rect& devicePageRect, 12 int32_t iRotate, 13 FX_DWORD dwCoordinatesType) { 14 FXSYS_assert(iRotate >= 0 && iRotate <= 3); 15 FX_BOOL bFlipX = (dwCoordinatesType & 0x01) != 0; 16 FX_BOOL bFlipY = (dwCoordinatesType & 0x02) != 0; 17 CFX_Matrix m; 18 m.Set((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0); 19 if (iRotate == 0 || iRotate == 2) { 20 m.a *= (FX_FLOAT)devicePageRect.width / docPageRect.width; 21 m.d *= (FX_FLOAT)devicePageRect.height / docPageRect.height; 22 } else { 23 m.a *= (FX_FLOAT)devicePageRect.height / docPageRect.width; 24 m.d *= (FX_FLOAT)devicePageRect.width / docPageRect.height; 25 } 26 m.Rotate(iRotate * 1.57079632675f); 27 switch (iRotate) { 28 case 0: 29 m.e = bFlipX ? (FX_FLOAT)devicePageRect.right() 30 : (FX_FLOAT)devicePageRect.left; 31 m.f = bFlipY ? (FX_FLOAT)devicePageRect.bottom() 32 : (FX_FLOAT)devicePageRect.top; 33 break; 34 case 1: 35 m.e = bFlipY ? (FX_FLOAT)devicePageRect.left 36 : (FX_FLOAT)devicePageRect.right(); 37 m.f = bFlipX ? (FX_FLOAT)devicePageRect.bottom() 38 : (FX_FLOAT)devicePageRect.top; 39 break; 40 case 2: 41 m.e = bFlipX ? (FX_FLOAT)devicePageRect.left 42 : (FX_FLOAT)devicePageRect.right(); 43 m.f = bFlipY ? (FX_FLOAT)devicePageRect.top 44 : (FX_FLOAT)devicePageRect.bottom(); 45 break; 46 case 3: 47 m.e = bFlipY ? (FX_FLOAT)devicePageRect.right() 48 : (FX_FLOAT)devicePageRect.left; 49 m.f = bFlipX ? (FX_FLOAT)devicePageRect.top 50 : (FX_FLOAT)devicePageRect.bottom(); 51 break; 52 default: 53 break; 54 } 55 pageMatrix = m; 56 } 57 IFDE_RenderContext* IFDE_RenderContext::Create() { 58 return new CFDE_RenderContext; 59 } 60 CFDE_RenderContext::CFDE_RenderContext() 61 : CFX_ThreadLock(), 62 m_eStatus(FDE_RENDERSTATUS_Reset), 63 m_pRenderDevice(NULL), 64 m_pSolidBrush(NULL), 65 m_Transform(), 66 m_pCharPos(NULL), 67 m_iCharPosCount(0), 68 m_pIterator(NULL) { 69 m_Transform.SetIdentity(); 70 } 71 CFDE_RenderContext::~CFDE_RenderContext() { 72 StopRender(); 73 } 74 FX_BOOL CFDE_RenderContext::StartRender(IFDE_RenderDevice* pRenderDevice, 75 IFDE_CanvasSet* pCanvasSet, 76 const CFX_Matrix& tmDoc2Device) { 77 if (m_pRenderDevice != NULL) { 78 return FALSE; 79 } 80 if (pRenderDevice == NULL) { 81 return FALSE; 82 } 83 if (pCanvasSet == NULL) { 84 return FALSE; 85 } 86 Lock(); 87 m_eStatus = FDE_RENDERSTATUS_Paused; 88 m_pRenderDevice = pRenderDevice; 89 m_Transform = tmDoc2Device; 90 if (m_pIterator == NULL) { 91 m_pIterator = IFDE_VisualSetIterator::Create(); 92 FXSYS_assert(m_pIterator != NULL); 93 } 94 FX_BOOL bAttach = 95 m_pIterator->AttachCanvas(pCanvasSet) && m_pIterator->FilterObjects(); 96 Unlock(); 97 return bAttach; 98 } 99 FDE_RENDERSTATUS CFDE_RenderContext::DoRender(IFX_Pause* pPause) { 100 if (m_pRenderDevice == NULL) { 101 return FDE_RENDERSTATUS_Failed; 102 } 103 if (m_pIterator == NULL) { 104 return FDE_RENDERSTATUS_Failed; 105 } 106 Lock(); 107 FDE_RENDERSTATUS eStatus = FDE_RENDERSTATUS_Paused; 108 CFX_Matrix rm; 109 rm.SetReverse(m_Transform); 110 CFX_RectF rtDocClip = m_pRenderDevice->GetClipRect(); 111 if (rtDocClip.IsEmpty()) { 112 rtDocClip.left = rtDocClip.top = 0; 113 rtDocClip.width = (FX_FLOAT)m_pRenderDevice->GetWidth(); 114 rtDocClip.height = (FX_FLOAT)m_pRenderDevice->GetHeight(); 115 } 116 rm.TransformRect(rtDocClip); 117 IFDE_VisualSet* pVisualSet; 118 FDE_HVISUALOBJ hVisualObj; 119 CFX_RectF rtObj; 120 int32_t iCount = 0; 121 while (TRUE) { 122 hVisualObj = m_pIterator->GetNext(pVisualSet); 123 if (hVisualObj == NULL || pVisualSet == NULL) { 124 eStatus = FDE_RENDERSTATUS_Done; 125 break; 126 } 127 rtObj.Empty(); 128 pVisualSet->GetRect(hVisualObj, rtObj); 129 if (!rtDocClip.IntersectWith(rtObj)) { 130 continue; 131 } 132 switch (pVisualSet->GetType()) { 133 case FDE_VISUALOBJ_Text: 134 RenderText((IFDE_TextSet*)pVisualSet, hVisualObj); 135 iCount += 5; 136 break; 137 case FDE_VISUALOBJ_Path: 138 RenderPath((IFDE_PathSet*)pVisualSet, hVisualObj); 139 iCount += 20; 140 break; 141 case FDE_VISUALOBJ_Widget: 142 iCount += 10; 143 break; 144 case FDE_VISUALOBJ_Canvas: 145 FXSYS_assert(FALSE); 146 break; 147 default: 148 break; 149 } 150 if (iCount >= 100 && pPause != NULL && pPause->NeedToPauseNow()) { 151 eStatus = FDE_RENDERSTATUS_Paused; 152 break; 153 } 154 } 155 Unlock(); 156 return m_eStatus = eStatus; 157 } 158 void CFDE_RenderContext::StopRender() { 159 Lock(); 160 m_eStatus = FDE_RENDERSTATUS_Reset; 161 m_pRenderDevice = nullptr; 162 m_Transform.SetIdentity(); 163 if (m_pIterator) { 164 m_pIterator->Release(); 165 m_pIterator = nullptr; 166 } 167 if (m_pSolidBrush) { 168 m_pSolidBrush->Release(); 169 m_pSolidBrush = nullptr; 170 } 171 FX_Free(m_pCharPos); 172 m_pCharPos = nullptr; 173 m_iCharPosCount = 0; 174 Unlock(); 175 } 176 void CFDE_RenderContext::RenderText(IFDE_TextSet* pTextSet, 177 FDE_HVISUALOBJ hText) { 178 FXSYS_assert(m_pRenderDevice != NULL); 179 FXSYS_assert(pTextSet != NULL && hText != NULL); 180 IFX_Font* pFont = pTextSet->GetFont(hText); 181 if (pFont == NULL) { 182 return; 183 } 184 int32_t iCount = pTextSet->GetDisplayPos(hText, NULL, FALSE); 185 if (iCount < 1) { 186 return; 187 } 188 if (m_pSolidBrush == NULL) { 189 m_pSolidBrush = (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid); 190 if (m_pSolidBrush == NULL) { 191 return; 192 } 193 } 194 if (m_pCharPos == NULL) { 195 m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, iCount); 196 } else if (m_iCharPosCount < iCount) { 197 m_pCharPos = FX_Realloc(FXTEXT_CHARPOS, m_pCharPos, iCount); 198 } 199 if (m_iCharPosCount < iCount) { 200 m_iCharPosCount = iCount; 201 } 202 iCount = pTextSet->GetDisplayPos(hText, m_pCharPos, FALSE); 203 FX_FLOAT fFontSize = pTextSet->GetFontSize(hText); 204 FX_ARGB dwColor = pTextSet->GetFontColor(hText); 205 m_pSolidBrush->SetColor(dwColor); 206 FDE_HDEVICESTATE hState; 207 FX_BOOL bClip = ApplyClip(pTextSet, hText, hState); 208 m_pRenderDevice->DrawString(m_pSolidBrush, pFont, m_pCharPos, iCount, 209 fFontSize, &m_Transform); 210 if (bClip) { 211 RestoreClip(hState); 212 } 213 } 214 void CFDE_RenderContext::RenderPath(IFDE_PathSet* pPathSet, 215 FDE_HVISUALOBJ hPath) { 216 FXSYS_assert(m_pRenderDevice != NULL); 217 FXSYS_assert(pPathSet != NULL && hPath != NULL); 218 IFDE_Path* pPath = pPathSet->GetPath(hPath); 219 if (pPath == NULL) { 220 return; 221 } 222 FDE_HDEVICESTATE hState; 223 FX_BOOL bClip = ApplyClip(pPathSet, hPath, hState); 224 int32_t iRenderMode = pPathSet->GetRenderMode(hPath); 225 if (iRenderMode & FDE_PATHRENDER_Stroke) { 226 IFDE_Pen* pPen = pPathSet->GetPen(hPath); 227 FX_FLOAT fWidth = pPathSet->GetPenWidth(hPath); 228 if (pPen != NULL && fWidth > 0) { 229 m_pRenderDevice->DrawPath(pPen, fWidth, pPath, &m_Transform); 230 } 231 } 232 if (iRenderMode & FDE_PATHRENDER_Fill) { 233 IFDE_Brush* pBrush = pPathSet->GetBrush(hPath); 234 if (pBrush != NULL) { 235 m_pRenderDevice->FillPath(pBrush, pPath, &m_Transform); 236 } 237 } 238 if (bClip) { 239 RestoreClip(hState); 240 } 241 } 242 FX_BOOL CFDE_RenderContext::ApplyClip(IFDE_VisualSet* pVisualSet, 243 FDE_HVISUALOBJ hObj, 244 FDE_HDEVICESTATE& hState) { 245 CFX_RectF rtClip; 246 if (!pVisualSet->GetClip(hObj, rtClip)) { 247 return FALSE; 248 } 249 CFX_RectF rtObj; 250 pVisualSet->GetRect(hObj, rtObj); 251 rtClip.Offset(rtObj.left, rtObj.top); 252 m_Transform.TransformRect(rtClip); 253 const CFX_RectF& rtDevClip = m_pRenderDevice->GetClipRect(); 254 rtClip.Intersect(rtDevClip); 255 hState = m_pRenderDevice->SaveState(); 256 return m_pRenderDevice->SetClipRect(rtClip); 257 } 258 void CFDE_RenderContext::RestoreClip(FDE_HDEVICESTATE hState) { 259 m_pRenderDevice->RestoreState(hState); 260 } 261