Skip to content

PDFDocument: More PDFGraphics Enhancements

With the added functionality of the Brush property and the ClipToPath, Clip and DrawObject methods, Xojo 2022r1 completes the practical PDFGraphics class support for all the methods and properties that makes sense (or are applicable) from Xojo’s Graphics class.

Fillings and Drawing with Brush

The Brush property allows you to assign, well, a brush to the current Graphics context in order to use it as the drawing color or filling for any of the available shapes when drawing text and also in drawing vectorial paths into the PDF document. When the Brush property is set to Nil, then the color set via DrawingColor will be applied.

What makes the Brush property especially interesting is that you can assign to it any instance created from the PictureBrush, LinearGradientBrush or RadialGradientBrush classes.

  • PictureBrush. PDFGraphics only supports the Tile, so the picture will be repeated until completing the filling area.
  • LinearGradientBrush. PDFGraphics offers the same support you expect when it is used in combination with the regular Graphics class.
  • RadialGradientBrush. PDFGraphics offers the same support you expect when it is used in combination with the regular Graphics class.

The following image shows a PDF with PictureBrush applied as the color for the text, RadialGradientBrush set to fill the lower rectangle, and also as the outline color for drawing the “The Golden” text. Additionally, a LinearGradientBrush is used to fill the upper rectangle. The graphic context has been set to use a transparency value when drawing the text, so it also affect the transparency of the filling brush on these.

ClipToPath

In opposition to ClipToRectangle or Clip, the ClipToPath method allows the definition of a irregular area that will act as the cropping area for any later drawing in the PDF, while ClipToRectangle and Clip provide regular areas: rectangles or squares.

When used in combination with PDFGraphics , expect the same behavior as when used in combination with a regular context from the Graphics class. For example, while the following snippet of code will draw a circle, only the portion contained in the ClipToPath set will be visible (a triangle), as you can see in the picture below from the generated PDF.

Var d As New PDFDocument
Var g As Graphics = d.Graphics

// Clip to a GraphicsPath
// Path is a triangle
Var p As New GraphicsPath
p.MoveToPoint(0, 0) // Start location
p.AddLineToPoint(20, 44)
p.AddLineToPoint(40, 0)
p.AddLineToPoint(0, 0)

g.SaveState
g.DrawingColor = Color.Red
g.ClipToPath(p)
g.FillOval(0, 0, 50, 50)
g.RestoreState

Var f As FolderItem = SpecialFolder.Desktop.Child("Cliptopath.pdf")
d.Save(f)

Clip: New Graphic Contexts

In opposition to ClipToRectangle and ClipToPath, the Clip method is more powerful because it not only provides a cropping area but a fully new Graphic context. That is, you’ll be able to set any of the properties on the returned Graphics.Clip context and also call any of the PDFGraphics supported methods on it.

In this regard, all the coordinates provided for the drawing are relative to the top/left of the new Clip, and not on the main Graphics context it is based on. So, if we run the following snippet of code:

Var d As New PDFDocument
Var g As Graphics = d.Graphics

g.FontSize = 40
g.DrawText("Hello…", 40, 100)

// Getting a new graphics context via Clip
// We change the Font and the 
// drawing color

Var g1 As Graphics = g.Clip(40, 130, 170, 50)
g1.FontName = "Times"
g1.DrawingColor = Color.Red
g1.DrawText("…World!", 0, 0)

// Back To drawing on the main Graphics context. 
// It Is Not affected by the changes made in the graphics subcontext from Clip.

g.DrawText("(Back to Main Graphics context)", 40, 240)

We can see how the line of code g1.DrawTex "…World!", 0, 0 provides 0,0 as the X and Y coordinates for drawing the text. That is, the top/left origin of the created clip, while these values would be 40,130 as absolute coordinates if we had used the main graphics context.

The PDF generated as result of the previous code is the one shown in the following picture:

Of course, you can nest as many Clips as you need. For example you can create a new Clip from a previous clip created in a previous step.

DrawObject

PDFGraphics also allows you to draw any of the objects created as instances from any of the Object2D class, and also those under the hierarchy of a Group2D object:

For example, the following snippet of code will create the PDF document you can see in the picture.:

Var c As New CurveShape
c.ControlX(0) = 120
c.ControlY(0) = -40
c.Order = 1
c.X = 10
c.Y = 100
c.X2 = 250
c.Y2 = 100

Var fx As New FigureShape
fx.AddLine(0, 100, 50, 0)
fx.AddLine(50, 0, -50, 0)
fx.Border = 100  // opaque border
fx.BorderColor = &cFF0000  // red border
fx.FillColor = &cFFFF00   // yellow interior

Var d As New PDFDocument

Var g As Graphics = d.Graphics
g.DrawObject(c, c.x, c.y)
g.DrawObject(fx, 100, 100)

d.Save(SpecialFolder.Desktop.Child("CurveShape.PDF"))

Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at Goto 10 and on Mastodon @lefebvre@hachyderm.io.