origami-docspring 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/examples/attachments/attachment.rb +7 -8
  4. data/examples/attachments/nested_document.rb +6 -5
  5. data/examples/encryption/encryption.rb +5 -4
  6. data/examples/events/events.rb +7 -6
  7. data/examples/flash/flash.rb +10 -9
  8. data/examples/forms/javascript.rb +14 -13
  9. data/examples/forms/xfa.rb +67 -66
  10. data/examples/javascript/hello_world.rb +6 -5
  11. data/examples/javascript/js_emulation.rb +26 -26
  12. data/examples/loop/goto.rb +12 -11
  13. data/examples/loop/named.rb +17 -16
  14. data/examples/signature/signature.rb +11 -11
  15. data/examples/uri/javascript.rb +25 -24
  16. data/examples/uri/open-uri.rb +5 -4
  17. data/examples/uri/submitform.rb +11 -10
  18. data/lib/origami/3d.rb +330 -334
  19. data/lib/origami/acroform.rb +267 -268
  20. data/lib/origami/actions.rb +266 -278
  21. data/lib/origami/annotations.rb +659 -670
  22. data/lib/origami/array.rb +192 -196
  23. data/lib/origami/boolean.rb +66 -70
  24. data/lib/origami/catalog.rb +360 -363
  25. data/lib/origami/collections.rb +132 -133
  26. data/lib/origami/compound.rb +125 -129
  27. data/lib/origami/destinations.rb +226 -237
  28. data/lib/origami/dictionary.rb +155 -154
  29. data/lib/origami/encryption.rb +967 -923
  30. data/lib/origami/extensions/fdf.rb +270 -275
  31. data/lib/origami/extensions/ppklite.rb +323 -328
  32. data/lib/origami/filespec.rb +170 -173
  33. data/lib/origami/filters/ascii.rb +162 -167
  34. data/lib/origami/filters/ccitt/tables.rb +248 -252
  35. data/lib/origami/filters/ccitt.rb +309 -312
  36. data/lib/origami/filters/crypt.rb +31 -34
  37. data/lib/origami/filters/dct.rb +47 -50
  38. data/lib/origami/filters/flate.rb +57 -60
  39. data/lib/origami/filters/jbig2.rb +50 -53
  40. data/lib/origami/filters/jpx.rb +40 -43
  41. data/lib/origami/filters/lzw.rb +151 -155
  42. data/lib/origami/filters/predictors.rb +250 -255
  43. data/lib/origami/filters/runlength.rb +111 -115
  44. data/lib/origami/filters.rb +319 -325
  45. data/lib/origami/font.rb +173 -177
  46. data/lib/origami/functions.rb +62 -66
  47. data/lib/origami/graphics/colors.rb +203 -208
  48. data/lib/origami/graphics/instruction.rb +79 -81
  49. data/lib/origami/graphics/path.rb +141 -144
  50. data/lib/origami/graphics/patterns.rb +156 -160
  51. data/lib/origami/graphics/render.rb +51 -47
  52. data/lib/origami/graphics/state.rb +144 -142
  53. data/lib/origami/graphics/text.rb +185 -188
  54. data/lib/origami/graphics/xobject.rb +818 -804
  55. data/lib/origami/graphics.rb +25 -26
  56. data/lib/origami/header.rb +63 -65
  57. data/lib/origami/javascript.rb +718 -651
  58. data/lib/origami/linearization.rb +284 -285
  59. data/lib/origami/metadata.rb +156 -135
  60. data/lib/origami/name.rb +98 -100
  61. data/lib/origami/null.rb +49 -51
  62. data/lib/origami/numeric.rb +133 -135
  63. data/lib/origami/obfuscation.rb +180 -182
  64. data/lib/origami/object.rb +634 -631
  65. data/lib/origami/optionalcontent.rb +147 -149
  66. data/lib/origami/outline.rb +46 -48
  67. data/lib/origami/outputintents.rb +76 -77
  68. data/lib/origami/page.rb +637 -596
  69. data/lib/origami/parser.rb +214 -221
  70. data/lib/origami/parsers/fdf.rb +44 -45
  71. data/lib/origami/parsers/pdf/lazy.rb +147 -154
  72. data/lib/origami/parsers/pdf/linear.rb +104 -109
  73. data/lib/origami/parsers/pdf.rb +109 -107
  74. data/lib/origami/parsers/ppklite.rb +44 -46
  75. data/lib/origami/pdf.rb +886 -896
  76. data/lib/origami/reference.rb +116 -120
  77. data/lib/origami/signature.rb +617 -625
  78. data/lib/origami/stream.rb +560 -558
  79. data/lib/origami/string.rb +366 -368
  80. data/lib/origami/template/patterns.rb +50 -52
  81. data/lib/origami/template/widgets.rb +111 -114
  82. data/lib/origami/trailer.rb +153 -157
  83. data/lib/origami/tree.rb +55 -57
  84. data/lib/origami/version.rb +19 -19
  85. data/lib/origami/webcapture.rb +87 -90
  86. data/lib/origami/xfa/config.rb +409 -414
  87. data/lib/origami/xfa/connectionset.rb +113 -117
  88. data/lib/origami/xfa/datasets.rb +38 -42
  89. data/lib/origami/xfa/localeset.rb +33 -37
  90. data/lib/origami/xfa/package.rb +49 -52
  91. data/lib/origami/xfa/pdf.rb +54 -59
  92. data/lib/origami/xfa/signature.rb +33 -37
  93. data/lib/origami/xfa/sourceset.rb +34 -38
  94. data/lib/origami/xfa/stylesheet.rb +35 -39
  95. data/lib/origami/xfa/template.rb +1630 -1634
  96. data/lib/origami/xfa/xdc.rb +33 -37
  97. data/lib/origami/xfa/xfa.rb +132 -123
  98. data/lib/origami/xfa/xfdf.rb +34 -38
  99. data/lib/origami/xfa/xmpmeta.rb +34 -38
  100. data/lib/origami/xfa.rb +50 -53
  101. data/lib/origami/xreftable.rb +462 -462
  102. data/lib/origami.rb +37 -38
  103. data/test/test_actions.rb +22 -20
  104. data/test/test_annotations.rb +54 -52
  105. data/test/test_forms.rb +23 -21
  106. data/test/test_native_types.rb +82 -78
  107. data/test/test_object_tree.rb +25 -24
  108. data/test/test_pages.rb +43 -41
  109. data/test/test_pdf.rb +2 -0
  110. data/test/test_pdf_attachment.rb +23 -21
  111. data/test/test_pdf_create.rb +16 -15
  112. data/test/test_pdf_encrypt.rb +69 -66
  113. data/test/test_pdf_parse.rb +131 -129
  114. data/test/test_pdf_parse_lazy.rb +53 -53
  115. data/test/test_pdf_sign.rb +67 -67
  116. data/test/test_streams.rb +145 -143
  117. data/test/test_xrefs.rb +46 -45
  118. metadata +64 -8
@@ -1,357 +1,354 @@
1
- =begin
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # This file is part of Origami, PDF manipulation framework for Ruby
5
+ # Copyright (C) 2016 Guillaume Delugré.
6
+ #
7
+ # Origami is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # Origami is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with Origami. If not, see <http://www.gnu.org/licenses/>.
19
+ #
2
20
 
3
- This file is part of Origami, PDF manipulation framework for Ruby
4
- Copyright (C) 2016 Guillaume Delugré.
21
+ require 'origami/filters/ccitt/tables'
5
22
 
6
- Origami is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU Lesser General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
23
+ module Origami
24
+ module Filter
25
+ class InvalidCCITTFaxDataError < DecodeError # :nodoc:
26
+ end
10
27
 
11
- Origami is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU Lesser General Public License for more details.
28
+ class CCITTFaxFilterError < Error # :nodoc:
29
+ end
15
30
 
16
- You should have received a copy of the GNU Lesser General Public License
17
- along with Origami. If not, see <http://www.gnu.org/licenses/>.
31
+ #
32
+ # Class representing a Filter used to encode and decode data with CCITT-facsimile compression algorithm.
33
+ #
34
+ class CCITTFax
35
+ include Filter
36
+
37
+ class DecodeParms < Dictionary
38
+ include StandardObject
39
+
40
+ field :K, Type: Integer, Default: 0
41
+ field :EndOfLine, Type: Boolean, Default: false
42
+ field :EncodedByteAlign, Type: Boolean, Default: false
43
+ field :Columns, Type: Integer, Default: 1728
44
+ field :Rows, Type: Integer, Default: 0
45
+ field :EndOfBlock, Type: Boolean, Default: true
46
+ field :BlackIs1, Type: Boolean, Default: false
47
+ field :DamagedRowsBeforeError, Type: :Integer, Default: 0
48
+ end
49
+
50
+ EOL = codeword('000000000001')
51
+ RTC = codeword('000000000001' * 6)
52
+
53
+ #
54
+ # Creates a new CCITT Fax Filter.
55
+ #
56
+ def initialize(parameters = {})
57
+ super(DecodeParms.new(parameters))
58
+ end
59
+
60
+ #
61
+ # Encodes data using CCITT-facsimile compression method.
62
+ #
63
+ def encode(stream)
64
+ mode = @params.key?(:K) ? @params.K.value : 0
65
+ colors = (@params.BlackIs1 == true) ? [0, 1] : [1, 0]
66
+ use_eob = (@params.EndOfBlock.nil? or @params.EndOfBlock == true)
67
+ use_eol = (@params.EndOfLine == true)
68
+ white, _black = colors
69
+
70
+ bitr = Utils::BitReader.new(stream)
71
+ bitw = Utils::BitWriter.new
72
+
73
+ unless mode.is_a?(::Integer) && (mode <= 0)
74
+ raise NotImplementedError.new("CCITT encoding scheme not supported", input_data: stream)
75
+ end
18
76
 
19
- =end
77
+ # Use a single row if no width has been set.
78
+ @params[:Columns] ||= stream.size * 8
79
+ columns = @params.Columns.value
20
80
 
21
- require 'origami/filters/ccitt/tables'
81
+ unless columns.is_a?(::Integer) && (columns >= 0)
82
+ raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
83
+ end
22
84
 
23
- module Origami
85
+ if columns > 0
86
+ # Group 4 requires an imaginary white line
87
+ if mode < 0
88
+ prev_line = Utils::BitWriter.new
89
+ write_bit_range(prev_line, white, columns)
90
+ prev_line = Utils::BitReader.new(prev_line.final.to_s)
91
+ end
92
+
93
+ until bitr.eod?
94
+ # Emit line synchronization code.
95
+ bitw.write(*EOL) if use_eol
96
+
97
+ if mode == 0
98
+ encode_one_dimensional_line(bitr, bitw, columns, colors)
99
+ elsif mode < 0
100
+ encode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
101
+ end
102
+ end
103
+ end
104
+
105
+ # Emit return-to-control code.
106
+ bitw.write(*RTC) if use_eob
107
+
108
+ bitw.final.to_s
109
+ end
24
110
 
25
- module Filter
111
+ #
112
+ # Decodes data using CCITT-facsimile compression method.
113
+ #
114
+ def decode(stream)
115
+ mode = @params.key?(:K) ? @params.K.value : 0
26
116
 
27
- class InvalidCCITTFaxDataError < DecodeError #:nodoc:
117
+ unless mode.is_a?(::Integer) && (mode <= 0)
118
+ raise NotImplementedError.new("CCITT encoding scheme not supported", input_data: stream)
28
119
  end
29
120
 
30
- class CCITTFaxFilterError < Error #:nodoc:
121
+ columns = @params.has_key?(:Columns) ? @params.Columns.value : 1728
122
+ unless columns.is_a?(::Integer) && (columns >= 0)
123
+ raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
31
124
  end
32
125
 
33
- #
34
- # Class representing a Filter used to encode and decode data with CCITT-facsimile compression algorithm.
35
- #
36
- class CCITTFax
37
- include Filter
38
-
39
- class DecodeParms < Dictionary
40
- include StandardObject
41
-
42
- field :K, :Type => Integer, :Default => 0
43
- field :EndOfLine, :Type => Boolean, :Default => false
44
- field :EncodedByteAlign, :Type => Boolean, :Default => false
45
- field :Columns, :Type => Integer, :Default => 1728
46
- field :Rows, :Type => Integer, :Default => 0
47
- field :EndOfBlock, :Type => Boolean, :Default => true
48
- field :BlackIs1, :Type => Boolean, :Default => false
49
- field :DamagedRowsBeforeError, :Type => :Integer, :Default => 0
50
- end
126
+ colors = (@params.BlackIs1 == true) ? [0, 1] : [1, 0]
127
+ white, _black = colors
128
+ params =
129
+ {
130
+ is_aligned?: (@params.EncodedByteAlign == true),
131
+ has_eob?: (@params.EndOfBlock.nil? or @params.EndOfBlock == true),
132
+ has_eol?: (@params.EndOfLine == true)
133
+ }
134
+
135
+ unless params[:has_eob?]
136
+ rows = @params.key?(:Rows) ? @params.Rows.value : 0
137
+
138
+ unless rows.is_a?(::Integer) && (rows >= 0)
139
+ raise CCITTFaxFilterError.new("Invalid value for parameter `Rows'", input_data: stream)
140
+ end
141
+ end
51
142
 
52
- EOL = codeword('000000000001')
53
- RTC = codeword('000000000001' * 6)
143
+ bitr = Utils::BitReader.new(stream)
144
+ bitw = Utils::BitWriter.new
54
145
 
55
- #
56
- # Creates a new CCITT Fax Filter.
57
- #
58
- def initialize(parameters = {})
59
- super(DecodeParms.new(parameters))
60
- end
146
+ # Group 4 requires an imaginary white line
147
+ if (columns > 0) && (mode < 0)
148
+ prev_line = Utils::BitWriter.new
149
+ write_bit_range(prev_line, white, columns)
150
+ prev_line = Utils::BitReader.new(prev_line.final.to_s)
151
+ end
61
152
 
62
- #
63
- # Encodes data using CCITT-facsimile compression method.
64
- #
65
- def encode(stream)
66
- mode = @params.key?(:K) ? @params.K.value : 0
67
- colors = (@params.BlackIs1 == true) ? [0,1] : [1,0]
68
- use_eob = (@params.EndOfBlock.nil? or @params.EndOfBlock == true)
69
- use_eol = (@params.EndOfLine == true)
70
- white, _black = colors
71
-
72
- bitr = Utils::BitReader.new(stream)
73
- bitw = Utils::BitWriter.new
74
-
75
- unless mode.is_a?(::Integer) and mode <= 0
76
- raise NotImplementedError.new("CCITT encoding scheme not supported", input_data: stream)
77
- end
78
-
79
- # Use a single row if no width has been set.
80
- @params[:Columns] ||= stream.size * 8
81
- columns = @params.Columns.value
82
-
83
- unless columns.is_a?(::Integer) and columns >= 0
84
- raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
85
- end
86
-
87
- if columns > 0
88
- # Group 4 requires an imaginary white line
89
- if mode < 0
90
- prev_line = Utils::BitWriter.new
91
- write_bit_range(prev_line, white, columns)
92
- prev_line = Utils::BitReader.new(prev_line.final.to_s)
93
- end
94
-
95
- until bitr.eod?
96
- # Emit line synchronization code.
97
- bitw.write(*EOL) if use_eol
98
-
99
- case
100
- when mode == 0
101
- encode_one_dimensional_line(bitr, bitw, columns, colors)
102
- when mode < 0
103
- encode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
104
- end
105
- end
106
- end
107
-
108
- # Emit return-to-control code.
109
- bitw.write(*RTC) if use_eob
110
-
111
- bitw.final.to_s
153
+ until bitr.eod? || (rows == 0)
154
+ # realign the read line on a 8-bit boundary if required
155
+ align_input(bitr) if params[:is_aligned?]
156
+
157
+ # received return-to-control code
158
+ if params[:has_eob?] && (bitr.peek(RTC[1]) == RTC[0])
159
+ bitr.pos += RTC[1]
160
+ break
161
+ end
162
+
163
+ break if columns == 0
164
+
165
+ # checking for the presence of EOL
166
+ if bitr.peek(EOL[1]) != EOL[0]
167
+ if params[:has_eol?]
168
+ raise InvalidCCITTFaxDataError.new(
169
+ "No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
170
+ input_data: stream,
171
+ decoded_data: bitw.final.to_s
172
+ )
112
173
  end
113
-
114
- #
115
- # Decodes data using CCITT-facsimile compression method.
116
- #
117
- def decode(stream)
118
- mode = @params.key?(:K) ? @params.K.value : 0
119
-
120
- unless mode.is_a?(::Integer) and mode <= 0
121
- raise NotImplementedError.new("CCITT encoding scheme not supported", input_data: stream)
122
- end
123
-
124
- columns = @params.has_key?(:Columns) ? @params.Columns.value : 1728
125
- unless columns.is_a?(::Integer) and columns >= 0
126
- raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
127
- end
128
-
129
- colors = (@params.BlackIs1 == true) ? [0,1] : [1,0]
130
- white, _black = colors
131
- params =
132
- {
133
- is_aligned?: (@params.EncodedByteAlign == true),
134
- has_eob?: (@params.EndOfBlock.nil? or @params.EndOfBlock == true),
135
- has_eol?: (@params.EndOfLine == true)
136
- }
137
-
138
- unless params[:has_eob?]
139
- rows = @params.key?(:Rows) ? @params.Rows.value : 0
140
-
141
- unless rows.is_a?(::Integer) and rows >= 0
142
- raise CCITTFaxFilterError.new("Invalid value for parameter `Rows'", input_data: stream)
143
- end
144
- end
145
-
146
- bitr = Utils::BitReader.new(stream)
147
- bitw = Utils::BitWriter.new
148
-
149
- # Group 4 requires an imaginary white line
150
- if columns > 0 and mode < 0
151
- prev_line = Utils::BitWriter.new
152
- write_bit_range(prev_line, white, columns)
153
- prev_line = Utils::BitReader.new(prev_line.final.to_s)
154
- end
155
-
156
- until bitr.eod? or rows == 0
157
- # realign the read line on a 8-bit boundary if required
158
- align_input(bitr) if params[:is_aligned?]
159
-
160
- # received return-to-control code
161
- if params[:has_eob?] and bitr.peek(RTC[1]) == RTC[0]
162
- bitr.pos += RTC[1]
163
- break
164
- end
165
-
166
- break if columns == 0
167
-
168
- # checking for the presence of EOL
169
- if bitr.peek(EOL[1]) != EOL[0]
170
- raise InvalidCCITTFaxDataError.new(
171
- "No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
172
- input_data: stream,
173
- decoded_data: bitw.final.to_s
174
- ) if params[:has_eol?]
175
- else
176
- bitr.pos += EOL[1]
177
- end
178
-
179
- begin
180
- case
181
- when mode == 0
182
- decode_one_dimensional_line(bitr, bitw, columns, colors)
183
- when mode < 0
184
- decode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
185
- end
186
- rescue DecodeError => error
187
- error.input_data = stream
188
- error.decoded_data = bitw.final.to_s
189
-
190
- raise error
191
- end
192
-
193
- rows -= 1 unless params[:has_eob?]
194
- end
195
-
196
- bitw.final.to_s
174
+ else
175
+ bitr.pos += EOL[1]
176
+ end
177
+
178
+ begin
179
+ if mode == 0
180
+ decode_one_dimensional_line(bitr, bitw, columns, colors)
181
+ elsif mode < 0
182
+ decode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
197
183
  end
184
+ rescue DecodeError => error
185
+ error.input_data = stream
186
+ error.decoded_data = bitw.final.to_s
198
187
 
199
- private
200
-
201
- def encode_one_dimensional_line(input, output, columns, colors) #:nodoc:
202
- scan_len = 0
203
- white, _black = colors
204
- current_color = white
205
- length = 0
206
-
207
- return if columns == 0
208
-
209
- # Process each bit in line.
210
- loop do
211
- if input.read(1) == current_color
212
- scan_len += 1
213
- else
214
- if current_color == white
215
- put_white_bits(output, scan_len)
216
- else
217
- put_black_bits(output, scan_len)
218
- end
219
-
220
- current_color ^= 1
221
- scan_len = 1
222
- end
223
-
224
- length += 1
225
- break if length == columns
226
- end
227
-
228
- if current_color == white
229
- put_white_bits(output, scan_len)
230
- else
231
- put_black_bits(output, scan_len)
232
- end
233
-
234
- # Align encoded lign on a 8-bit boundary.
235
- align_output(write) if @params.EncodedByteAlign == true
236
- end
188
+ raise error
189
+ end
237
190
 
238
- # Align input to a byte boundary.
239
- def align_input(input)
240
- return if input.pos % 8 == 0
241
- input.pos += 8 - (input.pos % 8)
242
- end
191
+ rows -= 1 unless params[:has_eob?]
192
+ end
243
193
 
244
- # Align output to a byte boundary by adding some zeros.
245
- def align_output(output)
246
- return if output.pos % 8 == 0
247
- output.write(0, 8 - (output.pos % 8))
248
- end
194
+ bitw.final.to_s
195
+ end
196
+
197
+ private
198
+
199
+ def encode_one_dimensional_line(input, output, columns, colors) # :nodoc:
200
+ scan_len = 0
201
+ white, _black = colors
202
+ current_color = white
203
+ length = 0
249
204
 
250
- def encode_two_dimensional_line(_input, _output, _columns, _colors, _prev_line) #:nodoc:
251
- raise NotImplementedError "CCITT two-dimensional encoding scheme not supported."
205
+ return if columns == 0
206
+
207
+ # Process each bit in line.
208
+ loop do
209
+ if input.read(1) == current_color
210
+ scan_len += 1
211
+ else
212
+ if current_color == white
213
+ put_white_bits(output, scan_len)
214
+ else
215
+ put_black_bits(output, scan_len)
252
216
  end
253
217
 
254
- def decode_one_dimensional_line(input, output, columns, colors) #:nodoc:
255
- white, _black = colors
256
- current_color = white
218
+ current_color ^= 1
219
+ scan_len = 1
220
+ end
257
221
 
258
- line_length = 0
259
- while line_length < columns
260
- if current_color == white
261
- bit_length = get_white_bits(input)
262
- else
263
- bit_length = get_black_bits(input)
264
- end
222
+ length += 1
223
+ break if length == columns
224
+ end
265
225
 
266
- raise InvalidCCITTFaxDataError, "Unfinished line (at bit pos #{input.pos}/#{input.size}})" if bit_length.nil?
226
+ if current_color == white
227
+ put_white_bits(output, scan_len)
228
+ else
229
+ put_black_bits(output, scan_len)
230
+ end
267
231
 
268
- line_length += bit_length
232
+ # Align encoded lign on a 8-bit boundary.
233
+ align_output(write) if @params.EncodedByteAlign == true
234
+ end
269
235
 
270
- raise InvalidCCITTFaxDataError, "Line is too long (at bit pos #{input.pos}/#{input.size}})" if line_length > columns
236
+ # Align input to a byte boundary.
237
+ def align_input(input)
238
+ return if input.pos % 8 == 0
239
+ input.pos += 8 - (input.pos % 8)
240
+ end
271
241
 
272
- write_bit_range(output, current_color, bit_length)
273
- current_color ^= 1
274
- end
275
- end
242
+ # Align output to a byte boundary by adding some zeros.
243
+ def align_output(output)
244
+ return if output.pos % 8 == 0
245
+ output.write(0, 8 - (output.pos % 8))
246
+ end
276
247
 
277
- def decode_two_dimensional_line(_input, _output, _columns, _colors, _prev_line) #:nodoc:
278
- raise NotImplementedError, "CCITT two-dimensional decoding scheme not supported."
279
- end
248
+ def encode_two_dimensional_line(_input, _output, _columns, _colors, _prev_line) # :nodoc:
249
+ raise NotImplementedError "CCITT two-dimensional encoding scheme not supported."
250
+ end
280
251
 
281
- def get_white_bits(bitr) #:nodoc:
282
- get_color_bits(bitr, WHITE_CONFIGURATION_DECODE_TABLE, WHITE_TERMINAL_DECODE_TABLE)
283
- end
252
+ def decode_one_dimensional_line(input, output, columns, colors) # :nodoc:
253
+ white, _black = colors
254
+ current_color = white
284
255
 
285
- def get_black_bits(bitr) #:nodoc:
286
- get_color_bits(bitr, BLACK_CONFIGURATION_DECODE_TABLE, BLACK_TERMINAL_DECODE_TABLE)
287
- end
256
+ line_length = 0
257
+ while line_length < columns
258
+ bit_length = if current_color == white
259
+ get_white_bits(input)
260
+ else
261
+ get_black_bits(input)
262
+ end
288
263
 
289
- def get_color_bits(bitr, config_words, term_words) #:nodoc:
290
- bits = 0
291
- check_conf = true
292
-
293
- while check_conf
294
- check_conf = false
295
- (2..13).each do |length|
296
- codeword = bitr.peek(length)
297
- config_value = config_words[[codeword, length]]
298
-
299
- if config_value
300
- bitr.pos += length
301
- bits += config_value
302
- check_conf = true if config_value == 2560
303
- break
304
- end
305
- end
306
- end
307
-
308
- (2..13).each do |length|
309
- codeword = bitr.peek(length)
310
- term_value = term_words[[codeword, length]]
311
-
312
- if term_value
313
- bitr.pos += length
314
- bits += term_value
315
-
316
- return bits
317
- end
318
- end
319
-
320
- nil
321
- end
264
+ raise InvalidCCITTFaxDataError, "Unfinished line (at bit pos #{input.pos}/#{input.size}})" if bit_length.nil?
322
265
 
323
- def lookup_bits(table, codeword, length)
324
- table.rassoc [codeword, length]
325
- end
266
+ line_length += bit_length
326
267
 
327
- def put_white_bits(bitw, length) #:nodoc:
328
- put_color_bits(bitw, length, WHITE_CONFIGURATION_ENCODE_TABLE, WHITE_TERMINAL_ENCODE_TABLE)
329
- end
268
+ raise InvalidCCITTFaxDataError, "Line is too long (at bit pos #{input.pos}/#{input.size}})" if line_length > columns
330
269
 
331
- def put_black_bits(bitw, length) #:nodoc:
332
- put_color_bits(bitw, length, BLACK_CONFIGURATION_ENCODE_TABLE, BLACK_TERMINAL_ENCODE_TABLE)
270
+ write_bit_range(output, current_color, bit_length)
271
+ current_color ^= 1
272
+ end
273
+ end
274
+
275
+ def decode_two_dimensional_line(_input, _output, _columns, _colors, _prev_line) # :nodoc:
276
+ raise NotImplementedError, "CCITT two-dimensional decoding scheme not supported."
277
+ end
278
+
279
+ def get_white_bits(bitr) # :nodoc:
280
+ get_color_bits(bitr, WHITE_CONFIGURATION_DECODE_TABLE, WHITE_TERMINAL_DECODE_TABLE)
281
+ end
282
+
283
+ def get_black_bits(bitr) # :nodoc:
284
+ get_color_bits(bitr, BLACK_CONFIGURATION_DECODE_TABLE, BLACK_TERMINAL_DECODE_TABLE)
285
+ end
286
+
287
+ def get_color_bits(bitr, config_words, term_words) # :nodoc:
288
+ bits = 0
289
+ check_conf = true
290
+
291
+ while check_conf
292
+ check_conf = false
293
+ (2..13).each do |length|
294
+ codeword = bitr.peek(length)
295
+ config_value = config_words[[codeword, length]]
296
+
297
+ if config_value
298
+ bitr.pos += length
299
+ bits += config_value
300
+ check_conf = true if config_value == 2560
301
+ break
333
302
  end
303
+ end
304
+ end
334
305
 
335
- def put_color_bits(bitw, length, config_words, term_words) #:nodoc:
336
- while length > 2559
337
- bitw.write(*config_words[2560])
338
- length -= 2560
339
- end
306
+ (2..13).each do |length|
307
+ codeword = bitr.peek(length)
308
+ term_value = term_words[[codeword, length]]
340
309
 
341
- if length > 63
342
- conf_length = (length >> 6) << 6
343
- bitw.write(*config_words[conf_length])
344
- length -= conf_length
345
- end
310
+ if term_value
311
+ bitr.pos += length
312
+ bits += term_value
346
313
 
347
- bitw.write(*term_words[length])
348
- end
314
+ return bits
315
+ end
316
+ end
349
317
 
350
- def write_bit_range(bitw, bit_value, length) #:nodoc:
351
- bitw.write((bit_value << length) - bit_value, length)
352
- end
318
+ nil
319
+ end
320
+
321
+ def lookup_bits(table, codeword, length)
322
+ table.rassoc [codeword, length]
323
+ end
324
+
325
+ def put_white_bits(bitw, length) # :nodoc:
326
+ put_color_bits(bitw, length, WHITE_CONFIGURATION_ENCODE_TABLE, WHITE_TERMINAL_ENCODE_TABLE)
327
+ end
328
+
329
+ def put_black_bits(bitw, length) # :nodoc:
330
+ put_color_bits(bitw, length, BLACK_CONFIGURATION_ENCODE_TABLE, BLACK_TERMINAL_ENCODE_TABLE)
331
+ end
332
+
333
+ def put_color_bits(bitw, length, config_words, term_words) # :nodoc:
334
+ while length > 2559
335
+ bitw.write(*config_words[2560])
336
+ length -= 2560
353
337
  end
354
- CCF = CCITTFax
355
338
 
339
+ if length > 63
340
+ conf_length = (length >> 6) << 6
341
+ bitw.write(*config_words[conf_length])
342
+ length -= conf_length
343
+ end
344
+
345
+ bitw.write(*term_words[length])
346
+ end
347
+
348
+ def write_bit_range(bitw, bit_value, length) # :nodoc:
349
+ bitw.write((bit_value << length) - bit_value, length)
350
+ end
356
351
  end
352
+ CCF = CCITTFax
353
+ end
357
354
  end