Print Page | Close Window

SetClippingPathEvenOdd

Printed From: Debenu Quick PDF Library - PDF SDK Community Forum
Category: For Users of the Library
Forum Name: I need help - I can help
Forum Description: Problems and solutions while programming with the Debenu Quick PDF Library and Debenu PDF Viewer SDK
URL: http://www.quickpdf.org/forum/forum_posts.asp?TID=3984
Printed Date: 18 Apr 24 at 11:22PM
Software Version: Web Wiz Forums 11.01 - http://www.webwizforums.com


Topic: SetClippingPathEvenOdd
Posted By: fellafoo
Subject: SetClippingPathEvenOdd
Date Posted: 21 May 22 at 3:58PM
Hello Forum Members:

Do any of you have experience with SetClippingPath/EvenOdd?

I am able to create a path, set a clipping path, and draw a bitmap over it and have it clipped to the outer boundary of the path. However, I also need to handle voids. I've tried drawing the perimeter, setting the clipping path, then drawing the interior void and setting the clipping path, but the bitmap always gets clipped to the 'smaller' path. The EvenOdd options seems to make no difference.

Here's the gist of my code:

  if Pipe.ToPlotter then
    PrinterPDF.SaveState; { Save current clipping path (there should be none at this point). }

  { PrinterPDF Clipping Path }
  { Convert point array for clipping path }
  PDF_Pnts := PntsArr;
  PDF_Cnts := PolyCounts;
  for i := 0 to Pred(Num_Contours) do begin { x Polygons }
    SetLength(iePtsArr, PDF_Cnts^); { No. Points in curr. Polygon }
    for j := 0 to Pred(PDF_Cnts^) do begin
      iePtsArr[j] := PDF_Pnts^; { Array of points in curr. Polygon. }
      Inc(PDF_Pnts);
    end;
    Inc(PDF_Cnts);

    X1 := iePtsArr[0].X / 600; { Convert printer canvas coordinate to inches }
    Y1 := iePtsArr[0].Y / 600;
    PrinterPDF.StartPath(X1, Y1);
    for k := 1 to High(iePtsArr) do begin
      X2 := iePtsArr[k].X / 600;
      Y2 := iePtsArr[k].Y / 600;
      PrinterPDF.AddLineToPath(X2, Y2);
    end;
    //PrinterPDF.SetClippingPath;
    PrinterPDF.SetClippingPathEvenOdd;
  end;

  ImageID := PrinterPDF.AddImageFromFile(ImgFName, 6);
  if (ImageID <> 0) then begin
    PrinterPDF.SelectImage(ImageID);
    PrinterPDF.DrawRotatedImage(PDF_ImgLeft, PDF_ImgTop, PDF_ImgWidth, PDF_ImgHeight, 270);
    PrinterPDF.ReleaseImage(ImageID);
    //PrinterPDF.ClearImage(ImageID);
  end;
  PrinterPDF.LoadState; { Restore clipping path (there should be none after this point). }

Thank You,

MFM



Replies:
Posted By: kevinqpl
Date Posted: 23 May 22 at 9:17PM
Hello MFM,

I could be mistaken but I think the different clipping path modes are related to the direction of the "inner" path, in other words if the points are clockwise or anticlockwise compared to the direction of the outer curve. Although maybe it's to do with paths that overlap themselves?

In any case, the following code shows how to have a void in a clipping path. The trick is to close the outer path, then move to the start of your inner path, and close that path when its done. Finally, set the clipping path depending on the direction.

You can change AntiClockwise to True or False and it will have the same effect as the direction of the inner curve is changed.

    QP.StartPath(100, 700);
    QP.AddLineToPath(500, 700);
    QP.AddLineToPath(500, 300);
    QP.AddLineToPath(100, 300);
    QP.AddLineToPath(100, 700);
    QP.ClosePath;

    AntiClockwise := False;

    if (AntiClockwise) then
    begin
      QP.MovePath(120, 320);
      QP.AddLineToPath(480, 320);
      QP.AddLineToPath(300, 680);
      QP.ClosePath;
      QP.SetClippingPath;
    end else
    begin
      QP.MovePath(120, 320);
      QP.AddLineToPath(300, 680);
      QP.AddLineToPath(480, 320);
      QP.ClosePath;
      QP.SetClippingPathEvenOdd;
    end;

    QP.SetFillColor(1, 0, 0);
    QP.DrawCircle(300, 500, 250, 1);



Posted By: fellafoo
Date Posted: 24 May 22 at 1:18PM
Thanks Kevin,

I'll need to do some more experimenting. I was looking for a way to start a new path before setting the clipping path but assumed MovePath was for actually moving the path not an equivalent to MoveTo. So at least I've got that part straightened out.

My point arrays / loops are closed (i.e., the first and last points are the same) so I don't think I need to call ClosePath. Section '8.5.3.3 Filling' of the PDF 1.7 document describes the Nonzero Winding Number and Even-Odd rules. The point order is considered in the first case but not the second.

MFM


Posted By: fellafoo
Date Posted: 24 May 22 at 2:04PM
I've got this working as expected now. I was starting my loop at 1 instead of 0. So this is compatible with the logic I use to create polygons and clipping regions with Windows.PolyPolygon. As in...
  BeginPath(aDC);
  PolyPolygon(aDC, aPtArr^, aPtCount^, aPlyCount);
  EndPath(aDC);

  Rgn := PathToRegion(aDC);
  SelectClipRgn(aDC, Rgn);
...and what I was hoping for.



Print Page | Close Window

Forum Software by Web Wiz Forums® version 11.01 - http://www.webwizforums.com
Copyright ©2001-2014 Web Wiz Ltd. - http://www.webwiz.co.uk