diff --git a/core/document.cpp b/core/document.cpp index e6093cb85..09199ab1f 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -381,6 +381,16 @@ QString KPDFDocument::getMetaData( const QString & key, const QString & option ) return generator ? generator->getMetaData( key, option ) : QString(); } +bool KPDFDocument::hasFonts() const +{ + return generator ? generator->hasFonts() : false; +} + +void KPDFDocument::putFontInfo(KListView *list) +{ + if (generator) generator->putFontInfo(list); +} + void KPDFDocument::requestPixmaps( const QValueList< PixmapRequest * > & requests ) { if ( !generator ) diff --git a/core/document.h b/core/document.h index e845f94db..725a5bc39 100644 --- a/core/document.h +++ b/core/document.h @@ -24,6 +24,7 @@ class DocumentInfo; class DocumentSynopsis; class Generator; class PixmapRequest; +class KListView; class KPrinter; class KURL; @@ -75,6 +76,8 @@ class KPDFDocument : public QObject bool historyAtBegin() const; bool historyAtEnd() const; QString getMetaData( const QString & key, const QString & option = QString() ) const; + bool hasFonts() const; + void putFontInfo(KListView *list); // perform actions on document / pages void setViewportPage( int page, int excludeId = -1, bool smoothMove = false ); diff --git a/core/generator.h b/core/generator.h index 9561d8b2b..4a53a0a2b 100644 --- a/core/generator.h +++ b/core/generator.h @@ -14,6 +14,7 @@ #include #include #include "core/document.h" +class KListView; class KPrinter; class KPDFPage; class KPDFLink; @@ -58,6 +59,10 @@ class Generator : public QObject virtual void generatePixmap( PixmapRequest * request ) = 0; virtual void generateSyncTextPage( KPDFPage * page ) = 0; + // font related + virtual bool hasFonts() const = 0; + virtual void putFontInfo(KListView *list) = 0; + // print document using already configured kprinter virtual bool print( KPrinter& /*printer*/ ) { return false; } // access meta data of the generator diff --git a/core/generator_pdf/generator_pdf.cpp b/core/generator_pdf/generator_pdf.cpp index 330e6b557..65f882ae9 100644 --- a/core/generator_pdf/generator_pdf.cpp +++ b/core/generator_pdf/generator_pdf.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,9 @@ #include // xpdf includes +#include "xpdf/Object.h" +#include "xpdf/Dict.h" +#include "xpdf/Annot.h" #include "xpdf/PSOutputDev.h" #include "xpdf/TextOutputDev.h" #include "xpdf/Link.h" @@ -338,6 +342,61 @@ void PDFGenerator::generateSyncTextPage( KPDFPage * page ) docLock.unlock(); } +bool PDFGenerator::hasFonts() const +{ + return true; +} + +void PDFGenerator::putFontInfo(KListView *list) +{ + Page *page; + Dict *resDict; + Annots *annots; + Object obj1, obj2; + int pg, i; + + Ref *fonts; + int fontsLen; + int fontsSize; + + list->addColumn(i18n("Name")); + list->addColumn(i18n("Type")); + list->addColumn(i18n("Embedded")); + list->addColumn(i18n("File")); + + docLock.lock(); + + fonts = NULL; + fontsLen = fontsSize = 0; + for (pg = 1; pg <= pdfdoc->getNumPages(); ++pg) + { + page = pdfdoc->getCatalog()->getPage(pg); + if ((resDict = page->getResourceDict())) + { + scanFonts(resDict, list, &fonts, fontsLen, fontsSize); + } + annots = new Annots(pdfdoc->getXRef(), page->getAnnots(&obj1)); + obj1.free(); + for (i = 0; i < annots->getNumAnnots(); ++i) + { + if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) + { + obj1.streamGetDict()->lookup("Resources", &obj2); + if (obj2.isDict()) + { + scanFonts(obj2.getDict(), list, &fonts, fontsLen, fontsSize); + } + obj2.free(); + } + obj1.free(); + } + delete annots; + } + gfree(fonts); + + docLock.unlock(); +} + bool PDFGenerator::print( KPrinter& printer ) { QString ps = printer.option("PageSize"); @@ -467,6 +526,131 @@ static QString unicodeToQString(Unicode* u, int len) { return ret; } +void PDFGenerator::scanFonts(Dict *resDict, KListView *list, Ref **fonts, int &fontsLen, int &fontsSize) +{ + Object obj1, obj2, xObjDict, xObj, resObj; + Ref r; + GfxFontDict *gfxFontDict; + GfxFont *font; + int i; + + // scan the fonts in this resource dictionary + gfxFontDict = NULL; + resDict->lookupNF("Font", &obj1); + if (obj1.isRef()) + { + obj1.fetch(pdfdoc->getXRef(), &obj2); + if (obj2.isDict()) + { + r = obj1.getRef(); + gfxFontDict = new GfxFontDict(pdfdoc->getXRef(), &r, obj2.getDict()); + } + obj2.free(); + } + else if (obj1.isDict()) + { + gfxFontDict = new GfxFontDict(pdfdoc->getXRef(), NULL, obj1.getDict()); + } + if (gfxFontDict) + { + for (i = 0; i < gfxFontDict->getNumFonts(); ++i) + { + if ((font = gfxFontDict->getFont(i))) scanFont(font, list, fonts, fontsLen, fontsSize); + } + delete gfxFontDict; + } + obj1.free(); + + // recursively scan any resource dictionaries in objects in this + // resource dictionary + resDict->lookup("XObject", &xObjDict); + if (xObjDict.isDict()) + { + for (i = 0; i < xObjDict.dictGetLength(); ++i) + { + xObjDict.dictGetVal(i, &xObj); + if (xObj.isStream()) + { + xObj.streamGetDict()->lookup("Resources", &resObj); + if (resObj.isDict()) scanFonts(resObj.getDict(), list, fonts, fontsLen, fontsSize); + resObj.free(); + } + xObj.free(); + } + } + xObjDict.free(); +} + +void PDFGenerator::scanFont(GfxFont *font, KListView *list, Ref **fonts, int &fontsLen, int &fontsSize) +{ + Ref fontRef, embRef; + Object fontObj, toUnicodeObj; + GString *name; + GBool emb; + int i; + + QString fontTypeNames[8] = { + i18n("unknown"), + i18n("Type 1"), + i18n("Type 1C"), + i18n("Type 3"), + i18n("TrueType"), + i18n("CID Type 0"), + i18n("CID Type 0C"), + i18n("CID TrueType") + }; + + fontRef = *font->getID(); + + // check for an already-seen font + for (i = 0; i < fontsLen; ++i) + { + if (fontRef.num == (*fonts)[i].num && fontRef.gen == (*fonts)[i].gen) + { + return; + } + } + + // font name + name = font->getOrigName(); + + // check for an embedded font + if (font->getType() == fontType3) emb = gTrue; + else emb = font->getEmbeddedFontID(&embRef); + + QString sName, sEmb, sPath; + if (name) + { + sName = name->getCString(); + if (!emb) + { + DisplayFontParam *dfp = globalParams->getDisplayFont(name); + if (dfp) + { + if (dfp -> kind == displayFontT1) sPath = dfp->t1.fileName->getCString(); + else sPath = dfp->tt.fileName->getCString(); + } + else sPath = i18n("-"); + } + else sPath = i18n("-"); + } + else + { + sName = i18n("[none]"); + sPath = i18n("-"); + } + sEmb = emb ? i18n("Yes") : i18n("No"); + new KListViewItem(list, sName, fontTypeNames[font->getType()], sEmb, sPath); + + // add this font to the list + if (fontsLen == fontsSize) + { + fontsSize += 32; + *fonts = (Ref *)grealloc(*fonts, fontsSize * sizeof(Ref)); + } + (*fonts)[fontsLen++] = *font->getID(); +} + QString PDFGenerator::getDocumentInfo( const QString & data ) const // note: MUTEX is LOCKED while calling this { diff --git a/core/generator_pdf/generator_pdf.h b/core/generator_pdf/generator_pdf.h index 5e0ab076b..0a3a4e416 100644 --- a/core/generator_pdf/generator_pdf.h +++ b/core/generator_pdf/generator_pdf.h @@ -19,6 +19,9 @@ #include "core/document.h" #include "core/link.h" +class Dict; +class GfxFont; +class Ref; class PDFDoc; class GList; class TextPage; @@ -62,6 +65,10 @@ class PDFGenerator : public Generator void generatePixmap( PixmapRequest * request ); void generateSyncTextPage( KPDFPage * page ); + // font related + bool hasFonts() const; + void putFontInfo(KListView *list); + // [INHERITED] print page using an already configured kprinter bool print( KPrinter& printer ); @@ -75,6 +82,9 @@ class PDFGenerator : public Generator // friend class to access private document related variables friend class PDFPixmapGeneratorThread; + void scanFonts(Dict *resDict, KListView *list, Ref **fonts, int &fontsLen, int &fontsSize); + void scanFont(GfxFont *font, KListView *list, Ref **fonts, int &fontsLen, int &fontsSize); + // private functions for accessing document informations via PDFDoc QString getDocumentInfo( const QString & data ) const; QString getDocumentDate( const QString & data ) const; diff --git a/ui/propertiesdialog.cpp b/ui/propertiesdialog.cpp index 701e7cf99..993b0682e 100644 --- a/ui/propertiesdialog.cpp +++ b/ui/propertiesdialog.cpp @@ -9,6 +9,7 @@ // qt/kde includes #include +#include #include #include @@ -17,9 +18,10 @@ #include "core/document.h" PropertiesDialog::PropertiesDialog(QWidget *parent, KPDFDocument *doc) - : KDialogBase( Plain, i18n( "Unknown File" ), Ok, Ok, parent, 0, true, true ) + : KDialogBase( Tabbed, i18n( "Unknown File" ), Ok, Ok, parent, 0, true, true ) { - QWidget *page = plainPage(); + // Properties + QFrame *page = addPage(i18n("Properties")); QGridLayout *layout = new QGridLayout( page, 2, 2, marginHint(), spacingHint() ); // get document info, if not present display blank data and a warning @@ -59,4 +61,14 @@ PropertiesDialog::PropertiesDialog(QWidget *parent, KPDFDocument *doc) layout->addWidget( key, row, 0 ); layout->addWidget( value, row, 1 ); } + + if (doc->hasFonts()) + { + // Properties + page = addPage(i18n("Fonts")); + QVBoxLayout *topLayout = new QVBoxLayout(page, 0, KDialog::spacingHint()); + KListView *lv = new KListView(page); + topLayout->add(lv); + doc->putFontInfo(lv); + } }