// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "xfa/fde/fde_render.h"

#include "xfa/fde/fde_renderdevice.h"
#include "xfa/fgas/crt/fgas_memory.h"

#define FDE_PATHRENDER_Stroke 1
#define FDE_PATHRENDER_Fill 2

namespace {

class CFDE_RenderContext : public IFDE_RenderContext, public CFX_Target {
 public:
  CFDE_RenderContext();
  virtual ~CFDE_RenderContext();
  virtual void Release() { delete this; }
  virtual FX_BOOL StartRender(IFDE_RenderDevice* pRenderDevice,
                              IFDE_CanvasSet* pCanvasSet,
                              const CFX_Matrix& tmDoc2Device);
  virtual FDE_RENDERSTATUS GetStatus() const { return m_eStatus; }
  virtual FDE_RENDERSTATUS DoRender(IFX_Pause* pPause = NULL);
  virtual void StopRender();
  void RenderPath(IFDE_PathSet* pPathSet, FDE_HVISUALOBJ hPath);
  void RenderText(IFDE_TextSet* pTextSet, FDE_HVISUALOBJ hText);
  FX_BOOL ApplyClip(IFDE_VisualSet* pVisualSet,
                    FDE_HVISUALOBJ hObj,
                    FDE_HDEVICESTATE& hState);
  void RestoreClip(FDE_HDEVICESTATE hState);

 protected:
  FDE_RENDERSTATUS m_eStatus;
  IFDE_RenderDevice* m_pRenderDevice;
  IFDE_SolidBrush* m_pSolidBrush;
  CFX_Matrix m_Transform;
  FXTEXT_CHARPOS* m_pCharPos;
  int32_t m_iCharPosCount;
  IFDE_VisualSetIterator* m_pIterator;
};

}  // namespace

void FDE_GetPageMatrix(CFX_Matrix& pageMatrix,
                       const CFX_RectF& docPageRect,
                       const CFX_Rect& devicePageRect,
                       int32_t iRotate,
                       FX_DWORD dwCoordinatesType) {
  FXSYS_assert(iRotate >= 0 && iRotate <= 3);
  FX_BOOL bFlipX = (dwCoordinatesType & 0x01) != 0;
  FX_BOOL bFlipY = (dwCoordinatesType & 0x02) != 0;
  CFX_Matrix m;
  m.Set((bFlipX ? -1.0f : 1.0f), 0, 0, (bFlipY ? -1.0f : 1.0f), 0, 0);
  if (iRotate == 0 || iRotate == 2) {
    m.a *= (FX_FLOAT)devicePageRect.width / docPageRect.width;
    m.d *= (FX_FLOAT)devicePageRect.height / docPageRect.height;
  } else {
    m.a *= (FX_FLOAT)devicePageRect.height / docPageRect.width;
    m.d *= (FX_FLOAT)devicePageRect.width / docPageRect.height;
  }
  m.Rotate(iRotate * 1.57079632675f);
  switch (iRotate) {
    case 0:
      m.e = bFlipX ? (FX_FLOAT)devicePageRect.right()
                   : (FX_FLOAT)devicePageRect.left;
      m.f = bFlipY ? (FX_FLOAT)devicePageRect.bottom()
                   : (FX_FLOAT)devicePageRect.top;
      break;
    case 1:
      m.e = bFlipY ? (FX_FLOAT)devicePageRect.left
                   : (FX_FLOAT)devicePageRect.right();
      m.f = bFlipX ? (FX_FLOAT)devicePageRect.bottom()
                   : (FX_FLOAT)devicePageRect.top;
      break;
    case 2:
      m.e = bFlipX ? (FX_FLOAT)devicePageRect.left
                   : (FX_FLOAT)devicePageRect.right();
      m.f = bFlipY ? (FX_FLOAT)devicePageRect.top
                   : (FX_FLOAT)devicePageRect.bottom();
      break;
    case 3:
      m.e = bFlipY ? (FX_FLOAT)devicePageRect.right()
                   : (FX_FLOAT)devicePageRect.left;
      m.f = bFlipX ? (FX_FLOAT)devicePageRect.top
                   : (FX_FLOAT)devicePageRect.bottom();
      break;
    default:
      break;
  }
  pageMatrix = m;
}
IFDE_RenderContext* IFDE_RenderContext::Create() {
  return new CFDE_RenderContext;
}
CFDE_RenderContext::CFDE_RenderContext()
    : m_eStatus(FDE_RENDERSTATUS_Reset),
      m_pRenderDevice(NULL),
      m_pSolidBrush(NULL),
      m_Transform(),
      m_pCharPos(NULL),
      m_iCharPosCount(0),
      m_pIterator(NULL) {
  m_Transform.SetIdentity();
}
CFDE_RenderContext::~CFDE_RenderContext() {
  StopRender();
}
FX_BOOL CFDE_RenderContext::StartRender(IFDE_RenderDevice* pRenderDevice,
                                        IFDE_CanvasSet* pCanvasSet,
                                        const CFX_Matrix& tmDoc2Device) {
  if (m_pRenderDevice != NULL) {
    return FALSE;
  }
  if (pRenderDevice == NULL) {
    return FALSE;
  }
  if (pCanvasSet == NULL) {
    return FALSE;
  }

  m_eStatus = FDE_RENDERSTATUS_Paused;
  m_pRenderDevice = pRenderDevice;
  m_Transform = tmDoc2Device;
  if (m_pIterator == NULL) {
    m_pIterator = IFDE_VisualSetIterator::Create();
    FXSYS_assert(m_pIterator != NULL);
  }
  return m_pIterator->AttachCanvas(pCanvasSet) && m_pIterator->FilterObjects();
}
FDE_RENDERSTATUS CFDE_RenderContext::DoRender(IFX_Pause* pPause) {
  if (m_pRenderDevice == NULL) {
    return FDE_RENDERSTATUS_Failed;
  }
  if (m_pIterator == NULL) {
    return FDE_RENDERSTATUS_Failed;
  }
  FDE_RENDERSTATUS eStatus = FDE_RENDERSTATUS_Paused;
  CFX_Matrix rm;
  rm.SetReverse(m_Transform);
  CFX_RectF rtDocClip = m_pRenderDevice->GetClipRect();
  if (rtDocClip.IsEmpty()) {
    rtDocClip.left = rtDocClip.top = 0;
    rtDocClip.width = (FX_FLOAT)m_pRenderDevice->GetWidth();
    rtDocClip.height = (FX_FLOAT)m_pRenderDevice->GetHeight();
  }
  rm.TransformRect(rtDocClip);
  IFDE_VisualSet* pVisualSet;
  FDE_HVISUALOBJ hVisualObj;
  CFX_RectF rtObj;
  int32_t iCount = 0;
  while (TRUE) {
    hVisualObj = m_pIterator->GetNext(pVisualSet);
    if (hVisualObj == NULL || pVisualSet == NULL) {
      eStatus = FDE_RENDERSTATUS_Done;
      break;
    }
    rtObj.Empty();
    pVisualSet->GetRect(hVisualObj, rtObj);
    if (!rtDocClip.IntersectWith(rtObj)) {
      continue;
    }
    switch (pVisualSet->GetType()) {
      case FDE_VISUALOBJ_Text:
        RenderText((IFDE_TextSet*)pVisualSet, hVisualObj);
        iCount += 5;
        break;
      case FDE_VISUALOBJ_Path:
        RenderPath((IFDE_PathSet*)pVisualSet, hVisualObj);
        iCount += 20;
        break;
      case FDE_VISUALOBJ_Widget:
        iCount += 10;
        break;
      case FDE_VISUALOBJ_Canvas:
        FXSYS_assert(FALSE);
        break;
      default:
        break;
    }
    if (iCount >= 100 && pPause != NULL && pPause->NeedToPauseNow()) {
      eStatus = FDE_RENDERSTATUS_Paused;
      break;
    }
  }
  return m_eStatus = eStatus;
}
void CFDE_RenderContext::StopRender() {
  m_eStatus = FDE_RENDERSTATUS_Reset;
  m_pRenderDevice = nullptr;
  m_Transform.SetIdentity();
  if (m_pIterator) {
    m_pIterator->Release();
    m_pIterator = nullptr;
  }
  if (m_pSolidBrush) {
    m_pSolidBrush->Release();
    m_pSolidBrush = nullptr;
  }
  FX_Free(m_pCharPos);
  m_pCharPos = nullptr;
  m_iCharPosCount = 0;
}
void CFDE_RenderContext::RenderText(IFDE_TextSet* pTextSet,
                                    FDE_HVISUALOBJ hText) {
  FXSYS_assert(m_pRenderDevice != NULL);
  FXSYS_assert(pTextSet != NULL && hText != NULL);
  IFX_Font* pFont = pTextSet->GetFont(hText);
  if (pFont == NULL) {
    return;
  }
  int32_t iCount = pTextSet->GetDisplayPos(hText, NULL, FALSE);
  if (iCount < 1) {
    return;
  }
  if (m_pSolidBrush == NULL) {
    m_pSolidBrush = (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid);
    if (m_pSolidBrush == NULL) {
      return;
    }
  }
  if (m_pCharPos == NULL) {
    m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, iCount);
  } else if (m_iCharPosCount < iCount) {
    m_pCharPos = FX_Realloc(FXTEXT_CHARPOS, m_pCharPos, iCount);
  }
  if (m_iCharPosCount < iCount) {
    m_iCharPosCount = iCount;
  }
  iCount = pTextSet->GetDisplayPos(hText, m_pCharPos, FALSE);
  FX_FLOAT fFontSize = pTextSet->GetFontSize(hText);
  FX_ARGB dwColor = pTextSet->GetFontColor(hText);
  m_pSolidBrush->SetColor(dwColor);
  FDE_HDEVICESTATE hState;
  FX_BOOL bClip = ApplyClip(pTextSet, hText, hState);
  m_pRenderDevice->DrawString(m_pSolidBrush, pFont, m_pCharPos, iCount,
                              fFontSize, &m_Transform);
  if (bClip) {
    RestoreClip(hState);
  }
}
void CFDE_RenderContext::RenderPath(IFDE_PathSet* pPathSet,
                                    FDE_HVISUALOBJ hPath) {
  FXSYS_assert(m_pRenderDevice != NULL);
  FXSYS_assert(pPathSet != NULL && hPath != NULL);
  IFDE_Path* pPath = pPathSet->GetPath(hPath);
  if (pPath == NULL) {
    return;
  }
  FDE_HDEVICESTATE hState;
  FX_BOOL bClip = ApplyClip(pPathSet, hPath, hState);
  int32_t iRenderMode = pPathSet->GetRenderMode(hPath);
  if (iRenderMode & FDE_PATHRENDER_Stroke) {
    IFDE_Pen* pPen = pPathSet->GetPen(hPath);
    FX_FLOAT fWidth = pPathSet->GetPenWidth(hPath);
    if (pPen != NULL && fWidth > 0) {
      m_pRenderDevice->DrawPath(pPen, fWidth, pPath, &m_Transform);
    }
  }
  if (iRenderMode & FDE_PATHRENDER_Fill) {
    IFDE_Brush* pBrush = pPathSet->GetBrush(hPath);
    if (pBrush != NULL) {
      m_pRenderDevice->FillPath(pBrush, pPath, &m_Transform);
    }
  }
  if (bClip) {
    RestoreClip(hState);
  }
}
FX_BOOL CFDE_RenderContext::ApplyClip(IFDE_VisualSet* pVisualSet,
                                      FDE_HVISUALOBJ hObj,
                                      FDE_HDEVICESTATE& hState) {
  CFX_RectF rtClip;
  if (!pVisualSet->GetClip(hObj, rtClip)) {
    return FALSE;
  }
  CFX_RectF rtObj;
  pVisualSet->GetRect(hObj, rtObj);
  rtClip.Offset(rtObj.left, rtObj.top);
  m_Transform.TransformRect(rtClip);
  const CFX_RectF& rtDevClip = m_pRenderDevice->GetClipRect();
  rtClip.Intersect(rtDevClip);
  hState = m_pRenderDevice->SaveState();
  return m_pRenderDevice->SetClipRect(rtClip);
}
void CFDE_RenderContext::RestoreClip(FDE_HDEVICESTATE hState) {
  m_pRenderDevice->RestoreState(hState);
}
