/* * Create a new empty region. */ static HRGN REGION_CreateRegion(void) { MWRGNOBJ *obj; obj = GdItemNew(MWRGNOBJ); if(!obj) return NULL; obj->hdr.type = OBJ_REGION; obj->hdr.stockobj = FALSE; if(!(obj->rgn = GdAllocRegion())) { GdItemFree(obj); return NULL; } return (HRGN)obj; }
/* * Prepare to do drawing in a window or pixmap using the specified * graphics context. Returns the drawable pointer if successful, * and the type of drawing id that was supplied. Returns the special value * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless. */ GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp) { GR_WINDOW *wp; /* found window */ GR_PIXMAP *pp; /* found pixmap */ GR_GC *gcp; /* found graphics context */ GR_FONT *fontp; GR_REGION *regionp; /* user clipping region */ MWCLIPREGION *reg; PMWFONT pf; *retdp = NULL; gcp = GsFindGC(gcid); if (gcp == NULL) return GR_DRAW_TYPE_NONE; /* * If the graphics context is not the current one, then * make it the current one and remember to update it. */ if (gcp != curgcp) { curgcp = gcp; gcp->changed = GR_TRUE; } /* * Look for window or pixmap id */ pp = NULL; wp = GsFindWindow(id); if (wp == NULL) { pp = GsFindPixmap(id); if (pp == NULL) return GR_DRAW_TYPE_NONE; #if DYNAMICREGIONS reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres, pp->psd->yvirtres); /* intersect with user region if any*/ if (gcp->regionid) { regionp = GsFindRegion(gcp->regionid); if (regionp) GdIntersectRegion(reg, reg, regionp->rgn); } GdSetClipRegion(pp->psd, reg); #else { MWCLIPRECT cliprect; /* FIXME: setup pixmap clipping, different from windows*/ cliprect.x = 0; cliprect.y = 0; cliprect.width = pp->psd->xvirtres; cliprect.height = pp->psd->yvirtres; GdSetClipRects(pp->psd, 1, &cliprect); } #endif /* reset clip cache for next window draw*/ clipwp = NULL; } else { if (!wp->output) { GsError(GR_ERROR_INPUT_ONLY_WINDOW, id); return GR_DRAW_TYPE_NONE; } if (wp->unmapcount) return GR_DRAW_TYPE_NONE; /* * If the window is not the currently clipped one, * then make it the current one and define its clip rectangles. */ if (wp != clipwp || gcp->changed) { /* find user region for intersect*/ if (gcp->regionid) regionp = GsFindRegion(gcp->regionid); else regionp = NULL; /* * Special handling if user region is not at offset 0,0 */ if (regionp && (gcp->xoff || gcp->yoff)) { MWCLIPREGION *local = GdAllocRegion(); GdCopyRegion(local, regionp->rgn); GdOffsetRegion(local, gcp->xoff, gcp->yoff); GsSetClipWindow(wp, local, gcp->mode & ~GR_MODE_DRAWMASK); GdDestroyRegion(local); } else { GsSetClipWindow(wp, regionp? regionp->rgn: NULL, gcp->mode & ~GR_MODE_DRAWMASK); } } } /* * If the graphics context has been changed, then tell the * device driver about it. */ if (gcp->changed) { GdSetForeground(GdFindColor(gcp->foreground)); GdSetBackground(GdFindColor(gcp->background)); GdSetMode(gcp->mode & GR_MODE_DRAWMASK); GdSetUseBackground(gcp->usebackground); fontp = GsFindFont(gcp->fontid); pf = fontp? fontp->pfont: stdfont; GdSetFont(pf); gcp->changed = GR_FALSE; } *retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp; return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP; }
/* * Set the clip rectangles for a window taking into account other * windows that may be obscuring it. The windows that may be obscuring * this one are the siblings of each direct ancestor which are higher * in priority than those ancestors. Also, each parent limits the visible * area of the window. */ void MwSetClipWindow(HDC hdc) { HWND wp = hdc->hwnd; HWND pwp; /* parent window */ HWND sibwp; /* sibling windows */ MWCOORD diff; /* difference in coordinates */ PRECT prc; /* client or window rectangle*/ MWCLIPREGION *vis, *r; MWCOORD x, y, width, height; /* * Start with the rectangle for the complete window. * We will then cut pieces out of it as needed. */ prc = MwIsClientDC(hdc)? &wp->clirect: &wp->winrect; x = prc->left; y = prc->top; width = prc->right - prc->left; height = prc->bottom - prc->top; /* * First walk upwards through all parent windows, * and restrict the visible part of this window to the part * that shows through all of those parent windows client areas. */ pwp = wp; while (pwp != rootwp) { pwp = pwp->parent; diff = pwp->clirect.left - x; if (diff > 0) { width -= diff; x = pwp->clirect.left; } diff = pwp->clirect.right - (x + width); if (diff < 0) width += diff; diff = pwp->clirect.top - y; if (diff > 0) { height -= diff; y = pwp->clirect.top; } diff = pwp->clirect.bottom - (y + height); if (diff < 0) height += diff; } /* * If the window is completely clipped out of view, then * set the clipping region to indicate that. */ if (width <= 0 || height <= 0) { GdSetClipRegion(hdc->psd, NULL); return; } /* * Allocate initial vis region to parent-clipped size of window */ vis = GdAllocRectRegion(x, y, x+width, y+height); /* * Allocate temp region */ r = GdAllocRegion(); /* * Now examine all windows that obscure this window, and * for each obscuration, break up the clip rectangles into * the smaller pieces that are still visible. The windows * that can obscure us are the earlier siblings of all of * our parents. When clipping the root window, search all children. */ pwp = wp; while (pwp != NULL) { wp = pwp; pwp = wp->parent; if(!pwp) { /* We're clipping the root window*/ if(hdc->flags & DCX_CLIPCHILDREN) /* start with root's children*/ sibwp = rootwp->children; else sibwp = NULL; /* no search*/ wp = NULL; /* search all root's children*/ } else { if(hdc->flags & DCX_CLIPSIBLINGS) sibwp = pwp->children; else sibwp = wp; /* no search*/ } for (; sibwp != wp; sibwp = sibwp->siblings) { if (sibwp->unmapcount) continue; GdSetRectRegionIndirect(r, &sibwp->winrect); GdSubtractRegion(vis, vis, r); } /* if not clipping the root window, stop when you reach it*/ if(pwp == rootwp) break; } /* * If not the root window and we're going to be drawing * in the client area, clip all children. This is * required for non-special paint handling for child windows. * Non-client dc's don't clip children in order to get * proper border clipping in the case of border-clipped children. */ wp = hdc->hwnd; if(wp != rootwp && MwIsClientDC(hdc)) { for (sibwp=wp->children; sibwp; sibwp = sibwp->siblings) { if (sibwp->unmapcount) continue; GdSetRectRegionIndirect(r, &sibwp->winrect); GdSubtractRegion(vis, vis, r); } } #if UPDATEREGIONS /* * Intersect with update region, unless requested not to. */ if(!(hdc->flags & DCX_EXCLUDEUPDATE)) GdIntersectRegion(vis, vis, wp->update); #endif /* * Intersect with user region, if set. */ if (hdc->region) GdIntersectRegion(vis, vis, hdc->region->rgn); /* * Set the clip region (later destroy handled by GdSetClipRegion) */ GdSetClipRegion(hdc->psd, vis); /* * Destroy temp region */ GdDestroyRegion(r); }
/* * Prepare to do drawing in a window or pixmap using the specified * graphics context. Returns the drawable pointer if successful, * and the type of drawing id that was supplied. Returns the special value * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless. */ GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp) { GR_WINDOW *wp; /* found window */ GR_PIXMAP *pp; /* found pixmap */ GR_GC *gcp; /* found graphics context */ GR_REGION *regionp; /* user clipping region */ MWCLIPREGION*reg; *retdp = NULL; gcp = GsFindGC(gcid); if (gcp == NULL) return GR_DRAW_TYPE_NONE; /* * If the graphics context is not the current one, then * make it the current one and remember to update it. */ if (gcp != curgcp) { curgcp = gcp; gcp->changed = GR_TRUE; } /* * Look for window or pixmap id */ pp = NULL; wp = GsFindWindow(id); if (wp == NULL) { pp = GsFindPixmap(id); if (pp == NULL) return GR_DRAW_TYPE_NONE; havepixmap: #if DYNAMICREGIONS reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres, pp->psd->yvirtres); /* intersect with user region if any*/ if (gcp->regionid) { regionp = GsFindRegion(gcp->regionid); if (regionp) { /* handle pixmap offsets*/ if (gcp->xoff || gcp->yoff) { MWCLIPREGION *local = GdAllocRegion(); GdCopyRegion(local, regionp->rgn); GdOffsetRegion(local, gcp->xoff, gcp->yoff); GdIntersectRegion(reg, reg, local); GdDestroyRegion(local); } else GdIntersectRegion(reg, reg, regionp->rgn); } } GdSetClipRegion(pp->psd, reg); #else { MWCLIPRECT cliprect; /* FIXME: setup pixmap clipping, different from windows*/ cliprect.x = 0; cliprect.y = 0; cliprect.width = pp->psd->xvirtres; cliprect.height = pp->psd->yvirtres; GdSetClipRects(pp->psd, 1, &cliprect); } #endif /* reset clip cache for next window draw*/ clipwp = NULL; } else { if (!wp->output) { GsError(GR_ERROR_INPUT_ONLY_WINDOW, id); return GR_DRAW_TYPE_NONE; } /* check if buffered window*/ if (wp->props & GR_WM_PROPS_BUFFERED) { pp = wp->buffer; wp = NULL; goto havepixmap; /* draw into pixmap buffer*/ } if (!wp->realized) return GR_DRAW_TYPE_NONE; /* * If the window is not the currently clipped one, * then make it the current one and define its clip rectangles. */ if (wp != clipwp || gcp->changed) { #if DYNAMICREGIONS /* find user region for intersect*/ regionp = gcp->regionid? GsFindRegion(gcp->regionid): NULL; /* Special handling if user region is not at offset 0,0*/ if (regionp && (gcp->xoff || gcp->yoff)) { MWCLIPREGION *local = GdAllocRegion(); GdCopyRegion(local, regionp->rgn); GdOffsetRegion(local, gcp->xoff, gcp->yoff); GsSetClipWindow(wp, local, gcp->mode & ~GR_MODE_DRAWMASK); GdDestroyRegion(local); } else GsSetClipWindow(wp, regionp? regionp->rgn: NULL, gcp->mode & ~GR_MODE_DRAWMASK); #else GsSetClipWindow(wp, NULL, gcp->mode & ~GR_MODE_DRAWMASK); #endif /* DYNAMICREGIONS*/ } } /* * If the graphics context has been changed, then tell the * device driver about it. */ if (gcp->changed) { PSD psd = (wp ? wp->psd : pp->psd); uint32_t mask; int count; if (gcp->linestyle == GR_LINE_SOLID) { mask = 0; count = 0; } else { mask = gcp->dashmask; count = gcp->dashcount; } if (gcp->fgispixelval) GdSetForegroundPixelVal(psd, gcp->foreground); else GdSetForegroundColor(psd, gcp->foreground); if (gcp->bgispixelval) GdSetBackgroundPixelVal(psd, gcp->background); else GdSetBackgroundColor(psd, gcp->background); GdSetMode(gcp->mode & GR_MODE_DRAWMASK); GdSetUseBackground(gcp->usebackground); #if MW_FEATURE_SHAPES GdSetDash(&mask, &count); GdSetFillMode(gcp->fillmode); GdSetTSOffset(gcp->ts_offset.x, gcp->ts_offset.y); switch(gcp->fillmode) { case GR_FILL_STIPPLE: case GR_FILL_OPAQUE_STIPPLE: GdSetStippleBitmap(gcp->stipple.bitmap, gcp->stipple.width, gcp->stipple.height); break; case GR_FILL_TILE: GdSetTilePixmap(gcp->tile.psd, gcp->tile.width, gcp->tile.height); break; } #endif gcp->changed = GR_FALSE; } *retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp; return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP; }
/* * Set the clip rectangles for a window taking into account other * windows that may be obscuring it. The windows that may be obscuring * this one are the siblings of each direct ancestor which are higher * in priority than those ancestors. Also, each parent limits the visible * area of the window. The clipping is not done if it is already up to * date of if the window is not outputtable. */ void GsSetClipWindow(GR_WINDOW *wp, MWCLIPREGION *userregion, int flags) { GR_WINDOW *orgwp; /* original window pointer */ GR_WINDOW *pwp; /* parent window */ GR_WINDOW *sibwp; /* sibling windows */ GR_COORD minx; /* minimum clip x coordinate */ GR_COORD miny; /* minimum clip y coordinate */ GR_COORD maxx; /* maximum clip x coordinate */ GR_COORD maxy; /* maximum clip y coordinate */ GR_COORD diff; /* difference in coordinates */ GR_SIZE bs; /* border size */ GR_COORD x, y, width, height; MWCLIPREGION *vis, *r; if (wp->unmapcount || !wp->output) return; clipwp = wp; /* * Start with the rectangle for the complete window. * We will then cut pieces out of it as needed. */ x = wp->x; y = wp->y; width = wp->width; height = wp->height; /* * First walk upwards through all parent windows, * and restrict the visible part of this window to the part * that shows through all of those parent windows. */ pwp = wp; while (pwp != rootwp) { pwp = pwp->parent; diff = pwp->x - x; if (diff > 0) { width -= diff; x = pwp->x; } diff = (pwp->x + pwp->width) - (x + width); if (diff < 0) width += diff; diff = pwp->y - y; if (diff > 0) { height -= diff; y = pwp->y; } diff = (pwp->y + pwp->height) - (y + height); if (diff < 0) height += diff; } /* * If the window is completely clipped out of view, then * set the clipping region to indicate that. */ if (width <= 0 || height <= 0) { GdSetClipRegion(clipwp->psd, NULL); return; } /* * Allocate region to clipped size of window */ vis = GdAllocRectRegion(x, y, x+width, y+height); /* * Allocate temp region */ r = GdAllocRegion(); /* * Now examine all windows that obscure this window, and * for each obscuration, break up the clip rectangles into * the smaller pieces that are still visible. The windows * that can obscure us are the earlier siblings of all of * our parents. */ orgwp = wp; pwp = wp; while (pwp != NULL) { wp = pwp; pwp = wp->parent; if(!pwp) { /* We're clipping the root window*/ if (!(flags & GR_MODE_EXCLUDECHILDREN)) /* start with root's children*/ sibwp = rootwp->children; else sibwp = NULL; /* no search*/ wp = NULL; /* search all root's children*/ } else { sibwp = pwp->children; /* clip siblings*/ } for (; sibwp != wp; sibwp = sibwp->siblings) { if (sibwp->unmapcount || !sibwp->output) continue; bs = sibwp->bordersize; minx = sibwp->x - bs; miny = sibwp->y - bs; maxx = sibwp->x + sibwp->width + bs; maxy = sibwp->y + sibwp->height + bs; GdSetRectRegion(r, minx, miny, maxx, maxy); GdSubtractRegion(vis, vis, r); } /* if not clipping the root window, stop when you reach it*/ if (pwp == rootwp) break; } wp = orgwp; /* * If not the root window, clip all children. * (Root window's children are are clipped above) */ if(wp != rootwp && !(flags & GR_MODE_EXCLUDECHILDREN)) { for (sibwp=wp->children; sibwp; sibwp = sibwp->siblings) { if (sibwp->unmapcount || !sibwp->output) continue; bs = sibwp->bordersize; minx = sibwp->x - bs; miny = sibwp->y - bs; maxx = sibwp->x + sibwp->width + bs; maxy = sibwp->y + sibwp->height + bs; GdSetRectRegion(r, minx, miny, maxx, maxy); GdSubtractRegion(vis, vis, r); } } /* * Intersect with user region, if set. */ if (userregion) { /* temporarily offset region by window coordinates*/ GdOffsetRegion(userregion, wp->x, wp->y); GdIntersectRegion(vis, vis, userregion); GdOffsetRegion(userregion, -wp->x, -wp->y); } /* * Set the clip region (later destroy handled by GdSetClipRegion) */ GdSetClipRegion(clipwp->psd, vis); /* * Destroy temp region */ GdDestroyRegion(r); }
/* init framebuffer*/ static PSD fb_open(PSD psd) { PSUBDRIVER subdriver; char *env; /* set statically in struct definition, may be overridden before calling fb_open*/ //psd->xres = psd->xvirtres = SCREEN_WIDTH; //psd->yres = psd->yvirtres = SCREEN_HEIGHT; /* use pixel format to set bpp*/ psd->pixtype = MWPIXEL_FORMAT; switch (psd->pixtype) { case MWPF_TRUECOLORARGB: case MWPF_TRUECOLORABGR: default: psd->bpp = 32; break; case MWPF_TRUECOLORRGB: psd->bpp = 24; break; case MWPF_TRUECOLOR565: case MWPF_TRUECOLOR555: psd->bpp = 16; break; case MWPF_TRUECOLOR332: psd->bpp = 8; break; #if MWPIXEL_FORMAT == MWPF_PALETTE case MWPF_PALETTE: psd->bpp = SCREEN_DEPTH; break; #endif } psd->planes = 1; /* set standard data format from bpp and pixtype*/ psd->data_format = set_data_format(psd); /* Calculate the correct size and pitch from xres, yres and bpp*/ GdCalcMemGCAlloc(psd, psd->xres, psd->yres, psd->planes, psd->bpp, &psd->size, &psd->pitch); psd->ncolors = (psd->bpp >= 24)? (1 << 24): (1 << psd->bpp); psd->flags = PSF_SCREEN; psd->portrait = MWPORTRAIT_NONE; /* select an fb subdriver matching our planes and bpp for backing store*/ subdriver = select_fb_subdriver(psd); psd->orgsubdriver = subdriver; if (!subdriver) return NULL; /* set subdriver into screen driver*/ set_subdriver(psd, subdriver); #ifdef PATH_FRAMEBUFFER /* try opening framebuffer file for mmap*/ if((env = getenv("FRAMEBUFFER")) == NULL) env = PATH_FRAMEBUFFER; fb = open(env, O_RDWR); #endif if (fb >= 0) { /* mmap framebuffer into this address space*/ psd->size = (psd->size + getpagesize() - 1) / getpagesize() * getpagesize(); psd->addr = mmap(NULL, psd->size, PROT_READ|PROT_WRITE, MAP_SHARED, fb, 0); if (psd->addr == NULL || psd->addr == (unsigned char *)-1) { EPRINTF("Error mmaping shared framebuffer %s: %m\n", env); close(fb); return NULL; } } else { /* allocate framebuffer*/ if ((psd->addr = malloc(psd->size)) == NULL) return NULL; psd->flags |= PSF_ADDRMALLOC; } /* allocate update region*/ fb_updateregion = GdAllocRegion(); return psd; /* success*/ }
/* * Initialize the graphics and mouse devices at startup. * Returns nonzero with a message printed if the initialization failed. */ int MwInitialize(void) { HWND wp; /* root window */ PSD psd; WNDCLASS wc; int fd; static MWCURSOR arrow = { /* default arrow cursor*/ 16, 16, 0, 0, RGB(255, 255, 255), RGB(0, 0, 0), { 0xe000, 0x9800, 0x8600, 0x4180, 0x4060, 0x2018, 0x2004, 0x107c, 0x1020, 0x0910, 0x0988, 0x0544, 0x0522, 0x0211, 0x000a, 0x0004 }, { 0xe000, 0xf800, 0xfe00, 0x7f80, 0x7fe0, 0x3ff8, 0x3ffc, 0x1ffc, 0x1fe0, 0x0ff0, 0x0ff8, 0x077c, 0x073e, 0x021f, 0x000e, 0x0004 } }; extern MWLISTHEAD mwClassHead; #if (UNIX | DOS_DJGPP) && !_MINIX for (fd = 0; fd < FD_SETSIZE; fd++) { userregfd[fd].read = NULL; userregfd[fd].write = NULL; userregfd[fd].except = NULL; userregfd[fd].next = -1; } userregfd_head = -1; #endif /* catch terminate signal to restore tty state*/ signal(SIGTERM, (void *)MwTerminate); startTicks = GetTickCount(); if ((keyb_fd = GdOpenKeyboard()) == -1) { EPRINTF("Cannot initialise keyboard\n"); return -1; } if ((psd = GdOpenScreen()) == NULL) { EPRINTF("Cannot initialise screen\n"); GdCloseKeyboard(); return -1; } if ((mouse_fd = GdOpenMouse()) == -1) { EPRINTF("Cannot initialise mouse\n"); GdCloseScreen(psd); GdCloseKeyboard(); return -1; } #if ANIMATEPALETTE setfadelevel(psd, 0); #endif /* * Initialize the root window. */ wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW; wc.lpfnWndProc = (WNDPROC)DefWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = 0; wc.hIcon = 0; /*LoadIcon(GetHInstance(), MAKEINTRESOURCE( 1));*/ wc.hCursor = 0; /*LoadCursor(NULL, IDC_ARROW);*/ wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND)); wc.lpszMenuName = NULL; wc.lpszClassName = "DeskTop"; RegisterClass( &wc); wp = GdItemNew(struct hwnd); if (!wp) { EPRINTF("No memory for root window\n"); GdCloseMouse(); GdCloseScreen(psd); GdCloseKeyboard(); return -1; } /* remove the WS_CAPTION to have bare desktop window*/ /*wp->style = WS_CLIPCHILDREN | WS_CAPTION | WS_VISIBLE;*/ wp->style = WS_CLIPCHILDREN | WS_VISIBLE; wp->exstyle = 0; wp->pClass = (PWNDCLASS)mwClassHead.head; wp->parent = NULL; wp->children = NULL; wp->siblings = NULL; wp->next = NULL; SetRect(&wp->winrect, 0, 0, psd->xvirtres, psd->yvirtres); MwCalcClientRect(wp); wp->cursor = NULL; wp->unmapcount = 0; wp->id = 0; strcpy(wp->szTitle, "Microwindows"); wp->gotPaintMsg = PAINT_PAINTED; #if UPDATEREGIONS wp->update = GdAllocRegion(); #endif listwp = wp; rootwp = wp; focuswp = wp; mousewp = wp; /* schedule desktop window paint*/ InvalidateRect(rootwp, NULL, TRUE); #if VTSWITCH MwInitVt(); /* Check for VT change every 50 ms: */ GdAddTimer(50, CheckVtChange, NULL); #endif /* * Initialize and position the default cursor. */ curcursor = NULL; cursorx = -1; cursory = -1; GdShowCursor(psd); MwMoveCursor(psd->xvirtres / 2, psd->yvirtres / 2); MwSetCursor(rootwp, &arrow); /* * Finally tell the mouse driver some things. */ GdRestrictMouse(0, 0, psd->xvirtres - 1, psd->yvirtres - 1); GdMoveMouse(psd->xvirtres / 2, psd->yvirtres / 2); return 0; }
HWND WINAPI CreateWindowEx(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { HWND pwp; /* parent window */ HWND wp; /* new window */ HWND hwndOwner; PWNDCLASS pClass; CREATESTRUCT cs; int titLen; static int nextx = 20; static int nexty = 20; /* WARNING: All modification made here should be reported on MwInitialize for the rootwp window */ pClass = MwFindClassByName(lpClassName); if(!pClass) return NULL; if(x == CW_USEDEFAULT || y == CW_USEDEFAULT) { x = nextx; nextx += 10; y = nexty; nexty += 10; if(nextx > 200) nextx = nexty = 20; } if(nWidth == CW_USEDEFAULT || nHeight == CW_USEDEFAULT) { nWidth = 250; nHeight = 250; } if(hwndParent == NULL) { if(dwStyle & WS_CHILD) return NULL; pwp = rootwp; } else pwp = hwndParent; /* WS_POPUP z-order parent is the root window (passed parent is owner)*/ if(dwStyle & WS_POPUP) pwp = rootwp; /* force clip to root, not z-parent*/ /* window owner is NULL for child windows, else it's the passed parent*/ if(dwStyle & WS_CHILD) hwndOwner = NULL; else hwndOwner = hwndParent; wp = (HWND)GdItemAlloc(sizeof(struct hwnd) - 1 + pClass->cbWndExtra); if(!wp) return NULL; /* force all clipping on by default*/ dwStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; wp->pClass = pClass; wp->lpfnWndProc = pClass->lpfnWndProc; wp->style = dwStyle; wp->exstyle = dwExStyle; wp->parent = pwp; wp->owner = hwndOwner; wp->children = NULL; wp->siblings = pwp->children; pwp->children = wp; wp->next = listwp; listwp = wp; wp->winrect.left = pwp->clirect.left + x; wp->winrect.top = pwp->clirect.top + y; wp->winrect.right = wp->winrect.left + nWidth; wp->winrect.bottom = wp->winrect.top + nHeight; wp->cursor = pwp->cursor; wp->cursor->usecount++; wp->unmapcount = pwp->unmapcount + 1; wp->id = (int)hMenu; wp->gotPaintMsg = PAINT_PAINTED; titLen = 0; if (lpWindowName != NULL) titLen = strlen(lpWindowName); if (titLen < 64) titLen = 64; /* old mw compatibility */ wp->szTitle = (LPTSTR)malloc(titLen + 1); if (wp->szTitle == NULL) { free(wp); return NULL; } if (lpWindowName != NULL) strcpy(wp->szTitle, lpWindowName); else wp->szTitle[0] = '\0'; #if UPDATEREGIONS wp->update = GdAllocRegion(); #endif wp->nextrabytes = pClass->cbWndExtra; wp->hInstance = hInstance; wp->nEraseBkGnd = 1; wp->paintBrush = NULL; wp->paintPen = NULL; /* calculate client area*/ MwCalcClientRect(wp); cs.lpCreateParams = lpParam; cs.hInstance = hInstance; cs.hMenu = hMenu; cs.hwndParent = hwndParent; cs.cy = nHeight; cs.cx = nWidth; cs.y = y; cs.x = x; cs.style = dwStyle; cs.lpszName = lpWindowName; cs.lpszClass = lpClassName; cs.dwExStyle = dwExStyle; if(SendMessage(wp, WM_CREATE, 0, (LPARAM)(LPSTR)&cs) == -1) { MwDestroyWindow(wp, FALSE); return NULL; } /* send SIZE and MOVE msgs*/ MwSendSizeMove(wp, TRUE, TRUE); if(wp->style & WS_VISIBLE) { MwShowWindow(wp, TRUE); SetFocus(wp); } return wp; }
/* * GdAllocPolyPolygonRegion */ MWCLIPREGION * GdAllocPolyPolygonRegion(MWPOINT *points, int *count, int nbpolygons, int mode) { MWCLIPREGION *rgn; EdgeTableEntry *pAET; /* Active Edge Table */ int y; /* current scanline */ int iPts = 0; /* number of pts in buffer */ EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/ ScanLineList *pSLL; /* current scanLineList */ MWPOINT *pts; /* output buffer */ EdgeTableEntry *pPrevAET; /* ptr to previous AET */ EdgeTable ET; /* header node for ET */ EdgeTableEntry AET; /* header node for AET */ EdgeTableEntry *pETEs; /* EdgeTableEntries pool */ ScanLineListBlock SLLBlock; /* header for scanlinelist */ int fixWAET = FALSE; POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */ POINTBLOCK *tmpPtBlock; int numFullPtBlocks = 0; int poly, total; if(!(rgn = GdAllocRegion())) return NULL; /* special case a rectangle */ if (((nbpolygons == 1) && ((*count == 4) || ((*count == 5) && (points[4].x == points[0].x) && (points[4].y == points[0].y)))) && (((points[0].y == points[1].y) && (points[1].x == points[2].x) && (points[2].y == points[3].y) && (points[3].x == points[0].x)) || ((points[0].x == points[1].x) && (points[1].y == points[2].y) && (points[2].x == points[3].x) && (points[3].y == points[0].y)))) { GdSetRectRegion( rgn, MWMIN(points[0].x, points[2].x), MWMIN(points[0].y, points[2].y), MWMAX(points[0].x, points[2].x), MWMAX(points[0].y, points[2].y) ); return rgn; } for(poly = total = 0; poly < nbpolygons; poly++) total += count[poly]; if (! (pETEs = malloc( sizeof(EdgeTableEntry) * total ))) { GdDestroyRegion( rgn ); return 0; } pts = FirstPtBlock.pts; REGION_CreateETandAET(count, nbpolygons, points, &ET, &AET, pETEs, &SLLBlock); pSLL = ET.scanlines.next; curPtBlock = &FirstPtBlock; if (mode != MWPOLY_WINDING) { /* * for each scanline */ for (y = ET.ymin; y < ET.ymax; y++) { /* * Add a new edge to the active edge table when we * get to the next edge. */ if (pSLL != NULL && y == pSLL->scanline) { REGION_loadAET(&AET, pSLL->edgelist); pSLL = pSLL->next; } pPrevAET = &AET; pAET = AET.next; /* * for each active edge */ while (pAET) { pts->x = pAET->bres.minor_axis, pts->y = y; pts++, iPts++; /* * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { tmpPtBlock = malloc( sizeof(POINTBLOCK)); if(!tmpPtBlock) { return 0; } curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; pts = curPtBlock->pts; numFullPtBlocks++; iPts = 0; } EVALUATEEDGEEVENODD(pAET, pPrevAET, y); } REGION_InsertionSort(&AET); } } else { /* * for each scanline */ for (y = ET.ymin; y < ET.ymax; y++) { /* * Add a new edge to the active edge table when we * get to the next edge. */ if (pSLL != NULL && y == pSLL->scanline) { REGION_loadAET(&AET, pSLL->edgelist); REGION_computeWAET(&AET); pSLL = pSLL->next; } pPrevAET = &AET; pAET = AET.next; pWETE = pAET; /* * for each active edge */ while (pAET) { /* * add to the buffer only those edges that * are in the Winding active edge table. */ if (pWETE == pAET) { pts->x = pAET->bres.minor_axis, pts->y = y; pts++, iPts++; /* * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { tmpPtBlock = malloc( sizeof(POINTBLOCK) ); if(!tmpPtBlock) { return 0; } curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; pts = curPtBlock->pts; numFullPtBlocks++; iPts = 0; } pWETE = pWETE->nextWETE; } EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); } /* * recompute the winding active edge table if * we just resorted or have exited an edge. */ if (REGION_InsertionSort(&AET) || fixWAET) { REGION_computeWAET(&AET); fixWAET = FALSE; } } } REGION_FreeStorage(SLLBlock.next); REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, rgn); for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { tmpPtBlock = curPtBlock->next; free( curPtBlock ); curPtBlock = tmpPtBlock; } free( pETEs ); return rgn; }
/** * Set a clip region for future drawing actions. * Each pixel will be drawn only if lies in one or more of the contained * clip rectangles. All clip rectangles are modified * if necessary to lie within the device area. Call only after device * has been initialized. * * @param psd Drawing surface. * @param reg New clipping region. */ void GdSetClipRegion(PSD psd, MWCLIPREGION *reg) { if(clipregion) GdDestroyRegion(clipregion); if(!reg) reg = GdAllocRegion(); clipregion = reg; #if 0 MWRECT rc; /* Copy the clip table to our own static array, modifying each * rectangle as necesary to fit within the device area. If the clip * rectangle lies entirely outside of the device area, then skip it. */ while (count-- > 0) { MWCLIPRECT cr; MWCLIPRECT *rp = &cr; *rp = *table++; if (rp->x < 0) { rp->width += rp->x; rp->x = 0; } if (rp->y < 0) { rp->height += rp->y; rp->y = 0; } if ((rp->x >= psd->xvirtres) || (rp->width <= 0) || (rp->y >= psd->yvirtres) || (rp->height <= 0)) continue; if (rp->x + rp->width > psd->xvirtres) rp->width = psd->xvirtres - rp->x; if (rp->y + rp->height > psd->yvirtres) rp->height = psd->yvirtres - rp->y; rc.left = rp->x; rc.top = rp->y; rc.right = rp->x+rp->width; rc.bottom = rp->y+rp->height; GdUnionRectWithRegion(&rc, clipregion); } #endif /* If there were no surviving clip rectangles, then set the clip * cache to prevent all drawing. */ if (clipregion->numRects == 0) { clipminx = MIN_MWCOORD; clipminy = MIN_MWCOORD; clipmaxx = MAX_MWCOORD; clipmaxy = MAX_MWCOORD; clipresult = FALSE; return; } /* There was at least one valid clip rectangle. Default the clip * cache to be the first clip rectangle. */ clipminx = clipregion->rects[0].left; clipminy = clipregion->rects[0].top; clipmaxx = clipregion->rects[0].right - 1; clipmaxy = clipregion->rects[0].bottom - 1; clipresult = TRUE; }