1
#region PDFsharp - A .NET library for processing PDF
4
// Stefan Lange (mailto:Stefan.Lange@pdfsharp.com)
6
// Copyright (c) 2005-2008 empira Software GmbH, Cologne (Germany)
8
// http://www.pdfsharp.com
9
// http://sourceforge.net/projects/pdfsharp
11
// Permission is hereby granted, free of charge, to any person obtaining a
12
// copy of this software and associated documentation files (the "Software"),
13
// to deal in the Software without restriction, including without limitation
14
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
// and/or sell copies of the Software, and to permit persons to whom the
16
// Software is furnished to do so, subject to the following conditions:
18
// The above copyright notice and this permission notice shall be included
19
// in all copies or substantial portions of the Software.
21
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
// DEALINGS IN THE SOFTWARE.
31
using System.Diagnostics;
32
using System.Globalization;
33
using System.ComponentModel;
38
using System.Windows.Media;
40
using PdfSharp.Internal;
42
namespace PdfSharp.Drawing
45
/// Represents a RGB, CMYK, or gray scale color.
47
[DebuggerDisplay("(A={A}, R={R}, G={G}, B={B} C={C}, M={M}, Y={Y}, K={K})")]
52
this.cs = XColorSpace.Rgb;
53
this.a = (byte)((argb >> 24) & 0xff) / 255f;
54
this.r = (byte)((argb >> 16) & 0xff);
55
this.g = (byte)((argb >> 8) & 0xff);
56
this.b = (byte)(argb & 0xff);
63
cs.GetType(); // Suppress warning
66
XColor(byte alpha, byte red, byte green, byte blue)
68
this.cs = XColorSpace.Rgb;
69
this.a = alpha / 255f;
79
cs.GetType(); // Suppress warning
82
XColor(double alpha, double cyan, double magenta, double yellow, double black)
84
this.cs = XColorSpace.Cmyk;
85
this.a = (float)(alpha > 1 ? 1 : (alpha < 0 ? 0 : alpha));
86
this.c = (float)(cyan > 1 ? 1 : (cyan < 0 ? 0 : cyan));
87
this.m = (float)(magenta > 1 ? 1 : (magenta < 0 ? 0 : magenta));
88
this.y = (float)(yellow > 1 ? 1 : (yellow < 0 ? 0 : yellow));
89
this.k = (float)(black > 1 ? 1 : (black < 0 ? 0 : black));
97
XColor(double cyan, double magenta, double yellow, double black)
98
: this(1.0, cyan, magenta, yellow, black)
103
this.cs = XColorSpace.GrayScale;
108
this.gs = (float)gray;
122
XColor(System.Drawing.Color color)
123
: this(color.A, color.R, color.G, color.B)
128
XColor(System.Windows.Media.Color color)
129
: this(color.A, color.R, color.G, color.B)
134
XColor(KnownColor knownColor)
135
: this(System.Drawing.Color.FromKnownColor((System.Drawing.KnownColor)knownColor))
139
internal XColor(XKnownColor knownColor)
140
: this(XKnownColorTable.KnownColorToArgb(knownColor))
144
/// Creates an XColor structure from a 32-bit ARGB value.
146
public static XColor FromArgb(int argb)
148
return new XColor((byte)(argb >> 24), (byte)(argb >> 16), (byte)(argb >> 8), (byte)(argb));
152
/// Creates an XColor structure from a 32-bit ARGB value.
154
public static XColor FromArgb(uint argb)
156
return new XColor((byte)(argb >> 24), (byte)(argb >> 16), (byte)(argb >> 8), (byte)(argb));
159
// from System.Drawing.Color
160
//public static XColor FromArgb(int alpha, Color baseColor);
161
//public static XColor FromArgb(int red, int green, int blue);
162
//public static XColor FromArgb(int alpha, int red, int green, int blue);
163
//public static XColor FromKnownColor(KnownColor color);
164
//public static XColor FromName(string name);
167
/// Creates an XColor structure from the specified 8-bit color values (red, green, and blue).
168
/// The alpha value is implicitly 255 (fully opaque).
170
public static XColor FromArgb(int red, int green, int blue)
172
CheckByte(red, "red");
173
CheckByte(green, "green");
174
CheckByte(blue, "blue");
175
return new XColor((byte)255, (byte)red, (byte)green, (byte)blue);
179
/// Creates an XColor structure from the four ARGB component (alpha, red, green, and blue) values.
181
public static XColor FromArgb(int alpha, int red, int green, int blue)
183
CheckByte(alpha, "alpha");
184
CheckByte(red, "red");
185
CheckByte(green, "green");
186
CheckByte(blue, "blue");
187
return new XColor((byte)alpha, (byte)red, (byte)green, (byte)blue);
192
/// Creates an XColor structure from the specified System.Drawing.Color.
194
public static XColor FromArgb(System.Drawing.Color color)
196
return new XColor(color);
202
/// Creates an XColor structure from the specified System.Drawing.Color.
204
public static XColor FromArgb(System.Windows.Media.Color color)
206
return new XColor(color);
211
/// Creates an XColor structure from the specified alpha value and color.
213
public static XColor FromArgb(int alpha, XColor color)
215
color.A = ((byte)alpha) / 255.0;
221
/// Creates an XColor structure from the specified alpha value and color.
223
public static XColor FromArgb(int alpha, System.Drawing.Color color)
225
return new XColor(alpha, color.R, color.G, color.B);
231
/// Creates an XColor structure from the specified alpha value and color.
233
public static XColor FromArgb(int alpha, System.Windows.Media.Color color)
235
return new XColor(alpha, color.R, color.G, color.B);
240
/// Creates an XColor structure from the specified CMYK values.
242
public static XColor FromCmyk(double cyan, double magenta, double yellow, double black)
244
return new XColor(cyan, magenta, yellow, black);
248
/// Creates an XColor structure from the specified CMYK values.
250
public static XColor FromCmyk(double alpha, double cyan, double magenta, double yellow, double black)
252
return new XColor(alpha, cyan, magenta, yellow, black);
256
/// Creates an XColor structure from the specified gray value.
258
public static XColor FromGrayScale(double grayScale)
260
return new XColor(grayScale);
264
/// Creates an XColor from the specified pre-defined color.
266
public static XColor FromKnownColor(XKnownColor color)
268
return new XColor(color);
273
/// Creates an XColor from the specified pre-defined color.
275
public static XColor FromKnownColor(KnownColor color)
277
return new XColor(color);
282
/// Creates an XColor from the specified name of a pre-defined color.
284
public static XColor FromName(string name)
287
// The implementation in System.Drawing.dll is interesting. It uses a ColorConverter
288
// with hash tables, locking mechanisms etc. I'm not sure what problems that solves.
289
// So I don't use the source, but the reflection.
292
return new XColor((KnownColor)Enum.Parse(typeof(KnownColor), name, true));
300
/// Gets or sets the color space to be used for PDF generation.
302
public XColorSpace ColorSpace
304
get { return this.cs; }
307
if (!Enum.IsDefined(typeof(XColorSpace), value))
308
throw new InvalidEnumArgumentException("value", (int)value, typeof(XColorSpace));
314
/// Indicates whether this XColor structure is uninitialized.
318
get { return this == XColor.Empty; }
324
/// Implicit conversion from Color to XColor
326
public static implicit operator XColor(Color color)
328
return new XColor(color);
333
/// Creates a System.Drawing.Color object from this color.
335
public System.Drawing.Color ToGdiColor()
337
return System.Drawing.Color.FromArgb((int)(this.a * 255), this.r, this.g, this.b);
343
/// Creates a System.Windows.Media.Color object from this color.
345
public System.Windows.Media.Color ToWpfColor()
347
return System.Windows.Media.Color.FromArgb((byte)(this.a * 255), this.r, this.g, this.b);
352
/// Determines whether the specified object is a Color structure and is equivalent to this
355
public override bool Equals(object obj)
359
XColor color = (XColor)obj;
360
if (this.r == color.r && this.g == color.g && this.b == color.b &&
361
this.c == color.c && this.m == color.m && this.y == color.y && this.k == color.k &&
364
return this.a == color.a;
371
/// Returns the hash code for this instance.
373
public override int GetHashCode()
375
return ((byte)(this.a * 255)) ^ this.r ^ this.g ^ this.b;
376
// ^ *(int*)&this.c ^ *(int*)&this.m ^ *(int*)&this.y ^ *(int*)&this.k;
380
/// Determines whether two colors are equal.
382
public static bool operator ==(XColor left, XColor right)
384
if (left.r == right.r && left.g == right.g && left.b == right.b &&
385
left.c == right.c && left.m == right.m && left.y == right.y && left.k == right.k &&
388
return left.a == right.a;
394
/// Determines whether two colors are not equal.
396
public static bool operator !=(XColor left, XColor right)
398
return !(left == right);
402
/// Gets a value indicating whether this color is a known color.
404
public bool IsKnownColor
406
get { return XKnownColorTable.IsKnownColor(Argb); }
409
//public bool IsNamedColor { get; }
410
//public bool IsSystemColor { get; }
413
/// Gets the hue-saturation-brightness (HSB) hue value, in degrees, for this color.
415
/// <returns>The hue, in degrees, of this color. The hue is measured in degrees, ranging from 0 through 360, in HSB color space.</returns>
416
public double GetHue()
418
if ((this.r == this.g) && (this.g == this.b))
421
double value1 = this.r / 255.0;
422
double value2 = this.g / 255.0;
423
double value3 = this.b / 255.0;
425
double value4 = value1;
426
double value5 = value1;
439
double value6 = value4 - value5;
440
if (value1 == value4)
441
value7 = (value2 - value3) / value6;
442
else if (value2 == value4)
443
value7 = 2f + ((value3 - value1) / value6);
444
else if (value3 == value4)
445
value7 = 4f + ((value1 - value2) / value6);
454
/// Gets the hue-saturation-brightness (HSB) saturation value for this color.
456
/// <returns>The saturation of this color. The saturation ranges from 0 through 1, where 0 is grayscale and 1 is the most saturated.</returns>
457
public double GetSaturation()
459
double value1 = this.r / 255.0;
460
double value2 = this.g / 255.0;
461
double value3 = this.b / 255.0;
463
double value4 = value1;
464
double value5 = value1;
477
if (value4 == value5)
480
double value6 = (value4 + value5) / 2;
482
return (value4 - value5) / (value4 + value5);
483
return (value4 - value5) / ((2f - value4) - value5);
487
/// Gets the hue-saturation-brightness (HSB) brightness value for this color.
489
/// <returns>The brightness of this color. The brightness ranges from 0 through 1, where 0 represents black and 1 represents white.</returns>
490
public double GetBrightness()
492
double value1 = this.r / 255.0;
493
double value2 = this.g / 255.0;
494
double value3 = this.b / 255.0;
495
double value4 = value1;
496
double value5 = value1;
509
return (value4 + value5) / 2;
513
/// One of the RGB values changed; recalculate other color representations.
517
this.cs = XColorSpace.Rgb;
518
int c = 255 - this.r;
519
int m = 255 - this.g;
520
int y = 255 - this.b;
521
int k = Math.Min(c, Math.Min(m, y));
523
this.c = this.m = this.y = 0;
526
float black = 255f - k;
527
this.c = (c - k) / black;
528
this.m = (m - k) / black;
529
this.y = (y - k) / black;
531
this.k = this.gs = k / 255f;
535
/// One of the CMYK values changed; recalculate other color representations.
539
this.cs = XColorSpace.Cmyk;
540
float black = this.k * 255;
541
float factor = 255f - black;
542
this.r = (byte)(255 - Math.Min(255f, this.c * factor + black));
543
this.g = (byte)(255 - Math.Min(255f, this.m * factor + black));
544
this.b = (byte)(255 - Math.Min(255f, this.y * factor + black));
545
this.gs = (float)(1 - Math.Min(1.0, 0.3f * this.c + 0.59f * this.m + 0.11 * this.y + this.k));
549
/// The gray scale value changed; recalculate other color representations.
553
this.cs = XColorSpace.GrayScale;
554
this.r = (byte)(this.gs * 255);
555
this.g = (byte)(this.gs * 255);
556
this.b = (byte)(this.gs * 255);
560
this.k = 1 - this.gs;
566
/// Gets or sets the alpha value the specifies the transparency.
567
/// The value is in the range from 1 (opaque) to 0 (completely transparent).
571
get { return this.a; }
579
this.a = (float)value;
584
/// Gets or sets the red value.
588
get { return this.r; }
589
set { this.r = value; RgbChanged(); }
593
/// Gets or sets the green value.
597
get { return this.g; }
598
set { this.g = value; RgbChanged(); }
602
/// Gets or sets the blue value.
606
get { return this.b; }
607
set { this.b = value; RgbChanged(); }
611
/// Gets the RGB part value of the color. Internal helper function.
615
get { return ((uint)this.r << 16) | ((uint)this.g << 8) | (uint)this.b; }
619
/// Gets the ARGB part value of the color. Internal helper function.
623
get { return ((uint)(this.a * 255) << 24) | ((uint)this.r << 16) | ((uint)this.g << 8) | (uint)this.b; }
627
/// Gets or sets the cyan value.
631
get { return this.c; }
639
this.c = (float)value;
645
/// Gets or sets the magenta value.
649
get { return this.m; }
657
this.m = (float)value;
663
/// Gets or sets the yellow value.
667
get { return this.y; }
675
this.y = (float)value;
681
/// Gets or sets the black (or key) value.
685
get { return this.k; }
693
this.k = (float)value;
699
/// Gets or sets the gray scale value.
703
get { return this.gs; }
711
this.gs = (float)value;
717
/// Represents the null color.
719
public static XColor Empty;
722
/// Special property for XmlSerializer only.
724
public string RgbCmykG
728
return String.Format(CultureInfo.InvariantCulture,
729
"{0};{1};{2};{3};{4};{5};{6};{7};{8}", this.r, this.g, this.b, this.c, this.m, this.y, this.k, this.gs, this.a);
733
string[] values = value.Split(';');
734
this.r = byte.Parse(values[0], CultureInfo.InvariantCulture);
735
this.g = byte.Parse(values[1], CultureInfo.InvariantCulture);
736
this.b = byte.Parse(values[2], CultureInfo.InvariantCulture);
737
this.c = float.Parse(values[3], CultureInfo.InvariantCulture);
738
this.m = float.Parse(values[4], CultureInfo.InvariantCulture);
739
this.y = float.Parse(values[5], CultureInfo.InvariantCulture);
740
this.k = float.Parse(values[6], CultureInfo.InvariantCulture);
741
this.gs = float.Parse(values[7], CultureInfo.InvariantCulture);
742
this.a = float.Parse(values[8], CultureInfo.InvariantCulture);
746
static void CheckByte(int val, string name)
748
if (val < 0 || val > 0xFF)
749
throw new ArgumentException(PSSR.InvalidValue(val, name, 0, 255));
752
private XColorSpace cs;
754
private float a; // alpha
757
private byte g; // |--- RGB
760
private float c; // \
761
private float m; // |--- CMYK
762
private float y; // |
763
private float k; // /
765
private float gs; // >--- gray scale
b'\\ No newline at end of file'