hexapdf 0.11.7 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -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 +2 -2
  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 +1 -1
  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 +401 -0
  162. data/lib/hexapdf/type/acro_form/button_field.rb +300 -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/content/common.rb +2 -2
  216. data/test/hexapdf/content/test_color_space.rb +71 -8
  217. data/test/hexapdf/content/test_operator.rb +22 -22
  218. data/test/hexapdf/content/test_parser.rb +14 -0
  219. data/test/hexapdf/document/test_fonts.rb +1 -1
  220. data/test/hexapdf/document/test_pages.rb +6 -6
  221. data/test/hexapdf/encryption/test_security_handler.rb +4 -0
  222. data/test/hexapdf/font/encoding/test_base.rb +10 -0
  223. data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
  224. data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
  225. data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
  226. data/test/hexapdf/layout/test_style.rb +1 -1
  227. data/test/hexapdf/test_document.rb +12 -0
  228. data/test/hexapdf/test_parser.rb +10 -0
  229. data/test/hexapdf/test_rectangle.rb +14 -0
  230. data/test/hexapdf/test_revision.rb +3 -0
  231. data/test/hexapdf/test_serializer.rb +3 -3
  232. data/test/hexapdf/test_writer.rb +2 -2
  233. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +515 -0
  234. data/test/hexapdf/type/acro_form/test_button_field.rb +276 -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: