// 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 <algorithm>

#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
#include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
#include "core/fxcrt/include/fx_ext.h"
#include "fpdfsdk/include/fsdk_baseannot.h"
#include "fpdfsdk/include/fsdk_define.h"
#include "fpdfsdk/include/fsdk_mgr.h"

#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/include/fpdfxfa_doc.h"
#endif  // PDF_ENABLE_XFA

namespace {

const float kMinWidth = 1.0f;
const float kMinHeight = 1.0f;

int gAfxGetTimeZoneInSeconds(int8_t tzhour, uint8_t tzminute) {
  return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60);
}

bool gAfxIsLeapYear(int16_t year) {
  return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
}

uint16_t gAfxGetYearDays(int16_t year) {
  return (gAfxIsLeapYear(year) ? 366 : 365);
}

uint8_t gAfxGetMonthDays(int16_t year, uint8_t month) {
  uint8_t mDays;
  switch (month) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
      mDays = 31;
      break;

    case 4:
    case 6:
    case 9:
    case 11:
      mDays = 30;
      break;

    case 2:
      if (gAfxIsLeapYear(year))
        mDays = 29;
      else
        mDays = 28;
      break;

    default:
      mDays = 0;
      break;
  }

  return mDays;
}

}  // namespace

CPDFSDK_DateTime::CPDFSDK_DateTime() {
  ResetDateTime();
}

CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) {
  ResetDateTime();

  FromPDFDateTimeString(dtStr);
}

CPDFSDK_DateTime::CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime) {
  operator=(datetime);
}

CPDFSDK_DateTime::CPDFSDK_DateTime(const FX_SYSTEMTIME& st) {
  operator=(st);
}

void CPDFSDK_DateTime::ResetDateTime() {
  tzset();

  time_t curTime;
  time(&curTime);
  struct tm* newtime = localtime(&curTime);

  dt.year = newtime->tm_year + 1900;
  dt.month = newtime->tm_mon + 1;
  dt.day = newtime->tm_mday;
  dt.hour = newtime->tm_hour;
  dt.minute = newtime->tm_min;
  dt.second = newtime->tm_sec;
}

CPDFSDK_DateTime& CPDFSDK_DateTime::operator=(
    const CPDFSDK_DateTime& datetime) {
  FXSYS_memcpy(&dt, &datetime.dt, sizeof(FX_DATETIME));
  return *this;
}

CPDFSDK_DateTime& CPDFSDK_DateTime::operator=(const FX_SYSTEMTIME& st) {
  tzset();

  dt.year = static_cast<int16_t>(st.wYear);
  dt.month = static_cast<uint8_t>(st.wMonth);
  dt.day = static_cast<uint8_t>(st.wDay);
  dt.hour = static_cast<uint8_t>(st.wHour);
  dt.minute = static_cast<uint8_t>(st.wMinute);
  dt.second = static_cast<uint8_t>(st.wSecond);
  return *this;
}

bool CPDFSDK_DateTime::operator==(const CPDFSDK_DateTime& datetime) const {
  return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) == 0);
}

bool CPDFSDK_DateTime::operator!=(const CPDFSDK_DateTime& datetime) const {
  return !(*this == datetime);
}

time_t CPDFSDK_DateTime::ToTime_t() const {
  struct tm newtime;

  newtime.tm_year = dt.year - 1900;
  newtime.tm_mon = dt.month - 1;
  newtime.tm_mday = dt.day;
  newtime.tm_hour = dt.hour;
  newtime.tm_min = dt.minute;
  newtime.tm_sec = dt.second;

  return mktime(&newtime);
}

CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString(
    const CFX_ByteString& dtStr) {
  int strLength = dtStr.GetLength();
  if (strLength <= 0)
    return *this;

  int i = 0;
  while (i < strLength && !std::isdigit(dtStr[i]))
    ++i;

  if (i >= strLength)
    return *this;

  int j = 0;
  int k = 0;
  FX_CHAR ch;
  while (i < strLength && j < 4) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.year = static_cast<int16_t>(k);
  if (i >= strLength || j < 4)
    return *this;

  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.month = static_cast<uint8_t>(k);
  if (i >= strLength || j < 2)
    return *this;

  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.day = static_cast<uint8_t>(k);
  if (i >= strLength || j < 2)
    return *this;

  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.hour = static_cast<uint8_t>(k);
  if (i >= strLength || j < 2)
    return *this;

  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.minute = static_cast<uint8_t>(k);
  if (i >= strLength || j < 2)
    return *this;

  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.second = static_cast<uint8_t>(k);
  if (i >= strLength || j < 2)
    return *this;

  ch = dtStr[i++];
  if (ch != '-' && ch != '+')
    return *this;
  if (ch == '-')
    dt.tzHour = -1;
  else
    dt.tzHour = 1;
  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.tzHour *= static_cast<int8_t>(k);
  if (i >= strLength || j < 2)
    return *this;

  if (dtStr[i++] != '\'')
    return *this;
  j = 0;
  k = 0;
  while (i < strLength && j < 2) {
    ch = dtStr[i];
    k = k * 10 + FXSYS_toDecimalDigit(ch);
    j++;
    if (!std::isdigit(ch))
      break;
    i++;
  }
  dt.tzMinute = static_cast<uint8_t>(k);
  return *this;
}

CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() {
  CFX_ByteString str1;
  str1.Format("%04d-%02u-%02u %02u:%02u:%02u ", dt.year, dt.month, dt.day,
              dt.hour, dt.minute, dt.second);
  if (dt.tzHour < 0)
    str1 += "-";
  else
    str1 += "+";
  CFX_ByteString str2;
  str2.Format("%02d:%02u", std::abs(static_cast<int>(dt.tzHour)), dt.tzMinute);
  return str1 + str2;
}

CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() {
  CFX_ByteString dtStr;
  char tempStr[32];
  memset(tempStr, 0, sizeof(tempStr));
  FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02u%02u%02u%02u%02u",
                 dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
  dtStr = CFX_ByteString(tempStr);
  if (dt.tzHour < 0)
    dtStr += CFX_ByteString("-");
  else
    dtStr += CFX_ByteString("+");
  memset(tempStr, 0, sizeof(tempStr));
  FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02u'",
                 std::abs(static_cast<int>(dt.tzHour)), dt.tzMinute);
  dtStr += CFX_ByteString(tempStr);
  return dtStr;
}

void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st) {
  time_t t = this->ToTime_t();
  struct tm* pTime = localtime(&t);
  if (pTime) {
    st.wYear = static_cast<uint16_t>(pTime->tm_year) + 1900;
    st.wMonth = static_cast<uint16_t>(pTime->tm_mon) + 1;
    st.wDay = static_cast<uint16_t>(pTime->tm_mday);
    st.wDayOfWeek = static_cast<uint16_t>(pTime->tm_wday);
    st.wHour = static_cast<uint16_t>(pTime->tm_hour);
    st.wMinute = static_cast<uint16_t>(pTime->tm_min);
    st.wSecond = static_cast<uint16_t>(pTime->tm_sec);
    st.wMilliseconds = 0;
  }
}

CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT() const {
  CPDFSDK_DateTime new_dt = *this;
  new_dt.AddSeconds(
      -gAfxGetTimeZoneInSeconds(new_dt.dt.tzHour, new_dt.dt.tzMinute));
  new_dt.dt.tzHour = 0;
  new_dt.dt.tzMinute = 0;
  return new_dt;
}

CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days) {
  if (days == 0)
    return *this;

  int16_t y = dt.year;
  uint8_t m = dt.month;
  uint8_t d = dt.day;

  int ldays = days;
  if (ldays > 0) {
    int16_t yy = y;
    if ((static_cast<uint16_t>(m) * 100 + d) > 300)
      yy++;
    int ydays = gAfxGetYearDays(yy);
    int mdays;
    while (ldays >= ydays) {
      y++;
      ldays -= ydays;
      yy++;
      mdays = gAfxGetMonthDays(y, m);
      if (d > mdays) {
        m++;
        d -= mdays;
      }
      ydays = gAfxGetYearDays(yy);
    }
    mdays = gAfxGetMonthDays(y, m) - d + 1;
    while (ldays >= mdays) {
      ldays -= mdays;
      m++;
      d = 1;
      mdays = gAfxGetMonthDays(y, m);
    }
    d += ldays;
  } else {
    ldays *= -1;
    int16_t yy = y;
    if ((static_cast<uint16_t>(m) * 100 + d) < 300)
      yy--;
    int ydays = gAfxGetYearDays(yy);
    while (ldays >= ydays) {
      y--;
      ldays -= ydays;
      yy--;
      int mdays = gAfxGetMonthDays(y, m);
      if (d > mdays) {
        m++;
        d -= mdays;
      }
      ydays = gAfxGetYearDays(yy);
    }
    while (ldays >= d) {
      ldays -= d;
      m--;
      d = gAfxGetMonthDays(y, m);
    }
    d -= ldays;
  }

  dt.year = y;
  dt.month = m;
  dt.day = d;

  return *this;
}

CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds) {
  if (seconds == 0)
    return *this;

  int n;
  int days;

  n = dt.hour * 3600 + dt.minute * 60 + dt.second + seconds;
  if (n < 0) {
    days = (n - 86399) / 86400;
    n -= days * 86400;
  } else {
    days = n / 86400;
    n %= 86400;
  }
  dt.hour = static_cast<uint8_t>(n / 3600);
  dt.hour %= 24;
  n %= 3600;
  dt.minute = static_cast<uint8_t>(n / 60);
  dt.second = static_cast<uint8_t>(n % 60);
  if (days != 0)
    AddDays(days);

  return *this;
}

CPDFSDK_Annot::CPDFSDK_Annot(CPDFSDK_PageView* pPageView)
    : m_pPageView(pPageView), m_bSelected(FALSE), m_nTabOrder(-1) {}

CPDFSDK_Annot::~CPDFSDK_Annot() {}

#ifdef PDF_ENABLE_XFA

FX_BOOL CPDFSDK_Annot::IsXFAField() {
  return FALSE;
}

CXFA_FFWidget* CPDFSDK_Annot::GetXFAWidget() const {
  return nullptr;
}

#endif  // PDF_ENABLE_XFA

FX_FLOAT CPDFSDK_Annot::GetMinWidth() const {
  return kMinWidth;
}

FX_FLOAT CPDFSDK_Annot::GetMinHeight() const {
  return kMinHeight;
}

int CPDFSDK_Annot::GetLayoutOrder() const {
  return 5;
}

CPDF_Annot* CPDFSDK_Annot::GetPDFAnnot() const {
  return nullptr;
}

CFX_ByteString CPDFSDK_Annot::GetType() const {
  return "";
}

CFX_ByteString CPDFSDK_Annot::GetSubType() const {
  return "";
}

void CPDFSDK_Annot::SetRect(const CFX_FloatRect& rect) {}

CFX_FloatRect CPDFSDK_Annot::GetRect() const {
  return CFX_FloatRect();
}

void CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice,
                                 CFX_Matrix* pUser2Device,
                                 CPDF_RenderOptions* pOptions) {}

CPDFSDK_BAAnnot::CPDFSDK_BAAnnot(CPDF_Annot* pAnnot,
                                 CPDFSDK_PageView* pPageView)
    : CPDFSDK_Annot(pPageView), m_pAnnot(pAnnot) {}

CPDFSDK_BAAnnot::~CPDFSDK_BAAnnot() {}

CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const {
  return m_pAnnot;
}

FX_BOOL CPDFSDK_Annot::IsSelected() {
  return m_bSelected;
}

void CPDFSDK_Annot::SetSelected(FX_BOOL bSelected) {
  m_bSelected = bSelected;
}

int CPDFSDK_Annot::GetTabOrder() {
  return m_nTabOrder;
}

void CPDFSDK_Annot::SetTabOrder(int iTabOrder) {
  m_nTabOrder = iTabOrder;
}

CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const {
  return m_pAnnot->GetAnnotDict();
}

void CPDFSDK_BAAnnot::SetRect(const CFX_FloatRect& rect) {
  ASSERT(rect.right - rect.left >= GetMinWidth());
  ASSERT(rect.top - rect.bottom >= GetMinHeight());

  m_pAnnot->GetAnnotDict()->SetAtRect("Rect", rect);
}

CFX_FloatRect CPDFSDK_BAAnnot::GetRect() const {
  CFX_FloatRect rect;
  m_pAnnot->GetRect(rect);
  return rect;
}

CFX_ByteString CPDFSDK_BAAnnot::GetType() const {
  return m_pAnnot->GetSubType();
}

CFX_ByteString CPDFSDK_BAAnnot::GetSubType() const {
  return "";
}

void CPDFSDK_BAAnnot::DrawAppearance(CFX_RenderDevice* pDevice,
                                     const CFX_Matrix* pUser2Device,
                                     CPDF_Annot::AppearanceMode mode,
                                     const CPDF_RenderOptions* pOptions) {
  m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device,
                           mode, pOptions);
}

FX_BOOL CPDFSDK_BAAnnot::IsAppearanceValid() {
  return !!m_pAnnot->GetAnnotDict()->GetDictBy("AP");
}

FX_BOOL CPDFSDK_BAAnnot::IsAppearanceValid(CPDF_Annot::AppearanceMode mode) {
  CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDictBy("AP");
  if (!pAP)
    return FALSE;

  // Choose the right sub-ap
  const FX_CHAR* ap_entry = "N";
  if (mode == CPDF_Annot::Down)
    ap_entry = "D";
  else if (mode == CPDF_Annot::Rollover)
    ap_entry = "R";
  if (!pAP->KeyExist(ap_entry))
    ap_entry = "N";

  // Get the AP stream or subdirectory
  CPDF_Object* psub = pAP->GetDirectObjectBy(ap_entry);
  return !!psub;
}

void CPDFSDK_BAAnnot::DrawBorder(CFX_RenderDevice* pDevice,
                                 const CFX_Matrix* pUser2Device,
                                 const CPDF_RenderOptions* pOptions) {
  m_pAnnot->DrawBorder(pDevice, pUser2Device, pOptions);
}

void CPDFSDK_BAAnnot::ClearCachedAP() {
  m_pAnnot->ClearCachedAP();
}

void CPDFSDK_BAAnnot::SetContents(const CFX_WideString& sContents) {
  if (sContents.IsEmpty())
    m_pAnnot->GetAnnotDict()->RemoveAt("Contents");
  else
    m_pAnnot->GetAnnotDict()->SetAtString("Contents",
                                          PDF_EncodeText(sContents));
}

CFX_WideString CPDFSDK_BAAnnot::GetContents() const {
  return m_pAnnot->GetAnnotDict()->GetUnicodeTextBy("Contents");
}

void CPDFSDK_BAAnnot::SetAnnotName(const CFX_WideString& sName) {
  if (sName.IsEmpty())
    m_pAnnot->GetAnnotDict()->RemoveAt("NM");
  else
    m_pAnnot->GetAnnotDict()->SetAtString("NM", PDF_EncodeText(sName));
}

CFX_WideString CPDFSDK_BAAnnot::GetAnnotName() const {
  return m_pAnnot->GetAnnotDict()->GetUnicodeTextBy("NM");
}

void CPDFSDK_BAAnnot::SetModifiedDate(const FX_SYSTEMTIME& st) {
  CPDFSDK_DateTime dt(st);
  CFX_ByteString str = dt.ToPDFDateTimeString();

  if (str.IsEmpty())
    m_pAnnot->GetAnnotDict()->RemoveAt("M");
  else
    m_pAnnot->GetAnnotDict()->SetAtString("M", str);
}

FX_SYSTEMTIME CPDFSDK_BAAnnot::GetModifiedDate() const {
  FX_SYSTEMTIME systime;
  CFX_ByteString str = m_pAnnot->GetAnnotDict()->GetStringBy("M");

  CPDFSDK_DateTime dt(str);
  dt.ToSystemTime(systime);

  return systime;
}

void CPDFSDK_BAAnnot::SetFlags(uint32_t nFlags) {
  m_pAnnot->GetAnnotDict()->SetAtInteger("F", nFlags);
}

uint32_t CPDFSDK_BAAnnot::GetFlags() const {
  return m_pAnnot->GetAnnotDict()->GetIntegerBy("F");
}

void CPDFSDK_BAAnnot::SetAppState(const CFX_ByteString& str) {
  if (str.IsEmpty())
    m_pAnnot->GetAnnotDict()->RemoveAt("AS");
  else
    m_pAnnot->GetAnnotDict()->SetAtString("AS", str);
}

CFX_ByteString CPDFSDK_BAAnnot::GetAppState() const {
  return m_pAnnot->GetAnnotDict()->GetStringBy("AS");
}

void CPDFSDK_BAAnnot::SetStructParent(int key) {
  m_pAnnot->GetAnnotDict()->SetAtInteger("StructParent", key);
}

int CPDFSDK_BAAnnot::GetStructParent() const {
  return m_pAnnot->GetAnnotDict()->GetIntegerBy("StructParent");
}

// border
void CPDFSDK_BAAnnot::SetBorderWidth(int nWidth) {
  CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArrayBy("Border");

  if (pBorder) {
    pBorder->SetAt(2, new CPDF_Number(nWidth));
  } else {
    CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDictBy("BS");

    if (!pBSDict) {
      pBSDict = new CPDF_Dictionary;
      m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict);
    }

    pBSDict->SetAtInteger("W", nWidth);
  }
}

int CPDFSDK_BAAnnot::GetBorderWidth() const {
  if (CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArrayBy("Border")) {
    return pBorder->GetIntegerAt(2);
  }
  if (CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDictBy("BS")) {
    return pBSDict->GetIntegerBy("W", 1);
  }
  return 1;
}

void CPDFSDK_BAAnnot::SetBorderStyle(BorderStyle nStyle) {
  CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDictBy("BS");
  if (!pBSDict) {
    pBSDict = new CPDF_Dictionary;
    m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict);
  }

  switch (nStyle) {
    case BorderStyle::SOLID:
      pBSDict->SetAtName("S", "S");
      break;
    case BorderStyle::DASH:
      pBSDict->SetAtName("S", "D");
      break;
    case BorderStyle::BEVELED:
      pBSDict->SetAtName("S", "B");
      break;
    case BorderStyle::INSET:
      pBSDict->SetAtName("S", "I");
      break;
    case BorderStyle::UNDERLINE:
      pBSDict->SetAtName("S", "U");
      break;
    default:
      break;
  }
}

BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const {
  CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDictBy("BS");
  if (pBSDict) {
    CFX_ByteString sBorderStyle = pBSDict->GetStringBy("S", "S");
    if (sBorderStyle == "S")
      return BorderStyle::SOLID;
    if (sBorderStyle == "D")
      return BorderStyle::DASH;
    if (sBorderStyle == "B")
      return BorderStyle::BEVELED;
    if (sBorderStyle == "I")
      return BorderStyle::INSET;
    if (sBorderStyle == "U")
      return BorderStyle::UNDERLINE;
  }

  CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArrayBy("Border");
  if (pBorder) {
    if (pBorder->GetCount() >= 4) {
      CPDF_Array* pDP = pBorder->GetArrayAt(3);
      if (pDP && pDP->GetCount() > 0)
        return BorderStyle::DASH;
    }
  }

  return BorderStyle::SOLID;
}

void CPDFSDK_BAAnnot::SetColor(FX_COLORREF color) {
  CPDF_Array* pArray = new CPDF_Array;
  pArray->AddNumber((FX_FLOAT)FXSYS_GetRValue(color) / 255.0f);
  pArray->AddNumber((FX_FLOAT)FXSYS_GetGValue(color) / 255.0f);
  pArray->AddNumber((FX_FLOAT)FXSYS_GetBValue(color) / 255.0f);
  m_pAnnot->GetAnnotDict()->SetAt("C", pArray);
}

void CPDFSDK_BAAnnot::RemoveColor() {
  m_pAnnot->GetAnnotDict()->RemoveAt("C");
}

FX_BOOL CPDFSDK_BAAnnot::GetColor(FX_COLORREF& color) const {
  if (CPDF_Array* pEntry = m_pAnnot->GetAnnotDict()->GetArrayBy("C")) {
    size_t nCount = pEntry->GetCount();
    if (nCount == 1) {
      FX_FLOAT g = pEntry->GetNumberAt(0) * 255;

      color = FXSYS_RGB((int)g, (int)g, (int)g);

      return TRUE;
    } else if (nCount == 3) {
      FX_FLOAT r = pEntry->GetNumberAt(0) * 255;
      FX_FLOAT g = pEntry->GetNumberAt(1) * 255;
      FX_FLOAT b = pEntry->GetNumberAt(2) * 255;

      color = FXSYS_RGB((int)r, (int)g, (int)b);

      return TRUE;
    } else if (nCount == 4) {
      FX_FLOAT c = pEntry->GetNumberAt(0);
      FX_FLOAT m = pEntry->GetNumberAt(1);
      FX_FLOAT y = pEntry->GetNumberAt(2);
      FX_FLOAT k = pEntry->GetNumberAt(3);

      FX_FLOAT r = 1.0f - std::min(1.0f, c + k);
      FX_FLOAT g = 1.0f - std::min(1.0f, m + k);
      FX_FLOAT b = 1.0f - std::min(1.0f, y + k);

      color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));

      return TRUE;
    }
  }

  return FALSE;
}

void CPDFSDK_BAAnnot::WriteAppearance(const CFX_ByteString& sAPType,
                                      const CFX_FloatRect& rcBBox,
                                      const CFX_Matrix& matrix,
                                      const CFX_ByteString& sContents,
                                      const CFX_ByteString& sAPState) {
  CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictBy("AP");

  if (!pAPDict) {
    pAPDict = new CPDF_Dictionary;
    m_pAnnot->GetAnnotDict()->SetAt("AP", pAPDict);
  }

  CPDF_Stream* pStream = nullptr;
  CPDF_Dictionary* pParentDict = nullptr;

  if (sAPState.IsEmpty()) {
    pParentDict = pAPDict;
    pStream = pAPDict->GetStreamBy(sAPType);
  } else {
    CPDF_Dictionary* pAPTypeDict = pAPDict->GetDictBy(sAPType);
    if (!pAPTypeDict) {
      pAPTypeDict = new CPDF_Dictionary;
      pAPDict->SetAt(sAPType, pAPTypeDict);
    }
    pParentDict = pAPTypeDict;
    pStream = pAPTypeDict->GetStreamBy(sAPState);
  }

  if (!pStream) {
    pStream = new CPDF_Stream(nullptr, 0, nullptr);
    CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
    int32_t objnum = pDoc->AddIndirectObject(pStream);
    pParentDict->SetAtReference(sAPType, pDoc, objnum);
  }

  CPDF_Dictionary* pStreamDict = pStream->GetDict();
  if (!pStreamDict) {
    pStreamDict = new CPDF_Dictionary;
    pStreamDict->SetAtName("Type", "XObject");
    pStreamDict->SetAtName("Subtype", "Form");
    pStreamDict->SetAtInteger("FormType", 1);
    pStream->InitStream(nullptr, 0, pStreamDict);
  }

  if (pStreamDict) {
    pStreamDict->SetAtMatrix("Matrix", matrix);
    pStreamDict->SetAtRect("BBox", rcBBox);
  }

  pStream->SetData((uint8_t*)sContents.c_str(), sContents.GetLength(), FALSE,
                   FALSE);
}

FX_BOOL CPDFSDK_BAAnnot::IsVisible() const {
  uint32_t nFlags = GetFlags();
  return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) ||
           (nFlags & ANNOTFLAG_NOVIEW));
}

CPDF_Action CPDFSDK_BAAnnot::GetAction() const {
  return CPDF_Action(m_pAnnot->GetAnnotDict()->GetDictBy("A"));
}

void CPDFSDK_BAAnnot::SetAction(const CPDF_Action& action) {
  ASSERT(action.GetDict());
  if (action.GetDict() != m_pAnnot->GetAnnotDict()->GetDictBy("A")) {
    CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
    CPDF_Dictionary* pDict = action.GetDict();
    if (pDict && pDict->GetObjNum() == 0) {
      pDoc->AddIndirectObject(pDict);
    }
    m_pAnnot->GetAnnotDict()->SetAtReference("A", pDoc, pDict->GetObjNum());
  }
}

void CPDFSDK_BAAnnot::RemoveAction() {
  m_pAnnot->GetAnnotDict()->RemoveAt("A");
}

CPDF_AAction CPDFSDK_BAAnnot::GetAAction() const {
  return CPDF_AAction(m_pAnnot->GetAnnotDict()->GetDictBy("AA"));
}

void CPDFSDK_BAAnnot::SetAAction(const CPDF_AAction& aa) {
  if (aa.GetDict() != m_pAnnot->GetAnnotDict()->GetDictBy("AA"))
    m_pAnnot->GetAnnotDict()->SetAt("AA", aa.GetDict());
}

void CPDFSDK_BAAnnot::RemoveAAction() {
  m_pAnnot->GetAnnotDict()->RemoveAt("AA");
}

CPDF_Action CPDFSDK_BAAnnot::GetAAction(CPDF_AAction::AActionType eAAT) {
  CPDF_AAction AAction = GetAAction();

  if (AAction.ActionExist(eAAT))
    return AAction.GetAction(eAAT);

  if (eAAT == CPDF_AAction::ButtonUp)
    return GetAction();

  return CPDF_Action();
}

void CPDFSDK_BAAnnot::Annot_OnDraw(CFX_RenderDevice* pDevice,
                                   CFX_Matrix* pUser2Device,
                                   CPDF_RenderOptions* pOptions) {
  m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal);
  m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device,
                           CPDF_Annot::Normal, nullptr);
}

UnderlyingPageType* CPDFSDK_Annot::GetUnderlyingPage() {
#ifdef PDF_ENABLE_XFA
  return GetPDFXFAPage();
#else   // PDF_ENABLE_XFA
  return GetPDFPage();
#endif  // PDF_ENABLE_XFA
}

CPDF_Page* CPDFSDK_Annot::GetPDFPage() {
  return m_pPageView ? m_pPageView->GetPDFPage() : nullptr;
}

#ifdef PDF_ENABLE_XFA

CPDFXFA_Page* CPDFSDK_Annot::GetPDFXFAPage() {
  return m_pPageView ? m_pPageView->GetPDFXFAPage() : nullptr;
}

#endif  // PDF_ENABLE_XFA
