Commit 2d197802 authored by Cédric Boutillier's avatar Cédric Boutillier

Imported Upstream version 2.0.2+dfsg

parent feceeb24
......@@ -7,98 +7,100 @@ Encoding:
- lib/prawn/images.rb
- spec/png_spec.rb
Void:
# These cops need to remain disabled for valid reasons on this code base
# We need to reference non-ascii characters when testing and explaining
# behavior related to win-1252, UTF-8 and UTF-16 encodings for example.
AsciiComments:
Enabled: false
StringLiterals:
# We don't always prefer modified if statements even if they do fit on
# a line.
IfUnlessModifier:
Enabled: false
SpaceAroundOperators:
# In this case we supress Prawn::Errors::CannotFit while trying to scale
# text down to fit.
HandleExceptions:
Exclude:
- lib/prawn/text/formatted/box.rb
# %w() style arrays don't always look better.
WordArray:
Enabled: false
HashSyntax:
# Due to some layout constraints in our examples we want to allow these rule to
# be ignored in the manual.
Style/ClosingParenthesisIndentation:
Exclude:
- manual/**/*
LineEndConcatenation:
Exclude:
- manual/**/*
MultilineOperationIndentation:
Exclude:
- manual/**/*
- prawn.gemspec
Style/SpaceInsideParens:
Exclude:
- manual/**/*
SingleSpaceBeforeFirstArg:
Exclude:
- manual/**/*
# This file shows examples on how to instantiate a document in multiple ways,
# it does not actually do the instantiation and isn't actually shadowing any
# variables.
ShadowingOuterLocalVariable:
Exclude:
- manual/basic_concepts/creation.rb
# We currently ignore usage of semicolons on this page of the manual so we
# don't have to worry about changing the content of the manual for now.
Semicolon:
Exclude:
- manual/bounding_box/nesting.rb
# This cops are candidates for enabling and doing the related cleanup and/or
# refactoring
Style/BlockDelimiters:
Enabled: false
UselessAssignment:
EnforcedStyle: semantic
Void:
Enabled: false
EmptyLines:
StringLiterals:
Enabled: false
LineEndConcatenation:
HashSyntax:
Enabled: false
SpaceAfterComma:
UselessAssignment:
Enabled: false
Lambda:
Enabled: false
AlignHash:
Enabled: false
LineLength:
Enabled: false
SpaceBeforeBlockBraces:
Enabled: false
AlignParameters:
Enabled: false
SpaceInsideBrackets:
Enabled: false
WordArray:
Enabled: false
SpaceAroundEqualsInParameterDefault:
Enabled: false
MethodCallParentheses:
Enabled: false
FormatString:
Enabled: false
Blocks:
Enabled: false
SpaceInsideBlockBraces:
Enabled: false
CollectionMethods:
Enabled: false
SpaceInsideHashLiteralBraces:
Enabled: false
DotPosition:
Enabled: false
SingleLineBlockParams:
Enabled: false
PercentLiteralDelimiters:
Enabled: false
SpaceInsideParens:
Enabled: false
IfUnlessModifier:
Enabled: false
NilComparison:
Enabled: false
Semicolon:
Enabled: false
LeadingCommentSpace:
Enabled: false
Documentation:
Enabled: false
AlignArray:
Enabled: false
BlockAlignment:
Enabled: false
IndentArray:
Enabled: false
BracesAroundHashParameters:
Enabled: false
TrailingComma:
Enabled: false
IndentHash:
Enabled: false
RegexpLiteral:
Enabled: false
MethodLength:
Enabled: false
IndentationWidth:
Enabled: false
VariableInterpolation:
Enabled: false
EvenOdd:
Enabled: false
AmbiguousOperator:
Enabled: false
SingleSpaceBeforeFirstArg:
Enabled: false
IndentationConsistency:
Enabled: false
TrailingBlankLines:
Enabled: false
AndOr:
Enabled: false
AssignmentInCondition:
......@@ -107,30 +109,14 @@ ClassAndModuleChildren:
Enabled: false
NumericLiterals:
Enabled: false
AsciiComments:
Enabled: false
SignalException:
Enabled: false
HandleExceptions:
Enabled: false
DoubleNegation:
Enabled: false
SelfAssignment:
Enabled: false
Eval:
Enabled: false
ClassLength:
Enabled: false
ShadowingOuterLocalVariable:
Enabled: false
TrivialAccessors:
Enabled: false
AccessModifierIndentation:
Enabled: false
CaseEquality:
Enabled: false
EmptyLineBetweenDefs:
Enabled: false
RedundantSelf:
Enabled: false
BlockNesting:
......@@ -143,87 +129,51 @@ ModuleFunction:
Enabled: false
CyclomaticComplexity:
Enabled: false
CaseIndentation:
Enabled: false
UnreachableCode:
Enabled: false
MultilineTernaryOperator:
Enabled: false
AccessorMethodName:
Enabled: false
SpaceAfterControlKeyword:
Enabled: false
UselessAccessModifier:
Enabled: false
PredicateName:
Enabled: false
ConstantName:
Enabled: false
UnlessElse:
Enabled: false
MethodName:
Enabled: false
Alias:
Enabled: false
RedundantReturn:
Enabled: false
EmptyLinesAroundAccessModifier:
Enabled: false
DeprecatedHashMethods:
Enabled: false
WhileUntilModifier:
Enabled: false
StringConversionInInterpolation:
Enabled: false
EndAlignment:
Enabled: false
RedundantBegin:
Enabled: false
PerlBackrefs:
Enabled: false
CharacterLiteral:
Enabled: false
ClassVars:
Enabled: false
ParameterLists:
Enabled: false
BlockComments:
Enabled: false
MultilineOperationIndentation:
Enabled: false
SpaceBeforeComment:
Enabled: false
AbcSize:
Enabled: false
EmptyLinesAroundClassBody:
Enabled: false
PerceivedComplexity:
Enabled: false
EmptyLinesAroundBlockBody:
Enabled: false
UnusedBlockArgument:
Enabled: false
UnusedMethodArgument:
Enabled: false
Next:
Enabled: false
SymbolProc:
Enabled: false
ClassCheck:
Enabled: false
SpaceBeforeComma:
Enabled: false
StringLiteralsInInterpolation:
Enabled: false
EmptyLinesAroundModuleBody:
Enabled: false
GuardClause:
Enabled: false
ElseAlignment:
Enabled: false
CommentIndentation:
Enabled: false
EachWithObject:
Enabled: false
BlockEndNewline:
Enabled: false
This diff is collapsed.
......@@ -2,11 +2,12 @@
[![Gem Version](https://badge.fury.io/rb/prawn.png)](http://badge.fury.io/rb/prawn)
[![Build Status](https://api.travis-ci.org/prawnpdf/prawn.svg?branch=master)](http://travis-ci.org/prawnpdf/prawn)
[![Code Climate](https://codeclimate.com/github/prawnpdf/prawn/badges/gpa.svg)](https://codeclimate.com/github/prawnpdf/prawn)
Prawn is a pure Ruby PDF generation library that provides a lot of great functionality while trying to remain simple and reasonably performant. Here are some of the important features we provide:
* Vector drawing support, including lines, polygons, curves, ellipses, etc.
* Extensive text rendering support, including flowing text and limited inline formatting options.
* Extensive text rendering support, including flowing text and limited inline formatting options.
* Support for both PDF builtin fonts as well as embedded TrueType fonts
* A variety of low level tools for basic layout needs, including a simple grid system
* PNG and JPG image embedding, with flexible scaling options
......@@ -26,9 +27,9 @@ One thing Prawn is not, and will never be, is an HTML to PDF generator. For thos
## Supported Ruby Versions and Implementations
Because Prawn is pure Ruby and all of its runtime dependencies are maintained
by us, it should work pretty much anywhere. We officially support
MRI {2.0.0, 2.1.x, 2.2.x} and jruby 1.7.x (>= 1.7.18) in 2.0 mode, however
we will accept patches to fix problems on other
by us, it should work pretty much anywhere. We officially support
MRI {2.0.0, 2.1.x, 2.2.x} and jruby 1.7.x (>= 1.7.18) in 2.0 mode, however
we will accept patches to fix problems on other
Ruby platforms if they aren't too invasive.
## Installing Prawn
......@@ -70,10 +71,14 @@ compatibility](https://github.com/prawnpdf/prawn/wiki/API-Compatibility-Notes)
guidelines. Generally speaking, you can expect tiny and minor version updates to always be
safe upgrades, but major updates can introduce incompatibilities.
Be sure to read the release notes in CHANGELOG.md each time we cut a
new release, and lock your gems accordingly.
Be sure to read the release notes in [CHANGELOG.md](https://github.com/prawnpdf/prawn/blob/master/CHANGELOG.md)
each time we cut a new release, and lock your gems accordingly.
## Support
The prawn team will release a new version of prawn every 6 weeks containing any
new features and bug fixes that have been completed during the previous release
cycle. We may release additional versions off cycle to fix major breakages.
## Support
The easiest way to get help with Prawn is to post a message to our mailing list:
......@@ -113,14 +118,13 @@ developers and contributors.
That said, there are a few folks who have been responsible for cutting releases,
merging important pull requests, and making major decisions about the
overall direction of the project.
overall direction of the project.
### Current maintainers
These are the folks to contact if you have a maintenance-related issue with
Prawn:
* Gregory Brown (practicingruby)
* Evan Sharp (PacketMonkey)
* Alexander Mankuta (cheba)
......@@ -129,6 +133,7 @@ Prawn:
These folks have helped out in a maintenance role in the past, but are no longer
actively involved in the project:
* Gregory Brown (practicingruby)
* Brad Ediger (bradediger)
* James Healy (yob)
* Daniel Nelson (Bluejade)
......@@ -149,13 +154,8 @@ collectively provided funding so that Gregory could take several months off from
work to focus on this project.
Over the last several years, we've received code contributions from dozens of
people, which is amazing considering the low-level nature of this project. You can find the full list of folks
people, which is amazing considering the low-level nature of this project. You can find the full list of folks
who have at least one patch accepted to Prawn on github at https://github.com/prawnpdf/prawn/contributors
After a long hiatus, Gregory resumed slow-by-steady maintenance work on Prawn
starting in November 2013. This was made possible thanks to some modest
funding from Madriska, Inc. (Brad Ediger's company) to see the project
through to its 1.0 release.
The fate of Prawn after 1.0 is uncertain, it's not a very easy project
to maintain. That said, we hope it keeps moving along!
After a long period of inactivity, Prawn reached its 1.0 milestone in 2014 thanks to some modest
funding provided to Gregory by Madriska, Inc. (Brad Ediger's company).
......@@ -17,8 +17,12 @@ end
desc "Show library's code statistics"
task :stats do
require 'code_statistics/code_statistics'
puts CodeStatistics::CodeStatistics.new( [["Prawn", "lib"],
["Specs", "spec"]] ).to_s
puts CodeStatistics::CodeStatistics.new(
[
["Prawn", "lib"],
["Specs", "spec"]
]
).to_s
end
YARD::Rake::YardocTask.new do |t|
......@@ -26,12 +30,10 @@ YARD::Rake::YardocTask.new do |t|
end
task :docs => :yard
desc "Generate the 'Prawn by Example' manual"
task :manual do
puts "Building manual..."
require File.expand_path(File.join(File.dirname(__FILE__),
%w[manual contents]))
require File.expand_path(File.join(File.dirname(__FILE__), %w[manual contents]))
puts "The Prawn manual is available at manual.pdf. Happy Prawning!"
end
......
......@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require "prawn"
require "benchmark"
N=2000
N = 2000
Benchmark.bmbm do |x|
x.report("AFM text") do
......
......@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require "prawn"
require "benchmark"
N=100
N = 100
Benchmark.bmbm do |x|
x.report("PNG Type 6") do
......
......@@ -15,4 +15,3 @@ after = GC.stat
total = after[:total_allocated_object] - before[:total_allocated_object]
puts "allocated objects: #{total}"
......@@ -13,28 +13,28 @@ class String
end
end
def data_for_table(columns,rows,string_size)
rows.times.collect { columns.times.collect { String.random(string_size) }}
def data_for_table(columns, rows, string_size)
rows.times.collect { columns.times.collect { String.random(string_size) } }
end
def benchmark_table_generation(columns,rows,string_size,options={})
data = data_for_table(columns,rows,string_size)
def benchmark_table_generation(columns, rows, string_size, options = {})
data = data_for_table(columns, rows, string_size)
Benchmark.bm do |x|
x.report("#{columns}x#{rows} table (#{columns*rows} cells, with #{string_size} char string contents#{", options = #{options.inspect}" unless options.empty?})") do
Prawn::Document.new { table(data,options) }.render
x.report("#{columns}x#{rows} table (#{columns * rows} cells, with #{string_size} char string contents#{", options = #{options.inspect}" unless options.empty?})") do
Prawn::Document.new { table(data, options) }.render
end
end
end
# Slowest case: styled table, which is very squeezed horizontally,
# so text has to be wrapped
benchmark_table_generation(26,50,10, :row_colors => ['FFFFFF','F0F0FF'], :header => true, :cell_style => {:inline_format=>true})
benchmark_table_generation(26, 50, 10, :row_colors => ['FFFFFF', 'F0F0FF'], :header => true, :cell_style => { :inline_format => true })
# Try building and rendering tables of different sizes
benchmark_table_generation(10,400,5)
benchmark_table_generation(10,200,5)
benchmark_table_generation(10,100,5)
benchmark_table_generation(10, 400, 5)
benchmark_table_generation(10, 200, 5)
benchmark_table_generation(10, 100, 5)
# Try different optional arguments to Prawn::Document#table
benchmark_table_generation(10,450,5, :cell_style => {:inline_format=>true})
benchmark_table_generation(10,450,5, :row_colors => ['FFFFFF','F0F0FF'], :header => true, :cell_style => {:inline_format=>true})
benchmark_table_generation(10, 450, 5, :cell_style => { :inline_format => true })
benchmark_table_generation(10, 450, 5, :row_colors => ['FFFFFF', 'F0F0FF'], :header => true, :cell_style => { :inline_format => true })
......@@ -4,18 +4,18 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require "prawn"
require "benchmark"
N=2000
N = 2000
Benchmark.bmbm do |x|
x.report("TTF text") do
Prawn::Document.new {
font "#{Prawn::DATADIR}/fonts/DejaVuSans.ttf"
N.times do
(1..5).each do |i|
draw_text "Hello Prawn", :at => [200, i * 100]
end
start_new_page
end
font "#{Prawn::DATADIR}/fonts/DejaVuSans.ttf"
N.times do
(1..5).each do |i|
draw_text "Hello Prawn", :at => [200, i * 100]
end
start_new_page
end
}.render
end
end
......@@ -36,10 +36,10 @@ module Prawn
def verify_options(accepted, actual) # @private
return unless debug || $DEBUG
unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
raise Prawn::Errors::UnknownOption,
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
"Accepted options are: #{accepted.inspect}"
unless (act = Set[*actual.keys]).subset?(acc = Set[*accepted])
fail Prawn::Errors::UnknownOption,
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" \
"Accepted options are: #{accepted.inspect}"
end
yield if block_given?
end
......
......@@ -14,7 +14,6 @@ require_relative "document/internals"
require_relative "document/span"
module Prawn
# The Prawn::Document class is how you start creating a PDF document.
#
# There are three basic ways you can instantiate PDF Documents in Prawn, they
......@@ -102,7 +101,7 @@ module Prawn
# @group Stable Attributes
attr_accessor :margin_box
attr_reader :margins, :y
attr_reader :margins, :y
attr_accessor :page_number
# @group Extension Attributes
......@@ -138,8 +137,8 @@ module Prawn
# pdf.draw_text content, :at => [200,720], :size => 32
# end
#
def self.generate(filename,options={},&block)
pdf = new(options,&block)
def self.generate(filename, options = {}, &block)
pdf = new(options, &block)
pdf.render_file(filename)
end
......@@ -189,7 +188,7 @@ module Prawn
# # New document, with background
# pdf = Prawn::Document.new(:background => "#{Prawn::DATADIR}/images/pigs.jpg")
#
def initialize(options={},&block)
def initialize(options = {}, &block)
options = options.dup
Prawn.verify_options VALID_OPTIONS, options
......@@ -198,8 +197,8 @@ module Prawn
# raise NotImplementedError if options[:skip_page_creation]
self.class.extensions.reverse_each { |e| extend e }
@internal_state = PDF::Core::DocumentState.new(options)
@internal_state.populate_pages_from_store(self)
self.state = PDF::Core::DocumentState.new(options)
self.state.populate_pages_from_store(self)
renderer.min_version(state.store.min_version) if state.store.min_version
renderer.min_version(1.6) if options[:print_scaling] == :none
......@@ -246,13 +245,17 @@ module Prawn
last_page_margins = last_page.margins.dup
end
page_options = {:size => options[:size] || last_page_size,
:layout => options[:layout] || last_page_layout,
:margins => last_page_margins}
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
# 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
......@@ -300,7 +303,7 @@ module Prawn
#
def go_to_page(k)
@page_number = k
state.page = state.pages[k-1]
state.page = state.pages[k - 1]
generate_margin_box
@y = @bounding_box.absolute_top
end
......@@ -466,7 +469,6 @@ module Prawn
move_down(y)
end
# Indents the specified number of PDF points for the duration of the block
#
# pdf.text "some text"
......@@ -518,18 +520,20 @@ module Prawn
# :size => 14}
# end
#
def number_pages(string, options={})
def number_pages(string, options = {})
opts = options.dup
start_count_at = opts.delete(:start_count_at).to_i
page_filter = if opts.has_key?(:page_filter)
opts.delete(:page_filter)
if opts.key?(:page_filter)
page_filter = opts.delete(:page_filter)
else
:all
page_filter = :all
end
total_pages = opts.delete(:total_pages)
txtcolor = opts.delete(:color)
# An explicit height so that we can draw page numbers in the margins
opts[:height] = 50 unless opts.has_key?(:height)
opts[:height] = 50 unless opts.key?(:height)
start_count = false
pseudopage = 0
......@@ -547,7 +551,7 @@ module Prawn
# have to use fill_color here otherwise text reverts back to default fill color
fill_color txtcolor unless txtcolor.nil?
total_pages = total_pages.nil? ? page_count : total_pages
str = string.gsub("<page>","#{pseudopage}").gsub("<total>","#{total_pages}")
str = string.gsub("<page>", "#{pseudopage}").gsub("<total>", "#{total_pages}")
text_box str, opts
start_count = true # increment page count as soon as first match found
end
......@@ -568,20 +572,20 @@ module Prawn
#
# @private
def group(*a, &b)
raise NotImplementedError,
"Document#group has been disabled because its implementation "+
"lead to corrupted documents whenever a page boundary was "+
"crossed. We will try to work on reimplementing it in a "+
"future release"
fail NotImplementedError,
"Document#group has been disabled because its implementation " \
"lead to corrupted documents whenever a page boundary was " \
"crossed. We will try to work on reimplementing it in a " \
"future release"
end
# @private
def transaction
raise NotImplementedError,
"Document#transaction has been disabled because its implementation "+
"lead to corrupted documents whenever a page boundary was "+
"crossed. We will try to work on reimplementing it in a "+
"future release"
fail NotImplementedError,
"Document#transaction has been disabled because its implementation " \
"lead to corrupted documents whenever a page boundary was " \
"crossed. We will try to work on reimplementing it in a " \
"future release"
end
# Provides a way to execute a block of code repeatedly based on a
......@@ -599,9 +603,9 @@ module Prawn
when :all
true
when :odd
page_number % 2 == 1
page_number.odd?
when :even
page_number % 2 == 0
page_number.even?
when Range, Array
page_filter.include?(page_number)
when Proc
......@@ -612,9 +616,9 @@ module Prawn
# @private
def mask(*fields)
# Stores the current state of the named attributes, executes the block, and
# then restores the original values after the block has executed.
# -- I will remove the nodoc if/when this feature is a little less hacky
# Stores the current state of the named attributes, executes the block, and
# then restores the original values after the block has executed.
# -- I will remove the nodoc if/when this feature is a little less hacky
stored = {}
fields.each { |f| stored[f] = send(f) }
yield
......@@ -634,9 +638,7 @@ module Prawn
## Internals. Don't depend on them!
# @private
def state
@internal_state
end
attr_accessor :state
# @private
def page
......@@ -645,7 +647,6 @@ module Prawn
private
# setting override_settings to true ensures that a new graphic state does not end up using
# previous settings.
def use_graphic_settings(override_settings = false)
......@@ -684,23 +685,23 @@ module Prawn
if options[:margin]
# Treat :margin as CSS shorthand with 1-4 values.
margin = Array(options[:margin])
positions = { 4 => [0,1,2,3], 3 => [0,1,2,1],
2 => [0,1,0,1], 1 => [0,0,0,0] }[margin.length]