~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/qt4/src/poppler-document.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* poppler-document.cc: qt interface to poppler
 
2
 * Copyright (C) 2005, Net Integration Technologies, Inc.
 
3
 * Copyright (C) 2005, 2008, Brad Hards <bradh@frogmouth.net>
 
4
 * Copyright (C) 2005-2010, Albert Astals Cid <aacid@kde.org>
 
5
 * Copyright (C) 2006-2010, Pino Toscano <pino@kde.org>
 
6
 * Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2, or (at your option)
 
11
 * any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
21
 */
 
22
 
 
23
#include "poppler-qt4.h"
 
24
 
 
25
#include <config.h>
 
26
#include <ErrorCodes.h>
 
27
#include <GlobalParams.h>
 
28
#include <Outline.h>
 
29
#include <PDFDoc.h>
 
30
#include <Stream.h>
 
31
#include <Catalog.h>
 
32
#include <DateInfo.h>
 
33
#include <GfxState.h>
 
34
 
 
35
#include <QtCore/QDebug>
 
36
#include <QtCore/QFile>
 
37
#include <QtCore/QByteArray>
 
38
 
 
39
#include "poppler-private.h"
 
40
#include "poppler-page-private.h"
 
41
 
 
42
#if defined(USE_CMS)
 
43
#include <lcms.h>
 
44
#endif
 
45
 
 
46
namespace Poppler {
 
47
 
 
48
  int DocumentData::count = 0;
 
49
 
 
50
  Document *Document::load(const QString &filePath, const QByteArray &ownerPassword,
 
51
                           const QByteArray &userPassword)
 
52
    {
 
53
        DocumentData *doc = new DocumentData(new GooString(QFile::encodeName(filePath)), 
 
54
                                             new GooString(ownerPassword.data()),
 
55
                                             new GooString(userPassword.data()));
 
56
        return DocumentData::checkDocument(doc);
 
57
    }
 
58
 
 
59
    Document *Document::loadFromData(const QByteArray &fileContents,
 
60
                              const QByteArray &ownerPassword,
 
61
                              const QByteArray &userPassword)
 
62
    {
 
63
        // create stream
 
64
        DocumentData *doc = new DocumentData(fileContents,
 
65
                                             new GooString(ownerPassword.data()),
 
66
                                             new GooString(userPassword.data()));
 
67
        return DocumentData::checkDocument(doc);
 
68
    }
 
69
    
 
70
    Document *DocumentData::checkDocument(DocumentData *doc)
 
71
    {
 
72
        Document *pdoc;
 
73
        if (doc->doc->isOk() || doc->doc->getErrorCode() == errEncrypted) {
 
74
                pdoc = new Document(doc);
 
75
                if (doc->doc->getErrorCode() == errEncrypted)
 
76
                        pdoc->m_doc->locked = true;
 
77
                else
 
78
                {
 
79
                        pdoc->m_doc->locked = false;
 
80
                        pdoc->m_doc->fillMembers();
 
81
                }
 
82
                return pdoc;
 
83
        }
 
84
        else
 
85
        {
 
86
                delete doc;
 
87
        }
 
88
        return NULL;
 
89
    }
 
90
 
 
91
    Document::Document(DocumentData *dataA)
 
92
    {
 
93
        m_doc = dataA;
 
94
    }
 
95
 
 
96
    Document::~Document()
 
97
    {
 
98
        delete m_doc;
 
99
    }
 
100
 
 
101
    Page *Document::page(int index) const
 
102
    {
 
103
        Page *page = new Page(m_doc, index);
 
104
        if (page->m_page->page == NULL) {
 
105
          delete page;
 
106
          return NULL;
 
107
        }
 
108
 
 
109
        return page;
 
110
    }
 
111
 
 
112
    bool Document::isLocked() const
 
113
    {
 
114
        return m_doc->locked;
 
115
    }
 
116
 
 
117
    bool Document::unlock(const QByteArray &ownerPassword,
 
118
                          const QByteArray &userPassword)
 
119
    {
 
120
        if (m_doc->locked) {
 
121
            /* racier then it needs to be */
 
122
            DocumentData *doc2;
 
123
            if (!m_doc->fileContents.isEmpty())
 
124
            {
 
125
                doc2 = new DocumentData(m_doc->fileContents,
 
126
                                        new GooString(ownerPassword.data()),
 
127
                                        new GooString(userPassword.data()));
 
128
            }
 
129
            else
 
130
            {
 
131
                doc2 = new DocumentData(new GooString(m_doc->doc->getFileName()),
 
132
                                        new GooString(ownerPassword.data()),
 
133
                                        new GooString(userPassword.data()));
 
134
            }
 
135
            if (!doc2->doc->isOk()) {
 
136
                delete doc2;
 
137
            } else {
 
138
                delete m_doc;
 
139
                m_doc = doc2;
 
140
                m_doc->locked = false;
 
141
                m_doc->fillMembers();
 
142
            }
 
143
        }
 
144
        return m_doc->locked;
 
145
    }
 
146
 
 
147
    Document::PageMode Document::pageMode() const
 
148
    {
 
149
        switch (m_doc->doc->getCatalog()->getPageMode()) {
 
150
        case Catalog::pageModeNone:
 
151
            return UseNone;
 
152
        case Catalog::pageModeOutlines:
 
153
            return UseOutlines;
 
154
        case Catalog::pageModeThumbs:
 
155
            return UseThumbs;
 
156
        case Catalog::pageModeFullScreen:
 
157
            return FullScreen;
 
158
        case Catalog::pageModeOC:
 
159
            return UseOC;
 
160
        case Catalog::pageModeAttach:
 
161
            return UseAttach;
 
162
        default:
 
163
            return UseNone;
 
164
        }
 
165
    }
 
166
 
 
167
    Document::PageLayout Document::pageLayout() const
 
168
    {
 
169
        switch (m_doc->doc->getCatalog()->getPageLayout()) {
 
170
        case Catalog::pageLayoutNone:
 
171
            return NoLayout;
 
172
        case Catalog::pageLayoutSinglePage:
 
173
            return SinglePage;
 
174
        case Catalog::pageLayoutOneColumn:
 
175
            return OneColumn;
 
176
        case Catalog::pageLayoutTwoColumnLeft:
 
177
            return TwoColumnLeft;
 
178
        case Catalog::pageLayoutTwoColumnRight:
 
179
            return TwoColumnRight;
 
180
        case Catalog::pageLayoutTwoPageLeft:
 
181
            return TwoPageLeft;
 
182
        case Catalog::pageLayoutTwoPageRight:
 
183
            return TwoPageRight;
 
184
        default:
 
185
            return NoLayout;
 
186
        }
 
187
    }
 
188
 
 
189
    int Document::numPages() const
 
190
    {
 
191
        return m_doc->doc->getNumPages();
 
192
    }
 
193
 
 
194
    QList<FontInfo> Document::fonts() const
 
195
    {
 
196
        QList<FontInfo> ourList;
 
197
        FontIterator it( 0, m_doc );
 
198
        while ( it.hasNext() )
 
199
        {
 
200
                ourList += it.next();
 
201
        }
 
202
        return ourList;
 
203
    }
 
204
 
 
205
    QList<EmbeddedFile*> Document::embeddedFiles() const
 
206
    {
 
207
        return m_doc->m_embeddedFiles;
 
208
    }
 
209
 
 
210
    bool Document::scanForFonts( int numPages, QList<FontInfo> *fontList ) const
 
211
    {
 
212
        if ( !m_doc->m_fontInfoIterator )
 
213
                return false;
 
214
        if ( !m_doc->m_fontInfoIterator->hasNext() )
 
215
                return false;
 
216
        while ( m_doc->m_fontInfoIterator->hasNext() && numPages )
 
217
        {
 
218
                (*fontList) += m_doc->m_fontInfoIterator->next();
 
219
                --numPages;
 
220
        }
 
221
        return true;
 
222
    }
 
223
 
 
224
    FontIterator* Document::newFontIterator( int startPage ) const
 
225
    {
 
226
        return new FontIterator( startPage, m_doc );
 
227
    }
 
228
 
 
229
    QByteArray Document::fontData(const FontInfo &fi) const
 
230
    {
 
231
        QByteArray result;
 
232
        if (fi.isEmbedded())
 
233
        {
 
234
                Object refObj, strObj;
 
235
                refObj.initRef(fi.m_data->embRef.num, fi.m_data->embRef.gen);
 
236
                refObj.fetch(m_doc->doc->getXRef(), &strObj);
 
237
                refObj.free();
 
238
                if (strObj.isStream())
 
239
                {
 
240
                        int c;
 
241
                        strObj.streamReset();
 
242
                        while ((c = strObj.streamGetChar()) != EOF)
 
243
                        {
 
244
                                result.append((char)c);
 
245
                        }
 
246
                        strObj.streamClose();
 
247
                }
 
248
                strObj.free();
 
249
        }
 
250
        return result;
 
251
    }
 
252
 
 
253
    /* borrowed from kpdf */
 
254
    QString Document::info( const QString & type ) const
 
255
    {
 
256
        // [Albert] Code adapted from pdfinfo.cc on xpdf
 
257
        Object info;
 
258
        if ( m_doc->locked )
 
259
            return QString();
 
260
 
 
261
        m_doc->doc->getDocInfo( &info );
 
262
        if ( !info.isDict() )
 
263
            return QString();
 
264
 
 
265
        QString result;
 
266
        Object obj;
 
267
        GooString *s1;
 
268
        Dict *infoDict = info.getDict();
 
269
 
 
270
        if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
 
271
        {
 
272
            s1 = obj.getString();
 
273
            result = UnicodeParsedString(s1);
 
274
            obj.free();
 
275
            info.free();
 
276
            return result;
 
277
        }
 
278
        obj.free();
 
279
        info.free();
 
280
        return QString();
 
281
    }
 
282
 
 
283
    QStringList Document::infoKeys() const
 
284
    {
 
285
        QStringList keys;
 
286
 
 
287
        Object info;
 
288
        if ( m_doc->locked )
 
289
            return QStringList();
 
290
 
 
291
        m_doc->doc->getDocInfo( &info );
 
292
        if ( !info.isDict() )
 
293
            return QStringList();
 
294
 
 
295
        Dict *infoDict = info.getDict();
 
296
        // somehow iterate over keys in infoDict
 
297
        for( int i=0; i < infoDict->getLength(); ++i ) {
 
298
            keys.append( QString::fromAscii(infoDict->getKey(i)) );
 
299
        }
 
300
 
 
301
        info.free();
 
302
        return keys;
 
303
    }
 
304
 
 
305
    /* borrowed from kpdf */
 
306
    QDateTime Document::date( const QString & type ) const
 
307
    {
 
308
        // [Albert] Code adapted from pdfinfo.cc on xpdf
 
309
        if ( m_doc->locked )
 
310
            return QDateTime();
 
311
 
 
312
        Object info;
 
313
        m_doc->doc->getDocInfo( &info );
 
314
        if ( !info.isDict() ) {
 
315
            info.free();
 
316
            return QDateTime();
 
317
        }
 
318
 
 
319
        Object obj;
 
320
        Dict *infoDict = info.getDict();
 
321
        QDateTime result;
 
322
 
 
323
        if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
 
324
        {
 
325
            char *aux = obj.getString()->getCString();
 
326
            result = Poppler::convertDate(aux);
 
327
        }
 
328
        obj.free();
 
329
        info.free();
 
330
        return result;
 
331
    }
 
332
 
 
333
    bool Document::isEncrypted() const
 
334
    {
 
335
        return m_doc->doc->isEncrypted();
 
336
    }
 
337
 
 
338
    bool Document::isLinearized() const
 
339
    {
 
340
        return m_doc->doc->isLinearized();
 
341
    }
 
342
 
 
343
    bool Document::okToPrint() const
 
344
    {
 
345
        return m_doc->doc->okToPrint();
 
346
    }
 
347
 
 
348
    bool Document::okToPrintHighRes() const
 
349
    {
 
350
        return m_doc->doc->okToPrintHighRes();
 
351
    }
 
352
 
 
353
    bool Document::okToChange() const
 
354
    {
 
355
        return m_doc->doc->okToChange();
 
356
    }
 
357
 
 
358
    bool Document::okToCopy() const
 
359
    {
 
360
        return m_doc->doc->okToCopy();
 
361
    }
 
362
 
 
363
    bool Document::okToAddNotes() const
 
364
    {
 
365
        return m_doc->doc->okToAddNotes();
 
366
    }
 
367
 
 
368
    bool Document::okToFillForm() const
 
369
    {
 
370
        return m_doc->doc->okToFillForm();
 
371
    }
 
372
 
 
373
    bool Document::okToCreateFormFields() const
 
374
    {
 
375
        return ( okToFillForm() && okToChange() );
 
376
    }
 
377
 
 
378
    bool Document::okToExtractForAccessibility() const
 
379
    {
 
380
        return m_doc->doc->okToAccessibility();
 
381
    }
 
382
 
 
383
    bool Document::okToAssemble() const
 
384
    {
 
385
        return m_doc->doc->okToAssemble();
 
386
    }
 
387
 
 
388
    double Document::pdfVersion() const
 
389
    {
 
390
        return m_doc->doc->getPDFMajorVersion () + m_doc->doc->getPDFMinorVersion() / 10.0;
 
391
    }
 
392
 
 
393
    void Document::getPdfVersion(int *major, int *minor) const
 
394
    {
 
395
        if (major)
 
396
            *major = m_doc->doc->getPDFMajorVersion();
 
397
        if (minor)
 
398
            *minor = m_doc->doc->getPDFMinorVersion();
 
399
    }
 
400
 
 
401
    Page *Document::page(const QString &label) const
 
402
    {
 
403
        GooString label_g(label.toAscii().data());
 
404
        int index;
 
405
 
 
406
        if (!m_doc->doc->getCatalog()->labelToIndex (&label_g, &index))
 
407
            return NULL;
 
408
 
 
409
        return page(index);
 
410
    }
 
411
 
 
412
    bool Document::hasEmbeddedFiles() const
 
413
    {
 
414
        return (!(0 == m_doc->doc->getCatalog()->numEmbeddedFiles()));
 
415
    }
 
416
    
 
417
    QDomDocument *Document::toc() const
 
418
    {
 
419
        Outline * outline = m_doc->doc->getOutline();
 
420
        if ( !outline )
 
421
            return NULL;
 
422
 
 
423
        GooList * items = outline->getItems();
 
424
        if ( !items || items->getLength() < 1 )
 
425
            return NULL;
 
426
 
 
427
        QDomDocument *toc = new QDomDocument();
 
428
        if ( items->getLength() > 0 )
 
429
           m_doc->addTocChildren( toc, toc, items );
 
430
 
 
431
        return toc;
 
432
    }
 
433
 
 
434
    LinkDestination *Document::linkDestination( const QString &name )
 
435
    {
 
436
        GooString * namedDest = QStringToGooString( name );
 
437
        LinkDestinationData ldd(NULL, namedDest, m_doc, false);
 
438
        LinkDestination *ld = new LinkDestination(ldd);
 
439
        delete namedDest;
 
440
        return ld;
 
441
    }
 
442
    
 
443
    void Document::setPaperColor(const QColor &color)
 
444
    {
 
445
        m_doc->setPaperColor(color);
 
446
    }
 
447
    
 
448
    void Document::setColorDisplayProfile(void* outputProfileA)
 
449
    {
 
450
#if defined(USE_CMS)
 
451
        GfxColorSpace::setDisplayProfile((cmsHPROFILE)outputProfileA);
 
452
#else
 
453
        Q_UNUSED(outputProfileA);
 
454
#endif
 
455
    }
 
456
 
 
457
    void Document::setColorDisplayProfileName(const QString &name)
 
458
    {
 
459
#if defined(USE_CMS)
 
460
        GooString *profileName = QStringToGooString( name );
 
461
        GfxColorSpace::setDisplayProfileName(profileName);
 
462
        delete profileName;
 
463
#else
 
464
        Q_UNUSED(name);
 
465
#endif
 
466
    }
 
467
 
 
468
    void* Document::colorRgbProfile() const
 
469
    {
 
470
#if defined(USE_CMS)
 
471
        return (void*)GfxColorSpace::getRGBProfile();
 
472
#else
 
473
        return NULL;
 
474
#endif
 
475
    }
 
476
 
 
477
    void* Document::colorDisplayProfile() const
 
478
    {
 
479
#if defined(USE_CMS)
 
480
       return (void*)GfxColorSpace::getDisplayProfile();
 
481
#else
 
482
       return NULL;
 
483
#endif
 
484
    }
 
485
 
 
486
    QColor Document::paperColor() const
 
487
    {
 
488
        return m_doc->paperColor;
 
489
    }
 
490
 
 
491
    void Document::setRenderBackend( Document::RenderBackend backend )
 
492
    {
 
493
        // no need to delete the outputdev as for the moment we always create a splash one
 
494
        // as the arthur one does not allow "precaching" due to it's signature
 
495
        // delete m_doc->m_outputDev;
 
496
        // m_doc->m_outputDev = NULL;
 
497
        m_doc->m_backend = backend;
 
498
    }
 
499
 
 
500
    Document::RenderBackend Document::renderBackend() const
 
501
    {
 
502
        return m_doc->m_backend;
 
503
    }
 
504
 
 
505
    QSet<Document::RenderBackend> Document::availableRenderBackends()
 
506
    {
 
507
        QSet<Document::RenderBackend> ret;
 
508
#if defined(HAVE_SPLASH)
 
509
        ret << Document::SplashBackend;
 
510
#endif
 
511
        ret << Document::ArthurBackend;
 
512
        return ret;
 
513
    }
 
514
 
 
515
    void Document::setRenderHint( Document::RenderHint hint, bool on )
 
516
    {
 
517
        if ( on )
 
518
            m_doc->m_hints |= hint;
 
519
        else
 
520
            m_doc->m_hints &= ~(int)hint;
 
521
 
 
522
        // the only way to set antialiasing for Splash is on creation
 
523
        if ( m_doc->m_backend == Document::SplashBackend &&
 
524
             ( hint & ( Document::Antialiasing || Document::TextAntialiasing || Document::TextHinting ) ) )
 
525
        {
 
526
            delete m_doc->m_outputDev;
 
527
            m_doc->m_outputDev = NULL;
 
528
        }
 
529
    }
 
530
 
 
531
    Document::RenderHints Document::renderHints() const
 
532
    {
 
533
        return Document::RenderHints( m_doc->m_hints );
 
534
    }
 
535
 
 
536
    PSConverter *Document::psConverter() const
 
537
    {
 
538
        return new PSConverter(m_doc);
 
539
    }
 
540
 
 
541
    PDFConverter *Document::pdfConverter() const
 
542
    {
 
543
        return new PDFConverter(m_doc);
 
544
    }
 
545
 
 
546
    QString Document::metadata() const
 
547
    {
 
548
        QString result;
 
549
        Catalog *catalog = m_doc->doc->getCatalog();
 
550
        if (catalog && catalog->isOk())
 
551
        {
 
552
            GooString *s = catalog->readMetadata();
 
553
            if (s) result = UnicodeParsedString(s);
 
554
            delete s;
 
555
        }
 
556
        return result;
 
557
    }
 
558
 
 
559
    bool Document::hasOptionalContent() const
 
560
    {
 
561
        return ( m_doc->doc->getOptContentConfig() && m_doc->doc->getOptContentConfig()->hasOCGs() );
 
562
    }
 
563
 
 
564
    OptContentModel *Document::optionalContentModel()
 
565
    {
 
566
        if (m_doc->m_optContentModel.isNull()) {
 
567
            m_doc->m_optContentModel = new OptContentModel(m_doc->doc->getOptContentConfig(), 0);
 
568
        }
 
569
        return (OptContentModel *)m_doc->m_optContentModel;
 
570
    }
 
571
 
 
572
    QStringList Document::scripts() const
 
573
    {
 
574
        Catalog *catalog = m_doc->doc->getCatalog();
 
575
        const int numScripts = catalog->numJS();
 
576
        QStringList scripts;
 
577
        for (int i = 0; i < numScripts; ++i) {
 
578
            GooString *s = catalog->getJS(i);
 
579
            if (s) {
 
580
                scripts.append(UnicodeParsedString(s));
 
581
                delete s;
 
582
            }
 
583
        }
 
584
        return scripts;
 
585
    }
 
586
 
 
587
    bool Document::getPdfId(QByteArray *permanentId, QByteArray *updateId) const
 
588
    {
 
589
        GooString gooPermanentId;
 
590
        GooString gooUpdateId;
 
591
 
 
592
        if (!m_doc->doc->getID(permanentId ? &gooPermanentId : 0, updateId ? &gooUpdateId : 0))
 
593
            return false;
 
594
 
 
595
        if (permanentId)
 
596
            *permanentId = gooPermanentId.getCString();
 
597
        if (updateId)
 
598
            *updateId = gooUpdateId.getCString();
 
599
 
 
600
        return true;
 
601
    }
 
602
 
 
603
    QDateTime convertDate( char *dateString )
 
604
    {
 
605
        int year, mon, day, hour, min, sec, tzHours, tzMins;
 
606
        char tz;
 
607
 
 
608
        if ( parseDateString( dateString, &year, &mon, &day, &hour, &min, &sec, &tz, &tzHours, &tzMins ) )
 
609
        {
 
610
            QDate d( year, mon, day );
 
611
            QTime t( hour, min, sec );
 
612
            if ( d.isValid() && t.isValid() ) {
 
613
                QDateTime dt( d, t, Qt::UTC );
 
614
                if ( tz ) {
 
615
                    // then we have some form of timezone
 
616
                    if ( 'Z' == tz  ) {
 
617
                        // We are already at UTC
 
618
                    } else if ( '+' == tz ) {
 
619
                        // local time is ahead of UTC
 
620
                        dt = dt.addSecs(-1*((tzHours*60)+tzMins)*60);
 
621
                    } else if ( '-' == tz ) {
 
622
                        // local time is behind UTC
 
623
                        dt = dt.addSecs(((tzHours*60)+tzMins)*60);
 
624
                    } else {
 
625
                        qWarning("unexpected tz val");
 
626
                    }
 
627
                }
 
628
                return dt;
 
629
            }
 
630
        }
 
631
        return QDateTime();
 
632
    }
 
633
 
 
634
    bool isCmsAvailable()
 
635
    {
 
636
#if defined(USE_CMS)
 
637
        return true;
 
638
#else
 
639
        return false;
 
640
#endif
 
641
    }
 
642
 
 
643
}