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
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Thinreports
4
- module Generator
5
- class PDF
6
- module Font
7
- FONT_STORE = Thinreports.root.join('fonts')
8
-
9
- BUILTIN_FONTS = {
10
- 'IPAMincho' => FONT_STORE.join('ipam.ttf').to_s,
11
- 'IPAPMincho' => FONT_STORE.join('ipamp.ttf').to_s,
12
- 'IPAGothic' => FONT_STORE.join('ipag.ttf').to_s,
13
- 'IPAPGothic' => FONT_STORE.join('ipagp.ttf').to_s
14
- }.freeze
15
-
16
- DEFAULT_FALLBACK_FONTS = %w[IPAMincho].freeze
17
-
18
- PRAWN_BUINTIN_FONT_ALIASES = {
19
- 'Courier New' => 'Courier',
20
- 'Times New Roman' => 'Times-Roman'
21
- }.freeze
22
-
23
- def setup_fonts
24
- # Install built-in fonts.
25
- BUILTIN_FONTS.each do |font_name, font_path|
26
- install_font(font_name, font_path)
27
- end
28
-
29
- # Create aliases from the font list provided by Prawn.
30
- PRAWN_BUINTIN_FONT_ALIASES.each do |alias_name, name|
31
- pdf.font_families[alias_name] = pdf.font_families[name]
32
- end
33
-
34
- # Setup custom fallback fonts
35
- fallback_fonts = Thinreports.config.fallback_fonts.uniq
36
- fallback_fonts.map!.with_index do |font, i|
37
- if pdf.font_families.key?(font)
38
- font
39
- else
40
- install_font "Custom-fallback-font#{i}", font
41
- end
42
- end
43
-
44
- # Set fallback fonts
45
- pdf.fallback_fonts(fallback_fonts + DEFAULT_FALLBACK_FONTS)
46
- end
47
-
48
- # @param [String] name
49
- # @param [String] file
50
- # @return [String] installed font name
51
- def install_font(name, file)
52
- raise Errors::FontFileNotFound unless File.exist?(file)
53
-
54
- pdf.font_families[name] = {
55
- normal: file,
56
- bold: file,
57
- italic: file,
58
- bold_italic: file
59
- }
60
- name
61
- end
62
-
63
- # @return [String]
64
- def default_family
65
- 'Helvetica'
66
- end
67
-
68
- # @param [String] family
69
- # @return [String]
70
- def default_family_if_missing(family)
71
- pdf.font_families.key?(family) ? family : default_family
72
- end
73
-
74
- # @param [String] font_name
75
- # @param [:bold, :italic] font_style
76
- # @return [Boolean]
77
- def font_has_style?(font_name, font_style)
78
- font = pdf.font_families[font_name]
79
-
80
- return false unless font
81
- return false unless font.key?(font_style)
82
-
83
- font[font_style] != font[:normal]
84
- end
85
- end
86
- end
87
- end
88
- end
@@ -1,147 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Thinreports
4
- module Generator
5
- class PDF
6
- module Graphics
7
- # @param [Hash] style
8
- # @yield [attrs]
9
- # @yieldparam [Hash] attrs
10
- # @return [Hash]
11
- def build_graphic_attributes(style, &block)
12
- graphic_attributes = {
13
- stroke: style['border-color'],
14
- stroke_width: style['border-width'],
15
- stroke_type: style['border-style'],
16
- fill: style['fill-color']
17
- }
18
- block.call(graphic_attributes) if block_given?
19
- graphic_attributes
20
- end
21
-
22
- # @param [Hash] style
23
- # @yield [attrs]
24
- # @yieldparam [Hash] attrs
25
- # @return [Hash]
26
- def build_text_attributes(style, &block)
27
- text_attributes = {
28
- font: font_family(style['font-family']),
29
- size: style['font-size'],
30
- color: style['color'],
31
- align: text_align(style['text-align']),
32
- valign: text_valign(style['vertical-align']),
33
- styles: font_styles(style['font-style']),
34
- letter_spacing: letter_spacing(style['letter-spacing']),
35
- line_height: line_height(style['line-height']),
36
- overflow: text_overflow(style['overflow']),
37
- word_wrap: word_wrap(style['word-wrap'])
38
- }
39
- block.call(text_attributes) if block_given?
40
- text_attributes
41
- end
42
-
43
- # @param [Array<String>] font_names
44
- # @return [String]
45
- def font_family(font_names)
46
- font_name = font_names.first
47
- default_family_if_missing(font_name)
48
- end
49
-
50
- # @param [Array<String>] styles
51
- # @return [Array<Symbol>]
52
- def font_styles(styles)
53
- styles.map do |font_style|
54
- case font_style
55
- when 'bold' then :bold
56
- when 'italic' then :italic
57
- when 'underline' then :underline
58
- when 'linethrough' then :strikethrough
59
- end
60
- end
61
- end
62
-
63
- # @param [Float, "", nil] spacing
64
- # @return [Float, nil]
65
- def letter_spacing(spacing)
66
- blank_value?(spacing) ? nil : spacing
67
- end
68
-
69
- # @param ["left", "center", "right", ""] align
70
- # @return [:left, :center, :right]
71
- def text_align(align)
72
- case align
73
- when 'left' then :left
74
- when 'center' then :center
75
- when 'right' then :right
76
- when '' then :left
77
- else :left
78
- end
79
- end
80
-
81
- # @param ["top", "middle", "bottom", "", nil] valign
82
- # @return [:top, :center, :bottom]
83
- def text_valign(valign)
84
- case valign
85
- when 'top' then :top
86
- when 'middle' then :center
87
- when 'bottom' then :bottom
88
- when '' then :top
89
- else :top
90
- end
91
- end
92
-
93
- # @param ["truncate", "fit", "expand", "", nil] overflow
94
- # @return [:truncate, :shrink_to_fit, :expand]
95
- def text_overflow(overflow)
96
- case overflow
97
- when 'truncate' then :truncate
98
- when 'fit' then :shrink_to_fit
99
- when 'expand' then :expand
100
- when '' then :truncate
101
- else :truncate
102
- end
103
- end
104
-
105
- # @param ["break-word", "none", "", nil] word_wrap
106
- # @return [:break_word, :none]
107
- def word_wrap(word_wrap)
108
- case word_wrap
109
- when 'break-word' then :break_word
110
- when 'none' then :none
111
- else :none
112
- end
113
- end
114
-
115
- # @param [Float, "", nil] height
116
- # @return [Float, nil]
117
- def line_height(height)
118
- blank_value?(height) ? nil : height
119
- end
120
-
121
- # @param ["left", "center", "right", ""] position
122
- # @return [:left, :center, :right]
123
- def image_position_x(position)
124
- case position
125
- when 'left' then :left
126
- when 'center' then :center
127
- when 'right' then :right
128
- when '' then :left
129
- else :left
130
- end
131
- end
132
-
133
- # @param ["top", "middle", "bottom", ""] position
134
- # @return [:left, :center, :right]
135
- def image_position_y(position)
136
- case position
137
- when 'top' then :top
138
- when 'middle' then :center
139
- when 'bottom' then :bottom
140
- when '' then :top
141
- else :top
142
- end
143
- end
144
- end
145
- end
146
- end
147
- end
@@ -1,135 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Thinreports
4
- module Generator
5
- class PDF
6
- module Graphics
7
- STROKE_DASH = {
8
- dashed: [2, 2],
9
- dotted: [1, 2]
10
- }.freeze
11
-
12
- # @param [Numeric, String] x1
13
- # @param [Numeric, String] y1
14
- # @param [Numeric, String] x2
15
- # @param [Numeric, String] y2
16
- # @param [Hash] attrs ({})
17
- # @option attrs [String] :stroke
18
- # @option attrs [Numeric, String] :stroke_width
19
- # @option attrs ["solid", "dashed", "dotted"] :stroke_type
20
- def line(x1, y1, x2, y2, attrs = {})
21
- with_graphic_styles(attrs) do
22
- pdf.line(pos(x1, y1), pos(x2, y2))
23
- end
24
- end
25
-
26
- # @param [Numeric, String] x
27
- # @param [Numeric, String] y
28
- # @param [Numeric, String] w width
29
- # @param [Numeric, String] h height
30
- # @param [Hash] attrs ({})
31
- # @option attrs [Integer, String] :radius
32
- # @option attrs [String] :stroke
33
- # @option attrs [Numeric, String] :stroke_width
34
- # @option attrs ["solid", "dashed", "dotted"] :stroke_type
35
- # @option attrs [String] :fill
36
- def rect(x, y, w, h, attrs = {})
37
- w, h = s2f(w, h)
38
- radius = s2f(attrs[:radius])
39
-
40
- with_graphic_styles(attrs) do
41
- if radius && !radius.zero?
42
- pdf.rounded_rectangle(pos(x, y), w, h, radius)
43
- else
44
- pdf.rectangle(pos(x, y), w, h)
45
- end
46
- end
47
- end
48
-
49
- # @param [Numeric, String] x center-x
50
- # @param [Numeric, String] y center-y
51
- # @param [Numeric, String] rx
52
- # @param [Numeric, String] ry
53
- # @param [Hash] attrs ({})
54
- # @option attrs [String] :stroke
55
- # @option attrs [Numeric, String] :stroke_width
56
- # @option attrs [Array<Integer, String>] :stroke_dash
57
- # @option attrs ["solid", "dashed", "dotted"] :stroke_type
58
- # @option attrs [String] :fill
59
- def ellipse(x, y, rx, ry, attrs = {})
60
- rx, ry = s2f(rx, ry)
61
-
62
- with_graphic_styles(attrs) do
63
- pdf.ellipse(pos(x, y), rx, ry)
64
- end
65
- end
66
-
67
- # @param [Hash] attrs
68
- def with_graphic_styles(attrs, &block)
69
- stroke = build_stroke_styles(attrs)
70
- fill = build_fill_styles(attrs)
71
-
72
- # Do not draw if no colors given.
73
- return unless fill || stroke
74
-
75
- save_graphics_state
76
-
77
- # Apply stroke-dashed.
78
- if stroke && stroke[:dash]
79
- length, space = stroke[:dash]
80
- pdf.dash(length, space: space)
81
- end
82
-
83
- # Draw with fill and stroke.
84
- if fill && stroke
85
- pdf.fill_and_stroke do
86
- line_width(stroke[:width])
87
- pdf.fill_color(fill[:color])
88
- pdf.stroke_color(stroke[:color])
89
- block.call
90
- end
91
- # Draw only with fill.
92
- elsif fill
93
- pdf.fill do
94
- pdf.fill_color(fill[:color])
95
- block.call
96
- end
97
- # Draw only with stroke.
98
- elsif stroke
99
- pdf.stroke do
100
- line_width(stroke[:width])
101
- pdf.stroke_color(stroke[:color])
102
- block.call
103
- end
104
- end
105
-
106
- restore_graphics_state
107
- end
108
-
109
- # @param [Hash] styles
110
- # @return [Hash, nil]
111
- def build_stroke_styles(styles)
112
- color = styles[:stroke]
113
- width = styles[:stroke_width]
114
- return nil unless color && color != 'none'
115
- return nil unless width && width != 0
116
-
117
- {
118
- color: parse_color(color),
119
- width: s2f(width),
120
- dash: STROKE_DASH[styles[:stroke_type].to_sym]
121
- }
122
- end
123
-
124
- # @param [Hash] styles
125
- # @return [Hash, nil]
126
- def build_fill_styles(styles)
127
- color = styles[:fill]
128
- return nil unless color && color != 'none'
129
-
130
- { color: parse_color(color) }
131
- end
132
- end
133
- end
134
- end
135
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tempfile'
4
- require 'base64'
5
- require 'digest/md5'
6
-
7
- module Thinreports
8
- module Generator
9
- class PDF
10
- module Graphics
11
- # @param [String, IO] filename_or_io
12
- # @param [Numeric, Strng] x
13
- # @param [Numeric, Strng] y
14
- # @param [Numeric, Strng] w
15
- # @param [Numeric, Strng] h
16
- def image(filename_or_io, x, y, w, h)
17
- w, h = s2f(w, h)
18
- pdf.image(filename_or_io, at: pos(x, y), width: w, height: h)
19
- end
20
-
21
- # @param [String] base64_data
22
- # @param [Numeric, Strng] x
23
- # @param [Numeric, Strng] y
24
- # @param [Numeric, Strng] w
25
- # @param [Numeric, Strng] h
26
- def base64image(base64_data, x, y, w, h)
27
- image_data = Base64.decode64(base64_data)
28
- image_id = Digest::MD5.hexdigest(base64_data)
29
- image_path = create_temp_imagefile(image_id, image_data)
30
-
31
- image(image_path, x, y, w, h)
32
- end
33
-
34
- # @param [String, IO] filename_or_io
35
- # @param [Numeric, Strng] x
36
- # @param [Numeric, Strng] y
37
- # @param [Numeric, Strng] w
38
- # @param [Numeric, Strng] h
39
- # @param [Hash] options
40
- # @option options [:left, :center, :right] :position_x (:left)
41
- # @option options [:top, :center, :bottom] :position_y (:top)
42
- # @option options [Numeric] :offset_x
43
- # @option options [Numeric] :offset_y
44
- def image_box(filename_or_io, x, y, w, h, options = {})
45
- w, h = s2f(w, h)
46
-
47
- computed_position = pos(
48
- x + (options[:offset_x] || 0),
49
- y + (options[:offset_y] || 0)
50
- )
51
- pdf.bounding_box(computed_position, width: w, height: h) do
52
- pdf.image(
53
- filename_or_io,
54
- position: options[:position_x] || :left,
55
- vposition: options[:position_y] || :top,
56
- auto_fit: [w, h]
57
- )
58
- end
59
- end
60
-
61
- def image_dimensions(filename_or_io, x, y, w, h, options = {})
62
- w, h = s2f(w, h)
63
- # XXX: Calling @private method
64
- _pdf_obj, info = pdf.build_image_object(filename_or_io)
65
- info.calc_image_dimensions(
66
- position: options[:position_x] || :left,
67
- vposition: options[:position_y] || :top,
68
- auto_fit: [w, h]
69
- )
70
- end
71
-
72
- def clean_temp_images
73
- temp_image_registry.each_value do |image_path|
74
- File.delete(image_path) if File.exist?(image_path)
75
- end
76
- end
77
-
78
- def temp_image_registry
79
- @temp_image_registry ||= {}
80
- end
81
-
82
- # @param [String] image_id
83
- # @param [String] image_data
84
- # @return [String] Path to imagefile
85
- def create_temp_imagefile(image_id, image_data)
86
- temp_image_registry[image_id] ||= begin
87
- file = Tempfile.new('temp-image')
88
- file.binmode
89
- file.write(image_data)
90
- file.open
91
- file
92
- end
93
- temp_image_registry[image_id].path
94
- end
95
- end
96
- end
97
- end
98
- end
@@ -1,178 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Thinreports
4
- module Generator
5
- class PDF
6
- module Graphics
7
- # @param [String] content
8
- # @param [Numeric, String] x
9
- # @param [Numeric, String] y
10
- # @param [Numeric, String] w
11
- # @param [Numeric, String] h
12
- # @param [Hash] attrs ({})
13
- # @option attrs [String] :font
14
- # @option attrs [Numeric, String] :size
15
- # @option attrs [String] :color
16
- # @option attrs [Array<:bold, :italic, :underline, :strikethrough>]
17
- # :styles (nil)
18
- # @option attrs [:left, :center, :right] :align (:left)
19
- # @option attrs [:top, :center, :bottom] :valign (:top)
20
- # @option attrs [Numeric, String] :line_height The total height of an text line.
21
- # @option attrs [Numeric, String] :letter_spacing
22
- # @option attrs [Boolean] :single (false)
23
- # @option attrs [:trancate, :shrink_to_fit, :expand] :overflow (:trancate)
24
- # @option attrs [:none, :break_word] :word_wrap (:none)
25
- def text_box(content, x, y, w, h, attrs = {}, &block)
26
- w, h = s2f(w, h)
27
-
28
- box_attrs = text_box_attrs(
29
- x, y, w, h,
30
- single: attrs.delete(:single),
31
- overflow: attrs[:overflow]
32
- )
33
-
34
- # Do not break by word unless :word_wrap is :break_word
35
- content = text_without_line_wrap(content) if attrs[:word_wrap] == :none
36
-
37
- with_text_styles(attrs) do |built_attrs, font_styles|
38
- if block
39
- block.call [{ text: content, styles: font_styles }],
40
- built_attrs.merge(box_attrs)
41
- else
42
- pdf.formatted_text_box(
43
- [{ text: content, styles: font_styles }],
44
- built_attrs.merge(box_attrs)
45
- )
46
- end
47
- end
48
- rescue Prawn::Errors::CannotFit
49
- # Nothing to do.
50
- #
51
- # When the area is too small compared
52
- # with the content and the style of the text.
53
- # (See prawn/core/text/formatted/line_wrap.rb#L185)
54
- end
55
-
56
- # @see #text_box
57
- def text(content, x, y, w, h, attrs = {})
58
- # Set the :overflow property to :shirink_to_fit.
59
- text_box(content, x, y, w, h, { overflow: :shirink_to_fit }.merge(attrs))
60
- end
61
-
62
- private
63
-
64
- # @param x (see #text_box)
65
- # @param y (see #text_box)
66
- # @param w (see #text_box)
67
- # @param h (see #text_box)
68
- # @param [Hash] states
69
- # @option states [Boolean] :single
70
- # @option states [Symbold] :overflow
71
- # @return [Hash]
72
- def text_box_attrs(x, y, w, h, states = {})
73
- attrs = {
74
- at: pos(x, y),
75
- width: s2f(w)
76
- }
77
- if states[:single]
78
- states[:overflow] != :expand ? attrs.merge(single_line: true) : attrs
79
- else
80
- attrs.merge(height: s2f(h))
81
- end
82
- end
83
-
84
- # @param attrs (see #text)
85
- # @yield [built_attrs, font_styles]
86
- # @yieldparam [Hash] built_attrs The finalized attributes.
87
- # @yieldparam [Array] font_styles The finalized styles.
88
- def with_text_styles(attrs, &block)
89
- # When no color is given, do not draw.
90
- return unless attrs.key?(:color) && attrs[:color] != 'none'
91
-
92
- save_graphics_state
93
-
94
- fontinfo = {
95
- name: attrs.delete(:font).to_s,
96
- color: parse_color(attrs.delete(:color)),
97
- size: s2f(attrs.delete(:size))
98
- }
99
-
100
- # Add the specified value to :leading option.
101
- line_height = attrs.delete(:line_height)
102
- if line_height
103
- attrs[:leading] = text_line_leading(
104
- s2f(line_height),
105
- name: fontinfo[:name],
106
- size: fontinfo[:size]
107
- )
108
- end
109
-
110
- # Set the :character_spacing option.
111
- spacing = attrs.delete(:letter_spacing)
112
- attrs[:character_spacing] = s2f(spacing) if spacing
113
-
114
- # Or... with_font_styles(attrs, fontinfo, &block)
115
- with_font_styles(attrs, fontinfo) do |modified_attrs, styles|
116
- block.call(modified_attrs, styles)
117
- end
118
-
119
- restore_graphics_state
120
- end
121
-
122
- # @param [Numeric] line_height
123
- # @param [Hash] font
124
- # @option font [String] :name Name of font.
125
- # @option font [Numeric] :size Size of font.
126
- # @return [Numeric]
127
- def text_line_leading(line_height, font)
128
- line_height - pdf.font(font[:name], size: font[:size]).height
129
- end
130
-
131
- # @param [String] content
132
- # @return [String]
133
- def text_without_line_wrap(content)
134
- content.gsub(/ /, Prawn::Text::NBSP)
135
- end
136
-
137
- # @param [Hash] attrs
138
- # @param [Hash] font
139
- # @option font [String] :color
140
- # @option font [Numeric] :size
141
- # @option font [String] :name
142
- # @yield [attributes, styles]
143
- # @yieldparam [Hash] modified_attrs
144
- # @yieldparam [Array] styles
145
- def with_font_styles(attrs, font, &block)
146
- # Building font styles.
147
- styles = attrs.delete(:styles)
148
-
149
- if styles
150
- manual, styles = styles.partition do |style|
151
- %i[bold italic].include?(style) && !font_has_style?(font[:name], style)
152
- end
153
- end
154
-
155
- # Emulate bold style.
156
- if manual && manual.include?(:bold)
157
- pdf.stroke_color(font[:color])
158
- pdf.line_width(font[:size] * 0.025)
159
-
160
- # Change rendering mode to :fill_stroke.
161
- attrs[:mode] = :fill_stroke
162
- end
163
-
164
- # Emulate italic style.
165
- if manual && manual.include?(:italic)
166
- # FIXME
167
- # pdf.transformation_matrix(1, 0, 0.26, 1, 0, 0)
168
- end
169
-
170
- pdf.font(font[:name], size: font[:size]) do
171
- pdf.fill_color(font[:color])
172
- block.call(attrs, styles || [])
173
- end
174
- end
175
- end
176
- end
177
- end
178
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Thinreports
4
- module Generator
5
- class PDF
6
- module Graphics
7
- BASE_LINE_WIDTH = 0.9
8
-
9
- private
10
-
11
- # Change the default graphic states defined by Prawn.
12
- def setup_custom_graphic_states
13
- pdf.line_width(BASE_LINE_WIDTH)
14
- end
15
-
16
- # @param [Numeric] width
17
- def line_width(width)
18
- pdf.line_width(width * BASE_LINE_WIDTH)
19
- end
20
-
21
- # Delegate to Prawn::Document#save_graphic_state
22
- # @see Prawn::Document#save_graphics_state
23
- def save_graphics_state
24
- pdf.save_graphics_state
25
- end
26
-
27
- # Delegate to Prawn::Document#restore_graphic_state
28
- # @see Prawn::Document#restore_graphics_state
29
- def restore_graphics_state
30
- pdf.restore_graphics_state
31
- end
32
- end
33
- end
34
- end
35
- end
36
-
37
- require_relative 'graphics/attributes'
38
- require_relative 'graphics/basic'
39
- require_relative 'graphics/image'
40
- require_relative 'graphics/text'