int ProcXFixesSetRegion (ClientPtr client) { int things; RegionPtr pRegion, pNew; REQUEST (xXFixesSetRegionReq); REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq); VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq); if (things & 4) return BadLength; things >>= 3; pNew = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED); if (!pNew) return BadAlloc; if (!REGION_COPY (0, pRegion, pNew)) { REGION_DESTROY (0, pNew); return BadAlloc; } REGION_DESTROY (0, pNew); return(client->noClientException); }
int miChangePictureClip (PicturePtr pPicture, int type, pointer value, int n) { ScreenPtr pScreen = pPicture->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); pointer clientClip; int clientClipType; switch (type) { case CT_PIXMAP: /* convert the pixmap to a region */ clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value); if (!clientClip) return BadAlloc; clientClipType = CT_REGION; (*pScreen->DestroyPixmap) ((PixmapPtr) value); break; case CT_REGION: clientClip = value; clientClipType = CT_REGION; break; case CT_NONE: clientClip = 0; clientClipType = CT_NONE; break; default: clientClip = (pointer) RECTS_TO_REGION(pScreen, n, (xRectangle *) value, type); if (!clientClip) return BadAlloc; clientClipType = CT_REGION; xfree(value); break; } (*ps->DestroyPictureClip) (pPicture); pPicture->clientClip = clientClip; pPicture->clientClipType = clientClipType; pPicture->stateChanges |= CPClipMask; return Success; }
int ProcXFixesCreateRegion (ClientPtr client) { int things; RegionPtr pRegion; REQUEST (xXFixesCreateRegionReq); REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq); LEGAL_NEW_RESOURCE (stuff->region, client); things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq); if (things & 4) return BadLength; things >>= 3; pRegion = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED); if (!pRegion) return BadAlloc; if (!AddResource (stuff->region, RegionResType, (pointer) pRegion)) return BadAlloc; return(client->noClientException); }
Bool xf86InitFBManagerArea( ScreenPtr pScreen, int PixelArea, int Verbosity ) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xRectangle Rect[3]; RegionPtr pRegion, pScreenRegion; int nRect; Bool ret = FALSE; if (PixelArea < (pScrn->displayWidth * pScrn->virtualY)) return FALSE; Rect[0].x = Rect[0].y = 0; Rect[0].width = pScrn->displayWidth; Rect[0].height = PixelArea / pScrn->displayWidth; nRect = 1; /* Add a possible partial scanline */ if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) { Rect[1].x = 0; Rect[1].y = Rect[0].height; Rect[1].height = 1; nRect++; } /* Factor out virtual resolution */ pRegion = RECTS_TO_REGION(pScreen, nRect, Rect, 0); if (pRegion) { if (!REGION_NAR(pRegion)) { Rect[2].x = Rect[2].y = 0; Rect[2].width = pScrn->virtualX; Rect[2].height = pScrn->virtualY; pScreenRegion = RECTS_TO_REGION(pScreen, 1, &Rect[2], 0); if (pScreenRegion) { if (!REGION_NAR(pScreenRegion)) { REGION_SUBTRACT(pScreen, pRegion, pRegion, pScreenRegion); ret = xf86InitFBManagerRegion(pScreen, pRegion); if (ret && xf86GetVerbosity() >= Verbosity) { int scrnIndex = pScrn->scrnIndex; xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, "Largest offscreen areas (with overlaps):\n"); if (Rect[2].width < Rect[0].width) { xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, "\t%d x %d rectangle at %d,0\n", Rect[0].width - Rect[2].width, Rect[0].height, Rect[2].width); } if (Rect[2].width < Rect[1].width) { xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, "\t%d x %d rectangle at %d,0\n", Rect[1].width - Rect[2].width, Rect[0].height + Rect[1].height, Rect[2].width); } if (Rect[2].height < Rect[0].height) { xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, "\t%d x %d rectangle at 0,%d\n", Rect[0].width, Rect[0].height - Rect[2].height, Rect[2].height); } if (Rect[1].height) { xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, "\t%d x %d rectangle at 0,%d\n", Rect[1].width, Rect[0].height - Rect[2].height + Rect[1].height, Rect[2].height); } } } REGION_DESTROY(pScreen, pScreenRegion); } } REGION_DESTROY(pScreen, pRegion); } return ret; }
void PclPolyRectangle( DrawablePtr pDrawable, GCPtr pGC, int nRects, xRectangle *pRects) { char t[80]; FILE *outFile; int nbox, i; BoxPtr pbox; xRectangle *drawRects, *r; RegionPtr drawRegion, region; short fudge; int xoffset, yoffset; XpContextPtr pCon; PclContextPrivPtr pConPriv; if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) return; pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); pConPriv = (PclContextPrivPtr) pCon->devPrivates[PclContextPrivateIndex].ptr; /* * Allocate the storage required to deal with the clipping * regions. */ region = REGION_CREATE( pGC->pScreen, NULL, 0 ); drawRects = (xRectangle *)xalloc( nRects * sizeof( xRectangle ) ); fudge = 3 * pGC->lineWidth + 1; /* * Generate the PCL code to draw the rectangles, by defining them * as a macro which uses the HP-GL/2 rectangle drawing function. */ MACRO_START( outFile, pConPriv ); SAVE_PCL( outFile, pConPriv, "\033%0B" ); xoffset = pDrawable->x; yoffset = pDrawable->y; for( i = 0, r = drawRects; i < nRects; i++, r++ ) { xRectangle rect = pRects[i]; /* Draw the rectangle */ sprintf( t, "PU%d,%d;ER%d,%d;", rect.x + xoffset, rect.y + yoffset, rect.width, rect.height ); SAVE_PCL( outFile, pConPriv, t ); /* Build the bounding box */ r->x = MIN( rect.x, rect.x + rect.width ) + xoffset - fudge; r->y = MIN( rect.y, rect.y + rect.height ) + yoffset - fudge; r->width = rect.width + 2 * fudge; r->height = rect.height + 2 * fudge; } SAVE_PCL( outFile, pConPriv, ";\033%0A" ); /* End the macro */ MACRO_END( outFile ); /* * Convert the collection of rectangles to a proper region, then * intersect it with the clip region. */ drawRegion = RECTS_TO_REGION( pGC->pScreen, nRects, drawRects, CT_UNSORTED ); REGION_INTERSECT( pGC->pScreen, region, drawRegion, pGC->pCompositeClip ); /* * For each rectangle in the clip region, set the HP-GL/2 "input * window" and render the set of rectangles to it. */ pbox = REGION_RECTS( region ); nbox = REGION_NUM_RECTS( region ); PclSendData(outFile, pConPriv, pbox, nbox, 1.0); /* * Clean up the temporary regions */ REGION_DESTROY( pGC->pScreen, drawRegion ); REGION_DESTROY( pGC->pScreen, region ); xfree( drawRects ); }
static void exaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { ExaScreenPriv (pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); ExaPixmapPriv (pPixmap); register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1, fullY2; int partX1, partX2, partY1, partY2; int xoff, yoff; int xorg, yorg; int n; RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); /* Compute intersection of rects and clip region */ REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); REGION_INTERSECT(pScreen, pReg, pClip, pReg); if (!REGION_NUM_RECTS(pReg)) { goto out; } exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); if (pExaScr->fallback_counter || pExaScr->swappedOut || pExaPixmap->accel_blocked) { goto fallback; } /* For ROPs where overlaps don't matter, convert rectangles to region and * call exaFillRegion{Solid,Tiled}. */ if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop || pGC->alu == GXcopyInverted || pGC->alu == GXset)) { if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? pGC->fgPixel : pGC->tile.pixel, pGC->planemask, pGC->alu, pGC->clientClipType)) || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, pGC->planemask, pGC->alu, pGC->clientClipType))) { goto out; } } if (pGC->fillStyle != FillSolid && !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { goto fallback; } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = NULL; exaDoMigration (pixmaps, 1, TRUE); } if (!exaPixmapIsOffscreen (pPixmap) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { fallback: ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); goto out; } xorg = pDrawable->x; yorg = pDrawable->y; pextent = REGION_EXTENTS(pGC->pScreen, pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; extentY2 = pextent->y2; while (nrect--) { fullX1 = prect->x + xorg; fullY1 = prect->y + yorg; fullX2 = fullX1 + (int) prect->width; fullY2 = fullY1 + (int) prect->height; prect++; if (fullX1 < extentX1) fullX1 = extentX1; if (fullY1 < extentY1) fullY1 = extentY1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullY2 > extentY2) fullY2 = extentY2; if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) continue; n = REGION_NUM_RECTS (pClip); if (n == 1) { (*pExaScr->info->Solid) (pPixmap, fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); } else { pbox = REGION_RECTS(pClip); /* * clip the rectangle to each box in the clip region * this is logically equivalent to calling Intersect(), * but rectangles may overlap each other here. */ while(n--) { partX1 = pbox->x1; if (partX1 < fullX1) partX1 = fullX1; partY1 = pbox->y1; if (partY1 < fullY1) partY1 = fullY1; partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; partY2 = pbox->y2; if (partY2 > fullY2) partY2 = fullY2; pbox++; if (partX1 < partX2 && partY1 < partY2) { (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); } } } } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); out: REGION_UNINIT(pScreen, pReg); REGION_DESTROY(pScreen, pReg); }
Bool exaHWCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown) { ExaScreenPriv (pDstDrawable->pScreen); PixmapPtr pSrcPixmap, pDstPixmap; ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; int src_off_x, src_off_y; int dst_off_x, dst_off_y; RegionPtr srcregion = NULL, dstregion = NULL; xRectangle *rects; Bool ret = TRUE; /* avoid doing copy operations if no boxes */ if (nbox == 0) return TRUE; pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); pDstPixmap = exaGetDrawablePixmap (pDstDrawable); exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); rects = xalloc(nbox * sizeof(xRectangle)); if (rects) { int i; int ordering; for (i = 0; i < nbox; i++) { rects[i].x = pbox[i].x1 + dx + src_off_x; rects[i].y = pbox[i].y1 + dy + src_off_y; rects[i].width = pbox[i].x2 - pbox[i].x1; rects[i].height = pbox[i].y2 - pbox[i].y1; } /* This must match the miRegionCopy() logic for reversing rect order */ if (nbox == 1 || (dx > 0 && dy > 0) || (pDstDrawable != pSrcDrawable && (pDstDrawable->type != DRAWABLE_WINDOW || pSrcDrawable->type != DRAWABLE_WINDOW))) ordering = CT_YXBANDED; else ordering = CT_UNSORTED; srcregion = RECTS_TO_REGION(pScreen, nbox, rects, ordering); xfree(rects); if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, pGC->fillStyle, pGC->alu, pGC->clientClipType)) { dstregion = REGION_CREATE(pScreen, NullBox, 0); REGION_COPY(pScreen, dstregion, srcregion); REGION_TRANSLATE(pScreen, dstregion, dst_off_x - dx - src_off_x, dst_off_y - dy - src_off_y); } } pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap); pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap); /* Check whether the accelerator can use this pixmap. * If the pitch of the pixmaps is out of range, there's nothing * we can do but fall back to software rendering. */ if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) goto fallback; /* If the width or the height of either of the pixmaps * is out of range, check whether the boxes are actually out of the * addressable range as well. If they aren't, we can still do * the copying in hardware. */ if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { int i; for (i = 0; i < nbox; i++) { /* src */ if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) goto fallback; /* dst */ if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) goto fallback; } } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[2]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pDstPixmap; pixmaps[0].pReg = dstregion; pixmaps[1].as_dst = FALSE; pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pSrcPixmap; pixmaps[1].pReg = srcregion; exaDoMigration (pixmaps, 2, TRUE); } /* Mixed directions must be handled specially if the card is lame */ if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && reverse != upsidedown) { if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) goto out; goto fallback; } if (exaPixmapIsOffscreen(pDstPixmap)) { /* Normal blitting. */ if (exaPixmapIsOffscreen(pSrcPixmap)) { if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) { goto fallback; } while (nbox--) { (*pExaScr->info->Copy) (pDstPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*pExaScr->info->DoneCopy) (pDstPixmap); exaMarkSync (pDstDrawable->pScreen); /* UTS: mainly for SHM PutImage's secondary path. */ } else if (pSrcExaPixmap->sys_ptr) { int bpp = pSrcDrawable->bitsPerPixel; int src_stride = exaGetPixmapPitch(pSrcPixmap); CARD8 *src = NULL; if (!pExaScr->info->UploadToScreen) goto fallback; if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) goto fallback; if (pSrcDrawable->bitsPerPixel < 8) goto fallback; if (pGC && !(pGC->alu == GXcopy && EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask))) goto fallback; while (nbox--) { src = pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + src_off_y) * src_stride + (pbox->x1 + dx + src_off_x) * (bpp / 8); if (!pExaScr->info->UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (char *) src, src_stride)) goto fallback; pbox++; } } else goto fallback; } else goto fallback; goto out; fallback: ret = FALSE; out: if (dstregion) { REGION_UNINIT(pScreen, dstregion); REGION_DESTROY(pScreen, dstregion); } if (srcregion) { REGION_UNINIT(pScreen, srcregion); REGION_DESTROY(pScreen, srcregion); } return ret; }
void PsFillSpans( DrawablePtr pDrawable, GCPtr pGC, int nSpans, DDXPointPtr pPoints, int *pWidths, int fSorted) { PsOutPtr psOut; int xoffset, yoffset; xRectangle *rects, *r; RegionPtr fillRegion, region = 0; int i; int nbox; BoxPtr pbox; ColormapPtr cMap; if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; /* * Build a region out of the spans */ rects = (xRectangle *)xalloc(nSpans*sizeof(xRectangle)); xoffset = pDrawable->x; yoffset = pDrawable->y; for( i = 0, r = rects; i < nSpans; i++, r++ ) { r->x = pPoints[i].x + xoffset; r->y = pPoints[i].y + yoffset; r->width = pWidths[i]; r->height = 1; } fillRegion = RECTS_TO_REGION(pGC->pScreen, nSpans, rects, (fSorted)?CT_YSORTED:CT_UNSORTED); /* * Intersect this region with the clip region. Whatever's left, * should be filled. */ /*REGION_INTERSECT(pGC->pScreen, region, fillRegion, pGC->clientClip);*/ pbox = REGION_RECTS(region); nbox = REGION_NUM_RECTS(region); /* Enter HP-GL/2 */ /*###SEND_PCL( outFile, "\27%0B" );*/ while( nbox ) { /*### sprintf( t, "PU%d,%d;RR%d,%d;", pbox->x1, pbox->y1, pbox->x2, pbox->y2); SEND_PCL( outFile, t ); */ nbox--; pbox++; } /* Go back to PCL */ /*###SEND_PCL( outFile, "\27%0A" );*/ /* * Clean up the temporary regions */ REGION_DESTROY(pGC->pScreen, fillRegion); REGION_DESTROY(pGC->pScreen, region); xfree(rects); }
void PclPolyLine( DrawablePtr pDrawable, GCPtr pGC, int mode, int nPoints, xPoint *pPoints) { char t[80]; FILE *outFile; int xoffset = 0, yoffset = 0; int nbox; BoxPtr pbox; xRectangle *drawRects, *r; RegionPtr drawRegion, region; short fudge; int i; XpContextPtr pCon; PclContextPrivPtr pConPriv; if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) return; pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); pConPriv = (PclContextPrivPtr) pCon->devPrivates[PclContextPrivateIndex].ptr; /* * Allocate the storage required to deal with the clipping * regions. */ region = REGION_CREATE( pGC->pScreen, NULL, 0 ); drawRects = (xRectangle *) xalloc( ( nPoints - 1 ) * sizeof( xRectangle ) ); /* * Calculate the "fudge factor" based on the line width. * Multiplying by three seems to be a good first guess. * XXX I need to think of a way to test this. */ fudge = 3 * pGC->lineWidth + 1; /* * Generate the PCL code to draw the polyline, by defining it as a * macro which uses the HP-GL/2 line drawing function. */ MACRO_START( outFile, pConPriv ); SAVE_PCL( outFile, pConPriv, "\033%0B" ); sprintf( t, "PU%d,%dPD\n", pPoints[0].x + pDrawable->x, pPoints[0].y + pDrawable->y ); SAVE_PCL( outFile, pConPriv, t ); /* Move to the start of the polyline */ switch( mode ) { case CoordModeOrigin: xoffset = pDrawable->x; yoffset = pDrawable->y; SAVE_PCL( outFile, pConPriv, "PA" ); break; case CoordModePrevious: xoffset = yoffset = 0; SAVE_PCL( outFile, pConPriv, "PR" ); break; } /* * Build the "drawing region" as we build the PCL to draw the * line. */ for(i = 1, r = drawRects; i < nPoints; i++, r++ ) { if( i != 1 ) SAVE_PCL( outFile, pConPriv, "," ); sprintf( t, "%d,%d", pPoints[i].x + xoffset, pPoints[i].y + yoffset ); SAVE_PCL( outFile, pConPriv, t ); r->x = MIN( pPoints[i-1].x, pPoints[i].x ) + xoffset - fudge; r->y = MIN( pPoints[i-1].y, pPoints[i].y ) + yoffset - fudge; r->width = abs( pPoints[i-1].x - pPoints[i].x ) + 2 * fudge; r->height = abs( pPoints[i-1].y - pPoints[i].y ) + 2 * fudge; } SAVE_PCL( outFile, pConPriv, ";\033%0A" ); /* End the macro */ MACRO_END( outFile ); /* * Convert the collection of rectangles into a proper region, then * intersect it with the clip region. */ drawRegion = RECTS_TO_REGION( pGC->pScreen, nPoints - 1, drawRects, CT_UNSORTED ); if( mode == CoordModePrevious ) REGION_TRANSLATE( pGC->pScreen, drawRegion, pPoints[0].x, pPoints[0].y ); REGION_INTERSECT( pGC->pScreen, region, drawRegion, pGC->pCompositeClip ); /* * For each rectangle in the clip region, set the HP-GL/2 "input * window" and render the entire polyline to it. */ pbox = REGION_RECTS( region ); nbox = REGION_NUM_RECTS( region ); PclSendData(outFile, pConPriv, pbox, nbox, 1.0); /* * Clean up the temporary regions */ REGION_DESTROY( pGC->pScreen, drawRegion ); REGION_DESTROY( pGC->pScreen, region ); xfree( drawRects ); }
void PclPolySegment( DrawablePtr pDrawable, GCPtr pGC, int nSegments, xSegment *pSegments) { FILE *outFile, *dummy; char t[80]; int xoffset, yoffset; int nbox, i; unsigned long valid; BoxPtr pbox; xRectangle *drawRects, *r; RegionPtr drawRegion, region; short fudge; XpContextPtr pCon; PclContextPrivPtr pConPriv; GC cacheGC; if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) return; pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); pConPriv = (PclContextPrivPtr) pCon->devPrivates[PclContextPrivateIndex].ptr; /* * Allocate the storage for the temporary regions. */ region = REGION_CREATE( pGC->pScreen, NULL, 0 ); drawRects = (xRectangle *) xalloc( nSegments * sizeof( xRectangle ) ); /* * Calculate the fudge factor, based on the line width */ fudge = pGC->lineWidth * 3 + 1; /* * Turn off line joining. */ SEND_PCL( outFile, "\033%0BLA2,6;\033%0A" ); /* * Generate the PCL code to draw the segments, by defining them as * a macro which uses the HP-GL/2 line drawing function. * * XXX I wonder if this should be implemented using the Encoded * XXX Polyline function. Since I'm only sending it once, it's not * XXX necessarily too important. */ MACRO_START( outFile, pConPriv ); SAVE_PCL( outFile, pConPriv, "\033%0B" ); xoffset = pDrawable->x; yoffset = pDrawable->y; for( i = 0, r = drawRects; i < nSegments; i++, r++ ) { r->x = MIN( pSegments[i].x1, pSegments[i].x2 ) + xoffset; r->y = MIN( pSegments[i].y1, pSegments[i].y2 ) + yoffset; r->width = abs( pSegments[i].x1 - pSegments[i].x2 ); r->height = abs( pSegments[i].y1 - pSegments[i].y2 ); sprintf( t, "PU%d,%d;PD%d,%d;", pSegments[i].x1 + xoffset, pSegments[i].y1 + yoffset, pSegments[i].x2 + xoffset, pSegments[i].y2 + yoffset ); SAVE_PCL( outFile, pConPriv, t ); r->x -= fudge; r->y -= fudge; r->width += 2 * fudge; r->height += 2 * fudge; } SAVE_PCL( outFile, pConPriv, "\033%0A" ); MACRO_END ( outFile ); /* * Convert the collection of rectangles into a proper region, then * intersect it with the clip region. */ drawRegion = RECTS_TO_REGION( pGC->pScreen, nSegments, drawRects, CT_UNSORTED ); REGION_INTERSECT( pGC->pScreen, region, drawRegion, pGC->pCompositeClip ); /* * For each rectangle in the clip region, set the HP-GL/2 "input * window" and render the entire set of segments to it. */ pbox = REGION_RECTS( region ); nbox = REGION_NUM_RECTS( region ); PclSendData(outFile, pConPriv, pbox, nbox, 1.0); /* * Now we need to reset the line join mode to whatever it was at before. * The easiest way is to force the cached GC's joinstyle to be different * from the current GC's joinstyle, then re-update the GC. This way, we * don't have to duplicate code unnecessarily. */ PclGetDrawablePrivateStuff( pDrawable, &cacheGC, &valid, &dummy ); cacheGC.joinStyle = !cacheGC.joinStyle; PclSetDrawablePrivateGC( pDrawable, cacheGC ); PclUpdateDrawableGC( pGC, pDrawable, &outFile ); /* * Clean up */ REGION_DESTROY( pGC->pScreen, drawRegion ); REGION_DESTROY( pGC->pScreen, region ); xfree( drawRects ); }
static void uxa_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle * prect) { uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap; RegionPtr pReg; BoxPtr pbox; int fullX1, fullX2, fullY1, fullY2; int xoff, yoff; int xorg, yorg; int n; if (uxa_screen->info->flags & UXA_USE_GLAMOR) { int ok = 0; if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) { ok = glamor_poly_fill_rect_nf(pDrawable, pGC, nrect, prect); uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW); } if (!ok) uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect); return; } /* Compute intersection of rects and clip region */ pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); REGION_INTERSECT(pScreen, pReg, pClip, pReg); if (!REGION_NUM_RECTS(pReg)) goto out; if (uxa_screen->force_fallback) goto fallback; pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); if (!pPixmap) goto fallback; /* For ROPs where overlaps don't matter, convert rectangles to region * and call uxa_fill_region_{solid,tiled}. */ if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop || pGC->alu == GXcopyInverted || pGC->alu == GXset)) { if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && uxa_fill_region_solid(pDrawable, pReg, pGC->fillStyle == FillSolid ? pGC->fgPixel : pGC->tile. pixel, pGC->planemask, pGC->alu)) || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && uxa_fill_region_tiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, pGC->planemask, pGC->alu))) { goto out; } } if (pGC->fillStyle != FillSolid && !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { goto fallback; } if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) { goto fallback; } if (!(*uxa_screen->info->prepare_solid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { fallback: uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect); goto out; } xorg = pDrawable->x; yorg = pDrawable->y; while (nrect--) { fullX1 = prect->x + xorg; fullY1 = prect->y + yorg; fullX2 = fullX1 + (int)prect->width; fullY2 = fullY1 + (int)prect->height; prect++; n = REGION_NUM_RECTS(pClip); pbox = REGION_RECTS(pClip); /* * clip the rectangle to each box in the clip region * this is logically equivalent to calling Intersect(), * but rectangles may overlap each other here. */ while (n--) { int x1 = fullX1; int x2 = fullX2; int y1 = fullY1; int y2 = fullY2; if (pbox->x1 > x1) x1 = pbox->x1; if (pbox->x2 < x2) x2 = pbox->x2; if (pbox->y1 > y1) y1 = pbox->y1; if (pbox->y2 < y2) y2 = pbox->y2; pbox++; if (x1 >= x2 || y1 >= y2) continue; (*uxa_screen->info->solid) (pPixmap, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } } (*uxa_screen->info->done_solid) (pPixmap); out: REGION_UNINIT(pScreen, pReg); REGION_DESTROY(pScreen, pReg); }