[cairo-commit] 8 commits - boilerplate/cairo-boilerplate-egl.c boilerplate/cairo-boilerplate-gl.c boilerplate/cairo-boilerplate-glx.c boilerplate/cairo-boilerplate-wgl.c boilerplate/Makefile.sources boilerplate/Makefile.win32.features build/Makefile.win32.features-h src/cairo-fixed-private.h src/cairo-font-options.c src/cairo-ft-font.c src/cairo-image-surface.c src/cairoint.h src/cairo-surface.c src/cairo-types-private.h src/cairo-wgl-context.c src/cairo-xlib-screen.c src/Makefile.win32.features test/a1-rasterisation.c test/a1-rasterisation-rectangles.ref.png test/a1-rasterisation-triangles.ref.png test/halo.c test/Makefile.am test/Makefile.sources

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 17 01:21:38 PDT 2010


 boilerplate/Makefile.sources             |    4 
 boilerplate/Makefile.win32.features      |    8 
 boilerplate/cairo-boilerplate-egl.c      |  141 ++++++
 boilerplate/cairo-boilerplate-gl.c       |  492 ----------------------
 boilerplate/cairo-boilerplate-glx.c      |  401 ++++++++++++++++++
 boilerplate/cairo-boilerplate-wgl.c      |  236 ++++++++++
 build/Makefile.win32.features-h          |    1 
 src/Makefile.win32.features              |    8 
 src/cairo-fixed-private.h                |   18 
 src/cairo-font-options.c                 |   51 ++
 src/cairo-ft-font.c                      |  675 ++++++++++++++++++++++---------
 src/cairo-image-surface.c                |   58 +-
 src/cairo-surface.c                      |    1 
 src/cairo-types-private.h                |   25 +
 src/cairo-wgl-context.c                  |   16 
 src/cairo-xlib-screen.c                  |   28 +
 src/cairoint.h                           |    7 
 test/Makefile.am                         |    2 
 test/Makefile.sources                    |    1 
 test/a1-rasterisation-rectangles.ref.png |binary
 test/a1-rasterisation-triangles.ref.png  |binary
 test/a1-rasterisation.c                  |  101 ++++
 test/halo.c                              |   36 +
 23 files changed, 1592 insertions(+), 718 deletions(-)

New commits:
commit a9a22649e2ffa1cd3720c8555dc3c6aff2040e3d
Author: Zoxc <zoxc32 at gmail.com>
Date:   Wed Jun 16 21:33:30 2010 +0200

    wgl: Only reset GL context on the dummy window.
    
    This changes the WGL context destruction code to only reset the GL
    context for the dummy window, since doing it on <nothing> is an
    invalid operation.

diff --git a/src/cairo-wgl-context.c b/src/cairo-wgl-context.c
index 7bba1d3..ac15b1d 100644
--- a/src/cairo-wgl-context.c
+++ b/src/cairo-wgl-context.c
@@ -129,13 +129,11 @@ _wgl_destroy (void *abstract_ctx)
 {
     cairo_wgl_context_t *ctx = abstract_ctx;
 
-    if (ctx->dummy_dc != 0) {
+    if (ctx->dummy_dc != 0) {	
+        wglMakeCurrent (ctx->dummy_dc, 0);
         ReleaseDC (ctx->dummy_wnd, ctx->dummy_dc);
         DestroyWindow (ctx->dummy_wnd);
-        CloseHandle (ctx->dummy_wnd);
     }
-
-    wglMakeCurrent (0, 0);
 }
 
 static cairo_status_t
commit ca35e09ece5107c3ebc9f111d4a3d96d69aa3d03
Author: Zoxc <zoxc32 at gmail.com>
Date:   Mon Jun 14 20:34:52 2010 +0200

    gl: Added wgl boilerplate and moved the glx and egl boilerplates into their own files.

diff --git a/boilerplate/Makefile.sources b/boilerplate/Makefile.sources
index b590b7f..d247510 100644
--- a/boilerplate/Makefile.sources
+++ b/boilerplate/Makefile.sources
@@ -25,7 +25,9 @@ cairo_boilerplate_private = \
 
 cairo_boilerplate_directfb_sources = cairo-boilerplate-directfb.c
 cairo_boilerplate_drm_sources = cairo-boilerplate-drm.c
-cairo_boilerplate_gl_sources = cairo-boilerplate-gl.c
+cairo_boilerplate_glx_sources = cairo-boilerplate-glx.c
+cairo_boilerplate_wgl_sources = cairo-boilerplate-wgl.c
+cairo_boilerplate_egl_sources = cairo-boilerplate-egl.c
 cairo_boilerplate_pdf_sources = cairo-boilerplate-pdf.c
 cairo_boilerplate_ps_sources = cairo-boilerplate-ps.c
 cairo_boilerplate_qt_sources = cairo-boilerplate-qt.cpp
diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features
index fd0e9c7..d79fe2f 100644
--- a/boilerplate/Makefile.win32.features
+++ b/boilerplate/Makefile.win32.features
@@ -209,6 +209,14 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_png_private)
 enabled_cairo_boilerplate_sources += $(cairo_boilerplate_png_sources)
 endif
 
+supported_cairo_boilerplate_headers += $(cairo_boilerplate_glew_headers)
+all_cairo_boilerplate_headers += $(cairo_boilerplate_glew_headers)
+all_cairo_boilerplate_private += $(cairo_boilerplate_glew_private)
+all_cairo_boilerplate_sources += $(cairo_boilerplate_glew_sources)
+enabled_cairo_boilerplate_headers += $(cairo_boilerplate_glew_headers)
+enabled_cairo_boilerplate_private += $(cairo_boilerplate_glew_private)
+enabled_cairo_boilerplate_sources += $(cairo_boilerplate_glew_sources)
+
 unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers)
 all_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers)
 all_cairo_boilerplate_private += $(cairo_boilerplate_gl_private)
diff --git a/boilerplate/cairo-boilerplate-egl.c b/boilerplate/cairo-boilerplate-egl.c
new file mode 100644
index 0000000..413c7ed
--- /dev/null
+++ b/boilerplate/cairo-boilerplate-egl.c
@@ -0,0 +1,141 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Chris Wilson.
+ */
+
+#include "cairo-boilerplate-private.h"
+
+#include <cairo-gl.h>
+
+static const cairo_user_data_key_t gl_closure_key;
+
+typedef struct _egl_target_closure {
+    EGLDisplay dpy;
+    EGLContext ctx;
+
+    cairo_device_t *device;
+    cairo_surface_t *surface;
+} egl_target_closure_t;
+
+static void
+_cairo_boilerplate_egl_cleanup (void *closure)
+{
+    egl_target_closure_t *gltc = closure;
+
+    cairo_device_finish (gltc->device);
+    cairo_device_destroy (gltc->device);
+
+    eglDestroyContext (gltc->dpy, gltc->ctx);
+    eglMakeCurrent (gltc->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate (gltc->dpy);
+
+    free (gltc);
+}
+
+static cairo_surface_t *
+_cairo_boilerplate_egl_create_surface (const char		 *name,
+				      cairo_content_t		  content,
+				      double			  width,
+				      double			  height,
+				      double			  max_width,
+				      double			  max_height,
+				      cairo_boilerplate_mode_t	  mode,
+				      int			  id,
+				      void			**closure)
+{
+    egl_target_closure_t *gltc;
+    cairo_surface_t *surface;
+    int major, minor;
+    EGLConfig *configs;
+    EGLint numConfigs;
+
+    gltc = xcalloc (1, sizeof (egl_target_closure_t));
+    *closure = gltc;
+
+    gltc->dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+
+    if (! eglInitialize (gltc->dpy, &major, &minor)) {
+	free (gltc);
+	return NULL;
+    }
+
+    eglGetConfigs (gltc->dpy, NULL, 0, &numConfigs);
+    configs = xmalloc(sizeof(*configs) *numConfigs);
+    eglGetConfigs (gltc->dpy, configs, numConfigs, &numConfigs);
+
+    eglBindAPI (EGL_OPENGL_API);
+
+    gltc->ctx = eglCreateContext (gltc->dpy, configs[0], EGL_NO_CONTEXT, NULL);
+    if (gltc->ctx == EGL_NO_CONTEXT) {
+	eglTerminate (gltc->dpy);
+	free (gltc);
+	return NULL;
+    }
+
+    gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx);
+
+    gltc->surface = surface = cairo_gl_surface_create (gltc->device,
+						       content,
+					               ceil (width),
+						       ceil (height));
+    if (cairo_surface_status (surface))
+	_cairo_boilerplate_egl_cleanup (gltc);
+
+    return surface;
+}
+
+static void
+_cairo_boilerplate_egl_synchronize (void *closure)
+{
+    egl_target_closure_t *gltc = closure;
+
+    if (cairo_device_acquire (gltc->device))
+        return;
+
+    glFinish ();
+
+    cairo_device_release (gltc->device);
+}
+
+static const cairo_boilerplate_target_t targets[] = {
+    {
+	"egl", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	"cairo_egl_device_create",
+	_cairo_boilerplate_egl_create_surface,
+	NULL, NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_egl_cleanup,
+	_cairo_boilerplate_egl_synchronize,
+	TRUE, FALSE, FALSE
+    }
+};
+CAIRO_BOILERPLATE (egl, targets)
diff --git a/boilerplate/cairo-boilerplate-gl.c b/boilerplate/cairo-boilerplate-gl.c
deleted file mode 100644
index 965beaa..0000000
--- a/boilerplate/cairo-boilerplate-gl.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2009 Chris Wilson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Chris Wilson.
- */
-
-#include "cairo-boilerplate-private.h"
-
-#include <cairo-gl.h>
-
-#include <X11/X.h>
-#include <X11/Xutil.h> /* for XDestroyImage */
-
-static const cairo_user_data_key_t gl_closure_key;
-
-typedef struct _gl_target_closure {
-    Display *dpy;
-    int screen;
-    Window drawable;
-
-    GLXContext ctx;
-    cairo_device_t *device;
-    cairo_surface_t *surface;
-} gl_target_closure_t;
-
-static void
-_cairo_boilerplate_gl_cleanup (void *closure)
-{
-    gl_target_closure_t *gltc = closure;
-
-    cairo_device_finish (gltc->device);
-    cairo_device_destroy (gltc->device);
-
-    glXDestroyContext (gltc->dpy, gltc->ctx);
-
-    if (gltc->drawable)
-	XDestroyWindow (gltc->dpy, gltc->drawable);
-    XCloseDisplay (gltc->dpy);
-
-    free (gltc);
-}
-
-static cairo_surface_t *
-_cairo_boilerplate_gl_create_surface (const char		 *name,
-				      cairo_content_t		  content,
-				      double			  width,
-				      double			  height,
-				      double			  max_width,
-				      double			  max_height,
-				      cairo_boilerplate_mode_t	  mode,
-				      int			  id,
-				      void			**closure)
-{
-    int rgba_attribs[] = { GLX_RGBA,
-			   GLX_RED_SIZE, 1,
-			   GLX_GREEN_SIZE, 1,
-			   GLX_BLUE_SIZE, 1,
-			   GLX_ALPHA_SIZE, 1,
-			   GLX_DOUBLEBUFFER,
-			   None };
-    int rgb_attribs[] = { GLX_RGBA,
-			  GLX_RED_SIZE, 1,
-			  GLX_GREEN_SIZE, 1,
-			  GLX_BLUE_SIZE, 1,
-			  GLX_DOUBLEBUFFER,
-			  None };
-    XVisualInfo *visinfo;
-    GLXContext ctx;
-    gl_target_closure_t *gltc;
-    cairo_surface_t *surface;
-    Display *dpy;
-
-    gltc = calloc (1, sizeof (gl_target_closure_t));
-    *closure = gltc;
-
-    if (width == 0)
-	width = 1;
-    if (height == 0)
-	height = 1;
-
-    dpy = XOpenDisplay (NULL);
-    gltc->dpy = dpy;
-    if (!gltc->dpy) {
-	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
-	free (gltc);
-	return NULL;
-    }
-
-    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
-	XSynchronize (gltc->dpy, 1);
-
-    if (content == CAIRO_CONTENT_COLOR)
-	visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs);
-    else
-	visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
-
-    if (visinfo == NULL) {
-	fprintf (stderr, "Failed to create RGB, double-buffered visual\n");
-	XCloseDisplay (dpy);
-	free (gltc);
-	return NULL;
-    }
-
-    ctx = glXCreateContext (dpy, visinfo, NULL, True);
-    XFree (visinfo);
-
-    gltc->ctx = ctx;
-    gltc->device = cairo_glx_device_create (dpy, ctx);
-
-    gltc->surface = surface = cairo_gl_surface_create (gltc->device,
-						       content,
-					               ceil (width),
-						       ceil (height));
-    if (cairo_surface_status (surface))
-	_cairo_boilerplate_gl_cleanup (gltc);
-
-    return surface;
-}
-
-static cairo_surface_t *
-_cairo_boilerplate_gl_create_window (const char			 *name,
-				     cairo_content_t		  content,
-				     double			  width,
-				     double			  height,
-				     double			  max_width,
-				     double			  max_height,
-				     cairo_boilerplate_mode_t	  mode,
-				     int			  id,
-				     void			**closure)
-{
-    int rgba_attribs[] = { GLX_RGBA,
-			   GLX_RED_SIZE, 1,
-			   GLX_GREEN_SIZE, 1,
-			   GLX_BLUE_SIZE, 1,
-			   GLX_ALPHA_SIZE, 1,
-			   GLX_DOUBLEBUFFER,
-			   None };
-    XVisualInfo *vi;
-    GLXContext ctx;
-    gl_target_closure_t *gltc;
-    cairo_surface_t *surface;
-    Display *dpy;
-    XSetWindowAttributes attr;
-
-    gltc = calloc (1, sizeof (gl_target_closure_t));
-    *closure = gltc;
-
-    if (width == 0)
-	width = 1;
-    if (height == 0)
-	height = 1;
-
-    dpy = XOpenDisplay (NULL);
-    gltc->dpy = dpy;
-    if (!gltc->dpy) {
-	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
-	free (gltc);
-	return NULL;
-    }
-
-    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
-	XSynchronize (gltc->dpy, 1);
-
-    vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
-    if (vi == NULL) {
-	fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
-	XCloseDisplay (dpy);
-	free (gltc);
-	return NULL;
-    }
-
-    attr.colormap = XCreateColormap (dpy,
-				     RootWindow (dpy, vi->screen),
-				     vi->visual,
-				     AllocNone);
-    attr.border_pixel = 0;
-    attr.override_redirect = True;
-    gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
-				    width, height, 0, vi->depth,
-				    InputOutput, vi->visual,
-				    CWOverrideRedirect | CWBorderPixel | CWColormap,
-				    &attr);
-    XMapWindow (dpy, gltc->drawable);
-
-    ctx = glXCreateContext (dpy, vi, NULL, True);
-    XFree (vi);
-
-    gltc->ctx = ctx;
-    gltc->device = cairo_glx_device_create (dpy, ctx);
-
-    gltc->surface = surface = cairo_gl_surface_create_for_window (gltc->device,
-								  gltc->drawable,
-								  ceil (width),
-								  ceil (height));
-    if (cairo_surface_status (surface))
-	_cairo_boilerplate_gl_cleanup (gltc);
-
-    return surface;
-}
-
-static cairo_surface_t *
-_cairo_boilerplate_gl_create_window_db (const char		 *name,
-					cairo_content_t		  content,
-					double			  width,
-					double			  height,
-					double			  max_width,
-					double			  max_height,
-					cairo_boilerplate_mode_t  mode,
-					int			  id,
-					void			**closure)
-{
-    int rgba_attribs[] = { GLX_RGBA,
-			   GLX_RED_SIZE, 1,
-			   GLX_GREEN_SIZE, 1,
-			   GLX_BLUE_SIZE, 1,
-			   GLX_ALPHA_SIZE, 1,
-			   GLX_DOUBLEBUFFER,
-			   None };
-    XVisualInfo *vi;
-    GLXContext ctx;
-    gl_target_closure_t *gltc;
-    cairo_surface_t *surface;
-    Display *dpy;
-    XSetWindowAttributes attr;
-    cairo_status_t status;
-
-    gltc = calloc (1, sizeof (gl_target_closure_t));
-    *closure = gltc;
-
-    if (width == 0)
-	width = 1;
-    if (height == 0)
-	height = 1;
-
-    dpy = XOpenDisplay (NULL);
-    gltc->dpy = dpy;
-    if (!gltc->dpy) {
-	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
-	free (gltc);
-	return NULL;
-    }
-
-    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
-	XSynchronize (gltc->dpy, 1);
-
-    vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
-    if (vi == NULL) {
-	fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
-	XCloseDisplay (dpy);
-	free (gltc);
-	return NULL;
-    }
-
-    attr.colormap = XCreateColormap (dpy,
-				     RootWindow (dpy, vi->screen),
-				     vi->visual,
-				     AllocNone);
-    attr.border_pixel = 0;
-    attr.override_redirect = True;
-    gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
-				    width, height, 0, vi->depth,
-				    InputOutput, vi->visual,
-				    CWOverrideRedirect | CWBorderPixel | CWColormap,
-				    &attr);
-    XMapWindow (dpy, gltc->drawable);
-
-    ctx = glXCreateContext (dpy, vi, NULL, True);
-    XFree (vi);
-
-    gltc->ctx = ctx;
-    gltc->device = cairo_glx_device_create (dpy, ctx);
-
-    gltc->surface = cairo_gl_surface_create_for_window (gltc->device,
-							gltc->drawable,
-							ceil (width),
-							ceil (height));
-    surface = cairo_surface_create_similar (gltc->surface, content, width, height);
-    status = cairo_surface_set_user_data (surface, &gl_closure_key, gltc, NULL);
-    if (status == CAIRO_STATUS_SUCCESS)
-	return surface;
-
-    cairo_surface_destroy (surface);
-    _cairo_boilerplate_gl_cleanup (gltc);
-    return cairo_boilerplate_surface_create_in_error (status);
-}
-
-static cairo_status_t
-_cairo_boilerplate_gl_finish_window (cairo_surface_t		*surface)
-{
-    gl_target_closure_t *gltc = cairo_surface_get_user_data (surface,
-							     &gl_closure_key);
-
-    if (gltc != NULL && gltc->surface != NULL) {
-	cairo_t *cr;
-
-	cr = cairo_create (gltc->surface);
-	cairo_surface_set_device_offset (surface, 0, 0);
-	cairo_set_source_surface (cr, surface, 0, 0);
-	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-	cairo_paint (cr);
-	cairo_destroy (cr);
-
-	surface = gltc->surface;
-    }
-
-    cairo_gl_surface_swapbuffers (surface);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_boilerplate_gl_synchronize (void *closure)
-{
-    gl_target_closure_t *gltc = closure;
-
-    if (cairo_device_acquire (gltc->device))
-        return;
-
-    glFinish ();
-
-    cairo_device_release (gltc->device);
-}
-
-#if CAIRO_HAS_EGL_FUNCTIONS
-typedef struct _egl_target_closure {
-    EGLDisplay dpy;
-    EGLContext ctx;
-
-    cairo_device_t *device;
-    cairo_surface_t *surface;
-} egl_target_closure_t;
-
-static void
-_cairo_boilerplate_egl_cleanup (void *closure)
-{
-    egl_target_closure_t *gltc = closure;
-
-    cairo_device_finish (gltc->device);
-    cairo_device_destroy (gltc->device);
-
-    eglDestroyContext (gltc->dpy, gltc->ctx);
-    eglMakeCurrent (gltc->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate (gltc->dpy);
-
-    free (gltc);
-}
-
-static cairo_surface_t *
-_cairo_boilerplate_egl_create_surface (const char		 *name,
-				      cairo_content_t		  content,
-				      double			  width,
-				      double			  height,
-				      double			  max_width,
-				      double			  max_height,
-				      cairo_boilerplate_mode_t	  mode,
-				      int			  id,
-				      void			**closure)
-{
-    egl_target_closure_t *gltc;
-    cairo_surface_t *surface;
-    int major, minor;
-    EGLConfig *configs;
-    EGLint numConfigs;
-
-    gltc = xcalloc (1, sizeof (gl_target_closure_t));
-    *closure = gltc;
-
-    gltc->dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
-
-    if (! eglInitialize (gltc->dpy, &major, &minor)) {
-	free (gltc);
-	return NULL;
-    }
-
-    eglGetConfigs (gltc->dpy, NULL, 0, &numConfigs);
-    configs = xmalloc(sizeof(*configs) *numConfigs);
-    eglGetConfigs (gltc->dpy, configs, numConfigs, &numConfigs);
-
-    eglBindAPI (EGL_OPENGL_API);
-
-    gltc->ctx = eglCreateContext (gltc->dpy, configs[0], EGL_NO_CONTEXT, NULL);
-    if (gltc->ctx == EGL_NO_CONTEXT) {
-	eglTerminate (gltc->dpy);
-	free (gltc);
-	return NULL;
-    }
-
-    gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx);
-
-    gltc->surface = surface = cairo_gl_surface_create (gltc->device,
-						       content,
-					               ceil (width),
-						       ceil (height));
-    if (cairo_surface_status (surface))
-	_cairo_boilerplate_egl_cleanup (gltc);
-
-    return surface;
-}
-#endif
-
-static const cairo_boilerplate_target_t targets[] = {
-    {
-	"gl", "gl", NULL, NULL,
-	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
-	"cairo_gl_surface_create",
-	_cairo_boilerplate_gl_create_surface,
-	NULL, NULL,
-	_cairo_boilerplate_get_image_surface,
-	cairo_surface_write_to_png,
-	_cairo_boilerplate_gl_cleanup,
-	_cairo_boilerplate_gl_synchronize,
-	TRUE, FALSE, FALSE
-    },
-    {
-	"gl", "gl", NULL, NULL,
-	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR, 1,
-	"cairo_gl_surface_create",
-	_cairo_boilerplate_gl_create_surface,
-	NULL, NULL,
-	_cairo_boilerplate_get_image_surface,
-	cairo_surface_write_to_png,
-	_cairo_boilerplate_gl_cleanup,
-	_cairo_boilerplate_gl_synchronize,
-	FALSE, FALSE, FALSE
-    },
-    {
-	"gl-window", "gl", NULL, NULL,
-	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
-	"cairo_gl_surface_create_for_window",
-	_cairo_boilerplate_gl_create_window,
-	NULL,
-	_cairo_boilerplate_gl_finish_window,
-	_cairo_boilerplate_get_image_surface,
-	cairo_surface_write_to_png,
-	_cairo_boilerplate_gl_cleanup,
-	_cairo_boilerplate_gl_synchronize,
-	FALSE, FALSE, FALSE
-    },
-    {
-	"gl-window&", "gl", NULL, NULL,
-	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
-	"cairo_gl_surface_create_for_window",
-	_cairo_boilerplate_gl_create_window_db,
-	NULL,
-	_cairo_boilerplate_gl_finish_window,
-	_cairo_boilerplate_get_image_surface,
-	cairo_surface_write_to_png,
-	_cairo_boilerplate_gl_cleanup,
-	_cairo_boilerplate_gl_synchronize,
-	FALSE, FALSE, FALSE
-    },
-#if CAIRO_HAS_EGL_FUNCTIONS
-    {
-	"egl", "gl", NULL, NULL,
-	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
-	"cairo_egl_device_create",
-	_cairo_boilerplate_egl_create_surface,
-	NULL, NULL,
-	_cairo_boilerplate_get_image_surface,
-	cairo_surface_write_to_png,
-	_cairo_boilerplate_egl_cleanup,
-	_cairo_boilerplate_gl_synchronize,
-	TRUE, FALSE, FALSE
-    },
-#endif
-};
-CAIRO_BOILERPLATE (gl, targets)
diff --git a/boilerplate/cairo-boilerplate-glx.c b/boilerplate/cairo-boilerplate-glx.c
new file mode 100644
index 0000000..66a031b
--- /dev/null
+++ b/boilerplate/cairo-boilerplate-glx.c
@@ -0,0 +1,401 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Chris Wilson.
+ */
+
+#include "cairo-boilerplate-private.h"
+
+#include <cairo-gl.h>
+
+#include <X11/X.h>
+#include <X11/Xutil.h> /* for XDestroyImage */
+
+static const cairo_user_data_key_t gl_closure_key;
+
+typedef struct _gl_target_closure {
+    Display *dpy;
+    int screen;
+    Window drawable;
+
+    GLXContext ctx;
+    cairo_device_t *device;
+    cairo_surface_t *surface;
+} gl_target_closure_t;
+
+static void
+_cairo_boilerplate_gl_cleanup (void *closure)
+{
+    gl_target_closure_t *gltc = closure;
+
+    cairo_device_finish (gltc->device);
+    cairo_device_destroy (gltc->device);
+
+    glXDestroyContext (gltc->dpy, gltc->ctx);
+
+    if (gltc->drawable)
+	XDestroyWindow (gltc->dpy, gltc->drawable);
+    XCloseDisplay (gltc->dpy);
+
+    free (gltc);
+}
+
+static cairo_surface_t *
+_cairo_boilerplate_gl_create_surface (const char		 *name,
+				      cairo_content_t		  content,
+				      double			  width,
+				      double			  height,
+				      double			  max_width,
+				      double			  max_height,
+				      cairo_boilerplate_mode_t	  mode,
+				      int			  id,
+				      void			**closure)
+{
+    int rgba_attribs[] = { GLX_RGBA,
+			   GLX_RED_SIZE, 1,
+			   GLX_GREEN_SIZE, 1,
+			   GLX_BLUE_SIZE, 1,
+			   GLX_ALPHA_SIZE, 1,
+			   GLX_DOUBLEBUFFER,
+			   None };
+    int rgb_attribs[] = { GLX_RGBA,
+			  GLX_RED_SIZE, 1,
+			  GLX_GREEN_SIZE, 1,
+			  GLX_BLUE_SIZE, 1,
+			  GLX_DOUBLEBUFFER,
+			  None };
+    XVisualInfo *visinfo;
+    GLXContext ctx;
+    gl_target_closure_t *gltc;
+    cairo_surface_t *surface;
+    Display *dpy;
+
+    gltc = calloc (1, sizeof (gl_target_closure_t));
+    *closure = gltc;
+
+    if (width == 0)
+	width = 1;
+    if (height == 0)
+	height = 1;
+
+    dpy = XOpenDisplay (NULL);
+    gltc->dpy = dpy;
+    if (!gltc->dpy) {
+	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
+	free (gltc);
+	return NULL;
+    }
+
+    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
+	XSynchronize (gltc->dpy, 1);
+
+    if (content == CAIRO_CONTENT_COLOR)
+	visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs);
+    else
+	visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
+
+    if (visinfo == NULL) {
+	fprintf (stderr, "Failed to create RGB, double-buffered visual\n");
+	XCloseDisplay (dpy);
+	free (gltc);
+	return NULL;
+    }
+
+    ctx = glXCreateContext (dpy, visinfo, NULL, True);
+    XFree (visinfo);
+
+    gltc->ctx = ctx;
+    gltc->device = cairo_glx_device_create (dpy, ctx);
+
+    gltc->surface = surface = cairo_gl_surface_create (gltc->device,
+						       content,
+					               ceil (width),
+						       ceil (height));
+    if (cairo_surface_status (surface))
+	_cairo_boilerplate_gl_cleanup (gltc);
+
+    return surface;
+}
+
+static cairo_surface_t *
+_cairo_boilerplate_gl_create_window (const char			 *name,
+				     cairo_content_t		  content,
+				     double			  width,
+				     double			  height,
+				     double			  max_width,
+				     double			  max_height,
+				     cairo_boilerplate_mode_t	  mode,
+				     int			  id,
+				     void			**closure)
+{
+    int rgba_attribs[] = { GLX_RGBA,
+			   GLX_RED_SIZE, 1,
+			   GLX_GREEN_SIZE, 1,
+			   GLX_BLUE_SIZE, 1,
+			   GLX_ALPHA_SIZE, 1,
+			   GLX_DOUBLEBUFFER,
+			   None };
+    XVisualInfo *vi;
+    GLXContext ctx;
+    gl_target_closure_t *gltc;
+    cairo_surface_t *surface;
+    Display *dpy;
+    XSetWindowAttributes attr;
+
+    gltc = calloc (1, sizeof (gl_target_closure_t));
+    *closure = gltc;
+
+    if (width == 0)
+	width = 1;
+    if (height == 0)
+	height = 1;
+
+    dpy = XOpenDisplay (NULL);
+    gltc->dpy = dpy;
+    if (!gltc->dpy) {
+	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
+	free (gltc);
+	return NULL;
+    }
+
+    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
+	XSynchronize (gltc->dpy, 1);
+
+    vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
+    if (vi == NULL) {
+	fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
+	XCloseDisplay (dpy);
+	free (gltc);
+	return NULL;
+    }
+
+    attr.colormap = XCreateColormap (dpy,
+				     RootWindow (dpy, vi->screen),
+				     vi->visual,
+				     AllocNone);
+    attr.border_pixel = 0;
+    attr.override_redirect = True;
+    gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
+				    width, height, 0, vi->depth,
+				    InputOutput, vi->visual,
+				    CWOverrideRedirect | CWBorderPixel | CWColormap,
+				    &attr);
+    XMapWindow (dpy, gltc->drawable);
+
+    ctx = glXCreateContext (dpy, vi, NULL, True);
+    XFree (vi);
+
+    gltc->ctx = ctx;
+    gltc->device = cairo_glx_device_create (dpy, ctx);
+
+    gltc->surface = surface = cairo_gl_surface_create_for_window (gltc->device,
+								  gltc->drawable,
+								  ceil (width),
+								  ceil (height));
+    if (cairo_surface_status (surface))
+	_cairo_boilerplate_gl_cleanup (gltc);
+
+    return surface;
+}
+
+static cairo_surface_t *
+_cairo_boilerplate_gl_create_window_db (const char		 *name,
+					cairo_content_t		  content,
+					double			  width,
+					double			  height,
+					double			  max_width,
+					double			  max_height,
+					cairo_boilerplate_mode_t  mode,
+					int			  id,
+					void			**closure)
+{
+    int rgba_attribs[] = { GLX_RGBA,
+			   GLX_RED_SIZE, 1,
+			   GLX_GREEN_SIZE, 1,
+			   GLX_BLUE_SIZE, 1,
+			   GLX_ALPHA_SIZE, 1,
+			   GLX_DOUBLEBUFFER,
+			   None };
+    XVisualInfo *vi;
+    GLXContext ctx;
+    gl_target_closure_t *gltc;
+    cairo_surface_t *surface;
+    Display *dpy;
+    XSetWindowAttributes attr;
+    cairo_status_t status;
+
+    gltc = calloc (1, sizeof (gl_target_closure_t));
+    *closure = gltc;
+
+    if (width == 0)
+	width = 1;
+    if (height == 0)
+	height = 1;
+
+    dpy = XOpenDisplay (NULL);
+    gltc->dpy = dpy;
+    if (!gltc->dpy) {
+	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
+	free (gltc);
+	return NULL;
+    }
+
+    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
+	XSynchronize (gltc->dpy, 1);
+
+    vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
+    if (vi == NULL) {
+	fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
+	XCloseDisplay (dpy);
+	free (gltc);
+	return NULL;
+    }
+
+    attr.colormap = XCreateColormap (dpy,
+				     RootWindow (dpy, vi->screen),
+				     vi->visual,
+				     AllocNone);
+    attr.border_pixel = 0;
+    attr.override_redirect = True;
+    gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
+				    width, height, 0, vi->depth,
+				    InputOutput, vi->visual,
+				    CWOverrideRedirect | CWBorderPixel | CWColormap,
+				    &attr);
+    XMapWindow (dpy, gltc->drawable);
+
+    ctx = glXCreateContext (dpy, vi, NULL, True);
+    XFree (vi);
+
+    gltc->ctx = ctx;
+    gltc->device = cairo_glx_device_create (dpy, ctx);
+
+    gltc->surface = cairo_gl_surface_create_for_window (gltc->device,
+							gltc->drawable,
+							ceil (width),
+							ceil (height));
+    surface = cairo_surface_create_similar (gltc->surface, content, width, height);
+    status = cairo_surface_set_user_data (surface, &gl_closure_key, gltc, NULL);
+    if (status == CAIRO_STATUS_SUCCESS)
+	return surface;
+
+    cairo_surface_destroy (surface);
+    _cairo_boilerplate_gl_cleanup (gltc);
+    return cairo_boilerplate_surface_create_in_error (status);
+}
+
+static cairo_status_t
+_cairo_boilerplate_gl_finish_window (cairo_surface_t		*surface)
+{
+    gl_target_closure_t *gltc = cairo_surface_get_user_data (surface,
+							     &gl_closure_key);
+
+    if (gltc != NULL && gltc->surface != NULL) {
+	cairo_t *cr;
+
+	cr = cairo_create (gltc->surface);
+	cairo_surface_set_device_offset (surface, 0, 0);
+	cairo_set_source_surface (cr, surface, 0, 0);
+	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+	cairo_paint (cr);
+	cairo_destroy (cr);
+
+	surface = gltc->surface;
+    }
+
+    cairo_gl_surface_swapbuffers (surface);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_boilerplate_gl_synchronize (void *closure)
+{
+    gl_target_closure_t *gltc = closure;
+
+    if (cairo_device_acquire (gltc->device))
+        return;
+
+    glFinish ();
+
+    cairo_device_release (gltc->device);
+}
+
+static const cairo_boilerplate_target_t targets[] = {
+    {
+	"gl", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	"cairo_gl_surface_create",
+	_cairo_boilerplate_gl_create_surface,
+	NULL, NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_gl_cleanup,
+	_cairo_boilerplate_gl_synchronize,
+	TRUE, FALSE, FALSE
+    },
+    {
+	"gl", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR, 1,
+	"cairo_gl_surface_create",
+	_cairo_boilerplate_gl_create_surface,
+	NULL, NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_gl_cleanup,
+	_cairo_boilerplate_gl_synchronize,
+	FALSE, FALSE, FALSE
+    },
+    {
+	"gl-window", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	"cairo_gl_surface_create_for_window",
+	_cairo_boilerplate_gl_create_window,
+	NULL,
+	_cairo_boilerplate_gl_finish_window,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_gl_cleanup,
+	_cairo_boilerplate_gl_synchronize,
+	FALSE, FALSE, FALSE
+    },
+    {
+	"gl-window&", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	"cairo_gl_surface_create_for_window",
+	_cairo_boilerplate_gl_create_window_db,
+	NULL,
+	_cairo_boilerplate_gl_finish_window,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_gl_cleanup,
+	_cairo_boilerplate_gl_synchronize,
+	FALSE, FALSE, FALSE
+    },
+};
+CAIRO_BOILERPLATE (gl, targets)
diff --git a/boilerplate/cairo-boilerplate-wgl.c b/boilerplate/cairo-boilerplate-wgl.c
new file mode 100644
index 0000000..559cc11
--- /dev/null
+++ b/boilerplate/cairo-boilerplate-wgl.c
@@ -0,0 +1,236 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Chris Wilson.
+ *
+ * Contributor(s):
+ *	Zoxc <zoxc32 at gmail.com>
+ */
+
+#include "cairo-boilerplate-private.h"
+
+#include <cairo-gl.h>
+
+static const cairo_user_data_key_t gl_closure_key;
+
+typedef struct _wgl_target_closure {
+    HWND wnd;
+    HDC dc;
+    HGLRC rc;
+    cairo_device_t *device;
+    cairo_surface_t *surface;
+} wgl_target_closure_t;
+
+static void
+_cairo_boilerplate_wgl_cleanup (void *closure)
+{
+    wgl_target_closure_t *wgltc = closure;
+
+    cairo_device_finish (wgltc->device);
+    cairo_device_destroy (wgltc->device);
+
+    wglDeleteContext(wgltc->rc);
+
+    ReleaseDC(wgltc->wnd, wgltc->dc);
+    DestroyWindow (wgltc->wnd);
+
+    free (wgltc);
+}
+
+static void
+_cairo_boilerplate_wgl_create_window (int width, int height,  wgl_target_closure_t *wgltc)
+{
+    WNDCLASSEXA wincl;
+    PIXELFORMATDESCRIPTOR pfd;
+    int format;
+    cairo_surface_t *surface;
+    
+    ZeroMemory (&wincl, sizeof (WNDCLASSEXA));
+    wincl.cbSize = sizeof (WNDCLASSEXA);
+    wincl.hInstance = GetModuleHandle (0);
+    wincl.lpszClassName = "cairo_boilerplate_wgl_dummy";
+    wincl.lpfnWndProc = DefWindowProcA;
+    wincl.style = CS_OWNDC;
+
+    RegisterClassExA (&wincl);
+    
+    wgltc->wnd = CreateWindow ("cairo_boilerplate_wgl_dummy", 0, WS_POPUP, 0, 0, width, height, 0, 0, 0, 0);
+    wgltc->dc = GetDC (wgltc->wnd);
+
+    ZeroMemory (&pfd, sizeof (PIXELFORMATDESCRIPTOR));
+    pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
+    pfd.nVersion = 1;
+    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+    pfd.iPixelType = PFD_TYPE_RGBA;
+    pfd.cColorBits = 24;
+    pfd.cDepthBits = 16;
+    pfd.iLayerType = PFD_MAIN_PLANE;
+
+    format = ChoosePixelFormat (wgltc->dc, &pfd);
+    SetPixelFormat (wgltc->dc, format, &pfd);
+    
+    wgltc->rc = wglCreateContext (wgltc->dc);
+    wgltc->device = cairo_wgl_device_create (wgltc->rc);
+}
+
+static cairo_surface_t *
+_cairo_boilerplate_wgl_create_surface (const char		 *name,
+				      cairo_content_t		  content,
+				      double			  width,
+				      double			  height,
+				      double			  max_width,
+				      double			  max_height,
+				      cairo_boilerplate_mode_t	  mode,
+				      int			  id,
+				      void			**closure)
+{
+    wgl_target_closure_t *wgltc;
+    cairo_surface_t *surface;
+    
+    wgltc = calloc (1, sizeof (wgl_target_closure_t));
+    
+    *closure = wgltc;
+
+    _cairo_boilerplate_wgl_create_window(0, 0, wgltc);
+    
+    if (width == 0)
+        width = 1;
+    if (height == 0)
+        height = 1;
+    
+    wgltc->surface = surface = cairo_gl_surface_create (wgltc->device,
+						       content,
+					               ceil (width),
+						       ceil (height));
+    if (cairo_surface_status (surface)) {
+        _cairo_boilerplate_wgl_cleanup (wgltc);
+        return NULL;
+    }
+
+    return surface;
+}
+
+static cairo_surface_t *
+_cairo_boilerplate_wgl_for_create_window (const char			 *name,
+				     cairo_content_t		  content,
+				     double			  width,
+				     double			  height,
+				     double			  max_width,
+				     double			  max_height,
+				     cairo_boilerplate_mode_t	  mode,
+				     int			  id,
+				     void			**closure)
+{
+    wgl_target_closure_t *wgltc;
+    cairo_surface_t *surface;
+    
+    wgltc = calloc (1, sizeof (wgl_target_closure_t));
+    
+    *closure = wgltc;
+
+     _cairo_boilerplate_wgl_create_window(width, height, wgltc);
+    
+    wgltc->surface = surface = cairo_gl_surface_create_for_dc (wgltc->device,
+						       wgltc->dc,
+					               ceil (width),
+						       ceil (height));
+    
+    if (cairo_surface_status (surface)) {
+        _cairo_boilerplate_wgl_cleanup (wgltc);
+        return NULL;
+    }
+
+    return surface;
+}
+
+static cairo_status_t
+_cairo_boilerplate_wgl_finish_window (cairo_surface_t		*surface)
+{
+    wgl_target_closure_t *wgltc = cairo_surface_get_user_data (surface,
+							     &gl_closure_key);
+
+    if (wgltc != NULL && wgltc->surface != NULL) {
+	cairo_t *cr;
+
+	cr = cairo_create (wgltc->surface);
+	cairo_surface_set_device_offset (surface, 0, 0);
+	cairo_set_source_surface (cr, surface, 0, 0);
+	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+	cairo_paint (cr);
+	cairo_destroy (cr);
+
+	surface = wgltc->surface;
+    }
+
+    cairo_gl_surface_swapbuffers (surface);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_boilerplate_wgl_synchronize (void *closure)
+{
+    wgl_target_closure_t *wgltc = closure;
+
+    if (cairo_device_acquire (wgltc->device))
+        return;
+
+    //glFinish ();
+
+    cairo_device_release (wgltc->device);
+}
+
+static const cairo_boilerplate_target_t targets[] = {
+    {
+	"gl", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	"cairo_gl_surface_create",
+	_cairo_boilerplate_wgl_create_surface,
+	NULL, NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_wgl_cleanup,
+	_cairo_boilerplate_wgl_synchronize,
+	TRUE, FALSE, FALSE
+    },
+    {
+	"gl-dc", "gl", NULL, NULL,
+	CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	"cairo_gl_surface_create_for_dc",
+	_cairo_boilerplate_wgl_for_create_window,
+	NULL,
+	_cairo_boilerplate_wgl_finish_window,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_wgl_cleanup,
+	_cairo_boilerplate_wgl_synchronize,
+	FALSE, FALSE, FALSE
+    },
+};
+
+CAIRO_BOILERPLATE (wgl, targets)
diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h
index 9d9468c..9aec98c 100644
--- a/build/Makefile.win32.features-h
+++ b/build/Makefile.win32.features-h
@@ -62,6 +62,7 @@ endif
 ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
 	@echo "#define CAIRO_HAS_PNG_FUNCTIONS 1" >> src/cairo-features.h
 endif
+	@echo "#define CAIRO_HAS_GLEW_FUNCTIONS 1" >> src/cairo-features.h
 ifeq ($(CAIRO_HAS_GL_SURFACE),1)
 	@echo "#define CAIRO_HAS_GL_SURFACE 1" >> src/cairo-features.h
 endif
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index 3cbdd2e..f99cb66 100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -287,6 +287,14 @@ ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
 enabled_cairo_pkgconf += cairo-png.pc
 endif
 
+supported_cairo_headers += $(cairo_glew_headers)
+all_cairo_headers += $(cairo_glew_headers)
+all_cairo_private += $(cairo_glew_private)
+all_cairo_sources += $(cairo_glew_sources)
+enabled_cairo_headers += $(cairo_glew_headers)
+enabled_cairo_private += $(cairo_glew_private)
+enabled_cairo_sources += $(cairo_glew_sources)
+
 unsupported_cairo_headers += $(cairo_gl_headers)
 all_cairo_headers += $(cairo_gl_headers)
 all_cairo_private += $(cairo_gl_private)
commit 2af3262895d74492a0f856f049d1524a527257bb
Author: Zoxc <zoxc32 at gmail.com>
Date:   Mon Jun 14 20:33:17 2010 +0200

    wgl: Renamed hwnd field to wnd.

diff --git a/src/cairo-wgl-context.c b/src/cairo-wgl-context.c
index e8b8ec6..7bba1d3 100644
--- a/src/cairo-wgl-context.c
+++ b/src/cairo-wgl-context.c
@@ -50,7 +50,7 @@ typedef struct _cairo_wgl_context {
     cairo_gl_context_t base;
 
     HDC dummy_dc;
-    HWND dummy_hwnd;
+    HWND dummy_wnd;
     HGLRC rc;
 
     HDC prev_dc;
@@ -130,9 +130,9 @@ _wgl_destroy (void *abstract_ctx)
     cairo_wgl_context_t *ctx = abstract_ctx;
 
     if (ctx->dummy_dc != 0) {
-        ReleaseDC (ctx->dummy_hwnd, ctx->dummy_dc);
-        DestroyWindow (ctx->dummy_hwnd);
-        CloseHandle (ctx->dummy_hwnd);
+        ReleaseDC (ctx->dummy_wnd, ctx->dummy_dc);
+        DestroyWindow (ctx->dummy_wnd);
+        CloseHandle (ctx->dummy_wnd);
     }
 
     wglMakeCurrent (0, 0);
@@ -155,8 +155,8 @@ _wgl_dummy_ctx (cairo_wgl_context_t *ctx)
 
     RegisterClassExA (&wincl);
 
-    ctx->dummy_hwnd = CreateWindow ("cairo_wgl_context_dummy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-    ctx->dummy_dc = GetDC (ctx->dummy_hwnd);
+    ctx->dummy_wnd = CreateWindow ("cairo_wgl_context_dummy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    ctx->dummy_dc = GetDC (ctx->dummy_wnd);
 
     ZeroMemory (&pfd, sizeof (PIXELFORMATDESCRIPTOR));
     pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
commit 7a023a62f7517ad0d54f4d59c99909fadcc05e82
Author: Nicolaus L Helper <nlhepler at gmail.com>
Date:   Thu Jun 17 08:56:30 2010 +0100

    ft,fc,xlib: LCD filtering patch.
    
    This adds internal API to retrieve the LCD filtering parameters from
    fontconfig, or as set on the Screen, and feed them to FreeType when
    rendering the glyph.
    
    References:
      Bug 10301 - LCD filtering patch
      https://bugs.freedesktop.org/show_bug.cgi?id=10301
    
    Tested-by: Brandon Wright <bearoso at gmail.com>
    Forward-ported-by: Robert Hooker <sarvatt at gmail.cm>
    
    ickle: The API is clearly not ready for public consumption, the enum are
    poorly named, however this stands by itself as enabling system wide
    properties.

diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
index 0348d28..971f7d5 100644
--- a/src/cairo-font-options.c
+++ b/src/cairo-font-options.c
@@ -40,6 +40,7 @@
 static const cairo_font_options_t _cairo_font_options_nil = {
     CAIRO_ANTIALIAS_DEFAULT,
     CAIRO_SUBPIXEL_ORDER_DEFAULT,
+    CAIRO_LCD_FILTER_DEFAULT,
     CAIRO_HINT_STYLE_DEFAULT,
     CAIRO_HINT_METRICS_DEFAULT
 };
@@ -55,6 +56,7 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
 {
     options->antialias = CAIRO_ANTIALIAS_DEFAULT;
     options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+    options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
     options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
     options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
 }
@@ -65,6 +67,7 @@ _cairo_font_options_init_copy (cairo_font_options_t		*options,
 {
     options->antialias = other->antialias;
     options->subpixel_order = other->subpixel_order;
+    options->lcd_filter = other->lcd_filter;
     options->hint_style = other->hint_style;
     options->hint_metrics = other->hint_metrics;
 }
@@ -190,6 +193,8 @@ cairo_font_options_merge (cairo_font_options_t       *options,
 	options->antialias = other->antialias;
     if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
 	options->subpixel_order = other->subpixel_order;
+    if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
+	options->lcd_filter = other->lcd_filter;
     if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
 	options->hint_style = other->hint_style;
     if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
@@ -222,6 +227,7 @@ cairo_font_options_equal (const cairo_font_options_t *options,
 
     return (options->antialias == other->antialias &&
 	    options->subpixel_order == other->subpixel_order &&
+	    options->lcd_filter == other->lcd_filter &&
 	    options->hint_style == other->hint_style &&
 	    options->hint_metrics == other->hint_metrics);
 }
@@ -247,7 +253,8 @@ cairo_font_options_hash (const cairo_font_options_t *options)
 
     return ((options->antialias) |
 	    (options->subpixel_order << 4) |
-	    (options->hint_style << 8) |
+	    (options->lcd_filter << 8) |
+	    (options->hint_style << 12) |
 	    (options->hint_metrics << 16));
 }
 slim_hidden_def (cairo_font_options_hash);
@@ -329,6 +336,48 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
 }
 
 /**
+ * _cairo_font_options_set_lcd_filter:
+ * @options: a #cairo_font_options_t
+ * @lcd_filter: the new LCD filter
+ *
+ * Sets the LCD filter for the font options object. The LCD filter
+ * specifies how pixels are filtered when rendered with an antialiasing
+ * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
+ * #cairo_lcd_filter_t for full details.
+ *
+ * Since: 1.8
+ **/
+void
+_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
+				    cairo_lcd_filter_t    lcd_filter)
+{
+    if (cairo_font_options_status (options))
+	return;
+
+    options->lcd_filter = lcd_filter;
+}
+
+/**
+ * _cairo_font_options_get_lcd_filter:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the LCD filter for the font options object.
+ * See the documentation for #cairo_lcd_filter_t for full details.
+ *
+ * Return value: the LCD filter for the font options object
+ *
+ * Since: 1.8
+ **/
+cairo_lcd_filter_t
+_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
+{
+    if (cairo_font_options_status ((cairo_font_options_t *) options))
+	return CAIRO_LCD_FILTER_DEFAULT;
+
+    return options->lcd_filter;
+}
+
+/**
  * cairo_font_options_set_hint_style:
  * @options: a #cairo_font_options_t
  * @hint_style: the new hint style
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index ae09740..d3b9660 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -60,6 +60,30 @@
 #include FT_SYNTHESIS_H
 #endif
 
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+#include FT_LCD_FILTER_H
+#endif
+
+/* Fontconfig version older than 2.6 didn't have these options */
+#ifndef FC_LCD_FILTER
+#define FC_LCD_FILTER	"lcdfilter"
+#endif
+/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
+#ifndef FC_LCD_NONE
+#define FC_LCD_NONE	0
+#define FC_LCD_DEFAULT	1
+#define FC_LCD_LIGHT	2
+#define FC_LCD_LEGACY	3
+#endif
+
+/* FreeType version older than 2.3.5(?) didn't have these options */
+#ifndef FT_LCD_FILTER_NONE
+#define FT_LCD_FILTER_NONE	0
+#define FT_LCD_FILTER_DEFAULT	1
+#define FT_LCD_FILTER_LIGHT	2
+#define FT_LCD_FILTER_LEGACY	16
+#endif
+
 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
@@ -177,6 +201,7 @@ typedef struct _cairo_ft_unscaled_font_map {
 
 static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
 
+
 static void
 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
 				  cairo_ft_unscaled_font_t *unscaled)
@@ -774,23 +799,286 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
     return CAIRO_STATUS_SUCCESS;
 }
 
-/* Empirically-derived subpixel filtering values thanks to Keith
- * Packard and libXft. */
-static const int    filters[3][3] = {
-    /* red */
-#if 0
-    {    65538*4/7,65538*2/7,65538*1/7 },
-    /* green */
-    {    65536*1/4, 65536*2/4, 65537*1/4 },
-    /* blue */
-    {    65538*1/7,65538*2/7,65538*4/7 },
+/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
+ * into a different format. For example, we want to convert a
+ * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
+ * ARGB or ABGR bitmap.
+ *
+ * this function prepares a target descriptor for this operation.
+ *
+ * input :: target bitmap descriptor. The function will set its
+ *          'width', 'rows' and 'pitch' fields, and only these
+ *
+ * slot  :: the glyph slot containing the source bitmap. this
+ *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
+ *
+ * mode  :: the requested final rendering mode. supported values are
+ *          MONO, NORMAL (i.e. gray), LCD and LCD_V
+ *
+ * the function returns the size in bytes of the corresponding buffer,
+ * it's up to the caller to allocate the corresponding memory block
+ * before calling _fill_xrender_bitmap
+ *
+ * it also returns -1 in case of error (e.g. incompatible arguments,
+ * like trying to convert a gray bitmap into a monochrome one)
+ */
+static int
+_compute_xrender_bitmap_size(FT_Bitmap      *target,
+			     FT_GlyphSlot    slot,
+			     FT_Render_Mode  mode)
+{
+    FT_Bitmap *ftbit;
+    int width, height, pitch;
+
+    if (slot->format != FT_GLYPH_FORMAT_BITMAP)
+	return -1;
+
+    /* compute the size of the final bitmap */
+    ftbit = &slot->bitmap;
+
+    width = ftbit->width;
+    height = ftbit->rows;
+    pitch = (width + 3) & ~3;
+
+    switch (ftbit->pixel_mode) {
+    case FT_PIXEL_MODE_MONO:
+	if (mode == FT_RENDER_MODE_MONO) {
+	    pitch = (((width + 31) & ~31) >> 3);
+	    break;
+	}
+	/* fall-through */
+
+    case FT_PIXEL_MODE_GRAY:
+	if (mode == FT_RENDER_MODE_LCD ||
+	    mode == FT_RENDER_MODE_LCD_V)
+	{
+	    /* each pixel is replicated into a 32-bit ARGB value */
+	    pitch = width * 4;
+	}
+	break;
+
+    case FT_PIXEL_MODE_LCD:
+	if (mode != FT_RENDER_MODE_LCD)
+	    return -1;
+
+	/* horz pixel triplets are packed into 32-bit ARGB values */
+	width /= 3;
+	pitch = width * 4;
+	break;
+
+    case FT_PIXEL_MODE_LCD_V:
+	if (mode != FT_RENDER_MODE_LCD_V)
+	    return -1;
+
+	/* vert pixel triplets are packed into 32-bit ARGB values */
+	height /= 3;
+	pitch = width * 4;
+	break;
+
+    default:  /* unsupported source format */
+	return -1;
+    }
+
+    target->width = width;
+    target->rows = height;
+    target->pitch = pitch;
+    target->buffer = NULL;
+
+    return pitch * height;
+}
+
+/* this functions converts the glyph bitmap found in a FT_GlyphSlot
+ * into a different format (see _compute_xrender_bitmap_size)
+ *
+ * you should call this function after _compute_xrender_bitmap_size
+ *
+ * target :: target bitmap descriptor. Note that its 'buffer' pointer
+ *           must point to memory allocated by the caller
+ *
+ * slot   :: the glyph slot containing the source bitmap
+ *
+ * mode   :: the requested final rendering mode
+ *
+ * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
+ */
+static void
+_fill_xrender_bitmap(FT_Bitmap      *target,
+		     FT_GlyphSlot    slot,
+		     FT_Render_Mode  mode,
+		     int             bgr)
+{
+    FT_Bitmap *ftbit = &slot->bitmap;
+    unsigned char *srcLine = ftbit->buffer;
+    unsigned char *dstLine = target->buffer;
+    int src_pitch = ftbit->pitch;
+    int width = target->width;
+    int height = target->rows;
+    int pitch = target->pitch;
+    int subpixel;
+    int h;
+
+    subpixel = (mode == FT_RENDER_MODE_LCD ||
+		mode == FT_RENDER_MODE_LCD_V);
+
+    if (src_pitch < 0)
+	srcLine -= src_pitch * (ftbit->rows - 1);
+
+    target->pixel_mode = ftbit->pixel_mode;
+
+    switch (ftbit->pixel_mode) {
+    case FT_PIXEL_MODE_MONO:
+	if (subpixel) {
+	    /* convert mono to ARGB32 values */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+
+		for (x = 0; x < width; x++) {
+		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
+			((unsigned int *) dstLine)[x] = 0xffffffffU;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_LCD;
+
+	} else if (mode == FT_RENDER_MODE_NORMAL) {
+	    /* convert mono to 8-bit gray */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+
+		for (x = 0; x < width; x++) {
+		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
+			dstLine[x] = 0xff;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_GRAY;
+
+	} else {
+	    /* copy mono to mono */
+
+	    int  bytes = (width + 7) >> 3;
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
+		memcpy (dstLine, srcLine, bytes);
+	}
+	break;
+
+    case FT_PIXEL_MODE_GRAY:
+	if (subpixel) {
+	    /* convert gray to ARGB32 values */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++) {
+		    unsigned int pix = srcLine[x];
+
+		    pix |= (pix << 8);
+		    pix |= (pix << 16);
+
+		    dst[x] = pix;
+		}
+	    }
+	    target->pixel_mode = FT_PIXEL_MODE_LCD;
+        } else {
+            /* copy gray into gray */
+
+            for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
+                memcpy (dstLine, srcLine, width);
+        }
+        break;
+
+    case FT_PIXEL_MODE_LCD:
+	if (!bgr) {
+	    /* convert horizontal RGB into ARGB32 */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 3) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[0] << 16) |
+			  ((unsigned int)src[1] <<  8) |
+			  ((unsigned int)src[2]      ) |
+			  ((unsigned int)src[1] << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	} else {
+	    /* convert horizontal BGR into ARGB32 */
+
+	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
+
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 3) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[2] << 16) |
+			  ((unsigned int)src[1] <<  8) |
+			  ((unsigned int)src[0]      ) |
+			  ((unsigned int)src[1] << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	}
+	break;
+
+    default:  /* FT_PIXEL_MODE_LCD_V */
+	/* convert vertical RGB into ARGB32 */
+	if (!bgr) {
+
+	    for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char* src = srcLine;
+		unsigned int*  dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 1) {
+		    unsigned int pix;
+#if 1
+		    pix = ((unsigned int)src[0]           << 16) |
+			  ((unsigned int)src[src_pitch]   <<  8) |
+			  ((unsigned int)src[src_pitch*2]      ) |
+			  0xFF000000 ;
+#else
+		    pix = ((unsigned int)src[0]           << 16) |
+			  ((unsigned int)src[src_pitch]   <<  8) |
+			  ((unsigned int)src[src_pitch*2]      ) |
+			  ((unsigned int)src[src_pitch]   << 24) ;
 #endif
-    {    65538*9/13,65538*3/13,65538*1/13 },
-    /* green */
-    {    65538*1/6, 65538*4/6, 65538*1/6 },
-    /* blue */
-    {    65538*1/13,65538*3/13,65538*9/13 },
-};
+		    dst[x] = pix;
+		}
+	    }
+	} else {
+
+	    for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
+		int x;
+		unsigned char *src = srcLine;
+		unsigned int *dst = (unsigned int *) dstLine;
+
+		for (x = 0; x < width; x++, src += 1) {
+		    unsigned int  pix;
+
+		    pix = ((unsigned int)src[src_pitch * 2] << 16) |
+			  ((unsigned int)src[src_pitch]     <<  8) |
+			  ((unsigned int)src[0]                  ) |
+			  ((unsigned int)src[src_pitch]     << 24) ;
+
+		    dst[x] = pix;
+		}
+	    }
+	}
+    }
+}
+
 
 /* Fills in val->image with an image surface created from @bitmap
  */
@@ -803,6 +1091,7 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
     int width, height, stride;
     unsigned char *data;
     int format = CAIRO_FORMAT_A8;
+    cairo_image_surface_t *image;
 
     width = bitmap->width;
     height = bitmap->rows;
@@ -859,11 +1148,7 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
     case FT_PIXEL_MODE_GRAY:
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
-	case CAIRO_ANTIALIAS_NONE:
-	default:
+        if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
 	    stride = bitmap->pitch;
 	    if (own_buffer) {
 		data = bitmap->buffer;
@@ -874,104 +1159,18 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
 
 		memcpy (data, bitmap->buffer, stride * height);
 	    }
-	    format = CAIRO_FORMAT_A8;
-	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL: {
-	    int		    x, y;
-	    unsigned char   *in_line, *out_line, *in;
-	    unsigned int    *out;
-	    unsigned int    red, green, blue;
-	    int		    rf, gf, bf;
-	    int		    s;
-	    int		    o, os;
-	    unsigned char   *data_rgba;
-	    unsigned int    width_rgba, stride_rgba;
-	    int		    vmul = 1;
-	    int		    hmul = 1;
-
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-	    default:
-		width /= 3;
-		hmul = 3;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		vmul = 3;
-		height /= 3;
-		break;
-	    }
-	    /*
-	     * Filter the glyph to soften the color fringes
-	     */
-	    width_rgba = width;
-	    stride = bitmap->pitch;
-	    stride_rgba = (width_rgba * 4 + 3) & ~3;
-	    data_rgba = calloc (stride_rgba, height);
-	    if (unlikely (data_rgba == NULL)) {
-		if (own_buffer)
-		    free (bitmap->buffer);
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    }
-
-	    os = 1;
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-		os = stride;
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    default:
-		rf = 0;
-		gf = 1;
-		bf = 2;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		os = stride;
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-		bf = 0;
-		gf = 1;
-		rf = 2;
-		break;
-	    }
-	    in_line = bitmap->buffer;
-	    out_line = data_rgba;
-	    for (y = 0; y < height; y++)
-	    {
-		in = in_line;
-		out = (unsigned int *) out_line;
-		in_line += stride * vmul;
-		out_line += stride_rgba;
-		for (x = 0; x < width * hmul; x += hmul)
-		{
-		    red = green = blue = 0;
-		    o = 0;
-		    for (s = 0; s < 3; s++)
-		    {
-			red += filters[rf][s]*in[x+o];
-			green += filters[gf][s]*in[x+o];
-			blue += filters[bf][s]*in[x+o];
-			o += os;
-		    }
-		    red = red / 65536;
-		    green = green / 65536;
-		    blue = blue / 65536;
-		    *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
-		}
-	    }
 
-	    /* Images here are stored in native format. The
-	     * backend must convert to its own format as needed
-	     */
+	format = CAIRO_FORMAT_A8;
+	} else {
+	    /* if we get there, the  data from the source bitmap
+	     * really comes from _fill_xrender_bitmap, and is
+	     * made of 32-bit ARGB or ABGR values */
+	    assert (own_buffer != 0);
+	    assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
 
-	    if (own_buffer)
-		free (bitmap->buffer);
-	    data = data_rgba;
-	    stride = stride_rgba;
-	    format = CAIRO_FORMAT_ARGB32;
-	    break;
-	}
+		data = bitmap->buffer;
+		stride = bitmap->pitch;
+		format = CAIRO_FORMAT_ARGB32;
 	}
 	break;
     case FT_PIXEL_MODE_GRAY2:
@@ -983,21 +1182,22 @@ _get_bitmap_surface (FT_Bitmap		     *bitmap,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    *surface = (cairo_image_surface_t *)
+    /* XXX */
+    *surface = image = (cairo_image_surface_t *)
 	cairo_image_surface_create_for_data (data,
 					     format,
 					     width, height, stride);
-    if ((*surface)->base.status) {
+    if (image->base.status) {
 	free (data);
 	return (*surface)->base.status;
     }
 
     if (format == CAIRO_FORMAT_ARGB32)
-	pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
+	pixman_image_set_component_alpha (image->pixman_image, TRUE);
 
-    _cairo_image_surface_assume_ownership_of_data ((*surface));
+    _cairo_image_surface_assume_ownership_of_data (image);
 
-    _cairo_debug_check_image_surface_is_defined (&(*surface)->base);
+    _cairo_debug_check_image_surface_is_defined (&image->base);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1022,16 +1222,59 @@ _render_glyph_outline (FT_Face                    face,
 		       cairo_font_options_t	 *font_options,
 		       cairo_image_surface_t	**surface)
 {
+    int rgba = FC_RGBA_UNKNOWN;
+    int lcd_filter = FT_LCD_FILTER_LEGACY;
     FT_GlyphSlot glyphslot = face->glyph;
     FT_Outline *outline = &glyphslot->outline;
     FT_Bitmap bitmap;
     FT_BBox cbox;
-    FT_Matrix matrix;
-    int hmul = 1;
-    int vmul = 1;
-    unsigned int width, height, stride;
-    cairo_bool_t subpixel = FALSE;
+    unsigned int width, height;
     cairo_status_t status;
+    FT_Error fterror;
+    FT_Library library = glyphslot->library;
+    FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
+
+    switch (font_options->antialias) {
+    case CAIRO_ANTIALIAS_NONE:
+	render_mode = FT_RENDER_MODE_MONO;
+	break;
+
+    case CAIRO_ANTIALIAS_SUBPIXEL:
+	switch (font_options->subpixel_order) {
+	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
+	    case CAIRO_SUBPIXEL_ORDER_RGB:
+	    case CAIRO_SUBPIXEL_ORDER_BGR:
+		render_mode = FT_RENDER_MODE_LCD;
+		break;
+
+	    case CAIRO_SUBPIXEL_ORDER_VRGB:
+	    case CAIRO_SUBPIXEL_ORDER_VBGR:
+		render_mode = FT_RENDER_MODE_LCD_V;
+		break;
+	}
+
+	switch (font_options->lcd_filter) {
+	case CAIRO_LCD_FILTER_NONE:
+	    lcd_filter = FT_LCD_FILTER_NONE;
+	    break;
+	case CAIRO_LCD_FILTER_DEFAULT:
+	case CAIRO_LCD_FILTER_INTRA_PIXEL:
+	    lcd_filter = FT_LCD_FILTER_LEGACY;
+	    break;
+	case CAIRO_LCD_FILTER_FIR3:
+	    lcd_filter = FT_LCD_FILTER_LIGHT;
+	    break;
+	case CAIRO_LCD_FILTER_FIR5:
+	    lcd_filter = FT_LCD_FILTER_DEFAULT;
+	    break;
+	}
+
+	break;
+
+    case CAIRO_ANTIALIAS_DEFAULT:
+    case CAIRO_ANTIALIAS_GRAY:
+	render_mode = FT_RENDER_MODE_NORMAL;
+    }
 
     FT_Outline_Get_CBox (outline, &cbox);
 
@@ -1042,20 +1285,21 @@ _render_glyph_outline (FT_Face                    face,
 
     width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
     height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
-    stride = (width * hmul + 3) & ~3;
 
     if (width * height == 0) {
 	cairo_format_t format;
 	/* Looks like fb handles zero-sized images just fine */
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
+	switch (render_mode) {
+	case FT_RENDER_MODE_MONO:
 	    format = CAIRO_FORMAT_A1;
 	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
+	case FT_RENDER_MODE_LCD:
+	case FT_RENDER_MODE_LCD_V:
 	    format= CAIRO_FORMAT_ARGB32;
 	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
+	case FT_RENDER_MODE_LIGHT:
+	case FT_RENDER_MODE_NORMAL:
+	case FT_RENDER_MODE_MAX:
 	default:
 	    format = CAIRO_FORMAT_A8;
 	    break;
@@ -1065,75 +1309,74 @@ _render_glyph_outline (FT_Face                    face,
 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
 	if ((*surface)->base.status)
 	    return (*surface)->base.status;
-    } else  {
+    } else {
 
-	matrix.xx = matrix.yy = 0x10000L;
-	matrix.xy = matrix.yx = 0;
+	int bitmap_size;
 
-	switch (font_options->antialias) {
-	case CAIRO_ANTIALIAS_NONE:
-	    bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
-	    bitmap.num_grays  = 1;
-	    stride = ((width + 31) & -32) >> 3;
+	switch (render_mode) {
+	case FT_RENDER_MODE_LCD:
+	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
+		rgba = FC_RGBA_BGR;
+	    } else {
+		rgba = FC_RGBA_RGB;
+	    }
+	case FT_RENDER_MODE_LCD_V:
+	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
+		rgba = FC_RGBA_VBGR;
+	    } else {
+		rgba = FC_RGBA_VRGB;
+		}
 	    break;
-	case CAIRO_ANTIALIAS_DEFAULT:
-	case CAIRO_ANTIALIAS_GRAY:
-	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-	    bitmap.num_grays  = 256;
-	    stride = (width + 3) & -4;
+	case FT_RENDER_MODE_MONO:
+	case FT_RENDER_MODE_LIGHT:
+	case FT_RENDER_MODE_NORMAL:
+	case FT_RENDER_MODE_MAX:
+	default:
 	    break;
-	case CAIRO_ANTIALIAS_SUBPIXEL:
-	    switch (font_options->subpixel_order) {
-	    case CAIRO_SUBPIXEL_ORDER_RGB:
-	    case CAIRO_SUBPIXEL_ORDER_BGR:
-	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
-	    default:
-		matrix.xx *= 3;
-		hmul = 3;
-		subpixel = TRUE;
-		break;
-	    case CAIRO_SUBPIXEL_ORDER_VRGB:
-	    case CAIRO_SUBPIXEL_ORDER_VBGR:
-		matrix.yy *= 3;
-		vmul = 3;
-		subpixel = TRUE;
-		break;
 	    }
-	    FT_Outline_Transform (outline, &matrix);
 
-	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-	    bitmap.num_grays  = 256;
-	    stride = (width * hmul + 3) & -4;
-	}
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+	FT_Library_SetLcdFilter (library, lcd_filter);
+#endif
 
-	bitmap.pitch = stride;
-	bitmap.width = width * hmul;
-	bitmap.rows = height * vmul;
-	bitmap.buffer = calloc (stride, bitmap.rows);
-	if (unlikely (bitmap.buffer == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	fterror = FT_Render_Glyph (face->glyph, render_mode);
+
+#if HAVE_FT_LIBRARY_SETLCDFILTER
+	FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
+#endif
 
-	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
+	if (fterror != 0)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
-	    free (bitmap.buffer);
+	bitmap_size = _compute_xrender_bitmap_size (&bitmap,
+						    face->glyph,
+						    render_mode);
+	if (bitmap_size < 0)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
 
+	bitmap.buffer = calloc (1, bitmap_size);
+	if (bitmap.buffer == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
+			      (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
+
+	/* Note:
+	 * _get_bitmap_surface will free bitmap.buffer if there is an error
+	 */
 	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
 	if (unlikely (status))
 	    return status;
-    }
 
-    /*
-     * Note: the font's coordinate system is upside down from ours, so the
-     * Y coordinate of the control box needs to be negated.  Moreover, device
-     * offsets are position of glyph origin relative to top left while xMin
-     * and yMax are offsets of top left relative to origin.  Another negation.
-     */
-    cairo_surface_set_device_offset (&(*surface)->base,
-				     floor (-(double) cbox.xMin / 64.0),
-				     floor (+(double) cbox.yMax / 64.0));
+	/* Note: the font's coordinate system is upside down from ours, so the
+	 * Y coordinate of the control box needs to be negated.  Moreover, device
+	 * offsets are position of glyph origin relative to top left while xMin
+	 * and yMax are offsets of top left relative to origin.  Another negation.
+	 */
+	cairo_surface_set_device_offset (&(*surface)->base,
+					 (double)-glyphslot->bitmap_left,
+					 (double)+glyphslot->bitmap_top);
+    }
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1341,6 +1584,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
     
     if (antialias) {
 	cairo_subpixel_order_t subpixel_order;
+	int lcd_filter;
 
 	/* disable hinting if requested */
 	if (FcPatternGetBool (pattern,
@@ -1376,6 +1620,25 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
 	    ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 	}
 
+	if (FcPatternGetInteger (pattern,
+				 FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
+	{
+	    switch (lcd_filter) {
+	    case FC_LCD_NONE:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
+		break;
+	    case FC_LCD_DEFAULT:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
+		break;
+	    case FC_LCD_LIGHT:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
+		break;
+	    case FC_LCD_LEGACY:
+		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+		break;
+	    }
+	}
+
 #ifdef FC_HINT_STYLE
 	if (FcPatternGetInteger (pattern,
 				 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
@@ -1477,6 +1740,12 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
     if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
 	options->base.hint_style = CAIRO_HINT_STYLE_NONE;
 
+    if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
+	options->base.lcd_filter = other->base.lcd_filter;
+
+    if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
+	options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
+
     if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
 	if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
 	    load_flags |= FT_LOAD_NO_HINTING;
@@ -1500,11 +1769,11 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
 		case CAIRO_SUBPIXEL_ORDER_DEFAULT:
 		case CAIRO_SUBPIXEL_ORDER_RGB:
 		case CAIRO_SUBPIXEL_ORDER_BGR:
-		    load_target |= FT_LOAD_TARGET_LCD;
+		    load_target = FT_LOAD_TARGET_LCD;
 		    break;
 		case CAIRO_SUBPIXEL_ORDER_VRGB:
 		case CAIRO_SUBPIXEL_ORDER_VBGR:
-		    load_target |= FT_LOAD_TARGET_LCD_V;
+		    load_target = FT_LOAD_TARGET_LCD_V;
 		break;
 		}
 	    }
@@ -2503,6 +2772,34 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
 	}
     }
 
+    if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
+    {
+	if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
+	{
+	    int lcd_filter;
+
+	    switch (options->lcd_filter) {
+	    case CAIRO_LCD_FILTER_NONE:
+		lcd_filter = FT_LCD_FILTER_NONE;
+		break;
+	    case CAIRO_LCD_FILTER_DEFAULT:
+	    case CAIRO_LCD_FILTER_INTRA_PIXEL:
+		lcd_filter = FT_LCD_FILTER_LEGACY;
+		break;
+	    case CAIRO_LCD_FILTER_FIR3:
+		lcd_filter = FT_LCD_FILTER_LIGHT;
+		break;
+	    default:
+	    case CAIRO_LCD_FILTER_FIR5:
+		lcd_filter = FT_LCD_FILTER_DEFAULT;
+		break;
+	    }
+
+	    if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
+    }
+
     if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
     {
 	if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 581e755..8806f13 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -74,6 +74,7 @@ const cairo_surface_t name = {					\
     { NULL, NULL },			/* snapshot */		\
     { CAIRO_ANTIALIAS_DEFAULT,		/* antialias */		\
       CAIRO_SUBPIXEL_ORDER_DEFAULT,	/* subpixel_order */	\
+      CAIRO_LCD_FILTER_DEFAULT,		/* lcd_filter */	\
       CAIRO_HINT_STYLE_DEFAULT,		/* hint_style */	\
       CAIRO_HINT_METRICS_DEFAULT	/* hint_metrics */	\
     }					/* font_options */	\
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 8b5a94b..49fc709 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -129,9 +129,34 @@ struct _cairo_array {
     cairo_bool_t is_snapshot;
 };
 
+/**
+ * cairo_lcd_filter_t:
+ * @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for
+ *   font backend and target device
+ * @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering
+ * @CAIRO_LCD_FILTER_INTRA_PIXEL: Intra-pixel filter
+ * @CAIRO_LCD_FILTER_FIR3: FIR filter with a 3x3 kernel
+ * @CAIRO_LCD_FILTER_FIR5: FIR filter with a 5x5 kernel
+ *
+ * The LCD filter specifies the low-pass filter applied to LCD-optimized
+ * bitmaps generated with an antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
+ *
+ * Note: This API was temporarily made available in the public
+ * interface during the 1.7.x development series, but was made private
+ * before 1.8.
+ **/
+typedef enum _cairo_lcd_filter {
+    CAIRO_LCD_FILTER_DEFAULT,
+    CAIRO_LCD_FILTER_NONE,
+    CAIRO_LCD_FILTER_INTRA_PIXEL,
+    CAIRO_LCD_FILTER_FIR3,
+    CAIRO_LCD_FILTER_FIR5
+} cairo_lcd_filter_t;
+
 struct _cairo_font_options {
     cairo_antialias_t antialias;
     cairo_subpixel_order_t subpixel_order;
+    cairo_lcd_filter_t lcd_filter;
     cairo_hint_style_t hint_style;
     cairo_hint_metrics_t hint_metrics;
 };
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index b094eaf..db01a84 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -152,13 +152,22 @@ _cairo_xlib_init_screen_font_options (Display *dpy,
     cairo_bool_t xft_antialias;
     int xft_hintstyle;
     int xft_rgba;
+    int xft_lcdfilter;
     cairo_antialias_t antialias;
     cairo_subpixel_order_t subpixel_order;
+    cairo_lcd_filter_t lcd_filter;
     cairo_hint_style_t hint_style;
 
     if (!get_boolean_default (dpy, "antialias", &xft_antialias))
 	xft_antialias = TRUE;
 
+    if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
+	/* -1 is an non-existant Fontconfig constant used to differentiate
+	 * the case when no lcdfilter property is available.
+	 */
+	xft_lcdfilter = -1;
+    }
+
     if (!get_boolean_default (dpy, "hinting", &xft_hinting))
 	xft_hinting = TRUE;
 
@@ -241,6 +250,24 @@ _cairo_xlib_init_screen_font_options (Display *dpy,
 	subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
     }
 
+    switch (xft_lcdfilter) {
+    case FC_LCD_NONE:
+	lcd_filter = CAIRO_LCD_FILTER_NONE;
+	break;
+    case FC_LCD_DEFAULT:
+	lcd_filter = CAIRO_LCD_FILTER_FIR5;
+	break;
+    case FC_LCD_LIGHT:
+	lcd_filter = CAIRO_LCD_FILTER_FIR3;
+	break;
+    case FC_LCD_LEGACY:
+	lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+	break;
+    default:
+	lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
+	break;
+    }
+
     if (xft_antialias) {
 	if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
 	    antialias = CAIRO_ANTIALIAS_GRAY;
@@ -253,6 +280,7 @@ _cairo_xlib_init_screen_font_options (Display *dpy,
     cairo_font_options_set_hint_style (&info->font_options, hint_style);
     cairo_font_options_set_antialias (&info->font_options, antialias);
     cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
+    _cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
     cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
 }
 
diff --git a/src/cairoint.h b/src/cairoint.h
index b3deee9..6ccc18f 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1072,6 +1072,13 @@ cairo_private void
 _cairo_font_options_init_copy (cairo_font_options_t		*options,
 			       const cairo_font_options_t	*other);
 
+cairo_private void
+_cairo_font_options_set_lcd_filter (cairo_font_options_t   *options,
+				   cairo_lcd_filter_t  lcd_filter);
+
+cairo_private cairo_lcd_filter_t
+_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options);
+
 /* cairo-hull.c */
 cairo_private cairo_status_t
 _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
commit 36b4b0631cc220d01c411b596a4eef839338cd7c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 17 08:50:31 2010 +0100

    image: Use consistent rounding modes for a1 rasterisation.
    
    When checking if the traps are equivalent to a set of rectangles, we
    need to use the same rounding mode as when converting the traps to a set
    of boxes and then filling them. Failure to do leads to a situation where
    (-127,-128) was thought to be equivalent to (0,0) but we attempted to
    fill from 0 to -1 instead.
    
    References:
      http://lists.cairographics.org/archives/cairo/2010-June/020115.html

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 06c63c1..c9f1f13 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -2889,7 +2889,6 @@ _composite_boxes (cairo_image_surface_t *dst,
 	    cairo_box_t *box = chunk->base;
 
 	    for (i = 0; i < chunk->count; i++) {
-                /* round down here to match Pixman's behavior when using traps. */
 		int x1 = _cairo_fixed_integer_round_down (box[i].p1.x);
 		int y1 = _cairo_fixed_integer_round_down (box[i].p1.y);
 		int x2 = _cairo_fixed_integer_round_down (box[i].p2.x);
@@ -2945,10 +2944,10 @@ _composite_boxes (cairo_image_surface_t *dst,
 	    const cairo_box_t *box = chunk->base;
 
 	    for (i = 0; i < chunk->count; i++) {
-		int x1 = _cairo_fixed_integer_round (box[i].p1.x);
-		int y1 = _cairo_fixed_integer_round (box[i].p1.y);
-		int x2 = _cairo_fixed_integer_round (box[i].p2.x);
-		int y2 = _cairo_fixed_integer_round (box[i].p2.y);
+		int x1 = _cairo_fixed_integer_round_down (box[i].p1.x);
+		int y1 = _cairo_fixed_integer_round_down (box[i].p1.y);
+		int x2 = _cairo_fixed_integer_round_down (box[i].p2.x);
+		int y2 = _cairo_fixed_integer_round_down (box[i].p2.y);
 
 		if (x2 == x1 || y2 == y1)
 		    continue;
@@ -3015,7 +3014,7 @@ _clip_and_composite_boxes (cairo_image_surface_t *dst,
 static cairo_bool_t
 _mono_edge_is_vertical (const cairo_line_t *line)
 {
-    return _cairo_fixed_integer_round (line->p1.x) == _cairo_fixed_integer_round (line->p2.x);
+    return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
 }
 
 static cairo_bool_t
@@ -3053,7 +3052,8 @@ _traps_are_pixel_aligned (cairo_traps_t *traps,
 
 static void
 _boxes_for_traps (cairo_boxes_t *boxes,
-		  cairo_traps_t *traps)
+		  cairo_traps_t *traps,
+		  cairo_antialias_t antialias)
 {
     int i;
 
@@ -3064,21 +3064,33 @@ _boxes_for_traps (cairo_boxes_t *boxes,
     boxes->chunks.count = traps->num_traps;
     boxes->chunks.size  = traps->num_traps;
 
-    for (i = 0; i < traps->num_traps; i++) {
-	cairo_fixed_t x1 = traps->traps[i].left.p1.x;
-	cairo_fixed_t x2 = traps->traps[i].right.p1.x;
-	cairo_fixed_t y1 = traps->traps[i].top;
-	cairo_fixed_t y2 = traps->traps[i].bottom;
-
-	boxes->chunks.base[i].p1.x = x1;
-	boxes->chunks.base[i].p1.y = y1;
-	boxes->chunks.base[i].p2.x = x2;
-	boxes->chunks.base[i].p2.y = y2;
-
-	if (boxes->is_pixel_aligned) {
-	    boxes->is_pixel_aligned =
-		_cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
-		_cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
+    if (antialias != CAIRO_ANTIALIAS_NONE) {
+	for (i = 0; i < traps->num_traps; i++) {
+	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
+	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
+	    cairo_fixed_t y1 = traps->traps[i].top;
+	    cairo_fixed_t y2 = traps->traps[i].bottom;
+
+	    boxes->chunks.base[i].p1.x = x1;
+	    boxes->chunks.base[i].p1.y = y1;
+	    boxes->chunks.base[i].p2.x = x2;
+	    boxes->chunks.base[i].p2.y = y2;
+
+	    if (boxes->is_pixel_aligned) {
+		boxes->is_pixel_aligned =
+		    _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
+		    _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
+	    }
+	}
+    } else {
+	boxes->is_pixel_aligned = TRUE;
+
+	for (i = 0; i < traps->num_traps; i++) {
+	    /* round down here to match Pixman's behavior when using traps. */
+	    boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (traps->traps[i].left.p1.x);
+	    boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (traps->traps[i].top);
+	    boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (traps->traps[i].right.p1.x);
+	    boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (traps->traps[i].bottom);
 	}
     }
 }
@@ -3127,7 +3139,7 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
     {
 	cairo_boxes_t boxes;
 
-	_boxes_for_traps (&boxes, traps);
+	_boxes_for_traps (&boxes, traps, antialias);
 	return _clip_and_composite_boxes (dst, op, src,
 					  &boxes, antialias,
 					  extents, clip);
commit 3306bcb1d91265d60c460aa64d3ee4a4acb430a1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 17 08:47:48 2010 +0100

    fixed: Refactor code to use more inlines and less duplication of logic.
    
    This also has the side-effect of fixing the types in the problematic
    functions which hid Andrea's true fix for the unsigned FRAC_MASK.

diff --git a/src/cairo-fixed-private.h b/src/cairo-fixed-private.h
index 8873056..6cecc8d 100644
--- a/src/cairo-fixed-private.h
+++ b/src/cairo-fixed-private.h
@@ -157,12 +157,24 @@ _cairo_fixed_is_integer (cairo_fixed_t f)
     return (f & CAIRO_FIXED_FRAC_MASK) == 0;
 }
 
-static inline int
+static inline cairo_fixed_t
 _cairo_fixed_floor (cairo_fixed_t f)
 {
     return f & ~CAIRO_FIXED_FRAC_MASK;
 }
 
+static inline cairo_fixed_t
+_cairo_fixed_round (cairo_fixed_t f)
+{
+    return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
+}
+
+static inline cairo_fixed_t
+_cairo_fixed_round_down (cairo_fixed_t f)
+{
+    return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK/2);
+}
+
 static inline int
 _cairo_fixed_integer_part (cairo_fixed_t f)
 {
@@ -172,13 +184,13 @@ _cairo_fixed_integer_part (cairo_fixed_t f)
 static inline int
 _cairo_fixed_integer_round (cairo_fixed_t f)
 {
-    return (f + (CAIRO_FIXED_FRAC_MASK+1)/2) >> CAIRO_FIXED_FRAC_BITS;
+    return _cairo_fixed_integer_part (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
 }
 
 static inline int
 _cairo_fixed_integer_round_down (cairo_fixed_t f)
 {
-    return (f + CAIRO_FIXED_FRAC_MASK/2) >> CAIRO_FIXED_FRAC_BITS;
+    return _cairo_fixed_integer_part (f + CAIRO_FIXED_FRAC_MASK/2);
 }
 
 static inline int
commit c0dee7964c4394b7963041f246855fd3b01f4ebb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 16 18:49:58 2010 +0100

    test: Add a1-rasterisation
    
    Check the rounding criteria when rasterising.

diff --git a/test/Makefile.am b/test/Makefile.am
index b76b814..a7f1845 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -137,6 +137,8 @@ REFERENCE_IMAGES = \
 	a1-mask.ref.png \
 	a1-mask-sample.ref.png \
 	a1-mask-sample.quartz.xfail.png \
+	a1-rasterisation-rectangles.ref.png \
+	a1-rasterisation-triangles.ref.png \
 	a1-traps-sample.ref.png \
 	a1-traps-sample.quartz.xfail.png \
 	a8-mask.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 6dd2e3e..243b53a 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -3,6 +3,7 @@ test_sources = \
 	a1-mask.c					\
 	a1-mask-sample.c 				\
 	a1-traps-sample.c				\
+	a1-rasterisation.c				\
 	a8-mask.c					\
 	aliasing.c					\
 	alpha-similar.c					\
diff --git a/test/a1-rasterisation-rectangles.ref.png b/test/a1-rasterisation-rectangles.ref.png
new file mode 100644
index 0000000..784cf87
Binary files /dev/null and b/test/a1-rasterisation-rectangles.ref.png differ
diff --git a/test/a1-rasterisation-triangles.ref.png b/test/a1-rasterisation-triangles.ref.png
new file mode 100644
index 0000000..784cf87
Binary files /dev/null and b/test/a1-rasterisation-triangles.ref.png differ
diff --git a/test/a1-rasterisation.c b/test/a1-rasterisation.c
new file mode 100644
index 0000000..b59090a
--- /dev/null
+++ b/test/a1-rasterisation.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+/*
+ * Test the fidelity of the rasterisation, paying careful attention to rounding.
+ */
+
+#include "../src/cairo-fixed-type-private.h"
+#define PRECISION (int)(1 << CAIRO_FIXED_FRAC_BITS)
+
+#define WIDTH ((PRECISION/2+1)*3)
+#define HEIGHT ((PRECISION/2+1)*3)
+
+#define SUBPIXEL(v) ((v)/(double)(PRECISION/2))
+
+static cairo_test_status_t
+rectangles (cairo_t *cr, int width, int height)
+{
+    int x, y;
+
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+    cairo_paint (cr);
+
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+
+    for (x = 0; x < WIDTH; x += 3) {
+	for (y = 0; y < HEIGHT; y += 3) {
+	    cairo_rectangle (cr, x + SUBPIXEL (y/3) - .5, y + SUBPIXEL (x/3) - .5, .5, .5);
+	}
+    }
+    cairo_fill (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+triangles (cairo_t *cr, int width, int height)
+{
+    int x, y;
+
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+    cairo_paint (cr);
+
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+
+    for (x = 0; x < WIDTH; x += 3) {
+	for (y = 0; y < HEIGHT; y += 3) {
+	    /* a rectangle with a diagonal to force tessellation */
+	    cairo_move_to (cr, x + SUBPIXEL (y/3) - .5, y + SUBPIXEL (x/3) - .5);
+	    cairo_rel_line_to (cr, .5, .5);
+	    cairo_rel_line_to (cr, 0, -.5);
+	    cairo_rel_line_to (cr, -.5, 0);
+	    cairo_rel_line_to (cr, 0, .5);
+	    cairo_rel_line_to (cr, .5, 0);
+	}
+    }
+    cairo_fill (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (a1_rasterisation_rectangles,
+	    "Check the fidelity of the rasterisation.",
+	    "rasterisation", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, rectangles)
+
+CAIRO_TEST (a1_rasterisation_triangles,
+	    "Check the fidelity of the rasterisation.",
+	    "rasterisation", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, triangles)
commit 16364768d79570e7201a87f0a985c65acaff5560
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 16 15:09:22 2010 +0100

    test/halo: Transformation seems key to the bug...

diff --git a/test/halo.c b/test/halo.c
index 30064e5..69a966a 100644
--- a/test/halo.c
+++ b/test/halo.c
@@ -143,6 +143,42 @@ draw_transform (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
+static cairo_test_status_t
+draw_transform (cairo_t *cr, int width, int height)
+{
+    const char *string = "0123456789";
+    cairo_text_extents_t extents;
+
+    cairo_translate (cr, 50, 50);
+    cairo_scale (cr, M_SQRT2, M_SQRT2);
+
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+    cairo_text_extents (cr, string, &extents);
+
+    cairo_set_line_width (cr, 3);
+    cairo_move_to (cr, 9, 4 + extents.height);
+    halo_around_path (cr, string);
+
+    cairo_move_to (cr, 109, 4 + extents.height);
+    halo_around_path (cr, string);
+
+    cairo_set_font_size (cr, 64);
+    cairo_set_line_width (cr, 10);
+    cairo_move_to (cr, 8, 70);
+    halo_around_path (cr, "6");
+    cairo_move_to (cr, 32, 90);
+    halo_around_path (cr, "7");
+
+    cairo_move_to (cr, 108, 70);
+    halo_around_text (cr, "6");
+    cairo_move_to (cr, 132, 90);
+    halo_around_text (cr, "7");
+
+    return CAIRO_TEST_SUCCESS;
+}
+
 CAIRO_TEST (halo,
 	    "Check the show_glyphs() vs glyph_path()",
 	    "text", /* keywords */


More information about the cairo-commit mailing list