rustpdf 0.4.4-aarch64-linux → 0.4.6-aarch64-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a9f8748dc44df1f9a62da646c68d0c72277cdc5be78b1d45e8a07e371936668
4
- data.tar.gz: 94a7fe602d4e77a601f6f4edd74f745ec0a20bb6b2706a6d1376c5e10409e09e
3
+ metadata.gz: 70178a69ffe81e07690514a1c1fe8116707b848b381fbf1ae17952571c9c31ef
4
+ data.tar.gz: 753e07ad832d29f6d638397f10cb0888495fc2a4c56f39b2216d260edf2267b8
5
5
  SHA512:
6
- metadata.gz: 58b4668a5ce6344d838a6b5c4da2ffdd0676d4b8890d4a088deb2d7c5ac4e0506d0116991584f505c5c542ebe6eb0dab42039531c079ca62f444c592e8fed6b5
7
- data.tar.gz: 70bf9dbca7a482309342e8cbcd838f9545925829bfa0eff7d1135674333ca601518e2a7ea0b993ce0630020de8574afd48f3c0014d745ca23343ee1004e46004
6
+ metadata.gz: 10f7a53e4b0d0f3d76e51ef0aac75654b4a9efda0b355aa84415d2a81a0510079f686d116d9b7ec69ccf9637e4fe8a10349001a85a0a0aa38c238e64341eb5d0
7
+ data.tar.gz: 48d2852ad7d33e705c4e8dac80fb807109704799d270c93367838bc160465792535b8c2d94380e19e5f30dfb307f9624b7f52772db628bab62b56dfde62c5cb3
@@ -146,6 +146,76 @@ module RustPdf
146
146
  self
147
147
  end
148
148
 
149
+ # ---- positioned drawing primitives (issue #45 P1) -----------------------
150
+
151
+ # Paint a filled rectangle at (+x+, +y+) sized +width+ x +height+ on page
152
+ # +page_index+ (0-based), in RGB +color+ (each 0..1, default opaque white) at
153
+ # +opacity+ (0..1). Coordinates are in the page's VISIBLE space (origin
154
+ # lower-left, y up), regardless of the page's /Rotate. The common use is
155
+ # masking a placeholder with an opaque white box. Returns whether the page
156
+ # existed.
157
+ def fill_rect(page_index, x, y, width, height, color = [1.0, 1.0, 1.0], opacity = 1.0)
158
+ r, g, b = color
159
+ found = RustPdf.out_int do |buf|
160
+ Native.call("pdf_editable_fill_rect", ptr, page_index, x.to_f, y.to_f,
161
+ width.to_f, height.to_f, r.to_f, g.to_f, b.to_f, opacity.to_f, buf)
162
+ end
163
+ found != 0
164
+ end
165
+
166
+ # Draw a line of positioned +text+ with baseline at (+x+, +y+) on page
167
+ # +page_index+ (0-based), using standard Helvetica at +size+ points in RGB
168
+ # +color+ (each 0..1, default black). +rotation_deg+ rotates the text
169
+ # counter-clockwise about its anchor (match the page rotation to follow a
170
+ # rotated page). +align+ (RustPdf::Align, default LEFT) shifts the start
171
+ # point along the baseline direction by the text width for RIGHT/CENTER
172
+ # alignment. Coordinates are in the page's VISIBLE space (origin lower-left,
173
+ # y up), regardless of the page's /Rotate. Returns whether the page existed.
174
+ 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)
176
+ r, g, b = color
177
+ found = RustPdf.out_int do |buf|
178
+ Native.call("pdf_editable_place_text_aligned", ptr, page_index, x.to_f, y.to_f, text,
179
+ size.to_f, r.to_f, g.to_f, b.to_f, rotation_deg.to_f, align, buf)
180
+ end
181
+ found != 0
182
+ end
183
+
184
+ # Mask a placeholder: fill an opaque background box +[x, y, x+width,
185
+ # y+height]+ in +bg_color+ (each 0..1, default white), then write +text+
186
+ # over it using standard Helvetica at +size+ points in +text_color+ (each
187
+ # 0..1, default black), horizontally aligned per +align+ (RustPdf::Align,
188
+ # default LEFT) and vertically centered within the box. Saves hand-computing
189
+ # the baseline when stamping a real value over a placeholder. Coordinates are
190
+ # in the page's VISIBLE space (origin lower-left, y up). Returns whether the
191
+ # page existed.
192
+ def masked_text(page_index, x, y, width, height, text, size = 12.0,
193
+ text_color = [0.0, 0.0, 0.0], bg_color = [1.0, 1.0, 1.0],
194
+ align: Align::LEFT)
195
+ tr, tg, tb = text_color
196
+ br, bg, bb = bg_color
197
+ found = RustPdf.out_int do |buf|
198
+ Native.call("pdf_editable_masked_text", ptr, page_index, x.to_f, y.to_f,
199
+ 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, buf)
201
+ end
202
+ found != 0
203
+ end
204
+
205
+ # Stamp an +image+ (PNG or JPEG bytes; the core dispatches on the signature)
206
+ # onto page +page_index+ (0-based), with its lower-left corner at (+x+, +y+),
207
+ # scaled to +width+ x +height+ points and rotated +rotation_deg+ degrees
208
+ # counter-clockwise about that corner. Coordinates are in the page's VISIBLE
209
+ # space (origin lower-left, y up), regardless of the page's /Rotate. Returns
210
+ # whether the page existed.
211
+ def draw_image(page_index, image, x, y, width, height, rotation_deg = 0.0)
212
+ found = RustPdf.out_int do |buf|
213
+ Native.call("pdf_editable_draw_image", ptr, page_index, image, image.bytesize,
214
+ x.to_f, y.to_f, width.to_f, height.to_f, rotation_deg.to_f, buf)
215
+ end
216
+ found != 0
217
+ end
218
+
149
219
  # ---- redaction + PDF/A conversion (Tier 2) ------------------------------
150
220
 
151
221
  # Black out rectangles on a page. rects = [[x0,y0,x1,y1], ...].
@@ -78,6 +78,7 @@ module RustPdf
78
78
  "pdf_editable_save" => [[VP, VP], I],
79
79
 
80
80
  "pdf_extract_text" => [[VP, SZ, VP, VP], I],
81
+ "pdf_extract_page_text" => [[VP, SZ, SZ, VP, VP], I],
81
82
  "pdf_extract_images_to_dir" => [[VP, SZ, VP, VP], I],
82
83
  "pdf_render_page_to_png" => [[VP, SZ, SZ, D, VP, VP], I],
83
84
  "pdf_page_count" => [[VP, SZ, VP], I],
@@ -123,6 +124,17 @@ module RustPdf
123
124
  "pdf_timestamp_begin" => [[VP, SZ, VP, VP, VP, VP], I],
124
125
  "pdf_timestamp_request" => [[VP, SZ, VP, SZ, I, VP, VP], I],
125
126
  "pdf_timestamp_token_from_response" => [[VP, SZ, VP, VP], I],
127
+
128
+ # Issue #45 P1: page geometry, document inspection, positioned drawing.
129
+ "pdf_measure_pages_json" => [[VP, SZ, VP, VP], I],
130
+ "pdf_inspect_json" => [[VP, SZ, VP, VP], I],
131
+ "pdf_editable_fill_rect" => [[VP, I, D, D, D, D, D, D, D, D, VP], I],
132
+ "pdf_editable_place_text" => [[VP, I, D, D, VP, D, D, D, D, D, VP], I],
133
+ "pdf_editable_place_text_aligned" => [[VP, I, D, D, VP, D, D, D, D, D, I, VP], I],
134
+ "pdf_editable_masked_text" => [[VP, I, D, D, D, D, VP, D, D, D, D, D, D, D, I, VP], I],
135
+ # Issue #50: stamp a PNG/JPEG image onto an existing page. The image bytes
136
+ # cross as the (uint8_t* data, uintptr_t len) pair, like pdf_editable_load.
137
+ "pdf_editable_draw_image" => [[VP, I, VP, SZ, D, D, D, D, D, VP], I],
126
138
  }.freeze
127
139
 
128
140
  def lib
data/lib/rustpdf.rb CHANGED
@@ -157,6 +157,31 @@ module RustPdf
157
157
  # origin lower-left; +x+/+y+ is the lower-left corner of the box.
158
158
  TextHit = Struct.new(:page, :text, :x, :y, :width, :height)
159
159
 
160
+ # A rectangle in PDF user space (points, origin lower-left). Used for a page's
161
+ # MediaBox/CropBox. #width / #height are the (non-negative) extents.
162
+ PdfRect = Struct.new(:x0, :y0, :x1, :y1) do
163
+ def width
164
+ (x1 - x0).abs
165
+ end
166
+
167
+ def height
168
+ (y1 - y0).abs
169
+ end
170
+ end
171
+
172
+ # Read-only geometry of one page (from #measure_page / #measure_pages). Sizes
173
+ # are in PDF points; +width+/+height+ ignore rotation while +rotated_width+/
174
+ # +rotated_height+ account for it (swapped for 90/270 pages). +media_box+ and
175
+ # +crop_box+ are PdfRect values.
176
+ PageGeometry = Struct.new(:page, :width, :height, :rotation,
177
+ :rotated_width, :rotated_height, :media_box, :crop_box)
178
+
179
+ # A non-mutating summary of a PDF (from #inspect_pdf). +pdfa_level+ is nil when
180
+ # the document is not PDF/A; +encryption+ is the cipher name ("None" when the
181
+ # document is not encrypted).
182
+ PdfOverview = Struct.new(:version, :pdfa_level, :encrypted, :encryption,
183
+ :requires_password, :page_count)
184
+
160
185
  # An in-progress two-phase signature: #document holds the placeholder PDF and
161
186
  # #bytes the exact bytes the signature covers. Hand #hash to a remote signer,
162
187
  # build the CMS container, then call #complete.
@@ -203,6 +228,13 @@ module RustPdf
203
228
  .force_encoding(Encoding::UTF_8)
204
229
  end
205
230
 
231
+ # Extract the text of a single 0-based +page_index+ (Unicode via ToUnicode),
232
+ # without building an intermediate one-page document.
233
+ def extract_page_text(pdf, page_index)
234
+ take_bytes { |pp, pn| Native.call("pdf_extract_page_text", pdf, pdf.bytesize, page_index, pp, pn) }
235
+ .force_encoding(Encoding::UTF_8)
236
+ end
237
+
206
238
  # Extract every raster image into +dir+ (JPEG verbatim as .jpg, others as
207
239
  # .png; files named page{N}_{name}.{ext}). Returns the number written.
208
240
  def extract_images_to_dir(pdf, dir)
@@ -240,6 +272,46 @@ module RustPdf
240
272
  end
241
273
  end
242
274
 
275
+ # Read the geometry (size, rotation, MediaBox, CropBox) of every page in +pdf+,
276
+ # in page order, without mutating it. Returns an Array of PageGeometry. Sizes
277
+ # are in PDF points; +rotated_width+/+rotated_height+ swap for 90/270 pages.
278
+ def measure_pages(pdf)
279
+ js = take_bytes { |pp, pn| Native.call("pdf_measure_pages_json", pdf, pdf.bytesize, pp, pn) }
280
+ .force_encoding(Encoding::UTF_8)
281
+ return [] if js.empty?
282
+
283
+ rect = lambda do |arr|
284
+ a = Array(arr)
285
+ a.size == 4 ? PdfRect.new(a[0], a[1], a[2], a[3]) : PdfRect.new(0, 0, 0, 0)
286
+ end
287
+ JSON.parse(js).map do |g|
288
+ PageGeometry.new(g["page"], g["width"], g["height"], g["rotation"],
289
+ g["rotatedWidth"], g["rotatedHeight"],
290
+ rect.call(g["mediaBox"]), rect.call(g["cropBox"]))
291
+ end
292
+ end
293
+
294
+ # Read the geometry of a single 0-based page of +pdf+. Raises IndexError if
295
+ # +index+ is out of range.
296
+ def measure_page(pdf, index)
297
+ pages = measure_pages(pdf)
298
+ raise IndexError, "page index #{index} out of range (#{pages.size} pages)" if index.negative? || index >= pages.size
299
+
300
+ pages[index]
301
+ end
302
+
303
+ # Inspect +pdf+ without mutating it: PDF version, PDF/A level (if any),
304
+ # encryption posture and page count. Works even on password-protected files
305
+ # (the encryption fields are still reported). Returns a PdfOverview. Named
306
+ # +inspect_pdf+ to avoid shadowing Object#inspect.
307
+ def inspect_pdf(pdf)
308
+ js = take_bytes { |pp, pn| Native.call("pdf_inspect_json", pdf, pdf.bytesize, pp, pn) }
309
+ .force_encoding(Encoding::UTF_8)
310
+ o = JSON.parse(js)
311
+ PdfOverview.new(o["version"], o["pdfaLevel"], o["encrypted"] ? true : false,
312
+ o["encryption"], o["requiresPassword"] ? true : false, o["pageCount"])
313
+ end
314
+
243
315
  # Validate every signature in +pdf+. Returns one Hash per signature with keys
244
316
  # "field_name", "sub_filter", "signer", "covers_whole_document",
245
317
  # "digest_valid", "signature_valid", "is_valid" and "byte_range", plus the
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rustpdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.6
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - rust-pdf