15.5.4 Shadings
A shading is represented by the PdfShading object creatable by the PdfDocument.CreateShading method
which expects three arguments: the list of parameters, a PdfFunction object, and a PdfColorSpace object.
An instance of the PdfShading object can then be used to create a shading pattern by passing it to the CreatePattern method as the 2nd argument,
or directly paint with it via the PdfCanvas.FillWithShading method.
The PdfColorSpace object can represent any color space described earlier in this chapter. The PdfFunction object must represent
a function with the number of outputs corresponding to the number of colorants in the specified color space. For example, if
the DeviceRGB color space is specified, the number of outputs in the specified function must be 3.
The number of inputs depends on the shading type and must be either 1 or 2. The PdfColorSpace argument is required
for all shading types. The PdfFunction argument is required for some shading types but not others.
AspPDF currently supports three types of shading: Function-based, Axial and Radial. Each type is described in detail below.
Function-based Shadings
In function-based (type 1) shadings, the color at every point in the domain is defined by a specified mathematical function.
Mathematical functions and the PdfFunction object representing them are described in detail earlier in this chapter in
Section 15.2 - PdfFunction Object.
The function must have 2 inputs, and the number of outputs matching the number of colorants of the specified color space.
The shading-creating parameters passed via the 1st argument to the CreateShading method are as follows:
- Type (required) -- must be 1 for function-based shadings.
- bc1, bc2, ..., bcN (optional) -- the color components for the background color. N is the number of colorants in the specified color space.
If specified, this color is used to fill the area before any painting operations involving the shading are applied.
- XMin, YMin, XMax, YMax (optional) -- specify the rectangular domain of coordinates over which the color function is defined. [0.0, 1.0, 0.0, 1.0] by default.
- Left, Bottom, Right, Top (optional) -- specify the shading's bounding box. The coordinates are interpreted in the shading's target coordinate space.
If present, this box is applied as a temporary clipping boundary when the shading is painted.
- a, b, c, d, e, f (optional) -- specify the transformation matrix mapping the coordinate space specified by the domain [XMin, YMin, XMax, YMax]
into the shading's target coordinate space. The identity matrix [1, 0, 0, 1, 0, 0] by default.
- AntiAlias (optional) -- a Boolean flag indicating whether to filter the shading function to prevent antialiasing artifacts. False by default.
For example, let's create a simple function-based shading over a rectangle with the corner colors (in RGB color space) are as follows:
- lower-left: yellow (rgb 1, 1, 0);
- lower-right: black (rgb 0, 0, 0).
- upper-left: red (rgb 1, 0, 0);
- upper-right: blue (rgb 0, 0, 1);
To implement this shading, we need to create a function with two inputs (x and y coordinates) and three outputs (R, G, and B colorants).
The sampled function (Type=0) is suitable for this task.
The sample values are:
- f(0, 0) = [1, 1, 0] (yellow, lower-left corner)
- f(1, 0) = [0, 0, 0] (black, lower-right corner)
- f(0, 1) = [1, 0, 0] (red, upper-left corner)
- f(1, 1) = [0, 0, 1] (blue, upper-right corner)
We will set BitsPerSample parameter in our function to 8. All 0s in our sampled values remain 0s, and all 1s become 255. The sample values need to be
listed according to the rule "the sample values in the first dimension vary fastest, and the values in the last dimension vary slowest" (see sub-section 15.2.3 above),
as follows: f(0, 0), f(1, 0), f(0, 1), f(1, 1), or [ [255, 255, 0], [0, 0, 0], [255, 0, 0], [0, 0, 255] ].
The following script creates the shading above:
Set ColorSpace = doc.CreateColorSpace("DeviceRGB")
Set Func = doc.CreateFunction("type=0; Dmin1=0; Dmax1=1; Dmin2=0; Dmax2=1; rmin1=0; rmax1=1; rmin2=0; rmax2=1; rmin3=0; rmax3=1; bitspersample=8; size1=2; size2=2")
Func.SetSampleData Array(255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255)
Set Shading = doc.CreateShading("type=1", Func, ColorSpace)
However. if we were to attempt to use this shading directly to paint an area of the page with the FillWithShading method,
we would discover that the area remains unpainted. That is because the shading has been created over a tiny square with the dimensions 1x1 (in user units).
To fill a large area, we need to stretch the shading and also shift it via the a, b, c, d, e, f parameters.
The following snippet does just that and the output is shown below:
...
Set Shading = doc.CreateShading("type=1; a=200; b=0; c=0; d=400; e=50; f=150", Func, ColorSpace)
Page.Canvas.AddRect 0, 0, Page.width, Page.height
Page.Canvas.ClosePath
Page.Canvas.FillWithShading Shading
The following snippet associates the shading with a pattern and uses this pattern to paint the letter "A". The result is shown below:
...
Set Shading = doc.CreateShading("type=1; a=200; b=0; c=0; d=400; e=50; f=150", Func, ColorSpace)
Set Pattern = doc.CreatePattern("type=2; left=0; bottom=0; right=300; top=960", Shading)
Page.Canvas.SetFillColorEx Pattern
Page.Canvas.DrawText "A", "x=50; y=500; size=250", doc.fonts("Helvetica-Bold")
Axial Shadings
Axial shadings define a color blend that varies along a linear axis between two endpoints and extends indefinitely perpendicular to this axis.
The shading may optionally be extended beyond either or both endpoints by continuing the boundary colors indefinitely.
The shading-creating parameters for axial shadings passed via the 1st argument to the CreateShading method are as follows:
- Type (required) -- must be 2 for axial shadings.
- X0. Y0, X1, Y1 (required) -- specify the starting and ending coordinates of the axis, expressed in the shading's target coordinate space.
- Offset1, Color1, Offset2, Color2, ..., OffsetM, ColorM (optional) -- a set of pairs Offset/Color defining a gradient. Offsets must be in the range [0.0, 1.0].
If at least two pairs are specified, the Function argument to the CreateShading method is not used and ignored. See below for more information.
- ExtendStart, ExtendEnd (optional) -- two Boolean flags specifying whether to extend the shading beyond the starting and ending points of the axis, respectively. (False, False) by default.
- bc1, bc2, ..., bcN (optional) -- the color components for the background color. N is the number of colorants in the specified color space.
If specified, this color is used to fill the area before any painting operations involving the shading are applied.
- t0, t1 (optional) -- specify the limiting values of a parametric variable t which is the input argument to the color function. [0.0, 1.0] by default.
- Left, Bottom, Right, Top (optional) -- specify the shading's bounding box. The coordinates are interpreted in the shading's target coordinate space.
If present, this box is applied as a temporary clipping boundary when the shading is painted.
- AntiAlias (optional) -- a Boolean flag indicating whether to filter the shading function to prevent antialiasing artifacts. False by default.
The Function argument to the CreateShading method must be set to an instance of the PdfFunction object representing a function with one input and
the number of outputs matching the number of colorants in the specified color space. Instead of passing a PdfFunction object, a set of pairs Offset/Color
can be specified defining a color gradient, as shown below.
To demonstrate a simple axial shading, let's create a shading with the appearance of a horizontal red-to-blue gradient.
We will use a sample function again with the following sample values:
- f(0) = [1, 0, 0] (red)
- f(1) = [0, 0, 1] (blue)
The gradient will extend horizontally from the points (100, 0) to (500, 0).
' Sample function with one input and 3 outputs
Set Func = doc.CreateFunction("type=0; Dmin1=0; Dmax1=1; rmin1=0; rmax1=1; rmin2=0; rmax2=1; rmin3=0; rmax3=1; bitspersample=8; size1=2;")
Func.SetSampleData Array(255, 0, 0, 0, 0, 255) ' Red to Blue
' RGB color space
Set ColorSpace = doc.CreateColorSpace("DeviceRGB")
' Create axial shading and fill a rectangle with it
Set Shading = doc.CreateShading("type=2; x0=100; y0=0; x1=500; y1=0;", Func, ColorSpace )
Page.Canvas.AddRect 100, 200, 400, 100
Page.Canvas.ClosePath
Page.Canvas.Clip ' to limit the shading area to this rectangle only
Page.Canvas.FillWithShading Shading
The simple two-color gradient shown above can be easily defined by a single sample function. However, if the gradient consists of multiple colors
and arbitrary distances between the key color positions, a stitching function comprised of multiple sample functions would be needed, and the coding
would be more complex. The CreateShading method is capable of creating multi-color gradients when it is passed a list of pairs Offset/Color specifying
the offset and color of all key positions of the gradient. All offsets must be in the range [0, 1], and must be specified in an ascending order.
The simple red-to-blue gradient above can be created with two Offset/Color pairs and without the use of a function, as follows:
...
Set Shading = doc.CreateShading("type=2; x0=100; y0=0; x1=500; y1=0; Offset1=0; Color1=red; Offset2=1 Color2=blue;", Nothing, ColorSpace)
A more complex multi-color gradient with unevenly spaced color positions such as the this one, can be created as follows:
...
Set Shading = doc.CreateShading("type=2; x0=100; y0=0; x1=500; y1=0; Color1=red; Offset1=0; Color2=blue; Offset2=0.5; Color3=green; offset3=0.75; Color4=yellow; Offset4 = 1", Nothing, ColorSpace)
Radial Shadings
Radial shadings define a color blend that varies between two circles. Shadings of this type are commonly used to depict three-dimensional spheres
and cones.
The shading-creating parameters for radial shadings passed via the 1st argument to the CreateShading method are as follows:
- Type (required) -- must be 3 for radial shadings.
- X0. Y0, R0, X1, Y1, R1 (required) -- specify the centers and radii of the starting and ending circles
in the shading's target coordinate space.
- The other parameters are exactly the same as in axial shadings, including the Offset/Color pairs.
The radial shading shown above is based on the same Offset/Color series as the axial shading shown in the previous example. It was created with the following code:
Set ColorSpace = doc.CreateColorSpace("DeviceRGB")
Set Shading = doc.CreateShading("type=3; x0=150; y0=200; r0=0; x1=200; y1=200; r1=100; Color1=red; Offset1=0; Color2=blue; Offset2=0.5; Color3=green; offset3=0.75; Color4=yellow; Offset4 = 1", Nothing, ColorSpace)
Page.Canvas.AddRect 0, 0, 400, 400
Page.Canvas.ClosePath
Page.Canvas.Clip
Page.Canvas.FillWithShading Shading