1 #region PDFsharp - A .NET library for processing PDF
\r
4 // Stefan Lange (mailto:Stefan.Lange@pdfsharp.com)
\r
6 // Copyright (c) 2005-2009 empira Software GmbH, Cologne (Germany)
\r
8 // http://www.pdfsharp.com
\r
9 // http://sourceforge.net/projects/pdfsharp
\r
11 // Permission is hereby granted, free of charge, to any person obtaining a
\r
12 // copy of this software and associated documentation files (the "Software"),
\r
13 // to deal in the Software without restriction, including without limitation
\r
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
\r
15 // and/or sell copies of the Software, and to permit persons to whom the
\r
16 // Software is furnished to do so, subject to the following conditions:
\r
18 // The above copyright notice and this permission notice shall be included
\r
19 // in all copies or substantial portions of the Software.
\r
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
\r
24 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
\r
26 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
\r
27 // DEALINGS IN THE SOFTWARE.
\r
31 using System.Diagnostics;
\r
32 using System.Globalization;
\r
33 using System.Collections;
\r
37 using System.Drawing;
\r
38 using System.Drawing.Imaging;
\r
41 using System.Windows.Media;
\r
43 using PdfSharp.Drawing;
\r
44 using PdfSharp.Fonts.OpenType;
\r
45 using PdfSharp.Internal;
\r
46 using PdfSharp.Pdf.Internal;
\r
48 namespace PdfSharp.Pdf.Advanced
\r
51 /// Represents a shading dictionary.
\r
53 public sealed class PdfShading : PdfDictionary
\r
56 /// Initializes a new instance of the <see cref="PdfShading"/> class.
\r
58 public PdfShading(PdfDocument document)
\r
63 /// Setups the shading from the specified brush.
\r
65 public void SetupFromBrush(XLinearGradientBrush brush)
\r
68 throw new ArgumentNullException("brush");
\r
70 PdfColorMode colorMode = this.document.Options.ColorMode;
\r
71 XColor color1 = ColorSpaceHelper.EnsureColorMode(colorMode, brush.color1);
\r
72 XColor color2 = ColorSpaceHelper.EnsureColorMode(colorMode, brush.color2);
\r
74 PdfDictionary function = new PdfDictionary();
\r
76 Elements[Keys.ShadingType] = new PdfInteger(2);
\r
77 if (colorMode != PdfColorMode.Cmyk)
\r
78 Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB");
\r
80 Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK");
\r
82 double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
\r
85 switch (brush.linearGradientMode)
\r
87 case XLinearGradientMode.Horizontal:
\r
90 x2 = brush.rect.x + brush.rect.width;
\r
94 case XLinearGradientMode.Vertical:
\r
98 y2 = brush.rect.y + brush.rect.height;
\r
101 case XLinearGradientMode.ForwardDiagonal:
\r
104 x2 = brush.rect.x + brush.rect.width;
\r
105 y2 = brush.rect.y + brush.rect.height;
\r
108 case XLinearGradientMode.BackwardDiagonal:
\r
109 x1 = brush.rect.x + brush.rect.width;
\r
112 y2 = brush.rect.y + brush.rect.height;
\r
118 x1 = brush.point1.x;
\r
119 y1 = brush.point1.y;
\r
120 x2 = brush.point2.x;
\r
121 y2 = brush.point2.y;
\r
123 Elements[Keys.Coords] = new PdfLiteral("[{0:0.###} {1:0.###} {2:0.###} {3:0.###}]", x1, y1, x2, y2);
\r
125 //Elements[Keys.Background] = new PdfRawItem("[0 1 1]");
\r
126 //Elements[Keys.Domain] =
\r
127 Elements[Keys.Function] = function;
\r
128 //Elements[Keys.Extend] = new PdfRawItem("[true true]");
\r
130 string clr1 = "[" + PdfEncoders.ToString(color1, colorMode) + "]";
\r
131 string clr2 = "[" + PdfEncoders.ToString(color2, colorMode) + "]";
\r
133 function.Elements["/FunctionType"] = new PdfInteger(2);
\r
134 function.Elements["/C0"] = new PdfLiteral(clr1);
\r
135 function.Elements["/C1"] = new PdfLiteral(clr2);
\r
136 function.Elements["/Domain"] = new PdfLiteral("[0 1]");
\r
137 function.Elements["/N"] = new PdfInteger(1);
\r
141 /// Common keys for all streams.
\r
143 internal sealed class Keys : KeysBase
\r
146 /// (Required) The shading type:
\r
147 /// 1 Function-based shading
\r
148 /// 2 Axial shading
\r
149 /// 3 Radial shading
\r
150 /// 4 Free-form Gouraud-shaded triangle mesh
\r
151 /// 5 Lattice-form Gouraud-shaded triangle mesh
\r
152 /// 6 Coons patch mesh
\r
153 /// 7 Tensor-product patch mesh
\r
155 [KeyInfo(KeyType.Integer | KeyType.Required)]
\r
156 public const string ShadingType = "/ShadingType";
\r
159 /// (Required) The color space in which color values are expressed. This may be any device,
\r
160 /// CIE-based, or special color space except a Pattern space.
\r
162 [KeyInfo(KeyType.NameOrArray | KeyType.Required)]
\r
163 public const string ColorSpace = "/ColorSpace";
\r
166 /// (Optional) An array of color components appropriate to the color space, specifying
\r
167 /// a single background color value. If present, this color is used, before any painting
\r
168 /// operation involving the shading, to fill those portions of the area to be painted
\r
169 /// that lie outside the bounds of the shading object. In the opaque imaging model,
\r
170 /// the effect is as if the painting operation were performed twice: first with the
\r
171 /// background color and then with the shading.
\r
173 [KeyInfo(KeyType.Array | KeyType.Optional)]
\r
174 public const string Background = "/Background";
\r
177 /// (Optional) An array of four numbers giving the left, bottom, right, and top coordinates,
\r
178 /// respectively, of the shading
\92s bounding box. The coordinates are interpreted in the
\r
179 /// shading
\92s target coordinate space. If present, this bounding box is applied as a temporary
\r
180 /// clipping boundary when the shading is painted, in addition to the current clipping path
\r
181 /// and any other clipping boundaries in effect at that time.
\r
183 [KeyInfo(KeyType.Rectangle | KeyType.Optional)]
\r
184 public const string BBox = "/BBox";
\r
187 /// (Optional) A flag indicating whether to filter the shading function to prevent aliasing
\r
188 /// artifacts. The shading operators sample shading functions at a rate determined by the
\r
189 /// resolution of the output device. Aliasing can occur if the function is not smooth
\97that
\r
190 /// is, if it has a high spatial frequency relative to the sampling rate. Anti-aliasing can
\r
191 /// be computationally expensive and is usually unnecessary, since most shading functions
\r
192 /// are smooth enough or are sampled at a high enough frequency to avoid aliasing effects.
\r
193 /// Anti-aliasing may not be implemented on some output devices, in which case this flag
\r
195 /// Default value: false.
\r
197 [KeyInfo(KeyType.Boolean | KeyType.Optional)]
\r
198 public const string AntiAlias = "/AntiAlias";
\r
201 // ---- Type 2 ----------------------------------------------------------
\r
204 /// (Required) An array of four numbers [x0 y0 x1 y1] specifying the starting and
\r
205 /// ending coordinates of the axis, expressed in the shading
\92s target coordinate space.
\r
207 [KeyInfo(KeyType.Array | KeyType.Required)]
\r
208 public const string Coords = "/Coords";
\r
211 /// (Optional) An array of two numbers [t0 t1] specifying the limiting values of a
\r
212 /// parametric variable t. The variable is considered to vary linearly between these
\r
213 /// two values as the color gradient varies between the starting and ending points of
\r
214 /// the axis. The variable t becomes the input argument to the color function(s).
\r
215 /// Default value: [0.0 1.0].
\r
217 [KeyInfo(KeyType.Array | KeyType.Optional)]
\r
218 public const string Domain = "/Domain";
\r
221 /// (Required) A 1-in, n-out function or an array of n 1-in, 1-out functions (where n
\r
222 /// is the number of color components in the shading dictionary
\92s color space). The
\r
223 /// function(s) are called with values of the parametric variable t in the domain defined
\r
224 /// by the Domain entry. Each function
\92s domain must be a superset of that of the shading
\r
225 /// dictionary. If the value returned by the function for a given color component is out
\r
226 /// of range, it is adjusted to the nearest valid value.
\r
228 [KeyInfo(KeyType.Function | KeyType.Required)]
\r
229 public const string Function = "/Function";
\r
232 /// (Optional) An array of two boolean values specifying whether to extend the shading
\r
233 /// beyond the starting and ending points of the axis, respectively.
\r
234 /// Default value: [false false].
\r
236 [KeyInfo(KeyType.Array | KeyType.Optional)]
\r
237 public const string Extend = "/Extend";
\r
240 /// Gets the KeysMeta for these keys.
\r
242 internal static DictionaryMeta Meta
\r
246 if (Keys.meta == null)
\r
247 Keys.meta = CreateMeta(typeof(Keys));
\r
251 static DictionaryMeta meta;
\r
255 /// Gets the KeysMeta of this dictionary type.
\r
257 internal override DictionaryMeta Meta
\r
259 get { return Keys.Meta; }
\r