pdf_tempura 0.0.2
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.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +342 -0
- data/Rakefile +1 -0
- data/example/my_pdf.rb +37 -0
- data/lib/pdf_tempura.rb +8 -0
- data/lib/pdf_tempura/document.rb +121 -0
- data/lib/pdf_tempura/document/boxed_characters.rb +70 -0
- data/lib/pdf_tempura/document/boxed_characters/groups.rb +53 -0
- data/lib/pdf_tempura/document/character_field.rb +37 -0
- data/lib/pdf_tempura/document/checkbox_field.rb +15 -0
- data/lib/pdf_tempura/document/default_commands.rb +40 -0
- data/lib/pdf_tempura/document/field/base.rb +55 -0
- data/lib/pdf_tempura/document/field_set.rb +51 -0
- data/lib/pdf_tempura/document/page.rb +33 -0
- data/lib/pdf_tempura/document/table.rb +95 -0
- data/lib/pdf_tempura/document/table/boxed_character_column.rb +20 -0
- data/lib/pdf_tempura/document/table/checkbox_column.rb +9 -0
- data/lib/pdf_tempura/document/table/column.rb +18 -0
- data/lib/pdf_tempura/document/table/spacer.rb +13 -0
- data/lib/pdf_tempura/document/table/text_column.rb +9 -0
- data/lib/pdf_tempura/document/text_field.rb +18 -0
- data/lib/pdf_tempura/document/validation.rb +79 -0
- data/lib/pdf_tempura/extensions/hash/stringify_keys.rb +35 -0
- data/lib/pdf_tempura/render.rb +18 -0
- data/lib/pdf_tempura/render/boxed_characters.rb +42 -0
- data/lib/pdf_tempura/render/character_field.rb +49 -0
- data/lib/pdf_tempura/render/checkbox_field.rb +35 -0
- data/lib/pdf_tempura/render/debug.rb +16 -0
- data/lib/pdf_tempura/render/debug/annotation/base.rb +83 -0
- data/lib/pdf_tempura/render/debug/character_field_annotation.rb +13 -0
- data/lib/pdf_tempura/render/debug/checkbox_field_annotation.rb +24 -0
- data/lib/pdf_tempura/render/debug/field_set_annotation.rb +23 -0
- data/lib/pdf_tempura/render/debug/grid.rb +59 -0
- data/lib/pdf_tempura/render/debug/outside_annotation.rb +42 -0
- data/lib/pdf_tempura/render/debug/table_annotation.rb +19 -0
- data/lib/pdf_tempura/render/debug/text_field_annotation.rb +42 -0
- data/lib/pdf_tempura/render/field.rb +40 -0
- data/lib/pdf_tempura/render/field_bounds.rb +26 -0
- data/lib/pdf_tempura/render/field_data_mapper.rb +15 -0
- data/lib/pdf_tempura/render/field_set.rb +31 -0
- data/lib/pdf_tempura/render/option_access.rb +21 -0
- data/lib/pdf_tempura/render/page.rb +23 -0
- data/lib/pdf_tempura/render/table.rb +35 -0
- data/lib/pdf_tempura/render/text_field.rb +13 -0
- data/lib/pdf_tempura/renderer.rb +39 -0
- data/lib/pdf_tempura/version.rb +3 -0
- data/pdf_tempura.gemspec +27 -0
- data/spec/assets/sample_pdf_form.odg +0 -0
- data/spec/assets/sample_pdf_form.pdf +0 -0
- data/spec/integration_spec.rb +88 -0
- data/spec/lib/pdf_tempura/document/boxed_characters_spec.rb +125 -0
- data/spec/lib/pdf_tempura/document/checkbox_field_spec.rb +54 -0
- data/spec/lib/pdf_tempura/document/field_common.rb +12 -0
- data/spec/lib/pdf_tempura/document/field_set_spec.rb +38 -0
- data/spec/lib/pdf_tempura/document/page_spec.rb +57 -0
- data/spec/lib/pdf_tempura/document/table_spec.rb +161 -0
- data/spec/lib/pdf_tempura/document/text_field_spec.rb +195 -0
- data/spec/lib/pdf_tempura/document_spec.rb +131 -0
- data/spec/lib/pdf_tempura/extensions/hash/stringify_keys_spec.rb +42 -0
- data/spec/lib/pdf_tempura/render/boxed_characters_spec.rb +68 -0
- data/spec/lib/pdf_tempura/render/checkbox_field_spec.rb +39 -0
- data/spec/lib/pdf_tempura/render/debug/annotation_renderer/base_spec.rb +45 -0
- data/spec/lib/pdf_tempura/render/debug/checkbox_field_annotation_spec.rb +45 -0
- data/spec/lib/pdf_tempura/render/debug/grid_spec.rb +15 -0
- data/spec/lib/pdf_tempura/render/debug/text_field_annotation_spec.rb +46 -0
- data/spec/lib/pdf_tempura/render/field_data_mapper_spec.rb +31 -0
- data/spec/lib/pdf_tempura/render/field_set_spec.rb +41 -0
- data/spec/lib/pdf_tempura/render/field_spec.rb +37 -0
- data/spec/lib/pdf_tempura/render/page_spec.rb +77 -0
- data/spec/lib/pdf_tempura/render/table_spec.rb +44 -0
- data/spec/lib/pdf_tempura/render/text_field_spec.rb +39 -0
- data/spec/lib/pdf_tempura/renderer_spec.rb +79 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/shared_examples/field_examples.rb +265 -0
- metadata +219 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
class CheckboxField < Field
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def set_styling(pdf)
|
8
|
+
pdf.fill_color = "000000"
|
9
|
+
pdf.font "Courier", style: :normal
|
10
|
+
end
|
11
|
+
|
12
|
+
def render_field(pdf)
|
13
|
+
field_bounds_box(pdf) do
|
14
|
+
padding_bounds_box(pdf) do
|
15
|
+
pdf.text_box("X", field_options) if @value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def field_options
|
21
|
+
{
|
22
|
+
valign: :center,
|
23
|
+
align: :center,
|
24
|
+
single_line: true,
|
25
|
+
size: @field.height
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_debug_annotation(pdf)
|
30
|
+
Debug::CheckboxFieldAnnotation.new(@field).render(pdf)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module Debug
|
4
|
+
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require_relative 'debug/annotation/base'
|
10
|
+
require_relative 'debug/character_field_annotation'
|
11
|
+
require_relative 'debug/checkbox_field_annotation'
|
12
|
+
require_relative 'debug/outside_annotation'
|
13
|
+
require_relative 'debug/text_field_annotation'
|
14
|
+
require_relative 'debug/grid'
|
15
|
+
require_relative 'debug/field_set_annotation'
|
16
|
+
require_relative 'debug/table_annotation'
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module Debug::Annotation
|
4
|
+
class Base
|
5
|
+
include Render::FieldBounds
|
6
|
+
|
7
|
+
def initialize(field)
|
8
|
+
@field = field
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(pdf)
|
12
|
+
set_field_styling(pdf)
|
13
|
+
render_boxes(pdf)
|
14
|
+
render_text(pdf)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_field_styling(pdf)
|
20
|
+
pdf.font_size = 7
|
21
|
+
pdf.fill_color = "000066"
|
22
|
+
pdf.line_width = 0.5
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_text(pdf)
|
26
|
+
field_bounds_box(pdf) do
|
27
|
+
render_xy(pdf)
|
28
|
+
render_label(pdf)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def render_xy(pdf)
|
33
|
+
pdf.text_box "x: #{@field.x} y: #{@field.y} w: #{@field.width} h: #{@field.height}", field_options
|
34
|
+
end
|
35
|
+
|
36
|
+
def render_label(pdf)
|
37
|
+
pdf.text_box "#{@field.name}", label_options
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_boxes(pdf)
|
41
|
+
pdf.transparent 0.5 do
|
42
|
+
field_bounds_box(pdf) do
|
43
|
+
draw_box_border(pdf, box_color)
|
44
|
+
fill_box_color(pdf, box_color)
|
45
|
+
draw_padding(pdf)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def box_color
|
51
|
+
"CCCC33"
|
52
|
+
end
|
53
|
+
|
54
|
+
def draw_box_border(pdf, color)
|
55
|
+
pdf.stroke_color = color
|
56
|
+
pdf.stroke_bounds
|
57
|
+
end
|
58
|
+
|
59
|
+
def fill_box_color(pdf, color)
|
60
|
+
pdf.fill_color = color
|
61
|
+
pdf.fill{ pdf.rectangle [0,pdf.bounds.height], pdf.bounds.width, pdf.bounds.height }
|
62
|
+
end
|
63
|
+
|
64
|
+
def draw_padding(pdf)
|
65
|
+
pdf.transparent 0.25 do
|
66
|
+
padding_bounds_box(pdf) do
|
67
|
+
draw_box_border(pdf, "0000CC")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def field_options
|
73
|
+
raise NotImplementedError, "Implement field_options in your subclass."
|
74
|
+
end
|
75
|
+
|
76
|
+
def label_options
|
77
|
+
raise NotImplementedError, "Implement label_options in your subclass."
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'outside_annotation'
|
2
|
+
|
3
|
+
module PdfTempura
|
4
|
+
module Render
|
5
|
+
module Debug
|
6
|
+
class CheckboxFieldAnnotation < OutsideAnnotation
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def coordinate_offsets
|
11
|
+
{
|
12
|
+
xy: [1,16],
|
13
|
+
label: [1,-9]
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def label_options
|
18
|
+
super.merge(align: :left)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module Debug
|
4
|
+
class FieldSetAnnotation < OutsideAnnotation
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def box_color
|
9
|
+
"66CCFF"
|
10
|
+
end
|
11
|
+
|
12
|
+
def render_xy(pdf)
|
13
|
+
#don't render an xy label for this annotation
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_label(pdf)
|
17
|
+
pdf.text_box "fieldset: #{@field.name}", label_options
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module Debug
|
4
|
+
class Grid
|
5
|
+
|
6
|
+
def render(pdf)
|
7
|
+
set_styling(pdf)
|
8
|
+
render_grid(pdf)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def set_styling(pdf)
|
14
|
+
pdf.stroke_color = "000000"
|
15
|
+
pdf.fill_color = "000000"
|
16
|
+
pdf.line_width = 0.5
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_grid(pdf)
|
20
|
+
pdf.transparent(0.125) do
|
21
|
+
render_vertical_lines(pdf)
|
22
|
+
render_horizontal_lines(pdf)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_vertical_lines(pdf)
|
27
|
+
line_loop(pdf.bounds.width, 25) do |x|
|
28
|
+
vertical_line_with_label pdf, x
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def render_horizontal_lines(pdf)
|
33
|
+
line_loop(pdf.bounds.height, 25) do |y|
|
34
|
+
horizontal_line_with_label pdf, y
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def line_loop(max, increment)
|
39
|
+
(0 .. max).step(increment){ |n| yield(n) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def vertical_line_with_label(pdf, x)
|
43
|
+
pdf.stroke do
|
44
|
+
pdf.line([x, 0], [x, pdf.bounds.height])
|
45
|
+
pdf.draw_text x.to_s, at: [x+3, 3], size: 6
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def horizontal_line_with_label(pdf, y)
|
50
|
+
pdf.stroke do
|
51
|
+
pdf.line([0, y], [pdf.bounds.width, y])
|
52
|
+
pdf.draw_text y.to_s, at: [3, y+3], size: 6
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module Debug
|
4
|
+
class OutsideAnnotation < Annotation::Base
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def coordinate_offsets
|
9
|
+
{
|
10
|
+
xy: [1,8],
|
11
|
+
label: [1,-9]
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_options
|
16
|
+
off = coordinate_offsets[:xy]
|
17
|
+
|
18
|
+
{
|
19
|
+
at: [off[0], @field.height + off[1]],
|
20
|
+
width: @field.width * 4,
|
21
|
+
height: @field.height - 2,
|
22
|
+
valign: :top
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def label_options
|
27
|
+
off = coordinate_offsets[:label]
|
28
|
+
|
29
|
+
{
|
30
|
+
at: [off[0], @field.height + off[1]],
|
31
|
+
width: @field.width - 2,
|
32
|
+
height: @field.height - 2,
|
33
|
+
valign: :bottom,
|
34
|
+
align: :right,
|
35
|
+
single_line: true
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module Debug
|
4
|
+
class TextFieldAnnotation < Annotation::Base
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def coordinate_offsets
|
9
|
+
{
|
10
|
+
xy: [1,-1],
|
11
|
+
label: [1,-1]
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_options
|
16
|
+
off = coordinate_offsets[:xy]
|
17
|
+
|
18
|
+
{
|
19
|
+
at: [off[0], @field.height + off[1]],
|
20
|
+
width: @field.width - 2,
|
21
|
+
height: @field.height - 2,
|
22
|
+
valign: :top,
|
23
|
+
single_line: true
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def label_options
|
28
|
+
off = coordinate_offsets[:label]
|
29
|
+
{
|
30
|
+
at: [off[0], @field.height + off[1]],
|
31
|
+
width: @field.width - 2,
|
32
|
+
height: @field.height - 2,
|
33
|
+
valign: :bottom,
|
34
|
+
align: :right,
|
35
|
+
single_line: true
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
class Field
|
4
|
+
include OptionAccess
|
5
|
+
include FieldBounds
|
6
|
+
|
7
|
+
def self.generate(field, value, options)
|
8
|
+
case field
|
9
|
+
when Document::CheckboxField
|
10
|
+
CheckboxField.new(field, value, options)
|
11
|
+
when Document::TextField
|
12
|
+
TextField.new(field, value, options)
|
13
|
+
when Document::CharacterField
|
14
|
+
CharacterField.new(field, value, options)
|
15
|
+
when Document::BoxedCharacters
|
16
|
+
BoxedCharacters.new(field, value, options)
|
17
|
+
when Document::Table
|
18
|
+
Table.new(field, value, options)
|
19
|
+
when Document::FieldSet
|
20
|
+
FieldSet.new(field, value, options)
|
21
|
+
else
|
22
|
+
raise ArgumentError, "don't know how to handle field kind: #{field.class}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(field, value, options = {})
|
27
|
+
@field = field
|
28
|
+
@value = value
|
29
|
+
@options = options
|
30
|
+
end
|
31
|
+
|
32
|
+
def render(pdf)
|
33
|
+
set_styling(pdf)
|
34
|
+
render_field(pdf)
|
35
|
+
render_debug_annotation(pdf) if draw_outlines?
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PdfTempura
|
2
|
+
module Render
|
3
|
+
module FieldBounds
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def field_bounds_box(pdf)
|
8
|
+
pdf.bounding_box([@field.x, @field.y], width: @field.width, height: @field.height) do
|
9
|
+
yield
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def padding_bounds_box(pdf)
|
14
|
+
x = @field.padding[3]
|
15
|
+
y = pdf.bounds.height - @field.padding[0]
|
16
|
+
width = pdf.bounds.width - @field.padding[1] - @field.padding[3]
|
17
|
+
height = pdf.bounds.height - @field.padding[0] - @field.padding[2]
|
18
|
+
|
19
|
+
pdf.bounding_box([x,y], width: width, height: height) do
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|