summaryrefslogtreecommitdiff
path: root/pixman/src/icimage.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/src/icimage.c')
-rw-r--r--pixman/src/icimage.c716
1 files changed, 716 insertions, 0 deletions
diff --git a/pixman/src/icimage.c b/pixman/src/icimage.c
new file mode 100644
index 0000000..86db441
--- /dev/null
+++ b/pixman/src/icimage.c
@@ -0,0 +1,716 @@
+/*
+ * 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;
+}
+
+void
+pixman_image_init (pixman_image_t *image)
+{
+ image->refcnt = 1;
+ image->repeat = 0;
+ 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 = 0;
+ image->alphaOrigin.x = 0;
+ image->alphaOrigin.y = 0;
+
+ image->clipOrigin.x = 0;
+ image->clipOrigin.y = 0;
+ image->clientClip = 0;
+
+ image->dither = 0L;
+
+ image->stateChanges = (1 << (CPLastBit+1)) - 1;
+/* XXX: What to lodge here?
+ image->serialNumber = GC_CHANGE_SERIAL_BIT;
+*/
+
+ 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;
+
+ image->transform = NULL;
+
+ image->filter = PIXMAN_FILTER_NEAREST;
+ image->filter_params = 0;
+ image->filter_nparams = 0;
+
+
+ image->owns_pixels = 0;
+}
+
+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 = 0;
+
+ 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 = 0;
+ }
+ }
+ return 0;
+}
+
+void
+pixman_image_set_repeat (pixman_image_t *image,
+ int 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)
+{
+ return image->pixels->width;
+}
+
+int
+pixman_image_get_height (pixman_image_t *image)
+{
+ return image->pixels->height;
+}
+
+int
+pixman_image_get_depth (pixman_image_t *image)
+{
+ return image->pixels->depth;
+}
+
+int
+pixman_image_get_stride (pixman_image_t *image)
+{
+ return image->pixels->stride;
+}
+
+pixman_format_t *
+pixman_image_get_format (pixman_image_t *image)
+{
+ return &image->image_format;
+}
+
+FbBits *
+pixman_image_get_data (pixman_image_t *image)
+{
+ return image->pixels->data;
+}
+
+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;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ image->stateChanges |= CPClipMask;
+ 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;
+ if (image->repeat)
+ {
+ /* 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;
+ }
+}