# GAMBAS BOOK 3.19.1

## 2D-Graphic

### Chapters

08.10.2022
k25:k25.1.6:start

## 25.1.6 CairoExtents

The CairoExtents class provides an extended bounding box as returned by the Cairo.ClipExtents or Cairo.FillExtents properties.

Figure 25.1.6.1: Bounding box

## 25.1.6.1 Properties

The CairoExtents class has these four properties:

PropertyData typeDescription
X1FloatReturns the x-coordinate of the upper left point (LT) of the bounding box.
Y1FloatReturns the y-coordinate of the upper left point (LT) of the bounding box.
X2FloatReturns the x-coordinate of the lower right point (RB) of the bounding box.
Y2FloatReturns the y-coordinate of the lower right point (RB) of the bounding box.

Table 25.1.6.1.1 : Properties of the CairoExtents class

## 25.1.6.2 Method

The class CairoExtents has only one method:

`Function Merge ( Extents As CairoExtents ) As CairoExtents`

The Merge() method returns the smallest rectangle of type CairoExtents that contains the union of the two extents.

It merges both extents E (current bounding box) and F (argument of the merge function) into one extent G. G is the smallest rectangle that contains both E and F. A fictitious implementation of the merge function could be formulated in Gambas as follows

```G.X  = Min(E.X,  F.X)
G.Y  = Min(E.Y,  F.Y)
G.X2 = Max(E.X2, F.X2)
G.Y2 = Max(E.Y2, F.Y2)```

The current bounding box E is then replaced by the new bounding box G.

## 25.1.6.3 Example 1 - Cairo.ClipExtents

The Clip method intersects the current clip area with the current path (using the active FillRule) to create a new clip area. If you define a clip area for the interface used, you can read this area at any time using the Cairo.ClipExtents property of type CairoExtents. In example 1, the standard clip area is read out first, then only the effect of the Cairo.Clip method with an empty (current) path is analysed and finally a (rectangular) clip area is defined and its area is read out.

Only 3 procedures are presented in the source code snippet:

```[1] Private Sub GeneratePDF()
[2]   Dim PDFSurface As CairoPdfSurface
[3]
[4]   PDFSurface = New CairoPdfSurface(sPfadPDFDatei, 210, 297) ' -->> DIN A4 surface area
[5]
[6]   Cairo.Begin(PDFSurface)
[7]     Cairo.Matrix.Translate(MMToPoints(20), MMToPoints(20))
[8]     Cairo.Matrix.Scale(1, 1) '-- Zoom factor = 1
[9]
[10] '-- Cairo.Rectangle(MMToPoints(0), MMToPoints(0), MMToPoints(175), MMToPoints(257))
[11] '-- Cairo.Clip
[12]
[13]     Print "X1 = "; Round(PointsToMM(Cairo.ClipExtents.X1), 0)
[14]     Print "Y1 = "; Round(PointsToMM(Cairo.ClipExtents.Y1), 0)
[15]     Print "X2 = "; Round(PointsToMM(Cairo.ClipExtents.X2), 0)
[16]     Print "Y1 = "; Round(PointsToMM(Cairo.ClipExtents.Y2), 0)
[17]
[18]     Cairo.Arc(MMToPoints(50), MMToPoints(70), MMToPoints(80))
[19]     Cairo.Source = Cairo.ColorPattern(&HC3DDFF)
[20]     Cairo.AntiAlias = True
[21]     Cairo.Fill()
[22]
[23]     Cairo.AntiAlias = False
[24]     Cairo.Rectangle(MMToPoints(0), MMToPoints(0), MMToPoints(175), MMToPoints(257))
[25]     Cairo.Source = Cairo.ColorPattern(Color.Black)
[26]     Cairo.LineWidth = 1
[27]     Cairo.Dash = [1, 1]
[28]     Cairo.Stroke()
[29]     Cairo.Dash = []
[30]   Cairo.End()
[31]
[32]   PDFSurface.Finish()
[33]
[34] End
[35]
[36] Private Function MMToPoints(Value As Float) As Float
[37]   Return Value * 2.83527
[38] End
[39]
[40] Private Function PointsToMM(Value As Float) As Float
[41]   Return Value * 0.3527
[42] End```

Comment:

• You can use the last two functions to convert user coordinates to millimetres and coordinates in millimetres to user coordinates very conveniently.
• The changes in lines 10 and 11 are interesting. In the first case, both lines are commented out, resulting in the following coordinates for the clip bounding box:
`Clip area = original surface (device) with X1 = -20, Y1 = -20, X2 = +190, Y2 = +277`

The results correspond to the settings for the translation of the Cairo coordinate system: 20mm in the x-direction and 20mm in the y-direction (which points downwards!). This results in exactly the width of 210mm and the height of 297mm for an A4 surface.

In the second case, only line 10 is commented out, resulting in the following coordinates for the current clip bounding box:

`Clip area = empty rectangle with X1 = -20, Y1 = -20, X2 = -20, Y2 = -20`

This means that all further instructions for drawing have no effect - you will not see anything on the surface, even though it has been drawn correctly and without errors!

In the third case, lines 10 and 11 are active, resulting in the following coordinates for the current clip bounding box:

`Clip boundary frame = defined clip area X1 = 0, Y1 = 0, X2 = 175, Y2 = 257`

The clip bounding box is the defined clip area in line 10.

For the second case, for example, the circle is only drawn in the defined clip area (dotted rectangle) - the current area for the character:

Figure 25.1.6.3.1: Circle in the defined clip area

You can see the following image of the circle in the first case: The circle is displayed on the surface, naturally cut off on the left-hand side, as this is where the original A4 clip area ends:

Figure 25.1.6.3.2: Circle in the defined A4 clip area

## 25.1.6.4 Example 2 - Cairo.FillExtents

In example 2, a circular area is filled with a light blue colour. The bounding box in this case is a square. The following image shows the circle, the bounding box (blue) and selected points of the circle and bounding box:

Figure 25.1.6.4.1: Circle in the defined clip area A4

In the source code excerpt below, lines 30 to 37 are particularly interesting. The two functions for converting the coordinates are also used in the 2nd example.

```[1] Private Sub GeneratePDF2()
[2]   Dim PDFSurface As CairoPdfSurface
[3]
[4]   PDFSurface = New CairoPdfSurface(sPfadPDFDatei, 210, 297) ' -->> DIN A4
[5]
[6]   Cairo.Begin(PDFSurface)
[7]     Cairo.Matrix.Translate(MMToPoints(20), MMToPoints(20))
[8]     Cairo.Matrix.Scale(1, 1) '-- Zoom factor = 1
[9]
[10]     Cairo.Rectangle(MMToPoints(0), MMToPoints(0), MMToPoints(175), MMToPoints(257))
[11]     Cairo.Source = Cairo.ColorPattern(Color.Red)
[12]     Cairo.AntiAlias = False
[13]     Cairo.LineWidth = 1
[14]     Cairo.Dash = [1, 1]
[15]     Cairo.Stroke()
[16]     Cairo.Dash = []
[17]
[18]     Cairo.Source = Cairo.ColorPattern(Color.DarkBlue)
[19]     Cairo.Arc(MMToPoints(10), MMToPoints(30), MMToPoints(1))
[20]     Cairo.Arc(MMToPoints(110), MMToPoints(130), MMToPoints(1))
[21]     Cairo.Fill()
[22]
[23]     Cairo.Rectangle(MMToPoints(10), MMToPoints(30), MMToPoints(100), MMToPoints(100))
[24]     Cairo.AntiAlias = False
[25]     Cairo.LineWidth = 1
[26]     Cairo.Dash = [1, 1]
[27]     Cairo.Stroke()
[28]     Cairo.Dash = []
[29]
[30]     Cairo.Source = Cairo.ColorPattern(&HC3DDFF)
[31]     Cairo.AntiAlias = True
[32]     Cairo.Arc(MMToPoints(60), MMToPoints(80), MMToPoints(50))
[33]        Print "X1 = "; Round(PointsToMM(Cairo.FillExtents.X1), 0)
[34]        Print "Y1 = "; Round(PointsToMM(Cairo.FillExtents.Y1), 0)
[35]        Print "X2 = "; Round(PointsToMM(Cairo.FillExtents.X2), 0)
[36]        Print "Y2 = "; Round(PointsToMM(Cairo.FillExtents.Y2), 0)
[37]     Cairo.Fill()
[38]
[39]     Cairo.Source = Cairo.ColorPattern(Color.Red)
[40]     Cairo.Arc(MMToPoints(60), MMToPoints(80), MMToPoints(0.5))
[41]     Cairo.Fill()
[42]
[43]   ' TEXT
[44]     Cairo.Source = Cairo.ColorPattern(Color.DarkBlue)
[45]     Cairo.Font.Name = "Arial"
[46]     Cairo.Font.Size = 14
[47]     Cairo.Font.Bold = True
[48]     Cairo.MoveTo(MMToPoints(50), MMToPoints(90))
[49]     Cairo.DrawText("M(60|80)")
[50]     Cairo.MoveTo(MMToPoints(0), MMToPoints(25))
[51]     Cairo.DrawText("P1(10|30)")
[52]     Cairo.MoveTo(MMToPoints(100), MMToPoints(140))
[53]     Cairo.DrawText("P2(110|130)")
[54]   Cairo.End()
[55]
[56]   PDFSurface.Finish()
[57]
[58] End```
The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.