/* * Draw the border of a window if there is one. * Note: To allow the border to be drawn with the correct clipping, * we temporarily grow the size of the window to include the border. */ void GsDrawBorder(GR_WINDOW *wp) { GR_COORD lminx; /* left edge minimum x */ GR_COORD rminx; /* right edge minimum x */ GR_COORD tminy; /* top edge minimum y */ GR_COORD bminy; /* bottom edge minimum y */ GR_COORD topy; /* top y value of window */ GR_COORD boty; /* bottom y value of window */ GR_SIZE width; /* original width of window */ GR_SIZE height; /* original height of window */ GR_SIZE bs; /* border size */ bs = wp->bordersize; if (bs <= 0) return; width = wp->width; height = wp->height; lminx = wp->x - bs; rminx = wp->x + width; tminy = wp->y - bs; bminy = wp->y + height; topy = wp->y; boty = bminy - 1; wp->x -= bs; wp->y -= bs; wp->width += (bs * 2); wp->height += (bs * 2); wp->bordersize = 0; clipwp = NULL; GsSetClipWindow(wp, NULL, 0); curgcp = NULL; GdSetMode(GR_MODE_COPY); GdSetForeground(GdFindColor(wp->bordercolor)); if (bs == 1) { GdLine(wp->psd, lminx, tminy, rminx, tminy, TRUE); GdLine(wp->psd, lminx, bminy, rminx, bminy, TRUE); GdLine(wp->psd, lminx, topy, lminx, boty, TRUE); GdLine(wp->psd, rminx, topy, rminx, boty, TRUE); } else { GdFillRect(wp->psd, lminx, tminy, width + bs * 2, bs); GdFillRect(wp->psd, lminx, bminy, width + bs * 2, bs); GdFillRect(wp->psd, lminx, topy, bs, height); GdFillRect(wp->psd, rminx, topy, bs, height); } /* * Restore the true window size. * Forget the currently clipped window since we messed it up. */ wp->x += bs; wp->y += bs; wp->width -= (bs * 2); wp->height -= (bs * 2); wp->bordersize = bs; clipwp = NULL; }
BOOL WINAPI Rectangle(HDC hdc, int nLeft, int nTop, int nRight, int nBottom) { HWND hwnd; RECT rc; hwnd = MwPrepareDC(hdc); if(!hwnd) return FALSE; SetRect(&rc, nLeft, nTop, nRight, nBottom); if(MwIsClientDC(hdc)) MapWindowPoints(hwnd, NULL, (LPPOINT)&rc, 2); /* draw rectangle in current pen color*/ if(hdc->pen->style != PS_NULL) { GdSetForegroundColor(hdc->psd, hdc->pen->color); GdRect(hdc->psd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); } /* fill rectangle in current brush color*/ if(hdc->brush->style != BS_NULL) { InflateRect(&rc, -1, -1); GdSetForegroundColor(hdc->psd, hdc->brush->color); GdFillRect(hdc->psd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); } return TRUE; }
/* * Clear the specified area of a window and possibly make an exposure event. * This sets the area window to its background color or pixmap. If the * exposeflag is nonzero, then this also creates an exposure event for the * window. */ void GsWpClearWindow(GR_WINDOW *wp, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height, GR_BOOL exposeflag) { if (!wp->realized || !wp->output) return; /* * Reduce the arguments so that they actually lie within the window. */ if (x < 0) { width += x; x = 0; } if (y < 0) { height += y; y = 0; } if (x + width > wp->width) width = wp->width - x; if (y + height > wp->height) height = wp->height - y; /* * Now see if the region is really in the window. If not, then * do nothing. */ if ((x >= wp->width) || (y >= wp->height) || (width <= 0) || (height <= 0)) return; /* * Draw the background of the window. * Invalidate the current graphics context since * we are changing the foreground color and mode. */ GsSetClipWindow(wp, NULL, 0); curgcp = NULL; GdSetFillMode(GR_FILL_SOLID); if (!(wp->props & GR_WM_PROPS_NOBACKGROUND)) { GdSetMode(GR_MODE_COPY); GdSetForegroundColor(wp->psd, wp->background); if (wp->bgpixmap) { GsWpDrawBackgroundPixmap(wp, wp->bgpixmap, x, y, width, height); } else { GdFillRect(wp->psd, wp->x + x, wp->y + y, width,height); } } /* * Now do the exposure if required. */ if (exposeflag) GsDeliverExposureEvent(wp, x, y, width, height); }
/* init buffered windows by allocating pixmap buffer and clearing background*/ void GsInitWindowBuffer(GR_WINDOW *wp, GR_SIZE width, GR_SIZE height) { /* create same size RGBA pixmap for buffer*/ GR_WINDOW_ID id; /* check if buffer size changed*/ if (wp->buffer) { if (wp->width == width && wp->height == height) return; GsDestroyPixmap(wp->buffer); } id = GsNewPixmap(width, height, MWIF_RGBA8888, NULL); wp->buffer = GsFindPixmap(id); if (!wp->buffer) { wp->props &= ~(GR_WM_PROPS_BUFFERED | GR_WM_PROPS_DRAWING_DONE); return; } /* mark buffer as not ready for display*/ wp->props &= ~GR_WM_PROPS_DRAWING_DONE; /* clear buffer to background color*/ if (!(wp->props & GR_WM_PROPS_NOBACKGROUND)) { GR_PIXMAP *pp = wp->buffer; /* clip to pixmap boundaries*/ #if DYNAMICREGIONS GdSetClipRegion(pp->psd, GdAllocRectRegion(0, 0, pp->psd->xvirtres, pp->psd->yvirtres)); #else MWCLIPRECT cliprect; cliprect.x = 0; cliprect.y = 0; cliprect.width = pp->psd->xvirtres; cliprect.height = pp->psd->yvirtres; GdSetClipRects(pp->psd, 1, &cliprect); #endif clipwp = NULL; /* reset clip cache for next window draw*/ curgcp = NULL; /* invalidate gc cache since we're changing color and mode*/ GdSetFillMode(GR_FILL_SOLID); GdSetMode(GR_MODE_COPY); GdSetForegroundColor(pp->psd, wp->background); GdFillRect(pp->psd, 0, 0, pp->width, pp->height); } }
int WINAPI FillRect(HDC hdc, CONST RECT *lprc, HBRUSH hbr) { HWND hwnd; RECT rc; MWBRUSHOBJ * obr = (MWBRUSHOBJ *)hbr; COLORREF crFill; hwnd = MwPrepareDC(hdc); if(!hwnd || !obr) return FALSE; if(!lprc) { if(MwIsClientDC(hdc)) GetClientRect(hwnd, &rc); else GetWindowRect(hwnd, &rc); lprc = &rc; } else rc = *lprc; if(MwIsClientDC(hdc)) MapWindowPoints(hwnd, NULL, (LPPOINT)&rc, 2); /* handle COLOR_xxx + 1 passed as HBRUSH*/ if((intptr_t)obr <= MAXSYSCOLORS) crFill = GetSysColor((intptr_t)obr-1); else { /* get color from passed HBRUSH*/ if(obr->style == BS_NULL) return TRUE; crFill = obr->color; } /* fill rectangle in passed brush color*/ GdSetForegroundColor(hdc->psd, crFill); GdFillRect(hdc->psd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); return TRUE; }
/* * Draw a window's background pixmap. * * The flags mean: * GR_BACKGROUND_TILE- tile the pixmap across the window (default). * GR_BACKGROUND_TOPLEFT- draw the pixmap at (0,0) relative to the window. * GR_BACKGROUND_CENTER- draw the pixmap in the middle of the window. * GR_BACKGROUND_STRETCH- stretch the pixmap within the window. * GR_BACKGROUND_TRANS- if the pixmap is smaller than the window and not * using tile mode, there will be gaps around the pixmap. This flag causes * to not fill in the spaces with the background colour. */ void GsWpDrawBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height) { GR_SIZE destwidth, destheight, fillwidth, fillheight, pmwidth, pmheight; GR_COORD fromx, fromy, destx, desty, pixmapx = 0, pixmapy = 0; if(wp->bgpixmapflags & (GR_BACKGROUND_TOPLEFT|GR_BACKGROUND_STRETCH)) { pixmapx = 0; pixmapy = 0; } else if(wp->bgpixmapflags & GR_BACKGROUND_CENTER) { if(pm->width >= wp->width) pixmapx = 0; else pixmapx = (wp->width - pm->width) / 2; if(pm->height >= wp->height) pixmapy = 0; else pixmapy = (wp->height - pm->height) / 2; } else { /* GR_BACKGROUND_TILE (default)*/ GsWpTileBackgroundPixmap(wp, pm, x, y, width, height); return; } if(pm->width > wp->width) pmwidth = wp->width; else pmwidth = pm->width; if(pm->height > wp->height) pmheight = wp->height; else pmheight = pm->height; if(x > pixmapx) { destx = x; fromx = x - pixmapx; destwidth = pixmapx + pmwidth - x; } else { destx = pixmapx; fromx = 0; destwidth = x + width - pixmapx; } if(y > pixmapy) { desty = y; fromy = y - pixmapy; destheight = pixmapy + pmheight - desty; } else { desty = pixmapy; fromy = 0; destheight = y + height - pixmapy; } if(destwidth > 0 && destheight > 0) { if (wp->bgpixmapflags & GR_BACKGROUND_STRETCH) { GdStretchBlit(wp->psd, destx + wp->x, desty + wp->y, destwidth, destheight, pm->psd, fromx, fromy, pm->width, pm->height, MWROP_COPY); } else GdBlit(wp->psd, destx + wp->x, desty + wp->y, destwidth, destheight, pm->psd, fromx, fromy, MWROP_COPY); } if(wp->bgpixmapflags & (GR_BACKGROUND_TRANS|GR_BACKGROUND_STRETCH)) return; /* Fill in the gaps around the pixmap */ if(x < pixmapx) { fillwidth = pixmapx - x; if(fillwidth > width) fillwidth = width; fillheight = height; GdFillRect(wp->psd, wp->x + x, wp->y + y, fillwidth,fillheight); } if((x + width) > (pixmapx + pmwidth)) { fillwidth = (x + width) - (pixmapx + pmwidth); if(fillwidth > width) fillwidth = width; fillheight = height; if(x < (pixmapx + pmwidth)) destx = pixmapx + pmwidth + wp->x; else destx = x + wp->x; GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight); } if(y < pixmapy) { fillheight = pixmapy - y; if(fillheight > height) fillheight = height; if(x < pixmapx) destx = pixmapx + wp->x; else destx = x + wp->x; if((x + width) > (pixmapx + pmwidth)) fillwidth = pixmapx + pmwidth - destx; else fillwidth = x + width - destx; if((fillwidth > 0) && (fillheight > 0)) { GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight); } } if((y + height) > (pixmapy + pmheight)) { fillheight = (y + height) - (pixmapy + pmheight); if(fillheight > height) fillheight = height; if(x < pixmapx) destx = pixmapx + wp->x; else destx = x + wp->x; if(y < (pixmapy + pmheight)) desty = pixmapy + pmheight + wp->y; else desty = y + wp->y; if((x + width) > (pixmapx + pmwidth)) fillwidth = pixmapx + pmwidth - destx; else fillwidth = x + width - destx; if((fillwidth > 0) && (fillheight > 0)) { GdFillRect(wp->psd, destx, desty, fillwidth,fillheight); } } }
/* * Clear the specified area of a window and possibly make an exposure event. * This sets the area window to its background color or pixmap. If the * exposeflag is 1, then this also creates an exposure event for the window. * For buffered windows, mark drawing finalized and draw if * exposeflag = 2. */ void GsClearWindow(GR_WINDOW *wp, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height, int exposeflag) { if (!wp->realized || !wp->output) return; /* * Reduce the arguments so that they actually lie within the window. */ if (x < 0) { width += x; x = 0; } if (y < 0) { height += y; y = 0; } if (x + width > wp->width) width = wp->width - x; if (y + height > wp->height) height = wp->height - y; /* * Now see if the region is really in the window. If not, then * do nothing. */ if (x >= wp->width || y >= wp->height || width <= 0 || height <= 0) return; /* * Buffered window drawing. First check if drawing finalized and * set flag. Physical window background erase is never performed * with buffered windows, all drawing is postponed until the application * is finished by calling GrClearWindow(..., 2), ie. GrFlushWindow() */ if (exposeflag == 2) wp->props |= GR_WM_PROPS_DRAWING_DONE; if (wp->props & GR_WM_PROPS_BUFFERED) { /* nothing to do until drawing finalized*/ if (!(wp->props & GR_WM_PROPS_DRAWING_DONE)) return; /* prepare clipping to window boundaries*/ GsSetClipWindow(wp, NULL, 0); clipwp = NULL; /* reset clip cache since no user regions used*/ #if DEBUG_EXPOSE curgcp = NULL; GdSetFillMode(GR_FILL_SOLID); GdSetMode(GR_MODE_COPY); GdSetForegroundColor(wp->psd, MWRGB(255,255,0)); /* yellow*/ GdFillRect(wp->psd, wp->x+x, wp->y+y, width, height); usleep(500000); #endif /* copy window pixmap buffer to window*/ GdBlit(wp->psd, wp->x + x, wp->y + y, width, height, wp->buffer->psd, x, y, MWROP_COPY); return; /* don't deliver exposure events*/ } /* * Unbuffered window: erase background unless nobackground flag set */ if (!(wp->props & GR_WM_PROPS_NOBACKGROUND)) { /* perhaps find a better way of determining whether pixmap needs src_over*/ int hasalpha = wp->bgpixmap && (wp->bgpixmap->psd->data_format & MWIF_HASALPHA); /* * Draw the background of the window. * Invalidate the current graphics context since * we are changing the foreground color and mode. */ GsSetClipWindow(wp, NULL, 0); clipwp = NULL; /* reset clip cache since no user regions used*/ #if DEBUG_EXPOSE GdSetFillMode(GR_FILL_SOLID); GdSetMode(GR_MODE_COPY); GdSetForegroundColor(wp->psd, MWRGB(255,255,0)); /* yellow*/ GdFillRect(wp->psd, wp->x+x, wp->y+y, width, height); usleep(500000); #endif curgcp = NULL; GdSetFillMode(GR_FILL_SOLID); GdSetMode(GR_MODE_COPY); GdSetForegroundColor(wp->psd, wp->background); /* if background pixmap w/alpha channel and stretchblit, fill entire (clipped) window*/ if (hasalpha && wp->bgpixmapflags == GR_BACKGROUND_STRETCH) GdFillRect(wp->psd, wp->x, wp->y, wp->width, wp->height); else /* if no pixmap background clear exposed area*/ if (!wp->bgpixmap || hasalpha) /* FIXME will flash with pixmap, should check src_over*/ if (!(wp->bgpixmapflags & GR_BACKGROUND_TRANS)) GdFillRect(wp->psd, wp->x + x, wp->y + y, width, height); if (wp->bgpixmap) GsDrawBackgroundPixmap(wp, wp->bgpixmap, x, y, width, height); } /* * Do the exposure if required for unbuffered windows. */ if (exposeflag) GsDeliverExposureEvent(wp, x, y, width, height); }
/* * Draw a window's background pixmap. * * The flags mean: * GR_BACKGROUND_TILE- tile the pixmap across the window (default). * GR_BACKGROUND_TOPLEFT- draw the pixmap at (0,0) relative to the window. * GR_BACKGROUND_CENTER- draw the pixmap in the middle of the window. * GR_BACKGROUND_STRETCH- stretch the pixmap within the window. * GR_BACKGROUND_TRANS- if the pixmap is smaller than the window and not * using tile mode, there will be gaps around the pixmap. This flag causes * to not fill in the spaces with the background colour. */ void GsDrawBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x, GR_COORD y, GR_SIZE width, GR_SIZE height) { GR_SIZE destwidth, destheight, fillwidth, fillheight, pmwidth, pmheight; GR_COORD fromx, fromy, destx, desty, pixmapx = 0, pixmapy = 0; if(wp->bgpixmapflags & GR_BACKGROUND_STRETCH) { /* must use whole window coords or stretch will have incorrect ratios*/ GdStretchBlit(wp->psd, wp->x, wp->y, wp->x + wp->width, wp->y + wp->height, pm->psd, 0, 0, pm->width - 1, pm->height - 1, MWROP_SRC_OVER); return; } if(wp->bgpixmapflags == GR_BACKGROUND_TILE) { GsTileBackgroundPixmap(wp, pm, x, y, width, height); return; } if(wp->bgpixmapflags & GR_BACKGROUND_CENTER) { if (pm->width < wp->width) pixmapx = (wp->width - pm->width) / 2; if (pm->height < wp->height) pixmapy = (wp->height - pm->height) / 2; } /* topleft & center calcs*/ pmwidth = MWMIN(pm->width, wp->width); pmheight = MWMIN(pm->height, wp->height); if(x > pixmapx) { destx = x; fromx = x - pixmapx; destwidth = pixmapx + pmwidth - x; } else { destx = pixmapx; fromx = 0; destwidth = x + width - pixmapx; } if(y > pixmapy) { desty = y; fromy = y - pixmapy; destheight = pixmapy + pmheight - desty; } else { desty = pixmapy; fromy = 0; destheight = y + height - pixmapy; } if(destwidth > 0 && destheight > 0) { destwidth = MWMIN(width, destwidth); destheight = MWMIN(height, destheight); GdBlit(wp->psd, wp->x + destx, wp->y + desty, destwidth, destheight, pm->psd, fromx, fromy, MWROP_SRC_OVER); } if(wp->bgpixmapflags & GR_BACKGROUND_TRANS) return; /* Fill in the gaps around the pixmap */ if(x < pixmapx) { fillwidth = pixmapx - x; if(fillwidth > width) fillwidth = width; fillheight = height; GdFillRect(wp->psd, wp->x + x, wp->y + y, fillwidth, fillheight); } if(x + width > pixmapx + pmwidth) { fillwidth = (x + width) - (pixmapx + pmwidth); if(fillwidth > width) fillwidth = width; fillheight = height; if(x < pixmapx + pmwidth) destx = pixmapx + pmwidth + wp->x; else destx = x + wp->x; GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight); } if(y < pixmapy) { fillheight = pixmapy - y; if(fillheight > height) fillheight = height; if(x < pixmapx) destx = pixmapx + wp->x; else destx = x + wp->x; if(x + width > pixmapx + pmwidth) fillwidth = pixmapx + pmwidth - destx; else fillwidth = x + width - destx; if(fillwidth > 0 && fillheight > 0) GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight); } if(y + height > pixmapy + pmheight) { fillheight = (y + height) - (pixmapy + pmheight); if(fillheight > height) fillheight = height; if(x < pixmapx) destx = pixmapx + wp->x; else destx = x + wp->x; if(y < pixmapy + pmheight) desty = pixmapy + pmheight + wp->y; else desty = y + wp->y; if(x + width > pixmapx + pmwidth) fillwidth = pixmapx + pmwidth - destx; else fillwidth = x + width - destx; if(fillwidth > 0 && fillheight > 0) GdFillRect(wp->psd, destx, desty, fillwidth, fillheight); } }
/* internal version of ExtTextOut, passed flags for text data type*/ static BOOL MwExtTextOut(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCVOID lpszString, UINT cbCount, CONST INT *lpDx, int flags) { HWND hwnd; POINT pt; RECT rc; hwnd = MwPrepareDC(hdc); if(!hwnd) return FALSE; pt.x = x; pt.y = y; if(MwIsClientDC(hdc)) ClientToScreen(hwnd, &pt); /* optionally fill passed rectangle*/ if(lprc && (fuOptions&ETO_OPAQUE)) { rc = *lprc; if(MwIsClientDC(hdc)) MapWindowPoints(hwnd, NULL, (LPPOINT)&rc, 2); /* fill rectangle with current background color*/ GdSetForegroundColor(hdc->psd, hdc->bkcolor); GdFillRect(hdc->psd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); GdSetUseBackground(FALSE); } else { /* use current background mode for text background draw*/ GdSetUseBackground(hdc->bkmode == OPAQUE? TRUE: FALSE); /* always set background color in case GdArea is * used to draw, which compares gr_foreground != gr_background * if gr_usebg is false... */ /*if(hdc->bkmode == OPAQUE)*/ GdSetBackgroundColor(hdc->psd, hdc->bkcolor); } if (cbCount == 0) { /* Special case - no text. Used to fill rectangle. */ return TRUE; } /* nyi: lpDx*/ /* draw text in current text foreground and background color*/ GdSetForegroundColor(hdc->psd, hdc->textcolor); //GdSetFont(hdc->font->pfont); /* this whole text alignment thing needs rewriting*/ if((hdc->textalign & TA_BASELINE) == TA_BASELINE) { /* this is not right... changed for kaffe port flags |= MWTF_TOP; */ flags |= MWTF_BASELINE; } else if(hdc->textalign & TA_BOTTOM) { MWCOORD ph, pw, pb; if(lprc) pt.y += lprc->bottom - lprc->top; else { GdGetTextSize(hdc->font->pfont, lpszString, cbCount, &pw, &ph, &pb, flags); pt.y += ph; } flags |= MWTF_BOTTOM; } else flags |= MWTF_TOP; if((hdc->textalign & TA_CENTER) == TA_CENTER) { MWCOORD ph, pw, pb; GdGetTextSize(hdc->font->pfont, lpszString, cbCount, &pw, &ph, &pb, flags); pt.x -= pw/2; } else if(hdc->textalign & TA_RIGHT) { MWCOORD ph, pw, pb; GdGetTextSize(hdc->font->pfont, lpszString, cbCount, &pw, &ph, &pb, flags); pt.x -= pw; } GdText(hdc->psd, hdc->font->pfont, pt.x, pt.y, lpszString, cbCount, flags); return TRUE; }