Home | History | Annotate | Download | only in fde
      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