mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-common
synced 2025-12-26 22:55:35 +00:00
Remove unused cairo helper functions
This commit is contained in:
parent
bbf8b18b85
commit
f853baae92
@ -334,345 +334,6 @@ static void canvas_mask_pixman(CairoCanvas *canvas,
|
||||
pixman_image_unref(image);
|
||||
}
|
||||
|
||||
static inline void canvas_invers_32bpp(uint8_t *dest, int dest_stride, uint8_t *src, int src_stride,
|
||||
int width, uint8_t *end)
|
||||
{
|
||||
for (; src != end; src += src_stride, dest += dest_stride) {
|
||||
uint32_t *src_line = (uint32_t *)src;
|
||||
uint32_t *src_line_end = src_line + width;
|
||||
uint32_t *dest_line = (uint32_t *)dest;
|
||||
|
||||
while (src_line < src_line_end) {
|
||||
*(dest_line++) = ~*(src_line++) & 0x00ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void canvas_invers_24bpp(uint8_t *dest, int dest_stride, uint8_t *src, int src_stride,
|
||||
int width, uint8_t *end)
|
||||
{
|
||||
for (; src != end; src += src_stride, dest += dest_stride) {
|
||||
uint8_t *src_line = src;
|
||||
uint8_t *src_line_end = src_line + width * 3;
|
||||
uint8_t *dest_line = dest;
|
||||
|
||||
for (; src_line < src_line_end; ++dest_line) {
|
||||
*(dest_line++) = ~*(src_line++);
|
||||
*(dest_line++) = ~*(src_line++);
|
||||
*(dest_line++) = ~*(src_line++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void canvas_invers_16bpp(uint8_t *dest, int dest_stride, uint8_t *src, int src_stride,
|
||||
int width, uint8_t *end)
|
||||
{
|
||||
for (; src != end; src += src_stride, dest += dest_stride) {
|
||||
uint16_t *src_line = (uint16_t*)src;
|
||||
uint16_t *src_line_end = src_line + width;
|
||||
uint32_t *dest_line = (uint32_t*)dest;
|
||||
|
||||
for (; src_line < src_line_end; ++dest_line, src_line++) {
|
||||
*dest_line = ~canvas_16bpp_to_32bpp(*src_line) & 0x00ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void canvas_invers_8bpp(uint8_t *dest, int dest_stride, uint8_t *src, int src_stride,
|
||||
int width, uint8_t *end, SpicePalette *palette)
|
||||
{
|
||||
if (!palette) {
|
||||
CANVAS_ERROR("no palette");
|
||||
}
|
||||
|
||||
for (; src != end; src += src_stride, dest += dest_stride) {
|
||||
uint32_t *dest_line = (uint32_t*)dest;
|
||||
uint8_t *src_line = src;
|
||||
uint8_t *src_line_end = src_line + width;
|
||||
|
||||
while (src_line < src_line_end) {
|
||||
ASSERT(*src_line < palette->num_ents);
|
||||
*(dest_line++) = ~palette->ents[*(src_line++)] & 0x00ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void canvas_invers_4bpp_be(uint8_t* dest, int dest_stride, uint8_t* src,
|
||||
int src_stride, int width, uint8_t* end,
|
||||
SpicePalette *palette)
|
||||
{
|
||||
if (!palette) {
|
||||
CANVAS_ERROR("no palette");
|
||||
}
|
||||
|
||||
for (; src != end; src += src_stride, dest += dest_stride) {
|
||||
uint32_t *dest_line = (uint32_t *)dest;
|
||||
uint8_t *now = src;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (width >> 1); i++) {
|
||||
ASSERT((*now & 0x0f) < palette->num_ents);
|
||||
ASSERT(((*now >> 4) & 0x0f) < palette->num_ents);
|
||||
*(dest_line++) = ~palette->ents[(*now >> 4) & 0x0f] & 0x00ffffff;
|
||||
*(dest_line++) = ~palette->ents[*(now++) & 0x0f] & 0x00ffffff;
|
||||
}
|
||||
if (width & 1) {
|
||||
*(dest_line) = ~palette->ents[(*src >> 4) & 0x0f] & 0x00ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void canvas_invers_1bpp_be(uint8_t* dest, int dest_stride, uint8_t* src,
|
||||
int src_stride, int width, uint8_t* end,
|
||||
SpicePalette *palette)
|
||||
{
|
||||
uint32_t fore_color;
|
||||
uint32_t back_color;
|
||||
|
||||
if (!palette) {
|
||||
CANVAS_ERROR("no palette");
|
||||
}
|
||||
|
||||
fore_color = palette->ents[1];
|
||||
back_color = palette->ents[0];
|
||||
|
||||
for (; src != end; src += src_stride, dest += dest_stride) {
|
||||
uint32_t* dest_line = (uint32_t*)dest;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; i++) {
|
||||
if (test_bit_be(src, i)) {
|
||||
*(dest_line++) = ~fore_color & 0x00ffffff;
|
||||
} else {
|
||||
*(dest_line++) = ~back_color & 0x00ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_image_t *canvas_bitmap_to_invers_surface(CairoCanvas *canvas, SpiceBitmap* bitmap,
|
||||
SpicePalette *palette)
|
||||
{
|
||||
uint8_t* src = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data);
|
||||
int src_stride;
|
||||
uint8_t* end;
|
||||
uint8_t* dest;
|
||||
int dest_stride;
|
||||
pixman_image_t* surface;
|
||||
|
||||
src_stride = bitmap->stride;
|
||||
end = src + (bitmap->y * src_stride);
|
||||
access_test(&canvas->base, src, bitmap->y * src_stride);
|
||||
|
||||
surface = pixman_image_create_bits((bitmap->format == SPICE_BITMAP_FMT_RGBA) ?
|
||||
PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
|
||||
bitmap->x, bitmap->y, NULL, 0);
|
||||
if (surface == NULL) {
|
||||
CANVAS_ERROR("create surface failed");
|
||||
}
|
||||
dest = (uint8_t *)pixman_image_get_data(surface);
|
||||
dest_stride = pixman_image_get_stride(surface);
|
||||
|
||||
if (!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
|
||||
ASSERT(bitmap->y > 0);
|
||||
dest += dest_stride * (bitmap->y - 1);
|
||||
dest_stride = -dest_stride;
|
||||
}
|
||||
switch (bitmap->format) {
|
||||
case SPICE_BITMAP_FMT_32BIT:
|
||||
case SPICE_BITMAP_FMT_RGBA:
|
||||
canvas_invers_32bpp(dest, dest_stride, src, src_stride, bitmap->x, end);
|
||||
break;
|
||||
case SPICE_BITMAP_FMT_24BIT:
|
||||
canvas_invers_24bpp(dest, dest_stride, src, src_stride, bitmap->x, end);
|
||||
break;
|
||||
case SPICE_BITMAP_FMT_16BIT:
|
||||
canvas_invers_16bpp(dest, dest_stride, src, src_stride, bitmap->x, end);
|
||||
break;
|
||||
case SPICE_BITMAP_FMT_8BIT:
|
||||
canvas_invers_8bpp(dest, dest_stride, src, src_stride, bitmap->x, end, palette);
|
||||
break;
|
||||
case SPICE_BITMAP_FMT_4BIT_BE:
|
||||
canvas_invers_4bpp_be(dest, dest_stride, src, src_stride, bitmap->x, end, palette);
|
||||
break;
|
||||
case SPICE_BITMAP_FMT_1BIT_BE:
|
||||
canvas_invers_1bpp_be(dest, dest_stride, src, src_stride, bitmap->x, end, palette);
|
||||
break;
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
|
||||
|
||||
#ifndef CAIRO_CANVAS_CACHE
|
||||
static SpicePalette *canvas_get_palette(CairoCanvas *canvas, SpiceBitmap *bitmap)
|
||||
{
|
||||
SpicePalette *local_palette;
|
||||
SpicePalette *palette;
|
||||
int size;
|
||||
|
||||
if (!bitmap->palette) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
palette = (SpicePalette *)SPICE_GET_ADDRESS(bitmap->palette);
|
||||
if (canvas->base.color_shift != 5) {
|
||||
return palette;
|
||||
}
|
||||
|
||||
size = sizeof(SpicePalette) + (palette->num_ents << 2);
|
||||
local_palette = malloc(size);
|
||||
memcpy(local_palette, palette, size);
|
||||
canvas_localize_palette(&canvas->base, palette);
|
||||
|
||||
return local_palette;
|
||||
}
|
||||
|
||||
static void free_palette(SpiceBitmap *bitmap, SpicePalette *palette)
|
||||
{
|
||||
if (!palette || palette == SPICE_GET_ADDRESS(bitmap->palette)) {
|
||||
return;
|
||||
}
|
||||
free(palette);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static pixman_image_t *canvas_get_invers_image(CairoCanvas *canvas, SPICE_ADDRESS addr)
|
||||
{
|
||||
SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
|
||||
pixman_image_t *surface;
|
||||
pixman_image_t *invers = NULL;
|
||||
|
||||
access_test(&canvas->base, descriptor, sizeof(SpiceImageDescriptor));
|
||||
|
||||
int cache_me = descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME;
|
||||
|
||||
switch (descriptor->type) {
|
||||
case SPICE_IMAGE_TYPE_QUIC: {
|
||||
SpiceQUICImage *image = (SpiceQUICImage *)descriptor;
|
||||
access_test(&canvas->base, descriptor, sizeof(SpiceQUICImage));
|
||||
if (cache_me) {
|
||||
surface = canvas_get_quic(&canvas->base, image, 0);
|
||||
} else {
|
||||
return canvas_get_quic(&canvas->base, image, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef CAIRO_CANVAS_NO_CHUNKS
|
||||
case SPICE_IMAGE_TYPE_LZ_PLT: {
|
||||
access_test(&canvas->base, descriptor, sizeof(SpiceLZPLTImage));
|
||||
LZImage *image = (LZImage *)descriptor;
|
||||
if (cache_me) {
|
||||
surface = canvas_get_lz(&canvas->base, image, 0);
|
||||
} else {
|
||||
return canvas_get_lz(&canvas->base, image, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPICE_IMAGE_TYPE_LZ_RGB: {
|
||||
access_test(&canvas->base, descriptor, sizeof(SpiceLZRGBImage));
|
||||
LZImage *image = (LZImage *)descriptor;
|
||||
if (cache_me) {
|
||||
surface = canvas_get_lz(&canvas->base, image, 0);
|
||||
} else {
|
||||
return canvas_get_lz(&canvas->base, image, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_GLZ
|
||||
case SPICE_IMAGE_TYPE_GLZ_RGB: {
|
||||
access_test(&canvas->base, descriptor, sizeof(SpiceLZRGBImage));
|
||||
LZImage *image = (LZImage *)descriptor;
|
||||
surface = canvas_get_glz(&canvas->base, image);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SPICE_IMAGE_TYPE_FROM_CACHE:
|
||||
surface = canvas->base.bits_cache->ops->get(canvas->base.bits_cache, descriptor->id);
|
||||
break;
|
||||
case SPICE_IMAGE_TYPE_BITMAP: {
|
||||
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor;
|
||||
access_test(&canvas->base, descriptor, sizeof(SpiceBitmapImage));
|
||||
if (cache_me) {
|
||||
surface = canvas_get_bits(&canvas->base, &bitmap->bitmap);
|
||||
} else {
|
||||
#ifdef CAIRO_CANVAS_CACHE
|
||||
return canvas_bitmap_to_invers_surface(canvas, &bitmap->bitmap,
|
||||
canvas_get_palett(&canvas->base,
|
||||
bitmap->bitmap.palette,
|
||||
bitmap->bitmap.flags));
|
||||
#else
|
||||
SpicePalette *palette = canvas_get_palette(canvas, &bitmap->bitmap);
|
||||
surface = canvas_bitmap_to_invers_surface(canvas, &bitmap->bitmap, palette);
|
||||
free_palette(&bitmap->bitmap, palette);
|
||||
return surface;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CANVAS_ERROR("invalid image type");
|
||||
}
|
||||
|
||||
if (cache_me) {
|
||||
canvas->base.bits_cache->ops->put(canvas->base.bits_cache, descriptor->id, surface);
|
||||
}
|
||||
|
||||
invers = canvas_handle_inverse_user_data(surface);
|
||||
pixman_image_unref(surface);
|
||||
return invers;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static pixman_image_t *canvas_get_invers(CairoCanvas *canvas, SpiceBitmap *bitmap)
|
||||
{
|
||||
SpicePalette *palette;
|
||||
|
||||
if (!bitmap->palette) {
|
||||
return canvas_bitmap_to_invers_surface(canvas, bitmap, NULL);
|
||||
}
|
||||
palette = (SpicePalette *)SPICE_GET_ADDRESS(bitmap->palette);
|
||||
if (canvas->color_shift == 5) {
|
||||
int size = sizeof(SpicePalette) + (palette->num_ents << 2);
|
||||
SpicePalette *local_palette = malloc(size);
|
||||
pixman_image_t* surface;
|
||||
|
||||
memcpy(local_palette, palette, size);
|
||||
canvas_localize_palette(canvas, palette);
|
||||
surface = canvas_bitmap_to_invers_surface(canvas, bitmap, local_palette);
|
||||
free(local_palette);
|
||||
return surface;
|
||||
} else {
|
||||
return canvas_bitmap_to_invers_surface(canvas, bitmap, palette);
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_image_t *canvas_get_invers_image(CairoCanvas *canvas, SPICE_ADDRESS addr)
|
||||
{
|
||||
SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
|
||||
|
||||
access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
|
||||
|
||||
switch (descriptor->type) {
|
||||
case SPICE_IMAGE_TYPE_QUIC: {
|
||||
SpiceQUICImage *image = (SpiceQUICImage *)descriptor;
|
||||
access_test(canvas, descriptor, sizeof(SpiceQUICImage));
|
||||
return canvas_get_quic(canvas, image, 1);
|
||||
}
|
||||
case SPICE_IMAGE_TYPE_BITMAP: {
|
||||
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor;
|
||||
access_test(canvas, descriptor, sizeof(SpiceBitmapImage));
|
||||
return canvas_get_invers(canvas, &bitmap->bitmap);
|
||||
}
|
||||
default:
|
||||
CANVAS_ERROR("invalid image type");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static pixman_image_t* canvas_surface_from_self(CairoCanvas *canvas,
|
||||
int x, int y,
|
||||
@ -741,122 +402,6 @@ static pixman_image_t *canvas_get_pixman_brush(CairoCanvas *canvas,
|
||||
}
|
||||
|
||||
|
||||
static cairo_pattern_t *canvas_get_brush(CairoCanvas *canvas, SpiceBrush *brush, uint32_t invers)
|
||||
{
|
||||
switch (brush->type) {
|
||||
case SPICE_BRUSH_TYPE_SOLID: {
|
||||
uint32_t color = (invers) ? ~brush->u.color : brush->u.color;
|
||||
double r, g, b;
|
||||
|
||||
b = (double)(color & canvas->base.color_mask) / canvas->base.color_mask;
|
||||
color >>= canvas->base.color_shift;
|
||||
g = (double)(color & canvas->base.color_mask) / canvas->base.color_mask;
|
||||
color >>= canvas->base.color_shift;
|
||||
r = (double)(color & canvas->base.color_mask) / canvas->base.color_mask;
|
||||
return cairo_pattern_create_rgb(r, g, b);
|
||||
}
|
||||
case SPICE_BRUSH_TYPE_PATTERN: {
|
||||
pixman_image_t* surface;
|
||||
cairo_surface_t* cairo_surface;
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
|
||||
if (invers) {
|
||||
surface = canvas_get_invers_image(canvas, brush->u.pattern.pat);
|
||||
} else {
|
||||
surface = canvas_get_image(&canvas->base, brush->u.pattern.pat);
|
||||
}
|
||||
cairo_surface = surface_from_pixman_image (surface);
|
||||
pixman_image_unref (surface);
|
||||
pattern = cairo_pattern_create_for_surface(cairo_surface);
|
||||
if (cairo_pattern_status(pattern) != CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_destroy(cairo_surface);
|
||||
CANVAS_ERROR("create pattern failed, %s",
|
||||
cairo_status_to_string(cairo_pattern_status(pattern)));
|
||||
}
|
||||
cairo_surface_destroy(cairo_surface);
|
||||
cairo_matrix_init_translate(&matrix, -brush->u.pattern.pos.x, -brush->u.pattern.pos.y);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
||||
return pattern;
|
||||
}
|
||||
case SPICE_BRUSH_TYPE_NONE:
|
||||
return NULL;
|
||||
default:
|
||||
CANVAS_ERROR("invalid brush type");
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*DrawMethod)(void *);
|
||||
|
||||
static inline void __canvas_draw_invers(CairoCanvas *canvas, DrawMethod draw_method, void *data)
|
||||
{
|
||||
cairo_t *cairo = canvas->cairo;
|
||||
cairo_set_source_rgb(cairo, 1, 1, 1);
|
||||
cairo_set_operator(cairo, CAIRO_OPERATOR_RASTER_XOR);
|
||||
draw_method(data);
|
||||
}
|
||||
|
||||
static inline int canvas_set_ropd_operator(cairo_t *cairo, uint16_t rop_decriptor)
|
||||
{
|
||||
cairo_operator_t cairo_op;
|
||||
|
||||
if (rop_decriptor & SPICE_ROPD_OP_PUT) {
|
||||
cairo_op = CAIRO_OPERATOR_RASTER_COPY;
|
||||
} else if (rop_decriptor & SPICE_ROPD_OP_XOR) {
|
||||
cairo_op = CAIRO_OPERATOR_RASTER_XOR;
|
||||
} else if (rop_decriptor & SPICE_ROPD_OP_OR) {
|
||||
cairo_op = CAIRO_OPERATOR_RASTER_OR;
|
||||
} else if (rop_decriptor & SPICE_ROPD_OP_AND) {
|
||||
cairo_op = CAIRO_OPERATOR_RASTER_AND;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
cairo_set_operator(cairo, cairo_op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void canvas_draw_with_pattern(CairoCanvas *canvas, cairo_pattern_t *pattern,
|
||||
uint16_t rop_decriptor,
|
||||
DrawMethod draw_method, void *data)
|
||||
{
|
||||
cairo_t *cairo = canvas->cairo;
|
||||
|
||||
if (rop_decriptor & SPICE_ROPD_OP_BLACKNESS) {
|
||||
cairo_set_source_rgb(cairo, 0, 0, 0);
|
||||
draw_method(data);
|
||||
} else if (rop_decriptor & SPICE_ROPD_OP_WHITENESS) {
|
||||
cairo_set_source_rgb(cairo, 1, 1, 1);
|
||||
draw_method(data);
|
||||
} else if (rop_decriptor & SPICE_ROPD_OP_INVERS) {
|
||||
__canvas_draw_invers(canvas, draw_method, data);
|
||||
} else {
|
||||
if (rop_decriptor & SPICE_ROPD_INVERS_DEST) {
|
||||
__canvas_draw_invers(canvas, draw_method, data);
|
||||
}
|
||||
|
||||
if (canvas_set_ropd_operator(cairo, rop_decriptor)) {
|
||||
ASSERT(pattern);
|
||||
cairo_set_source(cairo, pattern);
|
||||
draw_method(data);
|
||||
}
|
||||
|
||||
if (rop_decriptor & SPICE_ROPD_INVERS_RES) {
|
||||
__canvas_draw_invers(canvas, draw_method, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void canvas_draw(CairoCanvas *canvas, SpiceBrush *brush, uint16_t rop_decriptor,
|
||||
DrawMethod draw_method, void *data)
|
||||
{
|
||||
cairo_pattern_t *pattern = canvas_get_brush(canvas, brush, rop_decriptor & SPICE_ROPD_INVERS_BRUSH);
|
||||
canvas_draw_with_pattern(canvas, pattern, rop_decriptor, draw_method, data);
|
||||
if (pattern) {
|
||||
cairo_pattern_destroy(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_region(CairoCanvas *canvas,
|
||||
pixman_region32_t *dest_region,
|
||||
int dx, int dy)
|
||||
|
||||
@ -264,45 +264,6 @@ pixman_image_from_surface (cairo_surface_t *surface)
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static cairo_format_t
|
||||
cairo_format_from_depth (int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 1:
|
||||
return CAIRO_FORMAT_A1;
|
||||
case 8:
|
||||
return CAIRO_FORMAT_A8;
|
||||
case 24:
|
||||
return CAIRO_FORMAT_RGB24;
|
||||
case 32:
|
||||
default:
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
surface_from_pixman_image (pixman_image_t *image)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
int depth;
|
||||
|
||||
depth = pixman_image_get_depth (image);
|
||||
|
||||
surface = cairo_image_surface_create_for_data ((uint8_t *)pixman_image_get_data (image),
|
||||
cairo_format_from_depth (depth),
|
||||
pixman_image_get_width (image),
|
||||
pixman_image_get_height (image),
|
||||
pixman_image_get_stride (image));
|
||||
|
||||
|
||||
if (cairo_surface_set_user_data (surface, &pixman_data_type,
|
||||
image, (cairo_destroy_func_t) pixman_image_unref) == CAIRO_STATUS_SUCCESS)
|
||||
pixman_image_ref (image);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline void canvas_localize_palette(CanvasBase *canvas, SpicePalette *palette)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user