mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-06 00:20:20 +01:00
1012 lines
23 KiB
C
1012 lines
23 KiB
C
/*
|
|
* Copyright © 2000 SuSE, Inc.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of SuSE not be used in advertising or
|
|
* publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. SuSE makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Author: Keith Packard, SuSE, Inc.
|
|
*/
|
|
|
|
#include "pixman-xserver-compat.h"
|
|
|
|
pixman_image_t *
|
|
pixman_image_create (pixman_format_t *format,
|
|
int width,
|
|
int height)
|
|
{
|
|
pixman_image_t *image;
|
|
FbPixels *pixels;
|
|
|
|
pixels = FbPixelsCreate (width, height, format->depth);
|
|
if (pixels == NULL)
|
|
return NULL;
|
|
|
|
image = pixman_image_createForPixels (pixels, format);
|
|
if (image == NULL) {
|
|
FbPixelsDestroy (pixels);
|
|
return NULL;
|
|
}
|
|
|
|
image->owns_pixels = 1;
|
|
|
|
return image;
|
|
}
|
|
slim_hidden_def(pixman_image_create);
|
|
|
|
pixman_image_t *
|
|
pixman_image_create_for_data (FbBits *data, pixman_format_t *format, int width, int height, int bpp, int stride)
|
|
{
|
|
pixman_image_t *image;
|
|
FbPixels *pixels;
|
|
|
|
pixels = FbPixelsCreateForData (data, width, height, format->depth, bpp, stride);
|
|
if (pixels == NULL)
|
|
return NULL;
|
|
|
|
image = pixman_image_createForPixels (pixels, format);
|
|
if (image == NULL) {
|
|
FbPixelsDestroy (pixels);
|
|
return NULL;
|
|
}
|
|
|
|
image->owns_pixels = 1;
|
|
|
|
return image;
|
|
}
|
|
|
|
pixman_image_t *
|
|
pixman_image_createForPixels (FbPixels *pixels,
|
|
pixman_format_t *format)
|
|
{
|
|
pixman_image_t *image;
|
|
|
|
image = malloc (sizeof (pixman_image_t));
|
|
if (!image)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
image->pixels = pixels;
|
|
image->image_format = *format;
|
|
image->format_code = format->format_code;
|
|
/* XXX: What's all this about?
|
|
if (pDrawable->type == DRAWABLE_PIXMAP)
|
|
{
|
|
++((PixmapPtr)pDrawable)->refcnt;
|
|
image->pNext = 0;
|
|
}
|
|
else
|
|
{
|
|
image->pNext = GetPictureWindow(((WindowPtr) pDrawable));
|
|
SetPictureWindow(((WindowPtr) pDrawable), image);
|
|
}
|
|
*/
|
|
|
|
pixman_image_init (image);
|
|
|
|
return image;
|
|
}
|
|
|
|
static CARD32 xRenderColorToCard32(pixman_color_t c)
|
|
{
|
|
return
|
|
(c.alpha >> 8 << 24) |
|
|
(c.red >> 8 << 16) |
|
|
(c.green & 0xff00) |
|
|
(c.blue >> 8);
|
|
}
|
|
|
|
static uint32_t premultiply(uint32_t x)
|
|
{
|
|
uint32_t a = x >> 24;
|
|
uint32_t t = (x & 0xff00ff) * a + 0x800080;
|
|
t = (t + ((t >> 8) & 0xff00ff)) >> 8;
|
|
t &= 0xff00ff;
|
|
|
|
x = ((x >> 8) & 0xff) * a + 0x80;
|
|
x = (x + ((x >> 8) & 0xff));
|
|
x &= 0xff00;
|
|
x |= t | (a << 24);
|
|
return x;
|
|
}
|
|
|
|
static uint32_t INTERPOLATE_PIXEL_256(uint32_t x, uint32_t a, uint32_t y, uint32_t b)
|
|
{
|
|
CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
|
|
t >>= 8;
|
|
t &= 0xff00ff;
|
|
|
|
x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
|
|
x &= 0xff00ff00;
|
|
x |= t;
|
|
return x;
|
|
}
|
|
|
|
uint32_t
|
|
pixman_gradient_color (pixman_gradient_stop_t *stop1,
|
|
pixman_gradient_stop_t *stop2,
|
|
uint32_t x)
|
|
{
|
|
uint32_t current_color, next_color;
|
|
int dist, idist;
|
|
|
|
current_color = xRenderColorToCard32 (stop1->color);
|
|
next_color = xRenderColorToCard32 (stop2->color);
|
|
|
|
dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
|
|
idist = 256 - dist;
|
|
|
|
return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
|
|
next_color, dist));
|
|
}
|
|
|
|
static int
|
|
pixman_init_gradient_color_table (pixman_gradient_image_t *gradient,
|
|
int tableSize)
|
|
{
|
|
int begin_pos, end_pos;
|
|
xFixed incr, dpos;
|
|
int pos, current_stop;
|
|
pixman_gradient_stop_t *stops = gradient->stops;
|
|
int nstops = gradient->nstops;
|
|
|
|
if (gradient->colorTableSize < tableSize)
|
|
{
|
|
uint32_t *newColorTable;
|
|
|
|
newColorTable = realloc (gradient->colorTable,
|
|
tableSize * sizeof (uint32_t));
|
|
if (!newColorTable)
|
|
return 1;
|
|
|
|
gradient->colorTable = newColorTable;
|
|
gradient->colorTableSize = tableSize;
|
|
}
|
|
|
|
gradient->stopRange = tableSize;
|
|
|
|
/* The position where the gradient begins and ends */
|
|
begin_pos = (stops[0].x * gradient->colorTableSize) >> 16;
|
|
end_pos = (stops[nstops - 1].x * gradient->colorTableSize) >> 16;
|
|
|
|
pos = 0; /* The position in the color table. */
|
|
|
|
/* Up to first point */
|
|
while (pos <= begin_pos) {
|
|
gradient->colorTable[pos] = xRenderColorToCard32(stops[0].color);
|
|
++pos;
|
|
}
|
|
|
|
incr = (1<<16)/ gradient->colorTableSize; /* the double increment. */
|
|
dpos = incr * pos; /* The position in terms of 0-1. */
|
|
|
|
current_stop = 0; /* We always interpolate between current and current + 1. */
|
|
|
|
/* Gradient area */
|
|
while (pos < end_pos) {
|
|
gradient->colorTable[pos] =
|
|
pixman_gradient_color (&stops[current_stop],
|
|
&stops[current_stop + 1],
|
|
dpos);
|
|
|
|
++pos;
|
|
dpos += incr;
|
|
|
|
if (dpos > stops[current_stop + 1].x)
|
|
++current_stop;
|
|
}
|
|
|
|
/* After last point */
|
|
while (pos < gradient->colorTableSize) {
|
|
gradient->colorTable[pos] =
|
|
xRenderColorToCard32 (stops[nstops - 1].color);
|
|
++pos;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_pixman_init_gradient (pixman_gradient_image_t *gradient,
|
|
const pixman_gradient_stop_t *stops,
|
|
int n_stops)
|
|
{
|
|
pixman_fixed16_16_t dpos;
|
|
int i;
|
|
|
|
if (n_stops <= 0)
|
|
return 1;
|
|
|
|
dpos = -1;
|
|
for (i = 0; i < n_stops; i++)
|
|
{
|
|
if (stops[i].x < dpos || stops[i].x > (1 << 16))
|
|
return 1;
|
|
|
|
dpos = stops[i].x;
|
|
}
|
|
|
|
gradient->class = SourcePictClassUnknown;
|
|
gradient->stopRange = 0xffff;
|
|
gradient->colorTable = NULL;
|
|
gradient->colorTableSize = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static pixman_image_t *
|
|
_pixman_create_source_image (void)
|
|
{
|
|
pixman_image_t *image;
|
|
|
|
image = (pixman_image_t *) malloc (sizeof (pixman_image_t));
|
|
image->pDrawable = 0;
|
|
image->pixels = 0;
|
|
image->format_code = PICT_a8r8g8b8;
|
|
|
|
pixman_image_init (image);
|
|
|
|
return image;
|
|
}
|
|
|
|
pixman_image_t *
|
|
pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
|
|
const pixman_gradient_stop_t *stops,
|
|
int n_stops)
|
|
{
|
|
pixman_linear_gradient_image_t *linear;
|
|
pixman_image_t *image;
|
|
|
|
if (n_stops < 2)
|
|
return 0;
|
|
|
|
image = _pixman_create_source_image ();
|
|
if (!image)
|
|
return 0;
|
|
|
|
linear = malloc (sizeof (pixman_linear_gradient_image_t) +
|
|
sizeof (pixman_gradient_stop_t) * n_stops);
|
|
if (!linear)
|
|
{
|
|
free (image);
|
|
return 0;
|
|
}
|
|
|
|
linear->stops = (pixman_gradient_stop_t *) (linear + 1);
|
|
linear->nstops = n_stops;
|
|
|
|
memcpy (linear->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
|
|
|
|
linear->type = SourcePictTypeLinear;
|
|
linear->p1 = gradient->p1;
|
|
linear->p2 = gradient->p2;
|
|
|
|
image->pSourcePict = (pixman_source_image_t *) linear;
|
|
|
|
if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
|
|
{
|
|
free (image);
|
|
return 0;
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
pixman_image_t *
|
|
pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
|
|
const pixman_gradient_stop_t *stops,
|
|
int n_stops)
|
|
{
|
|
pixman_radial_gradient_image_t *radial;
|
|
pixman_image_t *image;
|
|
double x;
|
|
|
|
if (n_stops < 2)
|
|
return 0;
|
|
|
|
image = _pixman_create_source_image ();
|
|
if (!image)
|
|
return 0;
|
|
|
|
radial = malloc (sizeof (pixman_radial_gradient_image_t) +
|
|
sizeof (pixman_gradient_stop_t) * n_stops);
|
|
if (!radial)
|
|
{
|
|
free (image);
|
|
return 0;
|
|
}
|
|
|
|
radial->stops = (pixman_gradient_stop_t *) (radial + 1);
|
|
radial->nstops = n_stops;
|
|
|
|
memcpy (radial->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
|
|
|
|
radial->type = SourcePictTypeRadial;
|
|
x = (double) gradient->inner.radius / (double) gradient->outer.radius;
|
|
radial->dx = (gradient->outer.x - gradient->inner.x);
|
|
radial->dy = (gradient->outer.y - gradient->inner.y);
|
|
radial->fx = (gradient->inner.x) - x * radial->dx;
|
|
radial->fy = (gradient->inner.y) - x * radial->dy;
|
|
radial->m = 1. / (1 + x);
|
|
radial->b = -x * radial->m;
|
|
radial->dx /= 65536.;
|
|
radial->dy /= 65536.;
|
|
radial->fx /= 65536.;
|
|
radial->fy /= 65536.;
|
|
x = gradient->outer.radius / 65536.;
|
|
radial->a = x * x - radial->dx * radial->dx - radial->dy * radial->dy;
|
|
|
|
image->pSourcePict = (pixman_source_image_t *) radial;
|
|
|
|
if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
|
|
{
|
|
free (image);
|
|
return 0;
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
void
|
|
pixman_image_init (pixman_image_t *image)
|
|
{
|
|
image->refcnt = 1;
|
|
image->repeat = PIXMAN_REPEAT_NONE;
|
|
image->graphicsExposures = 0;
|
|
image->subWindowMode = ClipByChildren;
|
|
image->polyEdge = PolyEdgeSharp;
|
|
image->polyMode = PolyModePrecise;
|
|
/*
|
|
* In the server this was 0 because the composite clip list
|
|
* can be referenced from a window (and often is)
|
|
*/
|
|
image->freeCompClip = 0;
|
|
image->freeSourceClip = 0;
|
|
image->clientClipType = CT_NONE;
|
|
image->componentAlpha = 0;
|
|
image->compositeClipSource = 0;
|
|
|
|
image->alphaMap = NULL;
|
|
image->alphaOrigin.x = 0;
|
|
image->alphaOrigin.y = 0;
|
|
|
|
image->clipOrigin.x = 0;
|
|
image->clipOrigin.y = 0;
|
|
image->clientClip = NULL;
|
|
|
|
image->dither = 0L;
|
|
|
|
image->stateChanges = (1 << (CPLastBit+1)) - 1;
|
|
/* XXX: What to lodge here?
|
|
image->serialNumber = GC_CHANGE_SERIAL_BIT;
|
|
*/
|
|
|
|
if (image->pixels)
|
|
{
|
|
image->pCompositeClip = pixman_region_create();
|
|
pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
|
|
0, 0, image->pixels->width,
|
|
image->pixels->height);
|
|
image->freeCompClip = 1;
|
|
|
|
image->pSourceClip = pixman_region_create ();
|
|
pixman_region_union_rect (image->pSourceClip, image->pSourceClip,
|
|
0, 0, image->pixels->width,
|
|
image->pixels->height);
|
|
image->freeSourceClip = 1;
|
|
}
|
|
else
|
|
{
|
|
image->pCompositeClip = NULL;
|
|
image->pSourceClip = NULL;
|
|
}
|
|
|
|
image->transform = NULL;
|
|
|
|
image->filter = PIXMAN_FILTER_NEAREST;
|
|
image->filter_params = NULL;
|
|
image->filter_nparams = 0;
|
|
|
|
|
|
image->owns_pixels = 0;
|
|
|
|
image->pSourcePict = NULL;
|
|
}
|
|
|
|
void
|
|
pixman_image_set_component_alpha (pixman_image_t *image,
|
|
int component_alpha)
|
|
{
|
|
if (image)
|
|
image->componentAlpha = component_alpha;
|
|
}
|
|
slim_hidden_def(pixman_image_set_component_alpha);
|
|
|
|
int
|
|
pixman_image_set_transform (pixman_image_t *image,
|
|
pixman_transform_t *transform)
|
|
{
|
|
static const pixman_transform_t identity = { {
|
|
{ xFixed1, 0x00000, 0x00000 },
|
|
{ 0x00000, xFixed1, 0x00000 },
|
|
{ 0x00000, 0x00000, xFixed1 },
|
|
} };
|
|
|
|
if (transform && memcmp (transform, &identity, sizeof (pixman_transform_t)) == 0)
|
|
transform = NULL;
|
|
|
|
if (transform)
|
|
{
|
|
if (!image->transform)
|
|
{
|
|
image->transform = malloc (sizeof (pixman_transform_t));
|
|
if (!image->transform)
|
|
return 1;
|
|
}
|
|
*image->transform = *transform;
|
|
}
|
|
else
|
|
{
|
|
if (image->transform)
|
|
{
|
|
free (image->transform);
|
|
image->transform = NULL;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
pixman_image_set_repeat (pixman_image_t *image,
|
|
pixman_repeat_t repeat)
|
|
{
|
|
if (image)
|
|
image->repeat = repeat;
|
|
}
|
|
slim_hidden_def(pixman_image_set_repeat);
|
|
|
|
void
|
|
pixman_image_set_filter (pixman_image_t *image,
|
|
pixman_filter_t filter)
|
|
{
|
|
if (image)
|
|
image->filter = filter;
|
|
}
|
|
|
|
int
|
|
pixman_image_get_width (pixman_image_t *image)
|
|
{
|
|
if (image->pixels)
|
|
return image->pixels->width;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
pixman_image_get_height (pixman_image_t *image)
|
|
{
|
|
if (image->pixels)
|
|
return image->pixels->height;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
pixman_image_get_depth (pixman_image_t *image)
|
|
{
|
|
if (image->pixels)
|
|
return image->pixels->depth;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
pixman_image_get_stride (pixman_image_t *image)
|
|
{
|
|
if (image->pixels)
|
|
return image->pixels->stride;
|
|
|
|
return 0;
|
|
}
|
|
|
|
pixman_format_t *
|
|
pixman_image_get_format (pixman_image_t *image)
|
|
{
|
|
return &image->image_format;
|
|
}
|
|
|
|
FbBits *
|
|
pixman_image_get_data (pixman_image_t *image)
|
|
{
|
|
if (image->pixels)
|
|
return image->pixels->data;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
pixman_image_destroy (pixman_image_t *image)
|
|
{
|
|
pixman_image_destroyClip (image);
|
|
|
|
if (image->freeCompClip) {
|
|
pixman_region_destroy (image->pCompositeClip);
|
|
image->pCompositeClip = NULL;
|
|
}
|
|
|
|
if (image->freeSourceClip) {
|
|
pixman_region_destroy (image->pSourceClip);
|
|
image->pSourceClip = NULL;
|
|
}
|
|
|
|
if (image->owns_pixels) {
|
|
FbPixelsDestroy (image->pixels);
|
|
image->pixels = NULL;
|
|
}
|
|
|
|
if (image->transform) {
|
|
free (image->transform);
|
|
image->transform = NULL;
|
|
}
|
|
|
|
if (image->pSourcePict) {
|
|
free (image->pSourcePict);
|
|
image->pSourcePict = NULL;
|
|
}
|
|
|
|
free (image);
|
|
}
|
|
slim_hidden_def(pixman_image_destroy);
|
|
|
|
void
|
|
pixman_image_destroyClip (pixman_image_t *image)
|
|
{
|
|
switch (image->clientClipType) {
|
|
case CT_NONE:
|
|
return;
|
|
case CT_PIXMAP:
|
|
pixman_image_destroy (image->clientClip);
|
|
break;
|
|
default:
|
|
pixman_region_destroy (image->clientClip);
|
|
break;
|
|
}
|
|
image->clientClip = NULL;
|
|
image->clientClipType = CT_NONE;
|
|
}
|
|
|
|
int
|
|
pixman_image_set_clip_region (pixman_image_t *image,
|
|
pixman_region16_t *region)
|
|
{
|
|
pixman_image_destroyClip (image);
|
|
if (region) {
|
|
image->clientClip = pixman_region_create ();
|
|
pixman_region_copy (image->clientClip, region);
|
|
image->clientClipType = CT_REGION;
|
|
}
|
|
|
|
image->stateChanges |= CPClipMask;
|
|
if (image->pSourcePict)
|
|
return 0;
|
|
|
|
if (image->freeCompClip)
|
|
pixman_region_destroy (image->pCompositeClip);
|
|
image->pCompositeClip = pixman_region_create();
|
|
pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
|
|
0, 0, image->pixels->width, image->pixels->height);
|
|
image->freeCompClip = 1;
|
|
if (region) {
|
|
pixman_region_translate (image->pCompositeClip,
|
|
- image->clipOrigin.x,
|
|
- image->clipOrigin.y);
|
|
pixman_region_intersect (image->pCompositeClip,
|
|
image->pCompositeClip,
|
|
region);
|
|
pixman_region_translate (image->pCompositeClip,
|
|
image->clipOrigin.x,
|
|
image->clipOrigin.y);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define BOUND(v) (int16_t) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
|
|
|
|
static __inline int
|
|
FbClipImageReg (pixman_region16_t *region,
|
|
pixman_region16_t *clip,
|
|
int dx,
|
|
int dy)
|
|
{
|
|
if (pixman_region_num_rects (region) == 1 &&
|
|
pixman_region_num_rects (clip) == 1)
|
|
{
|
|
pixman_box16_t *pRbox = pixman_region_rects (region);
|
|
pixman_box16_t *pCbox = pixman_region_rects (clip);
|
|
int v;
|
|
|
|
if (pRbox->x1 < (v = pCbox->x1 + dx))
|
|
pRbox->x1 = BOUND(v);
|
|
if (pRbox->x2 > (v = pCbox->x2 + dx))
|
|
pRbox->x2 = BOUND(v);
|
|
if (pRbox->y1 < (v = pCbox->y1 + dy))
|
|
pRbox->y1 = BOUND(v);
|
|
if (pRbox->y2 > (v = pCbox->y2 + dy))
|
|
pRbox->y2 = BOUND(v);
|
|
if (pRbox->x1 >= pRbox->x2 ||
|
|
pRbox->y1 >= pRbox->y2)
|
|
{
|
|
pixman_region_empty (region);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pixman_region_translate (region, dx, dy);
|
|
pixman_region_intersect (region, clip, region);
|
|
pixman_region_translate (region, -dx, -dy);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static __inline int
|
|
FbClipImageSrc (pixman_region16_t *region,
|
|
pixman_image_t *image,
|
|
int dx,
|
|
int dy)
|
|
{
|
|
/* XXX what to do with clipping from transformed pictures? */
|
|
if (image->transform)
|
|
return 1;
|
|
/* XXX davidr hates this, wants to never use source-based clipping */
|
|
if (image->repeat != PIXMAN_REPEAT_NONE || image->pSourcePict)
|
|
{
|
|
/* XXX no source clipping */
|
|
if (image->compositeClipSource &&
|
|
image->clientClipType != CT_NONE)
|
|
{
|
|
pixman_region_translate (region,
|
|
dx - image->clipOrigin.x,
|
|
dy - image->clipOrigin.y);
|
|
pixman_region_intersect (region, image->clientClip, region);
|
|
pixman_region_translate (region,
|
|
- (dx - image->clipOrigin.x),
|
|
- (dy - image->clipOrigin.y));
|
|
}
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
pixman_region16_t *clip;
|
|
|
|
if (image->compositeClipSource)
|
|
clip = image->pCompositeClip;
|
|
else
|
|
clip = image->pSourceClip;
|
|
return FbClipImageReg (region,
|
|
clip,
|
|
dx,
|
|
dy);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* XXX: Need to decide what to do with this
|
|
#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
|
|
|
|
#define NEXT_PTR(_type) ((_type) ulist++->ptr)
|
|
|
|
int
|
|
pixman_image_change (pixman_image_t *image,
|
|
Mask vmask,
|
|
unsigned int *vlist,
|
|
DevUnion *ulist,
|
|
int *error_value)
|
|
{
|
|
BITS32 index2;
|
|
int error = 0;
|
|
BITS32 maskQ;
|
|
|
|
maskQ = vmask;
|
|
while (vmask && !error)
|
|
{
|
|
index2 = (BITS32) lowbit (vmask);
|
|
vmask &= ~index2;
|
|
image->stateChanges |= index2;
|
|
switch (index2)
|
|
{
|
|
case CPRepeat:
|
|
{
|
|
unsigned int newr;
|
|
newr = NEXT_VAL(unsigned int);
|
|
if (newr <= xTrue)
|
|
image->repeat = newr;
|
|
else
|
|
{
|
|
*error_value = newr;
|
|
error = BadValue;
|
|
}
|
|
}
|
|
break;
|
|
case CPAlphaMap:
|
|
{
|
|
pixman_image_t *iAlpha;
|
|
|
|
iAlpha = NEXT_PTR(pixman_image_t *);
|
|
if (iAlpha)
|
|
iAlpha->refcnt++;
|
|
if (image->alphaMap)
|
|
pixman_image_destroy ((void *) image->alphaMap);
|
|
image->alphaMap = iAlpha;
|
|
}
|
|
break;
|
|
case CPAlphaXOrigin:
|
|
image->alphaOrigin.x = NEXT_VAL(int16_t);
|
|
break;
|
|
case CPAlphaYOrigin:
|
|
image->alphaOrigin.y = NEXT_VAL(int16_t);
|
|
break;
|
|
case CPClipXOrigin:
|
|
image->clipOrigin.x = NEXT_VAL(int16_t);
|
|
break;
|
|
case CPClipYOrigin:
|
|
image->clipOrigin.y = NEXT_VAL(int16_t);
|
|
break;
|
|
case CPClipMask:
|
|
{
|
|
pixman_image_t *mask;
|
|
int clipType;
|
|
|
|
mask = NEXT_PTR(pixman_image_t *);
|
|
if (mask) {
|
|
clipType = CT_PIXMAP;
|
|
mask->refcnt++;
|
|
} else {
|
|
clipType = CT_NONE;
|
|
}
|
|
error = pixman_image_change_clip (image, clipType,
|
|
(void *)mask, 0);
|
|
break;
|
|
}
|
|
case CPGraphicsExposure:
|
|
{
|
|
unsigned int newe;
|
|
newe = NEXT_VAL(unsigned int);
|
|
if (newe <= xTrue)
|
|
image->graphicsExposures = newe;
|
|
else
|
|
{
|
|
*error_value = newe;
|
|
error = BadValue;
|
|
}
|
|
}
|
|
break;
|
|
case CPSubwindowMode:
|
|
{
|
|
unsigned int news;
|
|
news = NEXT_VAL(unsigned int);
|
|
if (news == ClipByChildren || news == IncludeInferiors)
|
|
image->subWindowMode = news;
|
|
else
|
|
{
|
|
*error_value = news;
|
|
error = BadValue;
|
|
}
|
|
}
|
|
break;
|
|
case CPPolyEdge:
|
|
{
|
|
unsigned int newe;
|
|
newe = NEXT_VAL(unsigned int);
|
|
if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
|
|
image->polyEdge = newe;
|
|
else
|
|
{
|
|
*error_value = newe;
|
|
error = BadValue;
|
|
}
|
|
}
|
|
break;
|
|
case CPPolyMode:
|
|
{
|
|
unsigned int newm;
|
|
newm = NEXT_VAL(unsigned int);
|
|
if (newm == PolyModePrecise || newm == PolyModeImprecise)
|
|
image->polyMode = newm;
|
|
else
|
|
{
|
|
*error_value = newm;
|
|
error = BadValue;
|
|
}
|
|
}
|
|
break;
|
|
case CPDither:
|
|
image->dither = NEXT_VAL(unsigned long);
|
|
break;
|
|
case CPComponentAlpha:
|
|
{
|
|
unsigned int newca;
|
|
|
|
newca = NEXT_VAL (unsigned int);
|
|
if (newca <= xTrue)
|
|
image->componentAlpha = newca;
|
|
else
|
|
{
|
|
*error_value = newca;
|
|
error = BadValue;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
*error_value = maskQ;
|
|
error = BadValue;
|
|
break;
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
*/
|
|
|
|
/* XXX: Do we need this?
|
|
int
|
|
SetPictureClipRects (PicturePtr pPicture,
|
|
int xOrigin,
|
|
int yOrigin,
|
|
int nRect,
|
|
xRectangle *rects)
|
|
{
|
|
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
|
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
|
pixman_region16_t *clientClip;
|
|
int result;
|
|
|
|
clientClip = RECTS_TO_REGION(pScreen,
|
|
nRect, rects, CT_UNSORTED);
|
|
if (!clientClip)
|
|
return 1;
|
|
result =(*ps->ChangePictureClip) (pPicture, CT_REGION,
|
|
(void *) clientClip, 0);
|
|
if (result == 0)
|
|
{
|
|
pPicture->clipOrigin.x = xOrigin;
|
|
pPicture->clipOrigin.y = yOrigin;
|
|
pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
|
|
pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
|
|
}
|
|
return result;
|
|
}
|
|
*/
|
|
|
|
int
|
|
FbComputeCompositeRegion (pixman_region16_t *region,
|
|
pixman_image_t *iSrc,
|
|
pixman_image_t *iMask,
|
|
pixman_image_t *iDst,
|
|
int16_t xSrc,
|
|
int16_t ySrc,
|
|
int16_t xMask,
|
|
int16_t yMask,
|
|
int16_t xDst,
|
|
int16_t yDst,
|
|
uint16_t width,
|
|
uint16_t height)
|
|
{
|
|
int v;
|
|
int x1, y1, x2, y2;
|
|
|
|
/* XXX: This code previously directly set the extents of the
|
|
region here. I need to decide whether removing that has broken
|
|
this. Also, it might be necessary to just make the pixman_region16_t
|
|
data structure transparent anyway in which case I can just put
|
|
the code back. */
|
|
x1 = xDst;
|
|
v = xDst + width;
|
|
x2 = BOUND(v);
|
|
y1 = yDst;
|
|
v = yDst + height;
|
|
y2 = BOUND(v);
|
|
/* Check for empty operation */
|
|
if (x1 >= x2 ||
|
|
y1 >= y2)
|
|
{
|
|
pixman_region_empty (region);
|
|
return 1;
|
|
}
|
|
/* clip against src */
|
|
if (!FbClipImageSrc (region, iSrc, xDst - xSrc, yDst - ySrc))
|
|
{
|
|
pixman_region_destroy (region);
|
|
return 0;
|
|
}
|
|
if (iSrc->alphaMap)
|
|
{
|
|
if (!FbClipImageSrc (region, iSrc->alphaMap,
|
|
xDst - (xSrc + iSrc->alphaOrigin.x),
|
|
yDst - (ySrc + iSrc->alphaOrigin.y)))
|
|
{
|
|
pixman_region_destroy (region);
|
|
return 0;
|
|
}
|
|
}
|
|
/* clip against mask */
|
|
if (iMask)
|
|
{
|
|
if (!FbClipImageSrc (region, iMask, xDst - xMask, yDst - yMask))
|
|
{
|
|
pixman_region_destroy (region);
|
|
return 0;
|
|
}
|
|
if (iMask->alphaMap)
|
|
{
|
|
if (!FbClipImageSrc (region, iMask->alphaMap,
|
|
xDst - (xMask + iMask->alphaOrigin.x),
|
|
yDst - (yMask + iMask->alphaOrigin.y)))
|
|
{
|
|
pixman_region_destroy (region);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
if (!FbClipImageReg (region, iDst->pCompositeClip, 0, 0))
|
|
{
|
|
pixman_region_destroy (region);
|
|
return 0;
|
|
}
|
|
if (iDst->alphaMap)
|
|
{
|
|
if (!FbClipImageReg (region, iDst->alphaMap->pCompositeClip,
|
|
-iDst->alphaOrigin.x,
|
|
-iDst->alphaOrigin.y))
|
|
{
|
|
pixman_region_destroy (region);
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
miIsSolidAlpha (pixman_image_t *src)
|
|
{
|
|
char line[1];
|
|
|
|
/* Alpha-only */
|
|
if (PICT_FORMAT_TYPE (src->format_code) != PICT_TYPE_A)
|
|
return 0;
|
|
/* repeat */
|
|
if (!src->repeat)
|
|
return 0;
|
|
/* 1x1 */
|
|
if (src->pixels->width != 1 || src->pixels->height != 1)
|
|
return 0;
|
|
line[0] = 1;
|
|
/* XXX: For the next line, fb has:
|
|
(*pScreen->GetImage) (src->pixels, 0, 0, 1, 1, ZPixmap, ~0L, line);
|
|
Is the following simple assignment sufficient?
|
|
*/
|
|
line[0] = src->pixels->data[0];
|
|
switch (src->pixels->bpp) {
|
|
case 1:
|
|
return (uint8_t) line[0] == 1 || (uint8_t) line[0] == 0x80;
|
|
case 4:
|
|
return (uint8_t) line[0] == 0xf || (uint8_t) line[0] == 0xf0;
|
|
case 8:
|
|
return (uint8_t) line[0] == 0xff;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|