On Saturday 16 May 2009 13:27:46 Albert Astals Cid wrote:
> Splash uses FreeType for fonts so if freetype has subpixel rendering (i
> guess you only want subpixel rendering for fonts?) you should be able to
> get it with some small patch here and there.

I tried, and it's unfortunately not trivial.  Splash simply assumes that text 
will always be monochrome.  I was able to get subpixel rendering working, but 
at the cost of text colour and the alpha channel, so text is always black and 
looks ugly on anything except white.  Maybe with some more work it would be 
possible (a few core methods would need reworking), but I found the Splash 
code difficult to work with, so I gave up on that approach.

> > > It is, noone is going to use Qt4 frontend with Cairo, politics.
> >
> > Mmm, well in the long term it's not ideal, but there are quite a few of
> > us out there that are pragmatists.  Most people will have Cairo installed
> > for Firefox anyway.  I'm guessing it shouldn't be too hard to do, right? 
> > I'll look into it further if I have the time.

I decided to try this approach anyway, and the results are good.  So that's 
one person at least who will be using the Qt4 frontend with Cairo :)  My 
patchset is attached for people to do with as they wish.  I'm afraid I've only 
modified the CMakeFiles, so this will almost certainly break an autotools 
build.

Here is a quick comparison:
Before (Splash): http://snurl.com/if1b1
After (Cairo + Subpixel Rendering): http://snurl.com/if1c2

The lcd filtering could do with some work -- there is some nasty colour 
fringing.  For me though, this is a step in the right direction.

Paul
From 8a00e96a780e195de7905945665242c150cc578c Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <pdgid...@gmail.com>
Date: Wed, 20 May 2009 11:42:28 +0100
Subject: [PATCH 1/4] Basic Cairo backend work completed

---
 qt4/src/CMakeLists.txt      |   13 ++++++++++
 qt4/src/poppler-document.cc |    1 +
 qt4/src/poppler-page.cc     |   54 +++++++++++++++++++++++++++++++++++++++++++
 qt4/src/poppler-private.h   |   12 +++++++++
 qt4/src/poppler-qt4.h       |    3 +-
 5 files changed, 82 insertions(+), 1 deletions(-)

diff --git a/qt4/src/CMakeLists.txt b/qt4/src/CMakeLists.txt
index b18c491..15d9cbf 100644
--- a/qt4/src/CMakeLists.txt
+++ b/qt4/src/CMakeLists.txt
@@ -5,6 +5,10 @@ include_directories(
   ${QT4_INCLUDE_DIR}
   ${CMAKE_CURRENT_BINARY_DIR}
 )
+if (HAVE_CAIRO)
+  include_directories(${CAIRO_INCLUDES})
+  add_definitions(${CAIRO_CFLAGS})
+endif (HAVE_CAIRO)
 
 set(poppler_qt4_SRCS
   poppler-annotation.cc
@@ -31,10 +35,19 @@ if (ENABLE_SPLASH)
     ${CMAKE_SOURCE_DIR}/poppler/ArthurOutputDev.cc
   )
 endif (ENABLE_SPLASH)
+if (HAVE_CAIRO)
+  set(poppler_qt4_SRCS ${poppler_qt4_SRCS}
+    ${CMAKE_SOURCE_DIR}/poppler/CairoOutputDev.cc
+    ${CMAKE_SOURCE_DIR}/poppler/CairoFontEngine.cc
+  )
+endif(HAVE_CAIRO)
 qt4_automoc(${poppler_qt4_SRCS})
 add_library(poppler-qt4 SHARED ${poppler_qt4_SRCS})
 set_target_properties(poppler-qt4 PROPERTIES VERSION 3.1.0 SOVERSION 3)
 target_link_libraries(poppler-qt4 poppler ${QT4_QTCORE_LIBRARY} ${QT4_QTGUI_LIBRARY} ${QT4_QTXML_LIBRARY})
+if (HAVE_CAIRO)
+  target_link_libraries(poppler-qt4 ${CAIRO_LIBRARIES})
+endif (HAVE_CAIRO)
 if(MSVC)
 target_link_libraries(poppler-qt4 poppler ${poppler_LIBS})
 endif(MSVC)
diff --git a/qt4/src/poppler-document.cc b/qt4/src/poppler-document.cc
index 877db52..0de0fce 100644
--- a/qt4/src/poppler-document.cc
+++ b/qt4/src/poppler-document.cc
@@ -449,6 +449,7 @@ namespace Poppler {
 #if defined(HAVE_SPLASH)
         ret << Document::SplashBackend;
         ret << Document::ArthurBackend;
+        ret << Document::CairoBackend;
 #endif
         return ret;
     }
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index 9a27538..0b30db7 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -272,6 +272,60 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
 #endif
       break;
     }
+    case Poppler::Document::CairoBackend:
+    {
+#if defined(HAVE_CAIRO)
+      CairoOutputDev *output_dev =
+        static_cast<CairoOutputDev *>(m_page->parentDoc->getOutputDev());
+      double width, height;
+      int cairo_width, cairo_height, cairo_rowstride, rotate;
+      unsigned char *cairo_data;
+      cairo_surface_t *surface;
+      cairo_t *cairo;
+
+      rotate = rotation + m_page->page->getRotate ();
+      if (rotate == 90 || rotate == 270) {
+        height = m_page->page->getCropWidth ();
+        width = m_page->page->getCropHeight ();
+      } else {
+        width = m_page->page->getCropWidth ();
+        height = m_page->page->getCropHeight ();
+      }
+
+      const double scale = yres / 72.0;
+      cairo_width = (int) ceil(width * scale);
+      cairo_height = (int) ceil(height * scale);
+
+      cairo_rowstride = cairo_width * 4;
+      cairo_data = (Guchar *) gmallocn (cairo_height, cairo_rowstride);
+      // Never transparent
+      memset (cairo_data, 0xff, cairo_height * cairo_rowstride);
+
+      surface = cairo_image_surface_create_for_data(cairo_data,
+                CAIRO_FORMAT_ARGB32,
+                cairo_width, cairo_height,
+                cairo_rowstride);
+
+      cairo = cairo_create (surface);
+      output_dev->setCairo (cairo);
+
+      m_page->parentDoc->doc->displayPageSlice(
+        output_dev, m_page->index + 1, xres, yres, rotation, false, true,
+        false, x, y, w, h);
+
+      // construct a qimage SHARING the raw bitmap data in memory
+      QImage tmpimg(cairo_data, cairo_width, cairo_height,
+                    QImage::Format_ARGB32);
+      img = tmpimg.copy();
+
+      // Clean up
+      output_dev->setCairo(NULL);
+      cairo_surface_destroy (surface);
+      cairo_destroy (cairo);
+      gfree(cairo_data);
+#endif
+      break;
+    }
   }
 
   return img;
diff --git a/qt4/src/poppler-private.h b/qt4/src/poppler-private.h
index acf3124..bd89008 100644
--- a/qt4/src/poppler-private.h
+++ b/qt4/src/poppler-private.h
@@ -38,6 +38,9 @@
 #if defined(HAVE_SPLASH)
 #include <SplashOutputDev.h>
 #endif
+#if defined(HAVE_CAIRO)
+#include <CairoOutputDev.h>
+#endif
 
 #include "poppler-qt4.h"
 
@@ -144,6 +147,15 @@ namespace Poppler {
 #endif
 			break;
 			}
+			case Document::CairoBackend:
+			{
+#if defined(HAVE_CAIRO)
+			CairoOutputDev *cairoOutputDev = new CairoOutputDev();
+			cairoOutputDev->startDoc(doc->getXRef (), doc->getCatalog ());
+			m_outputDev = cairoOutputDev;
+#endif
+			break;
+			}
 			}
 		}
 		return m_outputDev;
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 05c4c0d..b6646b8 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -637,7 +637,8 @@ while (it->hasNext()) {
 	*/
 	enum RenderBackend {
 	    SplashBackend,   ///< Splash backend
-	    ArthurBackend   ///< Arthur (Qt4) backend
+	    ArthurBackend,   ///< Arthur (Qt4) backend
+	    CairoBackend     ///< Cairo backend
 	};
 
 	/**
-- 
1.6.3.1

From 631947a34b77bfa11c0553a034c994ff8e1cd346 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <pdgid...@gmail.com>
Date: Wed, 20 May 2009 14:10:16 +0100
Subject: [PATCH 2/4] Cairo output can now be built (for Qt4) without building Glib backend

---
 CMakeLists.txt |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37ae56d..5c2a58a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,9 +48,9 @@ endif(JPEG_FOUND)
 macro_optional_find_package(Qt3)
 macro_optional_find_package(Qt4)
 macro_optional_find_package(GTK)
+macro_optional_find_package(Cairo)
+set(HAVE_CAIRO ${CAIRO_FOUND})
 if(GLIB_FOUND)
-  macro_optional_find_package(Cairo)
-  set(HAVE_CAIRO ${CAIRO_FOUND})
   set(POPPLER_WITH_GDK ${GDK_FOUND})
   if(CAIRO_FOUND)
     set(CAIRO_REQ "cairo")
-- 
1.6.3.1

From 1adafd3bdf247988e45d1f8acb9cee6f26811072 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <pdgid...@gmail.com>
Date: Wed, 20 May 2009 13:17:29 +0100
Subject: [PATCH 3/4] Setting default QT4 backend to Cairo

---
 qt4/src/poppler-private.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/qt4/src/poppler-private.h b/qt4/src/poppler-private.h
index bd89008..545935d 100644
--- a/qt4/src/poppler-private.h
+++ b/qt4/src/poppler-private.h
@@ -95,7 +95,7 @@ namespace Poppler {
 	void init(GooString *ownerPassword, GooString *userPassword)
 	    {
 		m_fontInfoIterator = 0;
-		m_backend = Document::SplashBackend;
+		m_backend = Document::CairoBackend;
 		m_outputDev = 0;
 		paperColor = Qt::white;
 		m_hints = 0;
-- 
1.6.3.1

From ae925f5104136c85716ccb97be6ec62a5004fb80 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <pdgid...@gmail.com>
Date: Wed, 20 May 2009 13:06:48 +0100
Subject: [PATCH 4/4] Forcing subpixel rendering in Cairo backend

---
 poppler/CairoOutputDev.cc |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 5d4cb82..afaf83b 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -176,6 +176,15 @@ void CairoOutputDev::setCairo(cairo_t *cairo)
   }
   if (cairo != NULL) {
     this->cairo = cairo_reference (cairo);
+    {
+      cairo_font_options_t *options = cairo_font_options_create ();
+      cairo_get_font_options (cairo, options);
+      cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL);
+      cairo_font_options_set_subpixel_order (options, CAIRO_SUBPIXEL_ORDER_RGB);
+      cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_SLIGHT);
+      cairo_set_font_options (cairo, options);
+      cairo_font_options_destroy (options);
+    }
 	/* save the initial matrix so that we can use it for type3 fonts. */
 	//XXX: is this sufficient? could we miss changes to the matrix somehow?
 	cairo_get_matrix(cairo, &orig_matrix);
-- 
1.6.3.1

_______________________________________________
poppler mailing list
poppler@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to