mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-08 17:08:35 +02:00
pixel-buffer: add the concept of a device scale
The device scale is a scale transformation that is applied to the pixel buffer contents, but is transparent to the user of the buffer (all pixel values are in logical pixels, not device pixels). The concept is modeled after the cairo API, and it is useful to implement HiDPI monitor support. https://bugs.freedesktop.org/show_bug.cgi?id=84482
This commit is contained in:
parent
85fac71e08
commit
d70c1dc9ee
2 changed files with 221 additions and 136 deletions
|
|
@ -43,11 +43,13 @@ struct _ply_pixel_buffer
|
|||
{
|
||||
uint32_t *bytes;
|
||||
|
||||
ply_rectangle_t area;
|
||||
ply_list_t *clip_areas;
|
||||
ply_rectangle_t area; /* in device pixels */
|
||||
ply_rectangle_t logical_area; /* in logical pixels */
|
||||
ply_list_t *clip_areas; /* in device pixels */
|
||||
|
||||
ply_region_t *updated_areas;
|
||||
ply_region_t *updated_areas; /* in device pixels */
|
||||
uint32_t is_opaque : 1;
|
||||
int device_scale;
|
||||
};
|
||||
|
||||
static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
||||
|
|
@ -168,6 +170,34 @@ ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
|||
buffer->bytes[y * buffer->area.width + x] = pixel_value;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_rectangle_upscale (ply_rectangle_t *area,
|
||||
int scale)
|
||||
{
|
||||
area->x *= scale;
|
||||
area->y *= scale;
|
||||
area->width *= scale;
|
||||
area->height *= scale;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_rectangle_downscale (ply_rectangle_t *area,
|
||||
int scale)
|
||||
{
|
||||
area->x /= scale;
|
||||
area->y /= scale;
|
||||
area->width /= scale;
|
||||
area->height /= scale;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_pixel_buffer_adjust_area_for_device_scale (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *area)
|
||||
{
|
||||
ply_rectangle_upscale (area, buffer->device_scale);
|
||||
}
|
||||
|
||||
/* this function will also convert logical pixels to device pixels */
|
||||
static void
|
||||
ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *area,
|
||||
|
|
@ -176,6 +206,7 @@ ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
|
|||
ply_list_node_t *node;
|
||||
|
||||
*cropped_area = *area;
|
||||
ply_pixel_buffer_adjust_area_for_device_scale (buffer, cropped_area);
|
||||
|
||||
node = ply_list_get_first_node (buffer->clip_areas);
|
||||
while (node != NULL) {
|
||||
|
|
@ -199,6 +230,9 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
|
|||
unsigned long row, column;
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->logical_area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
/* If we're filling the entire buffer with a fully opaque color,
|
||||
|
|
@ -216,6 +250,8 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
|
|||
pixel_value);
|
||||
}
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -227,6 +263,8 @@ ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer,
|
|||
new_clip_area = malloc (sizeof(*new_clip_area));
|
||||
|
||||
*new_clip_area = *clip_area;
|
||||
ply_pixel_buffer_adjust_area_for_device_scale (buffer, new_clip_area);
|
||||
|
||||
ply_list_append_data (buffer->clip_areas, new_clip_area);
|
||||
}
|
||||
|
||||
|
|
@ -252,6 +290,8 @@ ply_pixel_buffer_new (unsigned long width,
|
|||
buffer->bytes = (uint32_t *) calloc (height, width * sizeof(uint32_t));
|
||||
buffer->area.width = width;
|
||||
buffer->area.height = height;
|
||||
buffer->logical_area = buffer->area;
|
||||
buffer->device_scale = 1;
|
||||
|
||||
buffer->clip_areas = ply_list_new ();
|
||||
ply_pixel_buffer_push_clip_area (buffer, &buffer->area);
|
||||
|
|
@ -290,21 +330,21 @@ ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
|
|||
assert (buffer != NULL);
|
||||
assert (size != NULL);
|
||||
|
||||
*size = buffer->area;
|
||||
*size = buffer->logical_area;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
ply_pixel_buffer_get_width (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
assert (buffer != NULL);
|
||||
return buffer->area.width;
|
||||
return buffer->logical_area.width;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
ply_pixel_buffer_get_height (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
assert (buffer != NULL);
|
||||
return buffer->area.height;
|
||||
return buffer->logical_area.height;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -386,7 +426,7 @@ ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
|
|||
ply_rectangle_t cropped_area;
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
fill_area = &buffer->logical_area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
|
|
@ -457,24 +497,16 @@ ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
|
|||
double alpha)
|
||||
{
|
||||
uint32_t pixel_value;
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
red *= alpha;
|
||||
green *= alpha;
|
||||
blue *= alpha;
|
||||
|
||||
pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
|
||||
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value);
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (buffer, fill_area, pixel_value);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -483,7 +515,6 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
|
|||
uint32_t hex_color,
|
||||
double opacity)
|
||||
{
|
||||
ply_rectangle_t cropped_area;
|
||||
uint32_t pixel_value;
|
||||
double red;
|
||||
double green;
|
||||
|
|
@ -492,11 +523,6 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
|
|||
|
||||
assert (buffer != NULL);
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
/* if they only gave an rgb hex number, assume an alpha of 0xff
|
||||
*/
|
||||
if ((hex_color & 0xff000000) == 0)
|
||||
|
|
@ -515,9 +541,7 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
|
|||
|
||||
pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
|
||||
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value);
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (buffer, fill_area, pixel_value);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -529,48 +553,120 @@ ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer,
|
|||
hex_color, 1.0);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ply_pixels_interpolate (uint32_t *bytes,
|
||||
int width,
|
||||
int height,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
int ix;
|
||||
int iy;
|
||||
int i;
|
||||
int offset_x;
|
||||
int offset_y;
|
||||
uint32_t pixels[2][2];
|
||||
uint32_t reply = 0;
|
||||
|
||||
for (offset_y = 0; offset_y < 2; offset_y++) {
|
||||
for (offset_x = 0; offset_x < 2; offset_x++) {
|
||||
ix = x + offset_x;
|
||||
iy = y + offset_y;
|
||||
|
||||
if (ix < 0 || ix >= width || iy < 0 || iy >= height)
|
||||
pixels[offset_y][offset_x] = 0x00000000;
|
||||
else
|
||||
pixels[offset_y][offset_x] = bytes[ix + iy * width];
|
||||
}
|
||||
}
|
||||
if (!pixels[0][0] && !pixels[0][1] && !pixels[1][0] && !pixels[1][1]) return 0;
|
||||
|
||||
ix = x;
|
||||
iy = y;
|
||||
x -= ix;
|
||||
y -= iy;
|
||||
for (i = 0; i < 4; i++) {
|
||||
uint32_t value = 0;
|
||||
uint32_t mask = 0xFF << (i * 8);
|
||||
value += ((pixels[0][0]) & mask) * (1 - x) * (1 - y);
|
||||
value += ((pixels[0][1]) & mask) * x * (1 - y);
|
||||
value += ((pixels[1][0]) & mask) * (1 - x) * y;
|
||||
value += ((pixels[1][1]) & mask) * x * y;
|
||||
reply |= value & mask;
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
uint32_t *data,
|
||||
double opacity)
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
uint32_t *data,
|
||||
double opacity,
|
||||
int scale)
|
||||
{
|
||||
unsigned long row, column;
|
||||
uint8_t opacity_as_byte;
|
||||
ply_rectangle_t logical_fill_area;
|
||||
ply_rectangle_t cropped_area;
|
||||
unsigned long x;
|
||||
unsigned long y;
|
||||
double scale_factor;
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
if (fill_area == NULL) {
|
||||
fill_area = &buffer->logical_area;
|
||||
logical_fill_area = buffer->logical_area;
|
||||
} else {
|
||||
logical_fill_area = *fill_area;
|
||||
ply_rectangle_downscale (&logical_fill_area, scale);
|
||||
}
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, &logical_fill_area, &cropped_area);
|
||||
|
||||
if (clip_area)
|
||||
ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
|
||||
if (clip_area) {
|
||||
ply_rectangle_t device_clip_area;
|
||||
|
||||
device_clip_area = *clip_area;
|
||||
ply_rectangle_downscale (&device_clip_area, scale);
|
||||
ply_pixel_buffer_adjust_area_for_device_scale (buffer, &device_clip_area);
|
||||
ply_rectangle_intersect (&cropped_area, &device_clip_area, &cropped_area);
|
||||
}
|
||||
|
||||
if (cropped_area.width == 0 || cropped_area.height == 0)
|
||||
return;
|
||||
|
||||
x = cropped_area.x - fill_area->x;
|
||||
y = cropped_area.y - fill_area->y;
|
||||
opacity_as_byte = (uint8_t) (opacity * 255.0);
|
||||
scale_factor = (double)scale / buffer->device_scale;
|
||||
x = cropped_area.x;
|
||||
y = cropped_area.y;
|
||||
|
||||
/* column, row are the point we want to write into, in
|
||||
pixel_buffer coordinate space (device pixels)
|
||||
|
||||
scale_factor * (column - fill_area->x), scale_factor * (row - fill_area->y)
|
||||
is the point we want to source from, in the data coordinate
|
||||
space */
|
||||
for (row = y; row < y + cropped_area.height; row++) {
|
||||
for (column = x; column < x + cropped_area.width; column++) {
|
||||
uint32_t pixel_value;
|
||||
|
||||
pixel_value = data[fill_area->width * row + column];
|
||||
if (buffer->device_scale == scale)
|
||||
pixel_value = data[fill_area->width * (row - fill_area->y) +
|
||||
column - fill_area->x];
|
||||
else
|
||||
pixel_value = ply_pixels_interpolate (data,
|
||||
fill_area->width,
|
||||
fill_area->height,
|
||||
scale_factor * column - fill_area->x,
|
||||
scale_factor * row - fill_area->y);
|
||||
if ((pixel_value >> 24) == 0x00)
|
||||
continue;
|
||||
|
||||
pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte);
|
||||
ply_pixel_buffer_blend_value_at_pixel (buffer,
|
||||
cropped_area.x + (column - x),
|
||||
cropped_area.y + (row - y),
|
||||
column, row,
|
||||
pixel_value);
|
||||
}
|
||||
}
|
||||
|
|
@ -578,16 +674,31 @@ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t
|
|||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
uint32_t *data,
|
||||
double opacity)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
|
||||
fill_area,
|
||||
clip_area,
|
||||
data,
|
||||
opacity,
|
||||
1);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t *data,
|
||||
double opacity)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
|
||||
fill_area,
|
||||
NULL,
|
||||
data, opacity);
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
|
||||
fill_area,
|
||||
NULL,
|
||||
data, opacity, 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -595,10 +706,10 @@ ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer,
|
|||
ply_rectangle_t *fill_area,
|
||||
uint32_t *data)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
|
||||
fill_area,
|
||||
NULL,
|
||||
data, 1.0);
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
|
||||
fill_area,
|
||||
NULL,
|
||||
data, 1.0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -607,10 +718,10 @@ ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer,
|
|||
ply_rectangle_t *clip_area,
|
||||
uint32_t *data)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
|
||||
fill_area,
|
||||
clip_area,
|
||||
data, 1.0);
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
|
||||
fill_area,
|
||||
clip_area,
|
||||
data, 1.0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -628,35 +739,6 @@ ply_pixel_buffer_copy_area (ply_pixel_buffer_t *canvas,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ply_pixel_buffer_blend_area (ply_pixel_buffer_t *canvas,
|
||||
ply_pixel_buffer_t *source,
|
||||
int x, int y,
|
||||
ply_rectangle_t *cropped_area,
|
||||
double opacity)
|
||||
{
|
||||
unsigned long row, column;
|
||||
uint8_t opacity_as_byte = (uint8_t) (opacity * 255.0);
|
||||
|
||||
for (row = y; row < y + cropped_area->height; row++) {
|
||||
for (column = x; column < x + cropped_area->width; column++) {
|
||||
uint32_t pixel_value;
|
||||
|
||||
pixel_value = source->bytes[row * source->area.width + column];
|
||||
|
||||
pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte);
|
||||
|
||||
if ((pixel_value >> 24) == 0x00)
|
||||
continue;
|
||||
|
||||
ply_pixel_buffer_blend_value_at_pixel (canvas,
|
||||
cropped_area->x + (column - x),
|
||||
cropped_area->y + (row - y),
|
||||
pixel_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canvas,
|
||||
ply_pixel_buffer_t *source,
|
||||
|
|
@ -665,36 +747,51 @@ ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canv
|
|||
ply_rectangle_t *clip_area,
|
||||
float opacity)
|
||||
{
|
||||
ply_rectangle_t cropped_area;
|
||||
ply_rectangle_t fill_area;
|
||||
unsigned long x;
|
||||
unsigned long y;
|
||||
|
||||
assert (canvas != NULL);
|
||||
assert (source != NULL);
|
||||
|
||||
cropped_area.x = x_offset;
|
||||
cropped_area.y = y_offset;
|
||||
cropped_area.width = source->area.width;
|
||||
cropped_area.height = source->area.height;
|
||||
/* Fast path to memcpy if we need no blending or scaling */
|
||||
if (opacity == 1.0 && ply_pixel_buffer_is_opaque (source) &&
|
||||
canvas->device_scale == source->device_scale) {
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (canvas, &cropped_area, &cropped_area);
|
||||
cropped_area.x = x_offset;
|
||||
cropped_area.y = y_offset;
|
||||
cropped_area.width = source->logical_area.width;
|
||||
cropped_area.height = source->logical_area.height;
|
||||
|
||||
if (clip_area)
|
||||
ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
|
||||
ply_pixel_buffer_crop_area_to_clip_area (canvas, &cropped_area, &cropped_area);
|
||||
|
||||
if (cropped_area.width == 0 || cropped_area.height == 0)
|
||||
return;
|
||||
/* clip_area is in source device pixels, which are also canvas device pixels */
|
||||
if (clip_area)
|
||||
ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
|
||||
|
||||
x = cropped_area.x - x_offset;
|
||||
y = cropped_area.y - y_offset;
|
||||
if (cropped_area.width == 0 || cropped_area.height == 0)
|
||||
return;
|
||||
|
||||
x = cropped_area.x - x_offset;
|
||||
y = cropped_area.y - y_offset;
|
||||
|
||||
if (opacity == 1.0 && ply_pixel_buffer_is_opaque (source))
|
||||
ply_pixel_buffer_copy_area (canvas, source, x, y, &cropped_area);
|
||||
else
|
||||
ply_pixel_buffer_blend_area (canvas, source, x, y, &cropped_area,
|
||||
opacity);
|
||||
|
||||
ply_region_add_rectangle (canvas->updated_areas, &cropped_area);
|
||||
ply_region_add_rectangle (canvas->updated_areas, &cropped_area);
|
||||
} else {
|
||||
fill_area.x = x_offset * source->device_scale;
|
||||
fill_area.y = y_offset * source->device_scale;
|
||||
fill_area.width = source->area.width;
|
||||
fill_area.height = source->area.height;
|
||||
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (canvas,
|
||||
&fill_area,
|
||||
clip_area,
|
||||
source->bytes,
|
||||
opacity,
|
||||
source->device_scale);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -752,52 +849,15 @@ ply_pixel_buffer_interpolate (ply_pixel_buffer_t *buffer,
|
|||
double x,
|
||||
double y)
|
||||
{
|
||||
int ix;
|
||||
int iy;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int i;
|
||||
|
||||
int offset_x;
|
||||
int offset_y;
|
||||
uint32_t pixels[2][2];
|
||||
uint32_t reply = 0;
|
||||
uint32_t *bytes;
|
||||
|
||||
width = buffer->area.width;
|
||||
height = buffer->area.height;
|
||||
|
||||
|
||||
bytes = ply_pixel_buffer_get_argb32_data (buffer);
|
||||
|
||||
for (offset_y = 0; offset_y < 2; offset_y++) {
|
||||
for (offset_x = 0; offset_x < 2; offset_x++) {
|
||||
ix = x + offset_x;
|
||||
iy = y + offset_y;
|
||||
|
||||
if (ix < 0 || ix >= width || iy < 0 || iy >= height)
|
||||
pixels[offset_y][offset_x] = 0x00000000;
|
||||
else
|
||||
pixels[offset_y][offset_x] = bytes[ix + iy * width];
|
||||
}
|
||||
}
|
||||
if (!pixels[0][0] && !pixels[0][1] && !pixels[1][0] && !pixels[1][1]) return 0;
|
||||
|
||||
ix = x;
|
||||
iy = y;
|
||||
x -= ix;
|
||||
y -= iy;
|
||||
for (i = 0; i < 4; i++) {
|
||||
uint32_t value = 0;
|
||||
uint32_t mask = 0xFF << (i * 8);
|
||||
value += ((pixels[0][0]) & mask) * (1 - x) * (1 - y);
|
||||
value += ((pixels[0][1]) & mask) * x * (1 - y);
|
||||
value += ((pixels[1][0]) & mask) * (1 - x) * y;
|
||||
value += ((pixels[1][1]) & mask) * x * y;
|
||||
reply |= value & mask;
|
||||
}
|
||||
return reply;
|
||||
return ply_pixels_interpolate (bytes, width, height, x, y);
|
||||
}
|
||||
|
||||
ply_pixel_buffer_t *
|
||||
|
|
@ -908,4 +968,20 @@ ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer,
|
|||
return buffer;
|
||||
}
|
||||
|
||||
int
|
||||
ply_pixel_buffer_get_device_scale (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
return buffer->device_scale;
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_set_device_scale (ply_pixel_buffer_t *buffer,
|
||||
int scale)
|
||||
{
|
||||
buffer->device_scale = scale;
|
||||
|
||||
buffer->logical_area.width = buffer->area.width / scale;
|
||||
buffer->logical_area.height = buffer->area.height / scale;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width,
|
|||
void ply_pixel_buffer_free (ply_pixel_buffer_t *buffer);
|
||||
void ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *size);
|
||||
int ply_pixel_buffer_get_device_scale (ply_pixel_buffer_t *buffer);
|
||||
void ply_pixel_buffer_set_device_scale (ply_pixel_buffer_t *buffer,
|
||||
int scale);
|
||||
|
||||
unsigned long ply_pixel_buffer_get_width (ply_pixel_buffer_t *buffer);
|
||||
unsigned long ply_pixel_buffer_get_height (ply_pixel_buffer_t *buffer);
|
||||
|
|
@ -90,6 +93,12 @@ void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buff
|
|||
ply_rectangle_t *clip_area,
|
||||
uint32_t *data,
|
||||
double opacity);
|
||||
void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
uint32_t *data,
|
||||
double opacity,
|
||||
int scale);
|
||||
|
||||
void ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canvas,
|
||||
ply_pixel_buffer_t *source,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue