rustpdf 0.4.6-x86_64-linux → 0.4.8-x86_64-linux
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/README.md +13 -18
- data/lib/rustpdf/editable_doc.rb +133 -21
- data/lib/rustpdf/native.rb +11 -0
- data/lib/rustpdf.rb +42 -0
- data/vendor/x86_64-linux/libpdf_ffi.so +0 -0
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 891a60b238e8fbe4f141d0252c180360841e60cdf54b3d83e3e6a81fafcca973
|
|
4
|
+
data.tar.gz: fbcdf3fac905a97922ca51881d7b187a8ea8bdaea121c97bfd230febff282fed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a87dc46b070cb6e73d6f54d364b4765bc59b698370da60c5ca3e3a9b32eae1e8237a45f865fb5c7bee6e1b1bcc79d2cc731e996e9078e750ec31a11678c7f4f
|
|
7
|
+
data.tar.gz: 9f25f278475388e7c76f6a34cb424d07f7a4f3a9207c572137b82c16ffd1589a8de3909537fc2d342e85e2eac699ef82839af2b834a499b2d2ea3bc342f6288d
|
data/README.md
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* `lib/rustpdf.rb` — module functions (`version`, `activate_license`,
|
|
15
|
-
`extract_text`, `sign`, `timestamp`, `add_dss`), enums, error, helpers;
|
|
16
|
-
* `lib/rustpdf/native.rb` — the Fiddle signature table + loader;
|
|
17
|
-
* `lib/rustpdf/document.rb`, `editable_doc.rb` — the `Document` / `EditableDoc`
|
|
18
|
-
classes.
|
|
1
|
+
# RustPdf for Ruby
|
|
2
|
+
|
|
3
|
+
Generate, edit, sign and process PDFs from Ruby: vector graphics, embedded fonts and Unicode text, wrapping paragraphs, images, **PDF/A** (1b-4f), **tagged/accessible** output, attachments, **AcroForm** fields, page manipulation (merge/split/stamp), watermarks, true **redaction**, **AES-256** encryption, **digital signatures (PAdES)** with HSM/deferred signing, timestamps/LTV, text extraction and search, and page **rendering to PNG**. Pure Ruby gem (stdlib Fiddle), no native extension to compile.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- **Full API reference:** https://rustpdf.dev/docs/ruby
|
|
8
|
+
- **Interactive positioning guide** (coordinates, anchors, rotation): https://rustpdf.dev/positioning
|
|
9
|
+
- All product guides (PDF/A, signatures, encryption, redaction, rendering): https://rustpdf.dev/docs/
|
|
10
|
+
|
|
11
|
+
The public API is `RustPdf::Document` (create PDFs), `RustPdf::EditableDoc`
|
|
12
|
+
(load and edit existing PDFs) and module functions (`version`,
|
|
13
|
+
`activate_license`, `extract_text`, `sign`, `timestamp`, `add_dss`).
|
|
19
14
|
|
|
20
15
|
## Loading the native library
|
|
21
16
|
|
data/lib/rustpdf/editable_doc.rb
CHANGED
|
@@ -163,41 +163,130 @@ module RustPdf
|
|
|
163
163
|
found != 0
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
-
#
|
|
167
|
-
#
|
|
166
|
+
# Register a TrueType/OpenType font (from a file path) for text stamping;
|
|
167
|
+
# returns a font id usable with the +font_id+ keyword of #place_text /
|
|
168
|
+
# #masked_text / #place_paragraph. The font is embedded as a subset —
|
|
169
|
+
# stamped text renders with the real font's glyphs and metrics.
|
|
170
|
+
def add_font_file(path)
|
|
171
|
+
RustPdf.out_int { |buf| Native.call("pdf_editable_add_font_file", ptr, path, buf) }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Register a stamping font from raw TrueType/OpenType bytes. See
|
|
175
|
+
# #add_font_file.
|
|
176
|
+
def add_font(data)
|
|
177
|
+
RustPdf.out_int { |buf| Native.call("pdf_editable_add_font", ptr, data, data.bytesize, buf) }
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Draw a line of positioned +text+ anchored at (+x+, +y+) on page
|
|
181
|
+
# +page_index+ (0-based), using standard Helvetica (or an embedded font —
|
|
182
|
+
# pass +font_id+ from #add_font_file / #add_font) at +size+ points in RGB
|
|
168
183
|
# +color+ (each 0..1, default black). +rotation_deg+ rotates the text
|
|
169
184
|
# counter-clockwise about its anchor (match the page rotation to follow a
|
|
170
185
|
# rotated page). +align+ (RustPdf::Align, default LEFT) shifts the start
|
|
171
186
|
# point along the baseline direction by the text width for RIGHT/CENTER
|
|
172
|
-
# alignment.
|
|
173
|
-
#
|
|
187
|
+
# alignment. +anchor+ (RustPdf::VerticalAnchor) says what +y+ means:
|
|
188
|
+
# BASELINE (default, historical behavior), TOP (text hangs from +y+ —
|
|
189
|
+
# baseline lands ascent x size below it, legacy fixed-position layout), BOTTOM
|
|
190
|
+
# (descender line rests on +y+), or LINE_TOP / LINE_BOTTOM (legacy layout engines line
|
|
191
|
+
# box). Coordinates are in the page's VISIBLE space (origin lower-left,
|
|
192
|
+
# y up) unless #stamp_space= chose MEDIA. Returns whether the page (and
|
|
193
|
+
# font) existed.
|
|
174
194
|
def place_text(page_index, x, y, text, size = 12.0, color = [0.0, 0.0, 0.0], rotation_deg = 0.0,
|
|
175
|
-
align: Align::LEFT)
|
|
195
|
+
align: Align::LEFT, font_id: -1, anchor: VerticalAnchor::BASELINE)
|
|
176
196
|
r, g, b = color
|
|
177
197
|
found = RustPdf.out_int do |buf|
|
|
178
|
-
Native.call("
|
|
179
|
-
size.to_f, r.to_f, g.to_f, b.to_f, rotation_deg.to_f, align, buf)
|
|
198
|
+
Native.call("pdf_editable_place_text_anchored", ptr, page_index, x.to_f, y.to_f, text,
|
|
199
|
+
size.to_f, r.to_f, g.to_f, b.to_f, rotation_deg.to_f, align, anchor, font_id, buf)
|
|
180
200
|
end
|
|
181
201
|
found != 0
|
|
182
202
|
end
|
|
183
203
|
|
|
204
|
+
# Choose the coordinate space of the positioned stamping primitives
|
|
205
|
+
# (#fill_rect, #place_text, #masked_text, #place_paragraph, #draw_image)
|
|
206
|
+
# for subsequent calls. StampSpace::VISIBLE (default) keeps the historical
|
|
207
|
+
# behavior — coordinates in the page's displayed space, compensating
|
|
208
|
+
# /Rotate. StampSpace::MEDIA interprets coordinates and +rotation_deg+ in
|
|
209
|
+
# the raw PDF user space (legacy layout semantics), never composing with the
|
|
210
|
+
# page's /Rotate — use it to reproduce legacy-engine placement on rotated/scanned
|
|
211
|
+
# pages. Watermarks and redaction are unaffected.
|
|
212
|
+
def stamp_space=(space)
|
|
213
|
+
RustPdf.check(Native.call("pdf_editable_set_stamp_space", ptr, space))
|
|
214
|
+
@stamp_space = space
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# The current stamping coordinate space (see #stamp_space=).
|
|
218
|
+
def stamp_space
|
|
219
|
+
@stamp_space || StampSpace::VISIBLE
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Chainable form of #stamp_space=.
|
|
223
|
+
def set_stamp_space(space)
|
|
224
|
+
self.stamp_space = space
|
|
225
|
+
self
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Stamp a paragraph with automatic word wrapping on page +page_index+:
|
|
229
|
+
# +text+ is broken into lines that fit +width+ points (greedy, by word;
|
|
230
|
+
# "\n" forces a break) and drawn downward from (+x+, +y+). +anchor+
|
|
231
|
+
# (RustPdf::VerticalAnchor) says what +y+ means for the block: TOP
|
|
232
|
+
# (default) — top of the box, first baseline ascent x size below +y+
|
|
233
|
+
# (legacy fixed-position layout); BASELINE — the first line's baseline; BOTTOM /
|
|
234
|
+
# LINE_BOTTOM — bottom-pinned: the block's bottom rests on +y+ and grows
|
|
235
|
+
# upward by its real content height. +align+ lays lines out inside
|
|
236
|
+
# +[x, x+width]+ (JUSTIFY stretches the word gaps of every line but the
|
|
237
|
+
# last of each paragraph). +max_height+ (points, nil = unlimited) truncates
|
|
238
|
+
# overflowing lines (a ceiling for the bottom-pinned anchors — the last
|
|
239
|
+
# lines stay pinned). +line_height+ scales the default 1.2 x size leading.
|
|
240
|
+
# Pass +font_id+ from #add_font_file / #add_font to wrap and draw with an
|
|
241
|
+
# embedded font (its real metrics drive the break points); -1 uses the
|
|
242
|
+
# built-in Helvetica. +rotation_deg+ rotates the laid-out block
|
|
243
|
+
# counter-clockwise about the anchor. Returns whether the page (and font)
|
|
244
|
+
# existed and the box was valid.
|
|
245
|
+
def place_paragraph(page_index, x, y, width, text, size: 12.0, color: [0.0, 0.0, 0.0],
|
|
246
|
+
align: Align::LEFT, font_id: -1, max_height: nil, line_height: 1.0,
|
|
247
|
+
anchor: VerticalAnchor::TOP, rotation_deg: 0.0)
|
|
248
|
+
found, = paragraph_anchored(page_index, x, y, width, text, size, color, align,
|
|
249
|
+
font_id, max_height, line_height, anchor, rotation_deg)
|
|
250
|
+
found
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Like #place_paragraph but returns a Hash with the number of +:lines+
|
|
254
|
+
# drawn and the consumed block +:height+ in points (top of the first drawn
|
|
255
|
+
# line's box to the bottom of the last one's; 0 when nothing fit) — stack
|
|
256
|
+
# blocks without re-measuring.
|
|
257
|
+
def place_paragraph_measured(page_index, x, y, width, text, size: 12.0, color: [0.0, 0.0, 0.0],
|
|
258
|
+
align: Align::LEFT, font_id: -1, max_height: nil, line_height: 1.0,
|
|
259
|
+
anchor: VerticalAnchor::TOP, rotation_deg: 0.0)
|
|
260
|
+
_, lines, height = paragraph_anchored(page_index, x, y, width, text, size, color, align,
|
|
261
|
+
font_id, max_height, line_height, anchor, rotation_deg)
|
|
262
|
+
{ lines: lines, height: height }
|
|
263
|
+
end
|
|
264
|
+
|
|
184
265
|
# Mask a placeholder: fill an opaque background box +[x, y, x+width,
|
|
185
266
|
# y+height]+ in +bg_color+ (each 0..1, default white), then write +text+
|
|
186
|
-
# over it using standard Helvetica
|
|
267
|
+
# over it using standard Helvetica (or an embedded font — pass +font_id+
|
|
268
|
+
# from #add_font_file / #add_font) at +size+ points in +text_color+ (each
|
|
187
269
|
# 0..1, default black), horizontally aligned per +align+ (RustPdf::Align,
|
|
188
|
-
# default LEFT)
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
#
|
|
270
|
+
# default LEFT). +valign+ (RustPdf::VerticalAlign) controls the vertical
|
|
271
|
+
# alignment of the line inside the box: MIDDLE (default, historical
|
|
272
|
+
# cap-height centering), TOP (line hangs from the top edge — legacy PDF libraries
|
|
273
|
+
# top line-alignment semantics) or BOTTOM (descender line rests on the
|
|
274
|
+
# bottom edge). +padding+ is the horizontal edge inset (points) for
|
|
275
|
+
# LEFT/RIGHT alignment: text starts at +x + padding+ (or ends at
|
|
276
|
+
# +x + width - padding+); nil keeps the historical
|
|
277
|
+
# min(0.15 x size, width / 4), 0 starts flush with the box edge like
|
|
278
|
+
# rectangle-based DrawString APIs. Coordinates are in the page's VISIBLE space
|
|
279
|
+
# (origin lower-left, y up). Returns whether the page (and font) existed.
|
|
192
280
|
def masked_text(page_index, x, y, width, height, text, size = 12.0,
|
|
193
281
|
text_color = [0.0, 0.0, 0.0], bg_color = [1.0, 1.0, 1.0],
|
|
194
|
-
align: Align::LEFT)
|
|
282
|
+
align: Align::LEFT, font_id: -1, valign: VerticalAlign::MIDDLE, padding: nil)
|
|
195
283
|
tr, tg, tb = text_color
|
|
196
284
|
br, bg, bb = bg_color
|
|
197
285
|
found = RustPdf.out_int do |buf|
|
|
198
|
-
Native.call("
|
|
286
|
+
Native.call("pdf_editable_masked_text_pad", ptr, page_index, x.to_f, y.to_f,
|
|
199
287
|
width.to_f, height.to_f, text, size.to_f,
|
|
200
|
-
tr.to_f, tg.to_f, tb.to_f, br.to_f, bg.to_f, bb.to_f, align,
|
|
288
|
+
tr.to_f, tg.to_f, tb.to_f, br.to_f, bg.to_f, bb.to_f, align, valign,
|
|
289
|
+
(padding || -1.0).to_f, font_id, buf)
|
|
201
290
|
end
|
|
202
291
|
found != 0
|
|
203
292
|
end
|
|
@@ -205,13 +294,18 @@ module RustPdf
|
|
|
205
294
|
# Stamp an +image+ (PNG or JPEG bytes; the core dispatches on the signature)
|
|
206
295
|
# onto page +page_index+ (0-based), with its lower-left corner at (+x+, +y+),
|
|
207
296
|
# scaled to +width+ x +height+ points and rotated +rotation_deg+ degrees
|
|
208
|
-
# counter-clockwise
|
|
209
|
-
#
|
|
210
|
-
#
|
|
211
|
-
|
|
297
|
+
# counter-clockwise. +anchor+ (RustPdf::ImageAnchor) controls how a rotated
|
|
298
|
+
# image is anchored: CORNER (default) rotates the image about its own
|
|
299
|
+
# lower-left corner at (x, y); BOUNDING_BOX lands the rotated image's
|
|
300
|
+
# bounding box with its lower-left at (x, y) (bounding-box layout semantics —
|
|
301
|
+
# e.g. a 90-degree image occupies [x, x+height] x [y, y+width]).
|
|
302
|
+
# Coordinates are in the page's VISIBLE space (origin lower-left, y up),
|
|
303
|
+
# regardless of the page's /Rotate. Returns whether the page existed.
|
|
304
|
+
def draw_image(page_index, image, x, y, width, height, rotation_deg = 0.0,
|
|
305
|
+
anchor: ImageAnchor::CORNER)
|
|
212
306
|
found = RustPdf.out_int do |buf|
|
|
213
|
-
Native.call("
|
|
214
|
-
x.to_f, y.to_f, width.to_f, height.to_f, rotation_deg.to_f, buf)
|
|
307
|
+
Native.call("pdf_editable_draw_image_anchored", ptr, page_index, image, image.bytesize,
|
|
308
|
+
x.to_f, y.to_f, width.to_f, height.to_f, rotation_deg.to_f, anchor, buf)
|
|
215
309
|
end
|
|
216
310
|
found != 0
|
|
217
311
|
end
|
|
@@ -289,6 +383,24 @@ module RustPdf
|
|
|
289
383
|
|
|
290
384
|
private
|
|
291
385
|
|
|
386
|
+
# Shared core of #place_paragraph / #place_paragraph_measured. Returns
|
|
387
|
+
# [found (bool), lines (Integer), height (Float)].
|
|
388
|
+
def paragraph_anchored(page_index, x, y, width, text, size, color, align,
|
|
389
|
+
font_id, max_height, line_height, anchor, rotation_deg)
|
|
390
|
+
r, g, b = color
|
|
391
|
+
height_buf = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE, Fiddle::RUBY_FREE)
|
|
392
|
+
lines_buf = Fiddle::Pointer.malloc(Native::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
393
|
+
found_buf = Fiddle::Pointer.malloc(Native::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
394
|
+
RustPdf.check(Native.call("pdf_editable_place_paragraph_anchored", ptr, page_index,
|
|
395
|
+
x.to_f, y.to_f, width.to_f, text, size.to_f,
|
|
396
|
+
r.to_f, g.to_f, b.to_f, align, anchor, font_id,
|
|
397
|
+
(max_height || 0.0).to_f, line_height.to_f, rotation_deg.to_f,
|
|
398
|
+
height_buf, lines_buf, found_buf))
|
|
399
|
+
[found_buf[0, Native::SIZEOF_INT].unpack1("i!") != 0,
|
|
400
|
+
lines_buf[0, Native::SIZEOF_INT].unpack1("i!"),
|
|
401
|
+
height_buf[0, Fiddle::SIZEOF_DOUBLE].unpack1("d")]
|
|
402
|
+
end
|
|
403
|
+
|
|
292
404
|
def ptr
|
|
293
405
|
raise Error, "operation on a closed EditableDoc" if @ptr.nil? || @ptr.null?
|
|
294
406
|
|
data/lib/rustpdf/native.rb
CHANGED
|
@@ -135,6 +135,17 @@ module RustPdf
|
|
|
135
135
|
# Issue #50: stamp a PNG/JPEG image onto an existing page. The image bytes
|
|
136
136
|
# cross as the (uint8_t* data, uintptr_t len) pair, like pdf_editable_load.
|
|
137
137
|
"pdf_editable_draw_image" => [[VP, I, VP, SZ, D, D, D, D, D, VP], I],
|
|
138
|
+
|
|
139
|
+
# Stamping fonts + anchored stamping primitives. font_id -1 = built-in
|
|
140
|
+
# Helvetica; anchors/valign/space/image-anchor cross as small ints.
|
|
141
|
+
"pdf_editable_add_font_file" => [[VP, VP, VP], I],
|
|
142
|
+
"pdf_editable_add_font" => [[VP, VP, SZ, VP], I],
|
|
143
|
+
"pdf_editable_place_text_anchored" => [[VP, I, D, D, VP, D, D, D, D, D, I, I, I, VP], I],
|
|
144
|
+
"pdf_editable_masked_text_pad" => [[VP, I, D, D, D, D, VP, D, D, D, D, D, D, D, I, I, D, I, VP], I],
|
|
145
|
+
"pdf_editable_place_paragraph_anchored" =>
|
|
146
|
+
[[VP, I, D, D, D, VP, D, D, D, D, I, I, I, D, D, D, VP, VP, VP], I],
|
|
147
|
+
"pdf_editable_set_stamp_space" => [[VP, I], I],
|
|
148
|
+
"pdf_editable_draw_image_anchored" => [[VP, I, VP, SZ, D, D, D, D, D, I, VP], I],
|
|
138
149
|
}.freeze
|
|
139
150
|
|
|
140
151
|
def lib
|
data/lib/rustpdf.rb
CHANGED
|
@@ -40,6 +40,48 @@ module RustPdf
|
|
|
40
40
|
JUSTIFY = 3
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
# What +y+ means for stamped text (EditableDoc#place_text /
|
|
44
|
+
# #place_paragraph). BASELINE is the historical place_text behavior; TOP
|
|
45
|
+
# hangs the text from +y+ (baseline lands ascent x size below it, legacy layout engines
|
|
46
|
+
# fixed-position layout semantics); BOTTOM rests the descender line on +y+.
|
|
47
|
+
# LINE_TOP / LINE_BOTTOM anchor via the layout line box (its height is also
|
|
48
|
+
# the leading basis, so a single line and a wrapped block agree vertically).
|
|
49
|
+
module VerticalAnchor
|
|
50
|
+
BASELINE = 0
|
|
51
|
+
TOP = 1
|
|
52
|
+
BOTTOM = 2
|
|
53
|
+
LINE_TOP = 3
|
|
54
|
+
LINE_BOTTOM = 4
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Vertical alignment of the line inside a masked_text box. MIDDLE is the
|
|
58
|
+
# historical cap-height centering; TOP hangs the line from the top edge
|
|
59
|
+
# (top line-alignment in rectangle-based text APIs semantics); BOTTOM rests the descender
|
|
60
|
+
# line on the bottom edge.
|
|
61
|
+
module VerticalAlign
|
|
62
|
+
TOP = 0
|
|
63
|
+
MIDDLE = 1
|
|
64
|
+
BOTTOM = 2
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Coordinate space of the positioned stamping primitives (EditableDoc).
|
|
68
|
+
# VISIBLE (default) compensates the page /Rotate so coordinates match what
|
|
69
|
+
# a viewer displays; MEDIA is the raw PDF user space (legacy layout engines
|
|
70
|
+
# fixed-position layout/rotation semantics — no /Rotate composition).
|
|
71
|
+
module StampSpace
|
|
72
|
+
VISIBLE = 0
|
|
73
|
+
MEDIA = 1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# How a rotated EditableDoc#draw_image is anchored. CORNER (default) rotates
|
|
77
|
+
# the image about its own lower-left corner at (x, y); BOUNDING_BOX lands
|
|
78
|
+
# the rotated image's bounding box with its lower-left at (x, y) (legacy layout engines
|
|
79
|
+
# layout semantics).
|
|
80
|
+
module ImageAnchor
|
|
81
|
+
CORNER = 0
|
|
82
|
+
BOUNDING_BOX = 1
|
|
83
|
+
end
|
|
84
|
+
|
|
43
85
|
# Embedded-file relationship (PDF/A-3).
|
|
44
86
|
module Relationship
|
|
45
87
|
SOURCE = 0
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rustpdf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.8
|
|
5
5
|
platform: x86_64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- rust-pdf
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description:
|
|
14
|
-
|
|
13
|
+
description: 'Generate, edit, sign and process PDFs in Ruby: PDF/A, AES-256 encryption,
|
|
14
|
+
digital signatures (PAdES), forms, stamping, redaction, text extraction and page
|
|
15
|
+
rendering. Docs: https://rustpdf.dev/docs/ruby'
|
|
15
16
|
email:
|
|
16
17
|
executables: []
|
|
17
18
|
extensions: []
|
|
@@ -45,6 +46,5 @@ requirements: []
|
|
|
45
46
|
rubygems_version: 3.5.22
|
|
46
47
|
signing_key:
|
|
47
48
|
specification_version: 4
|
|
48
|
-
summary:
|
|
49
|
-
PDFs).
|
|
49
|
+
summary: 'Generate, edit, sign and process PDFs in Ruby. Docs: https://rustpdf.dev/docs/ruby'
|
|
50
50
|
test_files: []
|