mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 04:15:43 +00:00
b=343655, optimize win32 image rendering, r=stuart
This commit is contained in:
parent
23050ef7af
commit
72045a4f50
@ -55,8 +55,10 @@ typedef struct _cairo_win32_surface {
|
||||
|
||||
HDC dc;
|
||||
|
||||
/* We create off-screen surfaces as DIBs */
|
||||
/* We create off-screen surfaces as DIBs or DDBs, based on what we created
|
||||
* originally*/
|
||||
HBITMAP bitmap;
|
||||
cairo_bool_t is_dib;
|
||||
|
||||
/* Used to save the initial 1x1 monochrome bitmap for the DC to
|
||||
* select back into the DC before deleting the DC and our
|
||||
@ -74,8 +76,26 @@ typedef struct _cairo_win32_surface {
|
||||
HRGN saved_clip;
|
||||
|
||||
cairo_rectangle_int16_t extents;
|
||||
|
||||
/* Surface DC flags */
|
||||
uint32_t flags;
|
||||
} cairo_win32_surface_t;
|
||||
|
||||
/* Surface DC flag values */
|
||||
enum {
|
||||
/* Whether the DC is a display DC or not */
|
||||
CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1),
|
||||
|
||||
/* Whether we can use BitBlt with this surface */
|
||||
CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2),
|
||||
|
||||
/* Whether we can use AlphaBlend with this surface */
|
||||
CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
|
||||
|
||||
/* Whether we can use StretchBlt with this surface */
|
||||
CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4)
|
||||
};
|
||||
|
||||
cairo_status_t
|
||||
_cairo_win32_print_gdi_error (const char *context);
|
||||
|
||||
|
@ -88,6 +88,42 @@ _cairo_win32_print_gdi_error (const char *context)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
_cairo_win32_flags_for_dc (HDC dc)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
|
||||
flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY;
|
||||
|
||||
/* These will always be possible, but the actual GetDeviceCaps
|
||||
* calls will return whether they're accelerated or not.
|
||||
* We may want to use our own (pixman) routines sometimes
|
||||
* if they're eventually faster, but for now have GDI do
|
||||
* everything.
|
||||
*/
|
||||
flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
|
||||
flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
|
||||
/*flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;*/
|
||||
} else {
|
||||
int cap;
|
||||
|
||||
cap = GetDeviceCaps(dc, SHADEBLENDCAPS);
|
||||
if (cap != SB_NONE)
|
||||
flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
|
||||
|
||||
cap = GetDeviceCaps(dc, RASTERCAPS);
|
||||
if (cap & RC_BITBLT)
|
||||
flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
|
||||
/*
|
||||
if (cap & RC_STRETCHBLT)
|
||||
flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
|
||||
*/
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_create_dc_and_bitmap (cairo_win32_surface_t *surface,
|
||||
HDC original_dc,
|
||||
@ -111,6 +147,7 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
|
||||
|
||||
surface->dc = NULL;
|
||||
surface->bitmap = NULL;
|
||||
surface->is_dib = FALSE;
|
||||
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
@ -199,6 +236,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
|
||||
if (!surface->bitmap)
|
||||
goto FAIL;
|
||||
|
||||
surface->is_dib = TRUE;
|
||||
|
||||
GdiFlush();
|
||||
|
||||
surface->saved_dc_bitmap = SelectObject (surface->dc,
|
||||
@ -230,6 +269,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
|
||||
}
|
||||
}
|
||||
|
||||
surface->flags = _cairo_win32_flags_for_dc (surface->dc);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
FAIL:
|
||||
@ -295,8 +336,8 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
|
||||
|
||||
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
|
||||
if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {
|
||||
DeleteObject(surface->saved_clip);
|
||||
surface->saved_clip = NULL;
|
||||
DeleteObject(surface->saved_clip);
|
||||
surface->saved_clip = NULL;
|
||||
}
|
||||
|
||||
surface->extents = surface->clip_rect;
|
||||
@ -309,8 +350,8 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
|
||||
FAIL:
|
||||
if (surface->bitmap) {
|
||||
SelectObject (surface->dc, surface->saved_dc_bitmap);
|
||||
DeleteObject (surface->bitmap);
|
||||
DeleteDC (surface->dc);
|
||||
DeleteObject (surface->bitmap);
|
||||
DeleteDC (surface->dc);
|
||||
}
|
||||
if (surface)
|
||||
free (surface);
|
||||
@ -324,16 +365,50 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_win32_surface_create_similar_internal (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
cairo_bool_t force_dib)
|
||||
{
|
||||
cairo_win32_surface_t *src = abstract_src;
|
||||
cairo_format_t format = _cairo_format_from_content (content);
|
||||
cairo_win32_surface_t *new_surf;
|
||||
|
||||
/* if the parent is a DIB or if we need alpha, then
|
||||
* we have to create a dib */
|
||||
if (force_dib || src->is_dib || (content & CAIRO_CONTENT_ALPHA)) {
|
||||
new_surf = (cairo_win32_surface_t*)
|
||||
_cairo_win32_surface_create_for_dc (src->dc, format, width, height);
|
||||
} else {
|
||||
/* otherwise, create a ddb */
|
||||
HBITMAP ddb = CreateCompatibleBitmap (src->dc, width, height);
|
||||
HDC ddb_dc = CreateCompatibleDC (src->dc);
|
||||
HRGN crgn = CreateRectRgn (0, 0, width, height);
|
||||
HBITMAP saved_dc_bitmap;
|
||||
|
||||
saved_dc_bitmap = SelectObject (ddb_dc, ddb);
|
||||
SelectClipRgn (ddb_dc, crgn);
|
||||
|
||||
DeleteObject (crgn);
|
||||
|
||||
new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
|
||||
new_surf->bitmap = ddb;
|
||||
new_surf->saved_dc_bitmap = saved_dc_bitmap;
|
||||
new_surf->is_dib = FALSE;
|
||||
}
|
||||
|
||||
return (cairo_surface_t*) new_surf;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_win32_surface_create_similar (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_win32_surface_t *src = abstract_src;
|
||||
cairo_format_t format = _cairo_format_from_content (content);
|
||||
|
||||
return _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
|
||||
return _cairo_win32_surface_create_similar_internal (abstract_src, content, width, height, FALSE);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
@ -350,8 +425,8 @@ _cairo_win32_surface_finish (void *abstract_surface)
|
||||
/* If we created the Bitmap and DC, destroy them */
|
||||
if (surface->bitmap) {
|
||||
SelectObject (surface->dc, surface->saved_dc_bitmap);
|
||||
DeleteObject (surface->bitmap);
|
||||
DeleteDC (surface->dc);
|
||||
DeleteObject (surface->bitmap);
|
||||
DeleteDC (surface->dc);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
@ -370,10 +445,8 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
|
||||
cairo_content_t content = _cairo_content_from_format (surface->format);
|
||||
|
||||
local =
|
||||
(cairo_win32_surface_t *) _cairo_win32_surface_create_similar (surface,
|
||||
content,
|
||||
width,
|
||||
height);
|
||||
(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
|
||||
(surface, content, width, height, TRUE);
|
||||
if (local->base.status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
@ -574,14 +647,18 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
|
||||
int alpha,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int src_w,
|
||||
int src_h,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height)
|
||||
int dst_w,
|
||||
int dst_h)
|
||||
{
|
||||
static unsigned alpha_blend_checked = FALSE;
|
||||
static cairo_alpha_blend_func_t alpha_blend = NULL;
|
||||
|
||||
int oldstretchmode;
|
||||
BOOL success;
|
||||
BLENDFUNCTION blend_function;
|
||||
|
||||
/* Check for AlphaBlend dynamically to allow compiling on
|
||||
@ -610,7 +687,7 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
|
||||
|
||||
if (alpha_blend == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (GetDeviceCaps(dst->dc, SHADEBLENDCAPS) == SB_NONE)
|
||||
if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
blend_function.BlendOp = AC_SRC_OVER;
|
||||
@ -618,14 +695,16 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
|
||||
blend_function.SourceConstantAlpha = alpha;
|
||||
blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0;
|
||||
|
||||
/*oldstretchmode = SetStretchBltMode(dst->dc, HALFTONE);*/
|
||||
if (!alpha_blend (dst->dc,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
dst_w, dst_h,
|
||||
src->dc,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
src_w, src_h,
|
||||
blend_function))
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
|
||||
/*SetStretchBltMode(dst->dc, oldstretchmode);*/
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
@ -648,11 +727,31 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
||||
cairo_win32_surface_t *src;
|
||||
cairo_surface_pattern_t *src_surface_pattern;
|
||||
int alpha;
|
||||
int integer_transform;
|
||||
int itx, ity;
|
||||
double scalex, scaley;
|
||||
cairo_fixed_t x0_fixed, y0_fixed;
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
|
||||
pattern->extend != CAIRO_EXTEND_NONE)
|
||||
int src_width, src_height;
|
||||
int dst_width, dst_height;
|
||||
|
||||
cairo_bool_t needs_alpha, needs_scale;
|
||||
|
||||
/* If the destination can't do any of these, then
|
||||
* we may as well give up, since this is what we'll
|
||||
* look to for optimization.
|
||||
*/
|
||||
if (dst->flags & (CAIRO_WIN32_SURFACE_CAN_BITBLT |
|
||||
CAIRO_WIN32_SURFACE_CAN_ALPHABLEND |
|
||||
CAIRO_WIN32_SURFACE_CAN_STRETCHBLT)
|
||||
== 0)
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (pattern->extend != CAIRO_EXTEND_NONE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (mask_pattern) {
|
||||
@ -664,7 +763,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
||||
|
||||
alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
|
||||
} else {
|
||||
alpha = 255;
|
||||
alpha = 255;
|
||||
}
|
||||
|
||||
src_surface_pattern = (cairo_surface_pattern_t *)pattern;
|
||||
@ -673,9 +772,71 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
||||
if (src->base.backend != dst->base.backend)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
integer_transform = _cairo_matrix_is_integer_translation (&pattern->matrix, &itx, &ity);
|
||||
if (!integer_transform)
|
||||
#if 0
|
||||
fprintf (stderr, "Before check: (%d %d) [%d %d] -> [%d %d %d %d] {mat %f %f %f %f}\n",
|
||||
src->extents.width, src->extents.height,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y, width, height,
|
||||
pattern->matrix.x0, pattern->matrix.y0, pattern->matrix.xx, pattern->matrix.yy);
|
||||
#endif
|
||||
|
||||
/* We can only use GDI functions if the source and destination rectangles
|
||||
* are on integer pixel boundaries. Figure that out here.
|
||||
*/
|
||||
x0_fixed = _cairo_fixed_from_double(pattern->matrix.x0 / pattern->matrix.xx);
|
||||
y0_fixed = _cairo_fixed_from_double(pattern->matrix.y0 / pattern->matrix.yy);
|
||||
|
||||
if (pattern->matrix.yx != 0.0 ||
|
||||
pattern->matrix.xy != 0.0 ||
|
||||
!_cairo_fixed_is_integer(x0_fixed) ||
|
||||
!_cairo_fixed_is_integer(y0_fixed))
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
itx = _cairo_fixed_integer_part(x0_fixed);
|
||||
ity = _cairo_fixed_integer_part(y0_fixed);
|
||||
|
||||
scalex = pattern->matrix.xx;
|
||||
scaley = pattern->matrix.yy;
|
||||
|
||||
src_x += itx;
|
||||
src_y += ity;
|
||||
|
||||
#if 0
|
||||
if (scalex != 1.0 || scaley != 1.0) {
|
||||
/* we already know that the destination is an integer rectangle;
|
||||
* we need to see if the source is also.
|
||||
*/
|
||||
cairo_fixed_t sx0 = _cairo_fixed_from_double(src_x * scalex);
|
||||
cairo_fixed_t sy0 = _cairo_fixed_from_double(src_y * scaley);
|
||||
cairo_fixed_t sw = _cairo_fixed_from_double((src->extents.width - src_x) * scalex);
|
||||
cairo_fixed_t sh = _cairo_fixed_from_double((src->extents.height - src_y) * scaley);
|
||||
|
||||
fprintf (stderr, "sx0 sy0 sw sh: %f %f %f %f\n",
|
||||
_cairo_fixed_to_double(sx0), _cairo_fixed_to_double(sy0),
|
||||
_cairo_fixed_to_double(sw), _cairo_fixed_to_double(sh));
|
||||
|
||||
if (!_cairo_fixed_is_integer(sw) ||
|
||||
!_cairo_fixed_is_integer(sh) ||
|
||||
!_cairo_fixed_is_integer(sx0) ||
|
||||
!_cairo_fixed_is_integer(sy0))
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scalex <= 0.0 || scaley <= 0.0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "Before fixup: (%d %d) src: [%d %d] -> dst: [%d %d %d %d] itsc {%d %d %f %f}\n",
|
||||
src->extents.width, src->extents.height,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y, width, height,
|
||||
itx, ity, scalex, scaley);
|
||||
#endif
|
||||
|
||||
/* Fix up src coordinates; the src coords and size must be within the
|
||||
* bounds of the source surface.
|
||||
@ -683,52 +844,113 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
||||
* - for OVER/SOURCE with RGB24 source -> opaque black
|
||||
* - for SOURCE with ARGB32 source -> 100% transparent black
|
||||
*/
|
||||
src_x += itx;
|
||||
src_y += ity;
|
||||
src_x *= scalex;
|
||||
src_y *= scaley;
|
||||
|
||||
if (src_x < 0) {
|
||||
width += src_x;
|
||||
dst_x -= src_x;
|
||||
src_x = 0;
|
||||
width += src_x / scalex;
|
||||
dst_x -= src_x / scalex;
|
||||
src_x = 0;
|
||||
}
|
||||
|
||||
if (src_y < 0) {
|
||||
height += src_y;
|
||||
dst_y -= src_y;
|
||||
src_y = 0;
|
||||
height += src_y / scaley;
|
||||
dst_y -= src_y / scaley;
|
||||
src_y = 0;
|
||||
}
|
||||
|
||||
if (src_x >= src->extents.x + src->extents.width ||
|
||||
src_y >= src->extents.y + src->extents.height)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (src_x + width > (src->extents.width / scalex))
|
||||
dst_width = (src->extents.width / scalex) - src_x;
|
||||
else
|
||||
dst_width = width;
|
||||
|
||||
if (src_x + width > src->extents.width)
|
||||
width = src->extents.width - src_x;
|
||||
if (src_y + height > (src->extents.height / scaley))
|
||||
dst_height = (src->extents.height / scaley) - src_y;
|
||||
else
|
||||
dst_height = height;
|
||||
/* If we're scaling up an iamge, we may have
|
||||
* less than 1 pixel's worth of width/height map
|
||||
* into 1 row in the destination. If this is the case,
|
||||
* we need to clip to the destination's width/height,
|
||||
* and then figure out the next source/dest width/height combo
|
||||
* where there is an integer match.
|
||||
*
|
||||
* For now, just let cairo scale that case. THIS IS NOT IDEAL,
|
||||
* as the scaling algorithms aren't identical!
|
||||
*/
|
||||
if (!_cairo_fixed_is_integer(_cairo_fixed_from_double(dst_width * scalex)) ||
|
||||
!_cairo_fixed_is_integer(_cairo_fixed_from_double(dst_height * scaley)))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (src_y + height > src->extents.height)
|
||||
height = src->extents.height - src_y;
|
||||
src_width = dst_width * scalex;
|
||||
src_height = dst_height * scaley;
|
||||
|
||||
if (alpha == 255 &&
|
||||
(op == CAIRO_OPERATOR_SOURCE ||
|
||||
(src->format == CAIRO_FORMAT_RGB24 && op == CAIRO_OPERATOR_OVER))) {
|
||||
|
||||
if (!BitBlt (dst->dc,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
src->dc,
|
||||
src_x, src_y,
|
||||
SRCCOPY))
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
(src->format == CAIRO_FORMAT_RGB24 && op == CAIRO_OPERATOR_OVER)))
|
||||
{
|
||||
needs_alpha = FALSE;
|
||||
} else if ((src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) &&
|
||||
(dst->format == CAIRO_FORMAT_RGB24 || dst->format == CAIRO_FORMAT_ARGB32) &&
|
||||
op == CAIRO_OPERATOR_OVER) {
|
||||
op == CAIRO_OPERATOR_OVER)
|
||||
{
|
||||
needs_alpha = TRUE;
|
||||
} else {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (scalex == 1.0 && scaley == 1.0) {
|
||||
needs_scale = FALSE;
|
||||
} else {
|
||||
needs_scale = TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n",
|
||||
src_x, src_y, src_width, src_height,
|
||||
dst_x, dst_y, dst_width, dst_height);
|
||||
fflush (stderr);
|
||||
#endif
|
||||
|
||||
/* Then do BitBlt, StretchBlt, AlphaBlend, or MaskBlt */
|
||||
if (!needs_alpha) {
|
||||
/* BitBlt or StretchBlt? */
|
||||
if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
|
||||
if (!BitBlt (dst->dc,
|
||||
dst_x, dst_y,
|
||||
dst_width, dst_height,
|
||||
src->dc,
|
||||
src_x, src_y,
|
||||
SRCCOPY))
|
||||
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
} else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
|
||||
/* StretchBlt? */
|
||||
/* XXX check if we want HALFTONE, based on the src filter */
|
||||
int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
|
||||
BOOL success;
|
||||
|
||||
success = StretchBlt(dst->dc,
|
||||
dst_x, dst_y,
|
||||
dst_width, dst_height,
|
||||
src->dc,
|
||||
src_x, src_y,
|
||||
src_width, src_height,
|
||||
SRCCOPY);
|
||||
SetStretchBltMode(dst->dc, oldmode);
|
||||
|
||||
if (!success) {
|
||||
_cairo_win32_print_gdi_error ("StretchBlt");
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
} else if (needs_alpha && !needs_scale) {
|
||||
return _composite_alpha_blend (dst, src, alpha,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y, width, height);
|
||||
src_x, src_y, src_width, src_height,
|
||||
dst_x, dst_y, dst_width, dst_height);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
@ -1138,7 +1360,7 @@ cairo_win32_surface_create (HDC hdc)
|
||||
if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {
|
||||
depth = GetDeviceCaps(hdc, BITSPIXEL);
|
||||
if (depth == 32)
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
else if (depth == 24)
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
else if (depth == 16)
|
||||
@ -1167,6 +1389,7 @@ cairo_win32_surface_create (HDC hdc)
|
||||
|
||||
surface->dc = hdc;
|
||||
surface->bitmap = NULL;
|
||||
surface->is_dib = FALSE;
|
||||
surface->saved_dc_bitmap = NULL;
|
||||
|
||||
surface->clip_rect.x = rect.left;
|
||||
@ -1188,6 +1411,8 @@ cairo_win32_surface_create (HDC hdc)
|
||||
|
||||
surface->extents = surface->clip_rect;
|
||||
|
||||
surface->flags = _cairo_win32_flags_for_dc (surface->dc);
|
||||
|
||||
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
|
||||
_cairo_content_from_format (format));
|
||||
|
||||
@ -1216,6 +1441,52 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
|
||||
return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_win32_surface_create_with_ddb (HDC hdc,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_win32_surface_t *new_surf;
|
||||
HBITMAP ddb;
|
||||
HDC screen_dc, ddb_dc;
|
||||
HRGN crgn;
|
||||
HBITMAP saved_dc_bitmap;
|
||||
|
||||
if (format != CAIRO_FORMAT_RGB24)
|
||||
return NULL;
|
||||
/* XXX handle these eventually
|
||||
format != CAIRO_FORMAT_A8 ||
|
||||
format != CAIRO_FORMAT_A1)
|
||||
*/
|
||||
|
||||
if (!hdc) {
|
||||
screen_dc = GetDC (NULL);
|
||||
hdc = screen_dc;
|
||||
} else {
|
||||
screen_dc = NULL;
|
||||
}
|
||||
|
||||
ddb = CreateCompatibleBitmap (hdc, width, height);
|
||||
ddb_dc = CreateCompatibleDC (hdc);
|
||||
|
||||
saved_dc_bitmap = SelectObject (ddb_dc, ddb);
|
||||
|
||||
crgn = CreateRectRgn (0, 0, width, height);
|
||||
SelectClipRgn (ddb_dc, crgn);
|
||||
DeleteObject (crgn);
|
||||
|
||||
new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
|
||||
new_surf->bitmap = ddb;
|
||||
new_surf->saved_dc_bitmap = saved_dc_bitmap;
|
||||
new_surf->is_dib = FALSE;
|
||||
|
||||
if (screen_dc)
|
||||
ReleaseDC (NULL, screen_dc);
|
||||
|
||||
return (cairo_surface_t*) new_surf;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_win32:
|
||||
* @surface: a #cairo_surface_t
|
||||
@ -1257,6 +1528,26 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
|
||||
return winsurf->dc;
|
||||
}
|
||||
|
||||
/**
|
||||
* cario_win32_surface_get_image
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Returns a #cairo_surface_t image surface that refers to the same bits
|
||||
* as the DIB of the Win32 surface. If the passed-in win32 surface
|
||||
* is not a DIB surface, NULL is returned.
|
||||
*
|
||||
* Return value: a #cairo_surface_t (reference owned by the win32 cairo_surface_t),
|
||||
* or NULL if the win32 surface is not a DIB.
|
||||
*/
|
||||
cairo_surface_t *
|
||||
cairo_win32_surface_get_image (cairo_surface_t *surface)
|
||||
{
|
||||
if (!_cairo_surface_is_win32(surface))
|
||||
return NULL;
|
||||
|
||||
return ((cairo_win32_surface_t*)surface)->image;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_WIN32,
|
||||
_cairo_win32_surface_create_similar,
|
||||
|
@ -47,6 +47,12 @@ CAIRO_BEGIN_DECLS
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_create (HDC hdc);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_create_with_ddb (HDC hdc,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_create_with_dib (cairo_format_t format,
|
||||
int width,
|
||||
@ -55,6 +61,9 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
|
||||
cairo_public HDC
|
||||
cairo_win32_surface_get_dc (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_win32_surface_get_image (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
||||
|
||||
|
@ -51,10 +51,12 @@ static PRBool gDisableOptimize = PR_FALSE;
|
||||
NS_IMPL_ISUPPORTS1(nsThebesImage, nsIImage)
|
||||
|
||||
nsThebesImage::nsThebesImage()
|
||||
: mWidth(0),
|
||||
: mFormat(gfxImageSurface::ImageFormatRGB24),
|
||||
mWidth(0),
|
||||
mHeight(0),
|
||||
mDecoded(0,0,0,0),
|
||||
mImageComplete(PR_FALSE),
|
||||
mSinglePixel(PR_FALSE),
|
||||
mAlphaDepth(0)
|
||||
{
|
||||
static PRBool hasCheckedOptimize = PR_FALSE;
|
||||
@ -108,7 +110,19 @@ nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequi
|
||||
break;
|
||||
}
|
||||
|
||||
mFormat = format;
|
||||
|
||||
#ifdef XP_WIN
|
||||
mWinSurface = new gfxWindowsSurface(mWidth, mHeight, format);
|
||||
mImageSurface = mWinSurface->GetImageSurface();
|
||||
|
||||
if (!mImageSurface) {
|
||||
mWinSurface = nsnull;
|
||||
mImageSurface = new gfxImageSurface(format, mWidth, mHeight);
|
||||
}
|
||||
#else
|
||||
mImageSurface = new gfxImageSurface(format, mWidth, mHeight);
|
||||
#endif
|
||||
mStride = mImageSurface->Stride();
|
||||
|
||||
return NS_OK;
|
||||
@ -194,10 +208,48 @@ nsThebesImage::Optimize(nsIDeviceContext* aContext)
|
||||
if (gDisableOptimize)
|
||||
return NS_OK;
|
||||
|
||||
if (mOptSurface)
|
||||
if (mOptSurface || mSinglePixel)
|
||||
return NS_OK;
|
||||
|
||||
if (mWidth == 1 && mHeight == 1) {
|
||||
// yeah, let's optimize this.
|
||||
if (mFormat == gfxImageSurface::ImageFormatARGB32 ||
|
||||
mFormat == gfxImageSurface::ImageFormatRGB24)
|
||||
{
|
||||
PRUint32 *pxl = (PRUint32 *) mImageSurface->Data();
|
||||
mSinglePixelColor = gfxRGBA(*pxl);
|
||||
if (mFormat == gfxImageSurface::ImageFormatRGB24)
|
||||
mSinglePixelColor.a = 1.0;
|
||||
|
||||
mSinglePixel = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if it's not RGB24/ARGB32, don't optimize, but we should
|
||||
// never hit this.
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// we need to special-case windows here, because windows has
|
||||
// a distinction between DIB and DDB and we want to use DDBs as much
|
||||
// as we can.
|
||||
if (mWinSurface) {
|
||||
nsRefPtr<gfxWindowsSurface> wsurf = mWinSurface->OptimizeToDDB(nsnull, mFormat, mWidth, mHeight);
|
||||
if (wsurf) {
|
||||
mOptSurface = wsurf;
|
||||
} else {
|
||||
// just use the DIB
|
||||
mOptSurface = mWinSurface;
|
||||
}
|
||||
} else {
|
||||
mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface);
|
||||
}
|
||||
|
||||
mWinSurface = nsnull;
|
||||
#else
|
||||
mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface);
|
||||
#endif
|
||||
|
||||
mImageSurface = nsnull;
|
||||
|
||||
@ -227,7 +279,7 @@ nsThebesImage::LockImagePixels(PRBool aMaskPixels)
|
||||
{
|
||||
if (aMaskPixels)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (mOptSurface && !mImageSurface) {
|
||||
if ((mOptSurface || mSinglePixel) && !mImageSurface) {
|
||||
// Recover the pixels
|
||||
mImageSurface = new gfxImageSurface(gfxImageSurface::ImageFormatARGB32,
|
||||
mWidth, mHeight);
|
||||
@ -239,7 +291,10 @@ nsThebesImage::LockImagePixels(PRBool aMaskPixels)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->SetSource(mOptSurface);
|
||||
if (mSinglePixel)
|
||||
context->SetColor(mSinglePixelColor);
|
||||
else
|
||||
context->SetSource(mOptSurface);
|
||||
context->Paint();
|
||||
}
|
||||
return NS_OK;
|
||||
@ -282,6 +337,18 @@ nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface,
|
||||
mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height);
|
||||
#endif
|
||||
|
||||
if (mSinglePixel) {
|
||||
// if a == 0, it's a noop
|
||||
if (mSinglePixelColor.a == 0.0)
|
||||
return NS_OK;
|
||||
|
||||
// otherwise
|
||||
ctx->SetColor(mSinglePixelColor);
|
||||
ctx->Rectangle(gfxRect(aDX, aDY, aDWidth, aDHeight), PR_TRUE);
|
||||
ctx->Fill();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gfxFloat xscale = gfxFloat(aDWidth) / aSWidth;
|
||||
gfxFloat yscale = gfxFloat(aDHeight) / aSHeight;
|
||||
|
||||
|
@ -41,8 +41,12 @@
|
||||
|
||||
#include "nsIImage.h"
|
||||
|
||||
#include "gfxColor.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#ifdef XP_WIN
|
||||
#include "gfxWindowsSurface.h"
|
||||
#endif
|
||||
|
||||
class nsThebesImage : public nsIImage
|
||||
{
|
||||
@ -102,14 +106,21 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
gfxImageSurface::gfxImageFormat mFormat;
|
||||
PRInt32 mWidth;
|
||||
PRInt32 mHeight;
|
||||
PRInt32 mStride;
|
||||
nsRect mDecoded;
|
||||
PRPackedBool mImageComplete;
|
||||
PRPackedBool mSinglePixel;
|
||||
|
||||
gfxRGBA mSinglePixelColor;
|
||||
|
||||
nsRefPtr<gfxImageSurface> mImageSurface;
|
||||
nsRefPtr<gfxASurface> mOptSurface;
|
||||
#ifdef XP_WIN
|
||||
nsRefPtr<gfxWindowsSurface> mWinSurface;
|
||||
#endif
|
||||
|
||||
PRUint8 mAlphaDepth;
|
||||
};
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
* Distance in bytes between the start of a line and the start of the
|
||||
* next line.
|
||||
*/
|
||||
long Stride() const;
|
||||
long Stride() const { return mStride; }
|
||||
/**
|
||||
* Returns a pointer for the image data. Users of this function can
|
||||
* write to it, but must not attempt to free the buffer.
|
||||
@ -82,10 +82,15 @@ public:
|
||||
unsigned char* Data() { return mData; } // delete this data under us and die.
|
||||
|
||||
private:
|
||||
|
||||
long ComputeStride() const;
|
||||
|
||||
PRBool mOwnsData;
|
||||
unsigned char *mData;
|
||||
gfxImageFormat mFormat;
|
||||
long mWidth;
|
||||
long mHeight;
|
||||
long mStride;
|
||||
};
|
||||
|
||||
#endif /* GFX_IMAGESURFACE_H */
|
||||
|
@ -96,9 +96,16 @@ public:
|
||||
*/
|
||||
virtual nsresult UpdateFontList();
|
||||
|
||||
/* Returns PR_TRUE if the given block of ARGB32 data really has alpha, otherwise PR_FALSE */
|
||||
static PRBool DoesARGBImageDataHaveAlpha(PRUint8* data,
|
||||
PRUint32 width,
|
||||
PRUint32 height,
|
||||
PRUint32 stride);
|
||||
|
||||
protected:
|
||||
gfxPlatform() { }
|
||||
virtual ~gfxPlatform() { }
|
||||
|
||||
};
|
||||
|
||||
#endif /* GFX_PLATFORM_H */
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define GFX_WINDOWSSURFACE_H
|
||||
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@ -46,14 +47,26 @@ class THEBES_API gfxWindowsSurface : public gfxASurface {
|
||||
public:
|
||||
gfxWindowsSurface(HWND wnd);
|
||||
gfxWindowsSurface(HDC dc, PRBool deleteDC = PR_FALSE);
|
||||
|
||||
// Create a DIB surface
|
||||
gfxWindowsSurface(unsigned long width, unsigned long height,
|
||||
gfxImageFormat imageFormat = ImageFormatRGB24);
|
||||
|
||||
// Create a DDB surface; dc may be NULL to use the screen DC
|
||||
gfxWindowsSurface(HDC dc,
|
||||
unsigned long width, unsigned long height,
|
||||
gfxImageFormat imageFormat = ImageFormatRGB24);
|
||||
|
||||
gfxWindowsSurface(cairo_surface_t *csurf);
|
||||
|
||||
virtual ~gfxWindowsSurface();
|
||||
|
||||
HDC GetDC() { return mDC; }
|
||||
|
||||
already_AddRefed<gfxImageSurface> GetImageSurface();
|
||||
|
||||
already_AddRefed<gfxWindowsSurface> OptimizeToDDB(HDC dc, gfxImageFormat format, PRUint32 width, PRUint32 height);
|
||||
|
||||
nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
|
||||
nsresult EndPrinting();
|
||||
nsresult AbortPrinting();
|
||||
|
@ -42,8 +42,9 @@
|
||||
gfxImageSurface::gfxImageSurface(gfxImageFormat format, long width, long height) :
|
||||
mFormat(format), mWidth(width), mHeight(height)
|
||||
{
|
||||
long stride = Stride();
|
||||
long stride = ComputeStride();
|
||||
mData = new unsigned char[height * stride];
|
||||
mOwnsData = PR_TRUE;
|
||||
|
||||
//memset(mData, 0xff, height*stride);
|
||||
|
||||
@ -53,6 +54,8 @@ gfxImageSurface::gfxImageSurface(gfxImageFormat format, long width, long height)
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
mStride = stride;
|
||||
|
||||
Init(surface);
|
||||
}
|
||||
|
||||
@ -60,8 +63,10 @@ gfxImageSurface::gfxImageSurface(cairo_surface_t *csurf)
|
||||
{
|
||||
mWidth = cairo_image_surface_get_width(csurf);
|
||||
mHeight = cairo_image_surface_get_height(csurf);
|
||||
mData = nsnull;
|
||||
mFormat = ImageFormatUnknown;
|
||||
mData = cairo_image_surface_get_data(csurf);
|
||||
mFormat = (gfxImageFormat) cairo_image_surface_get_format(csurf);
|
||||
mOwnsData = PR_FALSE;
|
||||
mStride = cairo_image_surface_get_stride(csurf);
|
||||
|
||||
Init(csurf, PR_TRUE);
|
||||
}
|
||||
@ -70,11 +75,12 @@ gfxImageSurface::~gfxImageSurface()
|
||||
{
|
||||
Destroy();
|
||||
|
||||
delete[] mData;
|
||||
if (mOwnsData)
|
||||
delete[] mData;
|
||||
}
|
||||
|
||||
long
|
||||
gfxImageSurface::Stride() const
|
||||
gfxImageSurface::ComputeStride() const
|
||||
{
|
||||
long stride;
|
||||
|
||||
|
@ -99,13 +99,46 @@ gfxPlatform::SetUseGlitz(PRBool use)
|
||||
gGlitzState = (use ? 1 : 0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxPlatform::DoesARGBImageDataHaveAlpha(PRUint8* data,
|
||||
PRUint32 width,
|
||||
PRUint32 height,
|
||||
PRUint32 stride)
|
||||
{
|
||||
PRUint32 *r;
|
||||
|
||||
for (int j = 0; j < height; j++) {
|
||||
r = (PRUint32*) (data + stride*j);
|
||||
for (int i = 0; i < width; i++) {
|
||||
if ((*r & 0xff000000) != 0xff000000) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
gfxPlatform::OptimizeImage(gfxImageSurface* aSurface)
|
||||
{
|
||||
nsRefPtr<gfxASurface> optSurface;
|
||||
gfxASurface::gfxImageFormat realFormat = aSurface->Format();
|
||||
|
||||
if (realFormat == gfxASurface::ImageFormatARGB32) {
|
||||
// this might not really need alpha; figure that out
|
||||
if (!DoesARGBImageDataHaveAlpha(aSurface->Data(),
|
||||
aSurface->Width(),
|
||||
aSurface->Height(),
|
||||
aSurface->Stride()))
|
||||
{
|
||||
realFormat = gfxASurface::ImageFormatRGB24;
|
||||
}
|
||||
}
|
||||
|
||||
optSurface = CreateOffscreenSurface(aSurface->Width(),
|
||||
aSurface->Height(),
|
||||
aSurface->Format());
|
||||
realFormat);
|
||||
|
||||
if (!optSurface)
|
||||
return nsnull;
|
||||
|
@ -64,7 +64,7 @@ gfxWindowsPlatform::CreateOffscreenSurface(PRUint32 width,
|
||||
PRUint32 height,
|
||||
gfxASurface::gfxImageFormat imageFormat)
|
||||
{
|
||||
gfxASurface *surf = new gfxWindowsSurface(nsnull, width, height, imageFormat);
|
||||
gfxASurface *surf = new gfxWindowsSurface(width, height, imageFormat);
|
||||
NS_IF_ADDREF(surf);
|
||||
return surf;
|
||||
}
|
||||
|
@ -38,6 +38,9 @@
|
||||
#include "gfxWindowsSurface.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#include <cairo-win32.h>
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(HWND wnd) :
|
||||
@ -53,17 +56,34 @@ gfxWindowsSurface::gfxWindowsSurface(HDC dc, PRBool deleteDC) :
|
||||
Init(cairo_win32_surface_create(mDC));
|
||||
}
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(unsigned long width, unsigned long height, gfxImageFormat imageFormat) :
|
||||
mOwnsDC(PR_FALSE), mWnd(nsnull)
|
||||
{
|
||||
HBITMAP bmp = nsnull;
|
||||
|
||||
cairo_surface_t *surf = cairo_win32_surface_create_with_dib((cairo_format_t)imageFormat,
|
||||
width, height);
|
||||
if (!surf || cairo_surface_status(surf)) {
|
||||
fprintf (stderr, "++++++++++++ gfxWindowsSurface: DIB surface creation failed!\n");
|
||||
}
|
||||
|
||||
Init(surf);
|
||||
|
||||
mDC = cairo_win32_surface_get_dc(CairoSurface());
|
||||
}
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(HDC dc, unsigned long width, unsigned long height, gfxImageFormat imageFormat) :
|
||||
mOwnsDC(PR_FALSE), mWnd(nsnull)
|
||||
{
|
||||
HBITMAP bmp = nsnull;
|
||||
|
||||
// At some point we might want to revisit creating a DDB
|
||||
// with CreateCompatibleDC, but from stuff that I've read
|
||||
// that's only useful for terminal services clients.
|
||||
cairo_surface_t *surf = cairo_win32_surface_create_with_ddb(dc, (cairo_format_t)imageFormat,
|
||||
width, height);
|
||||
if (!surf || cairo_surface_status(surf)) {
|
||||
fprintf (stderr, "++++++++++++ gfxWindowsSurface: DDB surface creation failed!\n");
|
||||
}
|
||||
|
||||
Init(cairo_win32_surface_create_with_dib((cairo_format_t)imageFormat,
|
||||
width, height));
|
||||
Init(surf);
|
||||
|
||||
mDC = cairo_win32_surface_get_dc(CairoSurface());
|
||||
}
|
||||
@ -89,6 +109,49 @@ gfxWindowsSurface::~gfxWindowsSurface()
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
gfxWindowsSurface::GetImageSurface()
|
||||
{
|
||||
cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface());
|
||||
if (!isurf)
|
||||
return nsnull;
|
||||
|
||||
nsRefPtr<gfxASurface> asurf = gfxASurface::Wrap(isurf);
|
||||
gfxImageSurface *imgsurf = (gfxImageSurface*) asurf.get();
|
||||
NS_ADDREF(imgsurf);
|
||||
return imgsurf;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxWindowsSurface>
|
||||
gfxWindowsSurface::OptimizeToDDB(HDC dc, gfxImageFormat format, PRUint32 width, PRUint32 height)
|
||||
{
|
||||
gfxImageFormat realFormat = format;
|
||||
if (realFormat == ImageFormatARGB32) {
|
||||
cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface());
|
||||
if (isurf && !gfxPlatform::DoesARGBImageDataHaveAlpha(cairo_image_surface_get_data(isurf),
|
||||
cairo_image_surface_get_width(isurf),
|
||||
cairo_image_surface_get_height(isurf),
|
||||
cairo_image_surface_get_stride(isurf)))
|
||||
{
|
||||
realFormat = ImageFormatRGB24;
|
||||
}
|
||||
}
|
||||
|
||||
if (realFormat != ImageFormatRGB24)
|
||||
return nsnull;
|
||||
|
||||
nsRefPtr<gfxWindowsSurface> wsurf = new gfxWindowsSurface (dc, width, height, realFormat);
|
||||
|
||||
nsRefPtr<gfxContext> tmpCtx(new gfxContext(wsurf));
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
tmpCtx->SetSource(this);
|
||||
tmpCtx->Paint();
|
||||
|
||||
gfxWindowsSurface *raw = (gfxWindowsSurface*) (wsurf.get());
|
||||
NS_ADDREF(raw);
|
||||
return raw;
|
||||
}
|
||||
|
||||
static char*
|
||||
GetACPString(const nsAString& aStr)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user