blob: dd298f382facad69d8496d7faa24e0ebb7e43b12 [file] [log] [blame]
// 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/fpdfapi/fpdf_page/include/cpdf_page.h"
#include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
#include "core/fpdfapi/fpdf_page/pageint.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
#include "core/fpdfapi/include/cpdf_modulemgr.h"
#include "core/fpdfapi/ipdf_rendermodule.h"
CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict,
const CFX_ByteStringC& name) {
int level = 0;
while (1) {
CPDF_Object* pObj = pPageDict->GetDirectObjectBy(name);
if (pObj) {
return pObj;
}
CPDF_Dictionary* pParent = pPageDict->GetDictBy("Parent");
if (!pParent || pParent == pPageDict) {
return NULL;
}
pPageDict = pParent;
level++;
if (level == 1000) {
return NULL;
}
}
}
CPDF_Page::CPDF_Page() : m_pPageRender(nullptr) {}
CPDF_Page::~CPDF_Page() {
if (m_pPageRender) {
IPDF_RenderModule* pModule = CPDF_ModuleMgr::Get()->GetRenderModule();
pModule->DestroyPageCache(m_pPageRender);
}
}
void CPDF_Page::Load(CPDF_Document* pDocument,
CPDF_Dictionary* pPageDict,
FX_BOOL bPageCache) {
m_pDocument = (CPDF_Document*)pDocument;
m_pFormDict = pPageDict;
if (bPageCache) {
m_pPageRender =
CPDF_ModuleMgr::Get()->GetRenderModule()->CreatePageCache(this);
}
if (!pPageDict) {
m_PageWidth = m_PageHeight = 100 * 1.0f;
m_pPageResources = m_pResources = NULL;
return;
}
CPDF_Object* pageAttr = GetPageAttr("Resources");
m_pResources = pageAttr ? pageAttr->GetDict() : NULL;
m_pPageResources = m_pResources;
CPDF_Object* pRotate = GetPageAttr("Rotate");
int rotate = 0;
if (pRotate) {
rotate = pRotate->GetInteger() / 90 % 4;
}
if (rotate < 0) {
rotate += 4;
}
CPDF_Array* pMediaBox = ToArray(GetPageAttr("MediaBox"));
CFX_FloatRect mediabox;
if (pMediaBox) {
mediabox = pMediaBox->GetRect();
mediabox.Normalize();
}
if (mediabox.IsEmpty()) {
mediabox = CFX_FloatRect(0, 0, 612, 792);
}
CPDF_Array* pCropBox = ToArray(GetPageAttr("CropBox"));
if (pCropBox) {
m_BBox = pCropBox->GetRect();
m_BBox.Normalize();
}
if (m_BBox.IsEmpty()) {
m_BBox = mediabox;
} else {
m_BBox.Intersect(mediabox);
}
if (rotate % 2) {
m_PageHeight = m_BBox.right - m_BBox.left;
m_PageWidth = m_BBox.top - m_BBox.bottom;
} else {
m_PageWidth = m_BBox.right - m_BBox.left;
m_PageHeight = m_BBox.top - m_BBox.bottom;
}
switch (rotate) {
case 0:
m_PageMatrix.Set(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom);
break;
case 1:
m_PageMatrix.Set(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right);
break;
case 2:
m_PageMatrix.Set(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top);
break;
case 3:
m_PageMatrix.Set(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left);
break;
}
m_Transparency = PDFTRANS_ISOLATED;
LoadTransInfo();
}
void CPDF_Page::StartParse(CPDF_ParseOptions* pOptions) {
if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) {
return;
}
m_pParser.reset(new CPDF_ContentParser);
m_pParser->Start(this, pOptions);
m_ParseState = CONTENT_PARSING;
}
void CPDF_Page::ParseContent(CPDF_ParseOptions* pOptions) {
StartParse(pOptions);
ContinueParse(nullptr);
}
CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteStringC& name) const {
return FPDFAPI_GetPageAttr(m_pFormDict, name);
}
void CPDF_Page::GetDisplayMatrix(CFX_Matrix& matrix,
int xPos,
int yPos,
int xSize,
int ySize,
int iRotate) const {
if (m_PageWidth == 0 || m_PageHeight == 0) {
return;
}
CFX_Matrix display_matrix;
int x0 = 0;
int y0 = 0;
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
iRotate %= 4;
switch (iRotate) {
case 0:
x0 = xPos;
y0 = yPos + ySize;
x1 = xPos;
y1 = yPos;
x2 = xPos + xSize;
y2 = yPos + ySize;
break;
case 1:
x0 = xPos;
y0 = yPos;
x1 = xPos + xSize;
y1 = yPos;
x2 = xPos;
y2 = yPos + ySize;
break;
case 2:
x0 = xPos + xSize;
y0 = yPos;
x1 = xPos + xSize;
y1 = yPos + ySize;
x2 = xPos;
y2 = yPos;
break;
case 3:
x0 = xPos + xSize;
y0 = yPos + ySize;
x1 = xPos;
y1 = yPos + ySize;
x2 = xPos + xSize;
y2 = yPos;
break;
}
display_matrix.Set(
((FX_FLOAT)(x2 - x0)) / m_PageWidth, ((FX_FLOAT)(y2 - y0)) / m_PageWidth,
((FX_FLOAT)(x1 - x0)) / m_PageHeight,
((FX_FLOAT)(y1 - y0)) / m_PageHeight, (FX_FLOAT)x0, (FX_FLOAT)y0);
matrix = m_PageMatrix;
matrix.Concat(display_matrix);
}