Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Ruby 2.0 compatibility #3

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
= PDF::Writer Change Log

== PDF::Writer 1.3.0: August 16, 2013
* Ruby 2.0 compatibility.
o ImageInfo fixes encoding issue
o Writer fixes enumeration of String
o Fixed computation of font-width calculations

== PDF::Writer 1.2.1: May 13, 2009
* Ruby 1.9 compatibility.

Expand Down
8 changes: 8 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ This software is based on Adobe's PDF Reference, Fifth Edition, version 1.6.
This and earlier editions are available from Adobe's PDF developer
website[http://partners.adobe.com/public/developer/pdf/index_reference.html].

== Ruby 2.0 Compatibility
This gem version has been updated to work with Ruby 2.0. This is a maintenance
effort only to support moving existing projects from Ruby 1.8 to 2.0. New project
development should use Prawn[1] over PDF-Writer as it is actively maintained and
is also the successor/rewrite of this library.

[1] http://prawn.majesticseacreature.com/

== LICENCE NOTES
Please read the file LICENCE for licensing restrictions on this library, as
well as important patent considerations.
Expand Down
42 changes: 27 additions & 15 deletions lib/pdf/writer.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#encoding: ISO-8859-1
#--
# PDF::Writer for Ruby.
# http://rubyforge.org/projects/ruby-pdf/
Expand All @@ -6,21 +7,20 @@
# Licensed under a MIT-style licence. See LICENCE in the main distribution
# for full licensing information.
#
# $Id$
# $Id: writer.rb 202 2008-03-16 23:30:11Z sandal $
#++
require 'thread'
require 'open-uri'

require 'transaction/simple'
require 'pdf/core_ext/mutex'
require 'color'

# A class to provide the core functionality to create a PDF document
# without any requirement for additional modules.
module PDF
class Writer
# The version of PDF::Writer.
VERSION = '1.2.0'
VERSION = '1.3.0'

# Escape the text so that it's safe for insertion into the PDF
# document.
Expand Down Expand Up @@ -710,14 +710,22 @@ def render(debug = false)

xref = []

content = "%PDF-#{@version}\n%\303\242\303\243\303\217\303\223\n"
content = "%PDF-#{@version}\n%âãÏÓ\n"
pos = content.size

objects.each do |oo|
cont = oo.to_s
content << cont
xref << pos
pos += cont.size
begin
cont = oo.to_s.force_encoding("ISO-8859-1")
content << cont
xref << pos
pos += cont.size
rescue
# puts '*' * 80
# puts cont.inspect
# puts cont.encoding.name
# puts '*' * 80
raise
end
end

# pos += 1 # Newline character before XREF
Expand All @@ -741,6 +749,10 @@ def render(debug = false)
end
alias :to_s :render

def render_to_file(filename)
IO.binwrite(filename, render)
end

# Loads the font metrics. This is now thread-safe.
def load_font_metrics(font)
metrics = PDF::Writer::FontMetrics.open(font)
Expand Down Expand Up @@ -1371,9 +1383,9 @@ def add_text(x, y, text, size = nil, angle = 0, word_space_adjust = 0)
end

select_font("Helvetica") if @fonts.empty?

text = text.to_s

# If there are any open callbacks, then they should be called, to show
# the start of the line
@callbacks.reverse_each do |ii|
Expand Down Expand Up @@ -1467,11 +1479,11 @@ def add_text(x, y, text, size = nil, angle = 0, word_space_adjust = 0)
end

def char_width(font, char)
if RUBY_VERSION >= '1.9'
char = char.bytes.to_a.first unless @fonts[font].c[char]
else
char = char[0] unless @fonts[font].c[char]
end
if RUBY_VERSION >= '1.9'
char = char.ord unless @fonts[font].c[char]
else
char = char[0] unless @fonts[font].c[char]
end

if @fonts[font].differences and @fonts[font].c[char].nil?
name = @fonts[font].differences[char] || 'M'
Expand Down
6 changes: 3 additions & 3 deletions lib/pdf/writer/fontmetrics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Licensed under a MIT-style licence. See LICENCE in the main distribution
# for full licensing information.
#
# $Id$
# $Id: fontmetrics.rb 168 2007-11-08 19:04:08Z sandal $
#++

class PDF::Writer::FontMetrics
Expand Down Expand Up @@ -78,7 +78,7 @@ def self.open(font_name)
font = PDF::Writer::FontMetrics.new

# An AFM file contains key names followed by valuees.
file.each_line do |line|
file.each do |line|
line.chomp!
line.strip!
key, *values = line.split
Expand Down Expand Up @@ -152,7 +152,7 @@ def self.open(font_name)
# C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;
bits = line.chomp.strip.split(/;/).collect { |r| r.strip }
dtmp = {}

bits.each do |bit|
b = bit.split
if b.size > 2
Expand Down
11 changes: 4 additions & 7 deletions lib/pdf/writer/graphics.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#encoding: ISO-8859-1
#--
# PDF::Writer for Ruby.
# http://rubyforge.org/projects/ruby-pdf/
Expand All @@ -6,7 +7,7 @@
# Licensed under a MIT-style licence. See LICENCE in the main distribution
# for full licensing information.
#
# $Id$
# $Id: graphics.rb 166 2007-11-08 18:22:05Z sandal $
#++
# Points for use in the drawing of polygons.
class PDF::Writer::PolygonPoint
Expand Down Expand Up @@ -543,11 +544,7 @@ def add_image_from_file(image, x, y, width = nil, height = nil, link = nil)
if image.respond_to?(:read)
data = image.read
else
if RUBY_VERSION >= '1.9'
open(image,'rb:binary') { |ff| data = ff.read }
else
open(image,'rb') { |ff| data = ff.read }
end
open(image, 'r:ISO-8859-1:ISO-8859-1') { |ff| data = ff.read }
end

add_image(data, x, y, width, height, nil, link)
Expand Down Expand Up @@ -664,7 +661,7 @@ def image(image, options = {})
if image.respond_to?(:read)
image_data = image.read
else
image_data = open(image, "rb") { |file| file.read }
image_data = open(image, "r:ISO-8859-1:ISO-8859-1") { |file| file.read }
end
info = PDF::Writer::Graphics::ImageInfo.new(image_data)
end
Expand Down
17 changes: 11 additions & 6 deletions lib/pdf/writer/graphics/imageinfo.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#encoding: ISO-8859-1
#--
# PDF::Writer for Ruby.
# http://rubyforge.org/projects/ruby-pdf/
Expand All @@ -9,7 +10,7 @@
# This file is also licensed under standard Ruby licensing provisions: the
# Ruby licence and the GNU General Public Licence, version 2 or later.
#
# $Id$
# $Id: imageinfo.rb 173 2007-11-15 17:58:43Z sandal $
#++
require 'pdf/writer/oreader'

Expand Down Expand Up @@ -47,8 +48,8 @@ def formats
alias :type_list :formats
end

JPEG_SOF_BLOCKS = %W(\xc0 \xc1 \xc2 \xc3 \xc5 \xc6 \xc7 \xc9 \xca \xcb \xcd \xce \xcf)
JPEG_APP_BLOCKS = %W(\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef)
JPEG_SOF_BLOCKS = %W(\xc0 \xc1 \xc2 \xc3 \xc5 \xc6 \xc7 \xc9 \xca \xcb \xcd \xce \xcf).map{|m| m.force_encoding("ISO-8859-1")}
JPEG_APP_BLOCKS = %W(\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef).map{|m| m.force_encoding("ISO-8859-1")}

# Receive image & make size. argument is image String or IO
def initialize(data, format = nil)
Expand Down Expand Up @@ -98,7 +99,7 @@ def @data.read_o(length = 1, offset = nil)
attr_reader :channels

attr_reader :info

def discover_format
if @top =~ %r{^GIF8[79]a}
Formats::GIF
Expand Down Expand Up @@ -173,8 +174,12 @@ def measure_JPEG
@data.read_o(2) # Skip the first two bytes of JPEG identifier.
loop do
marker, code, length = @data.read_o(4).unpack('aan')

marker.force_encoding("ISO-8859-1")
code.force_encoding("ISO-8859-1")

raise "JPEG marker not found!" if marker != c_marker

if JPEG_SOF_BLOCKS.include?(code)
@bits, @height, @width, @channels = @data.read_o(6).unpack("CnnC")
break
Expand Down Expand Up @@ -351,7 +356,7 @@ def measure_TIFF

Dir.glob("*").each do |file|
print "#{file} (string)\n"
open(file, "rb") do |fh|
open(file, "r:ISO-8859-1:ISO-8859-1") do |fh|
image = PDF::Writer::Graphics::ImageInfo.new(fh.read)
print <<-EOF
Format : #{image.format}
Expand Down
70 changes: 70 additions & 0 deletions test/test_image_read.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#encoding: UTF-8
$LOAD_PATH.unshift(File.dirname(__FILE__) + "/../lib")
require "pdf/writer"

MAIN_TEXT_WIDTH = 330
MAIN_TEXT_LINE_SPACING = 16
PADDING_BOTTOM = 20

def write_text(pdf, text, options = {})
y = options[:y] if options[:y]
left = options[:left] if options[:left]
width = options[:width] if options[:width]
size = options[:font_size] || 0
height = options[:leading]

# Filled with the text that would flow onto the next page
next_page_text = nil

text.each_line do |line|
start = true
loop do
break if (line.nil? or line.empty?) and not start

start = false

y -= height

if y < (pdf.absolute_bottom_margin + PADDING_BOTTOM)
if options[:no_newpage]
# Collect remaining text so it can be returned
next_page_text = "" if next_page_text.nil?
next_page_text += line
line = nil
else
pdf.start_new_page
y = options[:new_page_y] || multi_page_top_y(pdf)
end
end

if next_page_text.nil?
line = pdf.add_text_wrap(left, y, width, line, size)
end
end
end

if options[:no_newpage]
{:leftover_text => next_page_text, :next_line_y => y}
else
y
end
end


pdf = PDF::Writer.new
top_logo_file = '/Users/mwlang/projects/clients/taftlaw/taft_site/website/public/images/hr_taft_logo.jpg'
pdf.image(top_logo_file, {:width => 85, :justification => :right, :pad => 0 })

body = "\r\n\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\r\n\r\n\r\nCHARLES R. \"ROCKY\" SAXBE is Partner-in-Charge of the Columbus office. He maintains an active litigation practice representing clients in all aspects of civil litigation. Over the course of his illustrious career, he has acted as principal litigation counsel in numerous complex litigation cases, including serving as principal outside Ohio special counsel for the State of Ohio in the national tobacco litigation. He has appeared in numerous jury trials and has appeared before the Ohio Supreme Court, Ohio Courts of Appeals, and the Sixth Circuit U.S. Court of Appeals. According to <em>Chambers USA</em>, who interviews clients for feedback, Rocky is held in high regard \"for his political acumen, especially in election law-related and complex civil litigation.\" Rocky has a long affiliation with the political scene in Ohio, having served four terms in the Ohio House of Representatives. He provides counsel to elected officials, political party organizations and candidates on election, campaign finance and public ethics law.\r\n\r\n<strong>Representative Experience</strong>\r\n\r\n\r\n\t<C:bullet/>Served as principal outside Ohio special counsel for the State of Ohio in the \"national tobacco litigation,\" contributing significantly to the record setting $10 billion settlement for the State of Ohio.\r\n\t<C:bullet/>Has been the principal litigation counsel in numerous complex litigations, including numerous jury trials and has appeared before Ohio Supreme Court, Ohio Courts of Appeals, and the Sixth Circuit U.S. Court of Appeals.\r\n\t<C:bullet/>Provided counsel to elected officials, political party organizations and candidates on election, campaign finance and public ethics law.\r\n\t<C:bullet/>Frequent mediator assigned by the Federal Court for the Southern District of Ohio, providing expert testimony in the areas of attorneys' fees and malpractice.\r\n\t<C:bullet/>Serves as legislative counsel for the Ohio Association of Municipal and County Judges.\r\n\r\n\r\n<strong>Achievements and Awards</strong>\r\n\r\n\r\n\t<C:bullet/>Recipient of the Ohio State Bar Association Distinguished Service Award\r\n\t<C:bullet/>AV Peer Review (Preeminent) Rated by Martindale-Hubbell\r\n\t<C:bullet/><em>Best Lawyers in America, </em>Commercial Litigation, Government Relations Law & Bet-the-Company Litigation\r\n\t<C:bullet/>Listed for inclusion in <em>Ohio Super Lawyers</em>, General Litigation (2004 - 2013)\r\n\t<C:bullet/><em>Chambers USA</em>, Litigation\r\n\r\n\r\n<strong>Professional Memberships and Community Service</strong>\r\n\r\n\r\n\t<C:bullet/>Columbus Bar Association\r\n\t<C:bullet/>Ohio State Bar Association\r\n\t<C:bullet/>American Bar Associations\r\n\t<C:bullet/>Champaign County Bar Association\r\n\t<C:bullet/>Greater Columbus Arts Council, Past Chairman\r\n\t<C:bullet/>Bexley Library Board, Past President\r\n\t<C:bullet/>Columbus College of Art and Design, Past Chairman\r\n\t<C:bullet/>Central State University, Past Trustee\r\n\t<C:bullet/>Mechanicsburg Lodge #113 F&AM, Past Master\r\n\t<C:bullet/>Ancient and Accepted Scottish Rite, 33°\r\n\t<C:bullet/>Vietnam Veterans of America\r\n\t<C:bullet/>American Legion\r\n\t<C:bullet/>Scioto Valley Rugby Football Club (SVRFC Hall of Fame)\r\n\r\n\r\n<strong>Other Professional Experience</strong>\r\n\r\n\r\n\t<C:bullet/>U.S. Marine Corps, infantry platoon commander with the First Marine Division in the Republic of Vietnam and was discharged with the rank of Captain\r\n\t<C:bullet/>Elected to the Ohio House of Representatives in 1974 where he served four terms\r\n\t<C:bullet/>Republican nominee for Ohio Attorney General in 1982\r\n\r\n"
write_text(pdf,
body,
{
:no_newpage => true,
:y => pdf.absolute_top_margin - 140,
:left => pdf.absolute_left_margin,
:leading => MAIN_TEXT_LINE_SPACING,
:width => MAIN_TEXT_WIDTH
}
)

pdf.render