Logo Search packages:      
Sourcecode: sam version File versions  Download package

gcs.c

/* Copyright (c) 1992 AT&T - All rights reserved. */
#include <libc.h>
#include <libg.h>
#include "libgint.h"

/*
 * Libg applications are written assuming that black is ~0
 * and white is 0.  Some screens use the reverse convention.
 * We get the effect the application desired by seeing what
 * happens if both the source and dest are converted to the
 * black==~0 convention, and then converting the dest back
 * to whatever convention it uses.
 *
 * Offscreen bitmaps of depth 1 use the black==~0 convention.
 *
 * Bitmaps of depth > 1 are probably in color.  Libg operations that
 * would produce a 1 should produce the foreground color, and
 * libg operations that would produce a 0 should produce the background
 * color.  Operations that use bitmaps of depth > 1 as source
 * should interpret the foreground pixel as "black" (1) and the
 * background pixel as "white" (0).  It is hard to make this work,
 * but the important cases are Fcodes Zero, F, S, and S^D, so
 * we make sure that those work.  When a fill value is given for
 * a bitmap of depth > 1, assume ~0 means foreground, but otherwise
 * take any other value literally (assume it came from rgbpix).
 * This may be wrong for the case of 0, but libg programmers
 * usually use Fcode Zero instead of passing 0 with Fcode S.
 *
 * We assume there are at most two depths of bitmaps: depth 1
 * and depth of the screen.
 */

/*
 * gx func code corresponding to libg func code when both
 * source and dest use 1 for black.  This is a straight translation.
 */
static int gx[16] = {
      GXclear,          /* Zero */
      GXnor,                  /* DnorS */
      GXandInverted,          /* DandnotS */
      GXcopyInverted,         /* notS */
      GXandReverse,           /* notDandS */
      GXinvert,         /* notD */
      GXxor,                  /* DxorS */
      GXnand,                 /* DnandS */
      GXand,                  /* DandS */
      GXequiv,          /* DxnorS */
      GXnoop,                 /* D */
      GXorInverted,           /* DornotS */
      GXcopy,                 /* S */
      GXorReverse,            /* notDorS */
      GXor,             /* DorS */
      GXset,                  /* F */
};

/*
 * gx func code corresponding to libg func code when 0 means black
 * in dst and 1 means black in src. These means the table has op'
 * where dst <- dst op' src == not ( not(dst)  op  src ).
 * The comment on each line is op, in Fcode terms.
 */
static int d0s1gx[16] = {
      GXset,                  /* Zero */
      GXorReverse,            /* DnorS */
      GXor,             /* DandnotS */
      GXcopy,                 /* notS */
      GXnand,                 /* notDandS */
      GXinvert,         /* notD */
      GXxor,                  /* DxorS */
      GXandReverse,           /* DnandS */
      GXorInverted,           /* DandS */
      GXequiv,          /* DxnorS */
      GXnoop,                 /* D */
      GXand,                  /* DornotS */
      GXcopyInverted,         /* S */
      GXnor,                  /* notDorS */
      GXandInverted,          /* DorS */
      GXclear,          /* F */
};
/*
 * gx func code corresponding to libg func code when 1 means black
 * in dst and 0 means black in src. These means the table has op'
 * where dst <- dst op' src == dst  op  not(src) )
 * The comment on each line is op, in Fcode terms.
 */
static int d1s0gx[16] = {
      GXclear,          /* Zero */
      GXandReverse,           /* DnorS */
      GXand,                  /* DandnotS */
      GXcopy,                 /* notS */
      GXnor,                  /* notDandS */
      GXinvert,         /* notD */
      GXequiv,          /* DxorS */
      GXorReverse,            /* DnandS */
      GXandInverted,          /* DandS */
      GXxor,                  /* DxnorS */
      GXnoop,                 /* D */
      GXor,             /* DornotS */
      GXcopyInverted,         /* S */
      GXnand,                 /* notDorS */
      GXorInverted,           /* DorS */
      GXset,                  /* F */
};

/*
 * gx func code corresponding to libg func code when 0 means black
 * in both the src and the dst. These means the table has op'
 * where dst <- dst op' src == not (not(dst)  op  not(src)) )
 * The comment on each line is op, in Fcode terms.
 */
static int d0s0gx[16] = {
      GXset,                  /* Zero */
      GXnand,                 /* DnorS */
      GXorInverted,           /* DandnotS */
      GXcopyInverted,         /* notS */
      GXorReverse,            /* notDandS */
      GXinvert,         /* notD */
      GXequiv,          /* DxorS */
      GXnor,                  /* DnandS */
      GXor,             /* DandS */
      GXxor,                  /* DxnorS */
      GXnoop,                 /* D */
      GXandInverted,          /* DornotS */
      GXcopy,                 /* S */
      GXandReverse,           /* notDorS */
      GXand,                  /* DorS */
      GXclear,          /* F */
};

/*
 * 1 for those Fcodes that are degenerate (don't involve src)
 */
static int degengc[16] = {
      1,                /* Zero */
      0,                /* DnorS */
      0,                /* DandnotS */
      0,                /* notS */
      0,                /* notDandS */
      1,                /* notD */
      0,                /* DxorS */
      0,                /* DnandS */
      0,                /* DandS */
      0,                /* DxnorS */
      1,                /* D */
      0,                /* DornotS */
      0,                /* S */
      0,                /* notDorS */
      0,                /* DorS */
      1,                /* F */
};

/*
 * GCs are all for same screen, and depth is either 1 or screen depth.
 * Return a GC for the depth of b, with values as specified by gcv.
 *
 * Also, set (or unset) the clip rectangle if necessary.
 * (This implementation should be improved if setting a clip rectangle is not rare).
 */
GC
_getgc(Bitmap *b, unsigned long gcvm, XGCValues *pgcv)
{
      static GC gc0, gcn;
      static clipset = 0;
      GC g;
      XRectangle xr;

      g = (b->ldepth==0)? gc0 : gcn;
      if(!g){
            g = XCreateGC(_dpy, (Drawable)b->id, gcvm, pgcv);
            if(b->ldepth==0)
                  gc0 = g;
            else
                  gcn = g;
      } else
            XChangeGC(_dpy, g, gcvm, pgcv);
      if(b->flag&CLIP){
            xr.x = b->clipr.min.x;
            xr.y = b->clipr.min.y;
            xr.width = Dx(b->clipr);
            xr.height = Dy(b->clipr);
            if(b->flag&SHIFT){
                  xr.x -= b->r.min.x;
                  xr.y -= b->r.min.y;
            }
            XSetClipRectangles(_dpy, g, 0, 0, &xr, 1, YXBanded);
            clipset = 1;
      }else if(clipset){
            pgcv->clip_mask = None;
            XChangeGC(_dpy, g, GCClipMask, pgcv);
            clipset = 0;
      }
      return g;
}

/*
 * Return a GC that will fill bitmap b using a pixel value v and Fcode f.
 * Pixel value v is according to libg convention, so 0 means
 * white (or background) and ~0 means black (or foreground).
 */
GC
_getfillgc(Fcode f, Bitmap *b, unsigned long val)
{
      int xf, m;
      unsigned long v, fg, bg, spix, vmax;
      XGCValues gcv;

      f &= F;
      vmax = _ld2dmask[b->ldepth];
      v = val & vmax;
      spix = v;
      xf = GXcopy;
      m = b->flag;
      if(m & DP1){
            xf = (m&BL1)? gx[f] : d0s1gx[f];
      }else{
            fg = _fgpixel;
            bg = _bgpixel;
            switch(f){
            case Zero:
          labZero:
                  spix = bg;
                  break;
            case F:
          labF:
                  spix = fg;
                  break;
            case D:
          labD:
                  xf = GXnoop;
                  break;
            case notD:
          labnotD:
                  xf = GXxor;
                  spix = fg^bg;
                  break;
            case S:
                  if(val == ~0)
                        spix = fg;
                  else
                        spix = v;
                  break;
            case notS:
                  if(val == ~0)
                        spix = bg;
                  else
                        spix = v;
                  break;
            case DxorS:
                  xf = GXxor;
                  if(val == ~0)
                        spix = fg^bg;
                  else
                        spix = v;
                  break;
            case DxnorS:
                  xf = GXxor;
                  if(val == 0)
                        spix = fg^bg;
                  else
                        spix = v;
                  break;
            default:
                  /* hard to do anything other than v==0 or v==~0 case */
                  if(v < vmax-v){
                        /* v is closer to 0 than vmax */
                        switch(f&~S){
                        case D&~S:  goto labD;
                        case notD&~S:     goto labnotD;
                        case Zero&~S:     goto labZero;
                        case F&~S:  goto labF;
                        }
                  }else{
                        /* v is closer to vmax than 0 */
                        switch(f&S){
                        case D&S:   goto labD;
                        case notD&S:      goto labnotD;
                        case Zero&S:      goto labZero;
                        case F&S:   goto labF;
                        }
                  }
                  
            }
      }
      gcv.foreground = spix;
      gcv.function = xf;
      return _getgc(b, GCForeground|GCFunction, &gcv);
}

/*
 * Return a GC to be used to copy an area from bitmap sb to
 * bitmap db.  Sometimes the calling function shouldn't use
 * XCopyArea, but instead should use XCopyPlane or XFillRectangle.
 * The *bltfunc arg is set to one of UseCopyArea, UseCopyPlane,
 * UseFillRectangle.
 */
GC
_getcopygc(Fcode f, Bitmap *db, Bitmap *sb, int *bltfunc)
{
      unsigned long spix, bg, fg, df, sf;
      int xf, c;
      XGCValues gcv;
      unsigned long gcvm;

      f &= F;
      gcvm = 0;
      df = db->flag;
      if(degengc[f]){
            *bltfunc = UseFillRectangle;
            if(df&SCR || !(df&DP1)){
                  fg = _fgpixel;
                  bg = _bgpixel;
            }else{
                  /* must be DP1 and BL1 */
                  fg = 1;
                  bg = 0;
            }
            switch(f){
            case Zero:
                  xf = GXcopy;
                  spix = bg;
                  break;
            case F:
                  xf = GXcopy;
                  spix = fg;
                  break;
            case D:
                  xf = GXnoop;
                  spix = fg;
                  break;
            case notD:
                  xf = GXxor;
                  spix = fg^bg;
                  break;
            }
            gcv.function = xf;
            gcv.foreground = spix;
            gcvm = GCFunction|GCForeground;
      }else{
            /* src is involved in f */

#define code(f1,f2) ((((f1)&(DP1|BL1))<<2)|((f2)&(DP1|BL1)))

            sf = sb->flag;
            c = code(df,sf);
            *bltfunc = UseCopyArea;
            switch(code(df,sf)){
            case code(DP1|BL1,DP1|BL1):
            case code(BL1,BL1):
                  xf = gx[f];
                  break;
            case code(DP1|BL1,DP1):
                  xf = d1s0gx[f];
                  break;
            case code(DP1,DP1|BL1):
                  xf = d0s1gx[f];
                  break;
            case code(DP1,DP1):
            case code(0,0):
                  xf = d0s0gx[f];
                  break;
            default:
                  /*
                   * One bitmap has depth 1, the other has screen depth.
                   * We know the bitmap must have BL1.
                   * CopyPlane must be used; it won't really work
                   * for more than fcode==S.
                   */

                  *bltfunc = UseCopyPlane;
                  xf = GXcopy;
                  switch(c){

                  case code(0,DP1|BL1):
                  case code(BL1,DP1|BL1):
                        fg = _fgpixel;
                        bg = _bgpixel;
                        break;
                  case code(DP1|BL1,0):
                        fg = 0;
                        bg = 1;
                        break;
                  case code(DP1|BL1,BL1):
                        fg = 1;
                        bg = 0;
                        break;
                  default:
                        berror("bad combination of copy bitmaps");
                  }
                  gcv.foreground = fg;
                  gcv.background = bg;
                  gcvm |= GCForeground|GCBackground;
            }
            gcv.function = xf;
            gcvm |= GCFunction;
      
#undef code
      }

      return _getgc(db, gcvm, &gcv);
}

Generated by  Doxygen 1.6.0   Back to index