rustpdf 0.4.6-universal-darwin → 0.5.0-universal-darwin
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 +12 -19
- data/lib/rustpdf/editable_doc.rb +134 -22
- data/lib/rustpdf/native.rb +11 -1
- data/lib/rustpdf.rb +46 -12
- data/vendor/universal-darwin/libpdf_ffi.dylib +0 -0
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64ca4d038b618dec18c4357fef57fb2fe6d9f78ee66ffc0ae1dd4e4f32d9f1cb
|
|
4
|
+
data.tar.gz: 8555d12cdc7b5c24df532892442d1d327a52285ae45b4416bc7eb074c29b4fbf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 499b563398fa46ab3a5efb9d77688ca9674305fb3e70f5e046e4ec4f62bfa065b7b0fa5da2a04bae38f4155fb3a4f353daa5bd049166448ce46c32659b575b20
|
|
7
|
+
data.tar.gz: 9d460b4c64c56d8810092a3336cf52fd91df84b440df88765e6db184fce4ceb0867b484ab49c1df3bb3468969eb3a17b1f1d6709e7f7c8b7c5b9857dd9e4b374
|
data/README.md
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# RustPdf for Ruby
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
using the built-in **Fiddle** standard library — no native gem to compile. It
|
|
5
|
-
covers the whole product surface: vector graphics, embedded/subsetted fonts and
|
|
6
|
-
text, wrapping paragraphs, images, **PDF/A** (levels 1b–3a),
|
|
7
|
-
**tagged/accessible** output, embedded-file attachments, **AcroForm** fields,
|
|
8
|
-
manipulation (merge/split/rotate/optimize/incremental update), **text
|
|
9
|
-
extraction**, **page rendering** (page to PNG image), **encryption** (RC4 / AES-128 / AES-256) and **digital signatures**
|
|
10
|
-
(PKCS#7 / PAdES) — plus **feature licensing**.
|
|
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.
|
|
11
4
|
|
|
12
|
-
|
|
5
|
+
## Documentation
|
|
13
6
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
+
`extract_text`, `sign`, `timestamp`, `add_dss`).
|
|
19
14
|
|
|
20
15
|
## Loading the native library
|
|
21
16
|
|
|
@@ -28,8 +23,6 @@ Files (module `RustPdf`):
|
|
|
28
23
|
```ruby
|
|
29
24
|
require "rustpdf"
|
|
30
25
|
|
|
31
|
-
RustPdf.activate_license(token) # or set RUSTPDF_LICENSE (auto-activated)
|
|
32
|
-
|
|
33
26
|
doc = RustPdf::Document.new
|
|
34
27
|
doc.pdfa(RustPdf::Pdfa::A2A).info(title: "Report")
|
|
35
28
|
f = doc.add_font_file("assets/fonts/Roboto-Regular.ttf")
|
|
@@ -46,8 +39,8 @@ ed.encrypt(method: RustPdf::Cipher::AES256, owner: "owner").save("secured.pdf")
|
|
|
46
39
|
signed = RustPdf.sign(data, key_der, cert_der, pades: true)
|
|
47
40
|
```
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
Every feature is free — PDF/A, digital signatures/PAdES, encryption,
|
|
43
|
+
accessibility/tagging, redaction and page rendering are all included.
|
|
51
44
|
|
|
52
45
|
## Deferred / HSM signing
|
|
53
46
|
|
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
|
|
@@ -265,7 +359,7 @@ module RustPdf
|
|
|
265
359
|
self
|
|
266
360
|
end
|
|
267
361
|
|
|
268
|
-
# Encrypt on save
|
|
362
|
+
# Encrypt on save.
|
|
269
363
|
def encrypt(method: Cipher::AES256, user: "", owner: "", read_only: false)
|
|
270
364
|
RustPdf.check(Native.call("pdf_editable_encrypt", ptr, method, user, owner, read_only ? 1 : 0))
|
|
271
365
|
self
|
|
@@ -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
|
@@ -19,7 +19,6 @@ module RustPdf
|
|
|
19
19
|
SIGS = {
|
|
20
20
|
"pdf_version" => [[], VP],
|
|
21
21
|
"pdf_last_error_message" => [[], VP],
|
|
22
|
-
"pdf_activate_license" => [[VP], I],
|
|
23
22
|
"pdf_buffer_free" => [[VP, SZ], VOID],
|
|
24
23
|
|
|
25
24
|
"pdf_document_new" => [[], VP],
|
|
@@ -135,6 +134,17 @@ module RustPdf
|
|
|
135
134
|
# Issue #50: stamp a PNG/JPEG image onto an existing page. The image bytes
|
|
136
135
|
# cross as the (uint8_t* data, uintptr_t len) pair, like pdf_editable_load.
|
|
137
136
|
"pdf_editable_draw_image" => [[VP, I, VP, SZ, D, D, D, D, D, VP], I],
|
|
137
|
+
|
|
138
|
+
# Stamping fonts + anchored stamping primitives. font_id -1 = built-in
|
|
139
|
+
# Helvetica; anchors/valign/space/image-anchor cross as small ints.
|
|
140
|
+
"pdf_editable_add_font_file" => [[VP, VP, VP], I],
|
|
141
|
+
"pdf_editable_add_font" => [[VP, VP, SZ, VP], I],
|
|
142
|
+
"pdf_editable_place_text_anchored" => [[VP, I, D, D, VP, D, D, D, D, D, I, I, I, VP], I],
|
|
143
|
+
"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],
|
|
144
|
+
"pdf_editable_place_paragraph_anchored" =>
|
|
145
|
+
[[VP, I, D, D, D, VP, D, D, D, D, I, I, I, D, D, D, VP, VP, VP], I],
|
|
146
|
+
"pdf_editable_set_stamp_space" => [[VP, I], I],
|
|
147
|
+
"pdf_editable_draw_image_anchored" => [[VP, I, VP, SZ, D, D, D, D, D, I, VP], I],
|
|
138
148
|
}.freeze
|
|
139
149
|
|
|
140
150
|
def lib
|
data/lib/rustpdf.rb
CHANGED
|
@@ -7,7 +7,7 @@ require_relative "rustpdf/native"
|
|
|
7
7
|
# using the built-in Fiddle stdlib. Covers the whole product surface: vector
|
|
8
8
|
# graphics, fonts/text, paragraphs, images, PDF/A (1b-3a), tagged/accessible
|
|
9
9
|
# output, attachments, AcroForm fields, manipulation, text extraction,
|
|
10
|
-
# encryption and digital signatures
|
|
10
|
+
# encryption and digital signatures. Free and open source (MIT).
|
|
11
11
|
module RustPdf
|
|
12
12
|
# Raised when a native call returns a non-zero PdfStatus.
|
|
13
13
|
class Error < StandardError
|
|
@@ -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
|
|
@@ -215,13 +257,6 @@ module RustPdf
|
|
|
215
257
|
Native.call("pdf_version").to_s
|
|
216
258
|
end
|
|
217
259
|
|
|
218
|
-
# Activate a license token (unlocks PDF/A, signing, encryption,
|
|
219
|
-
# accessibility). Tokens may also be supplied via the RUSTPDF_LICENSE /
|
|
220
|
-
# RUSTPDF_LICENSE_FILE environment variables (auto-activated).
|
|
221
|
-
def activate_license(token)
|
|
222
|
-
check(Native.call("pdf_activate_license", token))
|
|
223
|
-
end
|
|
224
|
-
|
|
225
260
|
# Extract a document's text (Unicode via ToUnicode).
|
|
226
261
|
def extract_text(pdf)
|
|
227
262
|
take_bytes { |pp, pn| Native.call("pdf_extract_text", pdf, pdf.bytesize, pp, pn) }
|
|
@@ -244,13 +279,12 @@ module RustPdf
|
|
|
244
279
|
end
|
|
245
280
|
|
|
246
281
|
# Render page +page+ (0-based) of +pdf+ to a PNG image at +dpi+
|
|
247
|
-
# dots-per-inch.
|
|
248
|
-
# license granting it is active.
|
|
282
|
+
# dots-per-inch.
|
|
249
283
|
def render_page_to_png(pdf, page = 0, dpi = 150.0)
|
|
250
284
|
take_bytes { |pp, pn| Native.call("pdf_render_page_to_png", pdf, pdf.bytesize, page, dpi.to_f, pp, pn) }
|
|
251
285
|
end
|
|
252
286
|
|
|
253
|
-
# Number of pages in +pdf+ (free
|
|
287
|
+
# Number of pages in +pdf+ (free).
|
|
254
288
|
def page_count(pdf)
|
|
255
289
|
count = Fiddle::Pointer.malloc(Native::SIZEOF_SZ, Fiddle::RUBY_FREE)
|
|
256
290
|
check(Native.call("pdf_page_count", pdf, pdf.bytesize, count))
|
|
@@ -324,7 +358,7 @@ module RustPdf
|
|
|
324
358
|
js.empty? ? [] : JSON.parse(js)
|
|
325
359
|
end
|
|
326
360
|
|
|
327
|
-
# Sign a PDF (PKCS#7 detached, incremental update).
|
|
361
|
+
# Sign a PDF (PKCS#7 detached, incremental update).
|
|
328
362
|
def sign(pdf, key_der, cert_der, reason: nil, location: nil, name: nil, pades: false)
|
|
329
363
|
take_bytes do |pp, pn|
|
|
330
364
|
Native.call("pdf_sign", pdf, pdf.bytesize, key_der, key_der.bytesize,
|
|
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
|
+
version: 0.5.0
|
|
5
5
|
platform: universal-darwin
|
|
6
6
|
authors:
|
|
7
7
|
- rust-pdf
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-23 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: []
|
|
@@ -25,7 +26,7 @@ files:
|
|
|
25
26
|
- vendor/universal-darwin/libpdf_ffi.dylib
|
|
26
27
|
homepage:
|
|
27
28
|
licenses:
|
|
28
|
-
-
|
|
29
|
+
- MIT
|
|
29
30
|
metadata: {}
|
|
30
31
|
post_install_message:
|
|
31
32
|
rdoc_options: []
|
|
@@ -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: []
|