mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-09 04:00:36 +02:00
In order for SLIM's PLT indirection avoidance to work, everything in
the library that makes internal function calls needs to see the
relevant slim_hidden_proto() macro in addition to the function's
prototype. However, external headers used by clients of the shared
library should not use the SLIM macros at all.
Pixman is a rather odd case -- it's mostly independent from cairo, so
it has it's own public interface, but it's built as a part of cairo
instead of its own shared library. This means that cairo would need to
see all of pixman's slim_hidden_proto() macros in order to function
and it doesn't currently, which results in a link failure on AMD64
systems and on i386 systems (I think, I haven't actually verified
this) it produces a shared object that isn't actally sharable.
I have no idea why exactly the link failure only showed up as a result
of commit e06246b9b1. I think it has
something to do with the pixman functions no longer having PLT entries
at all, but the exact interaction isn't clear to me.
However, all of these pixman functions aren't part of the cairo ABI
(which is why they were marked pixman_private in the first place),
which means that the SLIMification of pixman is largely pointless --
they aren't externally visible, so they don't need PLT entries at
all. Furthermore, while pixman may eventually be shared among cairo
and X, I'm told that this sharing will be source-level only, which
means it won't ever be an actual shared library and thus won't ever
need SLIM at all.
So, I just removed all use of SLIM in pixman (leaving behind
slim_internal.h for the future edification of anyone who cares).This
fixes the AMD64 link failure and passes the check-plt & check-def
parts of make check.
Signed-off-by: Nicholas Miell <nmiell@gmail.com>
943 lines
21 KiB
C
943 lines
21 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;
|
|
}
|
|
|
|
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 (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 = NULL;
|
|
image->pixels = NULL;
|
|
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 NULL;
|
|
|
|
image = _pixman_create_source_image ();
|
|
if (!image)
|
|
return NULL;
|
|
|
|
linear = malloc (sizeof (pixman_linear_gradient_image_t) +
|
|
sizeof (pixman_gradient_stop_t) * n_stops);
|
|
if (!linear)
|
|
{
|
|
free (image);
|
|
return NULL;
|
|
}
|
|
|
|
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 (linear);
|
|
free (image);
|
|
return NULL;
|
|
}
|
|
|
|
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 NULL;
|
|
|
|
image = _pixman_create_source_image ();
|
|
if (!image)
|
|
return NULL;
|
|
|
|
radial = malloc (sizeof (pixman_radial_gradient_image_t) +
|
|
sizeof (pixman_gradient_stop_t) * n_stops);
|
|
if (!radial)
|
|
{
|
|
free (image);
|
|
return NULL;
|
|
}
|
|
|
|
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 (radial);
|
|
free (image);
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 NULL;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|