Class: PSD::TypeTool

Inherits:
LayerInfo show all
Defined in:
lib/psd/layer/info/typetool.rb

Overview

Parses and provides information about text areas within layers in the document.

Direct Known Subclasses

LegacyTypeTool

Instance Attribute Summary

Attributes inherited from LayerInfo

#data

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from LayerInfo

#initialize, #skip

Constructor Details

This class inherits a constructor from PSD::LayerInfo

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



165
166
167
168
# File 'lib/psd/layer/info/typetool.rb', line 165

def method_missing(method, *args, &block)
  return @data[method] if @data.has_key?(method)
  return super
end

Class Method Details

.should_parse?(key) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
# File 'lib/psd/layer/info/typetool.rb', line 8

def self.should_parse?(key)
  key == 'TySh'
end

Instance Method Details

#alignmentObject



81
82
83
84
85
86
87
88
# File 'lib/psd/layer/info/typetool.rb', line 81

def alignment
  return {} if engine_data.nil?
  engine_data.EngineDict.ParagraphRun.RunArray.map do |s| 
    ["left", "right", "center", "justify"][[s.ParagraphSheet.Properties.Justification.to_i,3].min]
  end
rescue
  []
end

#colorsObject

Return all colors used for text in this layer. The colors are returned in RGBA format as an array of arrays.

> [[255, 0, 0, 255], [0, 0, 255, 255]]



94
95
96
97
98
99
100
101
# File 'lib/psd/layer/info/typetool.rb', line 94

def colors
  # If the color is opaque black, this field is sometimes omitted.
  return [[0, 0, 0, 255]] if engine_data.nil? || !styles.has_key?('FillColor')
  styles['FillColor'].map { |s|
    values = s['Values'].map { |v| (v * 255).round }
    values << values.shift # Change ARGB -> RGBA for consistency
  }.uniq
end

#engine_dataObject



103
104
105
# File 'lib/psd/layer/info/typetool.rb', line 103

def engine_data
  @data[:engine_data]
end

#fontObject

Gets all of the basic font information for this text area. This assumes that the first font is the only one you want.



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/psd/layer/info/typetool.rb', line 50

def font
  {
    name: fonts.first,
    fonts: fonts,
    sizes: sizes,
    colors: colors,
    alignment: alignment,
    leadings: leadings,
    css: to_css
  }
end

#fontsObject

Returns all fonts listed for this layer, since fonts are defined on a per-character basis.



64
65
66
67
# File 'lib/psd/layer/info/typetool.rb', line 64

def fonts
  return [] if engine_data.nil?
  engine_data.ResourceDict.FontSet.map(&:Name)
end

#leadingsObject

Return all leadings (line spacing) for this layer.



70
71
72
73
# File 'lib/psd/layer/info/typetool.rb', line 70

def leadings
  return [] if engine_data.nil? || !styles.has_key?('Leading')
  styles['Leading'].uniq
end

#parseObject

Parse all of the text data in the layer.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/psd/layer/info/typetool.rb', line 13

def parse
  version = @file.read_short
  parse_transform_info

  text_version = @file.read_short
  descriptor_version = @file.read_int

  @data[:text] = Descriptor.new(@file).parse

  @data[:engine_data] = nil
  begin
    parser.parse!
    @data[:engine_data] = parser.result
  rescue Exception => e
    PSD.logger.error e.message
  end

  warpVersion = @file.read_short
  descriptor_version = @file.read_int

  @data[:warp] = Descriptor.new(@file).parse
  [:left, :top, :right, :bottom].each do |pos|
    @data[pos] = @file.read_int
  end

  return self
end

#parserObject



127
128
129
# File 'lib/psd/layer/info/typetool.rb', line 127

def parser
  @parser ||= PSD::EngineData.new(@data[:text]['EngineData'])
end

#sizesObject

Return all font sizes for this layer.



76
77
78
79
# File 'lib/psd/layer/info/typetool.rb', line 76

def sizes
  return [] if engine_data.nil? || !styles.has_key?('FontSize')
  styles['FontSize'].uniq
end

#stylesObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/psd/layer/info/typetool.rb', line 107

def styles
  return {} if engine_data.nil?

  @styles ||= (
    data = engine_data.EngineDict.StyleRun.RunArray.map do |r|
      r.StyleSheet.StyleSheetData
    end

    Hash[data.reduce({}) { |m, o|
      o.each do |k, v|
        (m[k] ||= []) << v
      end

      m
    }.map { |k, v|
      [k, v.uniq]
    }]
  )
end

#text_valueObject Also known as: to_s

Extracts the text within the text area. In the event that psd-enginedata fails for some reason, we attempt to extract the text using some rough regex.



43
44
45
# File 'lib/psd/layer/info/typetool.rb', line 43

def text_value
  @data[:text]['Txt ']
end

#to_cssObject

Creates the CSS string and returns it. Each property is newline separated and not all properties may be present depending on the document.

Colors are returned in rgba() format and fonts may include some internal Photoshop fonts.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/psd/layer/info/typetool.rb', line 136

def to_css      
  definition = {
    'font-family' => fonts.join(', '),
    'font-size' => "#{sizes.first}pt",
    'color' => "rgba(#{colors.first.join(', ')})",
    'text-align' => alignment.first
  }

  css = []
  definition.each do |k, v|
    next if v.nil?
    css << "#{k}: #{v};"
  end

  css.join("\n")
end

#to_hashObject



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/psd/layer/info/typetool.rb', line 153

def to_hash
  {
    value:      text_value,
    font:       font,
    left:       left,
    top:        top,
    right:      right,
    bottom:     bottom,
    transform:  transform
  }
end