color-tools 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ #--
2
+ # Colour management with Ruby.
3
+ #
4
+ # Copyright 2005 Austin Ziegler
5
+ # http://rubyforge.org/ruby-pdf/
6
+ #
7
+ # Licensed under a MIT-style licence.
8
+ #
9
+ # $Id: css.rb,v 1.1 2005/08/05 23:07:20 austin Exp $
10
+ #++
11
+
12
+ require 'color'
13
+
14
+ # This namespace contains some CSS colour names.
15
+ module Color::CSS
16
+ # Returns the RGB colour for name or +nil+ if the name is not valid.
17
+ def self.[](name)
18
+ @colors[name.to_s.downcase.to_sym]
19
+ end
20
+
21
+ @colors = {}
22
+ Color::RGB.constants.each do |const|
23
+ next if const == "PDF_FORMAT_STR"
24
+ next if const == "Metallic"
25
+ @colors[const.downcase.to_sym] ||= Color::RGB.const_get(const)
26
+ end
27
+ end
@@ -3,22 +3,32 @@
3
3
  #
4
4
  # Copyright 2005 Austin Ziegler
5
5
  # http://rubyforge.org/ruby-pdf/
6
+ #
7
+ # Licensed under a MIT-style licence.
8
+ #
9
+ # $Id: grayscale.rb,v 1.3 2005/08/08 02:44:17 austin Exp $
6
10
  #++
7
11
 
8
12
  # A colour object representing shades of grey. Used primarily in PDF
9
13
  # document creation.
10
14
  class Color::GrayScale
11
- # The format required to present the colour to a PDF document.
15
+ # The format of a DeviceGrey colour for PDF. In color-tools 2.0 this
16
+ # will be removed from this package and added back as a modification by
17
+ # the PDF::Writer package.
12
18
  PDF_FORMAT_STR = "%.3f %s"
13
19
 
14
- # Creates a greyscale colour object from fractional values 0 .. 1.
20
+ # Creates a greyscale colour object from fractional values 0..1.
21
+ #
22
+ # Color::GreyScale.from_fraction(0.5)
15
23
  def self.from_fraction(g = 0)
16
24
  color = Color::GrayScale.new
17
25
  color.g = g
18
26
  color
19
27
  end
20
28
 
21
- # Creates a greyscale colour object from percentages 0 .. 100.
29
+ # Creates a greyscale colour object from percentages 0..100.
30
+ #
31
+ # Color::GrayScale.new(50)
22
32
  def initialize(g = 0)
23
33
  @g = g / 100.0
24
34
  end
@@ -27,18 +37,23 @@ class Color::GrayScale
27
37
  # converted to GreyScale before comparison, so the comparison between a
28
38
  # GreyScale colour and a non-GreyScale colour will be approximate and
29
39
  # based on the other colour's #to_greyscale conversion. If there is no
30
- # #to_greyscale conversion, this will raise an exception.
40
+ # #to_greyscale conversion, this will raise an exception. This will
41
+ # report that two GreyScale values are equivalent if they are within
42
+ # 1e-4 (0.0001) of each other.
31
43
  def ==(other)
32
44
  other = other.to_grayscale
33
- other.kind_of?(Color::GrayScale) and (@g == other.g)
45
+ other.kind_of?(Color::GrayScale) and
46
+ ((@g - other.g).abs <= 1e-4)
34
47
  end
35
48
 
36
- # Present the colour as a fill colour string for PDF.
49
+ # Present the colour as a DeviceGrey fill colour string for PDF. This
50
+ # will be removed from the default package in color-tools 2.0.
37
51
  def pdf_fill
38
52
  PDF_FORMAT_STR % [ @g, "g" ]
39
53
  end
40
54
 
41
- # Present the colour as a stroke colour string for PDF.
55
+ # Present the colour as a DeviceGrey stroke colour string for PDF. This
56
+ # will be removed from the default package in color-tools 2.0.
42
57
  def pdf_stroke
43
58
  PDF_FORMAT_STR % [ @g, "G" ]
44
59
  end
@@ -50,19 +65,19 @@ class Color::GrayScale
50
65
 
51
66
  # Present the colour as an HTML/CSS colour string.
52
67
  def html
53
- gs = "%02x" % @g.to_255
68
+ gs = "%02x" % to_255
54
69
  "##{gs * 3}"
55
70
  end
56
71
 
57
72
  # Convert the greyscale colour to CMYK.
58
73
  def to_cmyk
59
74
  k = 1.0 - @g.to_f
60
- Color::CMYK.from_Fraction(0, 0, 0, k)
75
+ Color::CMYK.from_fraction(0, 0, 0, k)
61
76
  end
62
77
 
63
78
  # Convert the greyscale colour to RGB.
64
79
  def to_rgb(ignored = true)
65
- g = @g.to_255
80
+ g = to_255
66
81
  Color::RGB.new(g, g, g)
67
82
  end
68
83
 
@@ -74,12 +89,12 @@ class Color::GrayScale
74
89
  # Lightens the greyscale colour by the stated percent.
75
90
  def lighten_by(percent)
76
91
  g = [@g + (@g * (percent / 100.0)), 1.0].min
77
- Color::Grayscale.from_fraction(g)
92
+ Color::GrayScale.from_fraction(g)
78
93
  end
79
94
 
80
95
  # Darken the RGB hue by the stated percent.
81
96
  def darken_by(percent)
82
- g = [@g - (@g * (percent / 100.0)), 1.0].max
97
+ g = [@g - (@g * (percent / 100.0)), 0.0].max
83
98
  Color::GrayScale.from_fraction(g)
84
99
  end
85
100
 
@@ -94,6 +109,11 @@ class Color::GrayScale
94
109
  Color::YIQ.from_fraction(y, i, q)
95
110
  end
96
111
 
112
+ # Returns the HSL colour encoding of the greyscale value.
113
+ def to_hsl
114
+ Color::HSL.from_fraction(0, 0, @g)
115
+ end
116
+
97
117
  # Returns the brightness value for this greyscale value; this is the
98
118
  # greyscale value.
99
119
  def brightness
@@ -101,5 +121,15 @@ class Color::GrayScale
101
121
  end
102
122
 
103
123
  attr_accessor :g
124
+ remove_method :g= ;
125
+ def g=(gg) #:nodoc:
126
+ gg = 1.0 if gg > 1
127
+ gg = 0.0 if gg < 0
128
+ @g = gg
129
+ end
130
+ end
131
+
132
+ module Color
133
+ # A synonym for Color::GrayScale.
134
+ GreyScale = GrayScale
104
135
  end
105
- Color::GreyScale = Color::GrayScale
@@ -0,0 +1,130 @@
1
+ #--
2
+ # Colour management with Ruby.
3
+ #
4
+ # Copyright 2005 Austin Ziegler
5
+ # http://rubyforge.org/ruby-pdf/
6
+ #
7
+ # Licensed under a MIT-style licence.
8
+ #
9
+ # $Id: hsl.rb,v 1.2 2005/08/08 02:44:17 austin Exp $
10
+ #++
11
+
12
+ # An HSL colour object. Internally, the hue (#h), saturation (#s), and
13
+ # luminosity (#l) values are dealt with as fractional values in the range
14
+ # 0..1.
15
+ class Color::HSL
16
+ class << self
17
+ # Creates an HSL colour object from fractional values 0..1.
18
+ def from_fraction(h = 0.0, s = 0.0, l = 0.0)
19
+ colour = Color::HSL.new
20
+ colour.h = h
21
+ colour.s = s
22
+ colour.l = l
23
+ colour
24
+ end
25
+ end
26
+
27
+ # Compares the other colour to this one. The other colour will be
28
+ # converted to HSL before comparison, so the comparison between a HSL
29
+ # colour and a non-HSL colour will be approximate and based on the other
30
+ # colour's #to_hsl conversion. If there is no #to_hsl conversion, this
31
+ # will raise an exception. This will report that two HSL values are
32
+ # equivalent if all component values are within 1e-4 (0.0001) of each
33
+ # other.
34
+ def ==(other)
35
+ other = other.to_hsl
36
+ other.kind_of?(Color::HSL) and
37
+ ((@h - other.h).abs <= 1e-4) and
38
+ ((@s - other.s).abs <= 1e-4) and
39
+ ((@l - other.l).abs <= 1e-4)
40
+ end
41
+
42
+ # Creates an HSL colour object from the standard values of degrees and
43
+ # percentages (e.g., 145�, 30%, 50%).
44
+ def initialize(h = 0, s = 0, l = 0)
45
+ @h = h / 360.0
46
+ @s = s / 100.0
47
+ @l = l / 100.0
48
+ end
49
+
50
+ # Present the colour as an HTML/CSS colour string.
51
+ def html
52
+ to_rgb.html
53
+ end
54
+
55
+ # Converting to HSL as adapted from Foley and Van-Dam from
56
+ # http://www.bobpowell.net/RGBHSB.htm.
57
+ def to_rgb(ignored = nil)
58
+ # If luminosity is zero, the colour is always black.
59
+ return Color::RGB.new if @l == 0
60
+ # If luminosity is one, the colour is always white.
61
+ return Color::RGB.new(0xff, 0xff, 0xff) if @l == 1
62
+ # If saturation is zero, the colour is always a greyscale colour.
63
+ return Color::RGB.new(@l, @l, @l) if @s <= 1e-5
64
+
65
+ if (@l - 0.5) < 1e-5
66
+ tmp2 = @l * (1.0 + @s.to_f)
67
+ else
68
+ tmp2 = @l + @s - (@l * @s.to_f)
69
+ end
70
+ tmp1 = 2.0 * @l - tmp2
71
+
72
+ t3 = [ @h + 1.0 / 3.0, @h, @h - 1.0 / 3.0 ]
73
+ t3 = t3.map { |tmp3|
74
+ tmp3 += 1.0 if tmp3 < 1e-5
75
+ tmp3 -= 1.0 if (tmp3 - 1.0) > 1e-5
76
+ tmp3
77
+ }
78
+
79
+ rgb = t3.map do |tmp3|
80
+ if ((6.0 * tmp3) - 1.0) < 1e-5
81
+ tmp1 + ((tmp2 - tmp1) * tmp3 * 6.0)
82
+ elsif ((2.0 * tmp3) - 1.0) < 1e-5
83
+ tmp2
84
+ elsif ((3.0 * tmp3) - 2.0) < 1e-5
85
+ tmp1 + (tmp2 - tmp1) * ((2 / 3.0) - tmp3) * 6.0
86
+ else
87
+ tmp1
88
+ end
89
+ end
90
+
91
+ Color::RGB.from_fraction(*rgb)
92
+ end
93
+
94
+ # Converts to RGB then YIQ.
95
+ def to_yiq
96
+ to_rgb.to_yiq
97
+ end
98
+
99
+ # Converts to RGB then CMYK.
100
+ def to_cmyk
101
+ to_rgb.to_cmyk
102
+ end
103
+
104
+ # Returns the luminosity (#l) of the colour.
105
+ def brightness
106
+ @l
107
+ end
108
+ def to_greyscale
109
+ Color::GrayScale.from_fraction(@l)
110
+ end
111
+ alias to_grayscale to_greyscale
112
+
113
+ attr_accessor :h, :s, :l
114
+ remove_method :h=, :s=, :l= ;
115
+ def h=(hh) #:nodoc:
116
+ hh = 1.0 if hh > 1
117
+ hh = 0.0 if hh < 0
118
+ @h = hh
119
+ end
120
+ def s=(ss) #:nodoc:
121
+ ss = 1.0 if ss > 1
122
+ ss = 0.0 if ss < 0
123
+ @s = ss
124
+ end
125
+ def l=(ll) #:nodoc:
126
+ ll = 1.0 if ll > 1
127
+ ll = 0.0 if ll < 0
128
+ @l = ll
129
+ end
130
+ end
@@ -3,6 +3,10 @@
3
3
  #
4
4
  # Copyright 2005 Austin Ziegler
5
5
  # http://rubyforge.org/ruby-pdf/
6
+ #
7
+ # Licensed under a MIT-style licence.
8
+ #
9
+ # $Id: palette.rb,v 1.2 2005/08/05 23:07:20 austin Exp $
6
10
  #++
7
11
 
8
12
  require 'color'
@@ -3,30 +3,50 @@
3
3
  #
4
4
  # Copyright 2005 Austin Ziegler
5
5
  # http://rubyforge.org/ruby-pdf/
6
+ #
7
+ # Licensed under a MIT-style licence.
8
+ #
9
+ # $Id: gimp.rb,v 1.3 2005/08/08 02:44:17 austin Exp $
6
10
  #++
7
11
 
8
12
  require 'color/palette'
9
13
 
14
+ # A class that can read a GIMP (GNU Image Manipulation Program) palette
15
+ # file and provide a Hash-like interface to the contents. GIMP colour
16
+ # palettes are RGB values only.
17
+ #
18
+ # Because two or more entries in a GIMP palette may have the same name,
19
+ # all named entries are returned as an array.
20
+ #
21
+ # pal = Color::Palette::Gimp.from_file(my_gimp_palette)
22
+ # pal[0] => Color::RGB<...>
23
+ # pal["white"] => [ Color::RGB<...> ]
24
+ # pal["unknown"] => [ Color::RGB<...>, Color::RGB<...>, ... ]
25
+ #
26
+ # GIMP Palettes are always indexable by insertion order (an integer key).
10
27
  class Color::Palette::Gimp
11
28
  include Enumerable
12
29
 
13
30
  class << self
31
+ # Create a GIMP palette object from the named file.
14
32
  def from_file(filename)
15
33
  File.open(filename, "rb") { |io| Color::Palette::Gimp.from_io(io) }
16
34
  end
17
35
 
36
+ # Create a GIMP palette object from the provided IO.
18
37
  def from_io(io)
19
38
  Color::Palette::Gimp.new(io.read)
20
39
  end
21
40
  end
22
41
 
42
+ # Create a new GIMP palette.
23
43
  def initialize(palette)
24
- @colors = {}
44
+ @colors = []
45
+ @names = {}
25
46
  @valid = false
26
47
  @name = "(unnamed)"
27
48
 
28
49
  index = 0
29
- collision = {}
30
50
 
31
51
  palette.split($/).each do |line|
32
52
  line.chomp!
@@ -47,26 +67,41 @@ class Color::Palette::Gimp
47
67
 
48
68
  line.gsub!(/^\s+/, '')
49
69
  data = line.split(/\s+/, 4)
50
- name = data.pop
70
+ name = data.pop.strip
51
71
  data.map! { |el| el.to_i }
52
72
 
53
- @colors[index] = Color::RGB.new(*data)
73
+ color = Color::RGB.new(*data)
54
74
 
55
- if @colors.has_key?(name)
56
- collision[name] = true
57
- else
58
- @colors[name] = @colors[index]
59
- end
60
- end
75
+ @colors[index] = color
76
+ @names[name] ||= []
77
+ @names[name] << color
61
78
 
62
- collision.each_key { |key| @colors.delete_at(key) }
79
+ index += 1
80
+ end
63
81
  end
64
82
 
65
83
  def [](key)
66
- @colors[key]
84
+ if key.kind_of?(Numeric)
85
+ @colors[key]
86
+ else
87
+ @names[key]
88
+ end
67
89
  end
68
90
 
91
+ # Loops through each colour.
69
92
  def each
70
93
  @colors.each { |el| yield el }
71
94
  end
95
+
96
+ # Loops through each named colour set.
97
+ def each_name #:yields color_name, color_set:#
98
+ @names.each { |color_name, color_set| yield color_name, color_set }
99
+ end
100
+
101
+ # Returns true if this is believed to be a valid GIMP palette.
102
+ def valid?
103
+ @valid
104
+ end
105
+
106
+ attr_reader :name
72
107
  end
@@ -3,6 +3,10 @@
3
3
  #
4
4
  # Copyright 2005 Austin Ziegler
5
5
  # http://rubyforge.org/ruby-pdf/
6
+ #
7
+ # Licensed under a MIT-style licence.
8
+ #
9
+ # $Id: monocontrast.rb,v 1.3 2005/08/08 02:44:17 austin Exp $
6
10
  #++
7
11
 
8
12
  require 'color/palette'
@@ -26,7 +30,7 @@ class Color::Palette::MonoContrast
26
30
  # 0:: The starting colour.
27
31
  # +1..+5:: Lighter colours.
28
32
  # -1..-5:: Darker colours.
29
- attr_accessor :background
33
+ attr_reader :background
30
34
  # Hash of CSS foreground colour values.
31
35
  #
32
36
  # This is always 11 values:
@@ -34,30 +38,56 @@ class Color::Palette::MonoContrast
34
38
  # 0:: The starting colour.
35
39
  # +1..+5:: Lighter colours.
36
40
  # -1..-5:: Darker colours.
37
- attr_accessor :foreground
41
+ attr_reader :foreground
42
+
43
+ DEFAULT_MINIMUM_BRIGHTNESS_DIFF = (125.0 / 255.0)
38
44
 
39
45
  # The minimum brightness difference between the background and the
40
- # foreground. Setting this value will regenerate the palette based on
41
- # the base colours. The default value for this is 125 / 255.0.
46
+ # foreground, and must be between 0..1. Setting this value will
47
+ # regenerate the palette based on the base colours. The default value
48
+ # for this is 125 / 255.0. If this value is set to +nil+, it will be
49
+ # restored to the default.
42
50
  attr_accessor :minimum_brightness_diff
51
+ remove_method :minimum_brightness_diff= ;
43
52
  def minimum_brightness_diff=(bd) #:nodoc:
44
- @minimum_brightness_diff = bd
53
+ if bd.nil?
54
+ @minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
55
+ elsif bd > 1.0
56
+ @minimum_brightness_diff = 1.0
57
+ elsif bd < 0.0
58
+ @minimum_brightness_diff = 0.0
59
+ else
60
+ @minimum_brightness_diff = bd
61
+ end
62
+
45
63
  regenerate(@background[0], @foreground[0])
46
64
  end
47
65
 
66
+ DEFAULT_MINIMUM_COLOR_DIFF = (500.0 / 255.0)
67
+
48
68
  # The minimum colour difference between the background and the
49
- # foreground. Setting this value will regenerate the palette based on
50
- # the base colours.
69
+ # foreground, and must be between 0..3. Setting this value will
70
+ # regenerate the palette based on the base colours. The default value
71
+ # for this is 500 / 255.0.
51
72
  attr_accessor :minimum_color_diff
73
+ remove_method :minimum_color_diff= ;
52
74
  def minimum_color_diff=(cd) #:noco:
53
- @minimum_color_diff = bd
75
+ if cd.nil?
76
+ @minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF
77
+ elsif cd > 3.0
78
+ @minimum_color_diff = 3.0
79
+ elsif cd < 0.0
80
+ @minimum_color_diff = 0.0
81
+ else
82
+ @minimum_color_diff = cd
83
+ end
54
84
  regenerate(@background[0], @foreground[0])
55
85
  end
56
86
 
57
87
  # Generate the initial palette.
58
88
  def initialize(background, foreground = nil)
59
- @minimum_brightness_diff = 125 / 255.0
60
- @minimum_color_diff = 500 / 765.0
89
+ @minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
90
+ @minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF
61
91
 
62
92
  regenerate(background, foreground)
63
93
  end
@@ -140,7 +170,7 @@ class Color::Palette::MonoContrast
140
170
  # Returns the contrast between to colours, a decimal value between 0 and
141
171
  # 3. W3C accessibility guidelines for colour
142
172
  # contrast[http://www.w3.org/TR/AERT#color-contrast] suggest that this
143
- # value be at least approximately 1.96 (500 / 765.0) for proper contrast.
173
+ # value be at least approximately 1.96 (500 / 255.0) for proper contrast.
144
174
  def color_diff(c1, c2)
145
175
  r = (c1.r - c2.r).abs
146
176
  g = (c1.g - c2.g).abs