[poppler] [PATCH] initial clean poppler-qt implementation

Kristian Høgsberg krh at bitplanet.net
Wed Mar 30 23:13:00 PST 2005


Jeff Muizelaar wrote:
> renderToPixmap will be changed to render a slice and take the more of
> the other parameters.
> 
> Comments welcome.

Great work, thanks for starting this, Jeff.  Comments below.

cheers, Kristian

> -Jeff
> 
> 
> diff -X /home/jrmuizel/rsrc/autoignore -urN poppler/Makefile.am poppler-qt-new/Makefile.am
> --- poppler/Makefile.am	2005-03-30 12:19:15.000000000 -0500
> +++ poppler-qt-new/Makefile.am	2005-03-30 12:14:26.000000000 -0500
> @@ -12,17 +12,24 @@
>  glib_pc_file = poppler-glib.pc
>  endif
>  
> -SUBDIRS = goo fofi $(splash_subdir) poppler $(glib_subdir) test
> +if BUILD_POPPLER_QT
> +qt_subdir = qt
> +qt_pc_file = poppler-qt.pc
> +endif
> +
> +SUBDIRS = goo fofi $(splash_subdir) poppler $(glib_subdir) $(qt_subdir) test
>  
>  EXTRA_DIST =					\
>  	README-XPDF				\
>  	poppler.pc.in				\
>  	poppler-cairo.pc.in			\
> -	poppler-splash.pc.in
> +	poppler-splash.pc.in			\
> +	poppler-qt.pc.in
>  
>  pkgconfigdir = $(libdir)/pkgconfig
>  pkgconfig_DATA =				\
>  	poppler.pc				\
>  	$(cairo_pc_file)			\
>  	$(splash_pc_file)			\
> -	$(glib_pc_file)
> +	$(glib_pc_file)				\
> +	$(qt_pc_file)
> diff -X /home/jrmuizel/rsrc/autoignore -urN poppler/configure.ac poppler-qt-new/configure.ac
> --- poppler/configure.ac	2005-03-30 12:19:15.000000000 -0500
> +++ poppler-qt-new/configure.ac	2005-03-30 12:56:53.000000000 -0500
> @@ -169,6 +169,66 @@
>  fi
>  AM_CONDITIONAL(BUILD_POPPLER_GLIB, test x$enable_poppler_glib = xyes)
>  
> +AC_ARG_ENABLE(poppler-qt,
> +	      AC_HELP_STRING([--disable-poppler-qt],
> +			     [Don't compile poppler qt wrapper.]),
> +	      enable_poppler_qt=$enableval,
> +	      enable_poppler_qt="try")
> +# Qt detection
> +AC_PATH_PROG(QT_MOC, moc, no)
> +
> +have_qt=no
> +AC_MSG_CHECKING([for qglobal.h])
> +if test -n "$QTDIR" -a -f "$QTDIR/include/qglobal.h"; then
> +    have_qt=yes
> +    POPPLER_QT_CXXFLAGS="-I$QTDIR/include"
> +else
> +    for dir in "${prefix}/include/qt" "/usr/include/qt-3.1" "/usr/include/qt3" "/usr/include/qt" "/usr/lib/qt/include" "/usr/lib/qt-3.1/include"; do
> +        if test -f "$dir/qglobal.h"; then
> +            have_qt=yes
> +            POPPLER_QT_CXXFLAGS="-I$dir"
> +       fi
> +    done
> +fi
> +if test x"$have_qt" = x"yes"; then
> +   AC_MSG_RESULT([found])
> +else
> +   AC_MSG_RESULT([not found])
> +fi
> +
> +dnl linking to kdecore will give us a bit of help from libtool
> +if (! kde-config >& /dev/null); then
> +    have_qt=no
> +else
> +    kdelibs=`kde-config --install lib --expandvars 2>/dev/null`
> +    if test -z $kdelibs -o ! -f $kdelibs/libkdecore.la; then
> +        have_qt=no
> +    else
> +        POPPLER_QT_LIBS="$kdelibs/libkdecore.la /usr/lib/libqt-mt.la"
> +    fi
> +fi
> +
> +if test x$have_qt = xno ; then
> +    AC_MSG_WARN([Qt development libraries not found])
> +fi
> +
> +if test x$enable_poppler_qt = xyes; then
> +  if test x$have_qt = xno; then
> +    AC_MSG_ERROR([Qt integration explicitly required, and Qt libraries not found])
> +  fi
> +elif test x$enable_poppler_qt = xtry; then
> +  echo "tryingidie"

Is this a debug echo?

> +  if test x$have_qt = xyes; then
> +    enable_poppler_qt="yes"
> +  else
> +    enable_poppler_qt="no"
> +  fi
> +fi
> +AM_CONDITIONAL(BUILD_POPPLER_QT, test x$enable_poppler_glib = xyes)
> +
> +dnl Qt flags
> +AC_SUBST(POPPLER_QT_CXXFLAGS)
> +AC_SUBST(POPPLER_QT_LIBS)
>  
>  AC_ARG_ENABLE(gtk-test,
>                AC_HELP_STRING([--disable-gtk-test],
> @@ -213,15 +273,18 @@
>  poppler/Makefile
>  glib/Makefile
>  test/Makefile
> +qt/Makefile
>  poppler.pc
>  poppler-cairo.pc
>  poppler-splash.pc
> -poppler-glib.pc])
> +poppler-glib.pc
> +poppler-qt.pc])
>  
>  
>  echo ""
>  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 "  glib wrapper:  $enable_poppler_glib"
>  echo "  use libjpeg:   $enable_libjpeg"
> diff -X /home/jrmuizel/rsrc/autoignore -urN poppler/qt/Makefile.am poppler-qt-new/qt/Makefile.am
> --- poppler/qt/Makefile.am	1969-12-31 19:00:00.000000000 -0500
> +++ poppler-qt-new/qt/Makefile.am	2005-03-30 13:14:42.000000000 -0500
> @@ -0,0 +1,31 @@
> +INCLUDES =					\
> +	-I$(top_srcdir)				\
> +	-I$(top_srcdir)/poppler			\
> +	$(cairo_includes)			\
> + 	$(POPPLER_QT_CXXFLAGS)			\
> +	$(FREETYPE_CFLAGS)			\
> +	-DDATADIR=\""$(datadir)"\"
> +
> +
> +poppler_includedir = $(includedir)/poppler
> +poppler_include_HEADERS =			\
> +	poppler-qt.h
> +
> +lib_LTLIBRARIES=libpoppler-qt.la
> +libpoppler_qt_la_SOURCES =			\
> +	poppler-qt.cc
> +
> +libpoppler_qt_la_LIBADD= 			\
> +	$(POPPLER_QT_LIBS)			\
> +	$(FREETYPE_LIBS)
> +
> +noinst_PROGRAMS = test-poppler-qt
> +
> +test_poppler_qt_SOURCES =			\
> +       test-poppler-qt.cpp
> +
> +test_poppler_qt_LDADD =				\
> +	$(top_builddir)/poppler/libpoppler.la	\
> +	libpoppler-qt.la			\
> +	$(POPPLER_QT_LIBS)			\
> +	$(FREETYPE_LIBS)
> diff -X /home/jrmuizel/rsrc/autoignore -urN poppler/qt/poppler-qt.cc poppler-qt-new/qt/poppler-qt.cc
> --- poppler/qt/poppler-qt.cc	1969-12-31 19:00:00.000000000 -0500
> +++ poppler-qt-new/qt/poppler-qt.cc	2005-03-30 13:28:22.000000000 -0500
> @@ -0,0 +1,123 @@
> +/* poppler-qt.cpp: 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.
> + */
> +
> +#include <poppler-qt.h>
> +#include <qfile.h>
> +#include <qimage.h>
> +#include <GlobalParams.h>
> +#include <PDFDoc.h>
> +#include <Catalog.h>
> +#include <ErrorCodes.h>
> +#include <SplashOutputDev.h>
> +#include <splash/SplashBitmap.h>
> +
> +PopplerDocument *PopplerDocument::load(const QString &filePath)
> +{
> +  if (!globalParams) {
> +    globalParams = new GlobalParams("/etc/xpdfrc");
> +    globalParams->setupBaseFontsFc(NULL);
> +  }
> +
> +  PDFDoc *doc = new PDFDoc(new GooString(QFile::encodeName(filePath)), 0, 0);
> +  PopplerDocument *pdoc;
> +  if (doc->isOk() || doc->getErrorCode() == errEncrypted) {
> +    pdoc = new PopplerDocument(doc);
> +    if (doc->getErrorCode() == errEncrypted)
> +      pdoc->locked = true;
> +    else
> +      pdoc->locked = false;
> +    return pdoc;
> +  }
> +  else
> +    return NULL;
> +}

I still think we should pass an error code back to the application here 
so that it's possible to distinguish between file not found and file not 
valid pdf.

> +bool PopplerDocument::unlock(QCString &password)
> +{
> +  if (locked) {
> +    /* racier then it needs to be */
> +    GooString *pwd = new GooString(password.data());
> +    PDFDoc *doc2 = new PDFDoc(doc->getFileName(), pwd, pwd);
> +    delete pwd;
> +    if (!doc2->isOk()) {
> +      delete doc2;
> +    } else {
> +      delete doc;
> +      doc = doc2;
> +      locked = false;
> +    }
> +  }
> +  return locked;
> +}
> +
> +
> +PopplerDocument::PopplerDocument(PDFDoc *docA)
> +{
> +  doc = docA;
> +}

Is this just for testing?  When we drop the xpdf headers, there will be 
no way to create a PDFDoc object.

> +PopplerDocument::~PopplerDocument()
> +{
> +  delete doc;
> +}
> +
> +PopplerDocument::PageMode PopplerDocument::getPageMode(void)
> +{
> +  switch (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;
> +  }
> +}
> +
> +void PopplerPage::renderToPixmap(QPixmap **q)
> +{
> +  SplashOutputDev *output_dev;
> +  SplashColor white;
> +  SplashBitmap *bitmap;
> +  white.rgb8 = splashMakeRGB8(255,255,255);
> +  SplashColorPtr color_ptr;
> +  output_dev = new SplashOutputDev(splashModeRGB8, gFalse, white);
> +  output_dev->startDoc(doc->doc->getXRef ());
> +  
> +  doc->doc->displayPage(output_dev, index + 1, 72, 72,
> +      0,
> +      true,
> +      false);
> +  bitmap = output_dev->getBitmap ();
> +  color_ptr = bitmap->getDataPtr ();
> +  QImage * img = new QImage( (uchar*)color_ptr.rgb8, bitmap->getWidth(), bitmap->getHeight(), 32, 0, 0, QImage::IgnoreEndian );
> +  *q = new QPixmap( *img );
> +  
> +  delete img;
> +  delete output_dev;
> +}
> +
> +int PopplerDocument::getNumPages()
> +{
> +  return doc->getNumPages();
> +}
> diff -X /home/jrmuizel/rsrc/autoignore -urN poppler/qt/poppler-qt.h poppler-qt-new/qt/poppler-qt.h
> --- poppler/qt/poppler-qt.h	1969-12-31 19:00:00.000000000 -0500
> +++ poppler-qt-new/qt/poppler-qt.h	2005-03-30 13:27:49.000000000 -0500
> @@ -0,0 +1,72 @@
> +/* poppler-qt.h: 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.
> + */
> +
> +#ifndef __POPPLER_QT_H__
> +#define __POPPLER_QT_H__
> +
> +#include <qpixmap.h>
> +
> +class PDFDoc *doc;

I think we should try to design the wrapper in a way that completely 
hides away the xpdf types.  PDFDoc and Page are quite nasty 
namespace-pollution-wise.  One approach I considered was

	class PopplerDocumentData;

in the header file and

	class PopplerDocumentData {
		PDFDoc doc;
	};

in the implementation.  The PDFDoc *doc member would then be 
PopplerDocumentData *data instead.  Could that work?

Oh, and should we use namespaces?  Poppler::Document, Poppler::Page?  I 
think that would be nice.

> +class PopplerDocument;
> +
> +class PopplerPage {
> +  friend class PopplerDocument;
> +  public:
> +    int index;
> +    void renderToPixmap(QPixmap **q);
> +  private:
> +    PopplerPage(PopplerDocument *_doc, int _index) {
> +      index = _index;
> +      doc = _doc;
> +    }
> +    PopplerDocument *doc;
> +};

In the glib binding I've chosen to also cache a pointer to the 
corresponding Page object in the PopplerPage object.

> +class PopplerDocument {
> +  friend class PopplerPage;
> +  
> +public:
> +  enum PageMode {
> +    UseNone,
> +    UseOutlines,
> +    UseThumbs,
> +    FullScreen,
> +    UseOC
> +  };
> +  
> +  static PopplerDocument *PopplerDocument::load(const QString & filePath);
> +  
> +  PopplerPage *getPage(int index) { return new PopplerPage(this, index); }
> +  
> +  int getNumPages();
> +  
> +  PageMode getPageMode();
> +  
> +  bool unlock(QCString &password);
> +  
> +  bool isLocked() { return locked; }
> +  PopplerDocument::~PopplerDocument();
> +  
> +private:
> +  PDFDoc *doc;
> +  bool locked;
> +  PopplerDocument::PopplerDocument(PDFDoc *docA);

Ahh... I get it now...

> +};
> +
> +#endif
> diff -X /home/jrmuizel/rsrc/autoignore -urN poppler/qt/test-poppler-qt.cpp poppler-qt-new/qt/test-poppler-qt.cpp
> --- poppler/qt/test-poppler-qt.cpp	1969-12-31 19:00:00.000000000 -0500
> +++ poppler-qt-new/qt/test-poppler-qt.cpp	2005-03-30 13:22:46.000000000 -0500
> @@ -0,0 +1,63 @@
> +#include <qapplication.h>
> +#include <qpainter.h>
> +#include <qpixmap.h>
> +#include <qwidget.h>
> +#include <qmessagebox.h>
> +#include <qfile.h>
> +#include <ctype.h>
> +#include <poppler-qt.h>
> +
> +class PDFDisplay : public QWidget           // picture display widget
> +{
> +public:
> +    PDFDisplay( const char *fileName );
> +   ~PDFDisplay();
> +protected:
> +    void        paintEvent( QPaintEvent * );
> +private:
> +    QPixmap	*pixmap;
> +    PopplerDocument *doc;
> +};
> +
> +PDFDisplay::PDFDisplay( const char *fileName )
> +{
> +  doc = PopplerDocument::load(fileName);
> +  if (doc) {
> +    PopplerPage *page = doc->getPage(0);
> +    if (page) {
> +      page->renderToPixmap(&pixmap);
> +      delete page;
> +    }
> +  } else {
> +    printf("doc not loaded\n");
> +  }
> +}
> +
> +PDFDisplay::~PDFDisplay()
> +{
> +  delete doc;
> +  delete pixmap;
> +}
> +
> +void PDFDisplay::paintEvent( QPaintEvent *e )
> +{
> +  QPainter paint( this );                     // paint widget
> +  if (pixmap)
> +    paint.drawPixmap(0, 0, *pixmap);
> +}
> +
> +int main( int argc, char **argv )
> +{
> +  QApplication a( argc, argv );               // QApplication required!
> +
> +  if ( argc != 2 )  {                          // use argument as file name
> +    printf("usage: test-poppler-qt filename\n");
> +    exit(1);
> +  }
> +  PDFDisplay test( argv[1] );        // create picture display
> +  a.setMainWidget( &test);                // set main widget
> +  test.setCaption("Poppler-Qt Test");
> +  test.show();                            // show it
> +
> +  return a.exec();                        // start event loop
> +}
> _______________________________________________
> poppler mailing list
> poppler at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/poppler
> 



More information about the poppler mailing list