Skip to content

Commit

Permalink
Transitional extraction of templates
Browse files Browse the repository at this point in the history
This commit is a squashed subset of #640, which begins the
process of extracting templates out of Prawn::Document and
into an extension. It's not complete, but it's functional
enough where I'd like to include it in release for
user testing. It accomplishes two main goals:

* Disables templates by default in Prawn

* Allows those who will use the future prawn-templates gem
to try it out as an extension by requiring "prawn/templates"

The way I extracted the code is not meant to be a permanent
solution. We will need to move away from a module-based monkey
patch to some sort of object-oriented solution, and we should
aim to cut down the duplication of code in the templates
extension. But this is something we can do later.

We also need to finish extracting the lower-level features
that templates depend upon, but that too can be done in
a future release. This patch is primarily about removing
the top-level use of the feature so that we can be sure
we didn't break anything critical in the process of doing so.
  • Loading branch information
practicingruby committed Jan 15, 2014
1 parent 92ad816 commit d426e12
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 137 deletions.
55 changes: 20 additions & 35 deletions lib/prawn/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ class Document
include Prawn::Stamp
include Prawn::SoftMask

# NOTE: We probably need to rethink the options validation system, but this
# constant temporarily allows for extensions to modify the list.

VALID_OPTIONS = [:page_size, :page_layout, :margin, :left_margin,
:right_margin, :top_margin, :bottom_margin, :skip_page_creation,
:compress, :skip_encoding, :background, :info,
:optimize_objects, :text_formatter, :print_scaling]

# Any module added to this array will be included into instances of
# Prawn::Document at the per-object level. These will also be inherited by
# any subclasses.
Expand Down Expand Up @@ -138,7 +146,6 @@ def self.generate(filename,options={},&block)
# <tt>:background</tt>:: An image path to be used as background on all pages [nil]
# <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
# <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
# <tt>:template</tt>:: The path to an existing PDF file to use as a template [nil]
# <tt>:text_formatter</tt>: The text formatter to use for <tt>:inline_format</tt>ted text [Prawn::Text::Formatted::Parser]
#
# Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
Expand Down Expand Up @@ -173,12 +180,7 @@ def self.generate(filename,options={},&block)
def initialize(options={},&block)
options = options.dup

Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
:right_margin, :top_margin, :bottom_margin, :skip_page_creation,
:compress, :skip_encoding, :background, :info,
:optimize_objects, :template, :text_formatter, :print_scaling], options


Prawn.verify_options VALID_OPTIONS, options

# need to fix, as the refactoring breaks this
# raise NotImplementedError if options[:skip_page_creation]
Expand All @@ -204,16 +206,7 @@ def initialize(options={},&block)
options[:size] = options.delete(:page_size)
options[:layout] = options.delete(:page_layout)

if options[:template]
fresh_content_streams(options)
go_to_page(1)
else
if options[:skip_page_creation] || options[:template]
start_new_page(options.merge(:orphan => true))
else
start_new_page(options)
end
end
initialize_first_page(options)

@bounding_box = @margin_box

Expand All @@ -236,6 +229,14 @@ def page
state.page
end

def initialize_first_page(options)
if options[:skip_page_creation]
start_new_page(options.merge(:orphan => true))
else
start_new_page(options)
end
end

# Creates and advances to a new page in the document.
#
# Page size, margins, and layout can also be set when generating a
Expand All @@ -246,14 +247,6 @@ def page
# pdf.start_new_page(:left_margin => 50, :right_margin => 50)
# pdf.start_new_page(:margin => 100)
#
# A template for a page can be specified by pointing to the path of and existing pdf.
# One can also specify which page of the template which defaults otherwise to 1.
#
# pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
#
# Note: templates get indexed by either the object_id of the filename or stream
# entered so that if you reuse the same template multiple times be sure to use the
# same instance for more efficient use of resources and smaller rendered pdfs.
def start_new_page(options = {})
if last_page = state.page
last_page_size = last_page.size
Expand All @@ -270,7 +263,6 @@ def start_new_page(options = {})
new_graphic_state.color_space = {} if new_graphic_state
page_options.merge!(:graphic_state => new_graphic_state)
end
merge_template_options(page_options, options) if options[:template]

state.page = PDF::Core::Page.new(self, page_options)

Expand All @@ -283,9 +275,7 @@ def start_new_page(options = {})
@bounding_box = @margin_box
end

state.page.new_content_stream if options[:template]
use_graphic_settings(options[:template])
forget_text_rendering_mode! if options[:template]
use_graphic_settings

unless options[:orphan]
state.insert_page(state.page, @page_number)
Expand Down Expand Up @@ -655,13 +645,8 @@ def compression_enabled?

private

def merge_template_options(page_options, options)
object_id = state.store.import_page(options[:template], options[:template_page] || 1)
page_options.merge!(:object_id => object_id, :page_template => true)
end

# setting override_settings to true ensures that a new graphic state does not end up using
# previous settings especially from imported template streams
# previous settings.
def use_graphic_settings(override_settings = false)
set_fill_color if current_fill_color != "000000" || override_settings
set_stroke_color if current_stroke_color != "000000" || override_settings
Expand Down
75 changes: 75 additions & 0 deletions lib/prawn/templates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
warn "Templates are no longer supported in Prawn!\n" +
"This code is for experimental testing only, and\n" +
"will extracted into its own gem in a future Prawn release"

module Prawn
module Templates
def initialize_first_page(options)
return super unless options[:template]

fresh_content_streams(options)
go_to_page(1)
end

## FIXME: This is going to be terribly brittle because
# it copy-pastes the start_new_page method. But at least
# it should only run when templates are used.

def start_new_page(options = {})
return super unless options[:template]

if last_page = state.page
last_page_size = last_page.size
last_page_layout = last_page.layout
last_page_margins = last_page.margins
end

page_options = {:size => options[:size] || last_page_size,
:layout => options[:layout] || last_page_layout,
:margins => last_page_margins}
if last_page
new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
#erase the color space so that it gets reset on new page for fussy pdf-readers
new_graphic_state.color_space = {} if new_graphic_state
page_options.merge!(:graphic_state => new_graphic_state)
end

merge_template_options(page_options, options)

state.page = PDF::Core::Page.new(self, page_options)

apply_margin_options(options)
generate_margin_box

# Reset the bounding box if the new page has different size or layout
if last_page && (last_page.size != state.page.size ||
last_page.layout != state.page.layout)
@bounding_box = @margin_box
end

state.page.new_content_stream
use_graphic_settings(true)
forget_text_rendering_mode!

unless options[:orphan]
state.insert_page(state.page, @page_number)
@page_number += 1

canvas { image(@background, :scale => @background_scale, :at => bounds.top_left) } if @background
@y = @bounding_box.absolute_top

float do
state.on_page_create_action(self)
end
end
end

def merge_template_options(page_options, options)
object_id = state.store.import_page(options[:template], options[:template_page] || 1)
page_options.merge!(:object_id => object_id, :page_template => true)
end
end
end

Prawn::Document::VALID_OPTIONS << :template
Prawn::Document.extensions << Prawn::Templates
1 change: 0 additions & 1 deletion manual/manual/manual.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,5 @@
load_package "document_and_page_options"
load_package "outline"
load_package "repeatable_content"
load_package "templates"
load_package "security"
end
25 changes: 0 additions & 25 deletions manual/templates/full_template.rb

This file was deleted.

48 changes: 0 additions & 48 deletions manual/templates/page_template.rb

This file was deleted.

27 changes: 0 additions & 27 deletions manual/templates/templates.rb

This file was deleted.

3 changes: 2 additions & 1 deletion spec/template_spec.rb → spec/template_spec_obsolete.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
require_relative "spec_helper"
require_relative "../lib/prawn/templates"

describe "Document built from a template" do
it "should have the same page count as the source document" do
Expand Down

0 comments on commit d426e12

Please sign in to comment.