mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=576143 copy and draw over background to avoid alpha extraction when possible r=roc
--HG-- extra : rebase_source : 810293a95d07bc0f0a981466a596ccd0db8d389b
This commit is contained in:
parent
1094a22411
commit
daf62b7225
@ -40,6 +40,7 @@
|
||||
#include "gfxXlibNativeRenderer.h"
|
||||
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "cairo-xlib.h"
|
||||
#include "cairo-xlib-xrender.h"
|
||||
@ -60,18 +61,38 @@
|
||||
#define NATIVE_DRAWING_NOTE(m) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* We have three basic strategies available:
|
||||
1) 'direct': cr targets an xlib 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 xlib surface,
|
||||
pass its underlying drawable to the callback, and paint the result
|
||||
using cairo
|
||||
3) 'default': create a temporary cairo xlib 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
|
||||
/* We have four basic strategies available:
|
||||
|
||||
1) 'direct': If the target is an xlib surface, and other conditions are met,
|
||||
we can pass the underlying drawable directly to the callback.
|
||||
|
||||
2) 'simple': If the drawing is opaque, or we can draw to a surface with an
|
||||
alpha channel, then we can create a temporary xlib surface, pass its
|
||||
underlying drawable to the callback, and composite the result using
|
||||
cairo.
|
||||
|
||||
3) 'copy-background': If the drawing is not opaque but the target is
|
||||
opaque, and we can draw to a surface with format such that pixel
|
||||
conversion to and from the target format is exact, we can create a
|
||||
temporary xlib surface, copy the background from the target, pass the
|
||||
underlying drawable to the callback, and copy back to the target.
|
||||
|
||||
This strategy is not used if the pixel format conversion is not exact,
|
||||
because that would mean that drawing intended to be very transparent
|
||||
messes with other content.
|
||||
|
||||
The strategy is prefered over simple for non-opaque drawing and opaque
|
||||
targets on the same screen as compositing without alpha is a simpler
|
||||
operation.
|
||||
|
||||
4) 'alpha-extraction': create a temporary xlib 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...
|
||||
image using cairo.
|
||||
|
||||
Sure would be nice to have an X extension or GL to do this for us on the
|
||||
server...
|
||||
*/
|
||||
|
||||
static cairo_bool_t
|
||||
@ -97,7 +118,7 @@ _get_rectangular_clip (cairo_t *cr,
|
||||
cliplist = cairo_copy_clip_rectangle_list (cr);
|
||||
if (cliplist->status != CAIRO_STATUS_SUCCESS) {
|
||||
retval = PR_FALSE;
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: non-rectangular clip\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: non-rectangular clip");
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
@ -113,7 +134,7 @@ _get_rectangular_clip (cairo_t *cr,
|
||||
!_convert_coord_to_int (clips[i].height, &rect.height))
|
||||
{
|
||||
retval = PR_FALSE;
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: non-integer clip\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: non-integer clip");
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
@ -128,7 +149,7 @@ _get_rectangular_clip (cairo_t *cr,
|
||||
|
||||
if (i >= max_rectangles) {
|
||||
retval = PR_FALSE;
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: unsupported clip rectangle count\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: unsupported clip rectangle count");
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
@ -157,16 +178,10 @@ gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
|
||||
{
|
||||
cairo_t *cr = ctx->GetCairo();
|
||||
|
||||
/* Check that the operator is OVER */
|
||||
if (cairo_get_operator (cr) != CAIRO_OPERATOR_OVER) {
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: non-OVER operator\n");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* Check that the target surface is an xlib surface. */
|
||||
cairo_surface_t *target = cairo_get_group_target (cr);
|
||||
if (cairo_surface_get_type (target) != CAIRO_SURFACE_TYPE_XLIB) {
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: non-X surface\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: non-X surface");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
@ -175,18 +190,18 @@ gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
|
||||
then alternate screens cannot be supported. */
|
||||
PRBool supports_alternate_visual =
|
||||
(flags & DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
|
||||
PRBool supports_alternate_screen = supports_alternate_visual
|
||||
&& (flags & DRAW_SUPPORTS_ALTERNATE_SCREEN);
|
||||
PRBool supports_alternate_screen = supports_alternate_visual &&
|
||||
(flags & DRAW_SUPPORTS_ALTERNATE_SCREEN);
|
||||
if (!supports_alternate_screen &&
|
||||
cairo_xlib_surface_get_screen (target) != screen) {
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: non-default screen\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: non-default screen");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* Check that there is a visual */
|
||||
Visual *target_visual = cairo_xlib_surface_get_visual (target);
|
||||
if (!target_visual) {
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: no Visual for surface\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: no Visual for surface");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Check that the visual is supported */
|
||||
@ -198,7 +213,7 @@ gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
|
||||
if (!target_format ||
|
||||
(target_format !=
|
||||
XRenderFindVisualFormat (DisplayOfScreen(screen), visual))) {
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: unsupported Visual\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: unsupported Visual");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
@ -269,57 +284,174 @@ gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
|
||||
}
|
||||
|
||||
static PRBool
|
||||
FormatHasAlpha(const XRenderPictFormat *format) {
|
||||
if (!format)
|
||||
return false;
|
||||
|
||||
if (format->type != PictTypeDirect)
|
||||
return false;
|
||||
|
||||
return format->direct.alphaMask != 0;
|
||||
VisualHasAlpha(Screen *screen, Visual *visual) {
|
||||
// There may be some other visuals format with alpha but usually this is
|
||||
// the only one we care about.
|
||||
return visual->c_class == TrueColor &&
|
||||
visual->bits_per_rgb == 8 &&
|
||||
visual->red_mask == 0xff0000 &&
|
||||
visual->green_mask == 0xff00 &&
|
||||
visual->blue_mask == 0xff &&
|
||||
gfxXlibSurface::DepthOfVisual(screen, visual) == 32;
|
||||
}
|
||||
|
||||
// Returns whether pixel conversion between visual and format is exact (in
|
||||
// both directions).
|
||||
static PRBool
|
||||
FormatConversionIsExact(Screen *screen, Visual *visual, XRenderPictFormat *format) {
|
||||
if (!format ||
|
||||
visual->c_class != TrueColor ||
|
||||
format->type != PictTypeDirect ||
|
||||
gfxXlibSurface::DepthOfVisual(screen, visual) != format->depth)
|
||||
return PR_FALSE;
|
||||
|
||||
XRenderPictFormat *visualFormat =
|
||||
XRenderFindVisualFormat(DisplayOfScreen(screen), visual);
|
||||
|
||||
if (visualFormat->type != PictTypeDirect )
|
||||
return PR_FALSE;
|
||||
|
||||
const XRenderDirectFormat& a = visualFormat->direct;
|
||||
const XRenderDirectFormat& b = format->direct;
|
||||
return a.redMask == b.redMask &&
|
||||
a.greenMask == b.greenMask &&
|
||||
a.blueMask == b.blueMask;
|
||||
}
|
||||
|
||||
// The 3 non-direct strategies described above.
|
||||
// The surface format and strategy are inter-dependent.
|
||||
enum DrawingMethod {
|
||||
eSimple,
|
||||
eCopyBackground,
|
||||
eAlphaExtraction
|
||||
};
|
||||
|
||||
static already_AddRefed<gfxXlibSurface>
|
||||
_create_temp_xlib_surface (cairo_t *cr, nsIntSize size,
|
||||
PRUint32 flags, Screen *screen, Visual *visual)
|
||||
CreateTempXlibSurface (gfxASurface *destination, nsIntSize size,
|
||||
PRBool canDrawOverBackground,
|
||||
PRUint32 flags, Screen *screen, Visual *visual,
|
||||
DrawingMethod *method)
|
||||
{
|
||||
Drawable drawable = None;
|
||||
PRBool drawIsOpaque = (flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE) != 0;
|
||||
PRBool supportsAlternateVisual =
|
||||
(flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
|
||||
PRBool supportsAlternateScreen = supportsAlternateVisual &&
|
||||
(flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN);
|
||||
|
||||
// For opaque drawing, set up the temp surface for copying to the target.
|
||||
// For non-opaque drawing we read back anyway so just use the
|
||||
// prefered screen and visual.
|
||||
cairo_surface_t *target = cairo_get_group_target (cr);
|
||||
if ((flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE)
|
||||
&& cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB) {
|
||||
cairo_surface_t *target = destination->CairoSurface();
|
||||
cairo_surface_type_t target_type = cairo_surface_get_type (target);
|
||||
cairo_content_t target_content = cairo_surface_get_content (target);
|
||||
|
||||
Screen *target_screen = cairo_xlib_surface_get_screen (target);
|
||||
PRBool supports_alternate_visual =
|
||||
(flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
|
||||
PRBool supports_alternate_screen = supports_alternate_visual
|
||||
&& (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN);
|
||||
if (target_screen == screen || supports_alternate_screen) {
|
||||
Screen *target_screen = target_type == CAIRO_SURFACE_TYPE_XLIB ?
|
||||
cairo_xlib_surface_get_screen (target) : screen;
|
||||
|
||||
if (supports_alternate_visual) {
|
||||
Visual *target_visual = cairo_xlib_surface_get_visual (target);
|
||||
if (target_visual &&
|
||||
(!FormatHasAlpha(cairo_xlib_surface_get_xrender_format (target)))) {
|
||||
visual = target_visual;
|
||||
} else if (target_screen != screen) {
|
||||
visual = DefaultVisualOfScreen (target_screen);
|
||||
}
|
||||
// When the background has an alpha channel, we need to draw with an alpha
|
||||
// channel anyway, so there is no need to copy the background. If
|
||||
// doCopyBackground is set here, we'll also need to check below that the
|
||||
// background can copied without any loss in format conversions.
|
||||
PRBool doCopyBackground = !drawIsOpaque && canDrawOverBackground &&
|
||||
target_content == CAIRO_CONTENT_COLOR;
|
||||
|
||||
if (supportsAlternateScreen && screen != target_screen && drawIsOpaque) {
|
||||
// Prefer a visual on the target screen.
|
||||
// (If !drawIsOpaque, we'll need doCopyBackground or an alpha channel.)
|
||||
visual = DefaultVisualOfScreen(target_screen);
|
||||
screen = target_screen;
|
||||
|
||||
} else if (doCopyBackground || (supportsAlternateVisual && drawIsOpaque)) {
|
||||
// Analyse the pixel formats either to check whether we can
|
||||
// doCopyBackground or to see if we can find a better visual for
|
||||
// opaque drawing.
|
||||
Visual *target_visual = NULL;
|
||||
XRenderPictFormat *target_format = NULL;
|
||||
switch (target_type) {
|
||||
case CAIRO_SURFACE_TYPE_XLIB:
|
||||
target_visual = cairo_xlib_surface_get_visual (target);
|
||||
target_format = cairo_xlib_surface_get_xrender_format (target);
|
||||
break;
|
||||
case CAIRO_SURFACE_TYPE_IMAGE: {
|
||||
gfxASurface::gfxImageFormat imageFormat =
|
||||
static_cast<gfxImageSurface*>(destination)->Format();
|
||||
target_visual = gfxXlibSurface::FindVisual(screen, imageFormat);
|
||||
Display *dpy = DisplayOfScreen(screen);
|
||||
if (target_visual) {
|
||||
target_format = XRenderFindVisualFormat(dpy, visual);
|
||||
} else {
|
||||
target_format =
|
||||
gfxXlibSurface::FindRenderFormat(dpy, imageFormat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (supportsAlternateVisual &&
|
||||
(supportsAlternateScreen || screen == target_screen)) {
|
||||
if (target_visual) {
|
||||
visual = target_visual;
|
||||
screen = target_screen;
|
||||
}
|
||||
}
|
||||
// Could try harder to match formats across screens for background
|
||||
// copying when !supportsAlternateScreen, if we cared. Preferably
|
||||
// we'll find a visual below with an alpha channel anyway; if so, the
|
||||
// background won't need to be copied.
|
||||
|
||||
drawable = cairo_xlib_surface_get_drawable (target);
|
||||
screen = target_screen;
|
||||
if (doCopyBackground && visual != target_visual &&
|
||||
!FormatConversionIsExact(screen, visual, target_format)) {
|
||||
doCopyBackground = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!drawable) {
|
||||
drawable = RootWindowOfScreen (screen);
|
||||
if (supportsAlternateVisual && !drawIsOpaque &&
|
||||
(screen != target_screen ||
|
||||
!(doCopyBackground || VisualHasAlpha(screen, visual)))) {
|
||||
// Try to find a visual with an alpha channel.
|
||||
Screen *visualScreen =
|
||||
supportsAlternateScreen ? target_screen : screen;
|
||||
Visual *argbVisual =
|
||||
gfxXlibSurface::FindVisual(visualScreen,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
if (argbVisual) {
|
||||
visual = argbVisual;
|
||||
screen = visualScreen;
|
||||
} else if (!doCopyBackground &&
|
||||
gfxXlibSurface::DepthOfVisual(screen, visual) != 24) {
|
||||
// Will need to do alpha extraction; prefer a 24-bit visual.
|
||||
// No advantage in using the target screen.
|
||||
Visual *rgb24Visual =
|
||||
gfxXlibSurface::FindVisual(screen,
|
||||
gfxASurface::ImageFormatRGB24);
|
||||
if (rgb24Visual) {
|
||||
visual = rgb24Visual;
|
||||
}
|
||||
}
|
||||
}
|
||||
return gfxXlibSurface::Create(screen, visual,
|
||||
gfxIntSize(size.width, size.height),
|
||||
drawable);
|
||||
|
||||
Drawable drawable =
|
||||
(screen == target_screen && target_type == CAIRO_SURFACE_TYPE_XLIB) ?
|
||||
cairo_xlib_surface_get_drawable (target) : RootWindowOfScreen(screen);
|
||||
|
||||
nsRefPtr<gfxXlibSurface> surface =
|
||||
gfxXlibSurface::Create(screen, visual,
|
||||
gfxIntSize(size.width, size.height),
|
||||
drawable);
|
||||
|
||||
if (drawIsOpaque ||
|
||||
surface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
|
||||
NATIVE_DRAWING_NOTE(drawIsOpaque ?
|
||||
", SIMPLE OPAQUE\n" : ", SIMPLE WITH ALPHA");
|
||||
*method = eSimple;
|
||||
} else if (doCopyBackground) {
|
||||
NATIVE_DRAWING_NOTE(", COPY BACKGROUND\n");
|
||||
*method = eCopyBackground;
|
||||
} else {
|
||||
NATIVE_DRAWING_NOTE(", SLOW ALPHA EXTRACTION\n");
|
||||
*method = eAlphaExtraction;
|
||||
}
|
||||
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -456,9 +588,17 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
|
||||
result->mUniformAlpha = PR_FALSE;
|
||||
result->mUniformColor = PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool matrixIsIntegerTranslation =
|
||||
!ctx->CurrentMatrix().HasNonIntegerTranslation();
|
||||
|
||||
PRBool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0;
|
||||
gfxMatrix matrix = ctx->CurrentMatrix();
|
||||
|
||||
// We can only draw direct or onto a copied background if pixels align and
|
||||
// native drawing is compatible with the current operator. (The matrix is
|
||||
// actually also pixel-exact for flips and right-angle rotations, which
|
||||
// would permit copying the background but not drawing direct.)
|
||||
PRBool matrixIsIntegerTranslation = !matrix.HasNonIntegerTranslation();
|
||||
PRBool canDrawOverBackground = matrixIsIntegerTranslation &&
|
||||
ctx->CurrentOperator() == gfxContext::OPERATOR_OVER;
|
||||
|
||||
// The padding of 0.5 for non-pixel-exact transformations used here is
|
||||
// the same as what _cairo_pattern_analyze_filter uses.
|
||||
@ -469,8 +609,11 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
|
||||
// little larger than the drawingRect;
|
||||
affectedRect.Outset(filterRadius);
|
||||
|
||||
NATIVE_DRAWING_NOTE("TAKING SLOW PATH: matrix not integer translation\n");
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: matrix not integer translation");
|
||||
} else if (!canDrawOverBackground) {
|
||||
NATIVE_DRAWING_NOTE("FALLBACK: unsupported operator");
|
||||
}
|
||||
|
||||
// Clipping to the region affected by drawing allows us to consider only
|
||||
// the portions of the clip region that will be affected by drawing.
|
||||
gfxRect clipExtents;
|
||||
@ -482,42 +625,59 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
|
||||
if (clipExtents.IsEmpty())
|
||||
return; // nothing to do
|
||||
|
||||
if (matrixIsIntegerTranslation &&
|
||||
if (canDrawOverBackground &&
|
||||
DrawDirect(ctx, size, flags, screen, visual))
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect drawingRect(nsIntPoint(0, 0), size);
|
||||
PRBool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0;
|
||||
if (drawIsOpaque || !result) {
|
||||
// Drawing need only be performed within the clip extents
|
||||
// (and padding for the filter).
|
||||
if (!matrixIsIntegerTranslation) {
|
||||
// The source surface may need to be a little larger than the clip
|
||||
// extents due to the filter footprint.
|
||||
clipExtents.Outset(filterRadius);
|
||||
}
|
||||
clipExtents.RoundOut();
|
||||
|
||||
nsIntRect intExtents(PRInt32(clipExtents.X()),
|
||||
PRInt32(clipExtents.Y()),
|
||||
PRInt32(clipExtents.Width()),
|
||||
PRInt32(clipExtents.Height()));
|
||||
drawingRect.IntersectRect(drawingRect, intExtents);
|
||||
// Drawing need only be performed within the clip extents
|
||||
// (and padding for the filter).
|
||||
if (!matrixIsIntegerTranslation) {
|
||||
// The source surface may need to be a little larger than the clip
|
||||
// extents due to the filter footprint.
|
||||
clipExtents.Outset(filterRadius);
|
||||
}
|
||||
clipExtents.RoundOut();
|
||||
|
||||
nsIntRect intExtents(PRInt32(clipExtents.X()),
|
||||
PRInt32(clipExtents.Y()),
|
||||
PRInt32(clipExtents.Width()),
|
||||
PRInt32(clipExtents.Height()));
|
||||
drawingRect.IntersectRect(drawingRect, intExtents);
|
||||
gfxPoint offset(drawingRect.x, drawingRect.y);
|
||||
|
||||
cairo_t *cr = ctx->GetCairo();
|
||||
DrawingMethod method;
|
||||
nsRefPtr<gfxASurface> target = ctx->CurrentSurface();
|
||||
nsRefPtr<gfxXlibSurface> tempXlibSurface =
|
||||
_create_temp_xlib_surface (cr, drawingRect.Size(),
|
||||
flags, screen, visual);
|
||||
if (tempXlibSurface == NULL)
|
||||
CreateTempXlibSurface(target, drawingRect.Size(),
|
||||
canDrawOverBackground, flags, screen, visual,
|
||||
&method);
|
||||
if (!tempXlibSurface)
|
||||
return;
|
||||
|
||||
if (drawingRect.Size() != size || method == eCopyBackground) {
|
||||
// Only drawing a portion, or copying background,
|
||||
// so won't return a result.
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> tmpCtx;
|
||||
if (!drawIsOpaque) {
|
||||
tmpCtx = new gfxContext(tempXlibSurface);
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
if (method == eCopyBackground) {
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
tmpCtx->SetSource(target, -(offset + matrix.GetTranslation()));
|
||||
// The copy from the tempXlibSurface to the target context should
|
||||
// use operator SOURCE, but that would need a mask to bound the
|
||||
// operation. Here we only copy opaque backgrounds so operator
|
||||
// OVER will behave like SOURCE masked by the surface.
|
||||
NS_ASSERTION(tempXlibSurface->GetContentType()
|
||||
== gfxASurface::CONTENT_COLOR,
|
||||
"Don't copy background with a transparent surface");
|
||||
} else {
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
}
|
||||
tmpCtx->Paint();
|
||||
}
|
||||
|
||||
@ -525,7 +685,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawIsOpaque) {
|
||||
if (method != eAlphaExtraction) {
|
||||
ctx->SetSource(tempXlibSurface, offset);
|
||||
ctx->Paint();
|
||||
if (result) {
|
||||
@ -561,6 +721,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
|
||||
_compute_alpha_values ((uint32_t*)black_data, (uint32_t*)white_data, width, height, result);
|
||||
cairo_surface_mark_dirty (black_image_surface);
|
||||
|
||||
cairo_t *cr = ctx->GetCairo();
|
||||
cairo_set_source_surface (cr, black_image_surface, offset.x, offset.y);
|
||||
/* if the caller wants to retrieve the rendered image, put it into
|
||||
a 'similar' surface, and use that as the source for the drawing right
|
||||
|
Loading…
Reference in New Issue
Block a user