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