mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
buffer: add buffer_convert_cairo_surface_for_icon()
Which handles: - conversion from other pixel formats to ARGB32 - setting the logical size to the desired display size - downscaling very large images using CAIRO_FILTER_GOOD
This commit is contained in:
parent
22e50aa4e2
commit
2e9b5886ce
2 changed files with 65 additions and 0 deletions
|
|
@ -61,6 +61,18 @@ struct lab_data_buffer *buffer_adopt_cairo_surface(cairo_surface_t *surface);
|
|||
struct lab_data_buffer *buffer_create_cairo(uint32_t logical_width,
|
||||
uint32_t logical_height, float scale);
|
||||
|
||||
/*
|
||||
* Create a buffer from an image surface, for display as an icon.
|
||||
*
|
||||
* The surface is either adopted by the buffer (which takes ownership),
|
||||
* or copied and then destroyed.
|
||||
*
|
||||
* This function allows non-ARGB32 source images and converts to
|
||||
* CAIRO_FORMAT_ARGB32 if needed.
|
||||
*/
|
||||
struct lab_data_buffer *buffer_convert_cairo_surface_for_icon(
|
||||
cairo_surface_t *surface, uint32_t icon_size, float scale);
|
||||
|
||||
/*
|
||||
* Create a buffer which holds (and takes ownership of) raw pixel data
|
||||
* in pre-multiplied ARGB32 format.
|
||||
|
|
|
|||
53
src/buffer.c
53
src/buffer.c
|
|
@ -29,6 +29,7 @@
|
|||
#include <drm_fourcc.h>
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
#include "buffer.h"
|
||||
#include "common/box.h"
|
||||
#include "common/mem.h"
|
||||
|
||||
static const struct wlr_buffer_impl data_buffer_impl;
|
||||
|
|
@ -134,6 +135,58 @@ buffer_create_cairo(uint32_t logical_width, uint32_t logical_height, float scale
|
|||
return buffer;
|
||||
}
|
||||
|
||||
struct lab_data_buffer *
|
||||
buffer_convert_cairo_surface_for_icon(cairo_surface_t *surface,
|
||||
uint32_t icon_size, float scale)
|
||||
{
|
||||
assert(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
|
||||
|
||||
/*
|
||||
* Compute logical size for display and decide whether we can
|
||||
* use the image data directly (fast path). Requirements are:
|
||||
*
|
||||
* - The pixel format must be ARGB32.
|
||||
* - The image must not be so large as to need downsampling by
|
||||
* more than 2x when displayed at the target scale. wlr_scene
|
||||
* uses linear interpolation without pixel averaging, which
|
||||
* starts to skip samples if downsampling more than 2x,
|
||||
* resulting in a grainy look.
|
||||
*/
|
||||
int width = cairo_image_surface_get_width(surface);
|
||||
int height = cairo_image_surface_get_height(surface);
|
||||
struct wlr_box logical =
|
||||
box_fit_within(width, height, icon_size, icon_size);
|
||||
struct lab_data_buffer *buffer;
|
||||
|
||||
if (cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32
|
||||
&& width <= 2 * logical.width * scale
|
||||
&& height <= 2 * logical.height * scale) {
|
||||
buffer = buffer_adopt_cairo_surface(surface);
|
||||
/* set logical size for display */
|
||||
buffer->logical_width = logical.width;
|
||||
buffer->logical_height = logical.height;
|
||||
} else {
|
||||
/* convert to ARGB32 and scale for display (slow path) */
|
||||
buffer = buffer_create_cairo(logical.width,
|
||||
logical.height, scale);
|
||||
|
||||
cairo_t *cairo = buffer->cairo;
|
||||
cairo_scale(cairo, (double)logical.width / width,
|
||||
(double)logical.height / height);
|
||||
cairo_set_source_surface(cairo, surface, 0, 0);
|
||||
cairo_pattern_set_filter(cairo_get_source(cairo),
|
||||
CAIRO_FILTER_GOOD);
|
||||
cairo_paint(cairo);
|
||||
|
||||
/* ensure pixel data is updated */
|
||||
cairo_surface_flush(buffer->surface);
|
||||
/* destroy original surface */
|
||||
cairo_surface_destroy(surface);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
struct lab_data_buffer *
|
||||
buffer_create_from_data(void *pixel_data, uint32_t width, uint32_t height,
|
||||
uint32_t stride)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue