зеркало из https://github.com/mozilla/gecko-dev.git
[dfb,422221] Gtk/DirectFB: turn NativeXlibRenderer into NativeGdkRenderer
This commit is contained in:
Родитель
abb36b9752
Коммит
27b16f2a53
|
@ -35,22 +35,22 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#ifndef GFXXLIBNATIVERENDER_H_
|
#ifndef GFXGDKNATIVERENDER_H_
|
||||||
#define GFXXLIBNATIVERENDER_H_
|
#define GFXGDKNATIVERENDER_H_
|
||||||
|
|
||||||
#include "gfxColor.h"
|
#include "gfxColor.h"
|
||||||
#include <X11/Xlib.h>
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
class gfxASurface;
|
class gfxASurface;
|
||||||
class gfxContext;
|
class gfxContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class lets us take code that draws into an X drawable and lets us
|
* This class lets us take code that draws into an GDK drawable and lets us
|
||||||
* use it to draw into any Thebes context. The user should subclass this class,
|
* use it to draw into any Thebes context. The user should subclass this class,
|
||||||
* override NativeDraw, and then call Draw(). The drawing will be subjected
|
* override NativeDraw, and then call Draw(). The drawing will be subjected
|
||||||
* to all Thebes transformations, clipping etc.
|
* to all Thebes transformations, clipping etc.
|
||||||
*/
|
*/
|
||||||
class THEBES_API gfxXlibNativeRenderer {
|
class THEBES_API gfxGdkNativeRenderer {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Perform the native drawing.
|
* Perform the native drawing.
|
||||||
|
@ -60,10 +60,8 @@ public:
|
||||||
* @param numClipRects the number of rects in the array, or zero if
|
* @param numClipRects the number of rects in the array, or zero if
|
||||||
* no clipping is required
|
* no clipping is required
|
||||||
*/
|
*/
|
||||||
virtual nsresult NativeDraw(Screen* screen, Drawable drawable,
|
virtual nsresult NativeDraw(GdkDrawable * drawable, short offsetX,
|
||||||
Visual* visual, Colormap colormap,
|
short offsetY, GdkRectangle * clipRects, PRUint32 numClipRects) = 0;
|
||||||
short offsetX, short offsetY,
|
|
||||||
XRectangle* clipRects, PRUint32 numClipRects) = 0;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// If set, then Draw() is opaque, i.e., every pixel in the intersection
|
// If set, then Draw() is opaque, i.e., every pixel in the intersection
|
||||||
|
@ -80,7 +78,7 @@ public:
|
||||||
// nor CLIP_RECT are set, then numClipRects will be zero
|
// nor CLIP_RECT are set, then numClipRects will be zero
|
||||||
DRAW_SUPPORTS_CLIP_LIST = 0x08,
|
DRAW_SUPPORTS_CLIP_LIST = 0x08,
|
||||||
// If set, then the visual passed in can be any visual, otherwise the
|
// If set, then the visual passed in can be any visual, otherwise the
|
||||||
// visual passed in must be the default visual for 'screen'
|
// visual passed in must be the default visual for dpy's default screen
|
||||||
DRAW_SUPPORTS_NONDEFAULT_VISUAL = 0x10,
|
DRAW_SUPPORTS_NONDEFAULT_VISUAL = 0x10,
|
||||||
// If set, then the Screen 'screen' in the callback can be different
|
// If set, then the Screen 'screen' in the callback can be different
|
||||||
// from the default Screen of the display passed to 'Draw' and can be
|
// from the default Screen of the display passed to 'Draw' and can be
|
||||||
|
@ -105,8 +103,8 @@ public:
|
||||||
* successful, a pointer to the new gfxASurface is stored in *resultSurface,
|
* successful, a pointer to the new gfxASurface is stored in *resultSurface,
|
||||||
* otherwise *resultSurface is set to nsnull.
|
* otherwise *resultSurface is set to nsnull.
|
||||||
*/
|
*/
|
||||||
nsresult Draw(Display* dpy, gfxContext* ctx, int width, int height,
|
nsresult Draw(gfxContext* ctx, int width, int height,
|
||||||
PRUint32 flags, DrawOutput* output);
|
PRUint32 flags, DrawOutput* output);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*GFXXLIBNATIVERENDER_H_*/
|
#endif /*GFXGDKNATIVERENDER_H_*/
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.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/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Novell code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Novell.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* rocallahan@novell.com
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "cairo-gdk-utils.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#elif HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#elif HAVE_SYS_INT_TYPES_H
|
||||||
|
#include <sys/int_types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* We have three basic strategies available:
|
||||||
|
1) 'direct': cr targets a native surface, and other conditions are met: we can
|
||||||
|
pass the underlying drawable directly to the callback
|
||||||
|
2) 'opaque': the image is opaque: we can create a temporary cairo native surface,
|
||||||
|
pass its underlying drawable to the callback, and paint the result
|
||||||
|
using cairo
|
||||||
|
3) 'default': create a temporary cairo native surface, fill with black, pass its
|
||||||
|
underlying drawable to the callback, copy the results to a cairo
|
||||||
|
image surface, repeat with a white background, update the on-black
|
||||||
|
image alpha values by comparing the two images, then paint the on-black
|
||||||
|
image using cairo
|
||||||
|
Sure would be nice to have an X extension to do 3 for us on the server...
|
||||||
|
*/
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_convert_coord_to_short (double coord, short *v)
|
||||||
|
{
|
||||||
|
*v = (short)coord;
|
||||||
|
/* XXX allow some tolerance here? */
|
||||||
|
return *v == coord;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_convert_coord_to_unsigned_short (double coord, unsigned short *v)
|
||||||
|
{
|
||||||
|
*v = (unsigned short)coord;
|
||||||
|
/* XXX allow some tolerance here? */
|
||||||
|
return *v == coord;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cairo_draw_with_gdk (cairo_t *cr,
|
||||||
|
GdkDrawable * drawable,
|
||||||
|
cairo_gdk_drawing_callback callback,
|
||||||
|
void * closure,
|
||||||
|
unsigned int width, unsigned int height,
|
||||||
|
cairo_gdk_drawing_opacity_t is_opaque,
|
||||||
|
cairo_gdk_drawing_support_t capabilities,
|
||||||
|
cairo_gdk_drawing_result_t *result)
|
||||||
|
{
|
||||||
|
double device_offset_x, device_offset_y;
|
||||||
|
short offset_x = 0, offset_y = 0;
|
||||||
|
//cairo_surface_t * target = cairo_get_group_target (cr);
|
||||||
|
cairo_surface_t * target = cairo_get_target (cr);
|
||||||
|
cairo_matrix_t matrix;
|
||||||
|
|
||||||
|
cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);
|
||||||
|
cairo_get_matrix (cr, &matrix);
|
||||||
|
|
||||||
|
_convert_coord_to_short (matrix.x0 + device_offset_x, &offset_x);
|
||||||
|
_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y);
|
||||||
|
|
||||||
|
cairo_surface_flush (target);
|
||||||
|
callback (closure, drawable, offset_x, offset_y, NULL, 0);
|
||||||
|
cairo_surface_mark_dirty (target);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,32 +35,30 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#ifndef CAIROXLIBUTILS_H_
|
#ifndef CAIROGDKUTILS_H_
|
||||||
#define CAIROXLIBUTILS_H_
|
#define CAIROGDKUTILS_H_
|
||||||
|
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
#include <X11/Xlib.h>
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
CAIRO_BEGIN_DECLS
|
CAIRO_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This callback encapsulates Xlib-based rendering. We assume that the
|
* This callback encapsulates GDK-based rendering. We assume that the
|
||||||
* execution of the callback is equivalent to compositing some RGBA image of
|
* execution of the callback is equivalent to compositing some RGBA image of
|
||||||
* size (bounds_width, bounds_height) onto the drawable at offset (offset_x,
|
* size (bounds_width, bounds_height) onto the drawable at offset (offset_x,
|
||||||
* offset_y), clipped to the union of the clip_rects if num_rects is greater
|
* offset_y), clipped to the union of the clip_rects if num_rects is greater
|
||||||
* than zero. This includes the assumption that the same RGBA image
|
* than zero. This includes the assumption that the same RGBA image
|
||||||
* is composited if you call the callback multiple times with the same closure,
|
* is composited if you call the callback multiple times with the same closure,
|
||||||
* display and visual during a single cairo_draw_with_xlib call.
|
* display and visual during a single cairo_draw_with_gdk call.
|
||||||
*
|
*
|
||||||
* @return True on success, False on non-recoverable error
|
* @return True on success, False on non-recoverable error
|
||||||
*/
|
*/
|
||||||
typedef cairo_bool_t (* cairo_xlib_drawing_callback)
|
typedef cairo_bool_t (* cairo_gdk_drawing_callback)
|
||||||
(void *closure,
|
(void *closure,
|
||||||
Screen *screen,
|
GdkDrawable * drawable,
|
||||||
Drawable drawable,
|
|
||||||
Visual *visual,
|
|
||||||
short offset_x, short offset_y,
|
short offset_x, short offset_y,
|
||||||
XRectangle* clip_rects, unsigned int num_rects);
|
GdkRectangle * clip_rects, unsigned int num_rects);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This structure captures the result of the native drawing, in case the
|
* This structure captures the result of the native drawing, in case the
|
||||||
|
@ -72,7 +70,7 @@ typedef struct {
|
||||||
cairo_bool_t uniform_color;
|
cairo_bool_t uniform_color;
|
||||||
double alpha; /* valid only if uniform_alpha is TRUE */
|
double alpha; /* valid only if uniform_alpha is TRUE */
|
||||||
double r, g, b; /* valid only if uniform_color is TRUE */
|
double r, g, b; /* valid only if uniform_color is TRUE */
|
||||||
} cairo_xlib_drawing_result_t;
|
} cairo_gdk_drawing_result_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type specifies whether the native drawing callback draws all pixels
|
* This type specifies whether the native drawing callback draws all pixels
|
||||||
|
@ -80,50 +78,50 @@ typedef struct {
|
||||||
* or whether it leaves pixels transparent/translucent or depends on the
|
* or whether it leaves pixels transparent/translucent or depends on the
|
||||||
* existing contents of the target drawable in some way.
|
* existing contents of the target drawable in some way.
|
||||||
*/
|
*/
|
||||||
typedef enum _cairo_xlib_drawing_opacity {
|
typedef enum _cairo_gdk_drawing_opacity {
|
||||||
CAIRO_XLIB_DRAWING_OPAQUE,
|
CAIRO_GDK_DRAWING_OPAQUE,
|
||||||
CAIRO_XLIB_DRAWING_TRANSPARENT
|
CAIRO_GDK_DRAWING_TRANSPARENT
|
||||||
} cairo_xlib_drawing_opacity_t;
|
} cairo_gdk_drawing_opacity_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type encodes the capabilities of the native drawing callback.
|
* This type encodes the capabilities of the native drawing callback.
|
||||||
*
|
*
|
||||||
* If CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET is set, 'offset_x' and 'offset_y'
|
* If CAIRO_GDK_DRAWING_SUPPORTS_OFFSET is set, 'offset_x' and 'offset_y'
|
||||||
* can be nonzero in the call to the callback; otherwise they will be zero.
|
* can be nonzero in the call to the callback; otherwise they will be zero.
|
||||||
*
|
*
|
||||||
* If CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT is set, then 'num_rects' can be
|
* If CAIRO_GDK_DRAWING_SUPPORTS_CLIP_RECT is set, then 'num_rects' can be
|
||||||
* zero or one in the call to the callback. If
|
* zero or one in the call to the callback. If
|
||||||
* CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST is set, then 'num_rects' can be
|
* CAIRO_GDK_DRAWING_SUPPORTS_CLIP_LIST is set, then 'num_rects' can be
|
||||||
* anything in the call to the callback. Otherwise 'num_rects' will be zero.
|
* anything in the call to the callback. Otherwise 'num_rects' will be zero.
|
||||||
* Do not set both of these values.
|
* Do not set both of these values.
|
||||||
*
|
*
|
||||||
* If CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN is set, then 'screen' can
|
* If CAIRO_GDK_DRAWING_SUPPORTS_ALTERNATE_DISPLAY is set, then 'dpy' can be
|
||||||
* be any screen on any display, otherwise it will be the default screen of
|
* any display, otherwise it will be the display passed into
|
||||||
* the display passed into cairo_draw_with_xlib.
|
* cairo_draw_with_gdk.
|
||||||
*
|
*
|
||||||
* If CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL is set, then 'visual' can be
|
* If CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL is set, then 'visual' can be
|
||||||
* any visual, otherwise it will be equal to
|
* any visual, otherwise it will be equal to
|
||||||
* DefaultVisualOfScreen (screen).
|
* DefaultVisual (dpy, DefaultScreen (dpy)).
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET = 0x01,
|
CAIRO_GDK_DRAWING_SUPPORTS_OFFSET = 0x01,
|
||||||
CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT = 0x02,
|
CAIRO_GDK_DRAWING_SUPPORTS_CLIP_RECT = 0x02,
|
||||||
CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST = 0x04,
|
CAIRO_GDK_DRAWING_SUPPORTS_CLIP_LIST = 0x04,
|
||||||
CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN = 0x08,
|
CAIRO_GDK_DRAWING_SUPPORTS_ALTERNATE_SCREEN = 0x08,
|
||||||
CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL = 0x10
|
CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL = 0x10
|
||||||
} cairo_xlib_drawing_support_t;
|
} cairo_gdk_drawing_support_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw Xlib output into any cairo context. All cairo transforms and effects
|
* Draw GDK output into any cairo context. All cairo transforms and effects
|
||||||
* are honored, including the current operator. This is equivalent to a
|
* are honored, including the current operator. This is equivalent to a
|
||||||
* cairo_set_source_surface and then cairo_paint.
|
* cairo_set_source_surface and then cairo_paint.
|
||||||
* @param cr the context to draw into
|
* @param cr the context to draw into
|
||||||
* @param callback the code to perform Xlib rendering
|
* @param drawable a GDK Drawable that we're targetting
|
||||||
|
* @param callback the code to perform GDK rendering
|
||||||
* @param closure associated data
|
* @param closure associated data
|
||||||
* @param dpy an X display to use in case the cairo context has no associated X display
|
|
||||||
* @param width the width of the putative image drawn by the callback
|
* @param width the width of the putative image drawn by the callback
|
||||||
* @param height the height of the putative image drawn by the callback
|
* @param height the height of the putative image drawn by the callback
|
||||||
* @param is_opaque set to CAIRO_XLIB_DRAWING_IS_OPAQUE to indicate
|
* @param is_opaque set to CAIRO_GDK_DRAWING_IS_OPAQUE to indicate
|
||||||
* that all alpha values of the putative image will be 1.0; the pixels drawn into
|
* that all alpha values of the putative image will be 1.0; the pixels drawn into
|
||||||
* the Drawable must not depend on the prior contents of the Drawable
|
* the Drawable must not depend on the prior contents of the Drawable
|
||||||
* in any way
|
* in any way
|
||||||
|
@ -137,15 +135,15 @@ typedef enum {
|
||||||
* in which case the color is always uniform) then we won't bother returning
|
* in which case the color is always uniform) then we won't bother returning
|
||||||
* a surface for it.
|
* a surface for it.
|
||||||
*/
|
*/
|
||||||
void cairo_draw_with_xlib (cairo_t *cr,
|
void cairo_draw_with_gdk (cairo_t *cr,
|
||||||
cairo_xlib_drawing_callback callback,
|
GdkDrawable * drawable,
|
||||||
void *closure,
|
cairo_gdk_drawing_callback callback,
|
||||||
Display *dpy,
|
void * closure,
|
||||||
unsigned int width, unsigned int height,
|
unsigned int width, unsigned int height,
|
||||||
cairo_xlib_drawing_opacity_t is_opaque,
|
cairo_gdk_drawing_opacity_t is_opaque,
|
||||||
cairo_xlib_drawing_support_t capabilities,
|
cairo_gdk_drawing_support_t capabilities,
|
||||||
cairo_xlib_drawing_result_t *result);
|
cairo_gdk_drawing_result_t *result);
|
||||||
|
|
||||||
CAIRO_END_DECLS
|
CAIRO_END_DECLS
|
||||||
|
|
||||||
#endif /*CAIROXLIBUTILS_H_*/
|
#endif /*CAIROGDKUTILS_H_*/
|
|
@ -35,7 +35,7 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "cairo-xlib-utils.h"
|
#include "cairo-gdk-utils.h"
|
||||||
|
|
||||||
#include "cairo-xlib.h"
|
#include "cairo-xlib.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -50,9 +50,9 @@
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define CAIRO_XLIB_DRAWING_NOTE(m) fprintf(stderr, m)
|
#define CAIRO_GDK_DRAWING_NOTE(m) fprintf(stderr, m)
|
||||||
#else
|
#else
|
||||||
#define CAIRO_XLIB_DRAWING_NOTE(m) do {} while (0)
|
#define CAIRO_GDK_DRAWING_NOTE(m) do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static cairo_user_data_key_t pixmap_free_key;
|
static cairo_user_data_key_t pixmap_free_key;
|
||||||
|
@ -200,10 +200,10 @@ FINISH:
|
||||||
static cairo_bool_t
|
static cairo_bool_t
|
||||||
_draw_with_xlib_direct (cairo_t *cr,
|
_draw_with_xlib_direct (cairo_t *cr,
|
||||||
Display *default_display,
|
Display *default_display,
|
||||||
cairo_xlib_drawing_callback callback,
|
cairo_gdk_drawing_callback callback,
|
||||||
void *closure,
|
void *closure,
|
||||||
int bounds_width, int bounds_height,
|
int bounds_width, int bounds_height,
|
||||||
cairo_xlib_drawing_support_t capabilities)
|
cairo_gdk_drawing_support_t capabilities)
|
||||||
{
|
{
|
||||||
cairo_surface_t *target;
|
cairo_surface_t *target;
|
||||||
Drawable d;
|
Drawable d;
|
||||||
|
@ -227,22 +227,22 @@ _draw_with_xlib_direct (cairo_t *cr,
|
||||||
/* Check that the matrix is a pure translation */
|
/* Check that the matrix is a pure translation */
|
||||||
/* XXX test some approximation to == 1.0 here? */
|
/* XXX test some approximation to == 1.0 here? */
|
||||||
if (matrix.xx != 1.0 || matrix.yy != 1.0 || matrix.xy != 0.0 || matrix.yx != 0.0) {
|
if (matrix.xx != 1.0 || matrix.yy != 1.0 || matrix.xy != 0.0 || matrix.yx != 0.0) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: matrix not a pure translation\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: matrix not a pure translation\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
/* Check that the matrix translation offsets (adjusted for
|
/* Check that the matrix translation offsets (adjusted for
|
||||||
device offset) are integers */
|
device offset) are integers */
|
||||||
if (!_convert_coord_to_short (matrix.x0 + device_offset_x, &offset_x) ||
|
if (!_convert_coord_to_short (matrix.x0 + device_offset_x, &offset_x) ||
|
||||||
!_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y)) {
|
!_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y)) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-integer offset\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: non-integer offset\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
max_rectangles = 0;
|
max_rectangles = 0;
|
||||||
if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT) {
|
if (capabilities & CAIRO_GDK_DRAWING_SUPPORTS_CLIP_RECT) {
|
||||||
max_rectangles = 1;
|
max_rectangles = 1;
|
||||||
}
|
}
|
||||||
if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST) {
|
if (capabilities & CAIRO_GDK_DRAWING_SUPPORTS_CLIP_LIST) {
|
||||||
max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
|
max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,26 +259,26 @@ _draw_with_xlib_direct (cairo_t *cr,
|
||||||
rectangles, max_rectangles, &rect_count);
|
rectangles, max_rectangles, &rect_count);
|
||||||
cairo_set_matrix (cr, &matrix);
|
cairo_set_matrix (cr, &matrix);
|
||||||
if (!have_rectangular_clip) {
|
if (!have_rectangular_clip) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported clip\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: unsupported clip\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop now if everything is clipped out */
|
/* Stop now if everything is clipped out */
|
||||||
if (needs_clip && rect_count == 0) {
|
if (needs_clip && rect_count == 0) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH: all clipped\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING FAST PATH: all clipped\n");
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the operator is OVER */
|
/* Check that the operator is OVER */
|
||||||
if (cairo_get_operator (cr) != CAIRO_OPERATOR_OVER) {
|
if (cairo_get_operator (cr) != CAIRO_OPERATOR_OVER) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-OVER operator\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: non-OVER operator\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the offset is supported */
|
/* Check that the offset is supported */
|
||||||
if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET) &&
|
if (!(capabilities & CAIRO_GDK_DRAWING_SUPPORTS_OFFSET) &&
|
||||||
(offset_x != 0 || offset_y != 0)) {
|
(offset_x != 0 || offset_y != 0)) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported offset\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: unsupported offset\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,35 +286,36 @@ _draw_with_xlib_direct (cairo_t *cr,
|
||||||
we might complete early above when when the object to be drawn is
|
we might complete early above when when the object to be drawn is
|
||||||
completely clipped out. */
|
completely clipped out. */
|
||||||
if (!d) {
|
if (!d) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-X surface\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: non-X surface\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the display is supported */
|
/* Check that the display is supported */
|
||||||
screen = cairo_xlib_surface_get_screen (target);
|
screen = cairo_xlib_surface_get_screen (target);
|
||||||
if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN) &&
|
if (!(capabilities & CAIRO_GDK_DRAWING_SUPPORTS_ALTERNATE_SCREEN) &&
|
||||||
screen != DefaultScreenOfDisplay (default_display)) {
|
screen != DefaultScreenOfDisplay (default_display)) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default display\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: non-default display\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that there is a visual */
|
/* Check that there is a visual */
|
||||||
visual = cairo_xlib_surface_get_visual (target);
|
visual = cairo_xlib_surface_get_visual (target);
|
||||||
if (!visual) {
|
if (!visual) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: no Visual for surface\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: no Visual for surface\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
/* Check that the visual is supported */
|
/* Check that the visual is supported */
|
||||||
if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL) &&
|
if (!(capabilities & CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL) &&
|
||||||
DefaultVisualOfScreen (screen) != visual) {
|
DefaultVisualOfScreen (screen) != visual) {
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default visual\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING SLOW PATH: non-default visual\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we're good to go! */
|
/* we're good to go! */
|
||||||
CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH\n");
|
CAIRO_GDK_DRAWING_NOTE("TAKING FAST PATH\n");
|
||||||
cairo_surface_flush (target);
|
cairo_surface_flush (target);
|
||||||
callback (closure, screen, d, visual, offset_x, offset_y, rectangles,
|
callback (closure, GDK_DRAWABLE(gdk_xid_table_lookup(d)),
|
||||||
|
offset_x, offset_y, rectangles,
|
||||||
needs_clip ? rect_count : 0);
|
needs_clip ? rect_count : 0);
|
||||||
cairo_surface_mark_dirty (target);
|
cairo_surface_mark_dirty (target);
|
||||||
return True;
|
return True;
|
||||||
|
@ -322,7 +323,7 @@ _draw_with_xlib_direct (cairo_t *cr,
|
||||||
|
|
||||||
static cairo_surface_t *
|
static cairo_surface_t *
|
||||||
_create_temp_xlib_surface (cairo_t *cr, Display *dpy, int width, int height,
|
_create_temp_xlib_surface (cairo_t *cr, Display *dpy, int width, int height,
|
||||||
cairo_xlib_drawing_support_t capabilities)
|
cairo_gdk_drawing_support_t capabilities)
|
||||||
{
|
{
|
||||||
/* base the temp surface on the *screen* surface, not any intermediate
|
/* base the temp surface on the *screen* surface, not any intermediate
|
||||||
* group surface, because the screen surface is more likely to have
|
* group surface, because the screen surface is more likely to have
|
||||||
|
@ -346,10 +347,10 @@ _create_temp_xlib_surface (cairo_t *cr, Display *dpy, int width, int height,
|
||||||
Screen *target_screen = cairo_xlib_surface_get_screen (target);
|
Screen *target_screen = cairo_xlib_surface_get_screen (target);
|
||||||
Visual *target_visual = cairo_xlib_surface_get_visual (target);
|
Visual *target_visual = cairo_xlib_surface_get_visual (target);
|
||||||
if ((target_screen == screen ||
|
if ((target_screen == screen ||
|
||||||
(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN)) &&
|
(capabilities & CAIRO_GDK_DRAWING_SUPPORTS_ALTERNATE_SCREEN)) &&
|
||||||
target_visual &&
|
target_visual &&
|
||||||
(target_visual == DefaultVisualOfScreen (target_screen) ||
|
(target_visual == DefaultVisualOfScreen (target_screen) ||
|
||||||
(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL))) {
|
(capabilities & CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL))) {
|
||||||
drawable = target_drawable;
|
drawable = target_drawable;
|
||||||
dpy = cairo_xlib_surface_get_display (target);
|
dpy = cairo_xlib_surface_get_display (target);
|
||||||
visual = target_visual;
|
visual = target_visual;
|
||||||
|
@ -381,7 +382,7 @@ _create_temp_xlib_surface (cairo_t *cr, Display *dpy, int width, int height,
|
||||||
|
|
||||||
static cairo_bool_t
|
static cairo_bool_t
|
||||||
_draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
|
_draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
|
||||||
cairo_xlib_drawing_callback callback,
|
cairo_gdk_drawing_callback callback,
|
||||||
void *closure,
|
void *closure,
|
||||||
double background_gray_value)
|
double background_gray_value)
|
||||||
{
|
{
|
||||||
|
@ -399,7 +400,8 @@ _draw_onto_temp_xlib_surface (cairo_surface_t *temp_xlib_surface,
|
||||||
cairo_surface_flush (temp_xlib_surface);
|
cairo_surface_flush (temp_xlib_surface);
|
||||||
/* no clipping is needed because the callback can't draw outside the native
|
/* no clipping is needed because the callback can't draw outside the native
|
||||||
surface anyway */
|
surface anyway */
|
||||||
result = callback (closure, screen, d, visual, 0, 0, NULL, 0);
|
result = callback (closure, GDK_DRAWABLE(gdk_xid_table_lookup(d)),
|
||||||
|
0, 0, NULL, 0);
|
||||||
cairo_surface_mark_dirty (temp_xlib_surface);
|
cairo_surface_mark_dirty (temp_xlib_surface);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -451,7 +453,7 @@ static void
|
||||||
_compute_alpha_values (uint32_t *black_data,
|
_compute_alpha_values (uint32_t *black_data,
|
||||||
uint32_t *white_data,
|
uint32_t *white_data,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
cairo_xlib_drawing_result_t *analysis)
|
cairo_gdk_drawing_result_t *analysis)
|
||||||
{
|
{
|
||||||
int num_pixels = width*height;
|
int num_pixels = width*height;
|
||||||
int i;
|
int i;
|
||||||
|
@ -511,21 +513,22 @@ _compute_alpha_values (uint32_t *black_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cairo_draw_with_xlib (cairo_t *cr,
|
cairo_draw_with_gdk (cairo_t *cr,
|
||||||
cairo_xlib_drawing_callback callback,
|
GdkDrawable * drawable,
|
||||||
void *closure,
|
cairo_gdk_drawing_callback callback,
|
||||||
Display *dpy,
|
void * closure,
|
||||||
unsigned int width, unsigned int height,
|
unsigned int width, unsigned int height,
|
||||||
cairo_xlib_drawing_opacity_t is_opaque,
|
cairo_gdk_drawing_opacity_t is_opaque,
|
||||||
cairo_xlib_drawing_support_t capabilities,
|
cairo_gdk_drawing_support_t capabilities,
|
||||||
cairo_xlib_drawing_result_t *result)
|
cairo_gdk_drawing_result_t *result)
|
||||||
{
|
{
|
||||||
cairo_surface_t *temp_xlib_surface;
|
cairo_surface_t *temp_xlib_surface;
|
||||||
cairo_surface_t *black_image_surface;
|
cairo_surface_t *black_image_surface;
|
||||||
cairo_surface_t *white_image_surface;
|
cairo_surface_t *white_image_surface;
|
||||||
unsigned char *black_data;
|
unsigned char *black_data;
|
||||||
unsigned char *white_data;
|
unsigned char *white_data;
|
||||||
|
Display *dpy = gdk_x11_drawable_get_xdisplay(drawable);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
result->surface = NULL;
|
result->surface = NULL;
|
||||||
|
@ -556,7 +559,7 @@ cairo_draw_with_xlib (cairo_t *cr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_opaque == CAIRO_XLIB_DRAWING_OPAQUE) {
|
if (is_opaque == CAIRO_GDK_DRAWING_OPAQUE) {
|
||||||
cairo_set_source_surface (cr, temp_xlib_surface, 0.0, 0.0);
|
cairo_set_source_surface (cr, temp_xlib_surface, 0.0, 0.0);
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.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/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Novell code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Novell.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* rocallahan@novell.com
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "gfxGdkNativeRenderer.h"
|
||||||
|
#include "gfxContext.h"
|
||||||
|
|
||||||
|
#include "cairo-gdk-utils.h"
|
||||||
|
|
||||||
|
#include "gfxPlatformGtk.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gfxGdkNativeRenderer* mRenderer;
|
||||||
|
nsresult mRV;
|
||||||
|
} NativeRenderingClosure;
|
||||||
|
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
NativeRendering(void *closure,
|
||||||
|
GdkDrawable * drawable,
|
||||||
|
short offset_x, short offset_y,
|
||||||
|
GdkRectangle * rectangles, unsigned int num_rects)
|
||||||
|
{
|
||||||
|
NativeRenderingClosure* cl = (NativeRenderingClosure*)closure;
|
||||||
|
nsresult rv = cl->mRenderer->
|
||||||
|
NativeDraw(drawable, offset_x, offset_y,
|
||||||
|
rectangles, num_rects);
|
||||||
|
cl->mRV = rv;
|
||||||
|
return NS_SUCCEEDED(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
gfxGdkNativeRenderer::Draw(gfxContext* ctx, int width, int height,
|
||||||
|
PRUint32 flags, DrawOutput* output)
|
||||||
|
{
|
||||||
|
NativeRenderingClosure closure = { this, NS_OK };
|
||||||
|
cairo_gdk_drawing_result_t result;
|
||||||
|
// Make sure result.surface is null to start with; we rely on it
|
||||||
|
// being non-null meaning that a surface actually got allocated.
|
||||||
|
result.surface = NULL;
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
output->mSurface = NULL;
|
||||||
|
output->mUniformAlpha = PR_FALSE;
|
||||||
|
output->mUniformColor = PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cairoFlags = 0;
|
||||||
|
if (flags & DRAW_SUPPORTS_OFFSET) {
|
||||||
|
cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_OFFSET;
|
||||||
|
}
|
||||||
|
if (flags & DRAW_SUPPORTS_CLIP_RECT) {
|
||||||
|
cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_CLIP_RECT;
|
||||||
|
}
|
||||||
|
if (flags & DRAW_SUPPORTS_CLIP_LIST) {
|
||||||
|
cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_CLIP_LIST;
|
||||||
|
}
|
||||||
|
if (flags & DRAW_SUPPORTS_ALTERNATE_SCREEN) {
|
||||||
|
cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_ALTERNATE_SCREEN;
|
||||||
|
}
|
||||||
|
if (flags & DRAW_SUPPORTS_NONDEFAULT_VISUAL) {
|
||||||
|
cairoFlags |= CAIRO_GDK_DRAWING_SUPPORTS_NONDEFAULT_VISUAL;
|
||||||
|
}
|
||||||
|
cairo_draw_with_gdk(ctx->GetCairo(),
|
||||||
|
gfxPlatformGtk::GetPlatform()->GetGdkDrawable(ctx->OriginalSurface()),
|
||||||
|
NativeRendering,
|
||||||
|
&closure, width, height,
|
||||||
|
(flags & DRAW_IS_OPAQUE) ? CAIRO_GDK_DRAWING_OPAQUE : CAIRO_GDK_DRAWING_TRANSPARENT,
|
||||||
|
(cairo_gdk_drawing_support_t)cairoFlags,
|
||||||
|
output ? &result : NULL);
|
||||||
|
if (NS_FAILED(closure.mRV)) {
|
||||||
|
if (result.surface) {
|
||||||
|
NS_ASSERTION(output, "How did that happen?");
|
||||||
|
cairo_surface_destroy (result.surface);
|
||||||
|
}
|
||||||
|
return closure.mRV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
if (result.surface) {
|
||||||
|
output->mSurface = gfxASurface::Wrap(result.surface);
|
||||||
|
if (!output->mSurface) {
|
||||||
|
cairo_surface_destroy (result.surface);
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output->mUniformAlpha = result.uniform_alpha;
|
||||||
|
output->mUniformColor = result.uniform_color;
|
||||||
|
output->mColor = gfxRGBA(result.r, result.g, result.b, result.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -1,209 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.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/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Novell code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is Novell.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* rocallahan@novell.com
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#include "gfxXlibNativeRenderer.h"
|
|
||||||
#include "gfxContext.h"
|
|
||||||
|
|
||||||
#include "cairo-xlib-utils.h"
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GTK2
|
|
||||||
#include <gdk/gdkscreen.h>
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Look for an existing Colormap that known to be associated with visual.
|
|
||||||
static Colormap
|
|
||||||
LookupColormapForVisual(const Screen* screen, const Visual* visual)
|
|
||||||
{
|
|
||||||
// common case
|
|
||||||
if (visual == DefaultVisualOfScreen(screen))
|
|
||||||
return DefaultColormapOfScreen(screen);
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GTK2
|
|
||||||
// I wish there were a gdk_x11_display_lookup_screen.
|
|
||||||
Display* dpy = DisplayOfScreen(screen);
|
|
||||||
GdkDisplay* gdkDpy = gdk_x11_lookup_xdisplay(dpy);
|
|
||||||
if (gdkDpy) {
|
|
||||||
gint screen_num = 0;
|
|
||||||
for (int s = 0; s < ScreenCount(dpy); ++s) {
|
|
||||||
if (ScreenOfDisplay(dpy, s) == screen) {
|
|
||||||
screen_num = s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GdkScreen* gdkScreen = gdk_display_get_screen(gdkDpy, screen_num);
|
|
||||||
|
|
||||||
GdkColormap* gdkColormap = NULL;
|
|
||||||
if (visual ==
|
|
||||||
GDK_VISUAL_XVISUAL(gdk_screen_get_rgb_visual(gdkScreen))) {
|
|
||||||
// widget/src/gtk2/mozcontainer.c uses gdk_rgb_get_colormap()
|
|
||||||
// which is inherited by child widgets, so this is the visual
|
|
||||||
// expected when drawing directly to widget surfaces or surfaces
|
|
||||||
// created using cairo_surface_create_similar with
|
|
||||||
// CAIRO_CONTENT_COLOR.
|
|
||||||
// gdk_screen_get_rgb_colormap is the generalization of
|
|
||||||
// gdk_rgb_get_colormap for any screen.
|
|
||||||
gdkColormap = gdk_screen_get_rgb_colormap(gdkScreen);
|
|
||||||
}
|
|
||||||
else if (visual ==
|
|
||||||
GDK_VISUAL_XVISUAL(gdk_screen_get_rgba_visual(gdkScreen))) {
|
|
||||||
// This is the visual expected on displays with the Composite
|
|
||||||
// extension enabled when the surface has been created using
|
|
||||||
// cairo_surface_create_similar with CAIRO_CONTENT_COLOR_ALPHA,
|
|
||||||
// as happens with non-unit opacity.
|
|
||||||
gdkColormap = gdk_screen_get_rgba_colormap(gdkScreen);
|
|
||||||
}
|
|
||||||
if (gdkColormap != NULL)
|
|
||||||
return GDK_COLORMAP_XCOLORMAP(gdkColormap);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
gfxXlibNativeRenderer* mRenderer;
|
|
||||||
nsresult mRV;
|
|
||||||
} NativeRenderingClosure;
|
|
||||||
|
|
||||||
static cairo_bool_t
|
|
||||||
NativeRendering(void *closure,
|
|
||||||
Screen *screen,
|
|
||||||
Drawable drawable,
|
|
||||||
Visual *visual,
|
|
||||||
short offset_x, short offset_y,
|
|
||||||
XRectangle* rectangles, unsigned int num_rects)
|
|
||||||
{
|
|
||||||
// Cairo doesn't provide a Colormap.
|
|
||||||
// See if a suitable existing Colormap is known.
|
|
||||||
Colormap colormap = LookupColormapForVisual(screen, visual);
|
|
||||||
PRBool allocColormap = colormap == None;
|
|
||||||
if (allocColormap) {
|
|
||||||
// No existing colormap found.
|
|
||||||
// This case is not expected with MOZ_WIDGET_GTK2.
|
|
||||||
// Create a Colormap for the Visual.
|
|
||||||
// This is only really useful for Visual classes with predefined
|
|
||||||
// Colormap entries, but cairo would be all confused with
|
|
||||||
// non-default non-TrueColor colormaps anyway.
|
|
||||||
NS_ASSERTION(visual->c_class == TrueColor ||
|
|
||||||
visual->c_class == StaticColor ||
|
|
||||||
visual->c_class == StaticGray,
|
|
||||||
"Creating empty colormap");
|
|
||||||
// If this case were expected then it might be worth considering
|
|
||||||
// using a service that maintains a set of Colormaps for associated
|
|
||||||
// Visuals so as to avoid repeating the LockDisplay required in
|
|
||||||
// XCreateColormap, but then it's no worse than the XCreatePixmap
|
|
||||||
// that produced the Drawable here.
|
|
||||||
colormap = XCreateColormap(DisplayOfScreen(screen),
|
|
||||||
RootWindowOfScreen(screen),
|
|
||||||
visual, AllocNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeRenderingClosure* cl = (NativeRenderingClosure*)closure;
|
|
||||||
nsresult rv = cl->mRenderer->
|
|
||||||
NativeDraw(screen, drawable, visual, colormap, offset_x, offset_y,
|
|
||||||
rectangles, num_rects);
|
|
||||||
cl->mRV = rv;
|
|
||||||
|
|
||||||
if (allocColormap) {
|
|
||||||
XFreeColormap(DisplayOfScreen(screen), colormap);
|
|
||||||
}
|
|
||||||
return NS_SUCCEEDED(rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
gfxXlibNativeRenderer::Draw(Display* dpy, gfxContext* ctx, int width, int height,
|
|
||||||
PRUint32 flags, DrawOutput* output)
|
|
||||||
{
|
|
||||||
NativeRenderingClosure closure = { this, NS_OK };
|
|
||||||
cairo_xlib_drawing_result_t result;
|
|
||||||
// Make sure result.surface is null to start with; we rely on it
|
|
||||||
// being non-null meaning that a surface actually got allocated.
|
|
||||||
result.surface = NULL;
|
|
||||||
|
|
||||||
if (output) {
|
|
||||||
output->mSurface = NULL;
|
|
||||||
output->mUniformAlpha = PR_FALSE;
|
|
||||||
output->mUniformColor = PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cairoFlags = 0;
|
|
||||||
if (flags & DRAW_SUPPORTS_OFFSET) {
|
|
||||||
cairoFlags |= CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET;
|
|
||||||
}
|
|
||||||
if (flags & DRAW_SUPPORTS_CLIP_RECT) {
|
|
||||||
cairoFlags |= CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT;
|
|
||||||
}
|
|
||||||
if (flags & DRAW_SUPPORTS_CLIP_LIST) {
|
|
||||||
cairoFlags |= CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST;
|
|
||||||
}
|
|
||||||
if (flags & DRAW_SUPPORTS_ALTERNATE_SCREEN) {
|
|
||||||
cairoFlags |= CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN;
|
|
||||||
}
|
|
||||||
if (flags & DRAW_SUPPORTS_NONDEFAULT_VISUAL) {
|
|
||||||
cairoFlags |= CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL;
|
|
||||||
}
|
|
||||||
cairo_draw_with_xlib(ctx->GetCairo(), NativeRendering, &closure, dpy,
|
|
||||||
width, height,
|
|
||||||
(flags & DRAW_IS_OPAQUE) ? CAIRO_XLIB_DRAWING_OPAQUE
|
|
||||||
: CAIRO_XLIB_DRAWING_TRANSPARENT,
|
|
||||||
(cairo_xlib_drawing_support_t)cairoFlags,
|
|
||||||
output ? &result : NULL);
|
|
||||||
if (NS_FAILED(closure.mRV)) {
|
|
||||||
if (result.surface) {
|
|
||||||
NS_ASSERTION(output, "How did that happen?");
|
|
||||||
cairo_surface_destroy (result.surface);
|
|
||||||
}
|
|
||||||
return closure.mRV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output) {
|
|
||||||
if (result.surface) {
|
|
||||||
output->mSurface = gfxASurface::Wrap(result.surface);
|
|
||||||
if (!output->mSurface) {
|
|
||||||
cairo_surface_destroy (result.surface);
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output->mUniformAlpha = result.uniform_alpha;
|
|
||||||
output->mUniformColor = result.uniform_color;
|
|
||||||
output->mColor = gfxRGBA(result.r, result.g, result.b, result.alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
Загрузка…
Ссылка в новой задаче