📄 devdraw.c
字号:
* nearest color from the inuse palette. * FIXME: tag the conversion table to the bitmap image */ for(i=0; i<palsize; ++i) { cr = GETPALENTRY(palette, i); convtable[i] = GdFindColor(cr); }#endif for(i=0; i<palsize; ++i) { convtable[i] = i; }}/* * 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. */voidGdDrawImage(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; } 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; }#endifnext: 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. */voidGdReadArea(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 * * 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. */voidGdArea(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: 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: 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: 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -