thinreports 0.12.1 → 0.13.0
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 +4 -4
- data/.github/dependabot.yml +3 -3
- data/.github/workflows/test.yml +28 -36
- data/.gitignore +1 -1
- data/CHANGELOG.md +19 -1
- data/Gemfile +11 -0
- data/README.md +12 -17
- data/Rakefile +17 -11
- data/lib/thinreports/basic_report/core/errors.rb +62 -0
- data/lib/thinreports/basic_report/core/format/base.rb +91 -0
- data/lib/thinreports/basic_report/core/shape/base/interface.rb +42 -0
- data/lib/thinreports/basic_report/core/shape/base/internal.rb +53 -0
- data/lib/thinreports/basic_report/core/shape/basic/block_format.rb +15 -0
- data/lib/thinreports/basic_report/core/shape/basic/block_interface.rb +34 -0
- data/lib/thinreports/basic_report/core/shape/basic/block_internal.rb +36 -0
- data/lib/thinreports/basic_report/core/shape/basic/format.rb +24 -0
- data/lib/thinreports/basic_report/core/shape/basic/interface.rb +87 -0
- data/lib/thinreports/basic_report/core/shape/basic/internal.rb +28 -0
- data/lib/thinreports/{core → basic_report/core}/shape/basic.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/image_block/format.rb +14 -0
- data/lib/thinreports/basic_report/core/shape/image_block/interface.rb +25 -0
- data/lib/thinreports/basic_report/core/shape/image_block/internal.rb +19 -0
- data/lib/thinreports/{core → basic_report/core}/shape/image_block.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/list/format.rb +92 -0
- data/lib/thinreports/basic_report/core/shape/list/manager.rb +231 -0
- data/lib/thinreports/basic_report/core/shape/list/page.rb +112 -0
- data/lib/thinreports/basic_report/core/shape/list/page_state.rb +50 -0
- data/lib/thinreports/basic_report/core/shape/list/section_format.rb +37 -0
- data/lib/thinreports/basic_report/core/shape/list/section_interface.rb +51 -0
- data/lib/thinreports/basic_report/core/shape/list/section_internal.rb +33 -0
- data/lib/thinreports/{core → basic_report/core}/shape/list.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/manager/format.rb +33 -0
- data/lib/thinreports/basic_report/core/shape/manager/internal.rb +109 -0
- data/lib/thinreports/basic_report/core/shape/manager/target.rb +114 -0
- data/lib/thinreports/basic_report/core/shape/page_number/format.rb +32 -0
- data/lib/thinreports/basic_report/core/shape/page_number/interface.rb +31 -0
- data/lib/thinreports/basic_report/core/shape/page_number/internal.rb +57 -0
- data/lib/thinreports/{core → basic_report/core}/shape/page_number.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/stack_view/format.rb +29 -0
- data/lib/thinreports/basic_report/core/shape/stack_view/interface.rb +19 -0
- data/lib/thinreports/basic_report/core/shape/stack_view/internal.rb +24 -0
- data/lib/thinreports/basic_report/core/shape/stack_view/row_format.rb +41 -0
- data/lib/thinreports/{core → basic_report/core}/shape/stack_view.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/style/base.rb +149 -0
- data/lib/thinreports/basic_report/core/shape/style/basic.rb +24 -0
- data/lib/thinreports/basic_report/core/shape/style/graphic.rb +43 -0
- data/lib/thinreports/basic_report/core/shape/style/text.rb +122 -0
- data/lib/thinreports/basic_report/core/shape/text/format.rb +17 -0
- data/lib/thinreports/basic_report/core/shape/text/interface.rb +20 -0
- data/lib/thinreports/basic_report/core/shape/text/internal.rb +24 -0
- data/lib/thinreports/{core → basic_report/core}/shape/text.rb +6 -4
- data/lib/thinreports/basic_report/core/shape/text_block/format.rb +43 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/basic.rb +41 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/datetime.rb +25 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/number.rb +69 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter/padding.rb +27 -0
- data/lib/thinreports/basic_report/core/shape/text_block/formatter.rb +38 -0
- data/lib/thinreports/basic_report/core/shape/text_block/interface.rb +37 -0
- data/lib/thinreports/basic_report/core/shape/text_block/internal.rb +75 -0
- data/lib/thinreports/{core → basic_report/core}/shape/text_block.rb +6 -4
- data/lib/thinreports/basic_report/core/shape.rb +44 -0
- data/lib/thinreports/basic_report/core/utils.rb +47 -0
- data/lib/thinreports/basic_report/generator/pdf/document/draw_shape.rb +108 -0
- data/lib/thinreports/basic_report/generator/pdf/document/draw_template_items.rb +71 -0
- data/lib/thinreports/basic_report/generator/pdf/document/font.rb +90 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/attributes.rb +149 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/basic.rb +137 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/image.rb +99 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics/text.rb +180 -0
- data/lib/thinreports/basic_report/generator/pdf/document/graphics.rb +42 -0
- data/lib/thinreports/basic_report/generator/pdf/document/page.rb +96 -0
- data/lib/thinreports/basic_report/generator/pdf/document/parse_color.rb +51 -0
- data/lib/thinreports/basic_report/generator/pdf/document.rb +132 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/base.rb +50 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/list.rb +65 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/list_section.rb +51 -0
- data/lib/thinreports/basic_report/generator/pdf/drawer/page.rb +127 -0
- data/lib/thinreports/basic_report/generator/pdf/prawn_ext/calc_image_dimensions.rb +34 -0
- data/lib/thinreports/basic_report/generator/pdf/prawn_ext/width_of.rb +31 -0
- data/lib/thinreports/basic_report/generator/pdf.rb +66 -0
- data/lib/thinreports/basic_report/layout/base.rb +48 -0
- data/lib/thinreports/basic_report/layout/format.rb +67 -0
- data/lib/thinreports/basic_report/layout/legacy_schema.rb +383 -0
- data/lib/thinreports/basic_report/layout/version.rb +41 -0
- data/lib/thinreports/{layout.rb → basic_report/layout.rb} +6 -4
- data/lib/thinreports/basic_report/report/base.rb +173 -0
- data/lib/thinreports/basic_report/report/internal.rb +107 -0
- data/lib/thinreports/basic_report/report/page.rb +97 -0
- data/lib/thinreports/basic_report/report.rb +26 -0
- data/lib/thinreports/basic_report.rb +15 -0
- data/lib/thinreports/config.rb +1 -1
- data/lib/thinreports/section_report.rb +12 -0
- data/lib/thinreports/version.rb +1 -1
- data/lib/thinreports.rb +2 -13
- data/thinreports.gemspec +3 -7
- metadata +97 -154
- data/gemfiles/prawn-2.2.gemfile +0 -5
- data/gemfiles/prawn-2.3.gemfile +0 -5
- data/gemfiles/prawn-2.4.gemfile +0 -5
- data/lib/thinreports/core/errors.rb +0 -60
- data/lib/thinreports/core/format/base.rb +0 -89
- data/lib/thinreports/core/shape/base/interface.rb +0 -40
- data/lib/thinreports/core/shape/base/internal.rb +0 -51
- data/lib/thinreports/core/shape/basic/block_format.rb +0 -13
- data/lib/thinreports/core/shape/basic/block_interface.rb +0 -32
- data/lib/thinreports/core/shape/basic/block_internal.rb +0 -34
- data/lib/thinreports/core/shape/basic/format.rb +0 -22
- data/lib/thinreports/core/shape/basic/interface.rb +0 -85
- data/lib/thinreports/core/shape/basic/internal.rb +0 -26
- data/lib/thinreports/core/shape/image_block/format.rb +0 -12
- data/lib/thinreports/core/shape/image_block/interface.rb +0 -23
- data/lib/thinreports/core/shape/image_block/internal.rb +0 -17
- data/lib/thinreports/core/shape/list/format.rb +0 -90
- data/lib/thinreports/core/shape/list/manager.rb +0 -229
- data/lib/thinreports/core/shape/list/page.rb +0 -110
- data/lib/thinreports/core/shape/list/page_state.rb +0 -48
- data/lib/thinreports/core/shape/list/section_format.rb +0 -35
- data/lib/thinreports/core/shape/list/section_interface.rb +0 -49
- data/lib/thinreports/core/shape/list/section_internal.rb +0 -31
- data/lib/thinreports/core/shape/manager/format.rb +0 -31
- data/lib/thinreports/core/shape/manager/internal.rb +0 -107
- data/lib/thinreports/core/shape/manager/target.rb +0 -112
- data/lib/thinreports/core/shape/page_number/format.rb +0 -30
- data/lib/thinreports/core/shape/page_number/interface.rb +0 -29
- data/lib/thinreports/core/shape/page_number/internal.rb +0 -55
- data/lib/thinreports/core/shape/stack_view/format.rb +0 -27
- data/lib/thinreports/core/shape/stack_view/interface.rb +0 -17
- data/lib/thinreports/core/shape/stack_view/internal.rb +0 -22
- data/lib/thinreports/core/shape/stack_view/row_format.rb +0 -39
- data/lib/thinreports/core/shape/style/base.rb +0 -146
- data/lib/thinreports/core/shape/style/basic.rb +0 -22
- data/lib/thinreports/core/shape/style/graphic.rb +0 -41
- data/lib/thinreports/core/shape/style/text.rb +0 -120
- data/lib/thinreports/core/shape/text/format.rb +0 -15
- data/lib/thinreports/core/shape/text/interface.rb +0 -18
- data/lib/thinreports/core/shape/text/internal.rb +0 -22
- data/lib/thinreports/core/shape/text_block/format.rb +0 -41
- data/lib/thinreports/core/shape/text_block/formatter/basic.rb +0 -39
- data/lib/thinreports/core/shape/text_block/formatter/datetime.rb +0 -23
- data/lib/thinreports/core/shape/text_block/formatter/number.rb +0 -67
- data/lib/thinreports/core/shape/text_block/formatter/padding.rb +0 -25
- data/lib/thinreports/core/shape/text_block/formatter.rb +0 -34
- data/lib/thinreports/core/shape/text_block/interface.rb +0 -35
- data/lib/thinreports/core/shape/text_block/internal.rb +0 -73
- data/lib/thinreports/core/shape.rb +0 -42
- data/lib/thinreports/core/utils.rb +0 -45
- data/lib/thinreports/generate.rb +0 -11
- data/lib/thinreports/generator/pdf/document/draw_shape.rb +0 -106
- data/lib/thinreports/generator/pdf/document/draw_template_items.rb +0 -69
- data/lib/thinreports/generator/pdf/document/font.rb +0 -88
- data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +0 -147
- data/lib/thinreports/generator/pdf/document/graphics/basic.rb +0 -135
- data/lib/thinreports/generator/pdf/document/graphics/image.rb +0 -98
- data/lib/thinreports/generator/pdf/document/graphics/text.rb +0 -178
- data/lib/thinreports/generator/pdf/document/graphics.rb +0 -40
- data/lib/thinreports/generator/pdf/document/page.rb +0 -94
- data/lib/thinreports/generator/pdf/document/parse_color.rb +0 -49
- data/lib/thinreports/generator/pdf/document.rb +0 -130
- data/lib/thinreports/generator/pdf/drawer/base.rb +0 -48
- data/lib/thinreports/generator/pdf/drawer/list.rb +0 -63
- data/lib/thinreports/generator/pdf/drawer/list_section.rb +0 -49
- data/lib/thinreports/generator/pdf/drawer/page.rb +0 -125
- data/lib/thinreports/generator/pdf/prawn_ext/calc_image_dimensions.rb +0 -32
- data/lib/thinreports/generator/pdf/prawn_ext/width_of.rb +0 -29
- data/lib/thinreports/generator/pdf.rb +0 -63
- data/lib/thinreports/layout/base.rb +0 -46
- data/lib/thinreports/layout/format.rb +0 -65
- data/lib/thinreports/layout/legacy_schema.rb +0 -381
- data/lib/thinreports/layout/version.rb +0 -39
- data/lib/thinreports/report/base.rb +0 -169
- data/lib/thinreports/report/internal.rb +0 -105
- data/lib/thinreports/report/page.rb +0 -95
- data/lib/thinreports/report.rb +0 -24
- /data/lib/thinreports/{core → basic_report/core}/shape/base.rb +0 -0
- /data/lib/thinreports/{core → basic_report/core}/shape/manager.rb +0 -0
- /data/lib/thinreports/{core → basic_report/core}/shape/style.rb +0 -0
- /data/lib/thinreports/{generator → basic_report/generator}/pdf/prawn_ext.rb +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'document/font'
|
|
4
|
+
require_relative 'document/parse_color'
|
|
5
|
+
require_relative 'document/graphics'
|
|
6
|
+
require_relative 'document/draw_shape'
|
|
7
|
+
require_relative 'document/draw_template_items'
|
|
8
|
+
require_relative 'document/page'
|
|
9
|
+
|
|
10
|
+
module Thinreports
|
|
11
|
+
module BasicReport
|
|
12
|
+
module Generator
|
|
13
|
+
class PDF
|
|
14
|
+
class Document
|
|
15
|
+
include Utils
|
|
16
|
+
|
|
17
|
+
include PDF::Font
|
|
18
|
+
include PDF::ParseColor
|
|
19
|
+
include PDF::Graphics
|
|
20
|
+
include PDF::DrawShape
|
|
21
|
+
include PDF::DrawTemplateItems
|
|
22
|
+
include PDF::Page
|
|
23
|
+
|
|
24
|
+
# @return [Prawn::Document]
|
|
25
|
+
attr_reader :pdf
|
|
26
|
+
|
|
27
|
+
# @param [String] title (nil)
|
|
28
|
+
# @param [Hash] security (nil)
|
|
29
|
+
def initialize(title: nil, security: nil)
|
|
30
|
+
@pdf = Prawn::Document.new(
|
|
31
|
+
skip_page_creation: true,
|
|
32
|
+
margin: [0, 0],
|
|
33
|
+
info: {
|
|
34
|
+
CreationDate: Time.now,
|
|
35
|
+
Creator: 'Thinreports Generator for Ruby ' + Thinreports::VERSION,
|
|
36
|
+
Title: title
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
# Setup to Prawn::Document.
|
|
40
|
+
setup_fonts
|
|
41
|
+
setup_custom_graphic_states
|
|
42
|
+
|
|
43
|
+
# Encrypts the document.
|
|
44
|
+
@pdf.encrypt_document(security) if security
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Delegate to Prawn::Document#render
|
|
48
|
+
# @see Prawn::Document#render
|
|
49
|
+
def render
|
|
50
|
+
result = pdf.render
|
|
51
|
+
finalize
|
|
52
|
+
result
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Delegate to Prawn::Document#render_file
|
|
56
|
+
# @see Prawn::Document#render_file
|
|
57
|
+
def render_file(*args)
|
|
58
|
+
finalize
|
|
59
|
+
pdf.render_file(*args)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @param [Numeric, String] x
|
|
63
|
+
# @param [Numeric, String] y
|
|
64
|
+
def translate(x, y, &block)
|
|
65
|
+
x, y = rpos(x, y)
|
|
66
|
+
pdf.translate(x, y, &block)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @param [String] stamp_id
|
|
70
|
+
# @param [Array<Numeric>] at (nil)
|
|
71
|
+
def stamp(stamp_id, at = nil)
|
|
72
|
+
if at.nil?
|
|
73
|
+
pdf.stamp(stamp_id)
|
|
74
|
+
else
|
|
75
|
+
pdf.stamp_at(stamp_id, rpos(*at))
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Delegate to Prawn::Document#create_stamp
|
|
80
|
+
# @param [String] id
|
|
81
|
+
# @see Prawn::Document#create_stamp
|
|
82
|
+
def create_stamp(id, &block)
|
|
83
|
+
pdf.create_stamp(id, &block)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @see #pdf
|
|
87
|
+
def internal
|
|
88
|
+
@pdf
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def finalize
|
|
94
|
+
clean_temp_images
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @param [Array<String, Numeric>] values
|
|
98
|
+
# @return [Numeric, Array<Numeric>, nil]
|
|
99
|
+
def s2f(*values)
|
|
100
|
+
return nil if values.empty?
|
|
101
|
+
|
|
102
|
+
if values.size == 1
|
|
103
|
+
value = values.first
|
|
104
|
+
return nil unless value
|
|
105
|
+
value.is_a?(::Numeric) ? value : value.to_f
|
|
106
|
+
else
|
|
107
|
+
values.map { |v| s2f(v) }
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param [Numeric, String] x
|
|
112
|
+
# @param [Numeric, String] y
|
|
113
|
+
# @return [Array<Float>]
|
|
114
|
+
def map_to_upper_left_relative_position(x, y)
|
|
115
|
+
x, y = s2f(x, y)
|
|
116
|
+
[x, -y]
|
|
117
|
+
end
|
|
118
|
+
alias rpos map_to_upper_left_relative_position
|
|
119
|
+
|
|
120
|
+
# @param [Numeric, String] x
|
|
121
|
+
# @param [Numeric, String] y
|
|
122
|
+
# @return [Array<Float>]
|
|
123
|
+
def map_to_upper_left_position(x, y)
|
|
124
|
+
x, y = s2f(x, y)
|
|
125
|
+
[x, pdf.bounds.height - y]
|
|
126
|
+
end
|
|
127
|
+
alias pos map_to_upper_left_position
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Generator
|
|
6
|
+
class PDF
|
|
7
|
+
module Drawer
|
|
8
|
+
# @abstract
|
|
9
|
+
class Base
|
|
10
|
+
# @param [Thinreports::BasicReport::Generator::PDF::Document] pdf
|
|
11
|
+
# @param [Thinreports::BasicReport::Core::Shape::Manager::Format] format
|
|
12
|
+
def initialize(pdf, format)
|
|
13
|
+
@pdf = pdf
|
|
14
|
+
@format = format
|
|
15
|
+
@stamps = []
|
|
16
|
+
@draw_at = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @abstract
|
|
20
|
+
def draw
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape
|
|
27
|
+
# @return [String]
|
|
28
|
+
def pdf_stamp_id(shape)
|
|
29
|
+
"#{@format.identifier}#{shape.identifier}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @overload pdf_stamp(shape_id)
|
|
33
|
+
# @param [String] shape_id
|
|
34
|
+
# @overload pdf_stamp(shape)
|
|
35
|
+
# @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape
|
|
36
|
+
def pdf_stamp(shape)
|
|
37
|
+
shape = pdf_stamp_id(shape) unless shape.is_a?(::String)
|
|
38
|
+
@pdf.stamp(shape, @draw_at)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape
|
|
42
|
+
def create_pdf_stamp(shape, &block)
|
|
43
|
+
@pdf.create_stamp(pdf_stamp_id(shape), &block)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Generator
|
|
6
|
+
class PDF
|
|
7
|
+
module Drawer
|
|
8
|
+
class List < Base
|
|
9
|
+
# @param (see PDF::Drawer::Base#initialize)
|
|
10
|
+
def initialize(pdf, format)
|
|
11
|
+
super
|
|
12
|
+
@sections = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @param [Thinreports::BasicReport::Core::Shape::List::PageState] list_page
|
|
16
|
+
def draw(list_page)
|
|
17
|
+
draw_section(list_page.header) if list_page.header
|
|
18
|
+
list_page.rows.each do |row|
|
|
19
|
+
draw_section(row)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns Thinreports::BasicReport::Report::Page object
|
|
23
|
+
manager = list_page.parent.manager
|
|
24
|
+
|
|
25
|
+
list_id = list_page.id.to_s
|
|
26
|
+
manager.format.shapes.each do |id, shape|
|
|
27
|
+
next unless list_pageno?(list_id, shape)
|
|
28
|
+
|
|
29
|
+
shape = manager.final_shape(id)
|
|
30
|
+
@pdf.draw_shape_pageno(shape.internal,
|
|
31
|
+
list_page.no, list_page.manager.page_count)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# @param [String] list_id
|
|
38
|
+
# @param [Thinreports::BasicReport::Core::Shape::Base::Format] shape
|
|
39
|
+
# @return [Boolean]
|
|
40
|
+
def list_pageno?(list_id, shape)
|
|
41
|
+
shape.type == Thinreports::BasicReport::Core::Shape::PageNumber::TYPE_NAME &&
|
|
42
|
+
shape.target == list_id
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @param [Thinreports::BasicReport::Core::Shape::List::SectionInterface] section
|
|
46
|
+
def draw_section(section)
|
|
47
|
+
internal = section.internal
|
|
48
|
+
|
|
49
|
+
base_top = @format.section_base_position_top(internal.section_name)
|
|
50
|
+
position = [internal.relative_left, base_top + internal.relative_top]
|
|
51
|
+
|
|
52
|
+
drawer(internal).draw(section, position)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @param [Thinreports::BasicReport::Core::Shape::List::SectionInternal] section
|
|
56
|
+
# @return [Thinreports::BasicReport::Generator::PDF::Drawer::ListSection]
|
|
57
|
+
def drawer(section)
|
|
58
|
+
@sections[section.section_name] ||= ListSection.new(@pdf, section)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Generator
|
|
6
|
+
class PDF
|
|
7
|
+
module Drawer
|
|
8
|
+
class ListSection < Page
|
|
9
|
+
# @param pdf (see PDF::Drawer::Page#initialize)
|
|
10
|
+
# @param section [Thinreports::BasicReport::Core::Shape::List::SectionInternal] section
|
|
11
|
+
def initialize(pdf, section)
|
|
12
|
+
super(pdf, section.format)
|
|
13
|
+
@section = section
|
|
14
|
+
@stamp_created = false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param [Thinreports::BasicReport::Core::Shape::List::SectionInternal] section
|
|
18
|
+
# @param [Array<Numeric>] at
|
|
19
|
+
def draw(section, at)
|
|
20
|
+
@draw_at = at
|
|
21
|
+
draw_section
|
|
22
|
+
super(section)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def draw_section
|
|
28
|
+
id = @format.identifier.to_s
|
|
29
|
+
|
|
30
|
+
unless @stamp_created
|
|
31
|
+
@pdf.create_stamp(id) { @pdf.draw_template_items(@format.attributes['items']) }
|
|
32
|
+
@stamp_created = true
|
|
33
|
+
end
|
|
34
|
+
pdf_stamp(id)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @see Thinreports::BasicReport::Generator::PDF::Drawer::Page#draw_tblock_shape
|
|
38
|
+
def draw_tblock_shape(shape)
|
|
39
|
+
@pdf.translate(*@draw_at) { super }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @see Thinreports::BasicReport::Generator::PDF::Drawer::Page#draw_iblock_shape
|
|
43
|
+
def draw_iblock_shape(shape)
|
|
44
|
+
@pdf.translate(*@draw_at) { super }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Generator
|
|
6
|
+
class PDF
|
|
7
|
+
module Drawer
|
|
8
|
+
class Page < Base
|
|
9
|
+
# @param (see PDF::Drawer::Base#initialize)
|
|
10
|
+
def initialize(pdf, format)
|
|
11
|
+
super
|
|
12
|
+
@lists = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @param [Thinreports::BasicReport::Report::Page] page
|
|
16
|
+
def draw(page)
|
|
17
|
+
manager = page.manager
|
|
18
|
+
|
|
19
|
+
manager.format.shapes.each_key do |id|
|
|
20
|
+
shape = manager.final_shape(id)
|
|
21
|
+
next unless shape
|
|
22
|
+
|
|
23
|
+
shape = shape.internal
|
|
24
|
+
|
|
25
|
+
if shape.type_of?(Core::Shape::PageNumber::TYPE_NAME)
|
|
26
|
+
# Do not draw pageno if is not for Report
|
|
27
|
+
draw_pageno_shape(shape, page) if page.count? && shape.for_report?
|
|
28
|
+
else
|
|
29
|
+
draw_shape(shape)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def draw_shape(shape)
|
|
37
|
+
if shape.type_of?(Core::Shape::TextBlock::TYPE_NAME)
|
|
38
|
+
draw_tblock_shape(shape)
|
|
39
|
+
elsif shape.type_of?(Core::Shape::List::TYPE_NAME)
|
|
40
|
+
draw_list_shape(shape)
|
|
41
|
+
elsif shape.type_of?(Core::Shape::ImageBlock::TYPE_NAME)
|
|
42
|
+
draw_iblock_shape(shape)
|
|
43
|
+
else
|
|
44
|
+
id = shape.identifier
|
|
45
|
+
unless @stamps.include?(id)
|
|
46
|
+
create_basic_shape_stamp(shape)
|
|
47
|
+
@stamps << id
|
|
48
|
+
end
|
|
49
|
+
pdf_stamp(shape)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def draw_pageno_shape(shape, page)
|
|
54
|
+
@pdf.draw_shape_pageno(shape, page.no, page.report.page_count)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @see #draw_shape
|
|
58
|
+
def draw_list_shape(shape)
|
|
59
|
+
drawer = @lists[shape.id] ||= List.new(@pdf, shape.format)
|
|
60
|
+
drawer.draw(shape)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @see #draw_shape
|
|
64
|
+
def draw_tblock_shape(shape)
|
|
65
|
+
@pdf.draw_shape_tblock(shape)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @see #draw_shape
|
|
69
|
+
def draw_iblock_shape(shape)
|
|
70
|
+
@pdf.draw_shape_iblock(shape)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape
|
|
74
|
+
def create_basic_shape_stamp(shape)
|
|
75
|
+
if shape.type_of?('text')
|
|
76
|
+
create_text_stamp(shape)
|
|
77
|
+
elsif shape.type_of?('image')
|
|
78
|
+
create_image_stamp(shape)
|
|
79
|
+
elsif shape.type_of?('ellipse')
|
|
80
|
+
create_ellipse_stamp(shape)
|
|
81
|
+
elsif shape.type_of?('rect')
|
|
82
|
+
create_rect_stamp(shape)
|
|
83
|
+
elsif shape.type_of?('line')
|
|
84
|
+
create_line_stamp(shape)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# @see #create_basic_shape_stamp
|
|
89
|
+
def create_image_stamp(shape)
|
|
90
|
+
create_pdf_stamp(shape) do
|
|
91
|
+
@pdf.draw_shape_image(shape)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @see #create_basic_shape_stamp
|
|
96
|
+
def create_rect_stamp(shape)
|
|
97
|
+
create_pdf_stamp(shape) do
|
|
98
|
+
@pdf.draw_shape_rect(shape)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @see #create_basic_shape_stamp
|
|
103
|
+
def create_ellipse_stamp(shape)
|
|
104
|
+
create_pdf_stamp(shape) do
|
|
105
|
+
@pdf.draw_shape_ellipse(shape)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @see #create_basic_shape_stamp
|
|
110
|
+
def create_line_stamp(shape)
|
|
111
|
+
create_pdf_stamp(shape) do
|
|
112
|
+
@pdf.draw_shape_line(shape)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# @see #create_basic_shape_stamp
|
|
117
|
+
def create_text_stamp(shape)
|
|
118
|
+
create_pdf_stamp(shape) do
|
|
119
|
+
@pdf.draw_shape_text(shape)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Generator
|
|
6
|
+
module PrawnExt
|
|
7
|
+
module CalcImageDimensions
|
|
8
|
+
# Implement :auto_fit option for image size calculation.
|
|
9
|
+
#
|
|
10
|
+
# When the image is larger than the box, the original: fit option does not change
|
|
11
|
+
# the image size. The :auto_fit option changes the image size to fit in the box
|
|
12
|
+
# while maintaining the aspect ratio.
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# image '/path/to/image.png', at: [100, 100], auto_fit: [100, 100]
|
|
16
|
+
#
|
|
17
|
+
def calc_image_dimensions(options)
|
|
18
|
+
if options[:auto_fit]
|
|
19
|
+
image_width = options[:width] || width
|
|
20
|
+
image_height = options[:height] || height
|
|
21
|
+
|
|
22
|
+
box_width, box_height = options.delete(:auto_fit)
|
|
23
|
+
|
|
24
|
+
options[:fit] = [box_width, box_height] if image_width > box_width || image_height > box_height
|
|
25
|
+
end
|
|
26
|
+
super(options)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
Prawn::Images::Image.prepend Thinreports::BasicReport::Generator::PrawnExt::CalcImageDimensions
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Generator
|
|
6
|
+
module PrawnExt
|
|
7
|
+
module WidthOf
|
|
8
|
+
# This patch fixes the character_spacing effect on text width calculation.
|
|
9
|
+
#
|
|
10
|
+
# The original #width_of:
|
|
11
|
+
#
|
|
12
|
+
# width_of('abcd') #=> 4 + 4 = 8
|
|
13
|
+
#
|
|
14
|
+
# The #width_of in this patch:
|
|
15
|
+
#
|
|
16
|
+
# width_of('abcd') #=> 4 + 3 = 7
|
|
17
|
+
#
|
|
18
|
+
def width_of(*)
|
|
19
|
+
width = super - character_spacing
|
|
20
|
+
width > 0 ? width : 0
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Prawn v2.3 and later includes this patch by https://github.com/prawnpdf/prawn/pull/1117.
|
|
29
|
+
if Prawn::VERSION < '2.3.0'
|
|
30
|
+
Prawn::Document.prepend Thinreports::BasicReport::Generator::PrawnExt::WidthOf
|
|
31
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'prawn'
|
|
4
|
+
|
|
5
|
+
module Thinreports
|
|
6
|
+
module BasicReport
|
|
7
|
+
module Generator
|
|
8
|
+
class PDF
|
|
9
|
+
# @return [Thinreports::BasicReport::Report::Base]
|
|
10
|
+
attr_reader :report
|
|
11
|
+
|
|
12
|
+
# @param [Thinreports::BasicReport::Report::Base] report
|
|
13
|
+
# @param [Hash] security (nil)
|
|
14
|
+
# @param [String] title (nil)
|
|
15
|
+
def initialize(report, security: nil, title: nil)
|
|
16
|
+
report.finalize
|
|
17
|
+
|
|
18
|
+
@report = report.internal
|
|
19
|
+
title ||= default_layout ? default_layout.format.report_title : nil
|
|
20
|
+
|
|
21
|
+
@document = Document.new(title: title, security: security)
|
|
22
|
+
@drawers = {}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param [String, nil] filename
|
|
26
|
+
# @return [String, nil]
|
|
27
|
+
def generate(filename = nil)
|
|
28
|
+
draw_report
|
|
29
|
+
filename ? @document.render_file(filename) : @document.render
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def default_layout
|
|
33
|
+
report.default_layout
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def draw_report
|
|
39
|
+
report.pages.each do |page|
|
|
40
|
+
draw_page(page)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def draw_page(page)
|
|
45
|
+
return @document.add_blank_page if page.blank?
|
|
46
|
+
|
|
47
|
+
format = page.layout.format
|
|
48
|
+
@document.start_new_page(format)
|
|
49
|
+
|
|
50
|
+
drawer(format).draw(page)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def drawer(format)
|
|
54
|
+
@drawers[format.identifier] ||= Drawer::Page.new(@document, format)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
require_relative 'pdf/prawn_ext'
|
|
62
|
+
require_relative 'pdf/document'
|
|
63
|
+
require_relative 'pdf/drawer/base'
|
|
64
|
+
require_relative 'pdf/drawer/page'
|
|
65
|
+
require_relative 'pdf/drawer/list'
|
|
66
|
+
require_relative 'pdf/drawer/list_section'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Thinreports
|
|
4
|
+
module BasicReport
|
|
5
|
+
module Layout
|
|
6
|
+
class Base
|
|
7
|
+
EXT_NAME = 'tlf'
|
|
8
|
+
include Utils
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
# @param [String] filename
|
|
12
|
+
# @return [Thinreports::BasicReport::Layout::Format]
|
|
13
|
+
# @raise [Thinreports::BasicReport::Errors::InvalidLayoutFormat]
|
|
14
|
+
# @raise [Thinreports::BasicReport::Errors::IncompatibleLayoutFormat]
|
|
15
|
+
def load_format(filename)
|
|
16
|
+
filename += ".#{EXT_NAME}" unless filename =~ /\.#{EXT_NAME}$/
|
|
17
|
+
|
|
18
|
+
raise Thinreports::BasicReport::Errors::LayoutFileNotFound unless File.exist?(filename)
|
|
19
|
+
# Build format.
|
|
20
|
+
Thinreports::BasicReport::Layout::Format.build(filename)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_reader :format
|
|
25
|
+
|
|
26
|
+
# @return [String]
|
|
27
|
+
attr_reader :filename
|
|
28
|
+
|
|
29
|
+
# @return [Symbol]
|
|
30
|
+
attr_reader :id
|
|
31
|
+
|
|
32
|
+
# @param [String] filename
|
|
33
|
+
# @param [Hash] options
|
|
34
|
+
# @option options [Symbol] :id (nil)
|
|
35
|
+
def initialize(filename, options = {})
|
|
36
|
+
@filename = filename
|
|
37
|
+
@format = self.class.load_format(filename)
|
|
38
|
+
@id = options[:id]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Boolean] Return the true if is default layout.
|
|
42
|
+
def default?
|
|
43
|
+
@id.nil?
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Thinreports
|
|
6
|
+
module BasicReport
|
|
7
|
+
module Layout
|
|
8
|
+
class Format < Core::Shape::Manager::Format
|
|
9
|
+
config_reader last_version: %w[version]
|
|
10
|
+
config_reader report_title: %w[title]
|
|
11
|
+
config_reader page_paper_type: %w[report paper-type],
|
|
12
|
+
page_width: %w[report width],
|
|
13
|
+
page_height: %w[report height],
|
|
14
|
+
page_orientation: %w[report orientation]
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def build(filename)
|
|
18
|
+
schema = JSON.parse(read_file(filename))
|
|
19
|
+
schema_version = Layout::Version.new(schema['version'])
|
|
20
|
+
|
|
21
|
+
unless schema_version.compatible?
|
|
22
|
+
raise Errors::IncompatibleLayoutFormat.new(
|
|
23
|
+
filename, schema['version'],
|
|
24
|
+
Layout::Version.compatible_rules.join(' and ')
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if schema_version.legacy?
|
|
29
|
+
warn '[DEPRECATION] Support for the layout file with old format' \
|
|
30
|
+
' that generated with Editor 0.8 or lower will be dropped in Thinreports 1.1.' \
|
|
31
|
+
' Please convert to new layout format using Thinreports Editor 0.9 or 1.0.'
|
|
32
|
+
schema = Layout::LegacySchema.new(schema).upgrade
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
new schema
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def read_file(filename)
|
|
39
|
+
File.read(filename, encoding: 'UTF-8')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def initialize(*)
|
|
44
|
+
super
|
|
45
|
+
initialize_items(attributes['items'])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def user_paper_type?
|
|
49
|
+
page_paper_type == 'user'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def initialize_items(item_schemas)
|
|
55
|
+
item_schemas.each do |item_schema|
|
|
56
|
+
id, type = item_schema.values_at 'id', 'type'
|
|
57
|
+
|
|
58
|
+
next if id.empty? && type != 'page-number'
|
|
59
|
+
|
|
60
|
+
item = Core::Shape::Format(type).new(item_schema)
|
|
61
|
+
shapes[item.id.to_sym] = item
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|