hexapdf 0.18.0 → 0.19.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/lib/hexapdf/cli/command.rb +7 -1
- data/lib/hexapdf/content/canvas.rb +2 -2
- data/lib/hexapdf/content/graphics_state.rb +144 -21
- data/lib/hexapdf/dictionary_fields.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +46 -3
- data/lib/hexapdf/version.rb +1 -1
- data/test/data/cert/create.sh +171 -0
- data/test/data/cert/root-ca/certs/84E66B6F4C359E741C0AFA014790DF39.pem +119 -0
- data/test/data/cert/root-ca/certs/84E66B6F4C359E741C0AFA014790DF3A.pem +125 -0
- data/test/data/cert/root-ca/db/crlnumber +1 -0
- data/test/data/cert/root-ca/db/index +2 -0
- data/test/data/cert/root-ca/db/index.attr +1 -0
- data/test/data/cert/root-ca/db/index.attr.old +1 -0
- data/test/data/cert/root-ca/db/index.old +1 -0
- data/test/data/cert/root-ca/db/serial +1 -0
- data/test/data/cert/root-ca/db/serial.old +1 -0
- data/test/data/cert/root-ca/private/root-ca.key +52 -0
- data/test/data/cert/root-ca/root-ca.conf +65 -0
- data/test/data/cert/root-ca/root-ca.crt +119 -0
- data/test/data/cert/root-ca/root-ca.csr +28 -0
- data/test/data/cert/signature-1-pkcs7-detached.pdf +182 -0
- data/test/data/cert/sub-ca/certs/453FF080E3EDCD6A388D5368DFC320D9.pem +125 -0
- data/test/data/cert/sub-ca/db/crlnumber +1 -0
- data/test/data/cert/sub-ca/db/index +1 -0
- data/test/data/cert/sub-ca/db/index.attr +1 -0
- data/test/data/cert/sub-ca/db/index.old +0 -0
- data/test/data/cert/sub-ca/db/serial +1 -0
- data/test/data/cert/sub-ca/db/serial.old +1 -0
- data/test/data/cert/sub-ca/private/signing.key +52 -0
- data/test/data/cert/sub-ca/private/sub-ca.key +52 -0
- data/test/data/cert/sub-ca/signing.crt +125 -0
- data/test/data/cert/sub-ca/signing.csr +28 -0
- data/test/data/cert/sub-ca/signing.p12 +0 -0
- data/test/data/cert/sub-ca/sub-ca.conf +65 -0
- data/test/data/cert/sub-ca/sub-ca.crt +125 -0
- data/test/data/cert/sub-ca/sub-ca.csr +28 -0
- data/test/hexapdf/task/test_optimize.rb +26 -0
- data/test/hexapdf/test_dictionary_fields.rb +1 -0
- data/test/hexapdf/test_writer.rb +2 -2
- metadata +32 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55ddbf5c737ab446c5793660957e64aaf6f8872c6bb1c4a76ba39a87193b951f
|
|
4
|
+
data.tar.gz: eb29fbb41cbb20c060c43cc80406bd4b11fa36b0d86a95daa9d1093d060ab89e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28368cd415cd9adf28050df8812a0cda999b8140fcba4a9f307d7e37f6dc0254d99abf5173a81a1b2b59f9f6a658a46f6998d7834b93ffc19840d578e507ce92
|
|
7
|
+
data.tar.gz: b25e409653a4bd9359f3a39c2920187261a43151942c4120d2bd818886dbf236f77483a42ca7a7fb39ffbcdfc7da8cf9d7a87609a4f4af514cf7f93f495eb5ed
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 0.19.0 - 2021-11-24
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
* Page resource pruning to the optimization task
|
|
6
|
+
* An option for page resources pruning to the optimization options of the
|
|
7
|
+
`hexapdf` command
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
* Handling of invalid date strings with a minute time zone offset greater than
|
|
12
|
+
59
|
|
13
|
+
|
|
14
|
+
|
|
1
15
|
## 0.18.0 - 2021-11-04
|
|
2
16
|
|
|
3
17
|
### Added
|
|
@@ -6,7 +20,7 @@
|
|
|
6
20
|
device colors in parts other than the canvas
|
|
7
21
|
* [HexaPDF::Type::AcroForm::VariableTextField::create_appearance_string] for
|
|
8
22
|
centralized creation of appearance strings
|
|
9
|
-
* [HexaPDF::Object
|
|
23
|
+
* [HexaPDF::Object::make_direct] for making objects and all parts of them direct
|
|
10
24
|
instead of indirect
|
|
11
25
|
|
|
12
26
|
### Changed
|
|
@@ -26,7 +40,7 @@
|
|
|
26
40
|
dictionary are indirect objects
|
|
27
41
|
* [HexaPDF::Content::GraphicObject::EndpointArc] to correctly determine the
|
|
28
42
|
start and end points
|
|
29
|
-
*
|
|
43
|
+
* HexaPDF::Dictionary#perform_validation to correctly handle objects that
|
|
30
44
|
should not be indirect objects
|
|
31
45
|
|
|
32
46
|
|
data/lib/hexapdf/cli/command.rb
CHANGED
|
@@ -66,6 +66,7 @@ module HexaPDF
|
|
|
66
66
|
@out_options.xref_streams = :preserve
|
|
67
67
|
@out_options.streams = :preserve
|
|
68
68
|
@out_options.optimize_fonts = false
|
|
69
|
+
@out_options.prune_page_resources = false
|
|
69
70
|
|
|
70
71
|
@out_options.encryption = :preserve
|
|
71
72
|
@out_options.enc_user_pwd = @out_options.enc_owner_pwd = nil
|
|
@@ -169,6 +170,10 @@ module HexaPDF
|
|
|
169
170
|
"time; default: #{@out_options.compress_pages})") do |c|
|
|
170
171
|
@out_options.compress_pages = c
|
|
171
172
|
end
|
|
173
|
+
options.on("--[no-]prune-page-resources", "Prunes unused objects from the page resources " \
|
|
174
|
+
"(may take a long time; default: #{@out_options.prune_page_resources})") do |c|
|
|
175
|
+
@out_options.prune_page_resources = c
|
|
176
|
+
end
|
|
172
177
|
options.on("--[no-]optimize-fonts", "Optimize embedded font files; " \
|
|
173
178
|
"default: #{@out_options.optimize_fonts})") do |o|
|
|
174
179
|
@out_options.optimize_fonts = o
|
|
@@ -236,7 +241,8 @@ module HexaPDF
|
|
|
236
241
|
doc.task(:optimize, compact: @out_options.compact,
|
|
237
242
|
object_streams: @out_options.object_streams,
|
|
238
243
|
xref_streams: @out_options.xref_streams,
|
|
239
|
-
compress_pages: @out_options.compress_pages
|
|
244
|
+
compress_pages: @out_options.compress_pages,
|
|
245
|
+
prune_page_resources: @out_options.prune_page_resources)
|
|
240
246
|
if @out_options.streams != :preserve || @out_options.optimize_fonts
|
|
241
247
|
doc.each(only_current: false) do |obj|
|
|
242
248
|
optimize_stream(obj)
|
|
@@ -589,7 +589,7 @@ module HexaPDF
|
|
|
589
589
|
#
|
|
590
590
|
# The line cap style specifies how the ends of stroked open paths should look like.
|
|
591
591
|
#
|
|
592
|
-
# The +style+ parameter can be one of:
|
|
592
|
+
# The +style+ parameter can be one of (also see LineCapStyle):
|
|
593
593
|
#
|
|
594
594
|
# :butt or 0::
|
|
595
595
|
# Stroke is squared off at the endpoint of a path.
|
|
@@ -641,7 +641,7 @@ module HexaPDF
|
|
|
641
641
|
#
|
|
642
642
|
# The line join style specifies the shape that is used at the corners of stroked paths.
|
|
643
643
|
#
|
|
644
|
-
# The +style+ parameter can be one of:
|
|
644
|
+
# The +style+ parameter can be one of (also see LineJoinStyle):
|
|
645
645
|
#
|
|
646
646
|
# :miter or 0::
|
|
647
647
|
# The outer lines of the two segments continue until the meet at an angle.
|
|
@@ -73,7 +73,7 @@ module HexaPDF
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
# Defines all available line cap styles as constants. Each line cap style is an instance of
|
|
76
|
-
# NamedValue. For use with Content::
|
|
76
|
+
# NamedValue, see ::normalize. For use with e.g. Content::Canvas#line_cap_style.
|
|
77
77
|
#
|
|
78
78
|
# See: PDF1.7 s8.4.3.3
|
|
79
79
|
module LineCapStyle
|
|
@@ -95,18 +95,39 @@ module HexaPDF
|
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# Stroke is squared off at the endpoint of a path.
|
|
98
|
+
#
|
|
99
|
+
# Specify as 0 or :butt.
|
|
100
|
+
#
|
|
101
|
+
# #>pdf-small-hide
|
|
102
|
+
# canvas.line_cap_style(:butt)
|
|
103
|
+
# canvas.line_width(10).line(50, 20, 50, 80).stroke
|
|
104
|
+
# canvas.stroke_color("white").line_width(1).line(50, 20, 50, 80).stroke
|
|
98
105
|
BUTT_CAP = NamedValue.new(:butt, 0)
|
|
99
106
|
|
|
100
107
|
# A semicircular arc is drawn at the endpoint of a path.
|
|
108
|
+
#
|
|
109
|
+
# Specify as 1 or :round.
|
|
110
|
+
#
|
|
111
|
+
# #>pdf-small-hide
|
|
112
|
+
# canvas.line_cap_style(:round)
|
|
113
|
+
# canvas.line_width(10).line(50, 20, 50, 80).stroke
|
|
114
|
+
# canvas.stroke_color("white").line_width(1).line(50, 20, 50, 80).stroke
|
|
101
115
|
ROUND_CAP = NamedValue.new(:round, 1)
|
|
102
116
|
|
|
103
117
|
# The stroke continues half the line width beyond the endpoint of a path.
|
|
118
|
+
#
|
|
119
|
+
# Specify as 2 or :projecting_square.
|
|
120
|
+
#
|
|
121
|
+
# #>pdf-small-hide
|
|
122
|
+
# canvas.line_cap_style(:projecting_square)
|
|
123
|
+
# canvas.line_width(10).line(50, 20, 50, 80).stroke
|
|
124
|
+
# canvas.stroke_color("white").line_width(1).line(50, 20, 50, 80).stroke
|
|
104
125
|
PROJECTING_SQUARE_CAP = NamedValue.new(:projecting_square, 2)
|
|
105
126
|
|
|
106
127
|
end
|
|
107
128
|
|
|
108
129
|
# Defines all available line join styles as constants. Each line join style is an instance of
|
|
109
|
-
# NamedValue
|
|
130
|
+
# NamedValue, see ::normalize For use with e.g. Content::Canvas#line_join_style.
|
|
110
131
|
#
|
|
111
132
|
# See: PDF1.7 s8.4.3.4
|
|
112
133
|
module LineJoinStyle
|
|
@@ -127,20 +148,47 @@ module HexaPDF
|
|
|
127
148
|
end
|
|
128
149
|
end
|
|
129
150
|
|
|
130
|
-
# The outer lines of the two segments continue until
|
|
151
|
+
# The outer lines of the two segments continue until they meet at an angle.
|
|
152
|
+
#
|
|
153
|
+
# Specify as 0 or :miter.
|
|
154
|
+
#
|
|
155
|
+
# #>pdf-small-hide
|
|
156
|
+
# canvas.line_join_style(:miter)
|
|
157
|
+
# canvas.line_width(10).
|
|
158
|
+
# polyline(20, 20, 50, 80, 80, 20).stroke
|
|
159
|
+
# canvas.stroke_color("white").line_width(1).line_join_style(:bevel).
|
|
160
|
+
# polyline(20, 20, 50, 80, 80, 20).stroke
|
|
131
161
|
MITER_JOIN = NamedValue.new(:miter, 0)
|
|
132
162
|
|
|
133
163
|
# An arc of a circle is drawn around the point where the segments meet.
|
|
164
|
+
#
|
|
165
|
+
# Specify as 1 or :round.
|
|
166
|
+
#
|
|
167
|
+
# #>pdf-small-hide
|
|
168
|
+
# canvas.line_join_style(:round)
|
|
169
|
+
# canvas.line_width(10).
|
|
170
|
+
# polyline(20, 20, 50, 80, 80, 20).stroke
|
|
171
|
+
# canvas.stroke_color("white").line_width(1).line_join_style(:bevel).
|
|
172
|
+
# polyline(20, 20, 50, 80, 80, 20).stroke
|
|
134
173
|
ROUND_JOIN = NamedValue.new(:round, 1)
|
|
135
174
|
|
|
136
|
-
# The two segments are finished with butt caps and the space between the ends is filled with
|
|
137
|
-
#
|
|
175
|
+
# The two segments are finished with butt caps and the space between the ends is filled with a
|
|
176
|
+
# triangle.
|
|
177
|
+
#
|
|
178
|
+
# Specify as 2 or :bevel.
|
|
179
|
+
#
|
|
180
|
+
# #>pdf-small-hide
|
|
181
|
+
# canvas.line_join_style(:bevel)
|
|
182
|
+
# canvas.line_width(10).
|
|
183
|
+
# polyline(20, 20, 50, 80, 80, 20).stroke
|
|
184
|
+
# canvas.stroke_color("white").line_width(1).line_join_style(:bevel).
|
|
185
|
+
# polyline(20, 20, 50, 80, 80, 20).stroke
|
|
138
186
|
BEVEL_JOIN = NamedValue.new(:bevel, 2)
|
|
139
187
|
|
|
140
188
|
end
|
|
141
189
|
|
|
142
|
-
# The line dash pattern defines how a line should be dashed. For use with
|
|
143
|
-
# Content::
|
|
190
|
+
# The line dash pattern defines how a line should be dashed. For use with e.g.
|
|
191
|
+
# Content::Canvas#line_dash_pattern.
|
|
144
192
|
#
|
|
145
193
|
# A dash pattern consists of two parts: the dash array and the dash phase. The dash array
|
|
146
194
|
# defines the length of alternating dashes and gaps (important: starting with dashes). And the
|
|
@@ -159,6 +207,12 @@ module HexaPDF
|
|
|
159
207
|
# See: PDF1.7 s8.4.3.6
|
|
160
208
|
class LineDashPattern
|
|
161
209
|
|
|
210
|
+
# :call-seq:
|
|
211
|
+
# LineDashPattern.normalize(line_dash_pattern) -> line_dash_pattern
|
|
212
|
+
# LineDashPattern.normalize(array, phase = 0) -> LineDashPattern.new(array, phase)
|
|
213
|
+
# LineDashPattern.normalize(number, phase = 0) -> LineDashPattern.new([number], phase)
|
|
214
|
+
# LineDashPattern.normalize(0) -> LineDashPattern.new
|
|
215
|
+
#
|
|
162
216
|
# Returns the arguments normalized to a valid LineDashPattern instance.
|
|
163
217
|
#
|
|
164
218
|
# If +array+ is 0, the default line dash pattern representing a solid line will be used. If it
|
|
@@ -206,8 +260,8 @@ module HexaPDF
|
|
|
206
260
|
|
|
207
261
|
end
|
|
208
262
|
|
|
209
|
-
# Defines all available rendering intents as constants. For use with
|
|
210
|
-
# Content::
|
|
263
|
+
# Defines all available rendering intents as constants. For use with e.g.
|
|
264
|
+
# Content::Canvas#rendering_intent.
|
|
211
265
|
#
|
|
212
266
|
# See: PDF1.7 s8.6.5.8
|
|
213
267
|
module RenderingIntent
|
|
@@ -241,7 +295,7 @@ module HexaPDF
|
|
|
241
295
|
end
|
|
242
296
|
|
|
243
297
|
# Defines all available text rendering modes as constants. Each text rendering mode is an
|
|
244
|
-
# instance of NamedValue. For use with Content::
|
|
298
|
+
# instance of NamedValue. For use with e.g. Content::Canvas#text_rendering_mode.
|
|
245
299
|
#
|
|
246
300
|
# See: PDF1.7 s9.3.6
|
|
247
301
|
module TextRenderingMode
|
|
@@ -272,28 +326,97 @@ module HexaPDF
|
|
|
272
326
|
end
|
|
273
327
|
end
|
|
274
328
|
|
|
275
|
-
# Fill text
|
|
329
|
+
# Fill text.
|
|
330
|
+
#
|
|
331
|
+
# Specify as 0 or :fill.
|
|
332
|
+
#
|
|
333
|
+
# #>pdf-small-hide
|
|
334
|
+
# canvas.font("Helvetica", size: 13)
|
|
335
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
336
|
+
# canvas.text_rendering_mode(:fill)
|
|
337
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
276
338
|
FILL = NamedValue.new(:fill, 0)
|
|
277
339
|
|
|
278
|
-
# Stroke text
|
|
340
|
+
# Stroke text.
|
|
341
|
+
#
|
|
342
|
+
# Specify as 1 or :stroke.
|
|
343
|
+
#
|
|
344
|
+
# #>pdf-small-hide
|
|
345
|
+
# canvas.font("Helvetica", size: 13)
|
|
346
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
347
|
+
# canvas.text_rendering_mode(:stroke)
|
|
348
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
279
349
|
STROKE = NamedValue.new(:stroke, 1)
|
|
280
350
|
|
|
281
|
-
# Fill, then stroke text
|
|
351
|
+
# Fill, then stroke text.
|
|
352
|
+
#
|
|
353
|
+
# Specify as 2 or :fill_stroke.
|
|
354
|
+
#
|
|
355
|
+
# #>pdf-small-hide
|
|
356
|
+
# canvas.font("Helvetica", size: 13)
|
|
357
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
358
|
+
# canvas.text_rendering_mode(:fill_stroke)
|
|
359
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
282
360
|
FILL_STROKE = NamedValue.new(:fill_stroke, 2)
|
|
283
361
|
|
|
284
|
-
# Neither fill nor stroke text (invisible)
|
|
362
|
+
# Neither fill nor stroke text (invisible).
|
|
363
|
+
#
|
|
364
|
+
# Specify as 3 or :invisible.
|
|
365
|
+
#
|
|
366
|
+
# #>pdf-small-hide
|
|
367
|
+
# canvas.font("Helvetica", size: 13)
|
|
368
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
369
|
+
# canvas.text_rendering_mode(:invisible)
|
|
370
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
371
|
+
# canvas.stroke_color("red").line_width(20).line(30, 20, 30, 80).stroke
|
|
285
372
|
INVISIBLE = NamedValue.new(:invisible, 3)
|
|
286
373
|
|
|
287
|
-
# Fill text and add to path for clipping
|
|
374
|
+
# Fill text and add to path for clipping.
|
|
375
|
+
#
|
|
376
|
+
# Specify as 4 or :fill_clip.
|
|
377
|
+
#
|
|
378
|
+
# #>pdf-small-hide
|
|
379
|
+
# canvas.font("Helvetica", size: 13)
|
|
380
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
381
|
+
# canvas.text_rendering_mode(:fill_clip)
|
|
382
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
383
|
+
# canvas.stroke_color("red").line_width(20).line(30, 20, 30, 80).stroke
|
|
288
384
|
FILL_CLIP = NamedValue.new(:fill_clip, 4)
|
|
289
385
|
|
|
290
|
-
# Stroke text and add to path for clipping
|
|
386
|
+
# Stroke text and add to path for clipping.
|
|
387
|
+
#
|
|
388
|
+
# Specify as 5 or :stroke_clip.
|
|
389
|
+
#
|
|
390
|
+
# #>pdf-small-hide
|
|
391
|
+
# canvas.font("Helvetica", size: 13)
|
|
392
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
393
|
+
# canvas.text_rendering_mode(:stroke_clip)
|
|
394
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
395
|
+
# canvas.stroke_color("red").line_width(20).line(30, 20, 30, 80).stroke
|
|
291
396
|
STROKE_CLIP = NamedValue.new(:stroke_clip, 5)
|
|
292
397
|
|
|
293
|
-
# Fill, then stroke text and add to path for clipping
|
|
398
|
+
# Fill, then stroke text and add to path for clipping.
|
|
399
|
+
#
|
|
400
|
+
# Specify as 6 or :fill_stroke_clip.
|
|
401
|
+
#
|
|
402
|
+
# #>pdf-small-hide
|
|
403
|
+
# canvas.font("Helvetica", size: 13)
|
|
404
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
405
|
+
# canvas.text_rendering_mode(:fill_stroke_clip)
|
|
406
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
407
|
+
# canvas.stroke_color("red").line_width(20).line(30, 20, 30, 80).stroke
|
|
294
408
|
FILL_STROKE_CLIP = NamedValue.new(:fill_stroke_clip, 6)
|
|
295
409
|
|
|
296
|
-
# Add text to path for clipping
|
|
410
|
+
# Add text to path for clipping.
|
|
411
|
+
#
|
|
412
|
+
# Specify as 7 or :clip.
|
|
413
|
+
#
|
|
414
|
+
# #>pdf-small-hide
|
|
415
|
+
# canvas.font("Helvetica", size: 13)
|
|
416
|
+
# canvas.stroke_color("green").line_width(0.5)
|
|
417
|
+
# canvas.text_rendering_mode(:clip)
|
|
418
|
+
# canvas.text("#{canvas.text_rendering_mode.name}", at: [10, 50])
|
|
419
|
+
# canvas.stroke_color("red").line_width(20).line(30, 20, 30, 80).stroke
|
|
297
420
|
CLIP = NamedValue.new(:clip, 7)
|
|
298
421
|
|
|
299
422
|
end
|
|
@@ -415,21 +538,21 @@ module HexaPDF
|
|
|
415
538
|
|
|
416
539
|
# The scaled character spacing used in glyph displacement calculations.
|
|
417
540
|
#
|
|
418
|
-
# This returns the
|
|
541
|
+
# This returns the character spacing multiplied by #scaled_horizontal_scaling.
|
|
419
542
|
#
|
|
420
543
|
# See PDF1.7 s9.4.4
|
|
421
544
|
attr_reader :scaled_character_spacing
|
|
422
545
|
|
|
423
546
|
# The scaled word spacing used in glyph displacement calculations.
|
|
424
547
|
#
|
|
425
|
-
# This returns the
|
|
548
|
+
# This returns the word spacing multiplied by #scaled_horizontal_scaling.
|
|
426
549
|
#
|
|
427
550
|
# See PDF1.7 s9.4.4
|
|
428
551
|
attr_reader :scaled_word_spacing
|
|
429
552
|
|
|
430
553
|
# The scaled font size used in glyph displacement calculations.
|
|
431
554
|
#
|
|
432
|
-
# This returns the
|
|
555
|
+
# This returns the font size divided by 1000 multiplied by #scaled_horizontal_scaling.
|
|
433
556
|
#
|
|
434
557
|
# See PDF1.7 s9.4.4
|
|
435
558
|
attr_reader :scaled_font_size
|
|
@@ -293,7 +293,7 @@ module HexaPDF
|
|
|
293
293
|
end
|
|
294
294
|
|
|
295
295
|
# :nodoc:
|
|
296
|
-
DATE_RE = /\AD:(\d{4})(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?([Z+-])?(?:(\d\d)(?:'|'(\d
|
|
296
|
+
DATE_RE = /\AD:(\d{4})(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?([Z+-])?(?:(\d\d)(?:'|'([0-5]\d)'?|\z)?)?\z/n
|
|
297
297
|
|
|
298
298
|
# Checks if the given object is a string and converts into a Time object if possible.
|
|
299
299
|
# Otherwise returns +nil+.
|
|
@@ -72,8 +72,19 @@ module HexaPDF
|
|
|
72
72
|
# Compresses the content streams of all pages if set to +true+. Note that this can take a
|
|
73
73
|
# *very* long time because each content stream has to be unfiltered, parsed, serialized
|
|
74
74
|
# and then filtered again.
|
|
75
|
+
#
|
|
76
|
+
# prune_page_resources::
|
|
77
|
+
# Removes all unused XObjects from the resources dictionaries of all pages. It is
|
|
78
|
+
# recommended to also set the +compact+ argument because otherwise the unused XObjects won't
|
|
79
|
+
# be deleted from the document.
|
|
80
|
+
#
|
|
81
|
+
# This is sometimes necessary after importing pages from other PDF files that use a single
|
|
82
|
+
# resources dictionary for all pages.
|
|
75
83
|
def self.call(doc, compact: false, object_streams: :preserve, xref_streams: :preserve,
|
|
76
|
-
compress_pages: false)
|
|
84
|
+
compress_pages: false, prune_page_resources: false)
|
|
85
|
+
used_refs = compress_pages(doc) if compress_pages
|
|
86
|
+
prune_page_resources(doc, used_refs) if prune_page_resources
|
|
87
|
+
|
|
77
88
|
if compact
|
|
78
89
|
compact(doc, object_streams, xref_streams)
|
|
79
90
|
elsif object_streams != :preserve
|
|
@@ -83,8 +94,6 @@ module HexaPDF
|
|
|
83
94
|
else
|
|
84
95
|
doc.each(only_current: false, &method(:delete_fields_with_defaults))
|
|
85
96
|
end
|
|
86
|
-
|
|
87
|
-
compress_pages(doc) if compress_pages
|
|
88
97
|
end
|
|
89
98
|
|
|
90
99
|
# Compacts the document by merging all revisions into one, deleting null and unused entries
|
|
@@ -214,12 +223,41 @@ module HexaPDF
|
|
|
214
223
|
|
|
215
224
|
# Compresses the contents of all pages by parsing and then serializing again. The HexaPDF
|
|
216
225
|
# serializer is already optimized for small output size so nothing else needs to be done.
|
|
226
|
+
#
|
|
227
|
+
# Returns a hash of the form key=>true where the keys are the used XObjects (for use with
|
|
228
|
+
# #prune_page_resources).
|
|
217
229
|
def self.compress_pages(doc)
|
|
230
|
+
used_refs = {}
|
|
218
231
|
doc.pages.each do |page|
|
|
219
232
|
processor = SerializationProcessor.new
|
|
220
233
|
HexaPDF::Content::Parser.parse(page.contents, processor)
|
|
221
234
|
page.contents = processor.result
|
|
222
235
|
page[:Contents].set_filter(:FlateDecode)
|
|
236
|
+
xobjects = page.resources[:XObject]
|
|
237
|
+
processor.used_references.each {|ref| used_refs[xobjects[ref]] = true }
|
|
238
|
+
end
|
|
239
|
+
used_refs
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Deletes all XObject entries from the resources dictionaries of all pages whose names do not
|
|
243
|
+
# match the keys in +used_refs+.
|
|
244
|
+
def self.prune_page_resources(doc, used_refs)
|
|
245
|
+
unless used_refs
|
|
246
|
+
used_refs = {}
|
|
247
|
+
doc.pages.each do |page|
|
|
248
|
+
xobjects = page.resources[:XObject]
|
|
249
|
+
HexaPDF::Content::Parser.parse(page.contents) do |op, operands|
|
|
250
|
+
used_refs[xobjects[operands[0]]] = true if op == :Do
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
doc.pages.each do |page|
|
|
256
|
+
xobjects = page.resources[:XObject]
|
|
257
|
+
xobjects.each do |key, obj|
|
|
258
|
+
next if used_refs[obj]
|
|
259
|
+
xobjects.delete(key)
|
|
260
|
+
end
|
|
223
261
|
end
|
|
224
262
|
end
|
|
225
263
|
|
|
@@ -228,14 +266,19 @@ module HexaPDF
|
|
|
228
266
|
|
|
229
267
|
attr_reader :result #:nodoc:
|
|
230
268
|
|
|
269
|
+
# Contains all found references
|
|
270
|
+
attr_reader :used_references
|
|
271
|
+
|
|
231
272
|
def initialize #:nodoc:
|
|
232
273
|
@result = ''.b
|
|
233
274
|
@serializer = HexaPDF::Serializer.new
|
|
275
|
+
@used_references = []
|
|
234
276
|
end
|
|
235
277
|
|
|
236
278
|
def process(op, operands) #:nodoc:
|
|
237
279
|
@result << HexaPDF::Content::Operator::DEFAULT_OPERATORS[op].
|
|
238
280
|
serialize(@serializer, *operands)
|
|
281
|
+
@used_references << operands[0] if op == :Do
|
|
239
282
|
end
|
|
240
283
|
|
|
241
284
|
end
|
data/lib/hexapdf/version.rb
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# See https://www.feistyduck.com/library/openssl-cookbook/online/ch-openssl.html
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#####################################3
|
|
6
|
+
# Root CA
|
|
7
|
+
mkdir root-ca
|
|
8
|
+
cd root-ca
|
|
9
|
+
mkdir certs db private
|
|
10
|
+
touch db/index
|
|
11
|
+
openssl rand -hex 16 > db/serial
|
|
12
|
+
echo 1001 > db/crlnumber
|
|
13
|
+
|
|
14
|
+
cat > root-ca.conf <<'CACONF'
|
|
15
|
+
[default]
|
|
16
|
+
name = root-ca
|
|
17
|
+
domain_suffix = hexapdf.gettalong.org
|
|
18
|
+
aia_url = http://$name.$domain_suffix/$name.crt
|
|
19
|
+
crl_url = http://$name.$domain_suffix/$name.crl
|
|
20
|
+
default_ca = ca_default
|
|
21
|
+
name_opt = utf8,esc_ctrl,multiline,lname,align
|
|
22
|
+
|
|
23
|
+
[ca_dn]
|
|
24
|
+
countryName = "AT"
|
|
25
|
+
organizationName = "HexaPDF"
|
|
26
|
+
commonName = "HexaPDF Test Root CA"
|
|
27
|
+
|
|
28
|
+
[ca_default]
|
|
29
|
+
home = ../root-ca
|
|
30
|
+
database = $home/db/index
|
|
31
|
+
serial = $home/db/serial
|
|
32
|
+
crlnumber = $home/db/crlnumber
|
|
33
|
+
certificate = $home/$name.crt
|
|
34
|
+
private_key = $home/private/$name.key
|
|
35
|
+
RANDFILE = $home/private/random
|
|
36
|
+
new_certs_dir = $home/certs
|
|
37
|
+
unique_subject = no
|
|
38
|
+
copy_extensions = none
|
|
39
|
+
default_days = 36500
|
|
40
|
+
default_crl_days = 365
|
|
41
|
+
default_md = sha256
|
|
42
|
+
policy = policy_c_o_match
|
|
43
|
+
|
|
44
|
+
[policy_c_o_match]
|
|
45
|
+
countryName = match
|
|
46
|
+
stateOrProvinceName = optional
|
|
47
|
+
organizationName = match
|
|
48
|
+
organizationalUnitName = optional
|
|
49
|
+
commonName = supplied
|
|
50
|
+
emailAddress = optional
|
|
51
|
+
|
|
52
|
+
[req]
|
|
53
|
+
default_bits = 4096
|
|
54
|
+
encrypt_key = no
|
|
55
|
+
default_md = sha256
|
|
56
|
+
utf8 = yes
|
|
57
|
+
string_mask = utf8only
|
|
58
|
+
prompt = no
|
|
59
|
+
distinguished_name = ca_dn
|
|
60
|
+
req_extensions = ca_ext
|
|
61
|
+
|
|
62
|
+
[ca_ext]
|
|
63
|
+
basicConstraints = critical,CA:true
|
|
64
|
+
keyUsage = critical,keyCertSign,cRLSign
|
|
65
|
+
subjectKeyIdentifier = hash
|
|
66
|
+
|
|
67
|
+
[sub_ca_ext]
|
|
68
|
+
authorityKeyIdentifier = keyid:always
|
|
69
|
+
basicConstraints = critical,CA:true,pathlen:0
|
|
70
|
+
extendedKeyUsage = clientAuth,serverAuth
|
|
71
|
+
keyUsage = critical,keyCertSign,cRLSign
|
|
72
|
+
subjectKeyIdentifier = hash
|
|
73
|
+
|
|
74
|
+
[client_ext]
|
|
75
|
+
authorityKeyIdentifier = keyid:always
|
|
76
|
+
basicConstraints = critical,CA:false
|
|
77
|
+
extendedKeyUsage = clientAuth
|
|
78
|
+
keyUsage = critical,digitalSignature
|
|
79
|
+
subjectKeyIdentifier = hash
|
|
80
|
+
CACONF
|
|
81
|
+
|
|
82
|
+
openssl req -new -config root-ca.conf -out root-ca.csr -keyout private/root-ca.key
|
|
83
|
+
openssl ca -selfsign -config root-ca.conf -batch -in root-ca.csr -out root-ca.crt -extensions ca_ext
|
|
84
|
+
|
|
85
|
+
#####################################3
|
|
86
|
+
# Subordinate CA
|
|
87
|
+
cd ..
|
|
88
|
+
mkdir sub-ca
|
|
89
|
+
cd sub-ca
|
|
90
|
+
mkdir certs db private
|
|
91
|
+
touch db/index
|
|
92
|
+
openssl rand -hex 16 > db/serial
|
|
93
|
+
echo 1001 > db/crlnumber
|
|
94
|
+
|
|
95
|
+
cat > sub-ca.conf <<'CACONF'
|
|
96
|
+
[default]
|
|
97
|
+
name = sub-ca
|
|
98
|
+
domain_suffix = hexapdf.gettalong.org
|
|
99
|
+
aia_url = http://$name.$domain_suffix/$name.crt
|
|
100
|
+
crl_url = http://$name.$domain_suffix/$name.crl
|
|
101
|
+
default_ca = ca_default
|
|
102
|
+
name_opt = utf8,esc_ctrl,multiline,lname,align
|
|
103
|
+
|
|
104
|
+
[ca_dn]
|
|
105
|
+
countryName = "AT"
|
|
106
|
+
organizationName = "HexaPDF"
|
|
107
|
+
commonName = "HexaPDF Test Subordinate CA"
|
|
108
|
+
|
|
109
|
+
[ca_default]
|
|
110
|
+
home = ../sub-ca
|
|
111
|
+
database = $home/db/index
|
|
112
|
+
serial = $home/db/serial
|
|
113
|
+
crlnumber = $home/db/crlnumber
|
|
114
|
+
certificate = $home/$name.crt
|
|
115
|
+
private_key = $home/private/$name.key
|
|
116
|
+
RANDFILE = $home/private/random
|
|
117
|
+
new_certs_dir = $home/certs
|
|
118
|
+
unique_subject = no
|
|
119
|
+
copy_extensions = copy
|
|
120
|
+
default_days = 36500
|
|
121
|
+
default_crl_days = 90
|
|
122
|
+
default_md = sha256
|
|
123
|
+
policy = policy_c_o_match
|
|
124
|
+
|
|
125
|
+
[policy_c_o_match]
|
|
126
|
+
countryName = match
|
|
127
|
+
stateOrProvinceName = optional
|
|
128
|
+
organizationName = match
|
|
129
|
+
organizationalUnitName = optional
|
|
130
|
+
commonName = supplied
|
|
131
|
+
emailAddress = optional
|
|
132
|
+
|
|
133
|
+
[req]
|
|
134
|
+
default_bits = 4096
|
|
135
|
+
encrypt_key = no
|
|
136
|
+
default_md = sha256
|
|
137
|
+
utf8 = yes
|
|
138
|
+
string_mask = utf8only
|
|
139
|
+
prompt = no
|
|
140
|
+
distinguished_name = ca_dn
|
|
141
|
+
req_extensions = ca_ext
|
|
142
|
+
|
|
143
|
+
[ca_ext]
|
|
144
|
+
basicConstraints = critical,CA:true
|
|
145
|
+
keyUsage = critical,keyCertSign,cRLSign
|
|
146
|
+
subjectKeyIdentifier = hash
|
|
147
|
+
|
|
148
|
+
[sub_ca_ext]
|
|
149
|
+
authorityKeyIdentifier = keyid:always
|
|
150
|
+
basicConstraints = critical,CA:true,pathlen:0
|
|
151
|
+
extendedKeyUsage = clientAuth,serverAuth
|
|
152
|
+
keyUsage = critical,keyCertSign,cRLSign
|
|
153
|
+
subjectKeyIdentifier = hash
|
|
154
|
+
|
|
155
|
+
[client_ext]
|
|
156
|
+
authorityKeyIdentifier = keyid:always
|
|
157
|
+
basicConstraints = critical,CA:false
|
|
158
|
+
extendedKeyUsage = clientAuth
|
|
159
|
+
keyUsage = critical,digitalSignature
|
|
160
|
+
subjectKeyIdentifier = hash
|
|
161
|
+
CACONF
|
|
162
|
+
|
|
163
|
+
openssl req -new -config sub-ca.conf -out sub-ca.csr -keyout private/sub-ca.key
|
|
164
|
+
openssl ca -config ../root-ca/root-ca.conf -batch -in sub-ca.csr -out sub-ca.crt -extensions sub_ca_ext
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
#####################################3
|
|
168
|
+
# Signing certificate
|
|
169
|
+
openssl req -new -config sub-ca.conf -subj "/C=AT/O=HexaPDF/CN=HexaPDF Test Certifcate" -keyout private/signing.key -out signing.csr
|
|
170
|
+
openssl ca -config sub-ca.conf -in signing.csr -batch -out signing.crt -extensions client_ext
|
|
171
|
+
openssl pkcs12 -export -in signing.crt -inkey private/signing.key -password pass: -out signing.p12
|