📄 devdraw.c
字号:
}
}
/* Now the x value is at the beginning of a row if there are
* any points left to be drawn. Draw all the complete rows
* with one call.
*/
rows = count / width;
if (rows > 0) {
if (dodraw) {
/* note: change to fillrect, (parm types changed)*/
/*GdFillRect(psd, x, y, maxx, y + rows - 1);*/
GdFillRect(psd, x, y, maxx - x + 1, rows);
}
count %= width;
y += rows;
}
/* If there is a final partial row of pixels left to be
* drawn, then do that.
*/
if (count > 0) {
if (dodraw)
drawrow(psd, x, x + count - 1, y);
x += count;
}
}
gr_foreground = savecolor;
GdFixCursor(psd);
}
#if NOTYET
/* Copy a rectangular area from one screen area to another.
* This bypasses clipping.
*/
void
GdCopyArea(PSD psd, MWCOORD srcx, MWCOORD srcy, MWCOORD width, MWCOORD height,
MWCOORD destx, MWCOORD desty)
{
if (width <= 0 || height <= 0)
return;
if (srcx == destx && srcy == desty)
return;
GdCheckCursor(psd, srcx, srcy, srcx + width - 1, srcy + height - 1);
GdCheckCursor(psd, destx, desty, destx + width - 1, desty + height - 1);
psd->CopyArea(psd, srcx, srcy, width, height, destx, desty);
GdFixCursor(psd);
}
#endif
/* Copy source rectangle of pixels to destination rectangle quickly*/
void
GdBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD width, MWCOORD height,
PSD srcpsd, MWCOORD srcx, MWCOORD srcy, long rop)
{
int rx1, rx2, ry1, ry2;
int px1, px2, py1, py2;
int pw, ph;
int count;
#if DYNAMICREGIONS
MWRECT * prc;
extern MWCLIPREGION *clipregion;
#else
MWCLIPRECT * prc;
extern MWCLIPRECT cliprects[];
extern int clipcount;
#endif
/*FIXME: compare bpp's and convert if necessary*/
assert(dstpsd->planes == srcpsd->planes);
assert(dstpsd->bpp == srcpsd->bpp);
/* temporary assert() until rotation blits completed*/
assert(dstpsd->portrait == srcpsd->portrait);
/* clip blit rectangle to source screen/bitmap size*/
/* we must do this because there isn't any source clipping setup*/
if(srcx < 0) {
width += srcx;
dstx -= srcx;
srcx = 0;
}
if(srcy < 0) {
height += srcy;
dsty -= srcy;
srcy = 0;
}
if(srcx+width > srcpsd->xvirtres)
width = srcpsd->xvirtres - srcx;
if(srcy+height > srcpsd->yvirtres)
height = srcpsd->yvirtres - srcy;
switch(GdClipArea(dstpsd, dstx, dsty, dstx+width-1, dsty+height-1)) {
case CLIP_VISIBLE:
/* check cursor in src region*/
GdCheckCursor(dstpsd, srcx, srcy, srcx+width-1, srcy+height-1);
dstpsd->Blit(dstpsd, dstx, dsty, width, height,
srcpsd, srcx, srcy, rop);
GdFixCursor(dstpsd);
return;
case CLIP_INVISIBLE:
return;
}
/* Partly clipped, we'll blit using destination clip
* rectangles, and offset the blit accordingly.
* Since the destination is already clipped, we
* only need to clip the source here.
*/
#if DYNAMICREGIONS
prc = clipregion->rects;
count = clipregion->numRects;
#else
prc = cliprects;
count = clipcount;
#endif
while(--count >= 0) {
#if DYNAMICREGIONS
rx1 = prc->left;
ry1 = prc->top;
rx2 = prc->right;
ry2 = prc->bottom;
#else
rx1 = prc->x;
ry1 = prc->y;
rx2 = prc->x + prc->width;
ry2 = prc->y + prc->height;
#endif
/* Check: does this rect intersect the one we want to draw? */
px1 = dstx;
py1 = dsty;
px2 = dstx + width;
py2 = dsty + height;
if (px1 < rx1) px1 = rx1;
if (py1 < ry1) py1 = ry1;
if (px2 > rx2) px2 = rx2;
if (py2 > ry2) py2 = ry2;
pw = px2 - px1;
ph = py2 - py1;
if(pw > 0 && ph > 0) {
/* check cursor in dest and src regions*/
GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
GdCheckCursor(dstpsd, srcx, srcy,
srcx+width, srcy+height);
dstpsd->Blit(dstpsd, px1, py1, pw, ph, srcpsd,
srcx + (px1-dstx), srcy + (py1-dsty), rop);
}
++prc;
}
GdFixCursor(dstpsd);
}
/* experimental globals for ratio bug when src != 0*/
int g_row_inc, g_col_inc;
/* Stretch source rectangle of pixels to destination rectangle quickly*/
void
GdStretchBlit(PSD dstpsd, MWCOORD dstx, MWCOORD dsty, MWCOORD dstw,
MWCOORD dsth, PSD srcpsd, MWCOORD srcx, MWCOORD srcy, MWCOORD srcw,
MWCOORD srch, long rop)
{
int count;
#if DYNAMICREGIONS
MWRECT * prc;
extern MWCLIPREGION *clipregion;
#else
MWCLIPRECT * prc;
extern MWCLIPRECT cliprects[];
extern int clipcount;
#endif
g_row_inc = g_col_inc = 0;
/* check for driver stretch blit implementation*/
if (!dstpsd->StretchBlit)
return;
/*FIXME: compare bpp's and convert if necessary*/
assert(dstpsd->planes == srcpsd->planes);
assert(dstpsd->bpp == srcpsd->bpp);
/* clip blit rectangle to source screen/bitmap size*/
/* we must do this because there isn't any source clipping setup*/
if(srcx < 0) {
srcw += srcx;
/*dstx -= srcx;*/
srcx = 0;
}
if(srcy < 0) {
srch += srcy;
/*dsty -= srcy;*/
srcy = 0;
}
if(srcx+srcw > srcpsd->xvirtres)
srcw = srcpsd->xvirtres - srcx;
if(srcy+srch > srcpsd->yvirtres)
srch = srcpsd->yvirtres - srcy;
/* temp dest clipping for partially visible case*/
if(dstx+dstw > dstpsd->xvirtres)
dstw = dstpsd->xvirtres - dstx;
if(dsty+dsth > dstpsd->yvirtres)
dsth = dstpsd->yvirtres - dsty;
switch(GdClipArea(dstpsd, dstx, dsty, dstx+dstw-1, dsty+dsth-1)) {
case CLIP_VISIBLE:
/* check cursor in src region*/
GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw-1, srcy+srch-1);
dstpsd->StretchBlit(dstpsd, dstx, dsty, dstw, dsth,
srcpsd, srcx, srcy, srcw, srch, rop);
GdFixCursor(dstpsd);
return;
case CLIP_INVISIBLE:
return;
}
/* Partly clipped, we'll blit using destination clip
* rectangles, and offset the blit accordingly.
* Since the destination is already clipped, we
* only need to clip the source here.
*/
#if DYNAMICREGIONS
prc = clipregion->rects;
count = clipregion->numRects;
#else
prc = cliprects;
count = clipcount;
#endif
while(--count >= 0) {
int rx1, rx2, ry1, ry2;
int px1, px2, py1, py2;
int pw, ph;
int sx, sy, sw, sh;
#if DYNAMICREGIONS
rx1 = prc->left;
ry1 = prc->top;
rx2 = prc->right;
ry2 = prc->bottom;
#else
rx1 = prc->x;
ry1 = prc->y;
rx2 = prc->x + prc->width;
ry2 = prc->y + prc->height;
#endif
/* Check: does this rect intersect the one we want to draw? */
px1 = dstx;
py1 = dsty;
px2 = dstx + dstw;
py2 = dsty + dsth;
if (px1 < rx1) px1 = rx1;
if (py1 < ry1) py1 = ry1;
if (px2 > rx2) px2 = rx2;
if (py2 > ry2) py2 = ry2;
pw = px2 - px1;
ph = py2 - py1;
if(pw > 0 && ph > 0) {
/* calc proper src/dst offset for stretch rect*/
g_row_inc = (srch << 16) / dsth;
g_col_inc = (srcw << 16) / dstw;
sw = pw * srcw / dstw;
sh = ph * srch / dsth;
if (sw > 0 && sh > 0) {
sx = srcx + (px1-dstx) * srcw / dstw;
sy = srcy + (py1-dsty) * srch / dsth;
/*printf("P %d,%d,%d,%d %d,%d\n", sx, sy, sw, sh, g_row_inc, g_col_inc);*/
/* check cursor in dest and src regions*/
GdCheckCursor(dstpsd, px1, py1, px2-1, py2-1);
GdCheckCursor(dstpsd, srcx, srcy, srcx+srcw, srcy+srch);
dstpsd->StretchBlit(dstpsd, px1, py1, pw, ph, srcpsd,
sx, sy, sw, sh, rop);
}
}
++prc;
}
GdFixCursor(dstpsd);
}
/*
* Calculate size and linelen of memory gc.
* If bpp or planes is 0, use passed psd's bpp/planes.
* Note: linelen is calculated to be DWORD aligned for speed
* for bpp <= 8. Linelen is converted to bytelen for bpp > 8.
*/
int
GdCalcMemGCAlloc(PSD psd, unsigned int width, unsigned int height, int planes,
int bpp, int *psize, int *plinelen)
{
int bytelen, linelen, tmp;
if(!planes)
planes = psd->planes;
if(!bpp)
bpp = psd->bpp;
/*
* swap width and height in left/right portrait modes,
* so imagesize is calculated properly
*/
if(psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT)) {
tmp = width;
width = height;
height = tmp;
}
/*
* use bpp and planes to create size and linelen.
* linelen is in bytes for bpp 1, 2, 4, 8, and pixels for bpp 16,24,32.
*/
if(planes == 1) {
switch(bpp) {
case 1:
linelen = (width+7)/8;
bytelen = linelen = (linelen+3) & ~3;
break;
case 2:
linelen = (width+3)/4;
bytelen = linelen = (linelen+3) & ~3;
break;
case 4:
linelen = (width+1)/2;
bytelen = linelen = (linelen+3) & ~3;
break;
case 8:
bytelen = linelen = (width+3) & ~3;
break;
case 16:
linelen = width;
bytelen = width * 2;
break;
case 24:
linelen = width;
bytelen = width * 3;
break;
case 32:
linelen = width;
bytelen = width * 4;
break;
default:
return 0;
}
} else if(planes == 4) {
/* FIXME assumes VGA 4 planes 4bpp*/
/* we use 4bpp linear for memdc format*/
linelen = (width+1)/2;
linelen = (linelen+3) & ~3;
bytelen = linelen;
} else {
*psize = *plinelen = 0;
return 0;
}
*plinelen = linelen;
*psize = bytelen * height;
return 1;
}
/* Translate a rectangle of color values
*
* The pixels are packed according to inpixtype/outpixtype:
*
* pixtype array of
* MWPF_RGB MWCOLORVAL (unsigned long)
* MWPF_PIXELVAL MWPIXELVAL (compile-time dependent)
* MWPF_PALETTE unsigned char
* MWPF_TRUECOLOR0888 unsigned long
* MWPF_TRUECOLOR888 packed struct {char r,char g,char b} (24 bits)
* MWPF_TRUECOLOR565 unsigned short
* MWPF_TRUECOLOR555 unsigned short
* MWPF_TRUECOLOR332 unsigned char
* MWPF_TRUECOLOR233 unsigned char
*/
void
GdTranslateArea(MWCOORD width, MWCOORD height, void *in, int inpixtype,
MWCOORD inpitch, void *out, int outpixtype, int outpitch)
{
unsigned char * inbuf = in;
unsigned char * outbuf = out;
unsigned long pixelval;
MWCOLORVAL colorval;
MWCOORD x, y;
unsigned char r, g, b;
extern MWPALENTRY gr_palette[256];
int gr_palsize = 256; /* FIXME*/
for(y=0; y<height; ++y) {
for(x=0; x<width; ++x) {
/* read pixel value and convert to BGR colorval (0x00BBGGRR)*/
switch (inpixtype) {
case MWPF_RGB:
colorval = *(MWCOLORVAL *)inbuf;
inbuf += sizeof(MWCOLORVAL);
break;
case MWPF_PIXELVAL:
pixelval = *(MWPIXELVAL *)inbuf;
inbuf += sizeof(MWPIXELVAL);
/* convert based on compile-time MWPIXEL_FORMAT*/
#if MWPIXEL_FORMAT == MWPF_PALETTE
colorval = GETPALENTRY(gr_palette, pixelval);
#else
colorval = PIXELVALTOCOLORVAL(pixelval);
#endif
break;
case MWPF_PALETTE:
pixelval = *inbuf++;
colorval = GETPALENTRY(gr_palette, pixelval);
break;
case MWPF_TRUECOLOR332:
pixelval = *inbuf++;
colorval = PIXEL332TOCOLORVAL(pixelval);
break;
case MWPF_TRUECOLOR233:
pixelval = *inbuf++;
colorval = PIXEL233TOCOLORVAL(pixelval);
break;
case MWPF_TRUECOLOR0888:
pixelval = *(unsigned long *)inbuf;
colorval = PIXEL888TOCOLORVAL(pixelval);
inbuf += sizeof(unsigned long);
break;
case MWPF_TRUECOLOR888:
r = *inbuf++;
g = *inbuf++;
b = *inbuf++;
colorval = (MWPIXELVAL)MWRGB(r, g, b);
break;
case MWPF_TRUECOLOR565:
pixelval = *(unsigned short *)inbuf;
colorval = PIXEL565TOCOLORVAL(pixelval);
inbuf += sizeof(unsigned short);
break;
case MWPF_TRUECOLOR555:
pixelval = *(unsigned short *)inbuf;
colorval = PIXEL555TOCOLORVAL(pixelval);
inbuf += sizeof(unsigned short);
break;
default:
return;
}
/* convert from BGR colorval to desired output pixel format*/
switch (outpixtype) {
case MWPF_RGB:
*(MWCOLORVAL *)outbuf = colorval;
outbuf += sizeof(MWCOLORVAL);
break;
case MWPF_PIXELVAL:
/* convert based on compile-time MWPIXEL_FORMAT*/
#if MWPIXEL_FORMAT == MWPF_PALETTE
*(MWPIXELVAL *)outbuf = GdFindNearestColor(gr_palette,
gr_palsize, colorval);
#else
*(MWPIXELVAL *)outbuf = COLORVALTOPIXELVAL(colorval);
#endif
outbuf += sizeof(MWPIXELVAL);
break;
case MWPF_PALETTE:
*outbuf++ = GdFindNearestColor(gr_palette, gr_palsize,
colorval);
break;
case MWPF_TRUECOLOR332:
*outbuf++ = COLOR2PIXEL332(colorval);
break;
case MWPF_TRUECOLOR233:
*outbuf++ = COLOR2PIXEL233(colorval);
break;
case MWPF_TRUECOLOR0888:
*(unsigned long *)outbuf = COLOR2PIXEL888(colorval);
outbuf += sizeof(unsigned long);
break;
case MWPF_TRUECOLOR888:
*outbuf++ = REDVALUE(colorval);
*outbuf++ = GREENVALUE(colorval);
*outbuf++ = BLUEVALUE(colorval);
break;
case MWPF_TRUECOLOR565:
*(unsigned short *)outbuf = COLOR2PIXEL565(colorval);
outbuf += sizeof(unsigned short);
break;
case MWPF_TRUECOLOR555:
*(unsigned short *)outbuf = COLOR2PIXEL555(colorval);
outbuf += sizeof(unsigned short);
break;
}
}
/* adjust line widths, if necessary*/
if(inpitch > width)
inbuf += inpitch - width;
if(outpitch > width)
outbuf += outpitch - width;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -