// 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/cfde_renderdevice.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/cfx_substfont.h"
#include "core/fxge/dib/cfx_imagerenderer.h"
#include "third_party/base/ptr_util.h"
#include "xfa/fde/cfde_brush.h"
#include "xfa/fde/cfde_path.h"
#include "xfa/fde/cfde_pen.h"
#include "xfa/fgas/font/cfgas_fontmgr.h"
#include "xfa/fgas/font/cfgas_gefont.h"

CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice)
    : m_pDevice(pDevice), m_iCharCount(0) {
  ASSERT(pDevice);

  FX_RECT rt = m_pDevice->GetClipBox();
  m_rtClip = CFX_RectF(static_cast<float>(rt.left), static_cast<float>(rt.top),
                       static_cast<float>(rt.Width()),
                       static_cast<float>(rt.Height()));
}

CFDE_RenderDevice::~CFDE_RenderDevice() {}

int32_t CFDE_RenderDevice::GetWidth() const {
  return m_pDevice->GetWidth();
}

int32_t CFDE_RenderDevice::GetHeight() const {
  return m_pDevice->GetHeight();
}

void CFDE_RenderDevice::SaveState() {
  m_pDevice->SaveState();
}

void CFDE_RenderDevice::RestoreState() {
  m_pDevice->RestoreState(false);
  const FX_RECT& rt = m_pDevice->GetClipBox();
  m_rtClip = CFX_RectF(static_cast<float>(rt.left), static_cast<float>(rt.top),
                       static_cast<float>(rt.Width()),
                       static_cast<float>(rt.Height()));
}

bool CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) {
  m_rtClip = rtClip;
  return m_pDevice->SetClip_Rect(
      FX_RECT((int32_t)floor(rtClip.left), (int32_t)floor(rtClip.top),
              (int32_t)ceil(rtClip.right()), (int32_t)ceil(rtClip.bottom())));
}

const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
  return m_rtClip;
}

bool CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
  return false;
}

CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
  return nullptr;
}

float CFDE_RenderDevice::GetDpiX() const {
  return 96;
}

float CFDE_RenderDevice::GetDpiY() const {
  return 96;
}

bool CFDE_RenderDevice::DrawImage(const CFX_RetainPtr<CFX_DIBSource>& pDib,
                                  const CFX_RectF* pSrcRect,
                                  const CFX_RectF& dstRect,
                                  const CFX_Matrix* pImgMatrix,
                                  const CFX_Matrix* pDevMatrix) {
  CFX_RectF srcRect;
  if (pSrcRect) {
    srcRect = *pSrcRect;
  } else {
    srcRect = CFX_RectF(0, 0, static_cast<float>(pDib->GetWidth()),
                        static_cast<float>(pDib->GetHeight()));
  }

  if (srcRect.IsEmpty())
    return false;

  CFX_Matrix dib2fxdev;
  if (pImgMatrix) {
    dib2fxdev = *pImgMatrix;
  } else {
    dib2fxdev.SetIdentity();
  }
  dib2fxdev.a = dstRect.width;
  dib2fxdev.d = -dstRect.height;
  dib2fxdev.e = dstRect.left;
  dib2fxdev.f = dstRect.bottom();
  if (pDevMatrix) {
    dib2fxdev.Concat(*pDevMatrix);
  }
  std::unique_ptr<CFX_ImageRenderer> handle;
  m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
                         &handle);
  while (m_pDevice->ContinueDIBits(handle.get(), nullptr)) {
  }
  return !!handle;
}

bool CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
                                   const CFX_RetainPtr<CFGAS_GEFont>& pFont,
                                   const FXTEXT_CHARPOS* pCharPos,
                                   int32_t iCount,
                                   float fFontSize,
                                   const CFX_Matrix* pMatrix) {
  ASSERT(pBrush && pFont && pCharPos && iCount > 0);
  CFX_Font* pFxFont = pFont->GetDevFont();
  FX_ARGB argb = pBrush->GetColor();
  if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
      !pFxFont->IsItalic()) {
    FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
    float* pAM;
    for (int32_t i = 0; i < iCount; ++i) {
      static const float mc = 0.267949f;
      pAM = pCP->m_AdjustMatrix;
      pAM[2] = mc * pAM[0] + pAM[2];
      pAM[3] = mc * pAM[1] + pAM[3];
      pCP++;
    }
  }
  FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
  CFX_RetainPtr<CFGAS_GEFont> pCurFont;
  CFX_RetainPtr<CFGAS_GEFont> pSTFont;
  FXTEXT_CHARPOS* pCurCP = nullptr;
  int32_t iCurCount = 0;

#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
  uint32_t dwFontStyle = pFont->GetFontStyles();
  CFX_Font FxFont;
  auto SubstFxFont = pdfium::MakeUnique<CFX_SubstFont>();
  SubstFxFont->m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
  SubstFxFont->m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
  SubstFxFont->m_WeightCJK = SubstFxFont->m_Weight;
  SubstFxFont->m_bItalicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
  FxFont.SetSubstFont(std::move(SubstFxFont));
#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_

  for (int32_t i = 0; i < iCount; ++i) {
    pSTFont = pFont->GetSubstFont((int32_t)pCP->m_GlyphIndex);
    pCP->m_GlyphIndex &= 0x00FFFFFF;
    pCP->m_bFontStyle = false;
    if (pCurFont != pSTFont) {
      if (pCurFont) {
        pFxFont = pCurFont->GetDevFont();
#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
        FxFont.SetFace(pFxFont->GetFace());
        m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize,
                                  pMatrix, argb, FXTEXT_CLEARTYPE);
#else
        m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
                                  pMatrix, argb, FXTEXT_CLEARTYPE);
#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
      }
      pCurFont = pSTFont;
      pCurCP = pCP;
      iCurCount = 1;
    } else {
      iCurCount++;
    }
    pCP++;
  }
  if (pCurFont && iCurCount) {
    pFxFont = pCurFont->GetDevFont();
#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
    FxFont.SetFace(pFxFont->GetFace());
    bool bRet =
        m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, -fFontSize,
                                  pMatrix, argb, FXTEXT_CLEARTYPE);
    FxFont.SetFace(nullptr);
    return bRet;
#else
    return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, -fFontSize,
                                     pMatrix, argb, FXTEXT_CLEARTYPE);
#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
  }

#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
  FxFont.SetFace(nullptr);
#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_

  return true;
}

bool CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
                                   float fPenWidth,
                                   const CFX_PointF& pt1,
                                   const CFX_PointF& pt2,
                                   const CFX_PointF& pt3,
                                   const CFX_PointF& pt4,
                                   const CFX_Matrix* pMatrix) {
  std::vector<CFX_PointF> points;
  points.push_back(pt1);
  points.push_back(pt2);
  points.push_back(pt3);
  points.push_back(pt4);
  CFDE_Path path;
  path.AddBezier(points);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
                                  float fPenWidth,
                                  const std::vector<CFX_PointF>& points,
                                  bool bClosed,
                                  float fTension,
                                  const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddCurve(points, bClosed, fTension);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
                                    float fPenWidth,
                                    const CFX_RectF& rect,
                                    const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddEllipse(rect);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
                                  float fPenWidth,
                                  const std::vector<CFX_PointF>& points,
                                  const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddLines(points);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
                                 float fPenWidth,
                                 const CFX_PointF& pt1,
                                 const CFX_PointF& pt2,
                                 const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddLine(pt1, pt2);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
                                 float fPenWidth,
                                 const CFDE_Path* pPath,
                                 const CFX_Matrix* pMatrix) {
  CFDE_Path* pGePath = (CFDE_Path*)pPath;
  if (!pGePath)
    return false;

  CFX_GraphStateData graphState;
  if (!CreatePen(pPen, fPenWidth, graphState)) {
    return false;
  }
  return m_pDevice->DrawPath(&pGePath->m_Path, (const CFX_Matrix*)pMatrix,
                             &graphState, 0, pPen->GetColor(), 0);
}

bool CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
                                    float fPenWidth,
                                    const std::vector<CFX_PointF>& points,
                                    const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddPolygon(points);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
                                      float fPenWidth,
                                      const CFX_RectF& rect,
                                      const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddRectangle(rect);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}

bool CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
                                        const std::vector<CFX_PointF>& points,
                                        float fTension,
                                        const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddCurve(points, true, fTension);
  return FillPath(pBrush, &path, pMatrix);
}

bool CFDE_RenderDevice::FillEllipse(CFDE_Brush* pBrush,
                                    const CFX_RectF& rect,
                                    const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddEllipse(rect);
  return FillPath(pBrush, &path, pMatrix);
}

bool CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
                                    const std::vector<CFX_PointF>& points,
                                    const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddPolygon(points);
  return FillPath(pBrush, &path, pMatrix);
}

bool CFDE_RenderDevice::FillRectangle(CFDE_Brush* pBrush,
                                      const CFX_RectF& rect,
                                      const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddRectangle(rect);
  return FillPath(pBrush, &path, pMatrix);
}

bool CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
                                  float fPenWidth,
                                  CFX_GraphStateData& graphState) {
  if (!pPen)
    return false;

  graphState.m_LineCap = CFX_GraphStateData::LineCapButt;
  graphState.m_LineJoin = CFX_GraphStateData::LineJoinMiter;
  graphState.m_LineWidth = fPenWidth;
  graphState.m_MiterLimit = 10;
  graphState.m_DashPhase = 0;
  return true;
}

bool CFDE_RenderDevice::FillPath(CFDE_Brush* pBrush,
                                 const CFDE_Path* pPath,
                                 const CFX_Matrix* pMatrix) {
  CFDE_Path* pGePath = (CFDE_Path*)pPath;
  if (!pGePath)
    return false;
  if (!pBrush)
    return false;
  return m_pDevice->DrawPath(&pGePath->m_Path, pMatrix, nullptr,
                             pBrush->GetColor(), 0, FXFILL_WINDING);
}
