tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

26-quartz-surface-mask.patch (3953B)


      1 # HG changeset patch
      2 # User Jonathan Kew <jkew@mozilla.com>
      3 # Date 1717237382 -3600
      4 #      Sat Jun 01 11:23:02 2024 +0100
      5 # Node ID d5f7b9fd904e04406c56899c5cac9248b122ea35
      6 # Parent  c8d3e447c892474e061c9ffd22ec1823f06ecffa
      7 Bug 1900028 - Handle CAIRO_FORMAT_A8 in _cairo_surface_to_cgimage for masking operations.
      8 
      9 Differential Revision: https://phabricator.services.mozilla.com/D212354
     10 
     11 diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
     12 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
     13 +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
     14 @@ -684,6 +684,55 @@ CairoQuartzCreateGradientFunction (const
     15 			     &gradient_callbacks);
     16 }
     17 
     18 +static CGImageRef
     19 +CairoQuartzCreateCGImageMask (cairo_format_t format,
     20 +			      unsigned int width,
     21 +			      unsigned int height,
     22 +			      unsigned int stride,
     23 +			      void *data,
     24 +			      cairo_bool_t interpolate,
     25 +			      CGDataProviderReleaseDataCallback releaseCallback,
     26 +			      void *releaseInfo)
     27 +{
     28 +    CGImageRef image = NULL;
     29 +    CGDataProviderRef dataProvider = NULL;
     30 +    int bitsPerComponent = 8, bitsPerPixel = 8;
     31 +
     32 +    if (format != CAIRO_FORMAT_A8)
     33 +	return NULL;
     34 +
     35 +    dataProvider = CGDataProviderCreateWithData (releaseInfo,
     36 +						 data,
     37 +						 height * stride,
     38 +						 releaseCallback);
     39 +
     40 +    if (unlikely (!dataProvider)) {
     41 +	// manually release
     42 +	if (releaseCallback)
     43 +	    releaseCallback (releaseInfo, data, height * stride);
     44 +	goto FINISH;
     45 +    }
     46 +
     47 +    cairo_quartz_float_t decode[] = {1.0, 0.0};
     48 +    image = CGImageMaskCreate (width, height,
     49 +			       bitsPerComponent,
     50 +			       bitsPerPixel,
     51 +			       stride,
     52 +			       dataProvider,
     53 +			       decode,
     54 +			       interpolate);
     55 +
     56 +FINISH:
     57 +    CGDataProviderRelease (dataProvider);
     58 +    return image;
     59 +}
     60 +
     61 +static void
     62 +DataProviderReleaseCallback (void *info, const void *data, size_t size)
     63 +{
     64 +    free (info);
     65 +}
     66 +
     67 static cairo_status_t
     68 _cairo_surface_to_cgimage (cairo_surface_t       *source,
     69 			   cairo_rectangle_int_t *extents,
     70 @@ -742,13 +791,48 @@ static cairo_status_t
     71 						      &image_extra);
     72 	if (unlikely (status))
     73 	    return status;
     74 -	image_surface =
     75 -	    (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base);
     76 -	status = image_surface->base.status;
     77 -	if (status)
     78 +
     79 +	if (surface->format == CAIRO_FORMAT_A8) {
     80 +	    /* cairo_quartz_image_surface_create doesn't handle CAIRO_FORMAT_A8,
     81 +	     * so we create a CGImage manually here for masking operations.
     82 +	     */
     83 +	    void* image_data = _cairo_malloc_ab (surface->height, surface->stride);
     84 +	    if (unlikely (!image_data))
     85 +	    {
     86 +		_cairo_surface_release_source_image (source, surface, image_extra);
     87 +		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     88 +	    }
     89 +
     90 +	    /* The last row of data may have less than stride bytes so make sure we
     91 +	     * only copy the minimum amount required from that row.
     92 +	     */
     93 +	    memcpy (image_data, surface->data,
     94 +		    (surface->height - 1) * surface->stride +
     95 +		    cairo_format_stride_for_width (surface->format,
     96 +						   surface->width));
     97 +	    *image_out = CairoQuartzCreateCGImageMask (surface->format,
     98 +						       surface->width,
     99 +						       surface->height,
    100 +						       surface->stride,
    101 +						       image_data,
    102 +						       TRUE,
    103 +						       DataProviderReleaseCallback,
    104 +						       image_data);
    105 +	    /* TODO: differentiate memory error and unsupported surface type */
    106 +	    if (unlikely (*image_out == NULL))
    107 +		status = CAIRO_INT_STATUS_UNSUPPORTED;
    108 +
    109 	    _cairo_surface_release_source_image (source, surface, image_extra);
    110 -	else
    111 -	    acquired = TRUE;
    112 +	    return status;
    113 +	} else {
    114 +	    image_surface =
    115 +		(cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base);
    116 +	    status = image_surface->base.status;
    117 +	    if (status)
    118 +		_cairo_surface_release_source_image (source, surface, image_extra);
    119 +	    else
    120 +		acquired = TRUE;
    121 +	}
    122     }
    123 
    124     *image_out = NULL;