lib/origami/page.rb in origami-1.2.5 vs lib/origami/page.rb in origami-1.2.6

- old
+ new

@@ -25,10 +25,13 @@ module Origami class PDF + # + # Appends a page or list of pages to the end of the page tree. + # def append_page(page = Page.new, *more) raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) pages = [ page ].concat(more).map! do |pg| if pg.pdf and pg.pdf != self @@ -50,10 +53,13 @@ end self end + # + # Inserts a page at position _index_ into the document. + # def insert_page(index, page) raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) # Page from another document must be exported. page = page.export if page.pdf and page.pdf != self @@ -106,99 +112,138 @@ end module ResourcesHolder - def add_extgstate(name, extgstate) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - - target.ExtGState ||= {} - target.ExtGState[name] = extgstate - - self + def add_extgstate(extgstate, name = nil) + add_resource(Resources::EXTGSTATE, extgstate, name) end - def add_colorspace(name, colorspace) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - - csdir = target[:ColorSpace] ||= {} - (csdir.is_a?(Reference) ? csdir.solve : csdir)[name] = colorspace + def add_colorspace(colorspace, name = nil) + add_resource(Resources::COLORSPACE, colorspace, name) + end - self + def add_pattern(pattern, name = nil) + add_resource(Resources::PATTERN, pattern, name) end - def add_pattern(name, pattern) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) + def add_shading(shading, name = nil) + add_resource(Resources::SHADING, shading, name) + end - target.Pattern ||= {} - target.Pattern[name] = pattern - - self + def add_xobject(xobject, name = nil) + add_resource(Resources::XOBJECT, xobject, name) end - def add_shading(name, shading) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) + def add_font(font, name = nil) + add_resource(Resources::FONT, font, name) + end - target.Shading ||= {} - target.Shading[name] = shading - - self + def add_properties(properties, name = nil) + add_resource(Resources::PROPERTIES, properties, name) end - def add_xobject(name, xobject) + def add_resource(type, rsrc, name = nil) + return existing if not name and existing = ls_resources(type).key(rsrc) + + name = new_id(type) unless name target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - target.XObject ||= {} - target.XObject[name] = xobject - - self + rsrc_dict = target.send(type) || (target[type] = Dictionary.new) + rsrc_dict[name] = rsrc + + name end - - def add_font(name, font) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - target.Font ||= {} - target.Font[name] = font + def ls_resources(type) + target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - self + rsrc = {} + (target.send(type) || {}).each_pair do |name, obj| + rsrc[name.value] = obj.solve + end + + rsrc end - def add_properties(name, properties) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) + def extgstates; ls_resources(Resources::EXTGSTATE) end + def colorspaces; ls_resources(Resources::COLORSPACE) end + def patterns; ls_resources(Resources::PATTERN) end + def shadings; ls_resources(Resources::SHADING) end + def xobjects; ls_resources(Resources::XOBJECT) end + def fonts; ls_resources(Resources::FONT) end + def properties; ls_resources(Resources::PROPERTIES) end + def resources; + self.extgstates. + merge self.colorspaces. + merge self.patterns. + merge self.shadings. + merge self.xobjects. + merge self.fonts. + merge self.properties + end - target.Properties ||= {} - target.Properties[name] = properties - - self + private + + def new_id(type, prefix = nil) #:nodoc: + prefix ||= + { + Resources::EXTGSTATE => 'ExtG', + Resources::COLORSPACE => 'CS', + Resources::PATTERN => 'P', + Resources::SHADING => 'Sh', + Resources::XOBJECT => 'Im', + Resources::FONT => 'F', + Resources::PROPERTIES => 'Pr' + }[type] + + rsrc = ls_resources(type) + n = '1' + + while rsrc.include? (prefix + n).to_sym + n.next! + end + + (prefix + n).to_sym end - + + def new_extgstate_id; new_id(Resources::EXTGSTATE) end + def new_colorspace_id; new_id(Resources::COLORSPACE) end + def new_pattern_id; new_id(Resources::PATTERN) end + def new_shading_id; new_id(Resources::SHADING) end + def new_xobject_id; new_id(Resources::XOBJECT) end + def new_font_id; new_name(Resources::FONT) end + def new_properties_id; new_name(Resources::PROPERTIES) end end # # Class representing a Resources Dictionary for a Page. # class Resources < Dictionary include StandardObject include ResourcesHolder - field :ExtGState, :Type => Dictionary - field :ColorSpace, :Type => Dictionary - field :Pattern, :Type => Dictionary - field :Shading, :Type => Dictionary, :Version => "1.3" - field :XObject, :Type => Dictionary - field :Font, :Type => Dictionary + EXTGSTATE = :ExtGState + COLORSPACE = :ColorSpace + PATTERN = :Pattern + SHADING = :Shading + XOBJECT = :XObject + FONT = :Font + PROPERTIES = :Properties + + field EXTGSTATE, :Type => Dictionary + field COLORSPACE, :Type => Dictionary + field PATTERN, :Type => Dictionary + field SHADING, :Type => Dictionary, :Version => "1.3" + field XOBJECT, :Type => Dictionary + field FONT, :Type => Dictionary field :ProcSet, :Type => Array - field :Properties, :Type => Dictionary, :Version => "1.2" + field PROPERTIES, :Type => Dictionary, :Version => "1.2" def pre_build - unless self.Font - fnt = Font::Type1::Standard::Helvetica.new.pre_build - fnt.Name = :F1 - - add_font(fnt.Name, fnt) - end + add_font(Font::Type1::Standard::Helvetica.new.pre_build) unless self.Font super end end @@ -345,30 +390,59 @@ pageset.each do |node| node.Parent = self end end end + + # Forward declaration. + class ContentStream < Stream; end # # Class representing a Page in the PDF document. # class Page < Dictionary include StandardObject include ResourcesHolder + + module Format + A0 = Rectangle[:width => 2384, :height => 3370] + A1 = Rectangle[:width => 1684, :height => 2384] + A2 = Rectangle[:width => 1191, :height => 1684] + A3 = Rectangle[:width => 842, :height => 1191] + A4 = Rectangle[:width => 595, :height => 842] + A5 = Rectangle[:width => 420, :height => 595] + A6 = Rectangle[:width => 298, :height => 420] + A7 = Rectangle[:width => 210, :height => 298] + A8 = Rectangle[:width => 147, :height => 210] + A9 = Rectangle[:width => 105, :height => 147] + A10 = Rectangle[:width => 74, :height => 105] + + B0 = Rectangle[:width => 2836, :height => 4008] + B1 = Rectangle[:width => 2004, :height => 2835] + B2 = Rectangle[:width => 1417, :height => 2004] + B3 = Rectangle[:width => 1001, :height => 1417] + B4 = Rectangle[:width => 709, :height => 1001] + B5 = Rectangle[:width => 499, :height => 709] + B6 = Rectangle[:width => 354, :height => 499] + B7 = Rectangle[:width => 249, :height => 354] + B8 = Rectangle[:width => 176, :height => 249] + B9 = Rectangle[:width => 125, :height => 176] + B10 = Rectangle[:width => 88, :height => 125] + end field :Type, :Type => Name, :Default => :Page, :Required => true field :Parent, :Type => Dictionary, :Required => true field :LastModified, :Type => String, :Version => "1.3" - field :Resources, :Type => Dictionary, :Required => true - field :MediaBox, :Type => Array, :Default => Rectangle[ :llx => 0, :lly => 0, :urx => 795, :ury => 842 ], :Required => true + field :Resources, :Type => Resources, :Required => true + field :MediaBox, :Type => Array, :Default => Format::A4, :Required => true field :CropBox, :Type => Array field :BleedBox, :Type => Array, :Version => "1.3" field :TrimBox, :Type => Array, :Version => "1.3" field :ArtBox, :Type => Array, :Version => "1.3" field :BoxColorInfo, :Type => Dictionary, :Version => "1.4" - field :Contents, :Type => [ Stream, Array ] + field :Contents, :Type => [ ContentStream, Array ] field :Rotate, :Type => Integer, :Default => 0 field :Group, :Type => Dictionary, :Version => "1.4" field :Thumb, :Type => Stream field :B, :Type => Array, :Version => "1.1" field :Dur, :Type => Integer, :Version => "1.1" @@ -391,21 +465,10 @@ super(hash) set_indirect(true) end - def render(engine) #:nodoc: - contents = self.Contents - return unless contents.is_a? Stream - - unless contents.is_a? ContentStream - contents = ContentStream.new(contents.data) - end - - contents.render(engine) - end - def pre_build self.Resources = Resources.new.pre_build unless self.has_key?(:Resources) super end @@ -592,5 +655,6 @@ field :Prev, :Type => Dictionary field :Dur, :Type => Number end end +