Commit 9727fdc0 authored by Pino Toscano's avatar Pino Toscano

Start of a pure C++ frontend for Poppler.

This initial version (called 'poppler-cpp') includes preliminary support for:
- document (loading from file name, some query methods, unlocking, font listing, embedded files)
- page (some query methods) with page transitions
- TOC

Modelled a bit on the Qt4 API, it provides also an own "ustring" typedef representing UTF-16 strings,
with methods to convert back/to UTF-8 and Latin 1.

Most probably it has bugs, but nevertheless worth testing and developing.
parent 62854051
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
)
set(poppler_cpp_SRCS
poppler-document.cpp
poppler-embedded-file.cpp
poppler-font.cpp
poppler-global.cpp
poppler-page.cpp
poppler-page-transition.cpp
poppler-private.cpp
poppler-toc.cpp
)
add_library(poppler-cpp SHARED ${poppler_cpp_SRCS})
set_target_properties(poppler-cpp PROPERTIES VERSION 0.1.0 SOVERSION 0)
target_link_libraries(poppler-cpp poppler)
if(MSVC)
target_link_libraries(poppler-cpp ${poppler_LIBS})
endif(MSVC)
install(TARGETS poppler-cpp RUNTIME DESTINATION bin LIBRARY DESTINATION lib${LIB_SUFFIX} ARCHIVE DESTINATION lib${LIB_SUFFIX})
install(FILES
poppler-document.h
poppler-embedded-file.h
poppler-font.h
poppler-global.h
poppler-page.h
poppler-page-transition.h
poppler-rectangle.h
poppler-toc.h
DESTINATION include/poppler/cpp)
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef POPPLER_DOCUMENT_PRIVATE_H
#define POPPLER_DOCUMENT_PRIVATE_H
#include "poppler-config.h"
#include "GooString.h"
#include "PDFDoc.h"
#include <vector>
namespace poppler
{
class document;
class embedded_file;
class document_private
{
public:
document_private(GooString *file_path, const std::string &owner_password,
const std::string &user_password);
~document_private();
static document* check_document(document_private *doc);
PDFDoc *doc;
bool is_locked;
std::vector<embedded_file *> embedded_files;
private:
void init();
static unsigned int count;
};
}
#endif
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "poppler-document.h"
#include "poppler-embedded-file.h"
#include "poppler-page.h"
#include "poppler-toc.h"
#include "poppler-document-private.h"
#include "poppler-embedded-file-private.h"
#include "poppler-private.h"
#include "poppler-toc-private.h"
#include "Catalog.h"
#include "ErrorCodes.h"
#include "GlobalParams.h"
#include "Outline.h"
#include <algorithm>
#include <memory>
using namespace poppler;
unsigned int poppler::document_private::count = 0U;
document_private::document_private(GooString *file_path, const std::string &owner_password,
const std::string &user_password)
: doc(0)
, is_locked(false)
{
GooString goo_owner_password(owner_password.c_str());
GooString goo_user_password(user_password.c_str());
doc = new PDFDoc(file_path, &goo_owner_password, &goo_user_password);
init();
}
document_private::~document_private()
{
delete_all(embedded_files);
delete doc;
if (count > 0) {
--count;
if (!count) {
delete globalParams;
globalParams = 0;
}
}
}
void document_private::init()
{
if (!count) {
globalParams = new GlobalParams();
setErrorFunction(detail::error_function);
}
count++;
}
document* document_private::check_document(document_private *doc)
{
if (doc->doc->isOk() || doc->doc->getErrorCode() == errEncrypted) {
if (doc->doc->getErrorCode() == errEncrypted) {
doc->is_locked = true;
}
return new document(*doc);
} else {
delete doc;
}
return 0;
}
document::document(document_private &dd)
: d(&dd)
{
}
document::~document()
{
delete d;
}
bool document::is_locked() const
{
return d->is_locked;
}
bool document::unlock(const std::string &owner_password, const std::string &user_password)
{
if (d->is_locked) {
document_private *newdoc = 0;
{
newdoc = new document_private(new GooString(d->doc->getFileName()),
owner_password, user_password);
}
if (!newdoc->doc->isOk()) {
delete newdoc;
} else {
delete d;
d = newdoc;
d->is_locked = false;
}
}
return d->is_locked;
}
document::page_mode_enum document::page_mode() const
{
switch (d->doc->getCatalog()->getPageMode()) {
case Catalog::pageModeNone:
return use_none;
case Catalog::pageModeOutlines:
return use_outlines;
case Catalog::pageModeThumbs:
return use_thumbs;
case Catalog::pageModeFullScreen:
return fullscreen;
case Catalog::pageModeOC:
return use_oc;
case Catalog::pageModeAttach:
return use_attach;
default:
return use_none;
}
}
document::page_layout_enum document::page_layout() const
{
switch (d->doc->getCatalog()->getPageLayout()) {
case Catalog::pageLayoutNone:
return no_layout;
case Catalog::pageLayoutSinglePage:
return single_page;
case Catalog::pageLayoutOneColumn:
return one_column;
case Catalog::pageLayoutTwoColumnLeft:
return two_column_left;
case Catalog::pageLayoutTwoColumnRight:
return two_column_right;
case Catalog::pageLayoutTwoPageLeft:
return two_page_left;
case Catalog::pageLayoutTwoPageRight:
return two_page_right;
default:
return no_layout;
}
}
void document::get_pdf_version(int *major, int *minor) const
{
if (major) {
*major = d->doc->getPDFMajorVersion();
}
if (minor) {
*minor = d->doc->getPDFMinorVersion();
}
}
std::vector<std::string> document::info_keys() const
{
if (d->is_locked) {
return std::vector<std::string>();
}
Object info;
if (!d->doc->getDocInfo(&info)->isDict()) {
info.free();
return std::vector<std::string>();
}
Dict *info_dict = info.getDict();
std::vector<std::string> keys(info_dict->getLength());
for (int i = 0; i < info_dict->getLength(); ++i) {
keys[i] = std::string(info_dict->getKey(i));
}
info.free();
return keys;
}
ustring document::info_key(const std::string &key) const
{
if (d->is_locked) {
return ustring();
}
Object info;
if (!d->doc->getDocInfo(&info)->isDict()) {
info.free();
return ustring();
}
Dict *info_dict = info.getDict();
Object obj;
ustring result;
if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) {
result = detail::unicode_GooString_to_ustring(obj.getString());
}
obj.free();
info.free();
return result;
}
unsigned int document::info_date(const std::string &key) const
{
if (d->is_locked) {
return (unsigned int)(-1);
}
Object info;
if (!d->doc->getDocInfo(&info)->isDict()) {
info.free();
return (unsigned int)(-1);
}
Dict *info_dict = info.getDict();
Object obj;
unsigned int result = (unsigned int)(-1);
if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) {
result = convert_date(obj.getString()->getCString());
}
obj.free();
info.free();
return result;
}
int document::pages() const
{
return d->doc->getNumPages();
}
page* document::create_page(const ustring &label) const
{
std::auto_ptr<GooString> goolabel(detail::ustring_to_unicode_GooString(label));
int index = 0;
if (!d->doc->getCatalog()->labelToIndex(goolabel.get(), &index)) {
return 0;
}
return create_page(index);
}
page* document::create_page(int index) const
{
return index >= 0 && index < d->doc->getNumPages() ? new page(d, index) : 0;
}
std::vector<font_info> document::fonts() const
{
std::vector<font_info> result;
font_iterator it(0, d);
while (it.has_next()) {
const std::vector<font_info> l = it.next();
std::copy(l.begin(), l.end(), std::back_inserter(result));
}
return result;
}
font_iterator* document::create_font_iterator(int start_page) const
{
return new font_iterator(start_page, d);
}
toc* document::create_toc() const
{
return toc_private::load_from_outline(d->doc->getOutline());
}
bool document::has_embedded_files() const
{
return d->doc->getCatalog()->numEmbeddedFiles() > 0;
}
std::vector<embedded_file *> document::embedded_files() const
{
if (d->is_locked) {
return std::vector<embedded_file *>();
}
if (d->embedded_files.empty() && d->doc->getCatalog()->numEmbeddedFiles() > 0) {
const int num = d->doc->getCatalog()->numEmbeddedFiles();
d->embedded_files.resize(num);
for (int i = 0; i < num; ++i) {
EmbFile *ef = d->doc->getCatalog()->embeddedFile(i);
d->embedded_files[i] = embedded_file_private::create(ef);
}
}
return d->embedded_files;
}
document* document::load_from_file(const std::string &file_name,
const std::string &owner_password,
const std::string &user_password)
{
document_private *doc = new document_private(
new GooString(file_name.c_str()),
owner_password, user_password);
return document_private::check_document(doc);
}
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef POPPLER_DOCUMENT_H
#define POPPLER_DOCUMENT_H
#include "poppler-global.h"
#include "poppler-font.h"
namespace poppler
{
class document_private;
class embedded_file;
class page;
class toc;
class POPPLER_CPP_EXPORT document : public poppler::noncopyable
{
public:
enum page_mode_enum {
use_none,
use_outlines,
use_thumbs,
fullscreen,
use_oc,
use_attach
};
enum page_layout_enum {
no_layout,
single_page,
one_column,
two_column_left,
two_column_right,
two_page_left,
two_page_right
};
~document();
bool is_locked() const;
bool unlock(const std::string &owner_password, const std::string &user_password);
page_mode_enum page_mode() const;
page_layout_enum page_layout() const;
void get_pdf_version(int *major, int *minor) const;
std::vector<std::string> info_keys() const;
ustring info_key(const std::string &key) const;
unsigned int /*time_t*/ info_date(const std::string &key) const;
int pages() const;
page* create_page(const ustring &label) const;
page* create_page(int index) const;
std::vector<font_info> fonts() const;
font_iterator* create_font_iterator(int start_page = 0) const;
toc* create_toc() const;
bool has_embedded_files() const;
std::vector<embedded_file *> embedded_files() const;
static document* load_from_file(const std::string &file_name,
const std::string &owner_password,
const std::string &user_password);
private:
document(document_private &dd);
document_private *d;
friend class document_private;
};
}
#endif
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef POPPLER_EMBEDDED_FILE_PRIVATE_H
#define POPPLER_EMBEDDED_FILE_PRIVATE_H
class EmbFile;
namespace poppler
{
class embedded_file_private
{
public:
embedded_file_private(EmbFile *ef);
~embedded_file_private();
static embedded_file* create(EmbFile *ef);
EmbFile *emb_file;
};
}
#endif
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "poppler-embedded-file.h"
#include "poppler-embedded-file-private.h"
#include "poppler-private.h"
#include "Object.h"
#include "Stream.h"
#include "Catalog.h"
using namespace poppler;
embedded_file_private::embedded_file_private(EmbFile *ef)
: emb_file(ef)
{
}
embedded_file_private::~embedded_file_private()
{
delete emb_file;
}
embedded_file* embedded_file_private::create(EmbFile *ef)
{
return new embedded_file(*new embedded_file_private(ef));
}
embedded_file::embedded_file(embedded_file_private &dd)
: d(&dd)
{
}
embedded_file::~embedded_file()
{
delete d;
}
bool embedded_file::is_valid() const
{
return d->emb_file->isOk();
}
std::string embedded_file::name() const
{
return std::string(d->emb_file->name()->getCString());
}
ustring embedded_file::description() const
{
return detail::unicode_GooString_to_ustring(d->emb_file->description());
}
int embedded_file::size() const
{
return d->emb_file->size();
}
unsigned int embedded_file::modification_date() const
{
return convert_date(d->emb_file->modDate()->getCString());
}
unsigned int embedded_file::creation_date() const
{
return convert_date(d->emb_file->createDate()->getCString());
}
std::string embedded_file::checksum() const
{
return std::string(d->emb_file->checksum()->getCString());
}
std::string embedded_file::mime_type() const
{
return std::string(d->emb_file->mimeType()->getCString());
}
std::vector<char> embedded_file::data() const
{
if (!is_valid()) {
return std::vector<char>();
}
Stream *stream = d->emb_file->streamObject().getStream();
stream->reset();
std::vector<char> ret(1024);
size_t data_len = 0;
int i;
while ((i = stream->getChar()) != EOF) {
if (data_len == ret.size()) {
ret.resize(ret.size() * 2);
}
ret[data_len] = (char)i;
++data_len;
}
ret.resize(data_len);
return ret;
}
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef POPPLER_EMBEDDED_FILE_H
#define POPPLER_EMBEDDED_FILE_H
#include "poppler-global.h"
#include <vector>
namespace poppler
{
class embedded_file_private;
class POPPLER_CPP_EXPORT embedded_file : public poppler::noncopyable
{
public:
~embedded_file();
bool is_valid() const;
std::string name() const;
ustring description() const;
int size() const;
unsigned int /*time_t*/ modification_date() const;
unsigned int /*time_t*/ creation_date() const;
std::string checksum() const;
std::string mime_type() const;
std::vector<char> data() const;
private:
embedded_file(embedded_file_private &dd);
embedded_file_private *d;
friend class embedded_file_private;
};
}
#endif
/*
* Copyright (C) 2009, Pino Toscano <pino@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "poppler-font.h"
#include "poppler-document-private.h"
#include "FontInfo.h"