// Copyright 2016 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 "core/fpdfapi/page/cpdf_colorstate.h"

#include "core/fpdfapi/page/cpdf_colorspace.h"
#include "core/fpdfapi/page/cpdf_pattern.h"
#include "core/fpdfapi/page/cpdf_tilingpattern.h"
#include "core/fxge/dib/fx_dib.h"
#include "third_party/base/check.h"

CPDF_ColorState::CPDF_ColorState() = default;

CPDF_ColorState::CPDF_ColorState(const CPDF_ColorState& that)
    : m_Ref(that.m_Ref) {}

CPDF_ColorState::~CPDF_ColorState() = default;

void CPDF_ColorState::Emplace() {
  m_Ref.Emplace();
}

void CPDF_ColorState::SetDefault() {
  m_Ref.GetPrivateCopy()->SetDefault();
}

FX_COLORREF CPDF_ColorState::GetFillColorRef() const {
  return m_Ref.GetObject()->m_FillColorRef;
}

void CPDF_ColorState::SetFillColorRef(FX_COLORREF colorref) {
  m_Ref.GetPrivateCopy()->m_FillColorRef = colorref;
}

FX_COLORREF CPDF_ColorState::GetStrokeColorRef() const {
  return m_Ref.GetObject()->m_StrokeColorRef;
}

void CPDF_ColorState::SetStrokeColorRef(FX_COLORREF colorref) {
  m_Ref.GetPrivateCopy()->m_StrokeColorRef = colorref;
}

const CPDF_Color* CPDF_ColorState::GetFillColor() const {
  const ColorData* pData = m_Ref.GetObject();
  return pData ? &pData->m_FillColor : nullptr;
}

CPDF_Color* CPDF_ColorState::GetMutableFillColor() {
  return &m_Ref.GetPrivateCopy()->m_FillColor;
}

bool CPDF_ColorState::HasFillColor() const {
  const CPDF_Color* pColor = GetFillColor();
  return pColor && !pColor->IsNull();
}

const CPDF_Color* CPDF_ColorState::GetStrokeColor() const {
  const ColorData* pData = m_Ref.GetObject();
  return pData ? &pData->m_StrokeColor : nullptr;
}

CPDF_Color* CPDF_ColorState::GetMutableStrokeColor() {
  return &m_Ref.GetPrivateCopy()->m_StrokeColor;
}

bool CPDF_ColorState::HasStrokeColor() const {
  const CPDF_Color* pColor = GetStrokeColor();
  return pColor && !pColor->IsNull();
}

void CPDF_ColorState::SetFillColor(const RetainPtr<CPDF_ColorSpace>& pCS,
                                   const std::vector<float>& values) {
  ColorData* pData = m_Ref.GetPrivateCopy();
  SetColor(pCS, values, &pData->m_FillColor, &pData->m_FillColorRef);
}

void CPDF_ColorState::SetStrokeColor(const RetainPtr<CPDF_ColorSpace>& pCS,
                                     const std::vector<float>& values) {
  ColorData* pData = m_Ref.GetPrivateCopy();
  SetColor(pCS, values, &pData->m_StrokeColor, &pData->m_StrokeColorRef);
}

void CPDF_ColorState::SetFillPattern(const RetainPtr<CPDF_Pattern>& pPattern,
                                     const std::vector<float>& values) {
  ColorData* pData = m_Ref.GetPrivateCopy();
  SetPattern(pPattern, values, &pData->m_FillColor, &pData->m_FillColorRef);
}

void CPDF_ColorState::SetStrokePattern(const RetainPtr<CPDF_Pattern>& pPattern,
                                       const std::vector<float>& values) {
  ColorData* pData = m_Ref.GetPrivateCopy();
  SetPattern(pPattern, values, &pData->m_StrokeColor, &pData->m_StrokeColorRef);
}

void CPDF_ColorState::SetColor(const RetainPtr<CPDF_ColorSpace>& pCS,
                               const std::vector<float>& values,
                               CPDF_Color* color,
                               FX_COLORREF* colorref) {
  DCHECK(color);
  DCHECK(colorref);

  if (pCS)
    color->SetColorSpace(pCS);
  else if (color->IsNull())
    color->SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));

  if (color->CountComponents() > values.size())
    return;

  if (!color->IsPattern())
    color->SetValueForNonPattern(values);
  int R;
  int G;
  int B;
  *colorref = color->GetRGB(&R, &G, &B) ? FXSYS_BGR(B, G, R) : 0xFFFFFFFF;
}

void CPDF_ColorState::SetPattern(const RetainPtr<CPDF_Pattern>& pPattern,
                                 const std::vector<float>& values,
                                 CPDF_Color* color,
                                 FX_COLORREF* colorref) {
  DCHECK(color);
  DCHECK(colorref);

  color->SetValueForPattern(pPattern, values);
  int R;
  int G;
  int B;
  bool ret = color->GetRGB(&R, &G, &B);
  if (CPDF_TilingPattern* pTilingPattern = pPattern->AsTilingPattern()) {
    if (!ret && pTilingPattern->colored()) {
      *colorref = 0x00BFBFBF;
      return;
    }
  }
  *colorref = ret ? FXSYS_BGR(B, G, R) : 0xFFFFFFFF;
}

CPDF_ColorState::ColorData::ColorData() = default;

CPDF_ColorState::ColorData::ColorData(const ColorData& src)
    : m_FillColorRef(src.m_FillColorRef),
      m_StrokeColorRef(src.m_StrokeColorRef),
      m_FillColor(src.m_FillColor),
      m_StrokeColor(src.m_StrokeColor) {}

CPDF_ColorState::ColorData::~ColorData() = default;

void CPDF_ColorState::ColorData::SetDefault() {
  m_FillColorRef = 0;
  m_StrokeColorRef = 0;
  m_FillColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
  m_StrokeColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
}

RetainPtr<CPDF_ColorState::ColorData> CPDF_ColorState::ColorData::Clone()
    const {
  return pdfium::MakeRetain<CPDF_ColorState::ColorData>(*this);
}
