poppler-private.h 7.17 KB
Newer Older
1 2
/* poppler-private.h: qt interface to poppler
 * Copyright (C) 2005, Net Integration Technologies, Inc.
3 4 5 6
 * Copyright (C) 2006 by Albert Astals Cid <aacid@kde.org>
 * Inspired on code by
 * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
 * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

Albert Astals Cid's avatar
Albert Astals Cid committed
23
#include <config.h>
24
#include <GfxState.h>
25
#include <GlobalParams.h>
26 27 28
#include <Link.h>
#include <Outline.h>
#include <PDFDoc.h>
29
#include <FontInfo.h>
30
#include <UGooString.h>
Albert Astals Cid's avatar
Albert Astals Cid committed
31 32 33 34
#include <OutputDev.h>
#if defined(HAVE_SPLASH)
#include <SplashOutputDev.h>
#endif
35 36


37 38 39

namespace Poppler {

40 41 42 43 44 45 46 47 48 49 50 51
    /* borrowed from kpdf */
    static QString unicodeToQString(Unicode* u, int len) {
	QString ret;
	ret.resize(len);
	QChar* qch = (QChar*) ret.unicode();
	for (;len;--len)
	    *qch++ = (QChar) *u++;
	return ret;
    }

    static UGooString *QStringToUGooString(const QString &s) {
	int len = s.length();
52
	Unicode *u = new Unicode[s.length()];
53 54 55 56 57 58 59 60
	for (int i = 0; i < len; ++i)
		u[i] = s.at(i).unicode();
	return new UGooString(u, len);
    }

    class LinkDestinationData
    {
        public:
61
		LinkDestinationData( LinkDest *l, UGooString *nd, Poppler::DocumentData *pdfdoc ) : ld(l), namedDest(nd), doc(pdfdoc)
62 63 64 65
		{
		}
	
	LinkDest *ld;
66 67
	UGooString *namedDest;
	Poppler::DocumentData *doc;
68 69
    };

70 71
    class DocumentData {
    public:
72
	DocumentData(GooString *filePath, GooString *ownerPassword, GooString *userPassword)
73
	    {
74
		doc = new PDFDoc(filePath, ownerPassword, userPassword);
75 76 77
		init(ownerPassword, userPassword);
	    }
	
78
	DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword)
79
	    {
80 81 82 83 84
		Object obj;
		fileContents = data;
		obj.initNull();
		MemStream *str = new MemStream((char*)fileContents.data(), 0, fileContents.length(), &obj);
	        doc = new PDFDoc(str, ownerPassword, userPassword);
85 86 87 88 89 90 91 92
		init(ownerPassword, userPassword);
	    }
	
	void init(GooString *ownerPassword, GooString *userPassword)
	    {
		m_fontInfoScanner = 0;
		m_backend = Document::SplashBackend;
		m_outputDev = 0;
93
		paperColor = Qt::white;
94 95 96
		// It might be more appropriate to delete these in PDFDoc
		delete ownerPassword;
		delete userPassword;
97 98 99
		
		if ( count == 0 ) globalParams = new GlobalParams("/etc/xpdfrc");
		count ++;
100
	    }
101 102 103
	
	~DocumentData()
	{
104
		delete doc;
105
		qDeleteAll(m_embeddedFiles);
106
		delete m_outputDev;
107
		delete m_fontInfoScanner;
108 109 110
		
		count --;
		if ( count == 0 ) delete globalParams;
111 112
	}
	
113
	OutputDev *getOutputDev()
114
	{
115
		if (!m_outputDev)
116
		{
117 118 119 120 121 122
			switch (m_backend)
			{
			case Document::ArthurBackend:
			// create a splash backend even in case of the Arthur Backend
			case Document::SplashBackend:
			{
Albert Astals Cid's avatar
Albert Astals Cid committed
123
#if defined(HAVE_SPLASH)
124 125 126 127
			SplashColor bgColor;
			bgColor[0] = paperColor.red();
			bgColor[1] = paperColor.green();
			bgColor[2] = paperColor.blue();
128
			SplashOutputDev * splashOutputDev = new SplashOutputDev(splashModeRGB8Qt, 4, gFalse, bgColor);
129
			splashOutputDev->startDoc(doc->getXRef());
130
			m_outputDev = splashOutputDev;
Albert Astals Cid's avatar
Albert Astals Cid committed
131
#endif
132 133 134
			break;
			}
			}
135
		}
136
		return m_outputDev;
137 138
	}
	
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
	void addTocChildren( QDomDocument * docSyn, QDomNode * parent, GooList * items )
	{
		int numItems = items->getLength();
		for ( int i = 0; i < numItems; ++i )
		{
			// iterate over every object in 'items'
			OutlineItem * outlineItem = (OutlineItem *)items->get( i );
			
			// 1. create element using outlineItem's title as tagName
			QString name;
			Unicode * uniChar = outlineItem->getTitle();
			int titleLength = outlineItem->getTitleLength();
			name = unicodeToQString(uniChar, titleLength);
			if ( name.isEmpty() )
				continue;
			
			QDomElement item = docSyn->createElement( name );
			parent->appendChild( item );
			
			// 2. find the page the link refers to
159
			::LinkAction * a = outlineItem->getAction();
160 161 162 163 164 165 166 167 168 169 170 171 172 173
			if ( a && ( a->getKind() == actionGoTo || a->getKind() == actionGoToR ) )
			{
				// page number is contained/referenced in a LinkGoTo
				LinkGoTo * g = static_cast< LinkGoTo * >( a );
				LinkDest * destination = g->getDest();
				if ( !destination && g->getNamedDest() )
				{
					// no 'destination' but an internal 'named reference'. we could
					// get the destination for the page now, but it's VERY time consuming,
					// so better storing the reference and provide the viewport on demand
					UGooString *s = g->getNamedDest();
					QString aux = unicodeToQString( s->unicode(), s->getLength() );
					item.setAttribute( "DestinationName", aux );
				}
174
				else if ( destination && destination->isOk() )
175
				{
176
					LinkDestinationData ldd(destination, NULL, this);
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
					item.setAttribute( "Destination", LinkDestination(ldd).toString() );
				}
				if ( a->getKind() == actionGoToR )
				{
					LinkGoToR * g2 = static_cast< LinkGoToR * >( a );
					item.setAttribute( "ExternalFileName", g2->getFileName()->getCString() );
				}
			}
			
			// 3. recursively descend over children
			outlineItem->open();
			GooList * children = outlineItem->getKids();
			if ( children )
				addTocChildren( docSyn, &item, children );
		}
	}
193 194 195 196 197 198
	
	void setPaperColor(const QColor &color)
	{
		if (color != paperColor)
		{
			paperColor = color;
199 200
			delete m_outputDev;
			m_outputDev = NULL;
201 202
		}
	}
203 204 205
	
	void fillMembers()
	{
206 207
		m_fontInfoScanner = new FontInfoScanner(doc);
		int numEmb = doc->getCatalog()->numEmbeddedFiles();
208 209 210
		if (!(0 == numEmb)) {
			// we have some embedded documents, build the list
			for (int yalv = 0; yalv < numEmb; ++yalv) {
211
				EmbFile *ef = doc->getCatalog()->embeddedFile(yalv);
212 213 214 215 216
				m_embeddedFiles.append(new EmbeddedFile(ef));
				delete ef;
			}
		}
	}
217

218 219
	PDFDoc *doc;
	QByteArray fileContents;
220 221
	bool locked;
	FontInfoScanner *m_fontInfoScanner;
222 223
	Document::RenderBackend m_backend;
	OutputDev *m_outputDev;
224
	QList<EmbeddedFile*> m_embeddedFiles;
225
	QColor paperColor;
226
	static int count;
227 228
    };

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
    class FontInfoData
    {
	public:
		FontInfoData( const FontInfoData &fid )
		{
			fontName = fid.fontName;
			fontFile = fid.fontFile;
			isEmbedded = fid.isEmbedded;
			isSubset = fid.isSubset;
			type = fid.type;
		}
		
		FontInfoData( ::FontInfo* fi )
		{
			if (fi->getName()) fontName = fi->getName()->getCString();
			if (fi->getFile()) fontFile = fi->getFile()->getCString();
			isEmbedded = fi->getEmbedded();
			isSubset = fi->getSubset();
			type = (Poppler::FontInfo::Type)fi->getType();
		}

		QString fontName;
		QString fontFile;
		bool isEmbedded;
		bool isSubset;
		FontInfo::Type type;
    };

257 258 259 260 261 262 263 264 265 266 267
    class TextBoxData
    {
	public:
		QString text;
		QRectF bBox;
		TextBox *nextWord;
		QVector<double> edge;	// "near" edge x or y coord of each char
					//   (plus one extra entry for the last char)
		bool hasSpaceAfter;
    };

268 269 270
}