// 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 "fpdfsdk/include/fsdk_define.h"
#include "fpdfsdk/include/fsdk_mgr.h"
#include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h"
#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h"
#include "fpdfsdk/include/fpdfxfa/fpdfxfa_page.h"
CPDFXFA_Page::CPDFXFA_Page(CPDFXFA_Document* pDoc, int page_index)
: m_pPDFPage(NULL),
m_pXFAPageView(NULL),
m_iPageIndex(page_index),
m_pDocument(pDoc),
m_iRef(1) {}
CPDFXFA_Page::~CPDFXFA_Page() {
if (m_pPDFPage)
delete m_pPDFPage;
m_pPDFPage = NULL;
m_pXFAPageView = NULL;
}
void CPDFXFA_Page::Release() {
m_iRef--;
if (m_iRef > 0)
return;
if (m_pDocument)
m_pDocument->RemovePage(this);
delete this;
}
FX_BOOL CPDFXFA_Page::LoadPDFPage() {
if (!m_pDocument)
return FALSE;
CPDF_Document* pPDFDoc = m_pDocument->GetPDFDoc();
if (pPDFDoc) {
CPDF_Dictionary* pDict = pPDFDoc->GetPage(m_iPageIndex);
if (pDict == NULL)
return FALSE;
if (m_pPDFPage) {
if (m_pPDFPage->m_pFormDict == pDict)
return TRUE;
delete m_pPDFPage;
m_pPDFPage = NULL;
}
m_pPDFPage = new CPDF_Page;
m_pPDFPage->Load(pPDFDoc, pDict);
m_pPDFPage->ParseContent();
return TRUE;
}
return FALSE;
}
FX_BOOL CPDFXFA_Page::LoadXFAPageView() {
if (!m_pDocument)
return FALSE;
IXFA_Doc* pXFADoc = m_pDocument->GetXFADoc();
if (!pXFADoc)
return FALSE;
IXFA_DocView* pXFADocView = m_pDocument->GetXFADocView();
if (!pXFADocView)
return FALSE;
IXFA_PageView* pPageView = pXFADocView->GetPageView(m_iPageIndex);
if (!pPageView)
return FALSE;
if (m_pXFAPageView == pPageView)
return TRUE;
m_pXFAPageView = pPageView;
(void)m_pXFAPageView->LoadPageView(nullptr);
return TRUE;
}
FX_BOOL CPDFXFA_Page::LoadPage() {
if (!m_pDocument || m_iPageIndex < 0)
return FALSE;
int iDocType = m_pDocument->GetDocType();
switch (iDocType) {
case DOCTYPE_PDF:
case DOCTYPE_STATIC_XFA: {
return LoadPDFPage();
}
case DOCTYPE_DYNAMIC_XFA: {
return LoadXFAPageView();
}
default:
return FALSE;
}
return FALSE;
}
FX_BOOL CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) {
if (!m_pDocument || m_iPageIndex < 0 || !pageDict)
return FALSE;
if (m_pPDFPage)
delete m_pPDFPage;
m_pPDFPage = new CPDF_Page();
m_pPDFPage->Load(m_pDocument->GetPDFDoc(), pageDict);
m_pPDFPage->ParseContent();
return TRUE;
}
FX_FLOAT CPDFXFA_Page::GetPageWidth() {
ASSERT(m_pDocument != NULL);
if (!m_pPDFPage && !m_pXFAPageView)
return 0.0f;
int nDocType = m_pDocument->GetDocType();
switch (nDocType) {
case DOCTYPE_DYNAMIC_XFA: {
if (m_pXFAPageView) {
CFX_RectF rect;
m_pXFAPageView->GetPageViewRect(rect);
return rect.width;
}
} break;
case DOCTYPE_STATIC_XFA:
case DOCTYPE_PDF: {
if (m_pPDFPage)
return m_pPDFPage->GetPageWidth();
} break;
default:
return 0.0f;
}
return 0.0f;
}
FX_FLOAT CPDFXFA_Page::GetPageHeight() {
ASSERT(m_pDocument != NULL);
if (!m_pPDFPage && !m_pXFAPageView)
return 0.0f;
int nDocType = m_pDocument->GetDocType();
switch (nDocType) {
case DOCTYPE_PDF:
case DOCTYPE_STATIC_XFA: {
if (m_pPDFPage)
return m_pPDFPage->GetPageHeight();
} break;
case DOCTYPE_DYNAMIC_XFA: {
if (m_pXFAPageView) {
CFX_RectF rect;
m_pXFAPageView->GetPageViewRect(rect);
return rect.height;
}
} break;
default:
return 0.0f;
}
return 0.0f;
}
void CPDFXFA_Page::DeviceToPage(int start_x,
int start_y,
int size_x,
int size_y,
int rotate,
int device_x,
int device_y,
double* page_x,
double* page_y) {
ASSERT(m_pDocument != NULL);
if (!m_pPDFPage && !m_pXFAPageView)
return;
CFX_Matrix page2device;
CFX_Matrix device2page;
FX_FLOAT page_x_f, page_y_f;
GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);
device2page.SetReverse(page2device);
device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f,
page_y_f);
*page_x = (page_x_f);
*page_y = (page_y_f);
}
void CPDFXFA_Page::PageToDevice(int start_x,
int start_y,
int size_x,
int size_y,
int rotate,
double page_x,
double page_y,
int* device_x,
int* device_y) {
if (!m_pPDFPage && !m_pXFAPageView)
return;
CFX_Matrix page2device;
FX_FLOAT device_x_f, device_y_f;
GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);
page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
device_y_f);
*device_x = FXSYS_round(device_x_f);
*device_y = FXSYS_round(device_y_f);
}
void CPDFXFA_Page::GetDisplayMatrix(CFX_Matrix& matrix,
int xPos,
int yPos,
int xSize,
int ySize,
int iRotate) const {
ASSERT(m_pDocument != NULL);
if (!m_pPDFPage && !m_pXFAPageView)
return;
int nDocType = m_pDocument->GetDocType();
switch (nDocType) {
case DOCTYPE_DYNAMIC_XFA: {
if (m_pXFAPageView) {
CFX_Rect rect;
rect.Set(xPos, yPos, xSize, ySize);
m_pXFAPageView->GetDisplayMatrix(matrix, rect, iRotate);
}
} break;
case DOCTYPE_PDF:
case DOCTYPE_STATIC_XFA: {
if (m_pPDFPage) {
m_pPDFPage->GetDisplayMatrix(matrix, xPos, yPos, xSize, ySize, iRotate);
}
} break;
default:
return;
}
}