/* poppler-document.cc: qt interface to poppler * Copyright (C) 2005, Net Integration Technologies, Inc. * Copyright (C) 2005-2009, Albert Astals Cid * Copyright (C) 2006, Stefan Kebekus * Copyright (C) 2006, Wilfried Huss * * 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 #include #include #include #include #include #include #include #include #include #include #include #include "poppler-private.h" #if !defined(HAVE_POPPLER_071) #undef bool #endif namespace Poppler { Document *Document::load(const TQString &filePath) { if (!globalParams) { globalParams = new GlobalParams(); } DocumentData *doc = new DocumentData(new GooString(TQFile::encodeName(filePath)), NULL); Document *pdoc; if (doc->doc.isOk() || doc->doc.getErrorCode() == errEncrypted) { pdoc = new Document(doc); if (doc->doc.getErrorCode() == errEncrypted) pdoc->data->locked = true; else pdoc->data->locked = false; pdoc->data->m_fontInfoScanner = new FontInfoScanner(&(doc->doc)); return pdoc; } else return NULL; } Document::Document(DocumentData *dataA) { data = dataA; } Document::~Document() { delete data; } bool Document::isLocked() const { return data->locked; } bool Document::unlock(const TQCString &password) { if (data->locked) { /* racier then it needs to be */ GooString *filename = new GooString(data->doc.getFileName()); GooString *pwd = new GooString(password.data()); DocumentData *doc2 = new DocumentData(filename, pwd); delete pwd; if (!doc2->doc.isOk()) { delete doc2; } else { delete data; data = doc2; data->locked = false; data->m_fontInfoScanner = new FontInfoScanner(&(data->doc)); } } return data->locked; } Document::PageMode Document::getPageMode(void) const { switch (data->doc.getCatalog()->getPageMode()) { case Catalog::pageModeNone: return UseNone; case Catalog::pageModeOutlines: return UseOutlines; case Catalog::pageModeThumbs: return UseThumbs; case Catalog::pageModeFullScreen: return FullScreen; case Catalog::pageModeOC: return UseOC; default: return UseNone; } } int Document::getNumPages() const { return data->doc.getNumPages(); } TQValueList Document::fonts() const { TQValueList ourList; scanForFonts(getNumPages(), &ourList); return ourList; } bool Document::scanForFonts( int numPages, TQValueList *fontList ) const { GooList *items = data->m_fontInfoScanner->scan( numPages ); if ( NULL == items ) return false; for ( int i = 0; i < items->getLength(); ++i ) { TQString fontName; if (((::FontInfo*)items->get(i))->getName()) fontName = ((::FontInfo*)items->get(i))->getName()->GOO_GET_CSTR(); FontInfo font(fontName, ((::FontInfo*)items->get(i))->getEmbedded(), ((::FontInfo*)items->get(i))->getSubset(), (Poppler::FontInfo::Type)((::FontInfo*)items->get(i))->getType()); fontList->append(font); } # if defined(HAVE_POPPLER_070) deleteGooList<::FontInfo>(items); # else deleteGooList(items, ::FontInfo); # endif return true; } /* borrowed from kpdf */ TQString Document::getInfo( const TQString & type ) const { // [Albert] Code adapted from pdfinfo.cc on xpdf Object info; if ( data->locked ) return NULL; # if defined(HAVE_POPPLER_058) info = data->doc.getDocInfo(); # else data->doc.getDocInfo( &info ); # endif if ( !info.isDict() ) return NULL; TQString result; Object obj; CONST_064 GooString *s1; GBool isUnicode; Unicode u; int i; Dict *infoDict = info.getDict(); #if defined(HAVE_POPPLER_058) obj = infoDict->lookup( (char*)type.latin1() ); #else infoDict->lookup( (char*)type.latin1(), &obj ); #endif if (!obj.isNull() && obj.isString()) { s1 = obj.getString(); if ( ( s1->getChar(0) & 0xff ) == 0xfe && ( s1->getChar(1) & 0xff ) == 0xff ) { isUnicode = gTrue; i = 2; } else { isUnicode = gFalse; i = 0; } while ( i < obj.getString()->getLength() ) { if ( isUnicode ) { u = ( ( s1->getChar(i) & 0xff ) << 8 ) | ( s1->getChar(i+1) & 0xff ); i += 2; } else { u = s1->getChar(i) & 0xff; ++i; } result += unicodeToTQString( &u, 1 ); } # if !defined(HAVE_POPPLER_058) obj.free(); info.free(); # endif return result; } # if !defined(HAVE_POPPLER_058) obj.free(); info.free(); # endif return NULL; } /* borrowed from kpdf */ TQDateTime Document::getDate( const TQString & type ) const { // [Albert] Code adapted from pdfinfo.cc on xpdf if ( data->locked ) return TQDateTime(); Object info; # if defined(HAVE_POPPLER_058) info = data->doc.getDocInfo(); # else data->doc.getDocInfo( &info ); # endif if ( !info.isDict() ) { # if !defined(HAVE_POPPLER_058) info.free(); # endif return TQDateTime(); } Object obj; int year, mon, day, hour, min, sec, tz_hour, tz_minute; char tz; Dict *infoDict = info.getDict(); TQString result; #if defined(HAVE_POPPLER_058) obj = infoDict->lookup( (char*)type.latin1() ); #else infoDict->lookup( (char*)type.latin1(), &obj ); #endif if (!obj.isNull() && obj.isString()) { TQString s = UnicodeParsedString(obj.getString()); // TODO do something with the timezone information if ( parseDateString( s.latin1(), &year, &mon, &day, &hour, &min, &sec, &tz, &tz_hour, &tz_minute ) ) { TQDate d( year, mon, day ); //CHECK: it was mon-1, Jan->0 (??) TQTime t( hour, min, sec ); if ( d.isValid() && t.isValid() ) { # if !defined(HAVE_POPPLER_058) obj.free(); info.free(); # endif return TQDateTime( d, t ); } } } # if !defined(HAVE_POPPLER_058) obj.free(); info.free(); # endif return TQDateTime(); } bool Document::isEncrypted() const { return data->doc.isEncrypted(); } bool Document::isLinearized() const { return data->doc.isLinearized(); } bool Document::okToPrint() const { return data->doc.okToPrint(); } bool Document::okToChange() const { return data->doc.okToChange(); } bool Document::okToCopy() const { return data->doc.okToCopy(); } bool Document::okToAddNotes() const { return data->doc.okToAddNotes(); } double Document::getPDFVersion() const { return data->doc.getPDFMajorVersion () + data->doc.getPDFMinorVersion() / 10.0; } void Document::getPdfVersion(int *major, int *minor) const { if (major) *major = data->doc.getPDFMajorVersion(); if (minor) *minor = data->doc.getPDFMinorVersion(); } TQDomDocument *Document::toc() const { Outline * outline = data->doc.getOutline(); if ( !outline ) return NULL; CONST_064 GooList * items = outline->getItems(); if ( !items || items->getLength() < 1 ) return NULL; TQDomDocument *toc = new TQDomDocument(); if ( items->getLength() > 0 ) data->addTocChildren( toc, toc, items ); return toc; } LinkDestination *Document::linkDestination( const TQString &name ) { GooString * namedDest = TQStringToGooString( name ); LinkDestinationData ldd(NULL, namedDest, data); LinkDestination *ld = new LinkDestination(ldd); delete namedDest; return ld; } bool Document::print(const TQString &fileName, TQValueList pageList, double hDPI, double vDPI, int rotate) { return print(fileName, pageList, hDPI, vDPI, rotate, -1, -1); } bool Document::print(const TQString &file, TQValueList pageList, double hDPI, double vDPI, int rotate, int paperWidth, int paperHeight) { #if defined(HAVE_POPPLER_058) || defined(HAVE_POPPLER_030) std::vector pages; TQValueList::iterator it; for (it = pageList.begin(); it != pageList.end(); ++it ) { pages.push_back(*it); } PSOutputDev *psOut = new PSOutputDev(file.latin1(), &(data->doc), NULL, pages, psModePS, paperWidth, paperHeight); #elif defined(HAVE_POPPLER_020) PSOutputDev *psOut = new PSOutputDev(file.latin1(), &(data->doc), NULL, 1, data->doc.getNumPages(), psModePS, paperWidth, paperHeight); #elif defined(HAVE_POPPLER_016) PSOutputDev *psOut = new PSOutputDev(file.latin1(), &(data->doc), data->doc.getXRef(), data->doc.getCatalog(), NULL, 1, data->doc.getNumPages(), psModePS, paperWidth, paperHeight); #else PSOutputDev *psOut = new PSOutputDev(file.latin1(), data->doc.getXRef(), data->doc.getCatalog(), NULL, 1, data->doc.getNumPages(), psModePS, paperWidth, paperHeight); #endif if (psOut->isOk()) { TQValueList::iterator it; for (it = pageList.begin(); it != pageList.end(); ++it ) data->doc.displayPage(psOut, *it, hDPI, vDPI, rotate, gFalse, gTrue, gTrue); delete psOut; return true; } else { delete psOut; return false; } } }