// Copyright 2016 The PDFium Authors
// 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 <utility>

#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(RetainPtr<CPDF_ColorSpace> colorspace,
                                   std::vector<float> values) {
  ColorData* pData = m_Ref.GetPrivateCopy();
  SetColor(std::move(colorspace), std::move(values), &pData->m_FillColor,
           &pData->m_FillColorRef);
}

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

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

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

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

  if (colorspace) {
    color->SetColorSpace(std::move(colorspace));
  } else if (color->IsNull()) {
    color->SetColorSpace(
        CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray));
  }
  if (color->CountComponents() > values.size())
    return;

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

void CPDF_ColorState::SetPattern(RetainPtr<CPDF_Pattern> pattern,
                                 pdfium::span<float> values,
                                 CPDF_Color* color,
                                 FX_COLORREF* colorref) {
  DCHECK(color);
  DCHECK(colorref);
  color->SetValueForPattern(pattern, values);
  int R;
  int G;
  int B;
  if (color->GetRGB(&R, &G, &B)) {
    *colorref = FXSYS_BGR(B, G, R);
    return;
  }
  CPDF_TilingPattern* tiling = pattern->AsTilingPattern();
  *colorref = tiling && tiling->colored() ? 0x00BFBFBF : 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(CPDF_ColorSpace::Family::kDeviceGray));
  m_StrokeColor.SetColorSpace(
      CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray));
}

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