hexapdf 0.11.8 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +126 -0
  3. data/LICENSE +1 -1
  4. data/examples/001-hello_world.rb +1 -1
  5. data/examples/002-graphics.rb +1 -1
  6. data/examples/003-arcs.rb +1 -1
  7. data/examples/004-optimizing.rb +1 -1
  8. data/examples/005-merging.rb +1 -1
  9. data/examples/006-standard_pdf_fonts.rb +1 -1
  10. data/examples/007-truetype.rb +1 -1
  11. data/examples/008-show_char_bboxes.rb +1 -1
  12. data/examples/009-text_layouter_alignment.rb +1 -1
  13. data/examples/010-text_layouter_inline_boxes.rb +1 -1
  14. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  15. data/examples/012-text_layouter_styling.rb +1 -1
  16. data/examples/013-text_layouter_shapes.rb +1 -1
  17. data/examples/014-text_in_polygon.rb +1 -1
  18. data/examples/015-boxes.rb +1 -1
  19. data/examples/016-frame_automatic_box_placement.rb +1 -1
  20. data/examples/017-frame_text_flow.rb +1 -1
  21. data/examples/018-composer.rb +1 -1
  22. data/examples/019-acro_form.rb +51 -0
  23. data/lib/hexapdf.rb +1 -1
  24. data/lib/hexapdf/cli.rb +3 -1
  25. data/lib/hexapdf/cli/batch.rb +1 -1
  26. data/lib/hexapdf/cli/command.rb +18 -9
  27. data/lib/hexapdf/cli/files.rb +1 -1
  28. data/lib/hexapdf/cli/form.rb +240 -0
  29. data/lib/hexapdf/cli/image2pdf.rb +1 -1
  30. data/lib/hexapdf/cli/images.rb +1 -1
  31. data/lib/hexapdf/cli/info.rb +1 -1
  32. data/lib/hexapdf/cli/inspect.rb +1 -1
  33. data/lib/hexapdf/cli/merge.rb +1 -1
  34. data/lib/hexapdf/cli/modify.rb +1 -1
  35. data/lib/hexapdf/cli/optimize.rb +1 -1
  36. data/lib/hexapdf/cli/split.rb +1 -1
  37. data/lib/hexapdf/cli/watermark.rb +1 -1
  38. data/lib/hexapdf/composer.rb +2 -2
  39. data/lib/hexapdf/configuration.rb +66 -11
  40. data/lib/hexapdf/content.rb +3 -1
  41. data/lib/hexapdf/content/canvas.rb +5 -18
  42. data/lib/hexapdf/content/color_space.rb +111 -32
  43. data/lib/hexapdf/content/graphic_object.rb +1 -1
  44. data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
  45. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  46. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  47. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  48. data/lib/hexapdf/content/graphics_state.rb +1 -1
  49. data/lib/hexapdf/content/operator.rb +9 -9
  50. data/lib/hexapdf/content/parser.rb +18 -5
  51. data/lib/hexapdf/content/processor.rb +1 -1
  52. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  53. data/lib/hexapdf/data_dir.rb +1 -1
  54. data/lib/hexapdf/dictionary.rb +1 -1
  55. data/lib/hexapdf/dictionary_fields.rb +1 -1
  56. data/lib/hexapdf/document.rb +14 -5
  57. data/lib/hexapdf/document/files.rb +1 -1
  58. data/lib/hexapdf/document/fonts.rb +1 -1
  59. data/lib/hexapdf/document/images.rb +1 -1
  60. data/lib/hexapdf/document/pages.rb +3 -14
  61. data/lib/hexapdf/encryption.rb +1 -1
  62. data/lib/hexapdf/encryption/aes.rb +1 -1
  63. data/lib/hexapdf/encryption/arc4.rb +1 -1
  64. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  65. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  66. data/lib/hexapdf/encryption/identity.rb +1 -1
  67. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  68. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  69. data/lib/hexapdf/encryption/security_handler.rb +7 -1
  70. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
  71. data/lib/hexapdf/error.rb +1 -1
  72. data/lib/hexapdf/filter.rb +3 -3
  73. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  74. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  75. data/lib/hexapdf/filter/encryption.rb +1 -1
  76. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  77. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  78. data/lib/hexapdf/filter/{jpx_decode.rb → pass_through.rb} +5 -5
  79. data/lib/hexapdf/filter/predictor.rb +1 -1
  80. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  81. data/lib/hexapdf/font/cmap.rb +1 -1
  82. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  83. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  84. data/lib/hexapdf/font/encoding.rb +1 -1
  85. data/lib/hexapdf/font/encoding/base.rb +9 -1
  86. data/lib/hexapdf/font/encoding/difference_encoding.rb +7 -1
  87. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  88. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  89. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  90. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  91. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  92. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  93. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  94. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  95. data/lib/hexapdf/font/true_type.rb +1 -1
  96. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  97. data/lib/hexapdf/font/true_type/font.rb +1 -1
  98. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  99. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  100. data/lib/hexapdf/font/true_type/table.rb +1 -1
  101. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  102. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  103. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  104. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  105. data/lib/hexapdf/font/true_type/table/head.rb +1 -1
  106. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  107. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  108. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  109. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  110. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  111. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  112. data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
  113. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  114. data/lib/hexapdf/font/true_type_wrapper.rb +54 -51
  115. data/lib/hexapdf/font/type1.rb +1 -1
  116. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  117. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  118. data/lib/hexapdf/font/type1/font.rb +1 -1
  119. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  120. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  121. data/lib/hexapdf/font/type1_wrapper.rb +68 -52
  122. data/lib/hexapdf/font_loader.rb +1 -1
  123. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  124. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  125. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  126. data/lib/hexapdf/image_loader.rb +1 -1
  127. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  128. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  129. data/lib/hexapdf/image_loader/png.rb +1 -1
  130. data/lib/hexapdf/importer.rb +2 -4
  131. data/lib/hexapdf/layout.rb +1 -1
  132. data/lib/hexapdf/layout/box.rb +1 -1
  133. data/lib/hexapdf/layout/frame.rb +1 -1
  134. data/lib/hexapdf/layout/image_box.rb +1 -1
  135. data/lib/hexapdf/layout/inline_box.rb +1 -1
  136. data/lib/hexapdf/layout/line.rb +1 -1
  137. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  138. data/lib/hexapdf/layout/style.rb +1 -1
  139. data/lib/hexapdf/layout/text_box.rb +1 -1
  140. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  141. data/lib/hexapdf/layout/text_layouter.rb +1 -1
  142. data/lib/hexapdf/layout/text_shaper.rb +1 -1
  143. data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
  144. data/lib/hexapdf/name_tree_node.rb +1 -1
  145. data/lib/hexapdf/number_tree_node.rb +1 -1
  146. data/lib/hexapdf/object.rb +2 -2
  147. data/lib/hexapdf/parser.rb +4 -3
  148. data/lib/hexapdf/pdf_array.rb +1 -1
  149. data/lib/hexapdf/rectangle.rb +31 -1
  150. data/lib/hexapdf/reference.rb +1 -1
  151. data/lib/hexapdf/revision.rb +2 -1
  152. data/lib/hexapdf/revisions.rb +1 -1
  153. data/lib/hexapdf/serializer.rb +1 -1
  154. data/lib/hexapdf/stream.rb +1 -1
  155. data/lib/hexapdf/task.rb +1 -1
  156. data/lib/hexapdf/task/dereference.rb +1 -1
  157. data/lib/hexapdf/task/optimize.rb +1 -1
  158. data/lib/hexapdf/tokenizer.rb +5 -4
  159. data/lib/hexapdf/type.rb +1 -1
  160. data/lib/hexapdf/type/acro_form.rb +7 -1
  161. data/lib/hexapdf/type/acro_form/appearance_generator.rb +405 -0
  162. data/lib/hexapdf/type/acro_form/button_field.rb +305 -0
  163. data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
  164. data/lib/hexapdf/type/acro_form/field.rb +220 -17
  165. data/lib/hexapdf/type/acro_form/form.rb +157 -7
  166. data/lib/hexapdf/type/acro_form/text_field.rb +186 -0
  167. data/lib/hexapdf/type/acro_form/variable_text_field.rb +122 -0
  168. data/lib/hexapdf/type/action.rb +1 -1
  169. data/lib/hexapdf/type/actions.rb +1 -1
  170. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  171. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  172. data/lib/hexapdf/type/actions/launch.rb +1 -1
  173. data/lib/hexapdf/type/actions/uri.rb +1 -1
  174. data/lib/hexapdf/type/annotation.rb +73 -3
  175. data/lib/hexapdf/type/annotations.rb +1 -1
  176. data/lib/hexapdf/type/annotations/link.rb +2 -2
  177. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  178. data/lib/hexapdf/type/annotations/text.rb +1 -1
  179. data/lib/hexapdf/type/annotations/widget.rb +239 -2
  180. data/lib/hexapdf/type/catalog.rb +21 -1
  181. data/lib/hexapdf/type/cid_font.rb +1 -1
  182. data/lib/hexapdf/type/embedded_file.rb +1 -1
  183. data/lib/hexapdf/type/file_specification.rb +1 -1
  184. data/lib/hexapdf/type/font.rb +18 -1
  185. data/lib/hexapdf/type/font_descriptor.rb +2 -2
  186. data/lib/hexapdf/type/font_simple.rb +1 -1
  187. data/lib/hexapdf/type/font_true_type.rb +1 -1
  188. data/lib/hexapdf/type/font_type0.rb +1 -1
  189. data/lib/hexapdf/type/font_type1.rb +16 -1
  190. data/lib/hexapdf/type/font_type3.rb +1 -1
  191. data/lib/hexapdf/type/form.rb +10 -1
  192. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  193. data/lib/hexapdf/type/icon_fit.rb +1 -1
  194. data/lib/hexapdf/type/image.rb +3 -1
  195. data/lib/hexapdf/type/info.rb +1 -1
  196. data/lib/hexapdf/type/names.rb +1 -1
  197. data/lib/hexapdf/type/object_stream.rb +1 -1
  198. data/lib/hexapdf/type/page.rb +20 -5
  199. data/lib/hexapdf/type/page_tree_node.rb +8 -11
  200. data/lib/hexapdf/type/resources.rb +16 -3
  201. data/lib/hexapdf/type/trailer.rb +2 -3
  202. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  203. data/lib/hexapdf/type/xref_stream.rb +1 -1
  204. data/lib/hexapdf/utils/bit_field.rb +38 -24
  205. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  206. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  207. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  208. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  209. data/lib/hexapdf/utils/object_hash.rb +1 -1
  210. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  211. data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
  212. data/lib/hexapdf/version.rb +2 -2
  213. data/lib/hexapdf/writer.rb +1 -1
  214. data/lib/hexapdf/xref_section.rb +1 -1
  215. data/test/hexapdf/common_tokenizer_tests.rb +5 -0
  216. data/test/hexapdf/content/common.rb +2 -2
  217. data/test/hexapdf/content/test_color_space.rb +71 -8
  218. data/test/hexapdf/content/test_operator.rb +22 -22
  219. data/test/hexapdf/content/test_parser.rb +14 -0
  220. data/test/hexapdf/document/test_fonts.rb +1 -1
  221. data/test/hexapdf/document/test_pages.rb +6 -6
  222. data/test/hexapdf/encryption/test_security_handler.rb +4 -0
  223. data/test/hexapdf/font/encoding/test_base.rb +10 -0
  224. data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
  225. data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
  226. data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
  227. data/test/hexapdf/layout/test_style.rb +1 -1
  228. data/test/hexapdf/test_document.rb +12 -0
  229. data/test/hexapdf/test_parser.rb +10 -0
  230. data/test/hexapdf/test_rectangle.rb +14 -0
  231. data/test/hexapdf/test_revision.rb +3 -0
  232. data/test/hexapdf/test_writer.rb +2 -2
  233. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +522 -0
  234. data/test/hexapdf/type/acro_form/test_button_field.rb +281 -0
  235. data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
  236. data/test/hexapdf/type/acro_form/test_field.rb +124 -6
  237. data/test/hexapdf/type/acro_form/test_form.rb +189 -22
  238. data/test/hexapdf/type/acro_form/test_text_field.rb +119 -0
  239. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
  240. data/test/hexapdf/type/annotations/test_text.rb +1 -1
  241. data/test/hexapdf/type/annotations/test_widget.rb +199 -0
  242. data/test/hexapdf/type/test_annotation.rb +45 -0
  243. data/test/hexapdf/type/test_catalog.rb +18 -0
  244. data/test/hexapdf/type/test_font.rb +5 -0
  245. data/test/hexapdf/type/test_font_type1.rb +8 -0
  246. data/test/hexapdf/type/test_form.rb +18 -0
  247. data/test/hexapdf/type/test_image.rb +7 -0
  248. data/test/hexapdf/type/test_page.rb +37 -6
  249. data/test/hexapdf/type/test_page_tree_node.rb +20 -12
  250. data/test/hexapdf/type/test_resources.rb +20 -0
  251. data/test/hexapdf/type/test_trailer.rb +4 -0
  252. data/test/hexapdf/utils/test_bit_field.rb +13 -1
  253. data/test/test_helper.rb +1 -1
  254. metadata +38 -18
  255. data/lib/hexapdf/filter/dct_decode.rb +0 -60
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -44,6 +44,8 @@ module HexaPDF
44
44
  autoload(:Canvas, 'hexapdf/content/canvas')
45
45
  autoload(:Parser, 'hexapdf/content/parser')
46
46
  autoload(:Processor, 'hexapdf/content/processor')
47
+ autoload(:ColorSpace, 'hexapdf/content/color_space')
48
+ autoload(:Operator, 'hexapdf/content/operator')
47
49
 
48
50
  end
49
51
 
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -1607,13 +1607,13 @@ module HexaPDF
1607
1607
  # See: PDF1.7 s9.2.2
1608
1608
  def font(name = nil, size: nil, **options)
1609
1609
  if name
1610
- @font = (name.respond_to?(:dict) ? name : context.document.fonts.add(name, **options))
1610
+ @font = (name.respond_to?(:pdf_object) ? name : context.document.fonts.add(name, **options))
1611
1611
  if size
1612
1612
  font_size(size)
1613
1613
  else
1614
1614
  size = font_size
1615
1615
  raise HexaPDF::Error, "No valid font size set" if size <= 0
1616
- invoke_font_operator(@font.dict, size)
1616
+ invoke_font_operator(@font.pdf_object, size)
1617
1617
  end
1618
1618
  self
1619
1619
  else
@@ -1644,7 +1644,7 @@ module HexaPDF
1644
1644
  unless @font
1645
1645
  raise HexaPDF::Error, "A font needs to be set before the font size can be set"
1646
1646
  end
1647
- invoke_font_operator(@font.dict, size)
1647
+ invoke_font_operator(@font.pdf_object, size)
1648
1648
  self
1649
1649
  else
1650
1650
  graphics_state.font_size
@@ -1855,7 +1855,7 @@ module HexaPDF
1855
1855
  elsif spec.length == 1 && spec[0].respond_to?(:color_space)
1856
1856
  spec[0]
1857
1857
  else
1858
- resources.color_space(color_space_for_components(spec)).color(*spec)
1858
+ resources.color_space(ColorSpace.for_components(spec)).color(*spec)
1859
1859
  end
1860
1860
  end
1861
1861
 
@@ -1993,19 +1993,6 @@ module HexaPDF
1993
1993
  end
1994
1994
  end
1995
1995
 
1996
- # Returns the name of the device color space that should be used for creating a color object
1997
- # from the components array.
1998
- def color_space_for_components(components)
1999
- case components.length
2000
- when 1 then :DeviceGray
2001
- when 3 then :DeviceRGB
2002
- when 4 then :DeviceCMYK
2003
- else
2004
- raise ArgumentError, "Invalid number of color components, 1|3|4 expected, " \
2005
- "#{components.length} given"
2006
- end
2007
- end
2008
-
2009
1996
  # Utility method that abstracts the implementation of a graphics state parameter
2010
1997
  # getter/setter method with a call sequence of:
2011
1998
  #
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -35,6 +35,7 @@
35
35
  #++
36
36
 
37
37
  require 'hexapdf/error'
38
+ require 'hexapdf/configuration'
38
39
 
39
40
  module HexaPDF
40
41
  module Content
@@ -71,14 +72,18 @@ module HexaPDF
71
72
  # Returns the PDF name of the color space family this color space belongs to.
72
73
  #
73
74
  # #definition::
74
- # Returns the color space definition as array.
75
+ # Returns the color space definition as array or symbol.
75
76
  #
76
77
  # #default_color::
77
78
  # Returns the default color for this color space.
78
79
  #
79
80
  # #color(*args)::
80
- # Returns the color corresponding to the given arguments. The number and types of the
81
- # arguments differ from one color space to another.
81
+ # Returns the color corresponding to the given arguments which may be normalized to conform to
82
+ # the PDF spec. The number and types of the arguments differ from one color space to another.
83
+ #
84
+ # #prenormalized_color(*args)::
85
+ # Returns the color corresponding to the given arguments without applying value normalization.
86
+ # The number and types of the arguments differ from one color space to another.
82
87
  #
83
88
  # The class representing a color in the color space needs to respond to the following methods:
84
89
  #
@@ -91,6 +96,52 @@ module HexaPDF
91
96
  # See: PDF1.7 s8.6
92
97
  module ColorSpace
93
98
 
99
+ # :call-seq:
100
+ # ColorSpace.device_color_from_specification(gray) => color
101
+ # ColorSpace.device_color_from_specification(r, g, b) => color
102
+ # ColorSpace.device_color_from_specification(c, m, y, k) => color
103
+ # ColorSpace.device_color_from_specification(string) => color
104
+ # ColorSpace.device_color_from_specification(array) => color
105
+ #
106
+ # Creates a device color object from the given color specification.
107
+ #
108
+ # There are several ways to define the color that should be used:
109
+ #
110
+ # * A single numeric argument specifies a gray color (see DeviceGray::Color).
111
+ # * Three numeric arguments specify an RGB color (see DeviceRGB::Color).
112
+ # * A string in the format "RRGGBB" where "RR" is the hexadecimal number for the red, "GG"
113
+ # for the green and "BB" for the blue color value also specifies an RGB color.
114
+ # * Four numeric arguments specify a CMYK color (see DeviceCMYK::Color).
115
+ # * An array is treated as if its items were specified separately as arguments.
116
+ #
117
+ # Note that it makes a difference whether integer or float values are used because the given
118
+ # values are first normalized - see DeviceGray#color, DeviceRGB#color and DeviceCMYK#color.
119
+ def self.device_color_from_specification(*spec)
120
+ spec.flatten!
121
+ spec = spec[0].scan(/../).map!(&:hex) if spec.length == 1 && spec[0].kind_of?(String)
122
+ GlobalConfiguration.constantize('color_space.map', for_components(spec)).new.color(*spec)
123
+ end
124
+
125
+ # Returns a device color object for the given components array without applying value
126
+ # normalization.
127
+ def self.prenormalized_device_color(components)
128
+ GlobalConfiguration.constantize('color_space.map', for_components(components)).new.
129
+ prenormalized_color(*components)
130
+ end
131
+
132
+ # Returns the name of the device color space that should be used for creating a color object
133
+ # from the components array.
134
+ def self.for_components(components)
135
+ case components.length
136
+ when 1 then :DeviceGray
137
+ when 3 then :DeviceRGB
138
+ when 4 then :DeviceCMYK
139
+ else
140
+ raise ArgumentError, "Invalid number of color components, 1|3|4 expected, " \
141
+ "#{components.length} given"
142
+ end
143
+ end
144
+
94
145
  # This module includes utility functions that are useful for all color classes.
95
146
  module ColorUtils
96
147
 
@@ -103,9 +154,10 @@ module HexaPDF
103
154
  # * If the color value is less than 0.0, it is set to 0.0.
104
155
  def normalize_value(value, upper)
105
156
  value = value.to_f / upper if value.kind_of?(Integer)
106
- (value < 0 ? 0.0 : (value > 1 ? 1.0 : value))
157
+ value.clamp(0, 1)
107
158
  end
108
159
  private :normalize_value
160
+ module_function :normalize_value
109
161
 
110
162
  # Compares this color to another one by looking at their associated color spaces and their
111
163
  # components.
@@ -137,6 +189,7 @@ module HexaPDF
137
189
  def color(*args)
138
190
  Color.new(self, *args)
139
191
  end
192
+ alias prenormalized_color color
140
193
 
141
194
  # Returns the PDF color space family this color space belongs to.
142
195
  def family
@@ -189,8 +242,22 @@ module HexaPDF
189
242
  Color.new(0.0, 0.0, 0.0)
190
243
  end
191
244
 
192
- # Returns the color object for the given red, green and blue components.
245
+ # Returns the color object for the red, green and blue components.
246
+ #
247
+ # Color values can either be integers in the range from 0 to 255 or floating point numbers
248
+ # between 0.0 and 1.0. The integer color values are automatically normalized to the
249
+ # DeviceRGB color value range of 0.0 to 1.0.
193
250
  def color(r, g, b)
251
+ Color.new(ColorUtils.normalize_value(r, 255),
252
+ ColorUtils.normalize_value(g, 255),
253
+ ColorUtils.normalize_value(b, 255))
254
+ end
255
+
256
+ # Returns the color object for the red, green and blue components without applying value
257
+ # normalization.
258
+ #
259
+ # See: #color
260
+ def prenormalized_color(r, g, b)
194
261
  Color.new(r, g, b)
195
262
  end
196
263
 
@@ -198,13 +265,10 @@ module HexaPDF
198
265
  def family
199
266
  :DeviceRGB
200
267
  end
268
+ alias definition family
201
269
 
202
270
  # A color in the DeviceRGB color space.
203
271
  #
204
- # Color values can either be integers in the range from 0 to 255 or floating point numbers
205
- # between 0.0 and 1.0. The integer color values are automatically normalized to the
206
- # DeviceRGB color value range of 0.0 to 1.0.
207
- #
208
272
  # See: PDF1.7 s8.6.4.3
209
273
  class Color
210
274
 
@@ -212,12 +276,11 @@ module HexaPDF
212
276
 
213
277
  # Initializes the color with the +r+ (red), +g+ (green) and +b+ (blue) components.
214
278
  #
215
- # Each argument has to be either an integer between 0 and 255 or a float between 0.0 and
216
- # 1.0.
279
+ # Each argument has to be a float between 0.0 and 1.0.
217
280
  def initialize(r, g, b)
218
- @r = normalize_value(r, 255)
219
- @g = normalize_value(g, 255)
220
- @b = normalize_value(b, 255)
281
+ @r = r
282
+ @g = g
283
+ @b = b
221
284
  end
222
285
 
223
286
  # Returns the DeviceRGB color space module.
@@ -251,7 +314,20 @@ module HexaPDF
251
314
  end
252
315
 
253
316
  # Returns the color object for the given cyan, magenta, yellow and black components.
317
+ #
318
+ # Color values can either be integers in the range from 0 to 100 or floating point numbers
319
+ # between 0.0 and 1.0. The integer color values are automatically normalized to the
320
+ # DeviceCMYK color value range of 0.0 to 1.0.
254
321
  def color(c, m, y, k)
322
+ Color.new(ColorUtils.normalize_value(c, 100), ColorUtils.normalize_value(m, 100),
323
+ ColorUtils.normalize_value(y, 100), ColorUtils.normalize_value(k, 100))
324
+ end
325
+
326
+ # Returns the color object for the cyan, magenta, yellow and black components without
327
+ # applying value normalization.
328
+ #
329
+ # See: #color
330
+ def prenormalized_color(c, m, y, k)
255
331
  Color.new(c, m, y, k)
256
332
  end
257
333
 
@@ -259,13 +335,10 @@ module HexaPDF
259
335
  def family
260
336
  :DeviceCMYK
261
337
  end
338
+ alias definition family
262
339
 
263
340
  # A color in the DeviceCMYK color space.
264
341
  #
265
- # Color values can either be integers in the range from 0 to 100 or floating point numbers
266
- # between 0.0 and 1.0. The integer color values are automatically normalized to the
267
- # DeviceCMYK color value range of 0.0 to 1.0.
268
- #
269
342
  # See: PDF1.7 s8.6.4.4
270
343
  class Color
271
344
 
@@ -274,13 +347,12 @@ module HexaPDF
274
347
  # Initializes the color with the +c+ (cyan), +m+ (magenta), +y+ (yellow) and +k+ (black)
275
348
  # components.
276
349
  #
277
- # Each argument has to be either an integer between 0 and 100 or a float between 0.0 and
278
- # 1.0.
350
+ # Each argument has to be a float between 0.0 and 1.0.
279
351
  def initialize(c, m, y, k)
280
- @c = normalize_value(c, 100)
281
- @m = normalize_value(m, 100)
282
- @y = normalize_value(y, 100)
283
- @k = normalize_value(k, 100)
352
+ @c = c
353
+ @m = m
354
+ @y = y
355
+ @k = k
284
356
  end
285
357
 
286
358
  # Returns the DeviceCMYK color space module.
@@ -314,7 +386,18 @@ module HexaPDF
314
386
  end
315
387
 
316
388
  # Returns the color object for the given gray component.
389
+ #
390
+ # Color values can either be integers in the range from 0 to 255 or floating point numbers
391
+ # between 0.0 and 1.0. The integer color values are automatically normalized to the
392
+ # DeviceGray color value range of 0.0 to 1.0.
317
393
  def color(gray)
394
+ Color.new(ColorUtils.normalize_value(gray, 255))
395
+ end
396
+
397
+ # Returns the color object for the gray component without applying value normalization.
398
+ #
399
+ # See: #color
400
+ def prenormalized_color(gray)
318
401
  Color.new(gray)
319
402
  end
320
403
 
@@ -322,13 +405,10 @@ module HexaPDF
322
405
  def family
323
406
  :DeviceGray
324
407
  end
408
+ alias definition family
325
409
 
326
410
  # A color in the DeviceGray color space.
327
411
  #
328
- # Color values can either be integers in the range from 0 to 255 or floating point numbers
329
- # between 0.0 and 1.0. The integer color values are automatically normalized to the
330
- # DeviceGray color value range of 0.0 to 1.0.
331
- #
332
412
  # See: PDF1.7 s8.6.4.2
333
413
  class Color
334
414
 
@@ -336,10 +416,9 @@ module HexaPDF
336
416
 
337
417
  # Initializes the color with the +gray+ component.
338
418
  #
339
- # The argument +gray+ has to be either an integer between 0 and 255 or a float between
340
- # 0.0 and 1.0.
419
+ # The argument +gray+ has to be a float between 0.0 and 1.0.
341
420
  def initialize(gray)
342
- @gray = normalize_value(gray, 255)
421
+ @gray = gray
343
422
  end
344
423
 
345
424
  # Returns the DeviceGray color space module.
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -397,7 +397,7 @@ module HexaPDF
397
397
 
398
398
  def invoke(processor, *operands) #:nodoc:
399
399
  processor.graphics_state.stroke_color =
400
- processor.graphics_state.stroke_color.color_space.color(*operands)
400
+ processor.graphics_state.stroke_color.color_space.prenormalized_color(*operands)
401
401
  end
402
402
 
403
403
  end
@@ -409,7 +409,7 @@ module HexaPDF
409
409
 
410
410
  def invoke(processor, *operands) #:nodoc:
411
411
  processor.graphics_state.fill_color =
412
- processor.graphics_state.fill_color.color_space.color(*operands)
412
+ processor.graphics_state.fill_color.color_space.prenormalized_color(*operands)
413
413
  end
414
414
 
415
415
  end
@@ -425,7 +425,7 @@ module HexaPDF
425
425
 
426
426
  def invoke(processor, gray) #:nodoc:
427
427
  processor.graphics_state.stroke_color =
428
- processor.resources.color_space(:DeviceGray).color(gray)
428
+ processor.resources.color_space(:DeviceGray).prenormalized_color(gray)
429
429
  end
430
430
 
431
431
  end
@@ -442,7 +442,7 @@ module HexaPDF
442
442
 
443
443
  def invoke(processor, gray) #:nodoc:
444
444
  processor.graphics_state.fill_color =
445
- processor.resources.color_space(:DeviceGray).color(gray)
445
+ processor.resources.color_space(:DeviceGray).prenormalized_color(gray)
446
446
  end
447
447
 
448
448
  end
@@ -459,7 +459,7 @@ module HexaPDF
459
459
 
460
460
  def invoke(processor, r, g, b) #:nodoc:
461
461
  processor.graphics_state.stroke_color =
462
- processor.resources.color_space(:DeviceRGB).color(r, g, b)
462
+ processor.resources.color_space(:DeviceRGB).prenormalized_color(r, g, b)
463
463
  end
464
464
 
465
465
  def serialize(serializer, r, g, b) #:nodoc:
@@ -481,7 +481,7 @@ module HexaPDF
481
481
 
482
482
  def invoke(processor, r, g, b) #:nodoc:
483
483
  processor.graphics_state.fill_color =
484
- processor.resources.color_space(:DeviceRGB).color(r, g, b)
484
+ processor.resources.color_space(:DeviceRGB).prenormalized_color(r, g, b)
485
485
  end
486
486
 
487
487
  def serialize(serializer, r, g, b) #:nodoc:
@@ -503,7 +503,7 @@ module HexaPDF
503
503
 
504
504
  def invoke(processor, c, m, y, k) #:nodoc:
505
505
  processor.graphics_state.stroke_color =
506
- processor.resources.color_space(:DeviceCMYK).color(c, m, y, k)
506
+ processor.resources.color_space(:DeviceCMYK).prenormalized_color(c, m, y, k)
507
507
  end
508
508
 
509
509
  def serialize(serializer, c, m, y, k) #:nodoc:
@@ -525,7 +525,7 @@ module HexaPDF
525
525
 
526
526
  def invoke(processor, c, m, y, k) #:nodoc:
527
527
  processor.graphics_state.fill_color =
528
- processor.resources.color_space(:DeviceCMYK).color(c, m, y, k)
528
+ processor.resources.color_space(:DeviceCMYK).prenormalized_color(c, m, y, k)
529
529
  end
530
530
 
531
531
  def serialize(serializer, c, m, y, k) #:nodoc: