📄 devdraw.c
字号:
cr = GETPALENTRY(palette, i);
convtable[i] = GdFindColor(cr);
}
}
/*
* Draw a color bitmap image in 1, 4, 8, 24 or 32 bits per pixel. The
* Microwindows color image format is DWORD padded bytes, with
* the upper bits corresponding to the left side (identical to
* the MS Windows format). This format is currently different
* than the MWIMAGEBITS format, which uses word-padded bits
* for monochrome display only, where the upper bits in the word
* correspond with the left side.
*/
void
GdDrawImage(PSD psd, MWCOORD x, MWCOORD y, PMWIMAGEHDR pimage)
{
MWCOORD minx;
MWCOORD maxx;
MWUCHAR bitvalue = 0;
int bitcount;
MWUCHAR *imagebits;
MWCOORD height, width;
MWPIXELVAL pixel;
int clip;
int extra, linesize;
int rgborder;
MWCOLORVAL cr;
MWCOORD yoff;
unsigned long transcolor;
MWPIXELVAL convtable[256];
height = pimage->height;
width = pimage->width;
/* determine if entire image is clipped out, save clipresult for later*/
clip = GdClipArea(psd, x, y, x + width - 1, y + height - 1);
if(clip == CLIP_INVISIBLE)
return;
transcolor = pimage->transcolor;
/*
* Merge the images's palette and build a palette index conversion table.
*/
if (pimage->bpp <= 8) {
if(!pimage->palette) {
/* for jpeg's without a palette*/
for(yoff=0; yoff<pimage->palsize; ++yoff)
convtable[yoff] = yoff;
} else GdMakePaletteConversionTable(psd, pimage->palette,
pimage->palsize, convtable, MERGEPALETTE);
/* The following is no longer used. One reason is that it required */
/* the transparent color to be unique, which was unnessecary */
/* convert transcolor to converted palette index for speed*/
/* if (transcolor != -1L)
transcolor = (unsigned long) convtable[transcolor]; */
}
minx = x;
maxx = x + width - 1;
imagebits = pimage->imagebits;
/* check for bottom-up image*/
if(pimage->compression & MWIMAGE_UPSIDEDOWN) {
y += height - 1;
yoff = -1;
} else
yoff = 1;
#define PIX2BYTES(n) (((n)+7)/8)
/* imagebits are dword aligned*/
switch(pimage->bpp) {
default:
case 8:
linesize = width;
break;
case 32:
linesize = width*4;
break;
case 24:
linesize = width*3;
break;
case 4:
linesize = PIX2BYTES(width<<2);
break;
case 1:
linesize = PIX2BYTES(width);
break;
}
extra = pimage->pitch - linesize;
/* 24bpp RGB rather than BGR byte order?*/
rgborder = pimage->compression & MWIMAGE_RGB;
bitcount = 0;
while(height > 0) {
unsigned long trans = 0;
if (bitcount <= 0) {
bitcount = sizeof(MWUCHAR) * 8;
bitvalue = *imagebits++;
}
switch(pimage->bpp) {
case 24:
case 32:
cr = rgborder? MWRGB(bitvalue, imagebits[0], imagebits[1]):
MWRGB(imagebits[1], imagebits[0], bitvalue);
/* Include the upper bits for transcolor stuff */
if (imagebits[2]) /* FIXME: 24bpp error*/
trans = cr | 0x01000000L;
if (pimage->bpp == 32)
imagebits += 3;
else imagebits += 2;
bitcount = 0;
/* handle transparent color*/
if (transcolor == trans)
goto next;
switch(psd->pixtype) {
case MWPF_PALETTE:
default:
pixel = GdFindColor(cr);
break;
case MWPF_TRUECOLOR0888:
case MWPF_TRUECOLOR888:
pixel = COLOR2PIXEL888(cr);
break;
case MWPF_TRUECOLOR565:
pixel = COLOR2PIXEL565(cr);
break;
case MWPF_TRUECOLOR555:
pixel = COLOR2PIXEL555(cr);
break;
case MWPF_TRUECOLOR332:
pixel = COLOR2PIXEL332(cr);
break;
case MWPF_TRUECOLOR233:
pixel = COLOR2PIXEL233(cr);
break;
}
break;
default:
case 8:
bitcount = 0;
if (bitvalue == transcolor)
goto next;
pixel = convtable[bitvalue];
break;
case 4:
if (((bitvalue & 0xf0) >> 4) == transcolor) {
bitvalue <<= 4;
bitcount -= 4;
goto next;
}
pixel = convtable[(bitvalue & 0xf0) >> 4];
bitvalue <<= 4;
bitcount -= 4;
break;
case 1:
--bitcount;
if (((bitvalue & 0x80) ? 1 : 0) == transcolor) {
bitvalue <<= 1;
goto next;
}
pixel = convtable[(bitvalue & 0x80)? 1: 0];
bitvalue <<= 1;
break;
}
/* if((unsigned long)pixel != transcolor &&*/
if (clip == CLIP_VISIBLE || GdClipPoint(psd, x, y))
psd->DrawPixel(psd, x, y, pixel);
#if 0
/* fix: use clipmaxx to clip quicker*/
else if(clip != CLIP_VISIBLE && !clipresult && x > clipmaxx) {
x = maxx;
}
#endif
next:
if(x++ == maxx) {
x = minx;
y += yoff;
height--;
bitcount = 0;
imagebits += extra;
}
}
GdFixCursor(psd);
}
/*
* Read a rectangular area of the screen.
* The color table is indexed row by row.
*/
void
GdReadArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
MWPIXELVAL *pixels)
{
MWCOORD row;
MWCOORD col;
if (width <= 0 || height <= 0)
return;
GdCheckCursor(psd, x, y, x+width-1, y+height-1);
for (row = y; row < height+y; row++)
for (col = x; col < width+x; col++)
if (row < 0 || row >= psd->yvirtres ||
col < 0 || col >= psd->xvirtres)
*pixels++ = 0;
else *pixels++ = psd->ReadPixel(psd, col, row);
GdFixCursor(psd);
}
/* Draw a rectangle of color values, clipping if necessary.
* If a color matches the background color,
* then that pixel is only drawn if the gr_usebg flag is set.
*
* The pixels are packed according to pixtype:
*
* 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
*
* NOTE: Currently, no translation is performed if the pixtype
* is not MWPF_RGB. Pixtype is only then used to determine the
* packed size of the pixel data, and is then stored unmodified
* in a MWPIXELVAL and passed to the screen driver. Virtually,
* this means there's only three reasonable options for client
* programs: (1) pass all data as RGB MWCOLORVALs, (2) pass
* data as unpacked 32-bit MWPIXELVALs in the format the current
* screen driver is running, or (3) pass data as packed values
* in the format the screen driver is running. Options 2 and 3
* are identical except for the packing structure.
*/
void
GdArea(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height, void *pixels,
int pixtype)
{
unsigned char *PIXELS = pixels; /* for ANSI compilers, can't use void*/
long cellstodo; /* remaining number of cells */
long count; /* number of cells of same color */
long cc; /* current cell count */
long rows; /* number of complete rows */
MWCOORD minx; /* minimum x value */
MWCOORD maxx; /* maximum x value */
MWPIXELVAL savecolor; /* saved foreground color */
MWBOOL dodraw; /* TRUE if draw these points */
MWCOLORVAL rgbcolor = 0L;
int pixsize;
unsigned char r, g, b;
minx = x;
maxx = x + width - 1;
/* Set up area clipping, and just return if nothing is visible */
if ( GdClipArea(psd, minx, y, maxx, y + height - 1) == CLIP_INVISIBLE )
return;
/* psd->DrawArea driver call temp removed, doesn't work with new blit routines*/
#if 0000
{
driver_gc_t hwgc;
int px1, px2, py1, py2, pw, ph, rx1, rx2, ry1, ry2;
#if DYNAMICREGIONS
MWRECT *prc;
extern MWCLIPREGION *clipregion;
#else
MWCLIPRECT *prc;
extern MWCLIPRECT cliprects[];
extern int clipcount;
#endif
#if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
/* can't use drawarea driver in 16 bpp mode yet with font routines*/
goto fallback;
#endif
if ( !(psd->flags & PSF_HAVEOP_COPY) )
goto fallback;
#if DYNAMICREGIONS
prc = clipregion->rects;
count = clipregion->numRects;
#else
prc = cliprects;
count = clipcount;
#endif
hwgc.pixels = PIXELS;
hwgc.src_linelen = width;
hwgc.gr_usebg = gr_usebg;
hwgc.bg_color = gr_background;
while ( count-- > 0 ) {
#if DYNAMICREGIONS
rx1 = prc->left;
ry1 = prc->top;
rx2 = prc->right;
ry2 = prc->bottom;
#else
/* New clip-code by Morten */
rx1 = prc->x;
ry1 = prc->y;
rx2 = prc->x + prc->width;
ry2 = prc->y + prc->height;
#endif
/* Check if this rect intersects with the one we draw */
px1 = x;
py1 = y;
px2 = x + width;
py2 = y + 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 ) {
hwgc.dstx = px1;
hwgc.dsty = py1;
hwgc.dstw = pw;
hwgc.dsth = ph;
hwgc.srcx = px1 - x;
hwgc.srcy = py1 - y;
GdCheckCursor(psd,px1,py1,px1+pw-1,py1+ph-1);
psd->DrawArea(psd,&hwgc,PSDOP_COPY);
}
prc++;
}
GdFixCursor(psd);
return;
fallback:
}
#endif /* if 0000 temp removed*/
/* Calculate size of packed pixels*/
switch(pixtype) {
case MWPF_RGB:
pixsize = sizeof(MWCOLORVAL);
break;
case MWPF_PIXELVAL:
pixsize = sizeof(MWPIXELVAL);
break;
case MWPF_PALETTE:
case MWPF_TRUECOLOR332:
case MWPF_TRUECOLOR233:
pixsize = sizeof(unsigned char);
break;
case MWPF_TRUECOLOR0888:
pixsize = sizeof(unsigned long);
break;
case MWPF_TRUECOLOR888:
pixsize = 3;
break;
case MWPF_TRUECOLOR565:
case MWPF_TRUECOLOR555:
pixsize = sizeof(unsigned short);
break;
default:
return;
}
savecolor = gr_foreground;
cellstodo = (long)width * height;
while (cellstodo > 0) {
/* read the pixel value from the pixtype*/
switch(pixtype) {
case MWPF_RGB:
rgbcolor = *(MWCOLORVAL *)PIXELS;
PIXELS += sizeof(MWCOLORVAL);
gr_foreground = GdFindColor(rgbcolor);
break;
case MWPF_PIXELVAL:
gr_foreground = *(MWPIXELVAL *)PIXELS;
PIXELS += sizeof(MWPIXELVAL);
break;
case MWPF_PALETTE:
case MWPF_TRUECOLOR332:
case MWPF_TRUECOLOR233:
gr_foreground = *PIXELS++;
break;
case MWPF_TRUECOLOR0888:
gr_foreground = *(unsigned long *)PIXELS;
PIXELS += sizeof(unsigned long);
break;
case MWPF_TRUECOLOR888:
r = *PIXELS++;
g = *PIXELS++;
b = *PIXELS++;
gr_foreground = (MWPIXELVAL)MWRGB(r, g, b);
break;
case MWPF_TRUECOLOR565:
case MWPF_TRUECOLOR555:
gr_foreground = *(unsigned short *)PIXELS;
PIXELS += sizeof(unsigned short);
break;
}
dodraw = (gr_usebg || (gr_foreground != gr_background));
count = 1;
--cellstodo;
/* See how many of the adjacent remaining points have the
* same color as the next point.
*
* NOTE: Yes, with the addition of the pixel unpacking,
* it's almost slower to look ahead than to just draw
* the pixel... FIXME
*/
while (cellstodo > 0) {
switch(pixtype) {
case MWPF_RGB:
if(rgbcolor != *(MWCOLORVAL *)PIXELS)
goto breakwhile;
PIXELS += sizeof(MWCOLORVAL);
break;
case MWPF_PIXELVAL:
if(gr_foreground != *(MWPIXELVAL *)PIXELS)
goto breakwhile;
PIXELS += sizeof(MWPIXELVAL);
break;
case MWPF_PALETTE:
case MWPF_TRUECOLOR332:
case MWPF_TRUECOLOR233:
if(gr_foreground != *(unsigned char *)PIXELS)
goto breakwhile;
++PIXELS;
break;
case MWPF_TRUECOLOR0888:
if(gr_foreground != *(unsigned long *)PIXELS)
goto breakwhile;
PIXELS += sizeof(unsigned long);
break;
case MWPF_TRUECOLOR888:
r = *(unsigned char *)PIXELS;
g = *(unsigned char *)(PIXELS + 1);
b = *(unsigned char *)(PIXELS + 2);
if(gr_foreground != (MWPIXELVAL)MWRGB(r, g, b))
goto breakwhile;
PIXELS += 3;
break;
case MWPF_TRUECOLOR565:
case MWPF_TRUECOLOR555:
if(gr_foreground != *(unsigned short *)PIXELS)
goto breakwhile;
PIXELS += sizeof(unsigned short);
break;
}
++count;
--cellstodo;
}
breakwhile:
/* If there is only one point with this color, then draw it
* by itself.
*/
if (count == 1) {
if (dodraw)
drawpoint(psd, x, y);
if (++x > maxx) {
x = minx;
y++;
}
continue;
}
/* There are multiple points with the same color. If we are
* not at the start of a row of the rectangle, then draw this
* first row specially.
*/
if (x != minx) {
cc = count;
if (x + cc - 1 > maxx)
cc = maxx - x + 1;
if (dodraw)
drawrow(psd, x, x + cc - 1, y);
count -= cc;
x += cc;
if (x > maxx) {
x = minx;
y++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -