Import Qt backend by Mozilla

Written by Vladimir Vukicevic to enable integration with Qt embedded
devices, this backend allows cairo code to target QPainter, and use
it as a source for other cairo backends.

This imports the sources from mozilla-central:
http://mxr.mozilla.org/mozilla-central/find?text=&kind=text&string=cairo-qpainter
renames them from cairo-qpainter to cairo-qt, and integrates the patch
by Oleg Romashin:
https://bugs.freedesktop.org/attachment.cgi?id=18953

And then attempts to restore 'make check' to full functionality.

However:
 - C++ does not play well with the PLT symbol hiding, and leaks into the
   global namespace. 'make check' fails at check-plt.sh

 - Qt embeds a GUI into QApplication which it requires to construct any
   QPainter drawable, i.e. used by the boilerplate to create a cairo-qt
   surface, and this leaks fonts (cairo-ft-fonts no less) causing assertion
   failures that all cairo objects are accounted for upon destruction.

[Updated by Chris Wilson]
Acked-by: Jeff Muizelaar <jeff@infidigm.net>
Acked-by: Carl Worth <cworth@cworth.org>
This commit is contained in:
Vladimir Vukicevic 2009-06-14 20:43:05 +01:00 committed by Chris Wilson
parent 7d3881114a
commit 22587f57bd
22 changed files with 2247 additions and 8 deletions

View file

@ -37,6 +37,9 @@ cairo_boilerplate_pdf_sources = cairo-boilerplate-pdf.c
cairo_boilerplate_ps_private = cairo-boilerplate-ps-private.h
cairo_boilerplate_ps_sources = cairo-boilerplate-ps.c
cairo_boilerplate_qt_private = cairo-boilerplate-qt-private.h
cairo_boilerplate_qt_sources = cairo-boilerplate-qt.cpp
cairo_boilerplate_quartz_private = cairo-boilerplate-quartz-private.h
cairo_boilerplate_quartz_sources = cairo-boilerplate-quartz.c

View file

@ -49,6 +49,16 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_xcb_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_xcb_sources)
endif
unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_qt_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_qt_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_qt_private)
all_cairo_boilerplate_sources += $(cairo_boilerplate_qt_sources)
ifeq ($(CAIRO_HAS_QT_SURFACE),1)
enabled_cairo_boilerplate_headers += $(cairo_boilerplate_qt_headers)
enabled_cairo_boilerplate_private += $(cairo_boilerplate_qt_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_qt_sources)
endif
supported_cairo_boilerplate_headers += $(cairo_boilerplate_quartz_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_quartz_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_quartz_private)

View file

@ -0,0 +1,60 @@
/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
*/
#ifndef CAIRO_BOILERPLATE_QT_PRIVATE_H
#define CAIRO_BOILERPLATE_QT_PRIVATE_H
#include <cairo.h>
CAIRO_BEGIN_DECLS
extern cairo_surface_t *
_cairo_boilerplate_qt_create_surface (const char *name,
cairo_content_t content,
int width,
int height,
int max_width,
int max_height,
cairo_boilerplate_mode_t mode,
int id,
void **closure);
extern void
_cairo_boilerplate_qt_cleanup (void* closure);
extern void
_cairo_boilerplate_qt_synchronize (void *closure);
CAIRO_END_DECLS
#endif /* CAIRO_BOILERPLATE_QT_PRIVATE_H */

View file

@ -0,0 +1,90 @@
/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.h"
#include "cairo-boilerplate-qt-private.h"
#include <cairo-qt.h>
#include <qapplication.h>
#include <X11/Xlib.h>
typedef struct _qt_closure {
Display *dpy;
QApplication *app;
} qt_closure_t;
void
_cairo_boilerplate_qt_cleanup (void *closure)
{
qt_closure_t *qtc = (qt_closure_t *) closure;
delete qtc->app;
XCloseDisplay (qtc->dpy);
free (qtc);
}
cairo_surface_t *
_cairo_boilerplate_qt_create_surface (const char *name,
cairo_content_t content,
int width,
int height,
int max_width,
int max_height,
cairo_boilerplate_mode_t mode,
int id,
void **closure)
{
qt_closure_t *qtc;
qtc = (qt_closure_t *) xcalloc (1, sizeof (qt_closure_t));
qtc->dpy = XOpenDisplay (NULL);
if (qtc->dpy == NULL) {
free (qtc);
return NULL;
}
if (mode == CAIRO_BOILERPLATE_MODE_TEST)
XSynchronize (qtc->dpy, True);
qtc->app = new QApplication (qtc->dpy);
*closure = qtc;
return cairo_qt_surface_create_with_qpixmap (content, width, height);
}
void
_cairo_boilerplate_qt_synchronize (void *closure)
{
qt_closure_t *qtc = (qt_closure_t *) closure;
qtc->app->flush (); /* not sure if this is sufficient */
}

View file

@ -44,6 +44,9 @@
#if CAIRO_HAS_PS_SURFACE
#include "cairo-boilerplate-ps-private.h"
#endif
#if CAIRO_HAS_QT_SURFACE
#include "cairo-boilerplate-qt-private.h"
#endif
#if CAIRO_HAS_QUARTZ_SURFACE
#include "cairo-boilerplate-quartz-private.h"
#endif
@ -446,6 +449,26 @@ static const cairo_boilerplate_target_t targets[] =
},
#endif
#endif /* CAIRO_HAS_GLITZ_SURFACE */
#if CAIRO_HAS_QT_SURFACE
{
"qt", "qt", NULL,
CAIRO_SURFACE_TYPE_QT, CAIRO_CONTENT_COLOR_ALPHA, 0,
_cairo_boilerplate_qt_create_surface, NULL,
NULL,
_cairo_boilerplate_get_image_surface,
cairo_surface_write_to_png,
_cairo_boilerplate_qt_cleanup
},
{
"qt", "qt", NULL,
CAIRO_SURFACE_TYPE_QT, CAIRO_CONTENT_COLOR, 0,
_cairo_boilerplate_qt_create_surface, NULL,
NULL,
_cairo_boilerplate_get_image_surface,
cairo_surface_write_to_png,
_cairo_boilerplate_qt_cleanup
},
#endif
#if CAIRO_HAS_QUARTZ_SURFACE
{
"quartz", "quartz", NULL,

View file

@ -93,6 +93,7 @@
#define M_PI 3.14159265358979323846
#endif
CAIRO_BEGIN_DECLS
/* A fake format we use for the flattened ARGB output of the PS and
* PDF surfaces. */
@ -210,4 +211,6 @@ cairo_boilerplate_version_string (void);
#include "cairo-boilerplate-system.h"
CAIRO_END_DECLS
#endif

View file

@ -3,6 +3,7 @@
CAIRO_HAS_XLIB_SURFACE=0
CAIRO_HAS_XLIB_XRENDER_SURFACE=0
CAIRO_HAS_XCB_SURFACE=0
CAIRO_HAS_QT_SURFACE=0
CAIRO_HAS_QUARTZ_SURFACE=0
CAIRO_HAS_QUARTZ_FONT=0
CAIRO_HAS_QUARTZ_IMAGE_SURFACE=0

View file

@ -14,6 +14,9 @@ endif
ifeq ($(CAIRO_HAS_XCB_SURFACE),1)
@echo "#define CAIRO_HAS_XCB_SURFACE 1" >> src/cairo-features.h
endif
ifeq ($(CAIRO_HAS_QT_SURFACE),1)
@echo "#define CAIRO_HAS_QT_SURFACE 1" >> src/cairo-features.h
endif
ifeq ($(CAIRO_HAS_QUARTZ_SURFACE),1)
@echo "#define CAIRO_HAS_QUARTZ_SURFACE 1" >> src/cairo-features.h
endif

View file

@ -363,6 +363,7 @@ AC_DEFUN([CAIRO_REPORT],
echo " Image: yes (always builtin)"
echo " Xlib: $use_xlib"
echo " Xlib Xrender: $use_xlib_xrender"
echo " Qt: $use_qt"
echo " Quartz: $use_quartz"
echo " Quartz-image: $use_quartz_image"
echo " XCB: $use_xcb"

View file

@ -82,6 +82,17 @@ CAIRO_ENABLE_SURFACE_BACKEND(xcb, XCB, no, [
dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(qt, Qt, no, [
qt_REQUIRES="QtGui >= 4.4.0"
PKG_CHECK_MODULES(qt, $qt_REQUIRES, ,
[AC_MSG_RESULT(no)
qt_REQUIRES=""
use_qt="no (requires Qt4 development libraries)"
])
])
dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(quartz, Quartz, auto, [
dnl There is no pkgconfig for quartz; lets do a header check
AC_CHECK_HEADER(ApplicationServices/ApplicationServices.h, , [use_quartz="no (requires ApplicationServices framework)"])

View file

@ -99,6 +99,7 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
case CAIRO_SURFACE_TYPE_BEOS:
case CAIRO_SURFACE_TYPE_DIRECTFB:
case CAIRO_SURFACE_TYPE_OS2:
case CAIRO_SURFACE_TYPE_QT:
case CAIRO_INTERNAL_SURFACE_TYPE_NULL:
return TRUE;
case CAIRO_SURFACE_TYPE_PDF:

View file

@ -92,9 +92,8 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
case CAIRO_SURFACE_TYPE_WIN32:
case CAIRO_SURFACE_TYPE_BEOS:
case CAIRO_SURFACE_TYPE_DIRECTFB:
#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR > 2)
case CAIRO_SURFACE_TYPE_OS2:
#endif
case CAIRO_SURFACE_TYPE_QT:
return TRUE;
case CAIRO_SURFACE_TYPE_PDF:
case CAIRO_SURFACE_TYPE_PS:

View file

@ -50,7 +50,7 @@ cairo.def: cairo-features.h $(enabled_cairo_headers)
@(echo EXPORTS; \
(cd $(srcdir); cat $(enabled_cairo_headers) || echo 'cairo_ERROR ()' ) | \
grep -v -E '^# *include' | \
( cat cairo-features.h - | $(CPP) - || echo 'cairo_ERROR ()' ) | \
( cat cairo-features.h - | $(CPP) -D__cplusplus - || echo 'cairo_ERROR ()' ) | \
grep -E '^cairo_.* \(' | \
sed -e 's/[ ].*//' | \
sort; \

View file

@ -223,6 +223,9 @@ cairo_xlib_xrender_headers = cairo-xlib-xrender.h
cairo_xcb_headers = cairo-xcb.h cairo-xcb-xrender.h
cairo_xcb_sources = cairo-xcb-surface.c
cairo_qt_headers = cairo-qt.h
cairo_qt_sources = cairo-qt-surface.cpp
cairo_quartz_headers = cairo-quartz.h
cairo_quartz_private = cairo-quartz-private.h
cairo_quartz_sources = cairo-quartz-surface.c

View file

@ -63,6 +63,20 @@ ifeq ($(CAIRO_HAS_XCB_SURFACE),1)
enabled_cairo_pkgconf += cairo-xcb.pc
endif
unsupported_cairo_headers += $(cairo_qt_headers)
all_cairo_headers += $(cairo_qt_headers)
all_cairo_private += $(cairo_qt_private)
all_cairo_sources += $(cairo_qt_sources)
ifeq ($(CAIRO_HAS_QT_SURFACE),1)
enabled_cairo_headers += $(cairo_qt_headers)
enabled_cairo_private += $(cairo_qt_private)
enabled_cairo_sources += $(cairo_qt_sources)
endif
all_cairo_pkgconf += cairo-qt.pc
ifeq ($(CAIRO_HAS_QT_SURFACE),1)
enabled_cairo_pkgconf += cairo-qt.pc
endif
supported_cairo_headers += $(cairo_quartz_headers)
all_cairo_headers += $(cairo_quartz_headers)
all_cairo_private += $(cairo_quartz_private)

View file

@ -117,3 +117,45 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
}
}
#endif
#if 0
void
_cairo_image_surface_write_to_ppm (cairo_image_surface_t *isurf, const char *fn)
{
char *fmt;
if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24)
fmt = "P6";
else if (isurf->format == CAIRO_FORMAT_A8)
fmt = "P5";
else
return;
FILE *fp = fopen(fn, "wb");
if (!fp)
return;
fprintf (fp, "%s %d %d 255\n", fmt,isurf->width, isurf->height);
for (int j = 0; j < isurf->height; j++) {
unsigned char *row = isurf->data + isurf->stride * j;
for (int i = 0; i < isurf->width; i++) {
if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24) {
unsigned char r = *row++;
unsigned char g = *row++;
unsigned char b = *row++;
*row++;
putc(r, fp);
putc(g, fp);
putc(b, fp);
} else {
unsigned char a = *row++;
putc(a, fp);
}
}
}
fclose (fp);
fprintf (stderr, "Wrote %s\n", fn);
}
#endif

1876
src/cairo-qt-surface.cpp Normal file

File diff suppressed because it is too large Load diff

89
src/cairo-qt.h Normal file
View file

@ -0,0 +1,89 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2008 Mozilla Corporation
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Mozilla Corporation.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@mozilla.com>
*/
#ifndef CAIRO_QT_H
#define CAIRO_QT_H
#include "cairo.h"
#if CAIRO_HAS_QT_SURFACE
#if defined(__cplusplus)
class QPainter;
class QImage;
cairo_public cairo_surface_t *
cairo_qt_surface_create (QPainter *painter);
cairo_public cairo_surface_t *
cairo_qt_surface_create_with_qimage (cairo_format_t format,
int width,
int height);
cairo_public cairo_surface_t *
cairo_qt_surface_create_with_qpixmap (cairo_content_t content,
int width,
int height);
cairo_public QPainter *
cairo_qt_surface_get_qpainter (cairo_surface_t *surface);
/* XXX needs hooking to generic surface layer, my vote is for
cairo_public cairo_surface_t *
cairo_surface_map_image (cairo_surface_t *surface);
cairo_public void
cairo_surface_unmap_image (cairo_surface_t *surface, cairo_surface_t *image);
*/
cairo_public cairo_surface_t *
cairo_qt_surface_get_image (cairo_surface_t *surface);
cairo_public QImage *
cairo_qt_surface_get_qimage (cairo_surface_t *surface);
#else /* ! __cplusplus */
# warning cairo-qt only exports a C++ interface
#endif /* __cplusplus */
#else /* CAIRO_HAS_QT_SURFACE */
# error Cairo was not compiled with support for the Qt backend
#endif /* CAIRO_HAS_QT_SURFACE */
#endif /* CAIRO_QT_H */

View file

@ -89,6 +89,10 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
int *remaining_glyphs,
cairo_rectangle_int_t *extents);
/* XXX temporarily used by cairo-qt-surface.c */
slim_hidden_proto (cairo_xlib_surface_create);
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
/*
* Instead of taking two round trips for each blending request,
* assume that if a particular drawable fails GetImage that it will
@ -2816,6 +2820,7 @@ cairo_xlib_surface_create (Display *dpy,
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
visual, NULL, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create);
/**
* cairo_xlib_surface_create_for_bitmap:
@ -2873,6 +2878,7 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
NULL, format, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
/**
* cairo_xlib_surface_get_xrender_format:

View file

@ -1889,6 +1889,7 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
* @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
* @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
* @CAIRO_SURFACE_TYPE_QT: The surface is of type Qt, since 1.10
*
* #cairo_surface_type_t is used to describe the type of a given
* surface. The surface types are also known as "backends" or "surface
@ -1928,7 +1929,8 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_OS2,
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
CAIRO_SURFACE_TYPE_SCRIPT
CAIRO_SURFACE_TYPE_SCRIPT,
CAIRO_SURFACE_TYPE_QT
} cairo_surface_type_t;
cairo_public cairo_surface_type_t

View file

@ -19,9 +19,10 @@ if tail -1 check-has-hidden-symbols.i | grep CAIRO_HAS_HIDDEN_SYMBOLS >/dev/null
exit 0
fi
get_cairo_syms='nm "$so" | grep " [BCDGINRSTVW] " | cut -d" " -f3'
if [ "`uname -s`" = "Linux" ]; then
get_cairo_syms='( objdump -t "$so" | grep "^[^ ]* [^l.*]*[.]"; objdump -t "$so" | grep "[.]hidden.*\\<cairo"; ) | sed "s/.* //"'
get_cairo_syms='( objdump -t "$so" | grep "^[^ ]* [^l.*]*[.]"; objdump -t "$so" | grep "[.]hidden.*\\<cairo"; ) | sed "s/.* //"'
else
get_cairo_syms='nm "$so" | grep " [BCDGINRSTVW] " | cut -d" " -f3'
fi
defs="cairo.def"
@ -37,7 +38,7 @@ for def in $defs; do
{
echo EXPORTS
eval $get_cairo_syms | grep -v '^_cairo_test_\|^_fini\|^_init\|^_save[fg]pr\|^_rest[fg]pr' | sort -u
eval $get_cairo_syms | c++filt --no-params | grep -v '^_cairo_test_\|^_fini\|^_init\|^_save[fg]pr\|^_rest[fg]pr\|^_Z' | sort -u
# cheat: copy the last line from the def file!
tail -n1 "$def"
} | diff "$def" - >&2 || stat=1

View file

@ -52,6 +52,7 @@ grep '#.*\<include\>.*<.*cairo' $ALL >&2 && stat=1
echo 'Checking that feature conditionals are used with #if only (not #ifdef)'
grep '#if.*CAIRO_HAS_' $ALL | grep def >&2 && stat=1
grep '#ifdef CAIRO_HAS_' $ALL && stat=1
grep '#if.*defined[ ]*(CAIRO_HAS_' $ALL && stat=1
exit $stat