psd 0.4.2 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db9f14cd10de0296d8511ad83cf909f20519d3ca
4
- data.tar.gz: 0246042fd4037c9466a0cde4f215ebe411d529e4
3
+ metadata.gz: 8e806c5a8d10b43d7bddb5bf2e0e9ca3843a579f
4
+ data.tar.gz: 5560fc10135e67e5d396a367c5ae737cf0f84c51
5
5
  SHA512:
6
- metadata.gz: e05a52e512a93122255bda14fb3cbb329b75dd5e7be620eed20e7bccf9f109e1ea969b5430383e7910313a22afa6e4e2842631182fd11d4925d998f2a52bfa44
7
- data.tar.gz: 82ebbb3fcee334bc73f039dde683c635724cf674f6b392f9523dd30cbf43d17ec54d04f4c2eeb360b93c7f09f781812abb5db30363efc35e6cf2bdcb2245e879
6
+ metadata.gz: bcac2c4003765bc89eaba409c48b860bcc6d49ec377953332dcfccbb58baecc9b7531d285a95cfeaff14c1f8102b5b8bfab341ae915b4270f67760d271abf186
7
+ data.tar.gz: c8656fe0d3ccb52301f09e40856a0f90d1ad7ebeba4ba2793a0cc3edef958fd57daa9e16a69034abf1ae416420126bd1e9e456da5ba69b7edc28d0483755c3cb
data/README.md CHANGED
@@ -184,7 +184,6 @@ PSD.debug = true
184
184
 
185
185
  There are a few features that are currently missing from PSD.rb.
186
186
 
187
- * Global layer mask
188
187
  * Individual layer image exporting
189
188
  * More image modes + depths for image exporting
190
189
  * A few layer info blocks
data/lib/psd/color.rb CHANGED
@@ -4,122 +4,120 @@ class PSD
4
4
  # value of some kind. This means that we have to do all the conversion ourselves
5
5
  # for each color space.
6
6
  class Color
7
- instance_eval do
8
7
  # This is a relic of libpsd that will likely go away in a future version. It
9
8
  # stored the entire color value in a 32-bit address space for speed.
10
- def color_space_to_argb(color_space, color_component)
11
- color = case color_space
12
- when 0
13
- rgb_to_color *color_component
14
- when 1
15
- hsb_to_color color_component[0],
16
- color_component[1] / 100.0, color_component[2] / 100.0
17
- when 2
18
- cmyk_to_color color_component[0] / 100.0,
19
- color_component[1] / 100.0, color_component[2] / 100.0,
20
- color_component[3] / 100.0
21
- when 7
22
- lab_to_color *color_component
23
- else
24
- 0x00FFFFFF
25
- end
26
-
27
- color_to_argb(color)
9
+ def self.color_space_to_argb(color_space, color_component)
10
+ color = case color_space
11
+ when 0
12
+ rgb_to_color *color_component
13
+ when 1
14
+ hsb_to_color color_component[0],
15
+ color_component[1] / 100.0, color_component[2] / 100.0
16
+ when 2
17
+ cmyk_to_color color_component[0] / 100.0,
18
+ color_component[1] / 100.0, color_component[2] / 100.0,
19
+ color_component[3] / 100.0
20
+ when 7
21
+ lab_to_color *color_component
22
+ else
23
+ 0x00FFFFFF
28
24
  end
29
25
 
30
- def color_to_argb(color)
31
- [
32
- (color) >> 24,
33
- ((color) & 0x00FF0000) >> 16,
34
- ((color) & 0x0000FF00) >> 8,
35
- (color) & 0x000000FF
36
- ]
37
- end
26
+ color_to_argb(color)
27
+ end
38
28
 
39
- def rgb_to_color(*args)
40
- argb_to_color(255, *args)
41
- end
29
+ def self.color_to_argb(color)
30
+ [
31
+ (color) >> 24,
32
+ ((color) & 0x00FF0000) >> 16,
33
+ ((color) & 0x0000FF00) >> 8,
34
+ (color) & 0x000000FF
35
+ ]
36
+ end
42
37
 
43
- def argb_to_color(a, r, g, b)
44
- (a << 24) | (r << 16) | (g << 8) | b
45
- end
38
+ def self.rgb_to_color(*args)
39
+ argb_to_color(255, *args)
40
+ end
46
41
 
47
- def hsb_to_color(*args)
48
- ahsb_to_color(255, *args)
49
- end
42
+ def self.argb_to_color(a, r, g, b)
43
+ (a << 24) | (r << 16) | (g << 8) | b
44
+ end
50
45
 
51
- def ahsb_to_color(alpha, hue, saturation, brightness)
52
- if saturation == 0.0
53
- b = g = r = (255 * brightness).to_i
46
+ def self.hsb_to_color(*args)
47
+ ahsb_to_color(255, *args)
48
+ end
49
+
50
+ def self.ahsb_to_color(alpha, hue, saturation, brightness)
51
+ if saturation == 0.0
52
+ b = g = r = (255 * brightness).to_i
53
+ else
54
+ if brightness <= 0.5
55
+ m2 = brightness * (1 + saturation)
54
56
  else
55
- if brightness <= 0.5
56
- m2 = brightness * (1 + saturation)
57
- else
58
- m2 = brightness + saturation - brightness * saturation
59
- end
60
-
61
- m1 = 2 * brightness - m2
62
- r = hue_to_color(hue + 120, m1, m2)
63
- g = hue_to_color(hue, m1, m2)
64
- b = hue_to_color(hue - 120, m1, m2)
57
+ m2 = brightness + saturation - brightness * saturation
65
58
  end
66
59
 
67
- argb_to_color alpha, r, g, b
60
+ m1 = 2 * brightness - m2
61
+ r = hue_to_color(hue + 120, m1, m2)
62
+ g = hue_to_color(hue, m1, m2)
63
+ b = hue_to_color(hue - 120, m1, m2)
68
64
  end
69
65
 
70
- def hue_to_color(hue, m1, m2)
71
- hue = (hue % 360).to_i
72
- if hue < 60
73
- v = m1 + (m2 - m1) * hue / 60
74
- elsif hue < 180
75
- v = m2
76
- elsif hue < 240
77
- v = m1 + (m2 - m1) * (240 - hue) / 60
78
- else
79
- v = m1
80
- end
66
+ argb_to_color alpha, r, g, b
67
+ end
81
68
 
82
- (v * 255).to_i
69
+ def self.hue_to_color(hue, m1, m2)
70
+ hue = (hue % 360).to_i
71
+ if hue < 60
72
+ v = m1 + (m2 - m1) * hue / 60
73
+ elsif hue < 180
74
+ v = m2
75
+ elsif hue < 240
76
+ v = m1 + (m2 - m1) * (240 - hue) / 60
77
+ else
78
+ v = m1
83
79
  end
84
80
 
85
- def cmyk_to_color(c, m, y, k)
86
- r = 1 - (c * (1 - k) + k) * 255
87
- g = 1 - (m * (1 - k) + k) * 255
88
- b = 1 - (y * (1 - k) + k) * 255
81
+ (v * 255).to_i
82
+ end
89
83
 
90
- r = [0, r, 255].sort[1]
91
- g = [0, g, 255].sort[1]
92
- b = [0, b, 255].sort[1]
84
+ def self.cmyk_to_color(c, m, y, k)
85
+ r = 1 - (c * (1 - k) + k) * 255
86
+ g = 1 - (m * (1 - k) + k) * 255
87
+ b = 1 - (y * (1 - k) + k) * 255
93
88
 
94
- rgb_to_color r, g, b
95
- end
89
+ r = [0, r, 255].sort[1]
90
+ g = [0, g, 255].sort[1]
91
+ b = [0, b, 255].sort[1]
96
92
 
97
- def lab_to_color(*args)
98
- alab_to_color(255, *args)
99
- end
93
+ rgb_to_color r, g, b
94
+ end
100
95
 
101
- def alab_to_color(alpha, l, a, b)
102
- xyz = lab_to_xyz(l, a, b)
103
- axyz_to_color alpha, xyz[:x], xyz[:y], xyz[:z]
104
- end
96
+ def self.lab_to_color(*args)
97
+ alab_to_color(255, *args)
98
+ end
105
99
 
106
- def lab_to_xyz(l, a, b)
107
- y = (l + 16) / 116
108
- x = y + (a / 500)
109
- z = y - (b / 200)
100
+ def self.alab_to_color(alpha, l, a, b)
101
+ xyz = lab_to_xyz(l, a, b)
102
+ axyz_to_color alpha, xyz[:x], xyz[:y], xyz[:z]
103
+ end
110
104
 
111
- x, y, z = [x, y, z].map do |n|
112
- n**3 > 0.008856 ? n**3 : (n - 16 / 116) / 7.787
113
- end
114
- end
105
+ def self.lab_to_xyz(l, a, b)
106
+ y = (l + 16) / 116
107
+ x = y + (a / 500)
108
+ z = y - (b / 200)
115
109
 
116
- def cmyk_to_rgb(c, m, y, k)
117
- Hash[{
118
- r: (65535 - (c * (255 - k) + (k << 8))) >> 8,
119
- g: (65535 - (m * (255 - k) + (k << 8))) >> 8,
120
- b: (65535 - (y * (255 - k) + (k << 8))) >> 8
121
- }.map { |k, v| [k, Util.clamp(v, 0, 255)] }]
110
+ x, y, z = [x, y, z].map do |n|
111
+ n**3 > 0.008856 ? n**3 : (n - 16 / 116) / 7.787
122
112
  end
123
113
  end
114
+
115
+ def self.cmyk_to_rgb(c, m, y, k)
116
+ Hash[{
117
+ r: (65535 - (c * (255 - k) + (k << 8))) >> 8,
118
+ g: (65535 - (m * (255 - k) + (k << 8))) >> 8,
119
+ b: (65535 - (y * (255 - k) + (k << 8))) >> 8
120
+ }.map { |k, v| [k, Util.clamp(v, 0, 255)] }]
121
+ end
124
122
  end
125
123
  end
@@ -2,22 +2,6 @@ class PSD::Image::Mode
2
2
  module Greyscale
3
3
  private
4
4
 
5
- def combine_greyscale8_channel
6
- if channels == 2
7
- # We have an alpha channel
8
- @num_pixels.times do |i|
9
- alpha = @channel_data[i]
10
- grey = @channel_data[@channel_length + i]
11
-
12
- @pixel_data.push grey, grey, grey, alpha
13
- end
14
- else
15
- @num_pixels.times do |i|
16
- @pixel_data.push *([@channel_data[i]] * 3), 255
17
- end
18
- end
19
- end
20
-
21
5
  def combine_greyscale_channel
22
6
  if channels == 2
23
7
  (0...@num_pixels).step(pixel_step) do |i|
@@ -58,7 +58,7 @@ class PSD
58
58
  name: fonts.first,
59
59
  sizes: sizes,
60
60
  colors: colors,
61
- css: parser.to_css
61
+ css: to_css
62
62
  }
63
63
  end
64
64
 
@@ -80,7 +80,8 @@ class PSD
80
80
  #
81
81
  # => [[255, 0, 0, 255], [0, 0, 255, 255]]
82
82
  def colors
83
- return [] if engine_data.nil? || !styles.has_key?('FillColor')
83
+ # If the color is opaque black, this field is sometimes omitted.
84
+ return [[0, 0, 0, 255]] if engine_data.nil? || !styles.has_key?('FillColor')
84
85
  styles['FillColor'].map { |s|
85
86
  values = s['Values'].map { |v| (v * 255).round }
86
87
  values << values.shift # Change ARGB -> RGBA for consistency
@@ -115,6 +116,26 @@ class PSD
115
116
  @parser ||= PSD::EngineData.new(@data[:text]['EngineData'])
116
117
  end
117
118
 
119
+ # Creates the CSS string and returns it. Each property is newline separated
120
+ # and not all properties may be present depending on the document.
121
+ #
122
+ # Colors are returned in rgba() format and fonts may include some internal
123
+ # Photoshop fonts.
124
+ def to_css
125
+ definition = {
126
+ 'font-family' => fonts.join(', '),
127
+ 'font-size' => "#{sizes.first}pt",
128
+ 'color' => "rgba(#{colors.first.join(', ')})"
129
+ }
130
+
131
+ css = []
132
+ definition.each do |k, v|
133
+ css << "#{k}: #{v};"
134
+ end
135
+
136
+ css.join("\n")
137
+ end
138
+
118
139
  def to_hash
119
140
  {
120
141
  value: text_value,
@@ -115,7 +115,7 @@ class PSD
115
115
  @global_mask = {}
116
116
  @global_mask[:overlay_color_space] = @file.read_short
117
117
  @global_mask[:color_components] = 4.times.map { |i| @file.read_short >> 8 }
118
- @global_mask[:opacity] = @file.read_short
118
+ @global_mask[:opacity] = @file.read_short / 16.0
119
119
 
120
120
  # 0 = color selected, 1 = color protected, 128 = use value per layer
121
121
  @global_mask[:kind] = @file.read(1).bytes.to_a[0]
@@ -27,7 +27,7 @@ class PSD
27
27
  end
28
28
 
29
29
  # Inverse of has_children?
30
- def is_childless?
30
+ def childless?
31
31
  !has_children?
32
32
  end
33
33
 
@@ -44,7 +44,7 @@ class PSD
44
44
  end
45
45
 
46
46
  # Is this node the only descendant of its parent?
47
- def is_only_child?
47
+ def only_child?
48
48
  siblings.length == 1
49
49
  end
50
50
 
data/lib/psd/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class PSD
2
- VERSION = "0.4.2"
2
+ VERSION = "1.0.0"
3
3
  end
data/psd.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
20
20
 
21
21
  gem.add_dependency "bindata"
22
22
  gem.add_dependency "oily_png"
23
- gem.add_dependency 'psd-enginedata'
23
+ gem.add_dependency 'psd-enginedata', '~> 1.0'
24
24
 
25
25
  gem.test_files = Dir.glob("spec/**/*")
26
26
  gem.add_development_dependency 'rspec'
data/spec/files/text.psd CHANGED
Binary file
@@ -9,8 +9,8 @@ describe "Hierarchy" do
9
9
  @psd.parse!
10
10
 
11
11
  tree = @psd.tree.to_hash
12
- tree.should include :children
13
- tree[:children].length.should == 3
12
+ expect(tree).to include :children
13
+ expect(tree[:children].length).to eq(3)
14
14
  end
15
15
 
16
16
  describe "Ancestry" do
@@ -20,66 +20,66 @@ describe "Hierarchy" do
20
20
  end
21
21
 
22
22
  it "should provide tree traversal methods" do
23
- @tree.respond_to?(:root).should be_true
24
- @tree.respond_to?(:siblings).should be_true
25
- @tree.respond_to?(:descendants).should be_true
26
- @tree.respond_to?(:subtree).should be_true
23
+ expect(@tree).to respond_to(:root)
24
+ expect(@tree).to respond_to(:siblings)
25
+ expect(@tree).to respond_to(:descendants)
26
+ expect(@tree).to respond_to(:subtree)
27
27
  end
28
28
 
29
29
  it "should properly identify the root node" do
30
- @tree.root?.should be_true
31
- @tree.root.should == @tree
32
- @tree.children.last.root.should == @tree
30
+ expect(@tree.root?).to be_true
31
+ expect(@tree.root).to be @tree
32
+ expect(@tree.children.last.root).to be @tree
33
33
  end
34
34
 
35
35
  it "should retrieve all descendants of a node" do
36
- @tree.descendants.size.should == 12
37
- @tree.descendant_layers.size.should == 9
38
- @tree.descendant_groups.size.should == 3
39
- @tree.descendants.first.should_not == @tree
36
+ expect(@tree.descendants.size).to eq(12)
37
+ expect(@tree.descendant_layers.size).to eq(9)
38
+ expect(@tree.descendant_groups.size).to eq(3)
39
+ expect(@tree.descendants.first).not_to be @tree
40
40
  end
41
41
 
42
42
  it "should retreive the entire subtree of a node" do
43
- @tree.subtree.size.should == 13
44
- @tree.subtree_layers.size.should == 9
45
- @tree.subtree_groups.size.should == 3
46
- @tree.subtree.first.should == @tree
43
+ expect(@tree.subtree.size).to eq(13)
44
+ expect(@tree.subtree_layers.size).to eq(9)
45
+ expect(@tree.subtree_groups.size).to eq(3)
46
+ expect(@tree.subtree.first).to be @tree
47
47
  end
48
48
 
49
49
  it "should properly identify the existence of children" do
50
- @tree.has_children?.should be_true
51
- @tree.is_childless?.should be_false
52
- @tree.descendant_layers.first.has_children?.should be_false
53
- @tree.descendant_layers.first.is_childless?.should be_true
50
+ expect(@tree).to have_children
51
+ expect(@tree).to_not be_childless
52
+ expect(@tree.descendant_layers.first).to_not have_children
53
+ expect(@tree.descendant_layers.first).to be_childless
54
54
  end
55
55
 
56
56
  it "should retrieve all siblings of a node" do
57
- @tree.children.first.siblings.should == @tree.children
58
- @tree.children.first.siblings.should include @tree.children.first
59
- @tree.children.first.has_siblings?.should be_true
60
- @tree.children.first.is_only_child?.should be_false
57
+ expect(@tree.children.first.siblings).to be @tree.children
58
+ expect(@tree.children.first.siblings).to include @tree.children.first
59
+ expect(@tree.children.first).to have_siblings
60
+ expect(@tree.children.first).to_not be_only_child
61
61
  end
62
62
 
63
63
  it "should properly calculate node depth" do
64
- @tree.depth.should == 0
65
- @tree.descendant_layers.last.depth.should == 2
66
- @tree.children.first.depth.should == 1
64
+ expect(@tree.depth).to eq(0)
65
+ expect(@tree.descendant_layers.last.depth).to eq(2)
66
+ expect(@tree.children.first.depth).to eq(1)
67
67
  end
68
68
 
69
69
  describe "Searching" do
70
70
  it "should find a node given a path" do
71
- @tree.children_at_path('Version A/Matte').is_a?(Array).should be_true
72
- @tree.children_at_path('Version A/Matte').size.should == 1
73
- @tree.children_at_path('Version A/Matte').first.is_a?(PSD::Node::Layer).should be_true
71
+ expect(@tree.children_at_path('Version A/Matte')).to be_an_instance_of(Array)
72
+ expect(@tree.children_at_path('Version A/Matte').size).to eq(1)
73
+ expect(@tree.children_at_path('Version A/Matte').first).to be_an_instance_of(PSD::Node::Layer)
74
74
  end
75
75
 
76
76
  it "should ignore leading slashes" do
77
- @tree.children_at_path('/Version A/Matte').size.should == 1
77
+ expect(@tree.children_at_path('/Version A/Matte').size).to eq(1)
78
78
  end
79
79
 
80
80
  it "should return an empty array when a node is not found" do
81
- @tree.children_at_path('LOLWUTOMGBBQSAUCE').is_a?(Array).should be_true
82
- @tree.children_at_path('LOLWUTOMGBBQSAUCE').size.should == 0
81
+ expect(@tree.children_at_path('NOPE')).to be_an_instance_of(Array)
82
+ expect(@tree.children_at_path('NOPE').size).to eq(0)
83
83
  end
84
84
  end
85
85
  end
@@ -9,7 +9,7 @@ describe "Identity exports" do
9
9
  tmpfile = Tempfile.new("simplest_export.psd")
10
10
  psd.export tmpfile.path
11
11
 
12
- Digest::MD5.hexdigest(tmpfile.read).should == Digest::MD5.hexdigest(File.read(filepath))
12
+ expect(Digest::MD5.hexdigest(tmpfile.read)).to eq(Digest::MD5.hexdigest(File.read(filepath)))
13
13
  end
14
14
 
15
15
  it "should export a file with a layer" do
@@ -19,7 +19,7 @@ describe "Identity exports" do
19
19
  tmpfile = Tempfile.new("one_layer_export.psd")
20
20
  psd.export tmpfile.path
21
21
 
22
- Digest::MD5.hexdigest(tmpfile.read).should == Digest::MD5.hexdigest(File.read(filepath))
22
+ expect(Digest::MD5.hexdigest(tmpfile.read)).to eq(Digest::MD5.hexdigest(File.read(filepath)))
23
23
  end
24
24
 
25
25
  it "should export a PSD with vector paths" do
@@ -29,6 +29,6 @@ describe "Identity exports" do
29
29
  tmpfile = Tempfile.new("path_export.psd")
30
30
  psd.export tmpfile.path
31
31
 
32
- Digest::MD5.hexdigest(tmpfile.read).should == Digest::MD5.hexdigest(File.read(filepath))
32
+ expect(Digest::MD5.hexdigest(tmpfile.read)).to eq(Digest::MD5.hexdigest(File.read(filepath)))
33
33
  end
34
34
  end
data/spec/parsing_spec.rb CHANGED
@@ -7,7 +7,7 @@ describe 'Parsing' do
7
7
 
8
8
  it "should parse without error" do
9
9
  @psd.parse!
10
- @psd.parsed?.should be_true
10
+ expect(@psd).to be_parsed
11
11
  end
12
12
 
13
13
  describe 'Header' do
@@ -16,25 +16,25 @@ describe 'Parsing' do
16
16
  end
17
17
 
18
18
  it "should contain data" do
19
- @psd.header.should_not be_nil
19
+ expect(@psd.header).not_to be_nil
20
20
  end
21
21
 
22
22
  it "should be the proper version" do
23
- @psd.header.version.should == 1
23
+ expect(@psd.header.version).to eq(1)
24
24
  end
25
25
 
26
26
  it "should have the proper number of channels" do
27
- @psd.header.channels.should == 3
27
+ expect(@psd.header.channels).to eq(3)
28
28
  end
29
29
 
30
30
  it "should parse the proper document dimensions" do
31
- @psd.header.width.should == 900
32
- @psd.header.height.should == 600
31
+ expect(@psd.header.width).to eq(900)
32
+ expect(@psd.header.height).to eq(600)
33
33
  end
34
34
 
35
35
  it "should correctly parse the color mode" do
36
- @psd.header.mode.should == 3
37
- @psd.header.mode_name.should == 'RGBColor'
36
+ expect(@psd.header.mode).to eq(3)
37
+ expect(@psd.header.mode_name).to eq('RGBColor')
38
38
  end
39
39
  end
40
40
 
@@ -44,18 +44,18 @@ describe 'Parsing' do
44
44
  end
45
45
 
46
46
  it "should contain data" do
47
- @psd.resources.should_not be_nil
48
- @psd.resources.data.is_a?(Hash).should be_true
49
- @psd.resources.data.size.should >= 1
47
+ expect(@psd.resources).not_to be_nil
48
+ expect(@psd.resources.data).to be_an_instance_of(Hash)
49
+ expect(@psd.resources.data.size).to be >= 1
50
50
  end
51
51
 
52
52
  it "should be of type 8BIM" do
53
- @psd.resources.data.each { |id, r| r.type.should == '8BIM' }
53
+ @psd.resources.data.each { |id, r| expect(r.type).to eq('8BIM') }
54
54
  end
55
55
 
56
56
  it "should have an ID" do
57
57
  @psd.resources.data.each do |id, r|
58
- r.id.should_not be_nil
58
+ expect(r.id).to_not be_nil
59
59
  end
60
60
  end
61
61
  end
@@ -66,18 +66,19 @@ describe 'Parsing' do
66
66
  end
67
67
 
68
68
  it "should contain data" do
69
- @psd.layer_mask.should_not be_nil
70
- @psd.layer_mask.is_a?(PSD::LayerMask).should be_true
69
+ expect(@psd.layer_mask).to_not be_nil
70
+ expect(@psd.layer_mask).to be_an_instance_of(PSD::LayerMask)
71
71
  end
72
72
 
73
73
  it "should contain layers" do
74
- @psd.layer_mask.layers.size.should > 0
74
+ expect(@psd.layer_mask.layers.size).to be > 0
75
75
  end
76
76
 
77
77
  it "should contain the global layer mask data" do
78
- pending "Not implemented yet"
79
-
80
- @psd.layer_mask.global_mask.should_not be_nil
78
+ expect(@psd.layer_mask.global_mask).to_not be_nil
79
+ expect(@psd.layer_mask.global_mask).to include :overlay_color_space
80
+ expect(@psd.layer_mask.global_mask).to include :color_components
81
+ expect(@psd.layer_mask.global_mask).to include opacity: 1.0
81
82
  end
82
83
  end
83
84
 
@@ -87,48 +88,48 @@ describe 'Parsing' do
87
88
  end
88
89
 
89
90
  it "should contain each layer" do
90
- @psd.layer_mask.layers.size.should == 15
91
- @psd.layers.should == @psd.layer_mask.layers
92
- @psd.layers.each { |l| l.is_a?(PSD::Layer).should be_true }
91
+ expect(@psd.layer_mask.layers.size).to eq(15)
92
+ expect(@psd.layers).to be @psd.layer_mask.layers
93
+ @psd.layers.each { |l| expect(l).to be_an_instance_of(PSD::Layer) }
93
94
  end
94
95
 
95
96
  it "should have a name" do
96
- @psd.layers.first.name.should == 'Version C'
97
+ expect(@psd.layers.first.name).to eq('Version C')
97
98
  end
98
99
 
99
100
  it "should properly identify folders" do
100
- @psd.layers.first.folder?.should be_true
101
- @psd.layers.select { |l| l.name == 'Matte' }.first.folder?.should be_false
101
+ expect(@psd.layers.first).to be_folder
102
+ expect(@psd.layers.select { |l| l.name == 'Matte' }.first).not_to be_folder
102
103
  end
103
104
 
104
105
  it "should properly detect visibility" do
105
- @psd.layers.first.visible?.should be_false
106
- @psd
107
- .layers
108
- .select { |l| l.name == 'Version A' }.first
109
- .visible?
110
- .should be_true
106
+ expect(@psd.layers.first).not_to be_visible
107
+ expect(
108
+ @psd
109
+ .layers
110
+ .select { |l| l.name == 'Version A' }.first
111
+ ).to be_visible
111
112
  end
112
113
 
113
114
  it "should properly calculate dimensions" do
114
115
  layer = @psd.layers.select { |l| l.name == 'Logo_Glyph' }.last
115
- layer.width.should == 142
116
- layer.height.should == 179
116
+ expect(layer.width).to eq(142)
117
+ expect(layer.height).to eq(179)
117
118
  end
118
119
 
119
120
  it "should properly calculate coordinates" do
120
121
  layer = @psd.layers.select { |l| l.name == 'Logo_Glyph' }.last
121
- layer.left.should == 379
122
- layer.top.should == 210
122
+ expect(layer.left).to eq(379)
123
+ expect(layer.top).to eq(210)
123
124
  end
124
125
 
125
126
  it "should have a blend mode" do
126
- layer = @psd.layers.select { |l| l.name == 'Version A' }.last
127
- layer.blend_mode.should_not be_nil
128
- layer.blend_mode.mode.should == 'normal'
129
- layer.blend_mode.opacity.should == 255
130
- layer.blend_mode.opacity_percentage.should == 100
131
- layer.blend_mode.visible.should be_true
127
+ blend_mode = @psd.layers.select { |l| l.name == 'Version A' }.last.blend_mode
128
+ expect(blend_mode).to_not be_nil
129
+ expect(blend_mode.mode).to eq('normal')
130
+ expect(blend_mode.opacity).to eq(255)
131
+ expect(blend_mode.opacity_percentage).to eq(100)
132
+ expect(blend_mode.visible).to be_true
132
133
  end
133
134
  end
134
135
  end
data/spec/psd_spec.rb CHANGED
@@ -5,8 +5,8 @@ describe 'PSD' do
5
5
 
6
6
  it 'should open a file without a block' do
7
7
  psd = PSD.open(filename)
8
- psd.parsed?.should == true
9
- psd.should be_instance_of PSD
8
+ expect(psd).to be_parsed
9
+ expect(psd).to be_an_instance_of(PSD)
10
10
  end
11
11
 
12
12
  it 'should refuse to open a bad filename' do
@@ -15,11 +15,13 @@ describe 'PSD' do
15
15
 
16
16
  it 'should open a file and feed it to a block' do
17
17
  PSD.open(filename) do |psd|
18
- psd.parsed?.should == true
19
- psd.should be_instance_of PSD
18
+ expect(psd).to be_parsed
19
+ expect(psd).to be_an_instance_of(PSD)
20
20
  end
21
21
  end
22
22
 
23
+ # We have to use #should syntax here because the DSL binds
24
+ # the block to the PSD instance.
23
25
  it 'should open a file and feed it to a block DSL style' do
24
26
  PSD.open(filename) do
25
27
  parsed?.should == true
data/spec/text_spec.rb CHANGED
@@ -7,6 +7,21 @@ describe 'Text' do
7
7
 
8
8
  text = psd.tree.children.first.text
9
9
  text.should be_an_instance_of(Hash)
10
- text[:value].should == 'Test'
10
+ expect(text[:value]).to eq('Test')
11
+ end
12
+
13
+ it "can be exported as CSS" do
14
+ psd = PSD.new('spec/files/text.psd')
15
+ psd.parse!
16
+
17
+ type = psd.tree.children.first.type
18
+ css = type.to_css
19
+ expect(css).to be_an_instance_of(String)
20
+ expect(css).to include 'MyriadPro-Regular'
21
+ expect(css).to include '37.0pt'
22
+ expect(css).to include 'rgba(24, 24, 24, 255)'
23
+ css.split(/\n/).each do |c|
24
+ expect(c[-1]).to eq(";")
25
+ end
11
26
  end
12
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: psd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan LeFevre
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-21 00:00:00.000000000 Z
12
+ date: 2013-08-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bindata
@@ -43,16 +43,16 @@ dependencies:
43
43
  name: psd-enginedata
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '>='
46
+ - - ~>
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: '1.0'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - '>='
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: '1.0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rspec
58
58
  requirement: !ruby/object:Gem::Requirement