gfx/cairo/gdi-RGB24-ARGB32.patch

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/gdi-RGB24-ARGB32.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,141 @@
     1.4 +changeset:   106848:28db6dbdd9ea
     1.5 +tag:         gdi-patch
     1.6 +tag:         qbase
     1.7 +tag:         qtip
     1.8 +tag:         tip
     1.9 +user:        Jeff Muizelaar <jmuizelaar@mozilla.com>
    1.10 +date:        Wed Sep 12 22:52:06 2012 -0400
    1.11 +summary:     Bug 788794. Use BitBlt to do SOURCE and OVER from RGB24 to ARGB32. r=nical
    1.12 +
    1.13 +diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
    1.14 +--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
    1.15 ++++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
    1.16 +@@ -884,16 +884,28 @@ static cairo_int_status_t
    1.17 + 		      src_x, src_y,
    1.18 + 		      src_w, src_h,
    1.19 + 		      blend_function))
    1.20 + 	return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
    1.21 + 
    1.22 +     return CAIRO_STATUS_SUCCESS;
    1.23 + }
    1.24 + 
    1.25 ++/* makes the alpha channel in a RGB24 surface 0xff */
    1.26 ++static void
    1.27 ++make_opaque (cairo_image_surface_t *image, cairo_rectangle_int_t src_r)
    1.28 ++{
    1.29 ++    int x; int y;
    1.30 ++    for (y = src_r.y; y < src_r.height; y++) {
    1.31 ++        for (x = src_r.x; x < src_r.width; x++) {
    1.32 ++            image->data[y * image->stride + x*4 + 3] = 0xff;
    1.33 ++        }
    1.34 ++    }
    1.35 ++}
    1.36 ++
    1.37 + static cairo_int_status_t
    1.38 + _cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
    1.39 + 				      cairo_image_surface_t *src_image,
    1.40 + 				      cairo_win32_surface_t *dst,
    1.41 + 				      cairo_rectangle_int_t src_extents,
    1.42 + 				      cairo_rectangle_int_t src_r,
    1.43 + 				      cairo_rectangle_int_t dst_r,
    1.44 + 				      int alpha,
    1.45 +@@ -935,16 +947,24 @@ static cairo_int_status_t
    1.46 + 				src_r.width, - (int) src_r.height,
    1.47 + 				src_image->data,
    1.48 + 				&bi,
    1.49 + 				DIB_RGB_COLORS,
    1.50 + 				SRCCOPY))
    1.51 + 		return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
    1.52 + 	}
    1.53 +     } else if (!needs_alpha) {
    1.54 ++	if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32) {
    1.55 ++	    /* Because we store RGB24 & ARGB32 in the same way GDI has no way
    1.56 ++	     * to ignore the alpha channel from a RGB24 source. Therefore, we set
    1.57 ++	     * the alpha channel in our RGB24 source to opaque so that we can treat
    1.58 ++	     * it like ARGB32. */
    1.59 ++	    GdiFlush();
    1.60 ++	    make_opaque(src->image, src_r);
    1.61 ++	}
    1.62 + 	/* BitBlt or StretchBlt? */
    1.63 + 	if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
    1.64 +             if (!BitBlt (dst->dc,
    1.65 + 			 dst_r.x, dst_r.y,
    1.66 + 			 dst_r.width, dst_r.height,
    1.67 + 			 src->dc,
    1.68 + 			 src_r.x, src_r.y,
    1.69 + 			 SRCCOPY))
    1.70 +@@ -1184,28 +1204,36 @@ static cairo_int_status_t
    1.71 + 	}
    1.72 +     } else {
    1.73 + 	needs_repeat = TRUE;
    1.74 +     }
    1.75 + 
    1.76 +     /*
    1.77 +      * Operations that we can do:
    1.78 +      *
    1.79 ++     * AlphaBlend uses the following formula for alpha when not use the per-pixel alpha (AlphaFormat = 0)
    1.80 ++     *   Dst.Alpha = Src.Alpha * (SCA/255.0) + Dst.Alpha * (1.0 - (SCA/255.0))
    1.81 ++     * This turns into Dst.Alpha = Src.Alpha when SCA = 255.
    1.82 ++     * (http://msdn.microsoft.com/en-us/library/aa921335.aspx)
    1.83 ++     *
    1.84 +      *  RGB OVER  RGB -> BitBlt (same as SOURCE)
    1.85 +-     *  RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
    1.86 ++     *  RGB OVER ARGB -> Partially supported, We convert this operation into a ARGB SOURCE ARGB
    1.87 ++     *                   by setting the alpha values of the source to 255.
    1.88 +      * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
    1.89 +      * ARGB OVER  RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
    1.90 +      * 
    1.91 +      *  RGB OVER  RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
    1.92 +-     *  RGB OVER ARGB + mask -> UNSUPPORTED
    1.93 ++     *  RGB OVER ARGB + mask -> Partially supported, We convert this operation into a ARGB OVER ARGB + mask
    1.94 ++     *                          by setting the alpha values of the source to 255.
    1.95 +      * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
    1.96 +      * ARGB OVER  RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
    1.97 +      * 
    1.98 +      *  RGB SOURCE  RGB -> BitBlt
    1.99 +-     *  RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
   1.100 ++     *  RGB SOURCE ARGB -> Partially supported, We convert this operation into a ARGB SOURCE ARGB
   1.101 ++     *                     by setting the alpha values of the source to 255.
   1.102 +      * ARGB SOURCE ARGB -> BitBlt
   1.103 +      * ARGB SOURCE  RGB -> BitBlt
   1.104 +      * 
   1.105 +      *  RGB SOURCE  RGB + mask -> unsupported
   1.106 +      *  RGB SOURCE ARGB + mask -> unsupported
   1.107 +      * ARGB SOURCE ARGB + mask -> unsupported
   1.108 +      * ARGB SOURCE  RGB + mask -> unsupported
   1.109 +      */
   1.110 +@@ -1222,22 +1250,32 @@ static cairo_int_status_t
   1.111 + 		needs_alpha = FALSE;
   1.112 + 	    } else {
   1.113 + 		needs_alpha = TRUE;
   1.114 + 	    }
   1.115 + 	} else if (src_format == CAIRO_FORMAT_ARGB32 &&
   1.116 + 		   dst->format == CAIRO_FORMAT_RGB24)
   1.117 + 	{
   1.118 + 	    needs_alpha = TRUE;
   1.119 ++	} else if (src_format == CAIRO_FORMAT_RGB24 &&
   1.120 ++		   dst->format == CAIRO_FORMAT_ARGB32 &&
   1.121 ++		   src->image)
   1.122 ++	{
   1.123 ++	    if (alpha == 255) {
   1.124 ++		needs_alpha = FALSE;
   1.125 ++	    } else {
   1.126 ++		needs_alpha = TRUE;
   1.127 ++	    }
   1.128 + 	} else {
   1.129 + 	    goto UNSUPPORTED;
   1.130 + 	}
   1.131 +     } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
   1.132 + 	if ((src_format == dst->format) ||
   1.133 +-	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
   1.134 ++	    (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24) ||
   1.135 ++	    (src_format == CAIRO_FORMAT_RGB24  && dst->format == CAIRO_FORMAT_ARGB32 && src->image))
   1.136 + 	{
   1.137 + 	    needs_alpha = FALSE;
   1.138 + 	} else {
   1.139 + 	    goto UNSUPPORTED;
   1.140 + 	}
   1.141 +     } else {
   1.142 + 	goto UNSUPPORTED;
   1.143 +     }
   1.144 +

mercurial