psd 0.4.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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