void fb_graphicsflush(PSD psd) { MWRECT *prc = fb_updateregion->rects; int count = fb_updateregion->numRects; int x, y, w, h; int n = 1; /* use single bounding box extent*/ x = fb_updateregion->extents.left; y = fb_updateregion->extents.top; w = fb_updateregion->extents.right - x; h = fb_updateregion->extents.bottom - y; DPRINTF("Extents: %d (%d,%d %d,%d)\n", count, x, y, w, h); /* or loop through individual list*/ while (--count >= 0) { int rx1, ry1, rx2, ry2; rx1 = prc->left; ry1 = prc->top; rx2 = prc->right; ry2 = prc->bottom; DPRINTF(" %d: %d,%d %d,%d\n", n++, rx1, ry1, rx2-rx1, ry2-ry1); ++prc; } /* empty update region*/ GdSetRectRegion(fb_updateregion, 0, 0, 0, 0); }
/* clear update region for layered windows repainting. * Since layered windows is recursive, you cannot clear this * region after the window is painted, since other windows * may depend on repainting this region too. Instead, enqueue * a message to clear region until all painting is complete */ void chkUpdateRegion(HWND hWnd) { if (hWnd->gotClearRegionMsg == REGION_NEEDSCLEAR) { hWnd->gotClearRegionMsg = REGION_CLEARED; GdSetRectRegion(hWnd->update, 0, 0, 0, 0); } }
BOOL WINAPI EndPaint(HWND hwnd, CONST PAINTSTRUCT *lpPaint) { ReleaseDC(hwnd, lpPaint->hdc); #if UPDATEREGIONS /* don't clear update region until done dragging*/ if(mwERASEMOVE && !dragwp) GdSetRectRegion(hwnd->update, 0, 0, 0, 0); #endif ShowCaret(hwnd); return TRUE; }
/* * Allows either or both left and top to be greater than right or bottom. */ VOID WINAPI SetRectRgn( HRGN hrgn, INT left, INT top, INT right, INT bottom ) { MWRGNOBJ * obj; MWCLIPREGION *rgn; /*TRACE(region, " %04x %d,%d-%d,%d\n", hrgn, left, top, right, bottom );*/ if (!(obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION ))) return; if (left > right) { INT tmp = left; left = right; right = tmp; } if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; } rgn = obj->rgn; GdSetRectRegion(rgn, left, top, right, bottom); }
BOOL WINAPI EndPaint(HWND hwnd, CONST PAINTSTRUCT *lpPaint) { if( hwnd->paintBrush != NULL ) { SelectObject ( lpPaint->hdc, GetStockObject(NULL_BRUSH) ); DeleteObject ( hwnd->paintBrush ); hwnd->paintBrush = NULL; } if( hwnd->paintPen != NULL ) { SelectObject ( lpPaint->hdc, GetStockObject(BLACK_PEN) ); DeleteObject ( hwnd->paintPen ); hwnd->paintPen = NULL; } ReleaseDC(hwnd, lpPaint->hdc); #if UPDATEREGIONS /* don't clear update region until done dragging*/ if(mwERASEMOVE && !dragwp) GdSetRectRegion(hwnd->update, 0, 0, 0, 0); #endif ShowCaret(hwnd); return TRUE; }
/* * 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); }
/* * 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; }