require 'psd/layer/info/black_white' require 'psd/layer/info/blend_clipping_elements' require 'psd/layer/info/blend_interior_elements' require 'psd/layer/info/brightness_contrast' require 'psd/layer/info/channel_blending_restrictions' require 'psd/layer/info/channel_mixer' require 'psd/layer/info/color_balance' require 'psd/layer/info/color_lookup' require 'psd/layer/info/content_generator' require 'psd/layer/info/curves' require 'psd/layer/info/exposure' require 'psd/layer/info/fill_opacity' require 'psd/layer/info/gradient_fill' require 'psd/layer/info/gradient_map' require 'psd/layer/info/hue_saturation' require 'psd/layer/info/invert' require 'psd/layer/info/knockout' require 'psd/layer/info/layer_mask_as_global_mask' require 'psd/layer/info/layer_group' require 'psd/layer/info/layer_id' require 'psd/layer/info/layer_name_source' require 'psd/layer/info/layer_section_divider' require 'psd/layer/info/legacy_typetool' require 'psd/layer/info/levels' require 'psd/layer/info/locked' require 'psd/layer/info/metadata_setting' require 'psd/layer/info/object_effects' require 'psd/layer/info/pattern' require 'psd/layer/info/pattern_fill' require 'psd/layer/info/photo_filter' require 'psd/layer/info/placed_layer' require 'psd/layer/info/posterize' require 'psd/layer/info/reference_point' require 'psd/layer/info/selective_color' require 'psd/layer/info/sheet_color' require 'psd/layer/info/solid_color' require 'psd/layer/info/threshold' require 'psd/layer/info/transparency_shapes_layer' require 'psd/layer/info/typetool' require 'psd/layer/info/unicode_name' require 'psd/layer/info/vector_mask' require 'psd/layer/info/vector_mask_as_global_mask' require 'psd/layer/info/vector_origination' require 'psd/layer/info/vector_stroke' require 'psd/layer/info/vector_stroke_content' require 'psd/layer/info/vibrance' class PSD class Layer module Info # All of the extra layer info sections that we know how to parse. LAYER_INFO = { black_white: BlackWhite, blend_clipping_elements: BlendClippingElements, blend_interior_elements: BlendInteriorElements, brightness_contrast: BrightnessContrast, channel_blending_restrictions: ChannelBlendingRestrictions, channel_mixer: ChannelMixer, color_balance: ColorBalance, color_lookup: ColorLookup, content_generator: ContentGenerator, curves: Curves, exposure: Exposure, fill_opacity: FillOpacity, gradient_fill: GradientFill, gradient_map: GradientMap, hue_saturation: HueSaturation, invert: Invert, knockout: Knockout, layer_mask_as_global_mask: LayerMaskAsGlobalMask, layer_id: LayerID, layer_name_source: LayerNameSource, legacy_type: LegacyTypeTool, levels: Levels, locked: Locked, metadata: MetadataSetting, name: UnicodeName, nested_section_divider: NestedLayerDivider, object_effects: ObjectEffects, pattern_fill: PatternFill, photo_filter: PhotoFilter, placed_layer: PlacedLayer, posterize: Posterize, reference_point: ReferencePoint, selective_color: SelectiveColor, section_divider: LayerSectionDivider, sheet_color: SheetColor, solid_color: SolidColor, threshold: Threshold, transparency_shapes_layer: TransparencyShapesLayer, type: TypeTool, vector_mask: VectorMask, vector_mask_as_global_mask: VectorMaskAsGlobalMask, vector_origination: VectorOrigination, vector_stroke: VectorStroke, vector_stroke_content: VectorStrokeContent, vibrance: Vibrance }.freeze BIG_LAYER_INFO_KEYS = %w{ LMsk Lr16 Lr32 Layr Mt16 Mt32 Mtrn Alph FMsk lnk2 FEid FXid PxSD } attr_reader :adjustments alias :info :adjustments LAYER_INFO.keys.each do |key| define_method(key) { @adjustments[key] } end private def parse_additional_layer_info_length(key) if @header.big? && BIG_LAYER_INFO_KEYS.include?(key) Util.pad2 @file.read_longlong else Util.pad2 @file.read_int end end # This section is a bit tricky to parse because it represents all of the # extra data that describes this layer. def parse_layer_info @extra_data_begin = @file.tell while @file.tell < @layer_end # Signature, don't need @file.seek 4, IO::SEEK_CUR # Key, very important key = @file.read_string(4) @info_keys << key length = parse_additional_layer_info_length(key) pos = @file.tell key_parseable = false LAYER_INFO.each do |name, info| next unless info.should_parse?(key) PSD.logger.debug "Layer Info: key = #{key}, start = #{pos}, length = #{length}" i = info.new(self, length) @adjustments[name] = LazyExecute.new(i, @file).now(:skip).later(:parse) key_parseable = true and break end unless key_parseable PSD.logger.debug "Skipping unknown layer info block: key = #{key}, length = #{length}" @file.seek length, IO::SEEK_CUR end end @extra_data_end = @file.tell end end end end