📄 devdraw.c
字号:
if (rw > 0 && rh > 0) { gc->dstx = rx1; gc->dsty = ry1; gc->dstw = rw; gc->dsth = rh; gc->srcx = srcx + rx1 - x; gc->srcy = srcy + ry1 - y; GdCheckCursor(psd, rx1, ry1, rx2 - 1, ry2 - 1); psd->DrawArea(psd, gc, op); } prc++; } /* Reset everything, in case the caller re-uses it. */ gc->dstx = x; gc->dsty = y; gc->dstw = width; gc->dsth = height; gc->srcx = srcx; gc->srcy = srcy; return;}/** * 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_TRUECOLOR8888 unsigned long * 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. * * @param psd Drawing surface. * @param x Left edge of rectangle to blit to. * @param y Top edge of rectangle to blit to. * @param width Width of image to blit. * @param height Height of image to blit. * @param pixels Image data. * @param pixtype Format of pixels. */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, hasn't been tested with new drawarea routines*/#if 0000 if (pixtype == MWPF_PIXELVAL) { driver_gc_t hwgc; if (!(psd->flags & PSF_HAVEOP_COPY)) goto fallback; hwgc.pixels = PIXELS; hwgc.src_linelen = width; hwgc.gr_usebg = gr_usebg; hwgc.bg_color = gr_background; hwgc.dstx = x; hwgc.dsty = y; hwgc.dstw = width; hwgc.dsth = height; hwgc.srcx = 0; hwgc.srcy = 0; GdDrawAreaInternal(psd, &hwgc, PSDOP_COPY); GdFixCursor(psd); return; fallback: } 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_TRUECOLOR8888: 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(psd, 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_TRUECOLOR8888: case MWPF_TRUECOLOR0888: gr_foreground = *(unsigned long *)PIXELS; PIXELS += sizeof(unsigned long); break; case MWPF_TRUECOLOR888: r = *PIXELS++; g = *PIXELS++; b = *PIXELS++; gr_foreground = RGB2PIXEL888(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_TRUECOLOR8888: 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 != RGB2PIXEL888(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++; } } /* 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. */voidGdCopyArea(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);}#endifextern MWCLIPREGION *clipregion;/** * Copy source rectangle of pixels to destination rectangle quickly * * @param dstpsd Drawing surface to draw to. * @param dstx Destination X co-ordinate. * @param dsty Destination Y co-ordinate. * @param width Width of rectangle to copy. * @param height Height of rectangle to copy. * @param srcpsd Drawing surface to copy from. * @param srcx Source X co-ordinate. * @param srcy Source Y co-ordinate. * @param rop Raster operation. */voidGdBlit(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;#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 of both screen devices*/ GdCheckCursor(dstpsd, srcx, srcy, srcx+width-1, srcy+height-1); if (dstpsd != srcpsd) GdCheckCursor(srcpsd, srcx, srcy, srcx+width-1, srcy+height-1); dstpsd->Blit(dstpsd, dstx, dsty, width, height, srcpsd, srcx, srcy, rop); GdFixCursor(dstpsd); if (dstpsd != srcpsd) GdFixCursor(srcpsd); 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*//* Only used by fblin16.c */int g_row_inc, g_col_inc;/** * Stretch source rectangle of pixels to destination rectangle quickly * * @param dstpsd Drawing surface to draw to. * @param dstx Destination X co-ordinate. * @param dsty Destination Y co-ordinate. * @param dstw Width of destination rectangle. * @param dsth Height of destination rectangle. * @param srcpsd Drawing surface to copy from. * @param srcx Source X co-ordinate. * @param srcy Source Y co-ordinate. * @param srcw Width of source rectangle. * @param srch Height of source rectangle. * @param rop Raster operation. */voidGdStretchBlit(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#if 1 /* FIXME*/ /* Use new improved stretchblit if the driver supports it */ if (dstpsd->StretchBlitEx) { GdStretchBlitEx(dstpsd, dstx, dsty, dstx + dstw, dsty + dsth, srcpsd, srcx, srcy, srcx + srcw, srcy + srch, rop); return; }#endifg_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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -