psd 2.1.2 → 3.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/psd.rb +8 -6
- data/lib/psd/blend_mode.rb +46 -38
- data/lib/psd/channel_image.rb +9 -5
- data/lib/psd/descriptor.rb +39 -16
- data/lib/psd/header.rb +33 -32
- data/lib/psd/image_formats/rle.rb +4 -10
- data/lib/psd/image_modes/rgb.rb +4 -4
- data/lib/psd/layer.rb +1 -15
- data/lib/psd/layer/blend_modes.rb +12 -12
- data/lib/psd/layer/helpers.rb +8 -10
- data/lib/psd/layer/info.rb +9 -7
- data/lib/psd/layer/position_and_channels.rb +0 -4
- data/lib/psd/layer_info.rb +0 -4
- data/lib/psd/layer_info/blend_clipping_elements.rb +4 -2
- data/lib/psd/layer_info/blend_interior_elements.rb +4 -2
- data/lib/psd/layer_info/fill_opacity.rb +4 -2
- data/lib/psd/layer_info/layer_group.rb +4 -2
- data/lib/psd/layer_info/layer_id.rb +4 -2
- data/lib/psd/layer_info/layer_name_source.rb +4 -2
- data/lib/psd/layer_info/layer_section_divider.rb +4 -2
- data/lib/psd/layer_info/legacy_typetool.rb +5 -3
- data/lib/psd/layer_info/locked.rb +4 -2
- data/lib/psd/layer_info/metadata_setting.rb +4 -2
- data/lib/psd/layer_info/object_effects.rb +4 -2
- data/lib/psd/layer_info/pattern.rb +14 -0
- data/lib/psd/layer_info/placed_layer.rb +4 -2
- data/lib/psd/layer_info/reference_point.rb +4 -2
- data/lib/psd/layer_info/sheet_color.rb +18 -0
- data/lib/psd/layer_info/solid_color.rb +36 -0
- data/lib/psd/layer_info/typetool.rb +4 -2
- data/lib/psd/layer_info/unicode_name.rb +4 -2
- data/lib/psd/layer_info/vector_mask.rb +4 -2
- data/lib/psd/layer_info/vector_origination.rb +14 -0
- data/lib/psd/layer_info/vector_stroke.rb +4 -2
- data/lib/psd/layer_info/vector_stroke_content.rb +4 -2
- data/lib/psd/layer_mask.rb +2 -8
- data/lib/psd/lazy_execute.rb +5 -1
- data/lib/psd/node.rb +112 -48
- data/lib/psd/nodes/ancestry.rb +80 -75
- data/lib/psd/nodes/build_preview.rb +4 -4
- data/lib/psd/nodes/group.rb +35 -0
- data/lib/psd/nodes/layer.rb +40 -0
- data/lib/psd/nodes/root.rb +90 -0
- data/lib/psd/nodes/search.rb +19 -19
- data/lib/psd/path_record.rb +1 -71
- data/lib/psd/renderer.rb +6 -5
- data/lib/psd/renderer/blender.rb +10 -5
- data/lib/psd/renderer/cairo_helpers.rb +46 -0
- data/lib/psd/renderer/canvas.rb +39 -19
- data/lib/psd/renderer/canvas_management.rb +2 -2
- data/lib/psd/renderer/clipping_mask.rb +5 -4
- data/lib/psd/renderer/compose.rb +61 -68
- data/lib/psd/renderer/layer_styles.rb +15 -5
- data/lib/psd/renderer/layer_styles/color_overlay.rb +46 -27
- data/lib/psd/renderer/mask.rb +26 -22
- data/lib/psd/renderer/mask_canvas.rb +12 -0
- data/lib/psd/renderer/vector_shape.rb +239 -0
- data/lib/psd/resource_section.rb +4 -7
- data/lib/psd/resources.rb +4 -19
- data/lib/psd/resources/base.rb +27 -0
- data/lib/psd/resources/guides.rb +6 -4
- data/lib/psd/resources/layer_comps.rb +6 -4
- data/lib/psd/resources/slices.rb +7 -5
- data/lib/psd/version.rb +1 -1
- data/psd.gemspec +1 -2
- data/spec/files/blendmodes.psd +0 -0
- data/spec/hierarchy_spec.rb +5 -0
- metadata +27 -26
- data/lib/psd/layer_info/vector_mask_2.rb +0 -10
- data/lib/psd/node_exporting.rb +0 -20
- data/lib/psd/node_group.rb +0 -86
- data/lib/psd/node_layer.rb +0 -81
- data/lib/psd/node_root.rb +0 -93
- data/lib/psd/nodes/has_children.rb +0 -13
- data/lib/psd/nodes/lock_to_origin.rb +0 -7
- data/lib/psd/nodes/parse_layers.rb +0 -18
- data/lib/psd/renderer/layer_styles/drop_shadow.rb +0 -75
- data/lib/psd/section.rb +0 -26
@@ -1,29 +1,29 @@
|
|
1
1
|
class PSD
|
2
2
|
class Layer
|
3
3
|
module BlendModes
|
4
|
-
attr_reader :blend_mode
|
4
|
+
attr_reader :blend_mode
|
5
|
+
|
6
|
+
delegate :opacity, :visible, :clipped?, to: :blend_mode
|
7
|
+
alias_method :visible?, :visible
|
8
|
+
|
9
|
+
# Is this layer hidden?
|
10
|
+
def hidden?
|
11
|
+
!visible
|
12
|
+
end
|
5
13
|
|
6
14
|
def blending_mode
|
7
15
|
if !info[:section_divider].nil? && info[:section_divider].blend_mode
|
8
16
|
BlendMode::BLEND_MODES[info[:section_divider].blend_mode.strip.to_sym]
|
9
17
|
else
|
10
|
-
@
|
18
|
+
@blend_mode.mode
|
11
19
|
end
|
12
20
|
end
|
13
21
|
|
14
|
-
# Is the layer below this one a clipping mask?
|
15
|
-
def clipped?
|
16
|
-
@blend_mode.clipping == 1
|
17
|
-
end
|
18
|
-
|
19
22
|
private
|
20
23
|
|
21
24
|
def parse_blend_modes
|
22
|
-
@blend_mode = BlendMode.
|
23
|
-
|
24
|
-
@blending_mode = @blend_mode.mode
|
25
|
-
@opacity = @blend_mode.opacity
|
26
|
-
@visible = @blend_mode.visible
|
25
|
+
@blend_mode = BlendMode.new(@file)
|
26
|
+
@blend_mode.parse!
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/lib/psd/layer/helpers.rb
CHANGED
@@ -47,16 +47,6 @@ class PSD
|
|
47
47
|
info[:locked].transparency_locked
|
48
48
|
end
|
49
49
|
|
50
|
-
# Is this layer visible?
|
51
|
-
def visible?
|
52
|
-
@visible
|
53
|
-
end
|
54
|
-
|
55
|
-
# Is this layer hidden?
|
56
|
-
def hidden?
|
57
|
-
!@visible
|
58
|
-
end
|
59
|
-
|
60
50
|
# Helper that exports the text data in this layer, if any.
|
61
51
|
def text
|
62
52
|
return nil unless info[:type]
|
@@ -72,6 +62,14 @@ class PSD
|
|
72
62
|
return 255 unless info.has_key?(:fill_opacity)
|
73
63
|
info[:fill_opacity].value
|
74
64
|
end
|
65
|
+
|
66
|
+
def raster_mask?
|
67
|
+
image.has_mask? && image.mask_data.length > 0
|
68
|
+
end
|
69
|
+
|
70
|
+
def vector_mask?
|
71
|
+
!vector_mask.nil?
|
72
|
+
end
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
data/lib/psd/layer/info.rb
CHANGED
@@ -12,21 +12,27 @@ class PSD
|
|
12
12
|
object_effects: ObjectEffects,
|
13
13
|
name: UnicodeName,
|
14
14
|
section_divider: LayerSectionDivider,
|
15
|
+
sheet_color: SheetColor,
|
15
16
|
nested_section_divider: NestedLayerDivider,
|
16
17
|
reference_point: ReferencePoint,
|
17
18
|
layer_id: LayerID,
|
18
19
|
fill_opacity: FillOpacity,
|
19
20
|
placed_layer: PlacedLayer,
|
20
21
|
locked: Locked,
|
22
|
+
solid_color: SolidColor,
|
21
23
|
vector_mask: VectorMask,
|
22
|
-
|
24
|
+
vector_origination: VectorOrigination,
|
23
25
|
vector_stroke: VectorStroke,
|
24
26
|
vector_stroke_content: VectorStrokeContent
|
25
|
-
}
|
27
|
+
}.freeze
|
26
28
|
|
27
29
|
attr_reader :adjustments
|
28
30
|
alias :info :adjustments
|
29
31
|
|
32
|
+
LAYER_INFO.keys.each do |key|
|
33
|
+
define_method(key) { @adjustments[key] }
|
34
|
+
end
|
35
|
+
|
30
36
|
private
|
31
37
|
|
32
38
|
# This section is a bit tricky to parse because it represents all of the
|
@@ -47,7 +53,7 @@ class PSD
|
|
47
53
|
|
48
54
|
key_parseable = false
|
49
55
|
LAYER_INFO.each do |name, info|
|
50
|
-
next unless info.key
|
56
|
+
next unless info.should_parse?(key)
|
51
57
|
|
52
58
|
PSD.logger.debug "Layer Info: key = #{key}, start = #{pos}, length = #{length}"
|
53
59
|
|
@@ -65,10 +71,6 @@ class PSD
|
|
65
71
|
|
66
72
|
@extra_data_end = @file.tell
|
67
73
|
end
|
68
|
-
|
69
|
-
def vector_mask
|
70
|
-
info[:vector_mask_2] || info[:vector_mask]
|
71
|
-
end
|
72
74
|
end
|
73
75
|
end
|
74
76
|
end
|
@@ -10,8 +10,6 @@ class PSD
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def parse_position_and_channels
|
13
|
-
start_section(:info)
|
14
|
-
|
15
13
|
@top = @file.read_int
|
16
14
|
@left = @file.read_int
|
17
15
|
@bottom = @file.read_int
|
@@ -27,8 +25,6 @@ class PSD
|
|
27
25
|
|
28
26
|
@channels_info << {id: channel_id, length: channel_length}
|
29
27
|
end
|
30
|
-
|
31
|
-
end_section(:info)
|
32
28
|
end
|
33
29
|
|
34
30
|
def export_position_and_channels(outfile)
|
data/lib/psd/layer_info.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'psd/layer_info'
|
2
2
|
|
3
3
|
class PSD
|
4
4
|
# Not 100% sure what the purpose of this key is, but it seems to exist
|
@@ -7,7 +7,9 @@ class PSD
|
|
7
7
|
#
|
8
8
|
# See https://github.com/layervault/psd.rb/issues/38
|
9
9
|
class NestedLayerDivider < LayerInfo
|
10
|
-
|
10
|
+
def self.should_parse?(key)
|
11
|
+
key == 'lsdk'
|
12
|
+
end
|
11
13
|
|
12
14
|
attr_reader :is_folder, :is_hidden
|
13
15
|
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
require 'psd/layer_info'
|
2
2
|
|
3
3
|
class PSD
|
4
4
|
class LayerSectionDivider < LayerInfo
|
5
|
-
|
5
|
+
def self.should_parse?(key)
|
6
|
+
key == 'lsct'
|
7
|
+
end
|
6
8
|
|
7
9
|
attr_reader :layer_type, :is_folder, :is_hidden, :blend_mode, :sub_type
|
8
10
|
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'psd/layer_info'
|
2
|
+
require 'psd/layer_info/typetool'
|
3
3
|
|
4
4
|
class PSD
|
5
5
|
class LegacyTypeTool < TypeTool
|
6
|
-
|
6
|
+
def self.should_parse?(key)
|
7
|
+
key == 'tySh'
|
8
|
+
end
|
7
9
|
|
8
10
|
def parse
|
9
11
|
version = @file.read_short
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
require 'psd/layer_info'
|
2
2
|
|
3
3
|
class PSD
|
4
4
|
class Locked < LayerInfo
|
5
|
-
|
5
|
+
def self.should_parse?(key)
|
6
|
+
key == 'lspf'
|
7
|
+
end
|
6
8
|
|
7
9
|
attr_reader :all_locked, :transparency_locked, :composite_locked, :position_locked
|
8
10
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'psd/layer_info'
|
2
|
+
|
3
|
+
class PSD
|
4
|
+
class SheetColor < LayerInfo
|
5
|
+
def self.should_parse?(key)
|
6
|
+
key == 'lclr'
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
10
|
+
@data = [
|
11
|
+
@file.read_short,
|
12
|
+
@file.read_short,
|
13
|
+
@file.read_short,
|
14
|
+
@file.read_short
|
15
|
+
]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'psd/layer_info'
|
2
|
+
|
3
|
+
class PSD
|
4
|
+
class SolidColor < LayerInfo
|
5
|
+
def self.should_parse?(key)
|
6
|
+
key == 'SoCo'
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
10
|
+
@file.seek 4, IO::SEEK_CUR
|
11
|
+
@data = Descriptor.new(@file).parse
|
12
|
+
end
|
13
|
+
|
14
|
+
def color
|
15
|
+
ChunkyPNG::Color.rgb(r, g, b)
|
16
|
+
end
|
17
|
+
|
18
|
+
def r
|
19
|
+
@r ||= color_data['Rd '].round
|
20
|
+
end
|
21
|
+
|
22
|
+
def g
|
23
|
+
@g ||= color_data['Grn '].round
|
24
|
+
end
|
25
|
+
|
26
|
+
def b
|
27
|
+
@b ||= color_data['Bl '].round
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def color_data
|
33
|
+
@data['Clr ']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
2
|
+
require 'psd/layer_info'
|
3
3
|
|
4
4
|
class PSD
|
5
5
|
# Parses and provides information about text areas within layers in
|
6
6
|
# the document.
|
7
7
|
class TypeTool < LayerInfo
|
8
|
-
|
8
|
+
def self.should_parse?(key)
|
9
|
+
key == 'TySh'
|
10
|
+
end
|
9
11
|
|
10
12
|
# Parse all of the text data in the layer.
|
11
13
|
def parse
|