Back to index

lightning-sunbird  0.9+nobinonly
icimage.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2000 SuSE, Inc.
00003  *
00004  * Permission to use, copy, modify, distribute, and sell this software and its
00005  * documentation for any purpose is hereby granted without fee, provided that
00006  * the above copyright notice appear in all copies and that both that
00007  * copyright notice and this permission notice appear in supporting
00008  * documentation, and that the name of SuSE not be used in advertising or
00009  * publicity pertaining to distribution of the software without specific,
00010  * written prior permission.  SuSE makes no representations about the
00011  * suitability of this software for any purpose.  It is provided "as is"
00012  * without express or implied warranty.
00013  *
00014  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
00015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
00016  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00017  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
00018  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
00019  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00020  *
00021  * Author:  Keith Packard, SuSE, Inc.
00022  */
00023 
00024 #include "pixman-xserver-compat.h"
00025 
00026 pixman_image_t *
00027 pixman_image_create (pixman_format_t      *format,
00028               int    width,
00029               int    height)
00030 {
00031     pixman_image_t   *image;
00032     FbPixels  *pixels;
00033 
00034     pixels = FbPixelsCreate (width, height, format->depth);
00035     if (pixels == NULL)
00036        return NULL;
00037     
00038     image = pixman_image_createForPixels (pixels, format);
00039     if (image == NULL) {
00040        FbPixelsDestroy (pixels);
00041        return NULL;
00042     }
00043 
00044     image->owns_pixels = 1;
00045 
00046     return image;
00047 }
00048 slim_hidden_def(pixman_image_create);
00049 
00050 pixman_image_t *
00051 pixman_image_create_for_data (FbBits *data, pixman_format_t *format, int width, int height, int bpp, int stride)
00052 {
00053     pixman_image_t   *image;
00054     FbPixels  *pixels;
00055 
00056     pixels = FbPixelsCreateForData (data, width, height, format->depth, bpp, stride);
00057     if (pixels == NULL)
00058        return NULL;
00059 
00060     image = pixman_image_createForPixels (pixels, format);
00061     if (image == NULL) {
00062        FbPixelsDestroy (pixels);
00063        return NULL;
00064     }
00065 
00066     image->owns_pixels = 1;
00067 
00068     return image;
00069 }
00070 
00071 pixman_image_t *
00072 pixman_image_createForPixels (FbPixels    *pixels,
00073                      pixman_format_t      *format)
00074 {
00075     pixman_image_t          *image;
00076 
00077     image = malloc (sizeof (pixman_image_t));
00078     if (!image)
00079     {
00080        return NULL;
00081     }
00082 
00083     image->pixels = pixels;
00084     image->image_format = *format;
00085     image->format_code = format->format_code;
00086 /* XXX: What's all this about?
00087     if (pDrawable->type == DRAWABLE_PIXMAP)
00088     {
00089        ++((PixmapPtr)pDrawable)->refcnt;
00090        image->pNext = 0;
00091     }
00092     else
00093     {
00094        image->pNext = GetPictureWindow(((WindowPtr) pDrawable));
00095        SetPictureWindow(((WindowPtr) pDrawable), image);
00096     }
00097 */
00098 
00099     pixman_image_init (image);
00100 
00101     return image;
00102 }
00103 
00104 void
00105 pixman_image_init (pixman_image_t *image)
00106 {
00107     image->refcnt = 1;
00108     image->repeat = 0;
00109     image->graphicsExposures = 0;
00110     image->subWindowMode = ClipByChildren;
00111     image->polyEdge = PolyEdgeSharp;
00112     image->polyMode = PolyModePrecise;
00113     /* 
00114      * In the server this was 0 because the composite clip list
00115      * can be referenced from a window (and often is)
00116      */
00117     image->freeCompClip = 0;
00118     image->freeSourceClip = 0;
00119     image->clientClipType = CT_NONE;
00120     image->componentAlpha = 0;
00121     image->compositeClipSource = 0;
00122 
00123     image->alphaMap = NULL;
00124     image->alphaOrigin.x = 0;
00125     image->alphaOrigin.y = 0;
00126 
00127     image->clipOrigin.x = 0;
00128     image->clipOrigin.y = 0;
00129     image->clientClip = NULL;
00130 
00131     image->dither = 0L;
00132 
00133     image->stateChanges = (1 << (CPLastBit+1)) - 1;
00134 /* XXX: What to lodge here?
00135     image->serialNumber = GC_CHANGE_SERIAL_BIT;
00136 */
00137 
00138     image->pCompositeClip = pixman_region_create();
00139     pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
00140                      0, 0, image->pixels->width, image->pixels->height);
00141     image->freeCompClip = 1;
00142 
00143     image->pSourceClip = pixman_region_create ();
00144     pixman_region_union_rect (image->pSourceClip, image->pSourceClip,
00145                      0, 0, image->pixels->width, image->pixels->height);
00146     image->freeSourceClip = 1;
00147     
00148     image->transform = NULL;
00149 
00150     image->filter = PIXMAN_FILTER_NEAREST;
00151     image->filter_params = NULL;
00152     image->filter_nparams = 0;
00153 
00154 
00155     image->owns_pixels = 0;
00156 }
00157 
00158 void
00159 pixman_image_set_component_alpha (pixman_image_t *image,
00160                               int         component_alpha)
00161 {
00162     if (image)
00163        image->componentAlpha = component_alpha;
00164 }
00165 slim_hidden_def(pixman_image_set_component_alpha);
00166 
00167 int
00168 pixman_image_set_transform (pixman_image_t              *image,
00169                    pixman_transform_t     *transform)
00170 {
00171     static const pixman_transform_t       identity = { {
00172        { xFixed1, 0x00000, 0x00000 },
00173        { 0x00000, xFixed1, 0x00000 },
00174        { 0x00000, 0x00000, xFixed1 },
00175     } };
00176 
00177     if (transform && memcmp (transform, &identity, sizeof (pixman_transform_t)) == 0)
00178        transform = NULL;
00179     
00180     if (transform)
00181     {
00182        if (!image->transform)
00183        {
00184            image->transform = malloc (sizeof (pixman_transform_t));
00185            if (!image->transform)
00186               return 1;
00187        }
00188        *image->transform = *transform;
00189     }
00190     else
00191     {
00192        if (image->transform)
00193        {
00194            free (image->transform);
00195            image->transform = NULL;
00196        }
00197     }
00198     return 0;
00199 }
00200 
00201 void
00202 pixman_image_set_repeat (pixman_image_t   *image,
00203                 int         repeat)
00204 {
00205     if (image)
00206        image->repeat = repeat;
00207 }
00208 slim_hidden_def(pixman_image_set_repeat);
00209 
00210 void
00211 pixman_image_set_filter (pixman_image_t   *image,
00212                 pixman_filter_t    filter)
00213 {
00214     if (image)
00215        image->filter = filter;
00216 }
00217 
00218 int
00219 pixman_image_get_width (pixman_image_t    *image)
00220 {
00221     return image->pixels->width;
00222 }
00223 
00224 int
00225 pixman_image_get_height (pixman_image_t   *image)
00226 {
00227     return image->pixels->height;
00228 }
00229 
00230 int
00231 pixman_image_get_depth (pixman_image_t    *image)
00232 {
00233     return image->pixels->depth;
00234 }
00235 
00236 int
00237 pixman_image_get_stride (pixman_image_t   *image)
00238 {
00239     return image->pixels->stride;
00240 }
00241 
00242 pixman_format_t *
00243 pixman_image_get_format (pixman_image_t   *image)
00244 {
00245     return &image->image_format;
00246 }
00247 
00248 FbBits *
00249 pixman_image_get_data (pixman_image_t     *image)
00250 {
00251     return image->pixels->data;
00252 }
00253 
00254 void
00255 pixman_image_destroy (pixman_image_t *image)
00256 {
00257     pixman_image_destroyClip (image);
00258 
00259     if (image->freeCompClip) {
00260        pixman_region_destroy (image->pCompositeClip);
00261        image->pCompositeClip = NULL;
00262     }
00263     
00264     if (image->freeSourceClip) {
00265        pixman_region_destroy (image->pSourceClip);
00266        image->pSourceClip = NULL;
00267     }
00268 
00269     if (image->owns_pixels) {
00270        FbPixelsDestroy (image->pixels);
00271        image->pixels = NULL;
00272     }
00273 
00274     if (image->transform) {
00275        free (image->transform);
00276        image->transform = NULL;
00277     }
00278 
00279     free (image);
00280 }
00281 slim_hidden_def(pixman_image_destroy);
00282 
00283 void
00284 pixman_image_destroyClip (pixman_image_t *image)
00285 {
00286     switch (image->clientClipType) {
00287     case CT_NONE:
00288        return;
00289     case CT_PIXMAP:
00290        pixman_image_destroy (image->clientClip);
00291        break;
00292     default:
00293        pixman_region_destroy (image->clientClip);
00294        break;
00295     }
00296     image->clientClip = NULL;
00297     image->clientClipType = CT_NONE;
00298 }    
00299 
00300 int
00301 pixman_image_set_clip_region (pixman_image_t     *image,
00302                            pixman_region16_t     *region)
00303 {
00304     pixman_image_destroyClip (image);
00305     if (region) {
00306        image->clientClip = pixman_region_create ();
00307        pixman_region_copy (image->clientClip, region);
00308        image->clientClipType = CT_REGION;
00309     }
00310     
00311     if (image->freeCompClip)
00312        pixman_region_destroy (image->pCompositeClip);
00313     image->pCompositeClip = pixman_region_create();
00314     pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
00315                            0, 0, image->pixels->width, image->pixels->height);
00316     image->freeCompClip = 1;
00317     if (region) {
00318        pixman_region_translate (image->pCompositeClip,
00319                              - image->clipOrigin.x,
00320                              - image->clipOrigin.y);
00321        pixman_region_intersect (image->pCompositeClip,
00322                              image->pCompositeClip,
00323                              region);
00324        pixman_region_translate (image->pCompositeClip,
00325                              image->clipOrigin.x,
00326                              image->clipOrigin.y);
00327     }
00328     
00329     image->stateChanges |= CPClipMask;
00330     return 0;
00331 }
00332 
00333 #define BOUND(v)     (int16_t) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
00334 
00335 static __inline int
00336 FbClipImageReg (pixman_region16_t  *region,
00337               pixman_region16_t    *clip,
00338               int           dx,
00339               int           dy)
00340 {
00341     if (pixman_region_num_rects (region) == 1 &&
00342        pixman_region_num_rects (clip) == 1)
00343     {
00344        pixman_box16_t *pRbox = pixman_region_rects (region);
00345        pixman_box16_t *pCbox = pixman_region_rects (clip);
00346        int    v;
00347 
00348        if (pRbox->x1 < (v = pCbox->x1 + dx))
00349            pRbox->x1 = BOUND(v);
00350        if (pRbox->x2 > (v = pCbox->x2 + dx))
00351            pRbox->x2 = BOUND(v);
00352        if (pRbox->y1 < (v = pCbox->y1 + dy))
00353            pRbox->y1 = BOUND(v);
00354        if (pRbox->y2 > (v = pCbox->y2 + dy))
00355            pRbox->y2 = BOUND(v);
00356        if (pRbox->x1 >= pRbox->x2 ||
00357            pRbox->y1 >= pRbox->y2)
00358        {
00359            pixman_region_empty (region);
00360        }
00361     }
00362     else
00363     {
00364        pixman_region_translate (region, dx, dy);
00365        pixman_region_intersect (region, clip, region);
00366        pixman_region_translate (region, -dx, -dy);
00367     }
00368     return 1;
00369 }
00370                 
00371 static __inline int
00372 FbClipImageSrc (pixman_region16_t  *region,
00373               pixman_image_t              *image,
00374               int           dx,
00375               int           dy)
00376 {
00377     /* XXX what to do with clipping from transformed pictures? */
00378     if (image->transform)
00379        return 1;
00380     if (image->repeat)
00381     {
00382        /* XXX no source clipping */
00383        if (image->compositeClipSource &&
00384            image->clientClipType != CT_NONE)
00385        {
00386            pixman_region_translate (region, 
00387                         dx - image->clipOrigin.x,
00388                         dy - image->clipOrigin.y);
00389            pixman_region_intersect (region, image->clientClip, region);
00390            pixman_region_translate (region, 
00391                         - (dx - image->clipOrigin.x),
00392                         - (dy - image->clipOrigin.y));
00393        }
00394        return 1;
00395     }
00396     else
00397     {
00398        pixman_region16_t   *clip;
00399 
00400        if (image->compositeClipSource)
00401            clip = image->pCompositeClip;
00402        else
00403            clip = image->pSourceClip;
00404        return FbClipImageReg (region,
00405                             clip,
00406                             dx,
00407                             dy);
00408     }
00409     return 1;
00410 }
00411 
00412 /* XXX: Need to decide what to do with this
00413 #define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
00414 
00415 #define NEXT_PTR(_type) ((_type) ulist++->ptr)
00416 
00417 int
00418 pixman_image_change (pixman_image_t              *image,
00419               Mask          vmask,
00420               unsigned int  *vlist,
00421               DevUnion             *ulist,
00422               int           *error_value)
00423 {
00424     BITS32           index2;
00425     int                     error = 0;
00426     BITS32           maskQ;
00427     
00428     maskQ = vmask;
00429     while (vmask && !error)
00430     {
00431        index2 = (BITS32) lowbit (vmask);
00432        vmask &= ~index2;
00433        image->stateChanges |= index2;
00434        switch (index2)
00435        {
00436        case CPRepeat:
00437            {
00438               unsigned int  newr;
00439               newr = NEXT_VAL(unsigned int);
00440               if (newr <= xTrue)
00441                   image->repeat = newr;
00442               else
00443               {
00444                   *error_value = newr;
00445                   error = BadValue;
00446               }
00447            }
00448            break;
00449        case CPAlphaMap:
00450            {
00451               pixman_image_t *iAlpha;
00452               
00453               iAlpha = NEXT_PTR(pixman_image_t *);
00454               if (iAlpha)
00455                   iAlpha->refcnt++;
00456               if (image->alphaMap)
00457                   pixman_image_destroy ((void *) image->alphaMap);
00458               image->alphaMap = iAlpha;
00459            }
00460            break;
00461        case CPAlphaXOrigin:
00462            image->alphaOrigin.x = NEXT_VAL(int16_t);
00463            break;
00464        case CPAlphaYOrigin:
00465            image->alphaOrigin.y = NEXT_VAL(int16_t);
00466            break;
00467        case CPClipXOrigin:
00468            image->clipOrigin.x = NEXT_VAL(int16_t);
00469            break;
00470        case CPClipYOrigin:
00471            image->clipOrigin.y = NEXT_VAL(int16_t);
00472            break;
00473        case CPClipMask:
00474            {
00475               pixman_image_t           *mask;
00476               int        clipType;
00477 
00478               mask = NEXT_PTR(pixman_image_t *);
00479               if (mask) {
00480                   clipType = CT_PIXMAP;
00481                   mask->refcnt++;
00482               } else {
00483                   clipType = CT_NONE;
00484               }
00485               error = pixman_image_change_clip (image, clipType,
00486                                       (void *)mask, 0);
00487               break;
00488            }
00489        case CPGraphicsExposure:
00490            {
00491               unsigned int  newe;
00492               newe = NEXT_VAL(unsigned int);
00493               if (newe <= xTrue)
00494                   image->graphicsExposures = newe;
00495               else
00496               {
00497                   *error_value = newe;
00498                   error = BadValue;
00499               }
00500            }
00501            break;
00502        case CPSubwindowMode:
00503            {
00504               unsigned int  news;
00505               news = NEXT_VAL(unsigned int);
00506               if (news == ClipByChildren || news == IncludeInferiors)
00507                   image->subWindowMode = news;
00508               else
00509               {
00510                   *error_value = news;
00511                   error = BadValue;
00512               }
00513            }
00514            break;
00515        case CPPolyEdge:
00516            {
00517               unsigned int  newe;
00518               newe = NEXT_VAL(unsigned int);
00519               if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
00520                   image->polyEdge = newe;
00521               else
00522               {
00523                   *error_value = newe;
00524                   error = BadValue;
00525               }
00526            }
00527            break;
00528        case CPPolyMode:
00529            {
00530               unsigned int  newm;
00531               newm = NEXT_VAL(unsigned int);
00532               if (newm == PolyModePrecise || newm == PolyModeImprecise)
00533                   image->polyMode = newm;
00534               else
00535               {
00536                   *error_value = newm;
00537                   error = BadValue;
00538               }
00539            }
00540            break;
00541        case CPDither:
00542            image->dither = NEXT_VAL(unsigned long);
00543            break;
00544        case CPComponentAlpha:
00545            {
00546               unsigned int  newca;
00547 
00548               newca = NEXT_VAL (unsigned int);
00549               if (newca <= xTrue)
00550                   image->componentAlpha = newca;
00551               else
00552               {
00553                   *error_value = newca;
00554                   error = BadValue;
00555               }
00556            }
00557            break;
00558        default:
00559            *error_value = maskQ;
00560            error = BadValue;
00561            break;
00562        }
00563     }
00564     return error;
00565 }
00566 */
00567 
00568 /* XXX: Do we need this?
00569 int
00570 SetPictureClipRects (PicturePtr    pPicture,
00571                    int      xOrigin,
00572                    int      yOrigin,
00573                    int      nRect,
00574                    xRectangle      *rects)
00575 {
00576     ScreenPtr        pScreen = pPicture->pDrawable->pScreen;
00577     PictureScreenPtr ps = GetPictureScreen(pScreen);
00578     pixman_region16_t              *clientClip;
00579     int                     result;
00580 
00581     clientClip = RECTS_TO_REGION(pScreen,
00582                              nRect, rects, CT_UNSORTED);
00583     if (!clientClip)
00584        return 1;
00585     result =(*ps->ChangePictureClip) (pPicture, CT_REGION, 
00586                                   (void *) clientClip, 0);
00587     if (result == 0)
00588     {
00589        pPicture->clipOrigin.x = xOrigin;
00590        pPicture->clipOrigin.y = yOrigin;
00591        pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
00592        pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
00593     }
00594     return result;
00595 }
00596 */
00597 
00598 int
00599 FbComputeCompositeRegion (pixman_region16_t      *region,
00600                        pixman_image_t     *iSrc,
00601                        pixman_image_t     *iMask,
00602                        pixman_image_t     *iDst,
00603                        int16_t            xSrc,
00604                        int16_t            ySrc,
00605                        int16_t            xMask,
00606                        int16_t            yMask,
00607                        int16_t            xDst,
00608                        int16_t            yDst,
00609                        uint16_t    width,
00610                        uint16_t    height)
00611 {
00612     int              v;
00613     int x1, y1, x2, y2;
00614 
00615     /* XXX: This code previously directly set the extents of the
00616        region here. I need to decide whether removing that has broken
00617        this. Also, it might be necessary to just make the pixman_region16_t
00618        data structure transparent anyway in which case I can just put
00619        the code back. */
00620     x1 = xDst;
00621     v = xDst + width;
00622     x2 = BOUND(v);
00623     y1 = yDst;
00624     v = yDst + height;
00625     y2 = BOUND(v);
00626     /* Check for empty operation */
00627     if (x1 >= x2 ||
00628        y1 >= y2)
00629     {
00630        pixman_region_empty (region);
00631        return 1;
00632     }
00633     /* clip against src */
00634     if (!FbClipImageSrc (region, iSrc, xDst - xSrc, yDst - ySrc))
00635     {
00636        pixman_region_destroy (region);
00637        return 0;
00638     }
00639     if (iSrc->alphaMap)
00640     {
00641        if (!FbClipImageSrc (region, iSrc->alphaMap,
00642                           xDst - (xSrc + iSrc->alphaOrigin.x),
00643                           yDst - (ySrc + iSrc->alphaOrigin.y)))
00644        {
00645            pixman_region_destroy (region);
00646            return 0;
00647        }
00648     }
00649     /* clip against mask */
00650     if (iMask)
00651     {
00652        if (!FbClipImageSrc (region, iMask, xDst - xMask, yDst - yMask))
00653        {
00654            pixman_region_destroy (region);
00655            return 0;
00656        }      
00657        if (iMask->alphaMap)
00658        {
00659            if (!FbClipImageSrc (region, iMask->alphaMap,
00660                              xDst - (xMask + iMask->alphaOrigin.x),
00661                              yDst - (yMask + iMask->alphaOrigin.y)))
00662            {
00663               pixman_region_destroy (region);
00664               return 0;
00665            }
00666        }
00667     }
00668     if (!FbClipImageReg (region, iDst->pCompositeClip, 0, 0))
00669     {
00670        pixman_region_destroy (region);
00671        return 0;
00672     }
00673     if (iDst->alphaMap)
00674     {
00675        if (!FbClipImageReg (region, iDst->alphaMap->pCompositeClip,
00676                           -iDst->alphaOrigin.x,
00677                           -iDst->alphaOrigin.y))
00678        {
00679            pixman_region_destroy (region);
00680            return 0;
00681        }
00682     }
00683     return 1;
00684 }
00685 
00686 int
00687 miIsSolidAlpha (pixman_image_t *src)
00688 {
00689     char      line[1];
00690     
00691     /* Alpha-only */
00692     if (PICT_FORMAT_TYPE (src->format_code) != PICT_TYPE_A)
00693        return 0;
00694     /* repeat */
00695     if (!src->repeat)
00696        return 0;
00697     /* 1x1 */
00698     if (src->pixels->width != 1 || src->pixels->height != 1)
00699        return 0;
00700     line[0] = 1;
00701     /* XXX: For the next line, fb has:
00702        (*pScreen->GetImage) (src->pixels, 0, 0, 1, 1, ZPixmap, ~0L, line);
00703        Is the following simple assignment sufficient?
00704     */
00705     line[0] = src->pixels->data[0];
00706     switch (src->pixels->bpp) {
00707     case 1:
00708        return (uint8_t) line[0] == 1 || (uint8_t) line[0] == 0x80;
00709     case 4:
00710        return (uint8_t) line[0] == 0xf || (uint8_t) line[0] == 0xf0;
00711     case 8:
00712        return (uint8_t) line[0] == 0xff;
00713     default:
00714        return 0;
00715     }
00716 }