thinreports 0.12.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +3 -3
  3. data/.github/workflows/test.yml +28 -36
  4. data/.gitignore +1 -1
  5. data/CHANGELOG.md +19 -1
  6. data/Gemfile +11 -0
  7. data/README.md +12 -17
  8. data/Rakefile +17 -11
  9. data/lib/thinreports/basic_report/core/errors.rb +62 -0
  10. data/lib/thinreports/basic_report/core/format/base.rb +91 -0
  11. data/lib/thinreports/basic_report/core/shape/base/interface.rb +42 -0
  12. data/lib/thinreports/basic_report/core/shape/base/internal.rb +53 -0
  13. data/lib/thinreports/basic_report/core/shape/basic/block_format.rb +15 -0
  14. data/lib/thinreports/basic_report/core/shape/basic/block_interface.rb +34 -0
  15. data/lib/thinreports/basic_report/core/shape/basic/block_internal.rb +36 -0
  16. data/lib/thinreports/basic_report/core/shape/basic/format.rb +24 -0
  17. data/lib/thinreports/basic_report/core/shape/basic/interface.rb +87 -0
  18. data/lib/thinreports/basic_report/core/shape/basic/internal.rb +28 -0
  19. data/lib/thinreports/{core → basic_report/core}/shape/basic.rb +6 -4
  20. data/lib/thinreports/basic_report/core/shape/image_block/format.rb +14 -0
  21. data/lib/thinreports/basic_report/core/shape/image_block/interface.rb +25 -0
  22. data/lib/thinreports/basic_report/core/shape/image_block/internal.rb +19 -0
  23. data/lib/thinreports/{core → basic_report/core}/shape/image_block.rb +6 -4
  24. data/lib/thinreports/basic_report/core/shape/list/format.rb +92 -0
  25. data/lib/thinreports/basic_report/core/shape/list/manager.rb +231 -0
  26. data/lib/thinreports/basic_report/core/shape/list/page.rb +112 -0
  27. data/lib/thinreports/basic_report/core/shape/list/page_state.rb +50 -0
  28. data/lib/thinreports/basic_report/core/shape/list/section_format.rb +37 -0
  29. data/lib/thinreports/basic_report/core/shape/list/section_interface.rb +51 -0
  30. data/lib/thinreports/basic_report/core/shape/list/section_internal.rb +33 -0
  31. data/lib/thinreports/{core → basic_report/core}/shape/list.rb +6 -4
  32. data/lib/thinreports/basic_report/core/shape/manager/format.rb +33 -0
  33. data/lib/thinreports/basic_report/core/shape/manager/internal.rb +109 -0
  34. data/lib/thinreports/basic_report/core/shape/manager/target.rb +114 -0
  35. data/lib/thinreports/basic_report/core/shape/page_number/format.rb +32 -0
  36. data/lib/thinreports/basic_report/core/shape/page_number/interface.rb +31 -0
  37. data/lib/thinreports/basic_report/core/shape/page_number/internal.rb +57 -0
  38. data/lib/thinreports/{core → basic_report/core}/shape/page_number.rb +6 -4
  39. data/lib/thinreports/basic_report/core/shape/stack_view/format.rb +29 -0
  40. data/lib/thinreports/basic_report/core/shape/stack_view/interface.rb +19 -0
  41. data/lib/thinreports/basic_report/core/shape/stack_view/internal.rb +24 -0
  42. data/lib/thinreports/basic_report/core/shape/stack_view/row_format.rb +41 -0
  43. data/lib/thinreports/{core → basic_report/core}/shape/stack_view.rb +6 -4
  44. data/lib/thinreports/basic_report/core/shape/style/base.rb +149 -0
  45. data/lib/thinreports/basic_report/core/shape/style/basic.rb +24 -0
  46. data/lib/thinreports/basic_report/core/shape/style/graphic.rb +43 -0
  47. data/lib/thinreports/basic_report/core/shape/style/text.rb +122 -0
  48. data/lib/thinreports/basic_report/core/shape/text/format.rb +17 -0
  49. data/lib/thinreports/basic_report/core/shape/text/interface.rb +20 -0
  50. data/lib/thinreports/basic_report/core/shape/text/internal.rb +24 -0
  51. data/lib/thinreports/{core → basic_report/core}/shape/text.rb +6 -4
  52. data/lib/thinreports/basic_report/core/shape/text_block/format.rb +43 -0
  53. data/lib/thinreports/basic_report/core/shape/text_block/formatter/basic.rb +41 -0
  54. data/lib/thinreports/basic_report/core/shape/text_block/formatter/datetime.rb +25 -0
  55. data/lib/thinreports/basic_report/core/shape/text_block/formatter/number.rb +69 -0
  56. data/lib/thinreports/basic_report/core/shape/text_block/formatter/padding.rb +27 -0
  57. data/lib/thinreports/basic_report/core/shape/text_block/formatter.rb +38 -0
  58. data/lib/thinreports/basic_report/core/shape/text_block/interface.rb +37 -0
  59. data/lib/thinreports/basic_report/core/shape/text_block/internal.rb +75 -0
  60. data/lib/thinreports/{core → basic_report/core}/shape/text_block.rb +6 -4
  61. data/lib/thinreports/basic_report/core/shape.rb +44 -0
  62. data/lib/thinreports/basic_report/core/utils.rb +47 -0
  63. data/lib/thinreports/basic_report/generator/pdf/document/draw_shape.rb +108 -0
  64. data/lib/thinreports/basic_report/generator/pdf/document/draw_template_items.rb +71 -0
  65. data/lib/thinreports/basic_report/generator/pdf/document/font.rb +90 -0
  66. data/lib/thinreports/basic_report/generator/pdf/document/graphics/attributes.rb +149 -0
  67. data/lib/thinreports/basic_report/generator/pdf/document/graphics/basic.rb +137 -0
  68. data/lib/thinreports/basic_report/generator/pdf/document/graphics/image.rb +99 -0
  69. data/lib/thinreports/basic_report/generator/pdf/document/graphics/text.rb +180 -0
  70. data/lib/thinreports/basic_report/generator/pdf/document/graphics.rb +42 -0
  71. data/lib/thinreports/basic_report/generator/pdf/document/page.rb +96 -0
  72. data/lib/thinreports/basic_report/generator/pdf/document/parse_color.rb +51 -0
  73. data/lib/thinreports/basic_report/generator/pdf/document.rb +132 -0
  74. data/lib/thinreports/basic_report/generator/pdf/drawer/base.rb +50 -0
  75. data/lib/thinreports/basic_report/generator/pdf/drawer/list.rb +65 -0
  76. data/lib/thinreports/basic_report/generator/pdf/drawer/list_section.rb +51 -0
  77. data/lib/thinreports/basic_report/generator/pdf/drawer/page.rb +127 -0
  78. data/lib/thinreports/basic_report/generator/pdf/prawn_ext/calc_image_dimensions.rb +34 -0
  79. data/lib/thinreports/basic_report/generator/pdf/prawn_ext/width_of.rb +31 -0
  80. data/lib/thinreports/basic_report/generator/pdf.rb +66 -0
  81. data/lib/thinreports/basic_report/layout/base.rb +48 -0
  82. data/lib/thinreports/basic_report/layout/format.rb +67 -0
  83. data/lib/thinreports/basic_report/layout/legacy_schema.rb +383 -0
  84. data/lib/thinreports/basic_report/layout/version.rb +41 -0
  85. data/lib/thinreports/{layout.rb → basic_report/layout.rb} +6 -4
  86. data/lib/thinreports/basic_report/report/base.rb +173 -0
  87. data/lib/thinreports/basic_report/report/internal.rb +107 -0
  88. data/lib/thinreports/basic_report/report/page.rb +97 -0
  89. data/lib/thinreports/basic_report/report.rb +26 -0
  90. data/lib/thinreports/basic_report.rb +15 -0
  91. data/lib/thinreports/config.rb +1 -1
  92. data/lib/thinreports/section_report.rb +12 -0
  93. data/lib/thinreports/version.rb +1 -1
  94. data/lib/thinreports.rb +2 -13
  95. data/thinreports.gemspec +3 -7
  96. metadata +97 -154
  97. data/gemfiles/prawn-2.2.gemfile +0 -5
  98. data/gemfiles/prawn-2.3.gemfile +0 -5
  99. data/gemfiles/prawn-2.4.gemfile +0 -5
  100. data/lib/thinreports/core/errors.rb +0 -60
  101. data/lib/thinreports/core/format/base.rb +0 -89
  102. data/lib/thinreports/core/shape/base/interface.rb +0 -40
  103. data/lib/thinreports/core/shape/base/internal.rb +0 -51
  104. data/lib/thinreports/core/shape/basic/block_format.rb +0 -13
  105. data/lib/thinreports/core/shape/basic/block_interface.rb +0 -32
  106. data/lib/thinreports/core/shape/basic/block_internal.rb +0 -34
  107. data/lib/thinreports/core/shape/basic/format.rb +0 -22
  108. data/lib/thinreports/core/shape/basic/interface.rb +0 -85
  109. data/lib/thinreports/core/shape/basic/internal.rb +0 -26
  110. data/lib/thinreports/core/shape/image_block/format.rb +0 -12
  111. data/lib/thinreports/core/shape/image_block/interface.rb +0 -23
  112. data/lib/thinreports/core/shape/image_block/internal.rb +0 -17
  113. data/lib/thinreports/core/shape/list/format.rb +0 -90
  114. data/lib/thinreports/core/shape/list/manager.rb +0 -229
  115. data/lib/thinreports/core/shape/list/page.rb +0 -110
  116. data/lib/thinreports/core/shape/list/page_state.rb +0 -48
  117. data/lib/thinreports/core/shape/list/section_format.rb +0 -35
  118. data/lib/thinreports/core/shape/list/section_interface.rb +0 -49
  119. data/lib/thinreports/core/shape/list/section_internal.rb +0 -31
  120. data/lib/thinreports/core/shape/manager/format.rb +0 -31
  121. data/lib/thinreports/core/shape/manager/internal.rb +0 -107
  122. data/lib/thinreports/core/shape/manager/target.rb +0 -112
  123. data/lib/thinreports/core/shape/page_number/format.rb +0 -30
  124. data/lib/thinreports/core/shape/page_number/interface.rb +0 -29
  125. data/lib/thinreports/core/shape/page_number/internal.rb +0 -55
  126. data/lib/thinreports/core/shape/stack_view/format.rb +0 -27
  127. data/lib/thinreports/core/shape/stack_view/interface.rb +0 -17
  128. data/lib/thinreports/core/shape/stack_view/internal.rb +0 -22
  129. data/lib/thinreports/core/shape/stack_view/row_format.rb +0 -39
  130. data/lib/thinreports/core/shape/style/base.rb +0 -146
  131. data/lib/thinreports/core/shape/style/basic.rb +0 -22
  132. data/lib/thinreports/core/shape/style/graphic.rb +0 -41
  133. data/lib/thinreports/core/shape/style/text.rb +0 -120
  134. data/lib/thinreports/core/shape/text/format.rb +0 -15
  135. data/lib/thinreports/core/shape/text/interface.rb +0 -18
  136. data/lib/thinreports/core/shape/text/internal.rb +0 -22
  137. data/lib/thinreports/core/shape/text_block/format.rb +0 -41
  138. data/lib/thinreports/core/shape/text_block/formatter/basic.rb +0 -39
  139. data/lib/thinreports/core/shape/text_block/formatter/datetime.rb +0 -23
  140. data/lib/thinreports/core/shape/text_block/formatter/number.rb +0 -67
  141. data/lib/thinreports/core/shape/text_block/formatter/padding.rb +0 -25
  142. data/lib/thinreports/core/shape/text_block/formatter.rb +0 -34
  143. data/lib/thinreports/core/shape/text_block/interface.rb +0 -35
  144. data/lib/thinreports/core/shape/text_block/internal.rb +0 -73
  145. data/lib/thinreports/core/shape.rb +0 -42
  146. data/lib/thinreports/core/utils.rb +0 -45
  147. data/lib/thinreports/generate.rb +0 -11
  148. data/lib/thinreports/generator/pdf/document/draw_shape.rb +0 -106
  149. data/lib/thinreports/generator/pdf/document/draw_template_items.rb +0 -69
  150. data/lib/thinreports/generator/pdf/document/font.rb +0 -88
  151. data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +0 -147
  152. data/lib/thinreports/generator/pdf/document/graphics/basic.rb +0 -135
  153. data/lib/thinreports/generator/pdf/document/graphics/image.rb +0 -98
  154. data/lib/thinreports/generator/pdf/document/graphics/text.rb +0 -178
  155. data/lib/thinreports/generator/pdf/document/graphics.rb +0 -40
  156. data/lib/thinreports/generator/pdf/document/page.rb +0 -94
  157. data/lib/thinreports/generator/pdf/document/parse_color.rb +0 -49
  158. data/lib/thinreports/generator/pdf/document.rb +0 -130
  159. data/lib/thinreports/generator/pdf/drawer/base.rb +0 -48
  160. data/lib/thinreports/generator/pdf/drawer/list.rb +0 -63
  161. data/lib/thinreports/generator/pdf/drawer/list_section.rb +0 -49
  162. data/lib/thinreports/generator/pdf/drawer/page.rb +0 -125
  163. data/lib/thinreports/generator/pdf/prawn_ext/calc_image_dimensions.rb +0 -32
  164. data/lib/thinreports/generator/pdf/prawn_ext/width_of.rb +0 -29
  165. data/lib/thinreports/generator/pdf.rb +0 -63
  166. data/lib/thinreports/layout/base.rb +0 -46
  167. data/lib/thinreports/layout/format.rb +0 -65
  168. data/lib/thinreports/layout/legacy_schema.rb +0 -381
  169. data/lib/thinreports/layout/version.rb +0 -39
  170. data/lib/thinreports/report/base.rb +0 -169
  171. data/lib/thinreports/report/internal.rb +0 -105
  172. data/lib/thinreports/report/page.rb +0 -95
  173. data/lib/thinreports/report.rb +0 -24
  174. /data/lib/thinreports/{core → basic_report/core}/shape/base.rb +0 -0
  175. /data/lib/thinreports/{core → basic_report/core}/shape/manager.rb +0 -0
  176. /data/lib/thinreports/{core → basic_report/core}/shape/style.rb +0 -0
  177. /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