Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
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);
}
Example #4
0
File: xf86fbman.c Project: aosm/X11
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;
}
Example #5
0
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 );
}
Example #6
0
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);
}
Example #7
0
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;
}
Example #8
0
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);
}
Example #9
0
File: PclLine.c Project: aosm/X11
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 );
}
Example #10
0
File: PclLine.c Project: aosm/X11
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 );
}
Example #11
0
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);
}