blob: 01f056f9dee18a63b636a0a96df10df66b99d52b [file] [log] [blame]
//========================================================================
//
// Page.h
//
// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
// Copyright (C) 2006 Pino Toscano <pino@kde.org>
// Copyright (C) 2006, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
// Copyright (C) 2008 Iñigo Martínez <inigomartinez@gmail.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2012, 2017, 2018 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2013, 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#ifndef PAGE_H
#define PAGE_H
#include <mutex>
#include "poppler-config.h"
#include "Object.h"
class Dict;
class PDFDoc;
class XRef;
class OutputDev;
class Links;
class LinkAction;
class Annots;
class Annot;
class Gfx;
class FormPageWidgets;
class Form;
//------------------------------------------------------------------------
class PDFRectangle {
public:
double x1, y1, x2, y2;
PDFRectangle() { x1 = y1 = x2 = y2 = 0; }
PDFRectangle(double x1A, double y1A, double x2A, double y2A)
{ x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
bool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
bool contains(double x, double y) { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
void clipTo(PDFRectangle *rect);
bool operator==(const PDFRectangle &rect) const { return x1 == rect.x1 && y1 == rect.y1 && x2 == rect.x2 && y2 == rect.y2; }
};
//------------------------------------------------------------------------
// PageAttrs
//------------------------------------------------------------------------
class PageAttrs {
public:
// Construct a new PageAttrs object by merging a dictionary
// (of type Pages or Page) into another PageAttrs object. If
// <attrs> is nullptr, uses defaults.
PageAttrs(PageAttrs *attrs, Dict *dict);
// Destructor.
~PageAttrs();
// Accessors.
const PDFRectangle *getMediaBox() const { return &mediaBox; }
const PDFRectangle *getCropBox() const { return &cropBox; }
bool isCropped() const { return haveCropBox; }
const PDFRectangle *getBleedBox() const { return &bleedBox; }
const PDFRectangle *getTrimBox() const { return &trimBox; }
const PDFRectangle *getArtBox() const { return &artBox; }
int getRotate() const { return rotate; }
const GooString *getLastModified() const
{ return lastModified.isString()
? lastModified.getString() : nullptr; }
Dict *getBoxColorInfo()
{ return boxColorInfo.isDict() ? boxColorInfo.getDict() : nullptr; }
Dict *getGroup()
{ return group.isDict() ? group.getDict() : nullptr; }
Stream *getMetadata()
{ return metadata.isStream() ? metadata.getStream() : nullptr; }
Dict *getPieceInfo()
{ return pieceInfo.isDict() ? pieceInfo.getDict() : nullptr; }
Dict *getSeparationInfo()
{ return separationInfo.isDict()
? separationInfo.getDict() : nullptr; }
Dict *getResourceDict()
{ return resources.isDict() ? resources.getDict() : nullptr; }
Object *getResourceDictObject()
{ return &resources; }
void replaceResource(Object &&obj1)
{ resources = std::move(obj1); }
// Clip all other boxes to the MediaBox.
void clipBoxes();
private:
bool readBox(Dict *dict, const char *key, PDFRectangle *box);
PDFRectangle mediaBox;
PDFRectangle cropBox;
bool haveCropBox;
PDFRectangle bleedBox;
PDFRectangle trimBox;
PDFRectangle artBox;
int rotate;
Object lastModified;
Object boxColorInfo;
Object group;
Object metadata;
Object pieceInfo;
Object separationInfo;
Object resources;
};
//------------------------------------------------------------------------
// Page
//------------------------------------------------------------------------
class Page {
public:
// Constructor.
Page(PDFDoc *docA, int numA, Object &&pageDict, Ref pageRefA, PageAttrs *attrsA, Form *form);
// Destructor.
~Page();
Page(const Page &) = delete;
Page& operator=(const Page &) = delete;
// Is page valid?
bool isOk() const { return ok; }
// Get page parameters.
int getNum() const { return num; }
const PDFRectangle *getMediaBox() const { return attrs->getMediaBox(); }
const PDFRectangle *getCropBox() const { return attrs->getCropBox(); }
bool isCropped() const { return attrs->isCropped(); }
double getMediaWidth() const
{ return attrs->getMediaBox()->x2 - attrs->getMediaBox()->x1; }
double getMediaHeight() const
{ return attrs->getMediaBox()->y2 - attrs->getMediaBox()->y1; }
double getCropWidth() const
{ return attrs->getCropBox()->x2 - attrs->getCropBox()->x1; }
double getCropHeight() const
{ return attrs->getCropBox()->y2 - attrs->getCropBox()->y1; }
const PDFRectangle *getBleedBox() const { return attrs->getBleedBox(); }
const PDFRectangle *getTrimBox() const { return attrs->getTrimBox(); }
const PDFRectangle *getArtBox() const { return attrs->getArtBox(); }
int getRotate() const { return attrs->getRotate(); }
const GooString *getLastModified() const { return attrs->getLastModified(); }
Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); }
Dict *getGroup() { return attrs->getGroup(); }
Stream *getMetadata() { return attrs->getMetadata(); }
Dict *getPieceInfo() { return attrs->getPieceInfo(); }
Dict *getSeparationInfo() { return attrs->getSeparationInfo(); }
PDFDoc *getDoc() { return doc; }
Ref getRef() { return pageRef; }
// Get resource dictionary.
Dict *getResourceDict();
Object *getResourceDictObject();
Dict *getResourceDictCopy(XRef *xrefA);
// Get annotations array.
Object getAnnotsObject(XRef *xrefA = nullptr) { return annotsObj.fetch(xrefA ? xrefA : xref); }
// Add a new annotation to the page
void addAnnot(Annot *annot);
// Remove an existing annotation from the page
void removeAnnot(Annot *annot);
// Return a list of links.
Links *getLinks();
// Return a list of annots. It will be valid until the page is destroyed
Annots *getAnnots(XRef *xrefA = nullptr);
// Get contents.
Object getContents() { return contents.fetch(xref); }
// Get thumb.
Object getThumb() { return thumb.fetch(xref); }
bool loadThumb(unsigned char **data, int *width, int *height, int *rowstride);
// Get transition.
Object getTrans() { return trans.fetch(xref); }
// Get form.
FormPageWidgets *getFormWidgets();
// Get duration, the maximum length of time, in seconds,
// that the page is displayed before the presentation automatically
// advances to the next page
double getDuration() { return duration; }
// Get actions
Object getActions() { return actions.fetch(xref); }
enum PageAdditionalActionsType {
actionOpenPage, ///< Performed when opening the page
actionClosePage, ///< Performed when closing the page
};
LinkAction *getAdditionalAction(PageAdditionalActionsType type);
Gfx *createGfx(OutputDev *out, double hDPI, double vDPI,
int rotate, bool useMediaBox, bool crop,
int sliceX, int sliceY, int sliceW, int sliceH,
bool printing,
bool (*abortCheckCbk)(void *data),
void *abortCheckCbkData, XRef *xrefA = nullptr);
// Display a page.
void display(OutputDev *out, double hDPI, double vDPI,
int rotate, bool useMediaBox, bool crop,
bool printing,
bool (*abortCheckCbk)(void *data) = nullptr,
void *abortCheckCbkData = nullptr,
bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr,
void *annotDisplayDecideCbkData = nullptr,
bool copyXRef = false);
// Display part of a page.
void displaySlice(OutputDev *out, double hDPI, double vDPI,
int rotate, bool useMediaBox, bool crop,
int sliceX, int sliceY, int sliceW, int sliceH,
bool printing,
bool (*abortCheckCbk)(void *data) = nullptr,
void *abortCheckCbkData = nullptr,
bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr,
void *annotDisplayDecideCbkData = nullptr,
bool copyXRef = false);
void display(Gfx *gfx);
void makeBox(double hDPI, double vDPI, int rotate,
bool useMediaBox, bool upsideDown,
double sliceX, double sliceY, double sliceW, double sliceH,
PDFRectangle *box, bool *crop);
void processLinks(OutputDev *out);
// Get the page's default CTM.
void getDefaultCTM(double *ctm, double hDPI, double vDPI,
int rotate, bool useMediaBox, bool upsideDown);
private:
// replace xref
void replaceXRef(XRef *xrefA);
PDFDoc *doc;
XRef *xref; // the xref table for this PDF file
Object pageObj; // page dictionary
Ref pageRef; // page reference
int num; // page number
PageAttrs *attrs; // page attributes
Annots *annots; // annotations
Object annotsObj; // annotations array
Object contents; // page contents
Object thumb; // page thumbnail
Object trans; // page transition
Object actions; // page additional actions
double duration; // page duration
bool ok; // true if page is valid
mutable std::recursive_mutex mutex;
};
#endif