Commit 8f4104a9 authored by Enrico Ros's avatar Enrico Ros

merge (refactored) patch_050,051,060

svn path=/branches/kpdf/annotations/kdegraphics/kpdf/; revision=424991
parent 04122718
......@@ -30,6 +30,7 @@ More items (first items will enter 'In progress list' first):
-> evaluate completely handling links internally instead of asking xpdf structs
-> pageview: change document viewport after mouse scrolling ended (not every scroll frame)
this will give better mvc consistancy
-> other info on pdfs properties: number of accessed times, time spent on pdf, ...
-> part: collapsing the left panel will hide it (activate hiding action)
-> preload: add a delay when forward loading pages
-> toc: add search bar (a 'prune on type' lineedit like in thumbnails widget) (BR99349)
......@@ -121,6 +122,7 @@ Done (newest features come first):
-> ADD: annotations: PDF1.6 reader (PDF's annotations -> our data structures)
-> ADD: Internal data structures for annotations handling.
-> FIX: rmb when no doc displayed to restore menu
-> ADD: Put fonts used by the document on the properties dialog
-> ADD: partial implementation of XYZ links
-> ADD: google-like search on thumbnails
-> ADD: use kde wallet for storing passwords of protected files
......
......@@ -344,6 +344,11 @@ const DocumentSynopsis * KPDFDocument::documentSynopsis() const
return generator ? generator->generateDocumentSynopsis() : NULL;
}
const DocumentFonts * KPDFDocument::documentFonts() const
{
return generator ? generator->generateDocumentFonts() : NULL;
}
const KPDFPage * KPDFDocument::page( uint n ) const
{
return ( n < pages_vector.count() ) ? pages_vector[n] : 0;
......@@ -1570,4 +1575,13 @@ DocumentSynopsis::DocumentSynopsis()
// void implementation, only subclassed for naming
}
/** DocumentFonts **/
DocumentFonts::DocumentFonts()
: QDomDocument( "DocumentFonts" )
{
// void implementation, only subclassed for naming
}
#include "document.moc"
......@@ -22,6 +22,7 @@ class DocumentObserver;
class DocumentViewport;
class DocumentInfo;
class DocumentSynopsis;
class DocumentFonts;
class Generator;
class PixmapRequest;
class Annotation;
......@@ -68,6 +69,7 @@ class KPDFDocument : public QObject
bool isOpened() const;
const DocumentInfo * documentInfo() const;
const DocumentSynopsis * documentSynopsis() const;
const DocumentFonts * documentFonts() const;
const KPDFPage * page( uint page ) const;
const DocumentViewport & viewport() const;
uint currentPage() const;
......@@ -168,7 +170,7 @@ class DocumentViewport
};
/**
* @short A dom tree containing informations about the document.
* @short A DOM tree containing informations about the document.
*
* The Info structure can be filled in by generators to display metadata
* about the currently opened file.
......@@ -193,10 +195,10 @@ class DocumentInfo : public QDomDocument
};
/**
* @short A Dom tree that describes the Table of Contents.
* @short A DOM tree that describes the Table of Contents.
*
* The Synopsis (TOC or Table Of Contents for friends) is represented via
* a dom tree where each nod has an internal name (displayed in the listview)
* a dom tree where each node has an internal name (displayed in the listview)
* and one or more attributes.
*
* In the tree the tag name is the 'screen' name of the entry. A tag can have
......@@ -211,4 +213,19 @@ class DocumentSynopsis : public QDomDocument
DocumentSynopsis();
};
/**
* @short A DOM thee describing fonts used in document.
*
* Root's childrend (if any) are font nodes with the following attributes:
* - Name
* - Type
* - Embedded (if font is shipped inside the document)
* - File (system's file that provides this font
*/
class DocumentFonts : public QDomDocument
{
public:
DocumentFonts();
};
#endif
......@@ -49,6 +49,7 @@ class Generator : public QObject
// Document description and Table of contents
virtual const DocumentInfo * generateDocumentInfo() { return 0L; }
virtual const DocumentSynopsis * generateDocumentSynopsis() { return 0L; }
virtual const DocumentFonts * generateDocumentFonts() { return 0L; }
// DRM handling
virtual bool isAllowed( int /*Document::Permisison(s)*/ ) { return true; }
......
......@@ -32,6 +32,7 @@
#include "xpdf/UnicodeMap.h"
#include "xpdf/Outline.h"
#include "xpdf/GfxState.h"
#include "xpdf/Annot.h" // for retrieving fonts only
#include "goo/GList.h"
// local includes
......@@ -65,7 +66,8 @@
PDFGenerator::PDFGenerator( KPDFDocument * doc )
: Generator( doc ), pdfdoc( 0 ), kpdfOutputDev( 0 ), ready( true ),
pixmapRequest( 0 ), docInfoDirty( true ), docSynopsisDirty( true )
pixmapRequest( 0 ), docInfoDirty( true ), docSynopsisDirty( true ),
docFontsDirty( true )
{
// generate kpdfOutputDev and cache page color
reparseConfig();
......@@ -256,6 +258,58 @@ const DocumentSynopsis * PDFGenerator::generateDocumentSynopsis()
return &docSyn;
}
const DocumentFonts * PDFGenerator::generateDocumentFonts()
{
if ( !docFontsDirty )
return &docFonts;
// initialize fonts dom
docFonts = DocumentFonts();
docFonts.appendChild( docFonts.createElement( "Fonts" ) );
// fonts repository to check for duplicates
Ref * fonts = NULL;
int fontsLen = 0;
int fontsSize = 0;
// temporary inner-loop xpdf objects
Object objAnn, objAnnStr, objAnnRes;
// loop on all pages
docLock.lock();
int pagesNumber = pdfdoc->getNumPages();
for ( int pg = 0; pg < pagesNumber; pg++ )
{
// look for fonts in page's resources
Page * page = pdfdoc->getCatalog()->getPage( pg + 1 );
Dict * resDict = page->getResourceDict();
if ( resDict )
addFonts( resDict, &fonts, fontsLen, fontsSize );
// look for fonts in annotation's resources
Annots * annots = new Annots( pdfdoc->getXRef(), page->getAnnots( &objAnn ) );
objAnn.free();
int annotsNumber = annots->getNumAnnots();
for ( int i = 0; i < annotsNumber; i++ )
{
if ( annots->getAnnot(i)->getAppearance( &objAnnStr )->isStream() )
{
objAnnStr.streamGetDict()->lookup( "Resources", &objAnnRes );
if ( objAnnRes.isDict() )
addFonts( objAnnRes.getDict(), &fonts, fontsLen, fontsSize );
objAnnRes.free();
}
objAnnStr.free();
}
delete annots;
}
kdWarning() << docFonts.toString() << endl;
// empty the font list and release mutex
gfree( fonts );
docLock.unlock();
return &docFonts;
}
bool PDFGenerator::isAllowed( int permissions )
{
#if !KPDF_FORCE_DRM
......@@ -633,6 +687,117 @@ void PDFGenerator::addSynopsisChildren( QDomNode * parent, GList * items )
}
}
void PDFGenerator::addFonts( Dict *resDict, Ref **fonts, int &fontsLen, int &fontsSize )
{
Object obj1, obj2;
// get the Font dictionary in current resource dictionary
GfxFontDict * gfxFontDict = NULL;
resDict->lookupNF( "Font", &obj1 );
if ( obj1.isRef() )
{
obj1.fetch( pdfdoc->getXRef(), &obj2 );
if ( obj2.isDict() )
{
Ref 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() );
// add all fonts in the Font dictionary
if ( gfxFontDict )
{
for ( int i = 0; i < gfxFontDict->getNumFonts(); i++ )
{
GfxFont * font = gfxFontDict->getFont( i );
if ( !font )
continue;
// skip already added fonts
Ref fontRef = *font->getID();
bool alreadyIn = false;
for ( int j = 0; j < fontsLen && !alreadyIn; j++ )
if ( fontRef.num == (*fonts)[j].num && fontRef.gen == (*fonts)[j].gen )
alreadyIn = true;
if ( alreadyIn )
continue;
// 0. add font element
QDomElement fontElem = docFonts.createElement( "font" );
docFonts.firstChild().appendChild( fontElem );
// 1. set Name
GString * name = font->getOrigName();
fontElem.setAttribute( "Name", name ? name->getCString() : i18n("[none]") );
// 2. set Type
const 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")
};
fontElem.setAttribute( "Type", fontTypeNames[ font->getType() ] );
// 3. set Embedded
Ref embRef;
bool emb = font->getType() == fontType3 ? true : font->getEmbeddedFontID( &embRef );
fontElem.setAttribute( "Embedded", emb ? i18n("Yes") : i18n("No") );
// 4. set Path
QString sPath = i18n("-");
if ( name && !emb )
{
DisplayFontParam *dfp = globalParams->getDisplayFont( name );
if ( dfp )
{
if ( dfp -> kind == displayFontT1 ) sPath = dfp->t1.fileName->getCString();
else sPath = dfp->tt.fileName->getCString();
}
}
fontElem.setAttribute( "File", sPath );
// enlarge font list if needed
if ( fontsLen == fontsSize )
{
fontsSize += 32;
*fonts = (Ref *)grealloc( *fonts, fontsSize * sizeof(Ref) );
}
// add this font to the list
(*fonts)[fontsLen++] = fontRef;
}
delete gfxFontDict;
}
obj1.free();
// recursively scan any resource dictionaries in objects in this dictionary
Object xObjDict, xObj, resObj;
resDict->lookup( "XObject", &xObjDict );
if ( xObjDict.isDict() )
{
for ( int i = 0; i < xObjDict.dictGetLength(); i++ )
{
xObjDict.dictGetVal(i, &xObj);
if ( xObj.isStream() )
{
xObj.streamGetDict()->lookup( "Resources", &resObj );
if ( resObj.isDict() )
addFonts( resObj.getDict(), fonts, fontsLen, fontsSize );
resObj.free();
}
xObj.free();
}
}
xObjDict.free();
}
class XPDFReader
{
......
......@@ -23,6 +23,8 @@ class PDFDoc;
class GList;
class TextPage;
class Page;
class Dict;
class Ref;
class ObjectRect;
class KPDFOutputDev;
......@@ -54,6 +56,7 @@ class PDFGenerator : public Generator
// [INHERITED] document informations
const DocumentInfo * generateDocumentInfo();
const DocumentSynopsis * generateDocumentSynopsis();
const DocumentFonts * generateDocumentFonts();
// [INHERITED] document informations
bool isAllowed( int permissions );
......@@ -76,15 +79,18 @@ class PDFGenerator : public Generator
// friend class to access private document related variables
friend class PDFPixmapGeneratorThread;
// private functions for accessing document informations via PDFDoc
// access document informations
QString getDocumentInfo( const QString & data ) const;
QString getDocumentDate( const QString & data ) const;
// private function for creating the document synopsis hieracy
// create the document synopsis hieracy
void addSynopsisChildren( QDomNode * parent, GList * items );
// private function for adding annotations read from the pdf file
// add fonts (in resDict) to the private 'docFonts' class
void addFonts( Dict * resDict, Ref ** fonts, int &fontsLen, int &fontsSize );
// fetch annotations from the pdf file and add they to the page
void addAnnotations( Page * xpdfPage, KPDFPage * page );
// private function for creating the transition information
// fetch the transition information and add it to the page
void addTransition( Page * xpdfPage, KPDFPage * page );
// (async related) receive data from the generator thread
void customEvent( QCustomEvent * );
......@@ -104,6 +110,8 @@ class PDFGenerator : public Generator
DocumentInfo docInfo;
bool docSynopsisDirty;
DocumentSynopsis docSyn;
bool docFontsDirty;
DocumentFonts docFonts;
};
......
......@@ -11,6 +11,7 @@
#include <qlayout.h>
#include <qlabel.h>
#include <klocale.h>
#include <klistview.h>
#include <ksqueezedtextlabel.h>
#include <kglobalsettings.h>
......@@ -19,9 +20,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
......@@ -68,10 +70,34 @@ PropertiesDialog::PropertiesDialog(QWidget *parent, KPDFDocument *doc)
layout->addWidget( value, row, 1 );
}
// FONTS
QVBoxLayout *page2Layout = 0;
const DocumentFonts * fonts = doc->documentFonts();
if ( fonts ) {
// create fonts tab and layout it
QFrame *page2 = addPage(i18n("Fonts"));
page2Layout = new QVBoxLayout(page2, 0, KDialog::spacingHint());
// add a klistview with 4 columns
KListView *lv = new KListView(page2);
lv->addColumn( i18n("Name") );
lv->addColumn( i18n("Type") );
lv->addColumn( i18n("Embedded") );
lv->addColumn( i18n("File") );
page2Layout->add(lv);
// populate the klistview
for ( QDomNode node = fonts->documentElement().firstChild(); !node.isNull(); node = node.nextSibling() ) {
QDomElement e = node.toElement();
new KListViewItem( lv, e.attribute( "Name" ), e.attribute( "Type" ),
e.attribute( "Embedded" ), e.attribute( "File" ) );
}
}
// current width: left columnt + right column + dialog borders
int width = layout->minimumSize().width() + valMaxWidth + 30;
int width = layout->minimumSize().width() + valMaxWidth + 2 * marginHint() + spacingHint() + 30;
if ( page2Layout )
width = QMAX( width, page2Layout->sizeHint().width() + marginHint() + spacingHint() + 31 );
// stay inside the 2/3 of the screen width
QRect screenContainer = KGlobalSettings::desktopGeometry( this );
width = QMIN( width, 2*screenContainer.width()/3 );
resize( width, 1 );
resize(width, 1);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment