// 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 "../../../third_party/base/nonstd_unique_ptr.h"
#include "../../include/fpdfdoc/fpdf_doc.h"
#include "../../include/fpdfapi/fpdf_pageobj.h"

CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) {
  ASSERT(pPage != NULL);
  m_pPageDict = pPage->m_pFormDict;
  if (m_pPageDict == NULL) {
    return;
  }
  m_pDocument = pPage->m_pDocument;
  CPDF_Array* pAnnots = m_pPageDict->GetArray("Annots");
  if (pAnnots == NULL) {
    return;
  }
  CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
  CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
  FX_BOOL bRegenerateAP = pAcroForm && pAcroForm->GetBoolean("NeedAppearances");
  for (FX_DWORD i = 0; i < pAnnots->GetCount(); ++i) {
    CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i);
    if (pDict == NULL || pDict->GetType() != PDFOBJ_DICTIONARY) {
      continue;
    }
    FX_DWORD dwObjNum = pDict->GetObjNum();
    if (dwObjNum == 0) {
      dwObjNum = m_pDocument->AddIndirectObject(pDict);
      CPDF_Reference* pAction = new CPDF_Reference(m_pDocument, dwObjNum);
      pAnnots->InsertAt(i, pAction);
      pAnnots->RemoveAt(i + 1);
      pDict = pAnnots->GetDict(i);
    }
    CPDF_Annot* pAnnot = new CPDF_Annot(pDict, this);
    m_AnnotList.Add(pAnnot);
    if (bRegenerateAP &&
        pDict->GetConstString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget"))
      if (CPDF_InterForm::UpdatingAPEnabled()) {
        FPDF_GenerateAP(m_pDocument, pDict);
      }
  }
}
CPDF_AnnotList::~CPDF_AnnotList() {
  int i = 0;
  for (i = 0; i < m_AnnotList.GetSize(); ++i) {
    delete (CPDF_Annot*)m_AnnotList[i];
  }
  for (i = 0; i < m_Borders.GetSize(); ++i) {
    delete (CPDF_PageObjects*)m_Borders[i];
  }
}
void CPDF_AnnotList::DisplayPass(const CPDF_Page* pPage,
                                 CFX_RenderDevice* pDevice,
                                 CPDF_RenderContext* pContext,
                                 FX_BOOL bPrinting,
                                 CFX_AffineMatrix* pMatrix,
                                 FX_BOOL bWidgetPass,
                                 CPDF_RenderOptions* pOptions,
                                 FX_RECT* clip_rect) {
  for (int i = 0; i < m_AnnotList.GetSize(); ++i) {
    CPDF_Annot* pAnnot = (CPDF_Annot*)m_AnnotList[i];
    FX_BOOL bWidget = pAnnot->GetSubType() == "Widget";
    if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget)) {
      continue;
    }
    FX_DWORD annot_flags = pAnnot->GetFlags();
    if (annot_flags & ANNOTFLAG_HIDDEN) {
      continue;
    }
    if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) {
      continue;
    }
    if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) {
      continue;
    }
    if (pOptions != NULL) {
      IPDF_OCContext* pOCContext = pOptions->m_pOCContext;
      CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
      if (pOCContext != NULL && pAnnotDict != NULL &&
          !pOCContext->CheckOCGVisible(pAnnotDict->GetDict(FX_BSTRC("OC")))) {
        continue;
      }
    }
    CPDF_Rect annot_rect_f;
    pAnnot->GetRect(annot_rect_f);
    CFX_Matrix matrix;
    matrix = *pMatrix;
    if (clip_rect) {
      annot_rect_f.Transform(&matrix);
      FX_RECT annot_rect = annot_rect_f.GetOutterRect();
      annot_rect.Intersect(*clip_rect);
      if (annot_rect.IsEmpty()) {
        continue;
      }
    }
    if (pContext) {
      pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal);
    } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix,
                                       CPDF_Annot::Normal, pOptions)) {
      pAnnot->DrawBorder(pDevice, &matrix, pOptions);
    }
  }
}
void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage,
                                   CFX_RenderDevice* pDevice,
                                   CFX_AffineMatrix* pUser2Device,
                                   FX_BOOL bShowWidget,
                                   CPDF_RenderOptions* pOptions) {
  FX_RECT clip_rect;
  if (pDevice) {
    clip_rect = pDevice->GetClipBox();
  }
  FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER ||
                      (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW));
  DisplayAnnots(pPage, pDevice, NULL, bPrinting, pUser2Device,
                bShowWidget ? 3 : 1, pOptions, &clip_rect);
}
void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage,
                                   CFX_RenderDevice* pDevice,
                                   CPDF_RenderContext* pContext,
                                   FX_BOOL bPrinting,
                                   CFX_AffineMatrix* pUser2Device,
                                   FX_DWORD dwAnnotFlags,
                                   CPDF_RenderOptions* pOptions,
                                   FX_RECT* pClipRect) {
  if (dwAnnotFlags & 0x01) {
    DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, FALSE,
                pOptions, pClipRect);
  }
  if (dwAnnotFlags & 0x02) {
    DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, TRUE,
                pOptions, pClipRect);
  }
}
int CPDF_AnnotList::GetIndex(CPDF_Annot* pAnnot) {
  for (int i = 0; i < m_AnnotList.GetSize(); ++i)
    if (m_AnnotList[i] == (void*)pAnnot) {
      return i;
    }
  return -1;
}
CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_AnnotList* pList)
    : m_pAnnotDict(pDict),
      m_pList(pList),
      m_sSubtype(m_pAnnotDict->GetConstString(FX_BSTRC("Subtype"))) {}
CPDF_Annot::~CPDF_Annot() {
  ClearCachedAP();
}
void CPDF_Annot::ClearCachedAP() {
  FX_POSITION pos = m_APMap.GetStartPosition();
  while (pos) {
    void* pForm;
    void* pObjects;
    m_APMap.GetNextAssoc(pos, pForm, pObjects);
    delete (CPDF_PageObjects*)pObjects;
  }
  m_APMap.RemoveAll();
}
CFX_ByteString CPDF_Annot::GetSubType() const {
  return m_sSubtype;
}

void CPDF_Annot::GetRect(CPDF_Rect& rect) const {
  if (m_pAnnotDict == NULL) {
    return;
  }
  rect = m_pAnnotDict->GetRect("Rect");
  rect.Normalize();
}

FX_DWORD CPDF_Annot::GetFlags() const {
  return m_pAnnotDict->GetInteger("F");
}

CPDF_Dictionary* CPDF_Annot::GetAnnotDict() {
  return m_pAnnotDict;
}

CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict,
                                CPDF_Annot::AppearanceMode mode) {
  CPDF_Dictionary* pAP = pAnnotDict->GetDict("AP");
  if (pAP == NULL) {
    return NULL;
  }
  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";
  }
  CPDF_Object* psub = pAP->GetElementValue(ap_entry);
  if (psub == NULL) {
    return NULL;
  }
  CPDF_Stream* pStream = NULL;
  if (psub->GetType() == PDFOBJ_STREAM) {
    pStream = (CPDF_Stream*)psub;
  } else if (psub->GetType() == PDFOBJ_DICTIONARY) {
    CFX_ByteString as = pAnnotDict->GetString("AS");
    if (as.IsEmpty()) {
      CFX_ByteString value = pAnnotDict->GetString(FX_BSTRC("V"));
      if (value.IsEmpty()) {
        CPDF_Dictionary* pDict = pAnnotDict->GetDict(FX_BSTRC("Parent"));
        value = pDict ? pDict->GetString(FX_BSTRC("V")) : CFX_ByteString();
      }
      if (value.IsEmpty() || !((CPDF_Dictionary*)psub)->KeyExist(value)) {
        as = FX_BSTRC("Off");
      } else {
        as = value;
      }
    }
    pStream = ((CPDF_Dictionary*)psub)->GetStream(as);
  }
  return pStream;
}
CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) {
  CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pAnnotDict, mode);
  if (pStream == NULL) {
    return NULL;
  }
  CPDF_Form* pForm;
  if (m_APMap.Lookup(pStream, (void*&)pForm)) {
    return pForm;
  }
  pForm = new CPDF_Form(m_pList->m_pDocument, pPage->m_pResources, pStream);
  pForm->ParseContent(NULL, NULL, NULL, NULL);
  m_APMap.SetAt(pStream, pForm);
  return pForm;
}
static CPDF_Form* FPDFDOC_Annot_GetMatrix(const CPDF_Page* pPage,
                                          CPDF_Annot* pAnnot,
                                          CPDF_Annot::AppearanceMode mode,
                                          const CFX_AffineMatrix* pUser2Device,
                                          CFX_Matrix& matrix) {
  CPDF_Form* pForm = pAnnot->GetAPForm(pPage, mode);
  if (!pForm) {
    return NULL;
  }
  CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRect(FX_BSTRC("BBox"));
  CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix"));
  form_matrix.TransformRect(form_bbox);
  CPDF_Rect arect;
  pAnnot->GetRect(arect);
  matrix.MatchRect(arect, form_bbox);
  matrix.Concat(*pUser2Device);
  return pForm;
}
FX_BOOL CPDF_Annot::DrawAppearance(const CPDF_Page* pPage,
                                   CFX_RenderDevice* pDevice,
                                   const CFX_AffineMatrix* pUser2Device,
                                   AppearanceMode mode,
                                   const CPDF_RenderOptions* pOptions) {
  CFX_Matrix matrix;
  CPDF_Form* pForm =
      FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix);
  if (!pForm) {
    return FALSE;
  }
  CPDF_RenderContext context;
  context.Create((CPDF_Page*)pPage);
  context.DrawObjectList(pDevice, pForm, &matrix, pOptions);
  return TRUE;
}
FX_BOOL CPDF_Annot::DrawInContext(const CPDF_Page* pPage,
                                  const CPDF_RenderContext* pContext,
                                  const CFX_AffineMatrix* pUser2Device,
                                  AppearanceMode mode) {
  CFX_Matrix matrix;
  CPDF_Form* pForm =
      FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix);
  if (!pForm) {
    return FALSE;
  }
  ((CPDF_RenderContext*)pContext)->AppendObjectList(pForm, &matrix);
  return TRUE;
}
void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice,
                            const CFX_AffineMatrix* pUser2Device,
                            const CPDF_RenderOptions* pOptions) {
  if (GetSubType() == "Popup") {
    return;
  }
  FX_DWORD annot_flags = GetFlags();
  if (annot_flags & ANNOTFLAG_HIDDEN) {
    return;
  }
  FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER ||
                      (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW));
  if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) {
    return;
  }
  if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) {
    return;
  }
  CPDF_Dictionary* pBS = m_pAnnotDict->GetDict("BS");
  char style_char;
  FX_FLOAT width;
  CPDF_Array* pDashArray = NULL;
  if (pBS == NULL) {
    CPDF_Array* pBorderArray = m_pAnnotDict->GetArray("Border");
    style_char = 'S';
    if (pBorderArray) {
      width = pBorderArray->GetNumber(2);
      if (pBorderArray->GetCount() == 4) {
        pDashArray = pBorderArray->GetArray(3);
        if (pDashArray == NULL) {
          return;
        }
        int nLen = pDashArray->GetCount();
        int i = 0;
        for (; i < nLen; ++i) {
          CPDF_Object* pObj = pDashArray->GetElementValue(i);
          if (pObj && pObj->GetInteger()) {
            break;
          }
        }
        if (i == nLen) {
          return;
        }
        style_char = 'D';
      }
    } else {
      width = 1;
    }
  } else {
    CFX_ByteString style = pBS->GetString("S");
    pDashArray = pBS->GetArray("D");
    style_char = style[1];
    width = pBS->GetNumber("W");
  }
  if (width <= 0) {
    return;
  }
  CPDF_Array* pColor = m_pAnnotDict->GetArray("C");
  FX_DWORD argb = 0xff000000;
  if (pColor != NULL) {
    int R = (int32_t)(pColor->GetNumber(0) * 255);
    int G = (int32_t)(pColor->GetNumber(1) * 255);
    int B = (int32_t)(pColor->GetNumber(2) * 255);
    argb = ArgbEncode(0xff, R, G, B);
  }
  CPDF_GraphStateData graph_state;
  graph_state.m_LineWidth = width;
  if (style_char == 'D') {
    if (pDashArray) {
      FX_DWORD dash_count = pDashArray->GetCount();
      if (dash_count % 2) {
        dash_count++;
      }
      graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count);
      graph_state.m_DashCount = dash_count;
      FX_DWORD i;
      for (i = 0; i < pDashArray->GetCount(); ++i) {
        graph_state.m_DashArray[i] = pDashArray->GetNumber(i);
      }
      if (i < dash_count) {
        graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1];
      }
    } else {
      graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2);
      graph_state.m_DashCount = 2;
      graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f;
    }
  }
  CFX_FloatRect rect;
  GetRect(rect);
  CPDF_PathData path;
  width /= 2;
  path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width,
                  rect.top - width);
  int fill_type = 0;
  if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) {
    fill_type |= FXFILL_NOPATHSMOOTH;
  }
  pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type);
}
