From bdfb693d3e1ea36e86d66067370d7677d1e864f5 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 16 Mar 2005 21:52:28 +0000 Subject: [PATCH] Welcome the fonts dialog, as normal the from xpdf source is our inspiration, this time pdffonts.cc Enrico, maybe you don't like the way of filling the KListView, the properties dialog asks the document if it has fonts (in the future maybe we support formats that don't have fonts), then create the KListView and pass it to the document that passes it to the generator that fills it, the "problem" is that now the generators are GUI aware. svn path=/trunk/kdegraphics/kpdf/; revision=398206 --- core/document.cpp | 10 ++ core/document.h | 3 + core/generator.h | 5 + core/generator_pdf/generator_pdf.cpp | 184 +++++++++++++++++++++++++++ core/generator_pdf/generator_pdf.h | 10 ++ ui/propertiesdialog.cpp | 16 ++- 6 files changed, 226 insertions(+), 2 deletions(-) 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); + } }