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

#include <algorithm>

#include "xfa/fde/cfde_path.h"
#include "xfa/fde/fde_object.h"
#include "xfa/fgas/font/fgas_font.h"

CFDE_RenderDevice::CFDE_RenderDevice(CFX_RenderDevice* pDevice,
                                     FX_BOOL bOwnerDevice)
    : m_pDevice(pDevice),
      m_bOwnerDevice(bOwnerDevice),
      m_pCharPos(nullptr),
      m_iCharCount(0) {
  ASSERT(pDevice);

  FX_RECT rt = m_pDevice->GetClipBox();
  m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
               (FX_FLOAT)rt.Height());
}

CFDE_RenderDevice::~CFDE_RenderDevice() {
  FX_Free(m_pCharPos);
  if (m_bOwnerDevice)
    delete m_pDevice;
}
int32_t CFDE_RenderDevice::GetWidth() const {
  return m_pDevice->GetWidth();
}
int32_t CFDE_RenderDevice::GetHeight() const {
  return m_pDevice->GetHeight();
}
FDE_HDEVICESTATE CFDE_RenderDevice::SaveState() {
  m_pDevice->SaveState();
  return NULL;
}
void CFDE_RenderDevice::RestoreState(FDE_HDEVICESTATE hState) {
  m_pDevice->RestoreState(false);
  const FX_RECT& rt = m_pDevice->GetClipBox();
  m_rtClip.Set((FX_FLOAT)rt.left, (FX_FLOAT)rt.top, (FX_FLOAT)rt.Width(),
               (FX_FLOAT)rt.Height());
}
FX_BOOL CFDE_RenderDevice::SetClipRect(const CFX_RectF& rtClip) {
  m_rtClip = rtClip;
  return m_pDevice->SetClip_Rect(FX_RECT((int32_t)FXSYS_floor(rtClip.left),
                                         (int32_t)FXSYS_floor(rtClip.top),
                                         (int32_t)FXSYS_ceil(rtClip.right()),
                                         (int32_t)FXSYS_ceil(rtClip.bottom())));
}
const CFX_RectF& CFDE_RenderDevice::GetClipRect() {
  return m_rtClip;
}
FX_BOOL CFDE_RenderDevice::SetClipPath(const CFDE_Path* pClip) {
  return FALSE;
}
CFDE_Path* CFDE_RenderDevice::GetClipPath() const {
  return NULL;
}
FX_FLOAT CFDE_RenderDevice::GetDpiX() const {
  return 96;
}
FX_FLOAT CFDE_RenderDevice::GetDpiY() const {
  return 96;
}
FX_BOOL CFDE_RenderDevice::DrawImage(CFX_DIBSource* pDib,
                                     const CFX_RectF* pSrcRect,
                                     const CFX_RectF& dstRect,
                                     const CFX_Matrix* pImgMatrix,
                                     const CFX_Matrix* pDevMatrix) {
  ASSERT(pDib != NULL);
  CFX_RectF srcRect;
  if (pSrcRect) {
    srcRect = *pSrcRect;
  } else {
    srcRect.Set(0, 0, (FX_FLOAT)pDib->GetWidth(), (FX_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);
  }
  void* handle = NULL;
  m_pDevice->StartDIBits(pDib, 255, 0, (const CFX_Matrix*)&dib2fxdev, 0,
                         handle);
  while (m_pDevice->ContinueDIBits(handle, NULL)) {
  }
  m_pDevice->CancelDIBits(handle);
  return handle != NULL;
}
FX_BOOL CFDE_RenderDevice::DrawString(CFDE_Brush* pBrush,
                                      IFX_Font* pFont,
                                      const FXTEXT_CHARPOS* pCharPos,
                                      int32_t iCount,
                                      FX_FLOAT fFontSize,
                                      const CFX_Matrix* pMatrix) {
  ASSERT(pBrush != NULL && pFont != NULL && pCharPos != NULL && iCount > 0);
  CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
  CFX_Font* pFxFont = (CFX_Font*)pFont->GetDevFont();

  FX_ARGB argb = pBrush->GetColor();
  if ((pFont->GetFontStyles() & FX_FONTSTYLE_Italic) != 0 &&
      !pFxFont->IsItalic()) {
    FXTEXT_CHARPOS* pCP = (FXTEXT_CHARPOS*)pCharPos;
    FX_FLOAT* pAM;
    for (int32_t i = 0; i < iCount; ++i) {
      static const FX_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;
  IFX_Font* pCurFont = NULL;
  IFX_Font* pSTFont = NULL;
  FXTEXT_CHARPOS* pCurCP = NULL;
  int32_t iCurCount = 0;

#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
  uint32_t dwFontStyle = pFont->GetFontStyles();
  CFX_Font FxFont;
  CFX_SubstFont SubstFxFont;
  FxFont.SetSubstFont(&SubstFxFont);
  SubstFxFont.m_Weight = dwFontStyle & FX_FONTSTYLE_Bold ? 700 : 400;
  SubstFxFont.m_WeightCJK = SubstFxFont.m_Weight;
  SubstFxFont.m_ItalicAngle = dwFontStyle & FX_FONTSTYLE_Italic ? -12 : 0;
  SubstFxFont.m_bItlicCJK = !!(dwFontStyle & FX_FONTSTYLE_Italic);
#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 != NULL) {
        pFxFont = (CFX_Font*)pCurFont->GetDevFont();

#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
        FxFont.SetFace(pFxFont->GetFace());
        m_pDevice->DrawNormalText(iCurCount, pCurCP, &FxFont, pCache,
                                  -fFontSize, (const CFX_Matrix*)pMatrix, argb,
                                  FXTEXT_CLEARTYPE);
#else
        m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
                                  -fFontSize, (const CFX_Matrix*)pMatrix, argb,
                                  FXTEXT_CLEARTYPE);
#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
      }
      pCurFont = pSTFont;
      pCurCP = pCP;
      iCurCount = 1;
    } else {
      iCurCount++;
    }
    pCP++;
  }
  if (pCurFont != NULL && iCurCount) {
    pFxFont = (CFX_Font*)pCurFont->GetDevFont();

#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
    FxFont.SetFace(pFxFont->GetFace());
    FX_BOOL bRet = m_pDevice->DrawNormalText(
        iCurCount, pCurCP, &FxFont, pCache, -fFontSize,
        (const CFX_Matrix*)pMatrix, argb, FXTEXT_CLEARTYPE);
    FxFont.SetSubstFont(nullptr);
    FxFont.SetFace(nullptr);
    return bRet;
#else
    return m_pDevice->DrawNormalText(iCurCount, pCurCP, pFxFont, pCache,
                                     -fFontSize, (const CFX_Matrix*)pMatrix,
                                     argb, FXTEXT_CLEARTYPE);
#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
  }

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

  return TRUE;
}

FX_BOOL CFDE_RenderDevice::DrawBezier(CFDE_Pen* pPen,
                                      FX_FLOAT fPenWidth,
                                      const CFX_PointF& pt1,
                                      const CFX_PointF& pt2,
                                      const CFX_PointF& pt3,
                                      const CFX_PointF& pt4,
                                      const CFX_Matrix* pMatrix) {
  CFX_PointsF points;
  points.Add(pt1);
  points.Add(pt2);
  points.Add(pt3);
  points.Add(pt4);
  CFDE_Path path;
  path.AddBezier(points);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}
FX_BOOL CFDE_RenderDevice::DrawCurve(CFDE_Pen* pPen,
                                     FX_FLOAT fPenWidth,
                                     const CFX_PointsF& points,
                                     FX_BOOL bClosed,
                                     FX_FLOAT fTension,
                                     const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddCurve(points, bClosed, fTension);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}
FX_BOOL CFDE_RenderDevice::DrawEllipse(CFDE_Pen* pPen,
                                       FX_FLOAT fPenWidth,
                                       const CFX_RectF& rect,
                                       const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddEllipse(rect);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}
FX_BOOL CFDE_RenderDevice::DrawLines(CFDE_Pen* pPen,
                                     FX_FLOAT fPenWidth,
                                     const CFX_PointsF& points,
                                     const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddLines(points);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}
FX_BOOL CFDE_RenderDevice::DrawLine(CFDE_Pen* pPen,
                                    FX_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);
}
FX_BOOL CFDE_RenderDevice::DrawPath(CFDE_Pen* pPen,
                                    FX_FLOAT fPenWidth,
                                    const CFDE_Path* pPath,
                                    const CFX_Matrix* pMatrix) {
  CFDE_Path* pGePath = (CFDE_Path*)pPath;
  if (pGePath == NULL) {
    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);
}
FX_BOOL CFDE_RenderDevice::DrawPolygon(CFDE_Pen* pPen,
                                       FX_FLOAT fPenWidth,
                                       const CFX_PointsF& points,
                                       const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddPolygon(points);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}
FX_BOOL CFDE_RenderDevice::DrawRectangle(CFDE_Pen* pPen,
                                         FX_FLOAT fPenWidth,
                                         const CFX_RectF& rect,
                                         const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddRectangle(rect);
  return DrawPath(pPen, fPenWidth, &path, pMatrix);
}
FX_BOOL CFDE_RenderDevice::FillClosedCurve(CFDE_Brush* pBrush,
                                           const CFX_PointsF& points,
                                           FX_FLOAT fTension,
                                           const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddCurve(points, TRUE, fTension);
  return FillPath(pBrush, &path, pMatrix);
}
FX_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);
}
FX_BOOL CFDE_RenderDevice::FillPolygon(CFDE_Brush* pBrush,
                                       const CFX_PointsF& points,
                                       const CFX_Matrix* pMatrix) {
  CFDE_Path path;
  path.AddPolygon(points);
  return FillPath(pBrush, &path, pMatrix);
}
FX_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);
}
FX_BOOL CFDE_RenderDevice::CreatePen(CFDE_Pen* pPen,
                                     FX_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;
}

FX_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);
}

