1
/* poppler-private.cc: qt interface to poppler
2
* Copyright (C) 2005, Net Integration Technologies, Inc.
3
* Copyright (C) 2006, 2011 by Albert Astals Cid <aacid@kde.org>
4
* Copyright (C) 2008, 2010, 2011 by Pino Toscano <pino@kde.org>
6
* Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
7
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2, or (at your option)
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
24
#include "poppler-private.h"
26
#include <QtCore/QByteArray>
27
#include <QtCore/QDebug>
28
#include <QtCore/QVariant>
32
#include <UnicodeMap.h>
38
void qDebugDebugFunction(const QString &message, const QVariant & /*closure*/)
43
PopplerDebugFunc debugFunction = qDebugDebugFunction;
44
QVariant debugClosure;
48
static UnicodeMap *utf8Map = 0;
50
void setDebugErrorFunction(PopplerDebugFunc function, const QVariant &closure)
52
Debug::debugFunction = function ? function : Debug::qDebugDebugFunction;
53
Debug::debugClosure = closure;
56
void qt4ErrorFunction(int pos, char *msg, va_list args)
59
char buffer[1024]; // should be big enough
63
emsg = QString::fromLatin1("Error (%1): ").arg(pos);
67
emsg = QString::fromLatin1("Error: ");
69
qvsnprintf(buffer, sizeof(buffer) - 1, msg, args);
70
emsg += QString::fromAscii(buffer);
71
(*Debug::debugFunction)(emsg, Debug::debugClosure);
74
QString unicodeToQString(Unicode* u, int len) {
77
GooString enc("UTF-8");
78
utf8Map = globalParams->getUnicodeMap(&enc);
82
// ignore the last character if it is 0x0
83
if ((len > 0) && (u[len - 1] == 0))
88
GooString convertedStr;
89
for (int i = 0; i < len; ++i)
92
const int n = utf8Map->mapUnicode(u[i], buf, sizeof(buf));
93
convertedStr.append(buf, n);
96
return QString::fromUtf8(convertedStr.getCString(), convertedStr.getLength());
99
QString UnicodeParsedString(GooString *s1) {
100
if ( !s1 || s1->getLength() == 0 )
107
if ( ( s1->getChar(0) & 0xff ) == 0xfe && ( s1->getLength() > 1 && ( s1->getChar(1) & 0xff ) == 0xff ) )
111
result.reserve( ( s1->getLength() - 2 ) / 2 );
117
result.reserve( s1->getLength() );
119
while ( i < s1->getLength() )
123
u = ( ( s1->getChar(i) & 0xff ) << 8 ) | ( s1->getChar(i+1) & 0xff );
128
u = s1->getChar(i) & 0xff;
131
result += QChar( u );
136
GooString *QStringToUnicodeGooString(const QString &s) {
137
int len = s.length() * 2 + 2;
138
char *cstring = (char *)gmallocn(len, sizeof(char));
141
for (int i = 0; i < s.length(); ++i)
143
cstring[2+i*2] = s.at(i).row();
144
cstring[3+i*2] = s.at(i).cell();
146
GooString *ret = new GooString(cstring, len);
151
GooString *QStringToGooString(const QString &s) {
152
int len = s.length();
153
char *cstring = (char *)gmallocn(s.length(), sizeof(char));
154
for (int i = 0; i < len; ++i)
155
cstring[i] = s.at(i).unicode();
156
GooString *ret = new GooString(cstring, len);
161
void linkActionToTocItem( ::LinkAction * a, DocumentData * doc, QDomElement * e )
166
switch ( a->getKind() )
170
// page number is contained/referenced in a LinkGoTo
171
LinkGoTo * g = static_cast< LinkGoTo * >( a );
172
LinkDest * destination = g->getDest();
173
if ( !destination && g->getNamedDest() )
175
// no 'destination' but an internal 'named reference'. we could
176
// get the destination for the page now, but it's VERY time consuming,
177
// so better storing the reference and provide the viewport on demand
178
GooString *s = g->getNamedDest();
179
QChar *charArray = new QChar[s->getLength()];
180
for (int i = 0; i < s->getLength(); ++i) charArray[i] = QChar(s->getCString()[i]);
181
QString aux(charArray, s->getLength());
182
e->setAttribute( "DestinationName", aux );
185
else if ( destination && destination->isOk() )
187
LinkDestinationData ldd(destination, NULL, doc, false);
188
e->setAttribute( "Destination", LinkDestination(ldd).toString() );
194
// page number is contained/referenced in a LinkGoToR
195
LinkGoToR * g = static_cast< LinkGoToR * >( a );
196
LinkDest * destination = g->getDest();
197
if ( !destination && g->getNamedDest() )
199
// no 'destination' but an internal 'named reference'. we could
200
// get the destination for the page now, but it's VERY time consuming,
201
// so better storing the reference and provide the viewport on demand
202
GooString *s = g->getNamedDest();
203
QChar *charArray = new QChar[s->getLength()];
204
for (int i = 0; i < s->getLength(); ++i) charArray[i] = QChar(s->getCString()[i]);
205
QString aux(charArray, s->getLength());
206
e->setAttribute( "DestinationName", aux );
209
else if ( destination && destination->isOk() )
211
LinkDestinationData ldd(destination, NULL, doc, g->getFileName() != 0);
212
e->setAttribute( "Destination", LinkDestination(ldd).toString() );
214
e->setAttribute( "ExternalFileName", g->getFileName()->getCString() );
219
LinkURI * u = static_cast< LinkURI * >( a );
220
e->setAttribute( "DestinationURI", u->getURI()->getCString() );
226
DocumentData::~DocumentData()
228
qDeleteAll(m_embeddedFiles);
229
delete (OptContentModel *)m_optContentModel;
232
delete m_fontInfoIterator;
242
void DocumentData::init(GooString *ownerPassword, GooString *userPassword)
244
m_fontInfoIterator = 0;
245
m_backend = Document::SplashBackend;
247
paperColor = Qt::white;
249
m_optContentModel = 0;
250
// It might be more appropriate to delete these in PDFDoc
251
delete ownerPassword;
257
globalParams = new GlobalParams();
258
setErrorFunction(qt4ErrorFunction);
264
void DocumentData::addTocChildren( QDomDocument * docSyn, QDomNode * parent, GooList * items )
266
int numItems = items->getLength();
267
for ( int i = 0; i < numItems; ++i )
269
// iterate over every object in 'items'
270
OutlineItem * outlineItem = (OutlineItem *)items->get( i );
272
// 1. create element using outlineItem's title as tagName
274
Unicode * uniChar = outlineItem->getTitle();
275
int titleLength = outlineItem->getTitleLength();
276
name = unicodeToQString(uniChar, titleLength);
277
if ( name.isEmpty() )
280
QDomElement item = docSyn->createElement( name );
281
parent->appendChild( item );
283
// 2. find the page the link refers to
284
::LinkAction * a = outlineItem->getAction();
285
linkActionToTocItem( a, this, &item );
287
item.setAttribute( "Open", QVariant( (bool)outlineItem->isOpen() ).toString() );
289
// 3. recursively descend over children
291
GooList * children = outlineItem->getKids();
293
addTocChildren( docSyn, &item, children );