gcs.c - sam - An updated version of the sam text editor.
 (HTM) git clone git://vernunftzentrum.de/sam.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
       gcs.c (11581B)
       ---
            1 /* Copyright (c) 1998 Lucent Technologies - All rights reserved. */
            2 #include <u.h>
            3 #include <libg.h>
            4 #include "libgint.h"
            5 
            6 /*
            7  * Libg applications are written assuming that black is ~0
            8  * and white is 0.  Some screens use the reverse convention.
            9  * We get the effect the application desired by seeing what
           10  * happens if both the source and dest are converted to the
           11  * black==~0 convention, and then converting the dest back
           12  * to whatever convention it uses.
           13  *
           14  * Offscreen bitmaps of depth 1 use the black==~0 convention.
           15  *
           16  * Bitmaps of depth > 1 are probably in color.  Libg operations that
           17  * would produce a 1 should produce the foreground color, and
           18  * libg operations that would produce a 0 should produce the background
           19  * color.  Operations that use bitmaps of depth > 1 as source
           20  * should interpret the foreground pixel as "black" (1) and the
           21  * background pixel as "white" (0).  It is hard to make this work,
           22  * but the important cases are Fcodes Zero, F, S, and S^D, so
           23  * we make sure that those work.  When a fill value is given for
           24  * a bitmap of depth > 1, assume ~0 means foreground, but otherwise
           25  * take any other value literally (assume it came from rgbpix).
           26  * This may be wrong for the case of 0, but libg programmers
           27  * usually use Fcode Zero instead of passing 0 with Fcode S.
           28  *
           29  * We assume there are at most two depths of bitmaps: depth 1
           30  * and depth of the screen.
           31  */
           32 
           33 /*
           34  * gx func code corresponding to libg func code when both
           35  * source and dest use 1 for black.  This is a straight translation.
           36  */
           37 static int gx[16] = {
           38     GXclear,        /* Zero */
           39     GXnor,          /* DnorS */
           40     GXandInverted,      /* DandnotS */
           41     GXcopyInverted,     /* notS */
           42     GXandReverse,       /* notDandS */
           43     GXinvert,       /* notD */
           44     GXxor,          /* DxorS */
           45     GXnand,         /* DnandS */
           46     GXand,          /* DandS */
           47     GXequiv,        /* DxnorS */
           48     GXnoop,         /* D */
           49     GXorInverted,       /* DornotS */
           50     GXcopy,         /* S */
           51     GXorReverse,        /* notDorS */
           52     GXor,           /* DorS */
           53     GXset,          /* F */
           54 };
           55 
           56 /*
           57  * gx func code corresponding to libg func code when 0 means black
           58  * in dst and 1 means black in src. These means the table has op'
           59  * where dst <- dst op' src == not ( not(dst)  op  src ).
           60  * The comment on each line is op, in Fcode terms.
           61  */
           62 static int d0s1gx[16] = {
           63     GXset,          /* Zero */
           64     GXorReverse,        /* DnorS */
           65     GXor,           /* DandnotS */
           66     GXcopy,         /* notS */
           67     GXnand,         /* notDandS */
           68     GXinvert,       /* notD */
           69     GXxor,          /* DxorS */
           70     GXandReverse,       /* DnandS */
           71     GXorInverted,       /* DandS */
           72     GXequiv,        /* DxnorS */
           73     GXnoop,         /* D */
           74     GXand,          /* DornotS */
           75     GXcopyInverted,     /* S */
           76     GXnor,          /* notDorS */
           77     GXandInverted,      /* DorS */
           78     GXclear,        /* F */
           79 };
           80 /*
           81  * gx func code corresponding to libg func code when 1 means black
           82  * in dst and 0 means black in src. These means the table has op'
           83  * where dst <- dst op' src == dst  op  not(src) )
           84  * The comment on each line is op, in Fcode terms.
           85  */
           86 static int d1s0gx[16] = {
           87     GXclear,        /* Zero */
           88     GXandReverse,       /* DnorS */
           89     GXand,          /* DandnotS */
           90     GXcopy,         /* notS */
           91     GXnor,          /* notDandS */
           92     GXinvert,       /* notD */
           93     GXequiv,        /* DxorS */
           94     GXorReverse,        /* DnandS */
           95     GXandInverted,      /* DandS */
           96     GXxor,          /* DxnorS */
           97     GXnoop,         /* D */
           98     GXor,           /* DornotS */
           99     GXcopyInverted,     /* S */
          100     GXnand,         /* notDorS */
          101     GXorInverted,       /* DorS */
          102     GXset,          /* F */
          103 };
          104 
          105 /*
          106  * gx func code corresponding to libg func code when 0 means black
          107  * in both the src and the dst. These means the table has op'
          108  * where dst <- dst op' src == not (not(dst)  op  not(src)) )
          109  * The comment on each line is op, in Fcode terms.
          110  */
          111 static int d0s0gx[16] = {
          112     GXset,          /* Zero */
          113     GXnand,         /* DnorS */
          114     GXorInverted,       /* DandnotS */
          115     GXcopyInverted,     /* notS */
          116     GXorReverse,        /* notDandS */
          117     GXinvert,       /* notD */
          118     GXequiv,        /* DxorS */
          119     GXnor,          /* DnandS */
          120     GXor,           /* DandS */
          121     GXxor,          /* DxnorS */
          122     GXnoop,         /* D */
          123     GXandInverted,      /* DornotS */
          124     GXcopy,         /* S */
          125     GXandReverse,       /* notDorS */
          126     GXand,          /* DorS */
          127     GXclear,        /* F */
          128 };
          129 
          130 /*
          131  * 1 for those Fcodes that are degenerate (don't involve src)
          132  */
          133 static int degengc[16] = {
          134     1,          /* Zero */
          135     0,          /* DnorS */
          136     0,          /* DandnotS */
          137     0,          /* notS */
          138     0,          /* notDandS */
          139     1,          /* notD */
          140     0,          /* DxorS */
          141     0,          /* DnandS */
          142     0,          /* DandS */
          143     0,          /* DxnorS */
          144     1,          /* D */
          145     0,          /* DornotS */
          146     0,          /* S */
          147     0,          /* notDorS */
          148     0,          /* DorS */
          149     1,          /* F */
          150 };
          151 
          152 /*
          153  * GCs are all for same screen, and depth is either 1 or screen depth.
          154  * Return a GC for the depth of b, with values as specified by gcv.
          155  *
          156  * Also, set (or unset) the clip rectangle if necessary.
          157  * (This implementation should be improved if setting a clip rectangle is not rare).
          158  */
          159 GC
          160 _getgc(Bitmap *b, uint64_t gcvm, XGCValues *pgcv)
          161 {
          162     static GC gc0, gcn;
          163     static bool clipset = false;
          164     GC g;
          165     XRectangle xr;
          166 
          167     g = (b->ldepth==0)? gc0 : gcn;
          168     if(!g){
          169         g = XCreateGC(_dpy, (Drawable)b->id, gcvm, pgcv);
          170         if(b->ldepth==0)
          171             gc0 = g;
          172         else
          173             gcn = g;
          174     } else
          175         XChangeGC(_dpy, g, gcvm, pgcv);
          176     if(b->flag&CLIP){
          177         xr.x = b->clipr.min.x;
          178         xr.y = b->clipr.min.y;
          179         xr.width = Dx(b->clipr);
          180         xr.height = Dy(b->clipr);
          181         if(b->flag&SHIFT){
          182             xr.x -= b->r.min.x;
          183             xr.y -= b->r.min.y;
          184         }
          185         XSetClipRectangles(_dpy, g, 0, 0, &xr, 1, YXBanded);
          186         clipset = true;
          187     }else if(clipset){
          188         pgcv->clip_mask = None;
          189         XChangeGC(_dpy, g, GCClipMask, pgcv);
          190         clipset = false;
          191     }
          192     return g;
          193 }
          194 
          195 /*
          196  * Return a GC that will fill bitmap b using a pixel value v and Fcode f.
          197  * Pixel value v is according to libg convention, so 0 means
          198  * white (or background) and ~0 means black (or foreground).
          199  */
          200 GC
          201 _getfillgc(Fcode f, Bitmap *b, uint64_t val)
          202 {
          203     return _getfillgc2(f, b, val, _fgpixel, _bgpixel);
          204 }
          205 
          206 GC
          207 _getfillgc2(Fcode f, Bitmap *b, uint64_t val, uint64_t fg, uint64_t bg)
          208 {
          209     int xf, m;
          210     uint64_t v, spix, vmax;
          211     XGCValues gcv;
          212 
          213     f &= F;
          214     vmax = _ld2dmask[b->ldepth];
          215     v = val & vmax;
          216     spix = v;
          217     xf = GXcopy;
          218     m = b->flag;
          219     if(m & DP1){
          220         xf = (m&BL1)? gx[f] : d0s1gx[f];
          221     }else{
          222         switch(f){
          223         case Zero:
          224         labZero:
          225             spix = bg;
          226             break;
          227         case F:
          228         labF:
          229             spix = fg;
          230             break;
          231         case D:
          232         labD:
          233             xf = GXnoop;
          234             break;
          235         case notD:
          236         labnotD:
          237             xf = GXxor;
          238             spix = fg^bg;
          239             break;
          240         case S:
          241             if(val == ~0)
          242                 spix = fg;
          243             else
          244                 spix = v;
          245             break;
          246         case notS:
          247             if(val == ~0)
          248                 spix = bg;
          249             else
          250                 spix = v;
          251             break;
          252         case DxorS:
          253             xf = GXxor;
          254             if(val == ~0)
          255                 spix = fg^bg;
          256             else
          257                 spix = v;
          258             break;
          259         case DxnorS:
          260             xf = GXxor;
          261             if(val == 0)
          262                 spix = fg^bg;
          263             else
          264                 spix = v;
          265             break;
          266         default:
          267             /* hard to do anything other than v==0 or v==~0 case */
          268             if(v < vmax-v){
          269                 /* v is closer to 0 than vmax */
          270                 switch(f&~S){
          271                 case D&~S:  goto labD;
          272                 case notD&~S:   goto labnotD;
          273                 case Zero&~S:   goto labZero;
          274                 case F&~S:  goto labF;
          275                 }
          276             }else{
          277                 /* v is closer to vmax than 0 */
          278                 switch(f&S){
          279                 case D&S:   goto labD;
          280                 case notD&S:    goto labnotD;
          281                 case Zero&S:    goto labZero;
          282                 case F&S:   goto labF;
          283                 }
          284             }
          285             
          286         }
          287     }
          288     gcv.foreground = spix;
          289     gcv.function = xf;
          290     return _getgc(b, GCForeground|GCFunction, &gcv);
          291 }
          292 
          293 /*
          294  * Return a GC to be used to copy an area from bitmap sb to
          295  * bitmap db.  Sometimes the calling function shouldn't use
          296  * XCopyArea, but instead should use XCopyPlane or XFillRectangle.
          297  * The *bltfunc arg is set to one of UseCopyArea, UseCopyPlane,
          298  * UseFillRectangle.
          299  */
          300 GC
          301 _getcopygc(Fcode f, Bitmap *db, Bitmap *sb, int *bltfunc)
          302 {
          303     return _getcopygc2(f, db, sb, bltfunc, _fgpixel, _bgpixel);
          304 }
          305 
          306 GC
          307 _getcopygc2(Fcode f, Bitmap *db, Bitmap *sb, int *bltfunc, uint64_t fg, uint64_t bg)
          308 {
          309     uint64_t spix, df, sf;
          310     int xf, c;
          311     XGCValues gcv;
          312     uint64_t gcvm;
          313 
          314     spix = xf = 0;
          315     f &= F;
          316     gcvm = 0;
          317     df = db->flag;
          318     if(degengc[f]){
          319         *bltfunc = UseFillRectangle;
          320         if(df&SCR || !(df&DP1)){
          321             // nothing XXX
          322         }else{
          323             /* must be DP1 and BL1 */
          324             fg = 1;
          325             bg = 0;
          326         }
          327         switch(f){
          328         case Zero:
          329             xf = GXcopy;
          330             spix = bg;
          331             break;
          332         case F:
          333             xf = GXcopy;
          334             spix = fg;
          335             break;
          336         case D:
          337             xf = GXnoop;
          338             spix = fg;
          339             break;
          340         case notD:
          341             xf = GXxor;
          342             spix = fg^bg;
          343             break;
          344         default:
          345             /* ignored */
          346             break;
          347         }
          348         gcv.function = xf;
          349         gcv.foreground = spix;
          350         gcvm = GCFunction|GCForeground;
          351     }else{
          352         /* src is involved in f */
          353 
          354 #define code(f1,f2) ((((f1)&(DP1|BL1))<<2)|((f2)&(DP1|BL1)))
          355 
          356         sf = sb->flag;
          357         c = code(df,sf);
          358         *bltfunc = UseCopyArea;
          359         switch(code(df,sf)){
          360         case code(DP1|BL1,DP1|BL1):
          361         case code(BL1,BL1):
          362             xf = gx[f];
          363             break;
          364         case code(DP1|BL1,DP1):
          365             xf = d1s0gx[f];
          366             break;
          367         case code(DP1,DP1|BL1):
          368             xf = d0s1gx[f];
          369             break;
          370         case code(DP1,DP1):
          371         case code(0,0):
          372             xf = d0s0gx[f];
          373             break;
          374         default:
          375             /*
          376              * One bitmap has depth 1, the other has screen depth.
          377              * We know the bitmap must have BL1.
          378              * CopyPlane must be used; it won't really work
          379              * for more than fcode==S.
          380              */
          381 
          382             *bltfunc = UseCopyPlane;
          383             xf = GXcopy;
          384             switch(c){
          385 
          386             case code(0,DP1|BL1):
          387             case code(BL1,DP1|BL1):
          388                 // nothing XXX
          389                 break;
          390             case code(DP1|BL1,0):
          391                 fg = 0;
          392                 bg = 1;
          393                 break;
          394             case code(DP1|BL1,BL1):
          395                 fg = 1;
          396                 bg = 0;
          397                 break;
          398             default:
          399                 berror("bad combination of copy bitmaps");
          400             }
          401             gcv.foreground = fg;
          402             gcv.background = bg;
          403             gcvm |= GCForeground|GCBackground;
          404         }
          405         gcv.function = xf;
          406         gcvm |= GCFunction;
          407     
          408 #undef code
          409     }
          410 
          411     return _getgc(db, gcvm, &gcv);
          412 }