--- /dev/null
+/* ply-pixel-buffer.c - pixelbuffer abstraction
+ *
+ * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
+ * 2008 Charlie Brej <cbrej@cs.man.ac.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Charlie Brej <cbrej@cs.man.ac.uk>
+ * Kristian Høgsberg <krh@redhat.com>
+ * Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+#include "ply-list.h"
+#include "ply-pixel-buffer.h"
+#include "ply-logger.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+struct _ply_pixel_buffer
+{
+ uint32_t *bytes;
+
+ ply_rectangle_t area;
+ ply_list_t *clip_areas;
+
+ ply_region_t *updated_areas;
+};
+
+static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
+ int x,
+ int y,
+ uint32_t pixel_value);
+
+static void ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t pixel_value);
+
+__attribute__((__pure__))
+static inline uint32_t
+blend_two_pixel_values (uint32_t pixel_value_1,
+ uint32_t pixel_value_2)
+{
+ if ((pixel_value_2 & 0xff000000) == 0xff000000)
+ {
+ uint8_t alpha_1, red_1, green_1, blue_1;
+ uint8_t red_2, green_2, blue_2;
+ uint_least16_t red, green, blue;
+
+ alpha_1 = (uint8_t) (pixel_value_1 >> 24);
+ red_1 = (uint8_t) (pixel_value_1 >> 16);
+ green_1 = (uint8_t) (pixel_value_1 >> 8);
+ blue_1 = (uint8_t) pixel_value_1;
+
+ red_2 = (uint8_t) (pixel_value_2 >> 16);
+ green_2 = (uint8_t) (pixel_value_2 >> 8);
+ blue_2 = (uint8_t) pixel_value_2;
+
+ red = red_1 * 255 + red_2 * (255 - alpha_1);
+ green = green_1 * 255 + green_2 * (255 - alpha_1);
+ blue = blue_1 * 255 + blue_2 * (255 - alpha_1);
+
+ red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8);
+ green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8);
+ blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8);
+
+ return 0xff000000 | (red << 16) | (green << 8) | blue;
+ }
+ else
+ {
+ uint8_t alpha_1, red_1, green_1, blue_1;
+ uint8_t alpha_2, red_2, green_2, blue_2;
+ uint_least32_t alpha, red, green, blue;
+
+ alpha_1 = (uint8_t) (pixel_value_1 >> 24);
+ red_1 = (uint8_t) (pixel_value_1 >> 16);
+ green_1 = (uint8_t) (pixel_value_1 >> 8);
+ blue_1 = (uint8_t) pixel_value_1;
+
+ alpha_2 = (uint8_t) (pixel_value_2 >> 24);
+ red_2 = (uint8_t) (pixel_value_2 >> 16);
+ green_2 = (uint8_t) (pixel_value_2 >> 8);
+ blue_2 = (uint8_t) pixel_value_2;
+
+ red = red_1 * alpha_1 + red_2 * alpha_2 * (255 - alpha_1);
+ green = green_1 * alpha_1 + green_2 * alpha_2 * (255 - alpha_1);
+ blue = blue_1 * alpha_1 + blue_2 * alpha_2 * (255 - alpha_1);
+ alpha = alpha_1 * 255 + alpha_2 * (255 - alpha_1);
+
+ red = (red + (red >> 8) + 0x80) >> 8;
+ red = MIN (red, 0xff);
+
+ green = (green + (green >> 8) + 0x80) >> 8;
+ green = MIN (green, 0xff);
+
+ blue = (blue + (blue >> 8) + 0x80) >> 8;
+ blue = MIN (blue, 0xff);
+
+ alpha = (alpha + (alpha >> 8) + 0x80) >> 8;
+ alpha = MIN (alpha, 0xff);
+
+ return (alpha << 24) | (red << 16) | (green << 8) | blue;
+ }
+}
+
+__attribute__((__pure__))
+static inline uint32_t
+make_pixel_value_translucent (uint32_t pixel_value,
+ uint8_t opacity)
+{
+ uint_least16_t alpha, red, green, blue;
+
+ if (opacity == 255)
+ return pixel_value;
+
+ alpha = (uint8_t) (pixel_value >> 24);
+ red = (uint8_t) (pixel_value >> 16);
+ green = (uint8_t) (pixel_value >> 8);
+ blue = (uint8_t) pixel_value;
+
+ red *= opacity;
+ green *= opacity;
+ blue *= opacity;
+ alpha *= opacity;
+
+ red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8);
+ green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8);
+ blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8);
+ alpha = (uint8_t) ((alpha + (alpha >> 8) + 0x80) >> 8);
+
+ return (alpha << 24) | (red << 16) | (green << 8) | blue;
+}
+
+static inline void
+ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
+ int x,
+ int y,
+ uint32_t pixel_value)
+{
+ uint32_t old_pixel_value;
+
+ if ((pixel_value >> 24) != 0xff)
+ {
+ old_pixel_value = buffer->bytes[y * buffer->area.width + x];
+
+ pixel_value = blend_two_pixel_values (pixel_value, old_pixel_value);
+ }
+
+ buffer->bytes[y * buffer->area.width + x] = pixel_value;
+}
+
+static void
+ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *area,
+ ply_rectangle_t *cropped_area)
+{
+ ply_list_node_t *node;
+
+ *cropped_area = *area;
+
+ node = ply_list_get_first_node (buffer->clip_areas);
+ while (node != NULL)
+ {
+ ply_list_node_t *next_node;
+ ply_rectangle_t *clip_rectangle;
+
+ clip_rectangle = ply_list_node_get_data (node);
+ next_node = ply_list_get_next_node (buffer->clip_areas, node);
+
+ ply_rectangle_intersect (cropped_area, clip_rectangle, cropped_area);
+
+ node = next_node;
+ }
+}
+
+static void
+ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t pixel_value)
+{
+ unsigned long row, column;
+ ply_rectangle_t cropped_area;
+
+ ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
+
+ for (row = cropped_area.y; row < cropped_area.y + cropped_area.height; row++)
+ {
+ for (column = cropped_area.x; column < cropped_area.x + cropped_area.width; column++)
+ {
+ ply_pixel_buffer_blend_value_at_pixel (buffer,
+ column, row,
+ pixel_value);
+ }
+ }
+}
+
+void
+ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *clip_area)
+{
+ ply_rectangle_t *new_clip_area;
+
+ new_clip_area = malloc (sizeof (*new_clip_area));
+
+ *new_clip_area = *clip_area;
+ ply_list_append_data (buffer->clip_areas, new_clip_area);
+}
+
+void
+ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer)
+{
+ ply_list_node_t *last_node;
+
+ last_node = ply_list_get_last_node (buffer->clip_areas);
+ free (ply_list_node_get_data (last_node));
+ ply_list_remove_node (buffer->clip_areas, last_node);
+}
+
+ply_pixel_buffer_t *
+ply_pixel_buffer_new (unsigned long width,
+ unsigned long height)
+{
+ ply_pixel_buffer_t *buffer;
+
+ buffer = calloc (1, sizeof (ply_pixel_buffer_t));
+
+ buffer->updated_areas = ply_region_new ();
+ buffer->bytes = (uint32_t *) calloc (height, width * sizeof (uint32_t));
+ buffer->area.width = width;
+ buffer->area.height = height;
+
+ buffer->clip_areas = ply_list_new ();
+ ply_pixel_buffer_push_clip_area (buffer, &buffer->area);
+
+ return buffer;
+}
+
+static void
+free_clip_areas (ply_pixel_buffer_t *buffer)
+{
+ while (ply_list_get_length (buffer->clip_areas) > 0)
+ ply_pixel_buffer_pop_clip_area (buffer);
+
+ ply_list_free (buffer->clip_areas);
+ buffer->clip_areas = NULL;
+}
+
+void
+ply_pixel_buffer_free (ply_pixel_buffer_t *buffer)
+{
+ if (buffer == NULL)
+ return;
+
+ free_clip_areas (buffer);
+ free (buffer->bytes);
+ ply_region_free (buffer->updated_areas);
+ free (buffer);
+}
+
+void
+ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *size)
+{
+ assert (buffer != NULL);
+ assert (size != NULL);
+
+ *size = buffer->area;
+}
+
+ply_region_t *
+ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer)
+{
+ return buffer->updated_areas;
+}
+
+void
+ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t start,
+ uint32_t end)
+{
+/* The gradient produced is a linear interpolation of the two passed
+ * in color stops: start and end.
+ *
+ * In order to prevent banding when the color stops are too close
+ * together, or are stretched over too large an area, we slightly
+ * perturb the intermediate colors as we generate them.
+ *
+ * Before we do this, we store the interpolated color values in a
+ * fixed point number with lots of fractional bits. This is so
+ * we don't add noise after the values have been clamped to 8-bits
+ *
+ * We add random noise to all of the fractional bits of each color
+ * channel and also NOISE_BITS worth of noise to the non-fractional
+ * part of the color. By default NOISE_BITS is 1.
+ *
+ * We incorporate the noise by filling the bottom 24 bits of an
+ * integer with random bits and then shifting the color channels
+ * to the left such that the top 8 bits of the channel overlap
+ * the noise by NOISE_BITS. E.g., if NOISE_BITS is 1, then the top
+ * 7 bits of each channel won't overlap with the noise, and the 8th
+ * bit + fractional bits will. When the noise and color channel
+ * are properly aligned, we add them together, drop the precision
+ * of the resulting channels back to 8 bits and stuff the results
+ * into a pixel in the pixel buffer.
+ */
+#define NOISE_BITS 1
+/* In the color stops, red is 8 bits starting at position 24
+ * (since they're argb32 pixels).
+ * We want to move those 8 bits such that the bottom NOISE_BITS
+ * of them overlap the top of the 24 bits of generated noise.
+ * Of course, green and blue are 8 bits away from red and each
+ * other, respectively.
+ */
+#define RED_SHIFT (32 - (24 + NOISE_BITS))
+#define GREEN_SHIFT (RED_SHIFT + 8)
+#define BLUE_SHIFT (GREEN_SHIFT + 8)
+#define NOISE_MASK (0x00ffffff)
+
+/* Once, we've lined up the color channel we're interested in with
+ * the noise, we need to mask out the other channels.
+ */
+#define COLOR_MASK (0xff << (24 - NOISE_BITS))
+
+ uint32_t red, green, blue, red_step, green_step, blue_step, t, pixel;
+ uint32_t x, y;
+ /* we use a fixed seed so that the dithering doesn't change on repaints
+ * of the same area.
+ */
+ uint32_t noise = 0x100001;
+ ply_rectangle_t cropped_area;
+
+ if (fill_area == NULL)
+ fill_area = &buffer->area;
+
+ ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
+
+ red = (start << RED_SHIFT) & COLOR_MASK;
+ green = (start << GREEN_SHIFT) & COLOR_MASK;
+ blue = (start << BLUE_SHIFT) & COLOR_MASK;
+
+ t = (end << RED_SHIFT) & COLOR_MASK;
+ red_step = (int32_t) (t - red) / (int32_t) buffer->area.height;
+ t = (end << GREEN_SHIFT) & COLOR_MASK;
+ green_step = (int32_t) (t - green) / (int32_t) buffer->area.height;
+ t = (end << BLUE_SHIFT) & COLOR_MASK;
+ blue_step = (int32_t) (t - blue) / (int32_t) buffer->area.height;
+
+
+#define RANDOMIZE(num) (num = (num + (num << 1)) & NOISE_MASK)
+#define UNROLLED_PIXEL_COUNT 8
+
+ for (y = buffer->area.y; y < buffer->area.y + buffer->area.height; y++)
+ {
+ if (cropped_area.y <= y && y < cropped_area.y + cropped_area.height)
+ {
+ if (cropped_area.width < UNROLLED_PIXEL_COUNT)
+ {
+ for (x = cropped_area.x; x < cropped_area.x + cropped_area.width; x++)
+ {
+ pixel = 0xff000000;
+ RANDOMIZE(noise);
+ pixel |= (((red + noise) & COLOR_MASK) >> RED_SHIFT);
+ RANDOMIZE(noise);
+ pixel |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT);
+ RANDOMIZE(noise);
+ pixel |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT);
+
+ buffer->bytes[y * buffer->area.width + x] = pixel;
+ }
+ }
+ else
+ {
+ uint32_t shaded_set[UNROLLED_PIXEL_COUNT];
+ uint32_t *ptr = &buffer->bytes[y * buffer->area.width + cropped_area.x];
+ for (x = 0; x < UNROLLED_PIXEL_COUNT; x++)
+ {
+ shaded_set[x] = 0xff000000;
+ RANDOMIZE(noise);
+ shaded_set[x] |= (((red + noise) & COLOR_MASK) >> RED_SHIFT);
+ RANDOMIZE(noise);
+ shaded_set[x] |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT);
+ RANDOMIZE(noise);
+ shaded_set[x] |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT);
+ }
+ for (x = cropped_area.width; x >=UNROLLED_PIXEL_COUNT; x-= UNROLLED_PIXEL_COUNT)
+ {
+ memcpy (ptr, (void *) shaded_set, UNROLLED_PIXEL_COUNT * sizeof (uint32_t));
+ ptr += UNROLLED_PIXEL_COUNT;
+ }
+
+ memcpy (ptr, (void *) shaded_set, x * sizeof (uint32_t));
+ }
+ }
+
+ red += red_step;
+ green += green_step;
+ blue += blue_step;
+ }
+
+ ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
+}
+
+void
+ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ double red,
+ double green,
+ double blue,
+ 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);
+}
+
+void
+ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t hex_color,
+ double opacity)
+{
+ ply_rectangle_t cropped_area;
+ uint32_t pixel_value;
+ double red;
+ double green;
+ double blue;
+ double alpha;
+
+ 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)
+ hex_color = (hex_color << 8) | 0xff;
+
+ red = ((double) (hex_color & 0xff000000) / 0xff000000);
+ green = ((double) (hex_color & 0x00ff0000) / 0x00ff0000);
+ blue = ((double) (hex_color & 0x0000ff00) / 0x0000ff00);
+ alpha = ((double) (hex_color & 0x000000ff) / 0x000000ff);
+
+ alpha *= opacity;
+
+ 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);
+}
+
+void
+ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t hex_color)
+{
+ return ply_pixel_buffer_fill_with_hex_color_at_opacity (buffer, fill_area,
+ hex_color, 1.0);
+}
+
+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,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data,
+ double opacity)
+{
+ unsigned long row, column;
+ uint8_t opacity_as_byte;
+ 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);
+
+ if (clip_area)
+ ply_rectangle_intersect (&cropped_area, 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);
+
+ 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 ((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),
+ pixel_value);
+
+ }
+ }
+
+ ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
+}
+
+void
+ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data,
+ double opacity)
+{
+ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
+ fill_area,
+ NULL, x, y,
+ data, opacity);
+}
+
+void
+ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data)
+{
+ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
+ fill_area,
+ NULL, x, y,
+ data, 1.0);
+}
+
+void
+ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ ply_rectangle_t *clip_area,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data)
+{
+ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
+ fill_area,
+ clip_area, x, y,
+ data, 1.0);
+}
+
+uint32_t *
+ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer)
+{
+ return buffer->bytes;
+}
+/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
--- /dev/null
+/* ply-pixel-buffer.h - pixel buffer abstraction
+ *
+ * Copyright (C) 2007, 2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written By: Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_PIXEL_BUFFER_H
+#define PLY_PIXEL_BUFFER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "ply-rectangle.h"
+#include "ply-region.h"
+#include "ply-utils.h"
+
+typedef struct _ply_pixel_buffer ply_pixel_buffer_t;
+
+#define PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE(r,g,b,a) \
+ (((uint8_t) (CLAMP (a * 255.0, 0.0, 255.0)) << 24) \
+ | ((uint8_t) (CLAMP (r * 255.0, 0.0, 255.0)) << 16) \
+ | ((uint8_t) (CLAMP (g * 255.0, 0.0, 255.0)) << 8) \
+ | ((uint8_t) (CLAMP (b * 255.0, 0.0, 255.0))))
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width,
+ unsigned long height);
+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);
+ply_region_t *ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer);
+
+void ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ double red,
+ double green,
+ double blue,
+ double alpha);
+void ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t hex_color);
+
+void ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t hex_color,
+ double opacity);
+
+void ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ uint32_t start,
+ uint32_t end);
+
+void ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data);
+void ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data,
+ double opacity);
+
+void ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *fill_area,
+ ply_rectangle_t *clip_area,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data);
+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,
+ unsigned long x,
+ unsigned long y,
+ uint32_t *data,
+ double opacity);
+
+void ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer,
+ ply_rectangle_t *clip_area);
+void ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer);
+
+uint32_t *ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer);
+
+#endif
+
+#endif /* PLY_PIXEL_BUFFER_H */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */