image: only cache analyzed transparency/color for snapshot surfaces

https://lists.cairographics.org/archives/cairo/2016-June/027429.html
This commit is contained in:
Adrian Johnson 2016-06-19 14:08:55 +09:30
parent 113ba5f3fa
commit eb808aa625

View file

@ -52,6 +52,7 @@
#include "cairo-recording-surface-private.h"
#include "cairo-region-private.h"
#include "cairo-scaled-font-private.h"
#include "cairo-surface-snapshot-inline.h"
#include "cairo-surface-snapshot-private.h"
#include "cairo-surface-subsurface-private.h"
@ -1153,79 +1154,87 @@ cleanup:
return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
}
cairo_image_transparency_t
_cairo_image_analyze_transparency (cairo_image_surface_t *image)
static cairo_image_transparency_t
_cairo_image_compute_transparency (cairo_image_surface_t *image)
{
int x, y;
if (image->transparency != CAIRO_IMAGE_UNKNOWN)
return image->transparency;
cairo_image_transparency_t transparency;
if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
return CAIRO_IMAGE_IS_OPAQUE;
if (image->base.is_clear)
return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
return CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
if (image->format == CAIRO_FORMAT_A1) {
return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
return CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
} else if (image->format == CAIRO_FORMAT_A8) {
for (y = 0; y < image->height; y++) {
uint8_t *alpha = (uint8_t *) (image->data + y * image->stride);
for (x = 0; x < image->width; x++, alpha++) {
if (*alpha > 0 && *alpha < 255)
return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
return CAIRO_IMAGE_HAS_ALPHA;
}
}
return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
return CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
} else {
return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
return CAIRO_IMAGE_HAS_ALPHA;
}
}
if (image->format == CAIRO_FORMAT_RGB16_565) {
image->transparency = CAIRO_IMAGE_IS_OPAQUE;
return CAIRO_IMAGE_IS_OPAQUE;
}
if (image->format != CAIRO_FORMAT_ARGB32)
return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
return CAIRO_IMAGE_HAS_ALPHA;
image->transparency = CAIRO_IMAGE_IS_OPAQUE;
transparency = CAIRO_IMAGE_IS_OPAQUE;
for (y = 0; y < image->height; y++) {
uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
for (x = 0; x < image->width; x++, pixel++) {
int a = (*pixel & 0xff000000) >> 24;
if (a > 0 && a < 255) {
return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
return CAIRO_IMAGE_HAS_ALPHA;
} else if (a == 0) {
image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
}
}
}
return image->transparency;
return transparency;
}
cairo_image_color_t
_cairo_image_analyze_color (cairo_image_surface_t *image)
cairo_image_transparency_t
_cairo_image_analyze_transparency (cairo_image_surface_t *image)
{
if (_cairo_surface_is_snapshot (&image->base)) {
if (image->transparency == CAIRO_IMAGE_UNKNOWN)
image->transparency = _cairo_image_compute_transparency (image);
return image->transparency;
}
return _cairo_image_compute_transparency (image);
}
static cairo_image_color_t
_cairo_image_compute_color (cairo_image_surface_t *image)
{
int x, y;
if (image->color != CAIRO_IMAGE_UNKNOWN_COLOR)
return image->color;
cairo_image_color_t color;
if (image->format == CAIRO_FORMAT_A1)
return image->color = CAIRO_IMAGE_IS_MONOCHROME;
return CAIRO_IMAGE_IS_MONOCHROME;
if (image->format == CAIRO_FORMAT_A8)
return image->color = CAIRO_IMAGE_IS_GRAYSCALE;
return CAIRO_IMAGE_IS_GRAYSCALE;
if (image->format == CAIRO_FORMAT_ARGB32) {
image->color = CAIRO_IMAGE_IS_MONOCHROME;
color = CAIRO_IMAGE_IS_MONOCHROME;
for (y = 0; y < image->height; y++) {
uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
@ -1242,16 +1251,16 @@ _cairo_image_analyze_color (cairo_image_surface_t *image)
b = (b * 255 + a / 2) / a;
}
if (!(r == g && g == b))
return image->color = CAIRO_IMAGE_IS_COLOR;
return CAIRO_IMAGE_IS_COLOR;
else if (r > 0 && r < 255)
image->color = CAIRO_IMAGE_IS_GRAYSCALE;
color = CAIRO_IMAGE_IS_GRAYSCALE;
}
}
return image->color;
return color;
}
if (image->format == CAIRO_FORMAT_RGB24) {
image->color = CAIRO_IMAGE_IS_MONOCHROME;
color = CAIRO_IMAGE_IS_MONOCHROME;
for (y = 0; y < image->height; y++) {
uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
@ -1260,15 +1269,28 @@ _cairo_image_analyze_color (cairo_image_surface_t *image)
int g = (*pixel & 0x0000ff00) >> 8;
int b = (*pixel & 0x000000ff);
if (!(r == g && g == b))
return image->color = CAIRO_IMAGE_IS_COLOR;
return CAIRO_IMAGE_IS_COLOR;
else if (r > 0 && r < 255)
image->color = CAIRO_IMAGE_IS_GRAYSCALE;
color = CAIRO_IMAGE_IS_GRAYSCALE;
}
}
return color;
}
return CAIRO_IMAGE_IS_COLOR;
}
cairo_image_color_t
_cairo_image_analyze_color (cairo_image_surface_t *image)
{
if (_cairo_surface_is_snapshot (&image->base)) {
if (image->color == CAIRO_IMAGE_UNKNOWN_COLOR)
image->color = _cairo_image_compute_color (image);
return image->color;
}
return image->color = CAIRO_IMAGE_IS_COLOR;
return _cairo_image_compute_color (image);
}
cairo_image_surface_t *