Commit ea58a20b authored by Brad Hards's avatar Brad Hards

Initial import of Qt4 bindings, and for a Qt4 "Arthur" (QPainter)

backend renderer.

The bindings are currently unstable - you can expect substantial change
in both source and binary interfaces.

The Arthur renderer currently does a reasonable job of rendering path
and fill, but the image rendering doesn't work (for reasons that aren't
clear to me) and text rendering doesn't use the right glyphs - it just
draws with the current font. There is a lot of work to do on this
too. Help is, of coure, welcome.
parent 61e9bc76
2005-06-28 Brad Hards <bradh@frogmouth.net>
* qt4/:
* Makefile.am:
* configure.ac:
* poppler-qt4.pc.in: Initial import of Qt4 bindings, based
on the Qt3 bindings. API is still in flux.
* poppler/AuthurOutputDev.[cc,h]:
* poppler/Makefile.am: Initial import of Qt4 backend renderer.
Incomplete at this stage.
2005-06-27 Kristian Høgsberg <krh@redhat.com>
* poppler/CairoOutputDev.cc:
......
......@@ -17,7 +17,12 @@ qt_subdir = qt
qt_pc_file = poppler-qt.pc
endif
SUBDIRS = goo fofi $(splash_subdir) poppler $(glib_subdir) $(qt_subdir) test
if BUILD_POPPLER_QT4
qt4_subdir = qt4
qt4_pc_file = poppler-qt4.pc
endif
SUBDIRS = goo fofi $(splash_subdir) poppler $(glib_subdir) $(qt_subdir) test $(qt4_subdir)
EXTRA_DIST = \
README-XPDF \
......@@ -32,4 +37,5 @@ pkgconfig_DATA = \
$(cairo_pc_file) \
$(splash_pc_file) \
$(glib_pc_file) \
$(qt_pc_file)
$(qt_pc_file) \
$(qt4_pc_file)
......@@ -295,6 +295,93 @@ elif test x$enable_poppler_qt = xtry; then
fi
AM_CONDITIONAL(BUILD_POPPLER_QT, test x$enable_poppler_qt = xyes)
dnl
dnl Try Qt4
dnl
AC_ARG_ENABLE(poppler-qt4,
AC_HELP_STRING([--disable-poppler-qt4],
[Don't compile poppler Qt4 wrapper.]),
enable_poppler_qt4=$enableval,
enable_poppler_qt4="try")
have_qt4=no
dnl ===================================================================
dnl Check whether the Qt4 libraries are available.
dnl Adapted from Qt3 check above!
dnl ===================================================================
dnl Search paths for Qt4 - not much real experience with this yet.
qt4_incdirs="/usr/local/qt/include /usr/include/qt /usr/include /usr/X11R6/include/X11/qt /usr/X11R6/include/qt /usr/lib/qt/include"
qt4_libdirs="/usr/local/qt/lib /usr/lib/qt /usr/lib /usr/X11R6/lib/X11/qt /usr/X11R6/lib/qt /usr/lib/qt/lib"
if test -n "$QTDIR" ; then
qt4_incdirs="$QTDIR/include $qt4_incdirs"
qt4_libdirs="$QTDIR/lib $qt4_libdirs"
fi
dnl What to test
qt4_test_include="QtCore/QCoreApplication"
qt4_test_la_library="libQtCore.la"
qt4_test_library="libQtCore.so"
dnl Check for Qt4 headers
AC_MSG_CHECKING([for Qt4 headers])
qt4_incdir="no"
for it in $qt4_incdirs ; do
if test -r "$it/$qt4_test_include" ; then
qt4_incdir="$it"
break
fi
done
AC_MSG_RESULT([$qt4_incdir])
dnl Check for Qt4 libraries
AC_MSG_CHECKING([for Qt4 libraries])
qt4_libdir="no"
for qt4_check in $qt4_libdirs ; do
if test -r "$qt4_check/$qt4_test_la_library" ; then
qt4_libdir="$qt4_check"
break
fi
if test -r "$qt4_check/$qt4_test_library" ; then
qt4_libdir="$qt4_check"
break
fi
done
AC_MSG_RESULT([$qt4_libdir])
if test "x$qt4_libdir" != "xno" ; then
if test "x$qt4_incdir" != "xno" ; then
have_qt4=yes;
fi
fi
dnl Set the variables
POPPLER_QT4_CXXFLAGS="-I$qt4_incdir"
POPPLER_QT4_LIBS="-L$qt4_libdir -lQtCore -lQtGui"
AC_SUBST(POPPLER_QT4_CXXFLAGS)
AC_SUBST(POPPLER_QT4_LIBS)
if test x$have_qt4 = xno ; then
AC_MSG_WARN([Qt4 development libraries not found])
fi
if test x$enable_poppler_qt4 = xyes; then
if test x$have_qt4 = xno; then
AC_MSG_ERROR([Qt4 integration explicitly required, and Qt4 libraries not found])
fi
elif test x$enable_poppler_qt4 = xtry; then
if test x$have_qt4 = xyes; then
enable_poppler_qt4="yes"
else
enable_poppler_qt4="no"
fi
fi
AM_CONDITIONAL(BUILD_POPPLER_QT4, test x$enable_poppler_qt4 = xyes)
AC_ARG_ENABLE(gtk-test,
AC_HELP_STRING([--disable-gtk-test],
[Don't compile GTK+ test program.]),
......@@ -339,11 +426,15 @@ poppler/Makefile
glib/Makefile
test/Makefile
qt/Makefile
qt4/Makefile
qt4/src/Makefile
qt4/tests/Makefile
poppler.pc
poppler-cairo.pc
poppler-splash.pc
poppler-glib.pc
poppler-qt.pc])
poppler-qt.pc
poppler-qt4.pc])
echo ""
......@@ -351,6 +442,7 @@ echo "Building poppler with support for:"
echo " splash output: $enable_splash_output"
echo " cairo output: $enable_cairo_output"
echo " qt wrapper: $enable_poppler_qt"
echo " qt4 wrapper: $enable_poppler_qt4"
echo " glib wrapper: $enable_poppler_glib"
echo " use libjpeg: $enable_libjpeg"
echo " use zlib: $enable_zlib"
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: poppler-qt4
Description: Qt4 bindings for poppler
Version: @VERSION@
Requires: poppler = @VERSION@
Libs: -L${libdir} -lpoppler-qt4
Cflags: -I${includedir}/poppler
This diff is collapsed.
//========================================================================
//
// ArthurOutputDev.h
//
// Copyright 2003 Glyph & Cog, LLC
// Copyright 2004 Red Hat, INC
//
//========================================================================
#ifndef CAIROOUTPUTDEV_H
#define CAIROOUTPUTDEV_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "goo/gtypes.h"
#include "OutputDev.h"
#include "GfxState.h"
#include <QtGui/QPainter>
class GfxState;
class GfxPath;
class Gfx8BitFont;
struct GfxRGB;
//------------------------------------------------------------------------
// ArthurOutputDev - Qt 4 QPainter renderer
//------------------------------------------------------------------------
class ArthurOutputDev: public OutputDev {
public:
// Constructor.
ArthurOutputDev(QPainter *painter );
// Destructor.
virtual ~ArthurOutputDev();
//----- get info about output device
// Does this device use upside-down coordinates?
// (Upside-down means (0,0) is the top left corner of the page.)
virtual GBool upsideDown() { return gTrue; }
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar() { return gFalse; }
// Does this device use beginType3Char/endType3Char? Otherwise,
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gTrue; }
//----- initialization and control
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
// End a page.
virtual void endPage();
//----- link borders
virtual void drawLink(Link *link, Catalog *catalog);
//----- save/restore graphics state
virtual void saveState(GfxState *state);
virtual void restoreState(GfxState *state);
//----- update graphics state
virtual void updateAll(GfxState *state);
virtual void updateCTM(GfxState *state, double m11, double m12,
double m21, double m22, double m31, double m32);
virtual void updateLineDash(GfxState *state);
virtual void updateFlatness(GfxState *state);
virtual void updateLineJoin(GfxState *state);
virtual void updateLineCap(GfxState *state);
virtual void updateMiterLimit(GfxState *state);
virtual void updateLineWidth(GfxState *state);
virtual void updateFillColor(GfxState *state);
virtual void updateStrokeColor(GfxState *state);
virtual void updateFillOpacity(GfxState *state);
virtual void updateStrokeOpacity(GfxState *state);
//----- update text state
virtual void updateFont(GfxState *state);
//----- path painting
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
virtual void eoFill(GfxState *state);
//----- path clipping
virtual void clip(GfxState *state);
virtual void eoClip(GfxState *state);
//----- text drawing
virtual void drawString(GfxState *state, GooString *s);
virtual GBool beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen);
virtual void endType3Char(GfxState *state);
virtual void endTextObject(GfxState *state);
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
virtual void drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg);
//----- Type 3 font operators
virtual void type3D0(GfxState *state, double wx, double wy);
virtual void type3D1(GfxState *state, double wx, double wy,
double llx, double lly, double urx, double ury);
//----- special access
// Called to indicate that a new PDF document has been loaded.
void startDoc(XRef *xrefA);
GBool isReverseVideo() { return gFalse; }
private:
QPainter *m_painter;
QFont m_currentFont;
QPen m_currentPen;
QBrush m_currentBrush;
GBool m_needFontUpdate; // set when the font needs to be updated
QImage *m_image;
};
#endif
......@@ -15,6 +15,22 @@ splash_libs = \
endif
if BUILD_POPPLER_QT4
arthur_headers = \
ArthurOutputDev.h
arthur_sources = \
ArthurOutputDev.cc
arthur_includes = \
$(POPPLER_QT4_CXXFLAGS)
arthur_libs = \
$(POPPLER_QT4_LIBS)
endif
if BUILD_CAIRO_OUTPUT
......@@ -60,6 +76,7 @@ INCLUDES = \
-I$(top_srcdir) \
$(splash_includes) \
$(cairo_includes) \
$(arthur_includes) \
-DDATADIR=\""$(datadir)"\"
lib_LTLIBRARIES = libpoppler.la
......@@ -69,6 +86,7 @@ libpoppler_la_LIBADD = \
$(top_builddir)/fofi/libfofi.la \
$(splash_libs) \
$(cairo_libs) \
$(arthur_libs) \
$(libjpeg_libs) \
$(zlib_libs)
......@@ -76,6 +94,7 @@ poppler_includedir = $(includedir)/poppler
poppler_include_HEADERS = \
$(splash_headers) \
$(cairo_headers) \
$(arthur_headers) \
Annot.h \
Array.h \
BaseFile.h \
......@@ -127,6 +146,7 @@ poppler_include_HEADERS = \
libpoppler_la_SOURCES = \
$(splash_sources) \
$(cairo_sources) \
$(arthur_sources) \
$(libjpeg_sources) \
$(zlib_sources) \
Annot.cc \
......
SUBDIRS = src tests
This diff is collapsed.
INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/poppler \
$(POPPLER_QT4_CXXFLAGS)
poppler_includedir = $(includedir)/poppler
poppler_include_HEADERS = \
poppler-qt4.h
lib_LTLIBRARIES=libpoppler-qt4.la
libpoppler_qt4_la_SOURCES = \
poppler-document.cc \
poppler-page.cc \
poppler-private.h
libpoppler_qt4_la_LIBADD= \
$(top_builddir)/poppler/libpoppler.la \
$(POPPLER_QT4_LIBS)
/* poppler-document.cc: qt interface to poppler
* Copyright (C) 2005, Net Integration Technologies, Inc.
*
* 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.
*/
#define UNSTABLE_POPPLER_QT4
#include <poppler-qt4.h>
#include <QtCore/QFile>
#include <QtGui/QImage>
#include <QtCore/QByteArray>
#include <GlobalParams.h>
#include <PDFDoc.h>
#include <Catalog.h>
#include <ErrorCodes.h>
#include <SplashOutputDev.h>
#include <splash/SplashBitmap.h>
#include "poppler-private.h"
namespace Poppler {
Document *Document::load(const QString &filePath)
{
if (!globalParams) {
globalParams = new GlobalParams("/etc/xpdfrc");
globalParams->setupBaseFontsFc(NULL);
}
DocumentData *doc = new DocumentData(new GooString(QFile::encodeName(filePath)), NULL, NULL);
Document *pdoc;
if (doc->doc.isOk() || doc->doc.getErrorCode() == errEncrypted) {
pdoc = new Document(doc);
if (doc->doc.getErrorCode() == errEncrypted)
pdoc->m_doc->locked = true;
else
pdoc->m_doc->locked = false;
pdoc->m_doc->m_fontInfoScanner = new FontInfoScanner(&(doc->doc));
return pdoc;
}
else
return NULL;
}
Document::Document(DocumentData *dataA)
{
m_doc = dataA;
}
Document::~Document()
{
delete m_doc;
}
bool Document::isLocked() const
{
return m_doc->locked;
}
bool Document::unlock(const QByteArray &ownerPassword,
const QByteArray &userPassword)
{
if (m_doc->locked) {
/* racier then it needs to be */
GooString *ownerPwd = new GooString(ownerPassword.data());
GooString *userPwd = new GooString(userPassword.data());
DocumentData *doc2 = new DocumentData(m_doc->doc.getFileName(),
ownerPwd,
userPwd);
delete ownerPwd;
delete userPwd;
if (!doc2->doc.isOk()) {
delete doc2;
} else {
delete m_doc;
m_doc = doc2;
m_doc->locked = false;
}
}
return m_doc->locked;
}
Document::PageMode Document::pageMode(void) const
{
switch (m_doc->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::numPages() const
{
return m_doc->doc.getNumPages();
}
QList<FontInfo> Document::fonts() const
{
QList<FontInfo> ourList;
scanForFonts(numPages(), &ourList);
return ourList;
}
bool Document::scanForFonts( int numPages, QList<FontInfo> *fontList ) const
{
GooList *items = m_doc->m_fontInfoScanner->scan( numPages );
if ( NULL == items )
return false;
for ( int i = 0; i < items->getLength(); ++i ) {
FontInfo thisFont(((::FontInfo*)items->get(i))->getName()->getCString());
fontList->append(thisFont);
}
return true;
}
/* 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;
}
/* borrowed from kpdf */
QString Document::info( const QString & type ) const
{
// [Albert] Code adapted from pdfinfo.cc on xpdf
Object info;
if ( m_doc->locked )
return NULL;
m_doc->doc.getDocInfo( &info );
if ( !info.isDict() )
return NULL;
QString result;
Object obj;
GooString *s1;
GBool isUnicode;
Unicode u;
int i;
Dict *infoDict = info.getDict();
if ( infoDict->lookup( type.toLatin1().data(), &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 += unicodeToQString( &u, 1 );
}
obj.free();
info.free();
return result;
}
obj.free();
info.free();
return NULL;
}
/* borrowed from kpdf */
QDateTime Document::date( const QString & type ) const
{
// [Albert] Code adapted from pdfinfo.cc on xpdf
if ( m_doc->locked )
return QDateTime();
Object info;
m_doc->doc.getDocInfo( &info );
if ( !info.isDict() ) {
info.free();
return QDateTime();
}
Object obj;
char *s;
int year, mon, day, hour, min, sec;
Dict *infoDict = info.getDict();
QString result;
if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
{
s = obj.getString()->getCString();
if ( s[0] == 'D' && s[1] == ':' )
s += 2;
/* FIXME process time zone on systems that support it */
if ( sscanf( s, "%4d%2d%2d%2d%2d%2d", &year, &mon, &day, &hour, &min, &sec ) == 6 )
{
/* Workaround for y2k bug in Distiller 3 stolen from gpdf, hoping that it won't
* * be used after y2.2k */
if ( year < 1930 && strlen (s) > 14) {
int century, years_since_1900;
if ( sscanf( s, "%2d%3d%2d%2d%2d%2d%2d",
&century, &years_since_1900,
&mon, &day, &hour, &min, &sec) == 7 )
year = century * 100 + years_since_1900;
else {
obj.free();
info.free();
return QDateTime();
}
}
QDate d( year, mon, day ); //CHECK: it was mon-1, Jan->0 (??)
QTime t( hour, min, sec );
if ( d.isValid() && t.isValid() ) {
obj.free();
info.free();
return QDateTime( d, t );
}
}
}
obj.free();
info.free();
return QDateTime();
}
bool Document::isEncrypted() const
{
return m_doc->doc.isEncrypted();
}
bool Document::isLinearized() const
{
return m_doc->doc.isLinearized();
}
bool Document::okToPrint() const
{
return m_doc->doc.okToPrint();
}
bool Document::okToChange() const
{
return m_doc->doc.okToChange();
}
bool Document::okToCopy() const
{
return m_doc->doc.okToCopy();
}
bool Document::okToAddNotes() const
{
return m_doc->doc.okToAddNotes();
}
double Document::pdfVersion() const
{
return m_doc->doc.getPDFVersion();
}
Page *Document::page(QString label) const
{
GooString label_g(label.toAscii().data());
int index;
if (!m_doc->doc.getCatalog()->labelToIndex (&label_g, &index))
return NULL;
return page(index);
}
}
/* poppler-page.cc: qt interface to poppler
* Copyright (C) 2005, Net Integration Technologies, Inc.
*
* 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.
*/
#define UNSTABLE_POPPLER_QT4
#include <poppler-qt4.h>
#include <QtCore/QFile>
#include <QtGui/QImage>
#include <QtGui/QPixmap>
#include <GlobalParams.h>
#include <PDFDoc.h>
#include <Catalog.h>
#include <ErrorCodes.h>
#include <ArthurOutputDev.h>
#include <TextOutputDev.h>
#include "poppler-private.h"
#include <SplashOutputDev.h>
#include <splash/SplashBitmap.h>
namespace Poppler {
class PageData {
public:
const Document *parentDoc;
int index;
};
Page::Page(const Document *doc, int index) {
m_page = new PageData();
m_page->index = index;
m_page->parentDoc = doc;
}
Page::~Page()
{
delete m_page;
}
void Page::splashRenderToPixmap(QPixmap **q, int x, int y, int w, int h) const
{
SplashOutputDev *output_dev;
SplashColor white;
SplashBitmap *