// Copyright 2017 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/fxfa/cxfa_ffline.h"

#include "xfa/fxfa/parser/cxfa_edge.h"
#include "xfa/fxfa/parser/cxfa_line.h"
#include "xfa/fxfa/parser/cxfa_value.h"
#include "xfa/fxgraphics/cxfa_gecolor.h"
#include "xfa/fxgraphics/cxfa_gepath.h"
#include "xfa/fxgraphics/cxfa_graphics.h"

namespace {

CFX_GraphStateData::LineCap LineCapToFXGE(XFA_AttributeEnum iLineCap) {
  switch (iLineCap) {
    case XFA_AttributeEnum::Round:
      return CFX_GraphStateData::LineCapRound;
    case XFA_AttributeEnum::Butt:
      return CFX_GraphStateData::LineCapButt;
    default:
      break;
  }
  return CFX_GraphStateData::LineCapSquare;
}

}  // namespace

CXFA_FFLine::CXFA_FFLine(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}

CXFA_FFLine::~CXFA_FFLine() {}

void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect,
                                  XFA_AttributeEnum iHand,
                                  float fLineWidth) {
  float fHalfWidth = fLineWidth / 2.0f;
  if (rect.height < 1.0f) {
    switch (iHand) {
      case XFA_AttributeEnum::Left:
        rect.top -= fHalfWidth;
        break;
      case XFA_AttributeEnum::Right:
        rect.top += fHalfWidth;
        break;
      case XFA_AttributeEnum::Even:
        break;
      default:
        NOTREACHED();
        break;
    }
  } else if (rect.width < 1.0f) {
    switch (iHand) {
      case XFA_AttributeEnum::Left:
        rect.left += fHalfWidth;
        break;
      case XFA_AttributeEnum::Right:
        rect.left += fHalfWidth;
        break;
      case XFA_AttributeEnum::Even:
        break;
      default:
        NOTREACHED();
        break;
    }
  } else {
    switch (iHand) {
      case XFA_AttributeEnum::Left:
        rect.Inflate(fHalfWidth, fHalfWidth);
        break;
      case XFA_AttributeEnum::Right:
        rect.Deflate(fHalfWidth, fHalfWidth);
        break;
      case XFA_AttributeEnum::Even:
        break;
      default:
        NOTREACHED();
        break;
    }
  }
}

void CXFA_FFLine::RenderWidget(CXFA_Graphics* pGS,
                               const CFX_Matrix& matrix,
                               uint32_t dwStatus) {
  if (!IsMatchVisibleStatus(dwStatus))
    return;

  CXFA_Value* value = m_pNode->GetFormValueIfExists();
  if (!value)
    return;

  FX_ARGB lineColor = 0xFF000000;
  float fLineWidth = 1.0f;
  XFA_AttributeEnum iStrokeType = XFA_AttributeEnum::Unknown;
  XFA_AttributeEnum iCap = XFA_AttributeEnum::Unknown;

  CXFA_Line* line = value->GetLineIfExists();
  if (line) {
    CXFA_Edge* edge = line->GetEdgeIfExists();
    if (edge && !edge->IsVisible())
      return;

    if (edge) {
      lineColor = edge->GetColor();
      iStrokeType = edge->GetStrokeType();
      fLineWidth = edge->GetThickness();
      iCap = edge->GetCapType();
    }
  }

  CFX_Matrix mtRotate = GetRotateMatrix();
  mtRotate.Concat(matrix);

  CFX_RectF rtLine = GetRectWithoutRotate();
  CXFA_Margin* margin = m_pNode->GetMarginIfExists();
  if (margin)
    XFA_RectWithoutMargin(rtLine, margin);

  GetRectFromHand(rtLine, line ? line->GetHand() : XFA_AttributeEnum::Left,
                  fLineWidth);
  CXFA_GEPath linePath;
  if (line && line->GetSlope() && rtLine.right() > 0.0f &&
      rtLine.bottom() > 0.0f) {
    linePath.AddLine(rtLine.TopRight(), rtLine.BottomLeft());
  } else {
    linePath.AddLine(rtLine.TopLeft(), rtLine.BottomRight());
  }

  pGS->SaveGraphState();
  pGS->SetLineWidth(fLineWidth);
  pGS->EnableActOnDash();
  XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap);

  pGS->SetStrokeColor(CXFA_GEColor(lineColor));
  pGS->SetLineCap(LineCapToFXGE(iCap));
  pGS->StrokePath(&linePath, &mtRotate);
  pGS->RestoreGraphState();
}