pdf-wrapper 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +15 -0
- data/{README → README.rdoc} +21 -16
- data/Rakefile +6 -4
- data/examples/text.rb +14 -0
- data/lib/pdf/errors.rb +1 -0
- data/lib/pdf/wrapper.rb +146 -65
- data/lib/pdf/wrapper/images.rb +10 -1
- data/lib/pdf/wrapper/page.rb +20 -0
- data/lib/pdf/wrapper/table.rb +21 -8
- data/lib/pdf/wrapper/text.rb +10 -7
- data/specs/image_spec.rb +8 -0
- data/specs/spec_helper.rb +4 -5
- data/specs/wrapper_spec.rb +33 -77
- metadata +24 -14
- data/examples/scaled.rb +0 -38
- data/examples/scaled_cells.rb +0 -30
data/CHANGELOG
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
v0.1.3 (24th July 2008)
|
2
|
+
- Require the gem version of cairo
|
3
|
+
- >= 1.5. However I recommend >= 1.6.3 to avoid FATAL error under 1.8.7
|
4
|
+
- Removed Wrapper#scale. Was causing more trouble than it's worth. May re-implement later.
|
5
|
+
- Allow the render functions to be called multiple times
|
6
|
+
- Added Wrapper#finished?
|
7
|
+
- rename Wrapper#render_to_file to Wrapper#render_file.
|
8
|
+
- old method still exists with a deprecation warning
|
9
|
+
- add :rotate option to Wrapper#image (thanks Lourens Naudé)
|
10
|
+
- borrowed some convenience methods for co-ordinate manipulation from Prawn
|
11
|
+
- Wrapper#translate now resets the point to 0,0 before yielding
|
12
|
+
|
13
|
+
v0.1.1 (Unreleased)
|
14
|
+
- use a proxy object when building repeating objects to prevent a new page being started
|
15
|
+
|
1
16
|
v0.1.0 (28th May 2008)
|
2
17
|
- added PDF::Wrapper#translate and PDF::Wrapper#scale
|
3
18
|
- fixed a bug that caused some text to be rendered off the page when wrapping onto 3rd and
|
data/{README → README.rdoc}
RENAMED
@@ -1,27 +1,30 @@
|
|
1
1
|
= Overview
|
2
2
|
|
3
3
|
PDF::Wrapper is a PDF generation library that uses the cairo and pango
|
4
|
-
libraries to do the heavy lifting.
|
5
|
-
purpose graphics libraries with some sugar that makes them a little
|
6
|
-
use for making PDFs. The idea is to lever the low level tools in
|
7
|
-
(drawing shapes, laying out text, importing raster images, etc)
|
8
|
-
higher level tools - tables, text boxes, borders, lists,
|
9
|
-
(headers/footers), etc.
|
10
|
-
|
11
|
-
The API started off *roughly* following that of PDF::Writer, but
|
12
|
-
|
13
|
-
|
4
|
+
native libraries to do the heavy lifting. It essentially just wraps these
|
5
|
+
general purpose graphics libraries with some sugar that makes them a little
|
6
|
+
easier to use for making PDFs. The idea is to lever the low level tools in
|
7
|
+
those libraries (drawing shapes, laying out text, importing raster images, etc)
|
8
|
+
to build some higher level tools - tables, text boxes, borders, lists,
|
9
|
+
repeating elements (headers/footers), etc.
|
10
|
+
|
11
|
+
The API started off *roughly* following that of PDF::Writer, but it has since
|
12
|
+
diverged significantly. I've spent some time contributing to a pure Ruby PDF
|
13
|
+
generation library (Prawn[http://github.com/sandal/prawn/tree]) and its elegant
|
14
|
+
and simple API is having a strong effect on the direction I've been taking
|
15
|
+
PDF::Wrapper.
|
14
16
|
|
15
17
|
A key motivation for writing this library is cairo's support for Unicode in PDFs.
|
16
|
-
All text functions in this library
|
17
|
-
English speaker I've only tested
|
18
|
+
All text functions in this library require UTF-8 input, although as a native
|
19
|
+
English speaker I've only tested non ASCII text a little, so any feedback is
|
20
|
+
welcome.
|
18
21
|
|
19
|
-
There also seems to be a lack of English documentation available for the ruby
|
22
|
+
There also seems to be a lack of English documentation available for the ruby
|
20
23
|
bindings to cairo/pango, so I'm aiming to document the code as much as possible
|
21
24
|
to provide worked examples for others. I'm learning as I go though, so if regular
|
22
25
|
users of either library spot techniques that fail best practice, please let me know.
|
23
26
|
|
24
|
-
It's early days, so the API is far from stable and I'm hesitant to write extensive
|
27
|
+
It's early days, so the API is far from stable and I'm hesitant to write extensive
|
25
28
|
documentation just yet. It's the price you pay for being an early adopter. The
|
26
29
|
examples/ dir should have a range of sample code, and I'll try to keep it up to
|
27
30
|
date.
|
@@ -44,7 +47,7 @@ James Healy <jimmy@deefa.com>
|
|
44
47
|
|
45
48
|
* GPL version 2 or the Ruby License
|
46
49
|
* Ruby: http://www.ruby-lang.org/en/LICENSE.txt
|
47
|
-
|
50
|
+
|
48
51
|
= Dependencies
|
49
52
|
|
50
53
|
* ruby/cairo[http://cairographics.org/rcairo/]
|
@@ -65,7 +68,9 @@ of the cairo source available on your system.
|
|
65
68
|
|
66
69
|
= Compatibility
|
67
70
|
|
68
|
-
JRuby users, you're
|
71
|
+
JRuby users, you're currently out of luck. In theory it should be possible to use the Java bindings
|
72
|
+
to the native libraries we need, but as I'm not a JRuby user, it's not an itch
|
73
|
+
I've been motivated to scratch.
|
69
74
|
|
70
75
|
Rubinius users, I have no idea.
|
71
76
|
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/testtask'
|
|
6
6
|
require "rake/gempackagetask"
|
7
7
|
require 'spec/rake/spectask'
|
8
8
|
|
9
|
-
PKG_VERSION = "0.1.
|
9
|
+
PKG_VERSION = "0.1.3"
|
10
10
|
PKG_NAME = "pdf-wrapper"
|
11
11
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
12
12
|
|
@@ -18,6 +18,7 @@ desc "Run all rspec files"
|
|
18
18
|
Spec::Rake::SpecTask.new("spec") do |t|
|
19
19
|
# spec files listed explicitly so that load_spec is the first one run
|
20
20
|
t.spec_files = ['specs/load_spec.rb','specs/image_spec.rb','specs/graphics_spec.rb','specs/tables_spec.rb','specs/text_spec.rb','specs/wrapper_spec.rb']
|
21
|
+
t.spec_opts = ['-c']
|
21
22
|
t.rcov = true
|
22
23
|
t.rcov_dir = (ENV['CC_BUILD_ARTIFACTS'] || 'doc') + "/rcov"
|
23
24
|
t.rcov_opts = ["--exclude","spec.*\.rb","--exclude",".*cairo.*","--exclude",".*rcov.*","--exclude",".*rspec.*","--exclude",".*pdf-reader.*", "--exclude",".*gems.*"]
|
@@ -45,7 +46,7 @@ desc "Create documentation"
|
|
45
46
|
Rake::RDocTask.new("doc") do |rdoc|
|
46
47
|
rdoc.title = "pdf-wrapper"
|
47
48
|
rdoc.rdoc_dir = (ENV['CC_BUILD_ARTIFACTS'] || 'doc') + '/rdoc'
|
48
|
-
rdoc.rdoc_files.include('README')
|
49
|
+
rdoc.rdoc_files.include('README.rdoc')
|
49
50
|
rdoc.rdoc_files.include('CHANGELOG')
|
50
51
|
rdoc.rdoc_files.include('TODO')
|
51
52
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
@@ -67,8 +68,9 @@ spec = Gem::Specification.new do |spec|
|
|
67
68
|
spec.files = Dir.glob("{examples,lib,specs}/**/**/*") + ["Rakefile"]
|
68
69
|
spec.require_path = "lib"
|
69
70
|
spec.has_rdoc = true
|
70
|
-
spec.extra_rdoc_files = %w{README CHANGELOG TODO}
|
71
|
-
spec.rdoc_options << '--title' << 'PDF::Wrapper Documentation' << '--main' << 'README' << '-q'
|
71
|
+
spec.extra_rdoc_files = %w{README.rdoc CHANGELOG TODO}
|
72
|
+
spec.rdoc_options << '--title' << 'PDF::Wrapper Documentation' << '--main' << 'README.rdoc' << '-q'
|
73
|
+
spec.add_dependency 'cairo', '>=1.5.0'
|
72
74
|
spec.author = "James Healy"
|
73
75
|
spec.homepage = "http://pdf-wrapper.rubyforge.org/"
|
74
76
|
spec.email = "jimmy@deefa.com"
|
data/examples/text.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
5
|
+
|
6
|
+
require 'pdf/wrapper'
|
7
|
+
|
8
|
+
pdf = PDF::Wrapper.new(:paper => :A4)
|
9
|
+
pdf.font("Sans Serif")
|
10
|
+
pdf.text "Line 1", :font_size => 8
|
11
|
+
pdf.text "Line 2", :font_size => 8
|
12
|
+
pdf.text "Line 3", :font_size => 8
|
13
|
+
pdf.text "Line 4\nLine 5", :font_size => 8
|
14
|
+
pdf.render_to_file("text.pdf")
|
data/lib/pdf/errors.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
class InvalidOperationError < RuntimeError; end;
|
data/lib/pdf/wrapper.rb
CHANGED
@@ -2,28 +2,18 @@
|
|
2
2
|
|
3
3
|
require 'stringio'
|
4
4
|
require 'pdf/core'
|
5
|
+
require 'pdf/errors'
|
5
6
|
|
6
7
|
require File.dirname(__FILE__) + "/wrapper/graphics"
|
7
8
|
require File.dirname(__FILE__) + "/wrapper/images"
|
8
9
|
require File.dirname(__FILE__) + "/wrapper/loading"
|
9
10
|
require File.dirname(__FILE__) + "/wrapper/table"
|
10
11
|
require File.dirname(__FILE__) + "/wrapper/text"
|
12
|
+
require File.dirname(__FILE__) + "/wrapper/page"
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
require 'cairo'
|
16
|
-
rescue LoadError
|
17
|
-
begin
|
18
|
-
require 'rubygems'
|
19
|
-
gem 'cairo', '>=1.5'
|
20
|
-
require 'cairo'
|
21
|
-
rescue Gem::LoadError
|
22
|
-
raise LoadError, "Could not find the ruby cairo bindings in the standard locations or via rubygems. Check to ensure they're installed correctly"
|
23
|
-
rescue LoadError
|
24
|
-
raise LoadError, "Could not load rubygems"
|
25
|
-
end
|
26
|
-
end
|
14
|
+
require 'rubygems'
|
15
|
+
gem 'cairo', '>=1.5'
|
16
|
+
require 'cairo'
|
27
17
|
|
28
18
|
module PDF
|
29
19
|
# Create PDF files by using the cairo and pango libraries.
|
@@ -289,33 +279,7 @@ module PDF
|
|
289
279
|
def translate(x, y, &block)
|
290
280
|
@context.save do
|
291
281
|
@context.translate(x, y)
|
292
|
-
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
# all code wrapped in the block passed to this function will have co-ordinates
|
297
|
-
# and distances (width/height) multiplied by these values before being used
|
298
|
-
#
|
299
|
-
# Divide everything by 2
|
300
|
-
#
|
301
|
-
# pdf.scale(0.5, 0.5) do
|
302
|
-
# ...
|
303
|
-
# end
|
304
|
-
#
|
305
|
-
# Make the page 1.0 wide and 1.0 tall, so co-ordinates and distances
|
306
|
-
# can be specified as percentages (0.5 == 50%, etc)
|
307
|
-
#
|
308
|
-
# pdf.scale(pdf.page_width.to_f, pdf.page_height.to_f) do
|
309
|
-
# ...
|
310
|
-
# end
|
311
|
-
#
|
312
|
-
def scale(w, h, &block)
|
313
|
-
@context.save do
|
314
|
-
@context.scale(w, h)
|
315
|
-
|
316
|
-
# set the line width again so that it's set relative to the current
|
317
|
-
# scale factor
|
318
|
-
line_width @line_width
|
282
|
+
move_to(0,0)
|
319
283
|
yield
|
320
284
|
end
|
321
285
|
end
|
@@ -343,16 +307,19 @@ module PDF
|
|
343
307
|
def render
|
344
308
|
# finalise the document, then convert the StringIO object it was rendered to
|
345
309
|
# into a string
|
346
|
-
|
347
|
-
@context.target.finish
|
310
|
+
finish
|
348
311
|
return @output.string
|
349
312
|
end
|
350
313
|
|
314
|
+
def render_to_file(filename) #nodoc
|
315
|
+
# TODO: remove this at some point
|
316
|
+
warn "WARNING: render_to_file() is deprecated, please use render_file()"
|
317
|
+
render_file filename
|
318
|
+
end
|
319
|
+
|
351
320
|
# save the rendered PDF to a file
|
352
|
-
def
|
353
|
-
|
354
|
-
@context.show_page
|
355
|
-
@context.target.finish
|
321
|
+
def render_file(filename)
|
322
|
+
finish
|
356
323
|
|
357
324
|
# write each line from the StringIO object it was rendered to into the
|
358
325
|
# requested file
|
@@ -366,10 +333,110 @@ module PDF
|
|
366
333
|
# Misc Functions
|
367
334
|
#####################################################
|
368
335
|
|
369
|
-
|
336
|
+
# move down the canvas by n points
|
337
|
+
# returns the new y position
|
338
|
+
#
|
339
|
+
def move_down(n)
|
340
|
+
x, y = current_point
|
341
|
+
newy = y + n
|
342
|
+
move_to(x, newy)
|
343
|
+
newy
|
344
|
+
end
|
345
|
+
|
346
|
+
# move up the canvas by n points
|
347
|
+
# returns the new y position
|
348
|
+
#
|
349
|
+
def move_up(n)
|
350
|
+
x, y = current_point
|
351
|
+
newy = y - n
|
352
|
+
move_to(x, newy)
|
353
|
+
newy
|
354
|
+
end
|
355
|
+
|
356
|
+
# move left across the canvas by n points
|
357
|
+
# returns the new x position
|
358
|
+
#
|
359
|
+
def move_left(n)
|
360
|
+
x, y = current_point
|
361
|
+
newx = x - n
|
362
|
+
move_to(newx, y)
|
363
|
+
newx
|
364
|
+
end
|
365
|
+
|
366
|
+
# move right across the canvas by n points
|
367
|
+
# returns the new x position
|
368
|
+
#
|
369
|
+
def move_right(n)
|
370
370
|
x, y = current_point
|
371
|
-
|
372
|
-
y
|
371
|
+
newx = x + n
|
372
|
+
move_to(newx, y)
|
373
|
+
newx
|
374
|
+
end
|
375
|
+
|
376
|
+
# Moves down the document and then executes a block.
|
377
|
+
#
|
378
|
+
# pdf.text "some text"
|
379
|
+
# pdf.pad_top(100) do
|
380
|
+
# pdf.text "This is 100 points below the previous line of text"
|
381
|
+
# end
|
382
|
+
# pdf.text "This text appears right below the previous line of text"
|
383
|
+
#
|
384
|
+
def pad_top(n)
|
385
|
+
move_down n
|
386
|
+
yield
|
387
|
+
end
|
388
|
+
|
389
|
+
# Executes a block then moves down the document
|
390
|
+
#
|
391
|
+
# pdf.text "some text"
|
392
|
+
# pdf.pad_bottom(100) do
|
393
|
+
# pdf.text "This text appears right below the previous line of text"
|
394
|
+
# end
|
395
|
+
# pdf.text "This is 100 points below the previous line of text"
|
396
|
+
#
|
397
|
+
def pad_bottom(n)
|
398
|
+
yield
|
399
|
+
move_down n
|
400
|
+
end
|
401
|
+
|
402
|
+
# Moves down the document by y, executes a block, then moves down the
|
403
|
+
# document by y again.
|
404
|
+
#
|
405
|
+
# pdf.text "some text"
|
406
|
+
# pdf.pad(100) do
|
407
|
+
# pdf.text "This is 100 points below the previous line of text"
|
408
|
+
# end
|
409
|
+
# pdf.text "This is 100 points below the previous line of text"
|
410
|
+
#
|
411
|
+
def pad(n)
|
412
|
+
if block_given?
|
413
|
+
move_down n
|
414
|
+
yield
|
415
|
+
move_down n
|
416
|
+
else
|
417
|
+
move_down n
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# Moves right across the document by n, executes a block, then moves back
|
422
|
+
# left by the same amount
|
423
|
+
#
|
424
|
+
# pdf.text "some text"
|
425
|
+
# pdf.indent(50) do
|
426
|
+
# pdf.text "This starts 50 points right the previous line of text"
|
427
|
+
# end
|
428
|
+
# pdf.text "This starts in line with the first line of text"
|
429
|
+
#
|
430
|
+
# If no block is provided, operates just like move_right.
|
431
|
+
#
|
432
|
+
def indent(n)
|
433
|
+
if block_given?
|
434
|
+
move_right n
|
435
|
+
yield
|
436
|
+
move_left n
|
437
|
+
else
|
438
|
+
move_right n
|
439
|
+
end
|
373
440
|
end
|
374
441
|
|
375
442
|
# move the cursor to an arbitary position on the current page
|
@@ -382,21 +449,35 @@ module PDF
|
|
382
449
|
@context.move_to(margin_left,margin_top)
|
383
450
|
end
|
384
451
|
|
452
|
+
# returns true if the PDF has already been rendered, false if it hasn't.
|
453
|
+
# Due to limitations of the underlying libraries, content cannot be
|
454
|
+
# added to a PDF once it has been rendered.
|
455
|
+
#
|
456
|
+
def finished?
|
457
|
+
@output.seek(@output.size - 6)
|
458
|
+
bytes = @output.read(6)
|
459
|
+
bytes == "%%EOF\n" ? true : false
|
460
|
+
end
|
461
|
+
|
385
462
|
# add the same elements to multiple pages. Useful for adding items like headers, footers and
|
386
463
|
# watermarks.
|
387
464
|
#
|
465
|
+
# There is a single block parameter that is a proxy to the current PDF::Wrapper object that
|
466
|
+
# disallows start_new_page calls. Every other method from PDF::Wrapper is considered valid.
|
467
|
+
#
|
388
468
|
# arguments:
|
389
469
|
# <tt>spec</tt>:: Which pages to add the items to. :all, :odd, :even, a range, an Array of numbers or an number
|
390
470
|
#
|
391
471
|
# To add text to every page that mentions the page number
|
392
|
-
# pdf.repeating_element(:all) do
|
393
|
-
#
|
472
|
+
# pdf.repeating_element(:all) do |page|
|
473
|
+
# page.text("Page #{page.page}!", :left => page.margin_left, :top => page.margin_top, :font_size => 18)
|
394
474
|
# end
|
395
475
|
#
|
396
476
|
# To add a circle to the middle of every page
|
397
|
-
# pdf.repeating_element(:all) do
|
398
|
-
#
|
477
|
+
# pdf.repeating_element(:all) do |page|
|
478
|
+
# page.circle(page.absolute_x_middle, page.absolute_y_middle, 100)
|
399
479
|
# end
|
480
|
+
#
|
400
481
|
def repeating_element(spec = :all, &block)
|
401
482
|
call_repeating_element(spec, block)
|
402
483
|
|
@@ -409,6 +490,7 @@ module PDF
|
|
409
490
|
# options:
|
410
491
|
# <tt>:pageno</tt>:: If specified, the current page number will be set to that. By default, the page number will just increment.
|
411
492
|
# <tt>:template</tt>:: The path to an image file. If specified, the new page will use the specified image as a template. The page will be sized to match the template size
|
493
|
+
#
|
412
494
|
def start_new_page(opts = {})
|
413
495
|
opts.assert_valid_keys(:pageno, :template)
|
414
496
|
|
@@ -440,10 +522,17 @@ module PDF
|
|
440
522
|
|
441
523
|
private
|
442
524
|
|
525
|
+
def finish
|
526
|
+
# finalise the document
|
527
|
+
@context.show_page
|
528
|
+
@context.target.finish
|
529
|
+
rescue Cairo::SurfaceFinishedError
|
530
|
+
# do nothing, we're happy that the surfaced has been finished
|
531
|
+
end
|
532
|
+
|
443
533
|
# runs the code in block, passing it a hash of options that might be
|
444
534
|
# required
|
445
535
|
def call_repeating_element(spec, block)
|
446
|
-
# TODO: disallow start_new_page when adding a repeating element
|
447
536
|
if spec == :all ||
|
448
537
|
(spec == :even && (page % 2) == 0) ||
|
449
538
|
(spec == :odd && (page % 2) == 1) ||
|
@@ -453,7 +542,7 @@ module PDF
|
|
453
542
|
|
454
543
|
@context.save do
|
455
544
|
# add it to the current page
|
456
|
-
block.call
|
545
|
+
block.call PDF::Wrapper::Page.new(self)
|
457
546
|
end
|
458
547
|
end
|
459
548
|
end
|
@@ -491,10 +580,6 @@ module PDF
|
|
491
580
|
Cairo::Color.parse(c).to_rgb.to_a
|
492
581
|
end
|
493
582
|
|
494
|
-
def user_to_device_dist(x,y)
|
495
|
-
@context.user_to_device_distance(x, y)
|
496
|
-
end
|
497
|
-
|
498
583
|
def user_x_to_device_x(x)
|
499
584
|
@context.user_to_device(x, 0).first.abs
|
500
585
|
end
|
@@ -503,10 +588,6 @@ module PDF
|
|
503
588
|
@context.user_to_device(0, y).last.abs
|
504
589
|
end
|
505
590
|
|
506
|
-
def device_to_user_dist(x, y)
|
507
|
-
@context.device_to_user_distance(x, y)
|
508
|
-
end
|
509
|
-
|
510
591
|
def device_x_to_user_x(x)
|
511
592
|
@context.device_to_user(x, 0).first.abs
|
512
593
|
end
|
data/lib/pdf/wrapper/images.rb
CHANGED
@@ -13,6 +13,8 @@ module PDF
|
|
13
13
|
# <tt>:proportional</tt>:: Boolean. Maintain image proportions when scaling. Defaults to false.
|
14
14
|
# <tt>:padding</tt>:: Add some padding between the image and the specified box.
|
15
15
|
# <tt>:center</tt>:: If the image is scaled, it will be centered horizontally and vertically
|
16
|
+
# <tt>:rotate</tt>:: The desired rotation. One of :counterclockwise, :upsidedown, :clockwise.
|
17
|
+
# Doesn't work with PNG, PDF or SVG files.
|
16
18
|
#
|
17
19
|
# left and top default to the current cursor location
|
18
20
|
# width and height default to the size of the imported image
|
@@ -20,7 +22,7 @@ module PDF
|
|
20
22
|
def image(filename, opts = {})
|
21
23
|
# TODO: add some options for justification and padding
|
22
24
|
raise ArgumentError, "file #{filename} not found" unless File.file?(filename)
|
23
|
-
opts.assert_valid_keys(default_positioning_options.keys + [:padding, :proportional, :center])
|
25
|
+
opts.assert_valid_keys(default_positioning_options.keys + [:padding, :proportional, :center, :rotate])
|
24
26
|
|
25
27
|
if opts[:padding]
|
26
28
|
opts[:left] += opts[:padding].to_i if opts[:left]
|
@@ -132,6 +134,9 @@ module PDF
|
|
132
134
|
load_libpixbuf
|
133
135
|
x, y = current_point
|
134
136
|
pixbuf = Gdk::Pixbuf.new(filename)
|
137
|
+
if opts[:rotate]
|
138
|
+
pixbuf = pixbuf.rotate( rotation_constant( opts[:rotate] ) )
|
139
|
+
end
|
135
140
|
width, height = calc_image_dimensions(opts[:width], opts[:height], pixbuf.width, pixbuf.height, opts[:proportional])
|
136
141
|
x, y = calc_image_coords(opts[:left] || x, opts[:top] || y, opts[:width] || pixbuf.width, opts[:height] || pixbuf.height, width, height, opts[:center])
|
137
142
|
@context.save do
|
@@ -145,6 +150,10 @@ module PDF
|
|
145
150
|
raise ArgumentError, "Unrecognised image format (#{filename})"
|
146
151
|
end
|
147
152
|
|
153
|
+
def rotation_constant( rotation )
|
154
|
+
Gdk::Pixbuf.const_get "ROTATE_#{rotation.to_s.upcase}"
|
155
|
+
end
|
156
|
+
|
148
157
|
def draw_png(filename, opts = {})
|
149
158
|
# based on a similar function in rabbit. Thanks Kou.
|
150
159
|
x, y = current_point
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PDF
|
2
|
+
class Wrapper
|
3
|
+
|
4
|
+
# a proxy to a PDF::Wrapper object that disallows new pages
|
5
|
+
class Page
|
6
|
+
|
7
|
+
def initialize(pdf)
|
8
|
+
@pdf = pdf
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args, &block)
|
12
|
+
if method.to_sym == :start_new_page
|
13
|
+
raise InvalidOperationError, 'start_new_page is not allowed in the current context'
|
14
|
+
else
|
15
|
+
@pdf.__send__(method, *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/pdf/wrapper/table.rb
CHANGED
@@ -16,6 +16,11 @@ module PDF
|
|
16
16
|
# <tt>:top</tt>:: The y co-ordinate of the top of the text. Defaults to the current cursor location
|
17
17
|
# <tt>:width</tt>:: The width of the table. Defaults to the distance from the left of the table to the right margin
|
18
18
|
def table(data, opts = {})
|
19
|
+
# TODO: add support for a table footer
|
20
|
+
# - repeating each page, or just at the bottom?
|
21
|
+
# - if it repeats, should it be different on each page? ie. a sum of that pages rows, etc.
|
22
|
+
# TODO: add support for manually specifying 1 or more column widths
|
23
|
+
# TODO: maybe support for multiple data sets with group headers/footers. useful for subtotals, etc
|
19
24
|
|
20
25
|
x, y = current_point
|
21
26
|
options = {:left => x, :top => y }
|
@@ -163,7 +168,7 @@ module PDF
|
|
163
168
|
# For example:
|
164
169
|
#
|
165
170
|
# table = Table.new do |t|
|
166
|
-
# t.
|
171
|
+
# t.headers = ["Words", "Numbers"]
|
167
172
|
# t.data = [['one', 1],
|
168
173
|
# ['two', 2],
|
169
174
|
# ['three',3]]
|
@@ -186,12 +191,6 @@ module PDF
|
|
186
191
|
attr_reader :cells, :headers
|
187
192
|
attr_accessor :width, :show_headers
|
188
193
|
|
189
|
-
# Create a new table object.
|
190
|
-
#
|
191
|
-
# data should be a 2d array
|
192
|
-
#
|
193
|
-
# [[ "one", "two"],
|
194
|
-
# [ "one", "two"]]
|
195
194
|
#
|
196
195
|
# headers should be a single array
|
197
196
|
#
|
@@ -209,7 +208,14 @@ module PDF
|
|
209
208
|
self
|
210
209
|
end
|
211
210
|
|
211
|
+
# Specify the tables data.
|
212
|
+
#
|
213
|
+
# The single argument should be a 2d array like:
|
214
|
+
#
|
215
|
+
# [[ "one", "two"],
|
216
|
+
# [ "one", "two"]]
|
212
217
|
def data=(d)
|
218
|
+
# TODO: raise an exception of the data rows aren't all the same size
|
213
219
|
# TODO: ensure d is array-like
|
214
220
|
@cells = d.collect do |row|
|
215
221
|
row.collect do |str|
|
@@ -218,14 +224,21 @@ module PDF
|
|
218
224
|
end
|
219
225
|
end
|
220
226
|
|
227
|
+
# Specify the tables optional column headers.
|
228
|
+
#
|
229
|
+
# The single argument should be an array like:
|
230
|
+
#
|
231
|
+
# [ "col one", "col two"]
|
221
232
|
def headers=(h)
|
233
|
+
# TODO: raise an exception of the size of the array does not match the size
|
234
|
+
# of the data row arrays
|
222
235
|
# TODO: ensure h is array-like
|
223
236
|
@headers = h.collect do |str|
|
224
237
|
Wrapper::Cell.new(str)
|
225
238
|
end
|
226
239
|
end
|
227
240
|
|
228
|
-
# access a particular cell
|
241
|
+
# access a particular cell at location x, y
|
229
242
|
def cell(col_idx, row_idx)
|
230
243
|
@cells[row_idx, col_idx]
|
231
244
|
end
|
data/lib/pdf/wrapper/text.rb
CHANGED
@@ -28,9 +28,10 @@ module PDF
|
|
28
28
|
def cell(str, x, y, w, h, opts={})
|
29
29
|
# TODO: add a wrap option so wrapping can be disabled
|
30
30
|
# TODO: add an option for vertical alignment
|
31
|
+
# TODO: allow cell contents to be defined as a block, like link_to in EDGE rails
|
31
32
|
|
32
33
|
options = default_text_options
|
33
|
-
options.merge!({:border => "tblr", :border_width => @default_line_width, :border_color => :black, :fill_color => nil, :padding =>
|
34
|
+
options.merge!({:border => "tblr", :border_width => @default_line_width, :border_color => :black, :fill_color => nil, :padding => 3, :radius => nil})
|
34
35
|
options.merge!(opts)
|
35
36
|
options.assert_valid_keys(default_text_options.keys + [:width, :border, :border_width, :border_color, :fill_color, :padding, :radius])
|
36
37
|
|
@@ -142,7 +143,7 @@ module PDF
|
|
142
143
|
# draw the context on our cairo layout
|
143
144
|
y = render_layout(layout, options[:left], options[:top], points_to_bottom_margin(options[:top]), :auto_new_page => true)
|
144
145
|
|
145
|
-
move_to(options[:left], y
|
146
|
+
move_to(options[:left], y)
|
146
147
|
end
|
147
148
|
|
148
149
|
# Returns the amount of vertical space needed to display the supplied text at the requested width
|
@@ -233,7 +234,7 @@ module PDF
|
|
233
234
|
layout.width = w * Pango::SCALE
|
234
235
|
end
|
235
236
|
# spacing is specified in user points
|
236
|
-
layout.spacing =
|
237
|
+
layout.spacing = options[:spacing] * Pango::SCALE
|
237
238
|
|
238
239
|
# set the alignment of the text in the layout
|
239
240
|
if options[:alignment].eql?(:left)
|
@@ -263,7 +264,7 @@ module PDF
|
|
263
264
|
# setup the font that will be used to render the text
|
264
265
|
fdesc = Pango::FontDescription.new(options[:font])
|
265
266
|
# font size should be specified in device points for simplicity's sake.
|
266
|
-
fdesc.size =
|
267
|
+
fdesc.size = options[:font_size] * Pango::SCALE
|
267
268
|
layout.font_description = fdesc
|
268
269
|
@context.update_pango_layout(layout)
|
269
270
|
|
@@ -296,6 +297,7 @@ module PDF
|
|
296
297
|
|
297
298
|
offset = 0
|
298
299
|
baseline = 0
|
300
|
+
spacing = layout.spacing / Pango::SCALE
|
299
301
|
|
300
302
|
iter = layout.iter
|
301
303
|
loop do
|
@@ -320,7 +322,7 @@ module PDF
|
|
320
322
|
end
|
321
323
|
|
322
324
|
# move to the start of this line
|
323
|
-
@context.move_to(x + linex, y + baseline - offset)
|
325
|
+
@context.move_to(x + linex, y + baseline - offset + spacing)
|
324
326
|
|
325
327
|
# draw the line on the canvas
|
326
328
|
@context.show_pango_layout_line(line)
|
@@ -328,10 +330,11 @@ module PDF
|
|
328
330
|
break unless iter.next_line!
|
329
331
|
end
|
330
332
|
|
333
|
+
width, height = layout.size
|
334
|
+
|
331
335
|
# return the y co-ord we finished on
|
332
|
-
return
|
336
|
+
return y + (height / Pango::SCALE) - offset + spacing
|
333
337
|
end
|
334
338
|
|
335
|
-
|
336
339
|
end
|
337
340
|
end
|
data/specs/image_spec.rb
CHANGED
@@ -29,5 +29,13 @@ context "The PDF::Wrapper class" do
|
|
29
29
|
pdf.calc_image_dimensions(300, 250, 200, 200, true).should eql([250.0,250.0])
|
30
30
|
end
|
31
31
|
|
32
|
+
specify "should be able to draw rotated images correctly" do
|
33
|
+
pdf = PDF::Wrapper.new
|
34
|
+
pdf.image(File.dirname(__FILE__) + "/data/shipsail.jpg", :rotate => :clockwise)
|
35
|
+
pdf.image(File.dirname(__FILE__) + "/data/shipsail.jpg", :rotate => :counterclockwise)
|
36
|
+
pdf.image(File.dirname(__FILE__) + "/data/shipsail.jpg", :rotate => :upsidedown)
|
37
|
+
pdf.image(File.dirname(__FILE__) + "/data/shipsail.jpg", :rotate => :none)
|
38
|
+
end
|
39
|
+
|
32
40
|
specify "should be able to draw an image with padding correctly"
|
33
41
|
end
|
data/specs/spec_helper.rb
CHANGED
@@ -6,7 +6,7 @@ require 'pdf/wrapper'
|
|
6
6
|
require 'tempfile'
|
7
7
|
require 'rubygems'
|
8
8
|
|
9
|
-
gem "pdf-reader", ">=0.
|
9
|
+
gem "pdf-reader", ">=0.7.3"
|
10
10
|
|
11
11
|
require 'pdf/reader'
|
12
12
|
|
@@ -27,7 +27,6 @@ class PDF::Wrapper
|
|
27
27
|
public :load_libpoppler
|
28
28
|
public :user_x_to_device_x
|
29
29
|
public :user_y_to_device_y
|
30
|
-
public :user_to_device_dist
|
31
30
|
public :device_x_to_user_x
|
32
31
|
public :device_y_to_user_y
|
33
32
|
public :validate_color
|
@@ -35,15 +34,15 @@ end
|
|
35
34
|
|
36
35
|
# a helper class for counting the number of pages in a PDF
|
37
36
|
class PageReceiver
|
38
|
-
attr_accessor :
|
37
|
+
attr_accessor :pages
|
39
38
|
|
40
39
|
def initialize
|
41
40
|
@page_count = 0
|
42
41
|
end
|
43
42
|
|
44
43
|
# Called when page parsing ends
|
45
|
-
def
|
46
|
-
@
|
44
|
+
def page_count(arg)
|
45
|
+
@pages = arg
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
data/specs/wrapper_spec.rb
CHANGED
@@ -92,16 +92,6 @@ context "The PDF::Wrapper class" do
|
|
92
92
|
y.to_i.should eql(100)
|
93
93
|
end
|
94
94
|
|
95
|
-
specify "should be able to move the cursor to any arbitary point on the canvas when scaled" do
|
96
|
-
pdf = PDF::Wrapper.new
|
97
|
-
pdf.scale(pdf.page_width, pdf.page_height) do
|
98
|
-
pdf.move_to(0.5, 0.5)
|
99
|
-
x,y = pdf.current_point
|
100
|
-
sprintf("%0.1f",x).should eql("0.5")
|
101
|
-
sprintf("%0.1f",y).should eql("0.5")
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
95
|
specify "should be able to shift the y position of the cursor using pad" do
|
106
96
|
pdf = PDF::Wrapper.new
|
107
97
|
pdf.move_to(100,100)
|
@@ -123,7 +113,7 @@ context "The PDF::Wrapper class" do
|
|
123
113
|
# verify the output
|
124
114
|
receiver = PageReceiver.new
|
125
115
|
reader = PDF::Reader.string(pdf.render, receiver)
|
126
|
-
receiver.
|
116
|
+
receiver.pages.should eql(2)
|
127
117
|
end
|
128
118
|
|
129
119
|
|
@@ -150,7 +140,7 @@ context "The PDF::Wrapper class" do
|
|
150
140
|
# write the PDF to a temp file
|
151
141
|
tmp = Tempfile.open("siftr")
|
152
142
|
tmp.close
|
153
|
-
pdf.
|
143
|
+
pdf.render_file(tmp.path)
|
154
144
|
|
155
145
|
# ensure an actual PDF was written out
|
156
146
|
File.open(tmp.path, "r") do |f|
|
@@ -175,7 +165,7 @@ context "The PDF::Wrapper class" do
|
|
175
165
|
test_str = "repeating"
|
176
166
|
|
177
167
|
pdf = PDF::Wrapper.new
|
178
|
-
pdf.repeating_element(:all) {
|
168
|
+
pdf.repeating_element(:all) { |page| page.text test_str }
|
179
169
|
|
180
170
|
pdf.start_new_page
|
181
171
|
pdf.start_new_page
|
@@ -195,7 +185,7 @@ context "The PDF::Wrapper class" do
|
|
195
185
|
test_str = "repeating"
|
196
186
|
|
197
187
|
pdf = PDF::Wrapper.new
|
198
|
-
pdf.repeating_element(:odd) {
|
188
|
+
pdf.repeating_element(:odd) { |page| page.text test_str }
|
199
189
|
|
200
190
|
pdf.start_new_page
|
201
191
|
pdf.start_new_page
|
@@ -215,7 +205,7 @@ context "The PDF::Wrapper class" do
|
|
215
205
|
test_str = "repeating"
|
216
206
|
|
217
207
|
pdf = PDF::Wrapper.new
|
218
|
-
pdf.repeating_element(:even) {
|
208
|
+
pdf.repeating_element(:even) { |page| page.text test_str }
|
219
209
|
|
220
210
|
pdf.start_new_page
|
221
211
|
pdf.start_new_page
|
@@ -235,7 +225,7 @@ context "The PDF::Wrapper class" do
|
|
235
225
|
test_str = "repeating"
|
236
226
|
|
237
227
|
pdf = PDF::Wrapper.new
|
238
|
-
pdf.repeating_element((2..3)) {
|
228
|
+
pdf.repeating_element((2..3)) { |page| page.text test_str }
|
239
229
|
|
240
230
|
pdf.start_new_page
|
241
231
|
pdf.start_new_page
|
@@ -255,7 +245,7 @@ context "The PDF::Wrapper class" do
|
|
255
245
|
test_str = "repeating"
|
256
246
|
|
257
247
|
pdf = PDF::Wrapper.new
|
258
|
-
pdf.repeating_element(2) {
|
248
|
+
pdf.repeating_element(2) { |page| page.text test_str }
|
259
249
|
|
260
250
|
pdf.start_new_page
|
261
251
|
pdf.start_new_page
|
@@ -275,7 +265,7 @@ context "The PDF::Wrapper class" do
|
|
275
265
|
test_str = "repeating"
|
276
266
|
|
277
267
|
pdf = PDF::Wrapper.new
|
278
|
-
pdf.repeating_element([1,3,4]) {
|
268
|
+
pdf.repeating_element([1,3,4]) { |page| page.text test_str }
|
279
269
|
|
280
270
|
pdf.start_new_page
|
281
271
|
pdf.start_new_page
|
@@ -292,6 +282,19 @@ context "The PDF::Wrapper class" do
|
|
292
282
|
end
|
293
283
|
|
294
284
|
specify "should not change the state of the cairo canvas or PDF::Writer defaults (fonts, colors, etc) when adding repeating elements"
|
285
|
+
|
286
|
+
specify "should not allow a new page to be started while adding repeating elements" do
|
287
|
+
test_str = "repeating"
|
288
|
+
|
289
|
+
pdf = PDF::Wrapper.new
|
290
|
+
lambda do
|
291
|
+
pdf.repeating_element([1,3,4]) do |page|
|
292
|
+
page.text test_str
|
293
|
+
page.start_new_page
|
294
|
+
end
|
295
|
+
end.should raise_error(InvalidOperationError)
|
296
|
+
|
297
|
+
end
|
295
298
|
|
296
299
|
specify "should leave the cursor on the bottom left corner of an object when using functions with optional positioning [func(data, opts)]" do
|
297
300
|
pdf = PDF::Wrapper.new
|
@@ -406,29 +409,6 @@ context "The PDF::Wrapper class" do
|
|
406
409
|
receiver.pages[1].should eql([0.0, 0.0, 734.0, 772.0])
|
407
410
|
end
|
408
411
|
|
409
|
-
specify "should return correct page dimensions when scaled" do
|
410
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
411
|
-
|
412
|
-
pdf.scale(595.28, 841.89) do
|
413
|
-
pdf.page_width.should eql(1.0)
|
414
|
-
pdf.page_height.should eql(1.0)
|
415
|
-
pdf.absolute_x_middle.should eql(0.5)
|
416
|
-
pdf.absolute_y_middle.should eql(0.5)
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
specify "should return correct body dimensions when scaled" do
|
421
|
-
pdf = PDF::Wrapper.new(:paper => :A4, :margin_top => 10, :margin_right => 10, :margin_bottom => 10, :margin_left => 10)
|
422
|
-
|
423
|
-
# scale so the dimensions of the body are 1,1
|
424
|
-
pdf.scale(595.28 - 20, 841.89 - 20) do
|
425
|
-
pdf.body_width.should eql(1.0)
|
426
|
-
pdf.body_height.should eql(1.0)
|
427
|
-
pdf.body_x_middle.should eql(0.5)
|
428
|
-
pdf.body_y_middle.should eql(0.5)
|
429
|
-
end
|
430
|
-
end
|
431
|
-
|
432
412
|
specify "should correctly convert a user x co-ordinate to device" do
|
433
413
|
pdf = PDF::Wrapper.new(:paper => :A4, :margin_left => 40)
|
434
414
|
|
@@ -439,11 +419,6 @@ context "The PDF::Wrapper class" do
|
|
439
419
|
# a user x co-ord of 10 is now equal to a device co-ord of 50
|
440
420
|
pdf.user_x_to_device_x(10).should eql(50.0)
|
441
421
|
end
|
442
|
-
|
443
|
-
# scale so the dimensions of the page are 1,1
|
444
|
-
pdf.scale(pdf.page_width, pdf.page_height) do
|
445
|
-
pdf.user_x_to_device_x(0.5).should eql(595.28/2)
|
446
|
-
end
|
447
422
|
end
|
448
423
|
|
449
424
|
specify "should correctly convert a user y co-ordinate to device" do
|
@@ -456,11 +431,6 @@ context "The PDF::Wrapper class" do
|
|
456
431
|
# a user y co-ord of 10 is now equal to a device co-ord of 50
|
457
432
|
pdf.user_y_to_device_y(10).should eql(50.0)
|
458
433
|
end
|
459
|
-
|
460
|
-
# scale so the dimensions of the page are 1,1
|
461
|
-
pdf.scale(pdf.page_width, pdf.page_height) do
|
462
|
-
pdf.user_y_to_device_y(0.5).should eql(841.89/2)
|
463
|
-
end
|
464
434
|
end
|
465
435
|
|
466
436
|
specify "should correctly convert a device x co-ordinate to user" do
|
@@ -472,11 +442,6 @@ context "The PDF::Wrapper class" do
|
|
472
442
|
pdf.translate(pdf.margin_left, pdf.margin_top) do
|
473
443
|
pdf.device_x_to_user_x(50).should eql(10.0)
|
474
444
|
end
|
475
|
-
|
476
|
-
# scale so the dimensions of the page are 1,1
|
477
|
-
pdf.scale(pdf.page_width, pdf.page_height) do
|
478
|
-
pdf.device_x_to_user_x(595.28/2).should eql(0.5)
|
479
|
-
end
|
480
445
|
end
|
481
446
|
|
482
447
|
specify "should correctly convert a device y co-ordinate to user" do
|
@@ -488,29 +453,20 @@ context "The PDF::Wrapper class" do
|
|
488
453
|
pdf.translate(pdf.margin_left, pdf.margin_top) do
|
489
454
|
pdf.device_y_to_user_y(50).should eql(10.0)
|
490
455
|
end
|
491
|
-
|
492
|
-
# scale so the dimensions of the page are 1,1
|
493
|
-
pdf.scale(pdf.page_width, pdf.page_height) do
|
494
|
-
pdf.device_y_to_user_y(841.89/2).should eql(0.5)
|
495
|
-
end
|
496
456
|
end
|
497
457
|
|
498
|
-
specify "should
|
499
|
-
pdf = PDF::Wrapper.new
|
500
|
-
|
501
|
-
pdf.
|
502
|
-
pdf.
|
503
|
-
|
504
|
-
# translate so that 0,0 is at the page body corner
|
505
|
-
pdf.translate(pdf.margin_left, pdf.margin_top) do
|
506
|
-
pdf.user_to_device_dist(10,0).should eql([10.0,0.0])
|
507
|
-
pdf.user_to_device_dist(0,10).should eql([0.0,10.0])
|
508
|
-
end
|
458
|
+
specify "should allow Wrapper#render to be called multiple times" do
|
459
|
+
pdf = PDF::Wrapper.new
|
460
|
+
pdf.text "Hi!"
|
461
|
+
pdf.render.should be_a_kind_of(String)
|
462
|
+
pdf.render.should be_a_kind_of(String)
|
463
|
+
end
|
509
464
|
|
510
|
-
|
511
|
-
pdf
|
512
|
-
|
513
|
-
|
514
|
-
|
465
|
+
specify "should be aware of when the underlying PDFSurface has been finished" do
|
466
|
+
pdf = PDF::Wrapper.new
|
467
|
+
pdf.text "Hi!"
|
468
|
+
pdf.finished?.should be_false
|
469
|
+
pdf.render
|
470
|
+
pdf.finished?.should be_true
|
515
471
|
end
|
516
472
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pdf-wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Healy
|
@@ -9,10 +9,19 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-07-28 00:00:00 +10:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: cairo
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.5.0
|
24
|
+
version:
|
16
25
|
description: A unicode aware PDF writing library that uses the ruby bindings to various c libraries ( like cairo, pango, poppler and rsvg ) to do the heavy lifting.
|
17
26
|
email: jimmy@deefa.com
|
18
27
|
executables: []
|
@@ -20,7 +29,7 @@ executables: []
|
|
20
29
|
extensions: []
|
21
30
|
|
22
31
|
extra_rdoc_files:
|
23
|
-
- README
|
32
|
+
- README.rdoc
|
24
33
|
- CHANGELOG
|
25
34
|
- TODO
|
26
35
|
files:
|
@@ -28,21 +37,22 @@ files:
|
|
28
37
|
- examples/image.rb
|
29
38
|
- examples/markup.rb
|
30
39
|
- examples/repeating.rb
|
31
|
-
- examples/
|
32
|
-
- examples/scaled_cells.rb
|
33
|
-
- examples/scaled_image.rb
|
40
|
+
- examples/utf8-long.rb
|
34
41
|
- examples/shapes.rb
|
35
42
|
- examples/table.rb
|
43
|
+
- examples/scaled_image.rb
|
36
44
|
- examples/translate.rb
|
37
|
-
- examples/utf8-long.rb
|
38
45
|
- examples/utf8.rb
|
46
|
+
- examples/text.rb
|
39
47
|
- lib/pdf
|
40
48
|
- lib/pdf/core.rb
|
41
49
|
- lib/pdf/wrapper.rb
|
50
|
+
- lib/pdf/errors.rb
|
42
51
|
- lib/pdf/wrapper
|
43
52
|
- lib/pdf/wrapper/graphics.rb
|
44
53
|
- lib/pdf/wrapper/images.rb
|
45
54
|
- lib/pdf/wrapper/loading.rb
|
55
|
+
- lib/pdf/wrapper/page.rb
|
46
56
|
- lib/pdf/wrapper/table.rb
|
47
57
|
- lib/pdf/wrapper/text.rb
|
48
58
|
- specs/data
|
@@ -57,15 +67,15 @@ files:
|
|
57
67
|
- specs/data/utf8.txt
|
58
68
|
- specs/data/windmill.jpg
|
59
69
|
- specs/data/zits.gif
|
60
|
-
- specs/
|
70
|
+
- specs/spec_helper.rb
|
61
71
|
- specs/image_spec.rb
|
62
72
|
- specs/load_spec.rb
|
63
|
-
- specs/spec_helper.rb
|
64
73
|
- specs/tables_spec.rb
|
65
74
|
- specs/text_spec.rb
|
66
75
|
- specs/wrapper_spec.rb
|
76
|
+
- specs/graphics_spec.rb
|
67
77
|
- Rakefile
|
68
|
-
- README
|
78
|
+
- README.rdoc
|
69
79
|
- CHANGELOG
|
70
80
|
- TODO
|
71
81
|
has_rdoc: true
|
@@ -75,7 +85,7 @@ rdoc_options:
|
|
75
85
|
- --title
|
76
86
|
- PDF::Wrapper Documentation
|
77
87
|
- --main
|
78
|
-
- README
|
88
|
+
- README.rdoc
|
79
89
|
- -q
|
80
90
|
require_paths:
|
81
91
|
- lib
|
@@ -94,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
104
|
requirements: []
|
95
105
|
|
96
106
|
rubyforge_project: pdf-wrapper
|
97
|
-
rubygems_version: 1.
|
107
|
+
rubygems_version: 1.2.0
|
98
108
|
signing_key:
|
99
109
|
specification_version: 2
|
100
110
|
summary: A PDF generating library built on top of cairo
|
data/examples/scaled.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# coding: utf-8
|
3
|
-
|
4
|
-
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
5
|
-
|
6
|
-
require 'pdf/wrapper'
|
7
|
-
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
9
|
-
pdf.line_width = 2
|
10
|
-
|
11
|
-
# grid lines
|
12
|
-
pdf.line(50, 0, 50, pdf.page_height)
|
13
|
-
pdf.line(100, 0, 100, pdf.page_height)
|
14
|
-
pdf.line(150, 0, 150, pdf.page_height)
|
15
|
-
pdf.line(200, 0, 200, pdf.page_height)
|
16
|
-
pdf.line(0, 50, pdf.page_width, 50)
|
17
|
-
pdf.line(0, 100, pdf.page_width, 100)
|
18
|
-
pdf.line(0, 150, pdf.page_width, 150)
|
19
|
-
pdf.line(0, 200, pdf.page_width, 200)
|
20
|
-
|
21
|
-
# non scaled
|
22
|
-
pdf.rectangle(100,100,100,100, :fill_color => :green)
|
23
|
-
|
24
|
-
# scaled
|
25
|
-
pdf.scale(pdf.page_width.to_f, pdf.page_height.to_f) do
|
26
|
-
# top left corner 10% of the page width from the left and top of the page.
|
27
|
-
# width 10% of the page width
|
28
|
-
# height 10% of the page height
|
29
|
-
# - obviously will not be square on a A4 page
|
30
|
-
pdf.rectangle(0.1,0.1,0.1,0.1, :fill_color => :red)
|
31
|
-
pdf.text("boo!", :top => 0.5, :left => 0.2, :width => 0.6)
|
32
|
-
end
|
33
|
-
|
34
|
-
#pdf.text("boo2!", :top => 500, :left => 100)
|
35
|
-
|
36
|
-
|
37
|
-
# show results
|
38
|
-
pdf.render_to_file("scaled.pdf")
|
data/examples/scaled_cells.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# coding: utf-8
|
3
|
-
|
4
|
-
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
5
|
-
|
6
|
-
require 'pdf/wrapper'
|
7
|
-
|
8
|
-
pdf = PDF::Wrapper.new(:paper => :A4)
|
9
|
-
pdf.font("Sans Serif")
|
10
|
-
pdf.line_width(0.1)
|
11
|
-
# naglowek
|
12
|
-
pdf.translate(pdf.absolute_left_margin, pdf.absolute_top_margin) do
|
13
|
-
pdf.scale(pdf.body_width, pdf.body_width) do
|
14
|
-
pdf.cell("Exorigo", 0, 0, 0.2, 0.05, :alignment => :center, :font_size => 15)
|
15
|
-
pdf.cell("Zamówienie nr PO/0000/01/01/2008", 0.2, 0, 0.8, 0.05, :fill_color => :gray, :alignment => :center)
|
16
|
-
pdf.cell("imię i naziwsko osoby zamawiającej. NALEŻY PODAĆ NA FAKTURZE", 0, 0.05, 0.55, 0.025, :font_size => 6)
|
17
|
-
pdf.cell("data zamówienia", 0.55, 0.05, 0.15, 0.025, :font_size => 6)
|
18
|
-
pdf.cell("POWYŻSZY NUMER ZAMÓWIENIA NALEŻY PODAĆ NA FAKTURZE", 0.7, 0.05, 0.3, 0.05, :font_size => 6, :alignment => :center, :spacing => 4)
|
19
|
-
pdf.cell("Jan Kowalski", 0, 0.075, 0.55, 0.025, :font => "Sans Serif bold", :font_size => 8)
|
20
|
-
pdf.cell("22.01.2008", 0.55, 0.075, 0.15, 0.025, :font => "Sans Serif bold", :font_size => 8)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
# dane dostawcy
|
24
|
-
|
25
|
-
# szczegoly zamowienia
|
26
|
-
|
27
|
-
# autoryzacja
|
28
|
-
|
29
|
-
# adres
|
30
|
-
pdf.render_to_file("scaled-cells.pdf")
|