On Wednesday 20 May 2009 23:25:01 Albert Astals Cid wrote:
> Can i have that pdf for local comparison?

Sorry, I'm afraid it's proprietary material.  (Probably shouldn't have used it 
for comparison; oh well!)  It's my copy of "Agile Web Development with Rails".  
I was reading it when I decided I had to get subpixel rendering working :)

However, you should be able to see the results in any PDF.

I've done further work on my patchset since my last e-mail.  After some 
hunting, I discovered how to enable FreeType's default LCD filter (FIR5) in 
the Cairo backend.  (By default Cairo uses the legacy version, hence the 
colour fringing.)  This function (in patch 4) relies on the LCD filtering 
patch for Cairo (http://aur.archlinux.org/packages/cairo-lcd/cairo-lcd/lcd-
filter.patch).

I've also added a further patch that enables slight hinting in the Cairo 
backend.  This has been suggested elsewhere, and does seem to sharpen text up 
a little.

Comparison of FIR5-filtered text with no hinting vs slight hinting:
No hinting: http://snurl.com/ihakt
Slight hinting: http://snurl.com/ihalk

Apologies for re-attaching the whole patchset -- I figured it would be cleaner 
than trying to track changes I made in each patch.

Most of this patchset is of course a quick hack to achieve the desired effect, 
but I do hope that the Cairo backend for Qt4 (patches 1+2) and the slight 
hinting (patch 5) will be considered for merging.  The rest will hopefully be 
helpful to anyone else wanting beautiful fonts in Okular right now.

Paul
From de4279b0a174a7c1b5e2a6974488d45aa5953842 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <[email protected]>
Date: Wed, 20 May 2009 14:10:16 +0100
Subject: [PATCH 2/5] 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 03085a5..4018982 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 899e96825df616511a8937f6012e112c7cebb379 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <[email protected]>
Date: Thu, 21 May 2009 10:55:49 +0100
Subject: [PATCH 5/5] Enabling slight hinting in Cairo Backend

Originally suggested at:
http://bugs.freedesktop.org/show_bug.cgi?id=3307#c20
---
 poppler/CairoFontEngine.cc |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index a4edd12..8bf7581 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -123,7 +123,7 @@ CairoFont::getSubstitutionCorrection(GfxFont *gfxFont)
 	cairo_matrix_t m;
 	cairo_matrix_init_identity(&m);
 	cairo_font_options_t *options = cairo_font_options_create();
-	cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
+	cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_SLIGHT);
 	cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF);
 	cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options);
 
@@ -178,7 +178,7 @@ _ft_new_face_uncached (FT_Library lib,
     return gFalse;
 
   font_face = cairo_ft_font_face_create_for_ft_face (face,
-							  FT_LOAD_NO_HINTING |
+							  FT_LOAD_TARGET_LIGHT |
 							  FT_LOAD_NO_BITMAP);
   if (cairo_font_face_set_user_data (font_face,
 				     &_ft_cairo_key,
@@ -325,7 +325,7 @@ _ft_new_face (FT_Library lib,
   _ft_open_faces = l;
 
   l->font_face = cairo_ft_font_face_create_for_ft_face (tmpl.face,
-							  FT_LOAD_NO_HINTING |
+							  FT_LOAD_TARGET_LIGHT |
 							  FT_LOAD_NO_BITMAP);
   if (cairo_font_face_set_user_data (l->font_face,
 				     &_ft_cairo_key,
-- 
1.6.3.1

From 23ef6b1d1e130a5ef74335f5d1a10f99459e3051 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <[email protected]>
Date: Wed, 20 May 2009 13:17:29 +0100
Subject: [PATCH 3/5] 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 c04f338133005f6b52e53e797034ddbe59091d6a Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <[email protected]>
Date: Wed, 20 May 2009 11:42:28 +0100
Subject: [PATCH 1/5] Basic Cairo backend work completed

---
 qt4/src/CMakeLists.txt      |   13 ++++++++++
 qt4/src/poppler-document.cc |    1 +
 qt4/src/poppler-page.cc     |   55 +++++++++++++++++++++++++++++++++++++++++++
 qt4/src/poppler-private.h   |   12 +++++++++
 qt4/src/poppler-qt4.h       |    3 +-
 5 files changed, 83 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..069dad9 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -30,6 +30,7 @@
 #include <QtGui/QPainter>
 
 #include <config.h>
+#include <math.h>
 #include <PDFDoc.h>
 #include <Catalog.h>
 #include <Form.h>
@@ -272,6 +273,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 6e858f2133cae7ccbfc0686d6c55c247ad124200 Mon Sep 17 00:00:00 2001
From: Paul Gideon Dann <[email protected]>
Date: Wed, 20 May 2009 13:06:48 +0100
Subject: [PATCH 4/5] Forcing subpixel rendering in Cairo backend

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

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 5d4cb82..99e3838 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -176,6 +176,16 @@ 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_lcd_filter (options, CAIRO_LCD_FILTER_FIR5);
+      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
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to