[q-lang-cvs] q/modules/ggi draw_line.c,NONE,1.1 ggilib.c,NONE,1.1 ggilib.h,NONE,1.1 Makefile.am,1.3,
Brought to you by:
agraef
Update of /cvsroot/q-lang/q/modules/ggi In directory sc8-pr-cvs1:/tmp/cvs-serv23691/modules/ggi Modified Files: Makefile.am Makefile.mingw README-GGI ggi.c ggi.q Added Files: draw_line.c ggilib.c ggilib.h Log Message: major overhaul of GGI interface; see ChangeLog for details --- NEW FILE: draw_line.c --- /* line clipping algorithm, pilfered from GGI sources ************************/ /* $Id: draw_line.c,v 1.1 2003/12/23 01:15:02 agraef Exp $ ****************************************************************************** Graphics library for GGI. Copyright (C) 1998 Alexander Larsson [al...@ly...] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************** */ #include <ggi/internal/ggi-dl.h> /* This is a line-clipper using the algorithm by cohen-sutherland. It is modified to do pixel-perfect clipping. This means that it will generate the same endpoints that would be drawn if an ordinary bresenham line-drawer where used and only visible pixels drawn. It can be used with a bresenham-like linedrawer if it is modified to start with a correct error-term. */ #define OC_LEFT 1 #define OC_RIGHT 2 #define OC_TOP 4 #define OC_BOTTOM 8 /* Outcodes: +-> x | | | V 0101 | 0100 | 0110 y --------------------- 0001 | 0000 | 0010 --------------------- 1001 | 1000 | 1010 | | */ #define outcode(code, xx, yy) \ {\ code = 0;\ if ((xx)<(LIBGGI_GC(vis)->cliptl.x))\ code |= OC_LEFT;\ else if ((xx)>=(LIBGGI_GC(vis)->clipbr.x))\ code |= OC_RIGHT;\ if ((yy)<(LIBGGI_GC(vis)->cliptl.y))\ code |= OC_TOP;\ else if ((yy)>=(LIBGGI_GC(vis)->clipbr.y))\ code |= OC_BOTTOM;\ } /* Calculates |_ a/b _| with mathematically correct floor */ static int FloorDiv(int a, int b) { int _floor; if (b>0) { if (a>0) { return a /b; } else { _floor = -((-a)/b); if ((-a)%b != 0) _floor--; } return _floor; } else { if (a>0) { _floor = -(a/(-b)); if (a%(-b) != 0) _floor--; return _floor; } else { return (-a)/(-b); } } } /* Calculates |^ a/b ^| with mathamatically correct floor */ static int CeilDiv(int a,int b) { if (b>0) return FloorDiv(a-1,b)+1; else return FloorDiv(-a-1,-b)+1; } static int _ggi_clip2d(ggi_visual *vis,int *_x0, int *_y0, int *_x1, int *_y1, int *clip_first, int *clip_last) { int first,last, code; int x0,y0,x1,y1; int x,y; int dx,dy; int xmajor; int slope; *clip_first = first = 0; *clip_last = last = 0; outcode(first,*_x0,*_y0); outcode(last,*_x1,*_y1); if ((first | last) == 0) { return 1; /* Trivially accepted! */ } if ((first & last) != 0) { return 0; /* Trivially rejected! */ } x0=*_x0; y0=*_y0; x1=*_x1; y1=*_y1; dx = x1 - x0; dy = y1 - y0; xmajor = (abs(dx) > abs(dy)); slope = ((dx>=0) && (dy>=0)) || ((dx<0) && (dy<0)); for (;;) { code = first; if (first==0) code = last; if (code&OC_LEFT) { x = LIBGGI_GC(vis)->cliptl.x; if (xmajor) { y = *_y0 + FloorDiv(dy*(x - *_x0)*2 + dx, 2*dx); } else { if (slope) { y = *_y0 + CeilDiv(dy*((x - *_x0)*2 - 1), 2*dx); } else { y = *_y0 + FloorDiv(dy*((x - *_x0)*2 - 1), 2*dx); } } } else if (code&OC_RIGHT) { x = LIBGGI_GC(vis)->clipbr.x - 1; if (xmajor) { y = *_y0 + FloorDiv(dy*(x - *_x0)*2 + dx, 2*dx); } else { if (slope) { y = *_y0 + CeilDiv(dy*((x - *_x0)*2 + 1), 2*dx)-1; } else { y = *_y0 + FloorDiv(dy*((x - *_x0)*2 + 1), 2*dx)+1; } } } else if (code&OC_TOP) { y = LIBGGI_GC(vis)->cliptl.y; if (xmajor) { if (slope) { x = *_x0 + CeilDiv(dx*((y - *_y0)*2 - 1), 2*dy); } else { x = *_x0 + FloorDiv(dx*((y - *_y0)*2 - 1), 2*dy); } } else { x = *_x0 + FloorDiv( dx*(y - *_y0)*2 + dy, 2*dy); } } else { /* OC_BOTTOM */ y = LIBGGI_GC(vis)->clipbr.y - 1; if (xmajor) { if (slope) { x = *_x0 + CeilDiv(dx*((y - *_y0)*2 + 1), 2*dy)-1; } else { x = *_x0 + FloorDiv(dx*((y - *_y0)*2 + 1), 2*dy)+1; } } else { x = *_x0 + FloorDiv(dx*(y - *_y0)*2 + dy, 2*dy); } } if (first!=0) { x0 = x; y0 = y; outcode(first,x0,y0); *clip_first = 1; } else { x1 = x; y1 = y; last = code; outcode(last,x1,y1); *clip_last = 1; } if ((first & last) != 0) { return 0; /* Trivially rejected! */ } if ((first | last) == 0) { *_x0=x0; *_y0=y0; *_x1=x1; *_y1=y1; return 1; /* Trivially accepted! */ } } } /* line drawing algorithm from GGI sources, slightly modified for Q-GGI ******/ /* $Id: draw_line.c,v 1.1 2003/12/23 01:15:02 agraef Exp $ ****************************************************************************** Graphics library for GGI. Copyright (C) 1995 Andreas Beck [be...@gg...] Copyright (C) 1997 Jason McMullan [jm...@gg...] Copyright (C) 1998 Alexander Larsson [al...@ly...] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************** */ typedef struct { ggi_visual_t vis; } visual_t; extern int draw_box(visual_t *v, int x, int y, int w, int h); static inline int DrawHLine(visual_t *v, int x, int y, int w) { return (draw_box(v,x,y,w,1) >= 0)?0:-1; } static inline int DrawVLine(visual_t *v, int x, int y, int h) { return (draw_box(v,x,y,1,h) >= 0)?0:-1; } static inline int DrawPixel(visual_t *v, int x, int y) { return (draw_box(v,x,y,1,1) >= 0)?0:-1; } int draw_line(visual_t *v, int orig_x1, int orig_y1, int orig_x2, int orig_y2) { ggi_visual *vis = v->vis; int orig_dx, orig_dy, sx, sy; int dx,dy; int i; int x1, y1, x2, y2; int clip_first, clip_last; x1 = orig_x1; y1 = orig_y1; x2 = orig_x2; y2 = orig_y2; /* clip x1,y1 and x2,y2. Set clip_first and clip_last if clipped */ if (!_ggi_clip2d(vis, &x1,&y1,&x2,&y2,&clip_first,&clip_last)) { return 0; /* Clipped */ } dy = y2 - y1; orig_dy = orig_y2 - orig_y1; sy = 1; if (orig_dy < 0) { orig_dy = -orig_dy; dy = -dy; sy = -1; } dx = x2-x1; orig_dx = orig_x2 - orig_x1; sx = 1; if (orig_dx < 0) { sx = -1; orig_dx = -orig_dx; dx = -dx; } if (dx == 0) { return (sy>0) ? DrawVLine(v,x1,y1,dy+1) : DrawVLine(v,x2,y2,dy+1); } if (dy == 0) { return (sx>0) ? DrawHLine(v,x1,y1,dx+1) : DrawHLine(v,x2,y2,dx+1); } if (orig_dx == orig_dy) { for (i=dx; i >= 0; i--) { DrawPixel(v, x1, y1); x1 += sx; y1 += sy; } return 0; } if (orig_dx >= orig_dy) { /* x major */ int runlen,adjup,adjdown,e,len; int firstlen,lastlen; runlen = orig_dx/orig_dy; adjup = orig_dx%orig_dy; lastlen = firstlen = (runlen>>1) + 1; if (clip_first) { /* clipped, Adjust firstlen */ int clip_dx = abs(x1 - orig_x1); int clip_dy = abs(y1 - orig_y1); int d = (2*clip_dy+1)*orig_dx; firstlen = d/(2*orig_dy) - clip_dx + 1; e = d%(2*orig_dy); if ((e==0) && (sy>0)) { /* Special case, arbitrary choise. Select lower pixel.(?) */ firstlen--; e += 2*orig_dy; } e -= (orig_dy*2); } else { /* Not clipped, calculate start error term */ e = adjup - (orig_dy<<1); /* initial errorterm == half a step */ if ((runlen&1) != 0) { e += orig_dy; } } if (clip_last) { /* Last endpoint clipped */ int clip_dx = abs(x2 - orig_x2); int clip_dy = abs(y2 - orig_y2); int d = (1+2*clip_dy)*orig_dx; lastlen = d/(2*orig_dy) - clip_dx + 1; if ((sy<0) && ((d%(2*orig_dy))==0)) { /* special arbitrary case */ lastlen--; } } adjup <<= 1; adjdown = orig_dy<<1; if (sy>0) { /* line goes down */ if ((adjup==0) && ((runlen&1)==0) && (!clip_first)) { firstlen--; } if (sx>0) { /* line goes right */ DrawHLine(v,x1,y1,firstlen); x1 += firstlen; y1 ++; for (i=dy-1; i>0; i--) { len = runlen; e += adjup; if (e>0) { len++; e -= adjdown; } DrawHLine(v,x1,y1,len); x1 += len; y1++; } DrawHLine(v,x1,y1,lastlen); return 0; } else { /* line goes left */ x1++; /* because ggiDrawHLine draws right */ x1 -= firstlen; DrawHLine(v,x1,y1,firstlen); y1++; for (i=dy-1; i>0; i--) { len = runlen; e += adjup; if (e>0) { len++; e -= adjdown; } x1 -= len; DrawHLine(v,x1,y1,len); y1 ++; } x1 -= lastlen; DrawHLine(v,x1,y1,lastlen); return 0; } } else { /* line goes up */ if ((adjup==0) && ((runlen&1)==0) && (!clip_last)) { lastlen--; } if (sx>0) { /* line goes right */ DrawHLine(v,x1,y1,firstlen); x1 += firstlen; y1--; for (i=dy-1; i>0; i--) { len = runlen; e += adjup; if (e>=0) { len++; e -= adjdown; } DrawHLine(v,x1,y1,len); x1 += len; y1--; } DrawHLine(v,x1,y1,lastlen); return 0; } else { /* line goes left */ x1++; /* because ggiDrawHLine draws right */ x1 -= firstlen; DrawHLine(v,x1,y1,firstlen); y1--; for (i=dy-1; i>0; i--) { len = runlen; e += adjup; if (e>=0) { len++; e -= adjdown; } x1 -= len; DrawHLine(v,x1,y1,len); y1--; } x1 -= lastlen; DrawHLine(v,x1,y1,lastlen); return 0; } } } else { /* y major */ int runlen,adjup,adjdown,e,len; int firstlen,lastlen; runlen = orig_dy/orig_dx; adjup = orig_dy%orig_dx; lastlen = firstlen = (runlen>>1) + 1; if (clip_first) { /* clipped, Adjust firstlen */ int clip_dx = abs(x1 - orig_x1); int clip_dy = abs(y1 - orig_y1); int d = (2*clip_dx+1)*orig_dy; firstlen = d/(2*orig_dx) - clip_dy + 1; e = d%(2*orig_dx); if ((e==0) && (sx>0)) { /* Special case, arbitrary choise. Select lower pixel.(?) */ firstlen--; e += 2*orig_dx; } e -= (orig_dx*2); } else { /* Not clipped, calculate start error term */ e = adjup - (orig_dx<<1); /* initial errorterm == half a step */ if ((runlen&1) != 0) { e += orig_dx; } } if (clip_last) { /* Last endpoint clipped */ int clip_dx = abs(x2 - orig_x2); int clip_dy = abs(y2 - orig_y2); int d = (1+2*clip_dx)*orig_dy; lastlen = d/(2*orig_dx) - clip_dy + 1; if ((sx<0) && ((d%(2*orig_dx))==0)) { /* special arbitrary case */ lastlen--; } } adjup <<= 1; adjdown = orig_dx<<1; if (sy>0) { /* Line goes DOWN */ if (sx>0) { /* line goes RIGHT */ if ((adjup==0) && ((runlen&1)==0) && (!clip_first)) { firstlen--; } DrawVLine(v,x1,y1,firstlen); y1 += firstlen; x1++; for (i=dx-1; i>0; i--) { len = runlen; e += adjup; if (e>0) { len++; e -= adjdown; } DrawVLine(v,x1,y1,len); y1 += len; x1++; } DrawVLine(v,x1,y1,lastlen); return 0; } else { /* line goes LEFT */ if ((adjup==0) && ((runlen&1)==0) && (!clip_last)) { lastlen--; } DrawVLine(v,x1,y1,firstlen); y1 += firstlen; x1--; for (i=dx-1; i>0; i--) { len = runlen; e += adjup; if (e>=0) { len++; e -= adjdown; } DrawVLine(v,x1,y1,len); y1 += len; x1--; } DrawVLine(v,x1,y1,lastlen); return 0; } } else { /* Line goes UP */ y1++; if (sx>0) { /* line goes RIGHT */ if ((adjup==0) && ((runlen&1)==0) && (!clip_first)) { firstlen--; } y1 -= firstlen; DrawVLine(v,x1,y1,firstlen); x1++; for (i=dx-1; i>0; i--) { len = runlen; e += adjup; if (e>0) { len++; e -= adjdown; } y1 -= len; DrawVLine(v,x1,y1,len); x1++; } y1 -= lastlen; DrawVLine(v,x1,y1,lastlen); return 0; } else { /* line goes LEFT */ if ((adjup==0) && ((runlen&1)==0) && (!clip_last)) { lastlen--; } y1 -= firstlen; DrawVLine(v,x1,y1,firstlen); x1--; for (i=dx-1; i>0; i--) { len = runlen; e += adjup; if (e>=0) { len++; e -= adjdown; } y1 -= len; DrawVLine(v,x1,y1,len); x1--; } y1 -= lastlen; DrawVLine(v,x1,y1,lastlen); return 0; } } } } /*****************************************************************************/ --- NEW FILE: ggilib.c --- /* This file is part of the Q programming system. The Q programming system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. The Q programming system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <limits.h> #include "ggilib.h" typedef struct { ggi_visual_t vis; void *abuf; unsigned char asz; unsigned short afg, abg; int stride, lines; } visual_t; /* calculate the size of a pixel pack */ static inline int pack_size(ggi_visual_t vis, int n) { int bpp, r; ggi_mode m; if (ggiGetMode(vis, &m)) return -1; bpp = GT_SIZE(m.graphtype); if (n > INT_MAX / bpp) return -1; r = ((bpp*n)%8>0)?1:0; return (bpp*n)/8+r; } /* clear clip area of alpha buffer */ int clear_alpha_buffer(void *_v) { visual_t *v = (visual_t*)_v; int x1, y1, x2, y2; if (ggiGetGCClipping(v->vis, &x1, &y1, &x2, &y2)) return -1; if (v->asz == 1) { unsigned char *abuf = (unsigned char*)v->abuf; int i, y; for (i = y1*v->stride+x1, y = y1; y < y2; y++, i += v->stride) memset(abuf+i, v->abg, x2-x1); } else { unsigned short *abuf = (unsigned short*)v->abuf; int i, j, x, y; for (i = y1*v->stride+x1, y = y1; y < y2; y++, i += v->stride) for (j = i, x = x1; x < x2; x++, j++) abuf[j] = v->abg; } return 0; } /* set alpha values, with clipping */ int set_alpha_box(void *_v, int x, int y, int w, int h, ggi_color *c) { visual_t *v = (visual_t*)_v; int x1, y1, x2, y2; int i, j, k, xx, yy; if (ggiGetGCClipping(v->vis, &x1, &y1, &x2, &y2)) return -1; if (v->asz == 1) { unsigned char *abuf = (unsigned char*)v->abuf; /* FIXME: optimize me! */ for (k = 0, i = y*v->stride+x, yy = y; yy < y+h; yy++, i += v->stride) for (j = i, xx = x; xx < x+w; xx++, j++, k++) if (xx >= x1 && xx < x2 && yy >= y1 && yy < y2) abuf[j] = c[k].a/0x101; } else { unsigned short *abuf = (unsigned short*)v->abuf; /* FIXME: optimize me! */ for (k = 0, i = y*v->stride+x, yy = y; yy < y+h; yy++, i += v->stride) for (j = i, xx = x; xx < x+w; xx++, j++, k++) if (xx >= x1 && xx < x2 && yy >= y1 && yy < y2) abuf[j] = c[k].a; } return 0; } /* same as above, but use current foreground color */ int draw_alpha_box(void *_v, int x, int y, int w, int h) { visual_t *v = (visual_t*)_v; int x1, y1, x2, y2; int i, j, xx, yy; if (ggiGetGCClipping(v->vis, &x1, &y1, &x2, &y2)) return -1; if (v->asz == 1) { unsigned char *abuf = (unsigned char*)v->abuf; /* FIXME: optimize me! */ for (i = y*v->stride+x, yy = y; yy < y+h; yy++, i += v->stride) for (j = i, xx = x; xx < x+w; xx++, j++) if (xx >= x1 && xx < x2 && yy >= y1 && yy < y2) abuf[j] = v->afg; } else { unsigned short *abuf = (unsigned short*)v->abuf; /* FIXME: optimize me! */ for (i = y*v->stride+x, yy = y; yy < y+h; yy++, i += v->stride) for (j = i, xx = x; xx < x+w; xx++, j++) if (xx >= x1 && xx < x2 && yy >= y1 && yy < y2) abuf[j] = v->afg; } return 0; } /* retrieve a rectangle of pixels from a visual, including alpha values */ int get_box(void *_v, int x, int y, int w, int h, ggi_color **c) { visual_t *v = (visual_t*)_v; int n = w*h, bpp, stride, ret; int xc = x, yc = y, wc = w, hc = h; int i, j, k, xx, yy; unsigned char *buf; ggi_mode m; *c = NULL; /* FIXME: we don't support packed non-byte-aligned pixels for now */ if (ggiGetMode(v->vis, &m) || (bpp = GT_SIZE(m.graphtype))%8 != 0) return 0; if (x >= v->stride || y >= v->lines || h <= 0 || w <= 0) return n; if (w > INT_MAX/h) return -1; if (!(buf = malloc(pack_size(v->vis, n)))) return -1; if (n > INT_MAX/sizeof(ggi_color) || !(*c = malloc(n*sizeof(ggi_color)))) { free(buf); return -1; } /* we do our own clipping here, since GGI doesn't handle it :( */ memset(buf, 0, n); memset(*c, 0, n*sizeof(ggi_color)); if (xc < 0) { wc += xc; xc = 0; } if (xc+wc > v->stride) wc = v->stride - xc; if (yc < 0) { hc += yc; yc = 0; } if (yc+hc > v->lines) hc = v->lines - yc; bpp /= 8; stride = w*bpp; if (xc == x && wc == w) { ret = ggiGetBox(v->vis, xc, yc, wc, hc, buf+(yc-y)*stride); } else { /* horizontal clipping, read the pixels line by line */ unsigned char *bufp; int off = (xc-x)*bpp; for (bufp = buf+(yc-y)*stride, yy = yc; yy < yc+hc; yy++, bufp += stride) if ((ret = ggiGetHLine(v->vis, xc, yy, wc, bufp+off))) break; } if (ret) { free(buf); free(*c); return 0; } if (ggiUnpackPixels(v->vis, buf, *c, n)) { free(buf); free(*c); return 0; } free(buf); /* get the alpha values from the alpha buffer if any */ if (v->abuf) { if (v->asz == 1) { unsigned char *abuf = (unsigned char*)v->abuf; /* FIXME: optimize me! */ for (i = y*v->stride+x, k = 0, yy = y; yy < y+h; yy++, i += v->stride) for (j = i, xx = x; xx < x+w; xx++, j++) if (xx >= 0 && xx < v->stride && yy >= 0 && yy < v->lines) (*c)[k++].a = abuf[j]*0x101; else (*c)[k++].a = 0xffff; } else { unsigned short *abuf = (unsigned short*)v->abuf; /* FIXME: optimize me! */ for (i = y*v->stride+x, k = 0, yy = y; yy < y+h; yy++, i += v->stride) for (j = i, xx = x; xx < x+w; xx++, j++) if (xx >= 0 && xx < v->stride && yy >= 0 && yy < v->lines) (*c)[k++].a = abuf[j]; else (*c)[k++].a = 0xffff; } } else { /* default alpha values */ int i; for (i = 0; i < n; i++) (*c)[i].a = 0xffff; } return n; } /* perform alpha blending */ static int blend_box(visual_t *v, int x, int y, int w, int h, ggi_color *c, ggi_color **d) { int i, n = w*h; *d = c; if (!v->abuf) return n; if ((n = get_box(v, x, y, w, h, d)) <= 0 || !(*d)) return n; for (i = 0; i < n; i++) { (*d)[i].r = (((unsigned long)c[i].a)*((unsigned long)c[i].r) + ((unsigned long)0xffff-c[i].a)*((unsigned long)(*d)[i].r))/0xffff; (*d)[i].g = (((unsigned long)c[i].a)*((unsigned long)c[i].g) + ((unsigned long)0xffff-c[i].a)*((unsigned long)(*d)[i].g))/0xffff; (*d)[i].b = (((unsigned long)c[i].a)*((unsigned long)c[i].b) + ((unsigned long)0xffff-c[i].a)*((unsigned long)(*d)[i].b))/0xffff; (*d)[i].a = (0xffffL*((unsigned long)c[i].a) + ((unsigned long)0xffff-c[i].a)*((unsigned long)(*d)[i].a))/0xffff; } return n; } /* same, for single source pixel */ static int blend_box1(visual_t *v, int x, int y, int w, int h, ggi_color *c, ggi_color **d) { int i, n = w*h; *d = NULL; if (!v->abuf || c->a == 0xffff) return n; if ((n = get_box(v, x, y, w, h, d)) <= 0 || !(*d)) return n; for (i = 0; i < n; i++) { (*d)[i].r = (((unsigned long)c->a)*((unsigned long)c->r) + ((unsigned long)0xffff-c->a)*((unsigned long)(*d)[i].r))/0xffff; (*d)[i].g = (((unsigned long)c->a)*((unsigned long)c->g) + ((unsigned long)0xffff-c->a)*((unsigned long)(*d)[i].g))/0xffff; (*d)[i].b = (((unsigned long)c->a)*((unsigned long)c->b) + ((unsigned long)0xffff-c->a)*((unsigned long)(*d)[i].b))/0xffff; (*d)[i].a = (0xffffL*((unsigned long)c->a) + ((unsigned long)0xffff-c->a)*((unsigned long)(*d)[i].a))/0xffff; } return n; } /* store a rectangle of pixels in a visual, with alpha blending */ int put_box(void *_v, int x, int y, int w, int h, ggi_color *c) { visual_t *v = (visual_t*)_v; int n = w*h, ret; unsigned char *buf; ggi_color *d = c; if (h <= 0 || w <= 0) return 0; if (w > INT_MAX/h) return -1; if ((ret = blend_box(v, x, y, w, h, c, &d)) <= 0 || !d) return ret; if (!(buf = malloc(pack_size(v->vis, n)))) return -1; ret = ggiPackColors(v->vis, buf, d, n) || ggiPutBox(v->vis, x, y, w, h, buf); free(buf); if (!ret && v->abuf) ret = set_alpha_box(v, x, y, w, h, d); if (d != c) free(d); if (ret) return 0; else return n; } /* same, with current foreground pixel */ int draw_box(void *_v, int x, int y, int w, int h) { visual_t *v = (visual_t*)_v; int n = w*h, ret; unsigned char *buf; ggi_pixel pix; ggi_color c, *d = NULL; if (h <= 0 || w <= 0) return 0; if (ggiGetGCForeground(v->vis, &pix) || ggiUnmapPixel(v->vis, pix, &c)) return 0; if (v->abuf) c.a = (v->asz==1)?(v->afg*0x101):v->afg; else c.a = 0xffff; if (w > INT_MAX/h) return -1; if ((ret = blend_box1(v, x, y, w, h, &c, &d)) <= 0) return ret; if (d) { if (!(buf = malloc(pack_size(v->vis, n)))) return -1; ret = ggiPackColors(v->vis, buf, d, n) || ggiPutBox(v->vis, x, y, w, h, buf); free(buf); if (!ret && v->abuf) ret = set_alpha_box(v, x, y, w, h, d); free(d); } else { ret = ggiDrawBox(v->vis, x, y, w, h); if (!ret && v->abuf) ret = draw_alpha_box(v, x, y, w, h); } if (ret) return 0; else return n; } --- NEW FILE: ggilib.h --- /* C interface to some of the internals of the Q-GGI module, to facilitate access for "third-party" extensions like the draw_wave module. 2003-12-23 AG */ /* This file is part of the Q programming system. The Q programming system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. The Q programming system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __GGILIB_H__ #define __GGILIB_H__ 1 #include <ggi/ggi.h> /* NOTE: The v argument of the following operations must point to a valid GGIVisual object, as obtained from the object pointer of a GGIVisual expression. */ /* the following operations return a negative value on error, zero otherwise */ /* clear clip area of alpha buffer */ extern int clear_alpha_buffer(void *v); /* set alpha values, with clipping */ extern int set_alpha_box(void *v, int x, int y, int w, int h, ggi_color *c); /* same as above, but use current foreground color */ extern int draw_alpha_box(void *v, int x, int y, int w, int h); /* the following operations return the number of processed pixels if successful, negative otherwise */ /* retrieve a rectangle of pixels from a visual, including alpha values (storage pointed to by c is malloc'ed, user must free it) */ extern int get_box(void *v, int x, int y, int w, int h, ggi_color **c); /* store a rectangle of pixels in a visual, with alpha blending */ extern int put_box(void *v, int x, int y, int w, int h, ggi_color *c); /* same, with current foreground pixel */ extern int draw_box(void *v, int x, int y, int w, int h); /* for this one, you need to link in draw_line.c; returns nonzero iff error */ extern int draw_line(void *v, int x1, int y1, int x2, int y2); /* convenience inline functions, to process horizontal and vertical lines and single pixels */ static inline int set_alpha_hline(void *v, int x, int y, int w, ggi_color *c) { return set_alpha_box(v, x, y, w, 1, c); } static inline int set_alpha_vline(void *v, int x, int y, int h, ggi_color *c) { return set_alpha_box(v, x, y, 1, h, c); } static inline int set_alpha_pixel(void *v, int x, int y, ggi_color *c) { return set_alpha_box(v, x, y, 1, 1, c); } static inline int draw_alpha_hline(void *v, int x, int y, int w) { return draw_alpha_box(v, x, y, w, 1); } static inline int draw_alpha_vline(void *v, int x, int y, int h) { return draw_alpha_box(v, x, y, 1, h); } static inline int draw_alpha_pixel(void *v, int x, int y) { return draw_alpha_box(v, x, y, 1, 1); } static inline int get_hline(void *v, int x, int y, int w, ggi_color **c) { return get_box(v, x, y, w, 1, c); } static inline int get_vline(void *v, int x, int y, int h, ggi_color **c) { return get_box(v, x, y, 1, h, c); } static inline int get_pixel(void *v, int x, int y, ggi_color **c) { return get_box(v, x, y, 1, 1, c); } static inline int put_hline(void *v, int x, int y, int w, ggi_color *c) { return put_box(v, x, y, w, 1, c); } static inline int put_vline(void *v, int x, int y, int h, ggi_color *c) { return put_box(v, x, y, 1, h, c); } static inline int put_pixel(void *v, int x, int y, ggi_color *c) { return put_box(v, x, y, 1, 1, c); } static inline int draw_hline(void *v, int x, int y, int w) { return draw_box(v, x, y, w, 1); } static inline int draw_vline(void *v, int x, int y, int h) { return draw_box(v, x, y, 1, h); } static inline int draw_pixel(void *v, int x, int y) { return draw_box(v, x, y, 1, 1); } #endif Index: Makefile.am =================================================================== RCS file: /cvsroot/q-lang/q/modules/ggi/Makefile.am,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Makefile.am 19 Dec 2003 21:31:34 -0000 1.3 --- Makefile.am 23 Dec 2003 01:15:02 -0000 1.4 *************** *** 11,17 **** endif ! ggi_la_SOURCES = ggi.c ggi_la_LDFLAGS = -no-undefined -module -avoid-version ! ggi_la_LIBADD = -L$(top_builddir)/libq -lq @LIBGMP@ @GGI_LIBS@ @GGI_LIBBUF@ @FT2_LIBS@ @LIBDMALLOCTH@ stdlibdir = $(pkgdatadir)/lib --- 11,17 ---- endif ! ggi_la_SOURCES = ggi.c ggilib.h ggilib.c draw_line.c ggi_la_LDFLAGS = -no-undefined -module -avoid-version ! ggi_la_LIBADD = -L$(top_builddir)/libq -lq @LIBGMP@ @GGI_LIBS@ @FT2_LIBS@ @LIBDMALLOCTH@ stdlibdir = $(pkgdatadir)/lib Index: Makefile.mingw =================================================================== RCS file: /cvsroot/q-lang/q/modules/ggi/Makefile.mingw,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Makefile.mingw 15 Dec 2003 12:07:14 -0000 1.2 --- Makefile.mingw 23 Dec 2003 01:15:02 -0000 1.3 *************** *** 13,18 **** all: ggi$(SHLEXT) ! ggi$(SHLEXT): ggi.c ! qcc -o ggi$(SHLEXT) ggi.c -- $(DEFS) -I. -I../../libq -I../../../ggi/include -I../../../gmp --link -L. -L../../../ggi/lib -lggi -lgii -lgg -lggibuf -lggigalloc -L../../../gmp -lgmp -L../../libq clean mostlyclean distclean maintainer-clean:: --- 13,18 ---- all: ggi$(SHLEXT) ! ggi$(SHLEXT): ggi.c ggilib.h ggilib.c draw_line.c ! qcc -o ggi$(SHLEXT) ggi.c ggilib.c draw_line.c -- $(DEFS) -I. -I../../libq -I../../../ggi/include -I../../../gmp --link -L. -L../../../ggi/lib -lggi -lgii -lgg -L../../../gmp -lgmp -L../../libq clean mostlyclean distclean maintainer-clean:: Index: README-GGI =================================================================== RCS file: /cvsroot/q-lang/q/modules/ggi/README-GGI,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** README-GGI 19 Dec 2003 21:31:34 -0000 1.3 --- README-GGI 23 Dec 2003 01:15:02 -0000 1.4 *************** *** 11,23 **** advanced features and extensions when these parts of GGI become stable. But the module is already quite usable for doing raster graphics on a wide variety ! of systems and output devices. Experimental support for alpha and z buffers ! via GGI's buffer extension, as well as advanced text rendering via FreeType2 ! is now also available. The module requires that you have libggi (version 2.0 or later) and libgii ! (version 0.8 or later) installed. To make the alpha/z buffer support work, you ! need the buffer extension (libggibuf+libggigalloc, currently only available ! from cvs). For the additional font support you also need to have FreeType2 ! (http://www.freetype.org/) installed. Since the GGI project at SourceForge [http://sourceforge. net/projects/ggi/] --- 11,20 ---- advanced features and extensions when these parts of GGI become stable. But the module is already quite usable for doing raster graphics on a wide variety ! of systems and output devices. Experimental support for simple alpha blending ! as well as advanced text rendering via FreeType2 is now also available. The module requires that you have libggi (version 2.0 or later) and libgii ! (version 0.8 or later) installed. For the additional font support you also ! need version 2 of the FreeType library (http://www.freetype.org/). Since the GGI project at SourceForge [http://sourceforge. net/projects/ggi/] *************** *** 33,37 **** Please see ggi.q for a description of the functions provided by this module. For more in-depth information about GGI please refer to the corresponding ! manual pages. A little demo can be found in the ggi_demo.q script. Acknowledgements --- 30,35 ---- Please see ggi.q for a description of the functions provided by this module. For more in-depth information about GGI please refer to the corresponding ! manual pages. A few sample scripts are also provided; you can find these, once ! installed, in the <q-prefix>/share/q/examples/ggi directory. Acknowledgements *************** *** 44,48 **** Enjoy! :) ! Nov 28 2003 Albert Graef ag...@mu..., Dr....@t-... --- 42,46 ---- Enjoy! :) ! Dec 22 2003 Albert Graef ag...@mu..., Dr....@t-... Index: ggi.c =================================================================== RCS file: /cvsroot/q-lang/q/modules/ggi/ggi.c,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** ggi.c 21 Dec 2003 12:53:26 -0000 1.14 --- ggi.c 23 Dec 2003 01:15:02 -0000 1.15 *************** *** 64,71 **** #endif - #if defined(HAVE_GGIBUFINIT) && !defined(HAVE_GGIBUF) - #define HAVE_GGIBUF 1 - #endif - #if defined(HAVE_FT_INIT_FREETYPE) && !defined(HAVE_FT2) #define HAVE_FT2 1 --- 64,67 ---- *************** [...1577 lines suppressed...] - v->vis && v->b[1] && istuple(argv[1], &n, &xv) && n == 2 && - isint(xv[0], &x) && isint(xv[1], &y) && - x >= 0 && y >= 0 && - istuple(argv[2], &n, &xv) && n == 2 && - isint(xv[0], &w) && isint(xv[1], &h) && - isobj(argv[3], type(ByteStr), (void**)&m) && m->size%2 == 0) { - n = m->size/2; - if (w*h != n) return __FAIL; - if (n <= 0) return mkvoid; - if ((n = put_buf_box(v->b[1], x, y, w, h, (unsigned short*)m->v)) < 0) - return __ERROR; - else if (n == 0) - return __FAIL; - else - return mkvoid; - } else - #endif return __FAIL; } --- 1770,1773 ---- Index: ggi.q =================================================================== RCS file: /cvsroot/q-lang/q/modules/ggi/ggi.q,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** ggi.q 20 Dec 2003 22:06:16 -0000 1.7 --- ggi.q 23 Dec 2003 01:15:02 -0000 1.8 *************** *** 32,56 **** /* The following values, bitwise or'ed together, are used as flag values in the ggi_set_flags and ggi_get_flags operations. See ggiSetFlags(3) for an - explanation of these values. (NOTE: At this time, GGI_FLAG_TIDYBUF is only - supported in the development version of GGI.) */ - - public var const GGI_FLAG_ASYNC, GGI_FLAG_TIDYBUF; - - /* The following values, bitwise or'ed together, are used as flags for the - gii_set_{alpha,z}_flags operations. See ggiBufSetGCFlags(3) for an explanation of these values. */ ! public var const GGI_BUF_DISPOSE, GGI_BUF_PUTGET, ! GGI_BUF_CMP_GT, GGI_BUF_CMP_LT, GGI_BUF_CMP_EQ, ! GGI_BUF_CMP_GTE, GGI_BUF_CMP_LTE, ! GGI_BUF_BLEND_OVER, GGI_BUF_BLEND_UNDER, ! GGI_BUF_BLEND_SRC_OVER, GGI_BUF_BLEND_DST_OVER, ! GGI_BUF_BLEND_SRC_IN, GGI_BUF_BLEND_DST_IN, ! GGI_BUF_BLEND_SRC_OUT, GGI_BUF_BLEND_DST_OUT, ! GGI_BUF_BLEND_TOP, GGI_BUF_BLEND_BOTTOM, ! GGI_BUF_BLEND_XOR, GGI_BUF_BLEND_PLUS, ! GGI_BUF_ALTBLEND_SHIFT, ! GGI_BUF_BLEND_SRC_PREMULT, GGI_BUF_BLEND_DST_PREMULT, ! GGI_BUF_BLEND_POSTDIV; /* The following values describe various types of events and event masks. See --- 32,38 ---- /* The following values, bitwise or'ed together, are used as flag values in the ggi_set_flags and ggi_get_flags operations. See ggiSetFlags(3) for an explanation of these values. */ ! public var const GGI_FLAG_ASYNC; /* The following values describe various types of events and event masks. See *************** *** 139,156 **** def (/* visual flags */ ! GGI_FLAG_ASYNC, GGI_FLAG_TIDYBUF, ! /* buffer flags */ ! GGI_BUF_DISPOSE, GGI_BUF_PUTGET, ! GGI_BUF_CMP_GT, GGI_BUF_CMP_LT, GGI_BUF_CMP_EQ, ! GGI_BUF_CMP_GTE, GGI_BUF_CMP_LTE, ! GGI_BUF_BLEND_OVER, GGI_BUF_BLEND_UNDER, ! GGI_BUF_BLEND_SRC_OVER, GGI_BUF_BLEND_DST_OVER, ! GGI_BUF_BLEND_SRC_IN, GGI_BUF_BLEND_DST_IN, ! GGI_BUF_BLEND_SRC_OUT, GGI_BUF_BLEND_DST_OUT, ! GGI_BUF_BLEND_TOP, GGI_BUF_BLEND_BOTTOM, ! GGI_BUF_BLEND_XOR, GGI_BUF_BLEND_PLUS, ! GGI_BUF_ALTBLEND_SHIFT, ! GGI_BUF_BLEND_SRC_PREMULT, GGI_BUF_BLEND_DST_PREMULT, ! GGI_BUF_BLEND_POSTDIV, /* events */ GGI_EV_NOTHING, GGI_EV_COMMAND, GGI_EV_INFORMATION, --- 121,125 ---- def (/* visual flags */ ! GGI_FLAG_ASYNC, /* events */ GGI_EV_NOTHING, GGI_EV_COMMAND, GGI_EV_INFORMATION, *************** *** 234,271 **** K=greyscale and T=text). ! If the GGI buffer extension is available, the mode string can also specify ! an alpha and/or z buffer which is to be attached to the visual, see also ! the discussion of alpha and z buffers below. E.g.: ! ! "1152x921.V1152x921.F1.D1x1.[C24/32].A8.Z8" ! ! The number following the A and Z symbols denotes the desired bit depth of ! the alpha and z values, respectively. In the current implementation only ! depth 8 is supported. Also note that these specifications are a Q-GGI ! specific extension, and thus cannot be used in the GGI_DEFMODE environment ! variable. ! ! Alpha and z buffers are created with the following defaults, which can ! later be overridden with the appropriate functions discussed in the section ! on alpha and z buffers below: ! - Alpha buffers are created with GGI_BUF_BLEND_OVER mode, with all alpha ! values initialized to 0, and the current foreground and background alpha ! value set to the maximum possible value. This means that by default ! graphic objects will not be transparent, and will be drawn over existing ! objects, which matches the behaviour of a visual without an alpha ! buffer. To get transparent objects, you will have to reduce the ! foreground and background alpha values accordingly. You can also set the ! buffer to GGI_BUF_BLEND_UNDER mode in order to have new objects drawn ! below existing ones. (Alpha buffers can also operate in a number of other ! modes which are discussed in the GGI documentation.) ! - Z buffers are created with GGI_BUF_CMP_LTE mode, with all z values and ! the current foreground and background z value set to the maximum possible ! value. This means that by default new objects will be drawn above objects ! with larger (or equal) z values, and below objects with smaller z ! values. With the default foreground and background z value, new objects ! will just be drawn over existing ones, which matches the behaviour of a ! visual without z buffer. If the MODE argument of ggi_check_mode or ggi_set_mode is () then the --- 203,219 ---- K=greyscale and T=text). ! The mode string can also specify an alpha buffer which is to be attached to ! the visual. E.g.: ! "1152x921.V1152x921.F1.D1x1.[C24/32].A8" ! This means that the visual will be "clad" with an alpha buffer of the ! requested bit depth (8 in this example), and subsequent graphics operations ! will transparently perform alpha blending when pixels are written to the ! visual. This is useful for handling graphics involving transparent or ! translucent pixels. Please note that in the current implementation only the ! depth 0, 8 and 16 are supported. Also note that since this a Q-GGI ! specific extension, the .A mode cannot be used in the GGI_DEFMODE ! environment variable. If the MODE argument of ggi_check_mode or ggi_set_mode is () then the *************** *** 279,284 **** ggi_get_mode VIS; ! /* Set and get flag values of a visual. Currently, the flags GGI_FLAG_ASYNC ! and GGI_FLAG_TIDYBUF(?) are supported; see ggiSetFlags(3). */ public extern ggi_set_flags VIS FLAGS, ggi_get_flags VIS; --- 227,231 ---- ggi_get_mode VIS; ! /* Set and get flag values of a visual; see ggiSetFlags(3). */ public extern ggi_set_flags VIS FLAGS, ggi_get_flags VIS; *************** *** 338,344 **** /* Advanced text rendering using FreeType2. *********************************/ ! /* This is a Q-GGI-specific extension which allows you to set the font used ! for text rendering in a GGI visual. The FreeType2 library is required to ! make this work. */ /* Reset a visual to the default builtin font. */ --- 285,291 ---- /* Advanced text rendering using FreeType2. *********************************/ ! /* This is another Q-GGI specific extension which allows you to set the font ! used for text rendering in a GGI visual. The FreeType2 library is required ! to make this work. */ /* Reset a visual to the default builtin font. */ *************** *** 454,461 **** /* Clear the screen. That is, fill the current clip area (the entire virtual screen by default) with the current background color. Also clear the ! contents of attached buffers. */ public extern ggi_clear VIS; /* Basic drawing operations. These functions always use the foreground color currently set on the visual. You can draw single pixels, horizontal/ --- 401,413 ---- /* Clear the screen. That is, fill the current clip area (the entire virtual screen by default) with the current background color. Also clear the ! clip area of an attached alpha buffer. */ public extern ggi_clear VIS; + /* Clear the alpha buffer only. This works like ggi_clear but only affects the + alpha buffer of a visual. */ + + public extern ggi_clear_alpha VIS; + /* Basic drawing operations. These functions always use the foreground color currently set on the visual. You can draw single pixels, horizontal/ *************** *** 497,507 **** bounding box of the string in relationship to the baseline. For the default font, the XMIN and YMIN values are always zero, and the XMAX and YMAX ! values correspond to the width and height of the rendered string. For other ! fonts, the XMIN value described the initial offset of the first character ! in the string from adjacent characters. The YMIN value specifies the amount ! of vertical space between the lowest pixel in the rendered string and the ! baseline of the text; note that this value can be negative, indicating that ! the string extends *below* the baseline. The YMIN value is useful, in ! particular, if text is to be aligned properly w.r.t. the baseline. */ public extern ggi_get_string_bbox VIS S; --- 449,460 ---- bounding box of the string in relationship to the baseline. For the default font, the XMIN and YMIN values are always zero, and the XMAX and YMAX ! values correspond to the width and height of the rendered string. For ! FreeType-managed fonts, the XMIN value described the initial offset of the ! first character in the string from adjacent characters. The YMIN value ! specifies the amount of vertical space between the lowest pixel in the ! rendered string and the baseline of the text; note that this value can be ! negative, indicating that the string extends *below* the baseline. The YMIN ! value is useful, in particular, if text is to be aligned properly w.r.t. ! the baseline. */ public extern ggi_get_string_bbox VIS S; *************** *** 515,526 **** line or rectangle from a visual as an RGBA byte string. The retrieved value can then be placed back into another or the same visual with the ! corresponding put operations. For the put operations, pixels can also be ! specified as a color tuple or list of color tuples, respectively. ! ! Note that the put operations always render the given pixels using the ! current alpha foreground setting in the target visual, i.e., the inpixel ! alpha values are effectively thrown away. If you want to render an image ! with full alpha blending you should instead use the blitting operations ! below, with the GGI_BUF_PUTGET flag set on the source visual. */ public extern ggi_get_pixel VIS P, ggi_put_pixel VIS P PIXEL; --- 468,474 ---- line or rectangle from a visual as an RGBA byte string. The retrieved value can then be placed back into another or the same visual with the ! corresponding put operations (performing alpha blending if the target ! visual has an alpha buffer). For the put operations, pixels can also be ! specified as a color tuple or list of color tuples, respectively. */ public extern ggi_get_pixel VIS P, ggi_put_pixel VIS P PIXEL; *************** *** 549,560 **** rectangle is denoted by its source position P = (X1,Y1), dimensions DIM = (H,W) and target position Q = (X2,Y2). The rectangle is copied from the ! read frame of the source visual to the write frame of the target visual. ! Overlaps are handled if source and target are the same. If the source ! visual has the GGI_BUF_PUTGET flag set, then full blending of the source ! and target alpha and/or z values is performed. (*FIXME* With the current ! libggibuf version this works for alpha values only.) */ ! public extern ggi_copy_box VIS P DIM Q; ! public extern ggi_cross_blit PVIS P DIM QVIS Q; /* Flush the display. This causes pending output operations to be completed --- 497,512 ---- rectangle is denoted by its source position P = (X1,Y1), dimensions DIM = (H,W) and target position Q = (X2,Y2). The rectangle is copied from the ! read frame of the source visual to the write frame of the target visual. */ ! public ggi_copy_box VIS P DIM Q; ! public ggi_cross_blit PVIS P DIM QVIS Q; ! ! ggi_copy_box VIS P DIM Q ! = () ! where () = ggi_put_box VIS Q DIM (ggi_get_box VIS P DIM); ! ! ggi_cross_blit PVIS P DIM QVIS Q ! = () ! where () = ggi_put_box QVIS Q DIM (ggi_get_box PVIS P DIM); /* Flush the display. This causes pending output operations to be completed *************** *** 566,620 **** public extern ggi_flush VIS, ggi_flush_region VIS P DIM; - - /* Alpha and Z buffers. *****************************************************/ - - /* These operations provide access to GGI's buffer extension, which adds the - capability to handle transparency and the stacking order of graphic - objects. This functionality is enabled when a visual is "clad", i.e., has - an alpha and/or z buffer attached to it (see ggi_set_mode on how to - accomplish this). The following additional operations are provided to - operate directly on the alpha and z buffers of a visual. Please note that - no matter what the internal bit depth of an alpha or z buffer is (at - present it is always 8, but this might change in future libggibuf - implementations), all alpha/z values are represented as normalized 16 bit - values; the necessary conversions from/to the bit depth of the target - buffer will be handled automatically. */ - - /* Set and retrieve flag values affecting the behaviour of alpha blending and - z rendering. These operations use the GGI_BUF_* flag values declared at the - beginning of this module. */ - - public extern ggi_set_alpha_flags VIS FLAGS, ggi_get_alpha_flags VIS; - public extern ggi_set_z_flags VIS FLAGS, ggi_get_z_flags VIS; - - /* Set and retrieve the current foreground and background alpha/z values of a - visual, specified as unsigned 16 bit integer values. These work much like - the ggi_{set,get}_{foreground,background} operations but operate only on - the alpha/z settings. Note that the foreground/background alpha values can - also be set and retrieved with ggi_{set,get}_{foreground,background}. */ - - public extern ggi_set_alpha_foreground VIS VAL, ggi_get_alpha_foreground VIS; - public extern ggi_set_alpha_background VIS VAL, ggi_get_alpha_background VIS; - public extern ggi_set_z_foreground VIS VAL, ggi_get_z_foreground VIS; - public extern ggi_set_z_background VIS VAL, ggi_get_z_background VIS; - - /* Clearing alpha and z buffers. The following operations work like ggi_clear - but only affect the alpha and z buffers of a visual. They cause the clip - area to be filled with the current background alpha/z values. */ - - public extern ggi_clear_alpha VIS; - public extern ggi_clear_z VIS; - - /* Get and set single buffer values, specified as unsigned 16 bit integer - values. */ - - public extern ggi_get_alpha_val VIS P, ggi_put_alpha_val VIS P VAL; - public extern ggi_get_z_val VIS P, ggi_put_z_val VIS P VAL; - - /* Get and set ranges of buffer values, specified as byte strings of 16 bit - values. */ - - public extern ggi_get_alpha_box VIS P DIM, ggi_put_alpha_box VIS P DIM VALS; - public extern ggi_get_z_box VIS P DIM, ggi_put_z_box VIS P DIM VALS; /* Event handling. **********************************************************/ --- 518,521 ---- |