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

#include <algorithm>
#include <vector>

#include "core/fpdfapi/parser/cpdf_simple_parser.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxge/cfx_color.h"
#include "third_party/base/notreached.h"

namespace {

// Find the token and its |nParams| parameters from the start of data,
// and move the current position to the start of those parameters.
bool FindTagParamFromStart(CPDF_SimpleParser* parser,
                           ByteStringView token,
                           int nParams) {
  nParams++;

  std::vector<uint32_t> pBuf(nParams);
  int buf_index = 0;
  int buf_count = 0;

  parser->SetCurPos(0);
  while (1) {
    pBuf[buf_index++] = parser->GetCurPos();
    if (buf_index == nParams)
      buf_index = 0;

    buf_count++;
    if (buf_count > nParams)
      buf_count = nParams;

    ByteStringView word = parser->GetWord();
    if (word.IsEmpty())
      return false;

    if (word == token) {
      if (buf_count < nParams)
        continue;

      parser->SetCurPos(pBuf[buf_index]);
      return true;
    }
  }
}

}  // namespace

CPDF_DefaultAppearance::CPDF_DefaultAppearance() = default;

CPDF_DefaultAppearance::CPDF_DefaultAppearance(const ByteString& csDA)
    : m_csDA(csDA) {}

CPDF_DefaultAppearance::CPDF_DefaultAppearance(
    const CPDF_DefaultAppearance& cDA) = default;

CPDF_DefaultAppearance::~CPDF_DefaultAppearance() = default;

Optional<ByteString> CPDF_DefaultAppearance::GetFont(float* fFontSize) {
  *fFontSize = 0.0f;
  if (m_csDA.IsEmpty())
    return pdfium::nullopt;

  ByteString csFontNameTag;
  CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
  if (FindTagParamFromStart(&syntax, "Tf", 2)) {
    csFontNameTag = ByteString(syntax.GetWord());
    csFontNameTag.Delete(0, 1);
    *fFontSize = StringToFloat(syntax.GetWord());
  }
  return PDF_NameDecode(csFontNameTag.AsStringView());
}

Optional<CFX_Color> CPDF_DefaultAppearance::GetColor() const {
  if (m_csDA.IsEmpty())
    return pdfium::nullopt;

  float fc[4];
  CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
  if (FindTagParamFromStart(&syntax, "g", 1)) {
    fc[0] = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kGray, fc[0]);
  }
  if (FindTagParamFromStart(&syntax, "rg", 3)) {
    fc[0] = StringToFloat(syntax.GetWord());
    fc[1] = StringToFloat(syntax.GetWord());
    fc[2] = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kRGB, fc[0], fc[1], fc[2]);
  }
  if (FindTagParamFromStart(&syntax, "k", 4)) {
    fc[0] = StringToFloat(syntax.GetWord());
    fc[1] = StringToFloat(syntax.GetWord());
    fc[2] = StringToFloat(syntax.GetWord());
    fc[3] = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kCMYK, fc[0], fc[1], fc[2], fc[3]);
  }
  return pdfium::nullopt;
}

Optional<CFX_Color::TypeAndARGB> CPDF_DefaultAppearance::GetColorARGB() const {
  Optional<CFX_Color> maybe_color = GetColor();
  if (!maybe_color.has_value())
    return pdfium::nullopt;

  const CFX_Color& color = maybe_color.value();
  if (color.nColorType == CFX_Color::Type::kGray) {
    int g = static_cast<int>(color.fColor1 * 255 + 0.5f);
    return CFX_Color::TypeAndARGB(CFX_Color::Type::kGray,
                                  ArgbEncode(255, g, g, g));
  }
  if (color.nColorType == CFX_Color::Type::kRGB) {
    int r = static_cast<int>(color.fColor1 * 255 + 0.5f);
    int g = static_cast<int>(color.fColor2 * 255 + 0.5f);
    int b = static_cast<int>(color.fColor3 * 255 + 0.5f);
    return CFX_Color::TypeAndARGB(CFX_Color::Type::kRGB,
                                  ArgbEncode(255, r, g, b));
  }
  if (color.nColorType == CFX_Color::Type::kCMYK) {
    float r = 1.0f - std::min(1.0f, color.fColor1 + color.fColor4);
    float g = 1.0f - std::min(1.0f, color.fColor2 + color.fColor4);
    float b = 1.0f - std::min(1.0f, color.fColor3 + color.fColor4);
    return CFX_Color::TypeAndARGB(
        CFX_Color::Type::kCMYK,
        ArgbEncode(255, static_cast<int>(r * 255 + 0.5f),
                   static_cast<int>(g * 255 + 0.5f),
                   static_cast<int>(b * 255 + 0.5f)));
  }
  NOTREACHED();
  return pdfium::nullopt;
}

bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting(
    CPDF_SimpleParser* parser,
    ByteStringView token,
    int nParams) {
  return FindTagParamFromStart(parser, token, nParams);
}
