Majorsilence PDF — Ruby Wrapper

Ruby bindings for Majorsilence PDF — generate PDF documents in-process via an AOT-compiled native shared library (pdfnative), accessed through Fiddle FFI. No subprocess is spawned and no .NET runtime is required at runtime.

Ruby 3.0 or later is recommended (# frozen_string_literal: true and endless method definitions are used throughout; Fiddle is part of the standard library through Ruby 3.x).

Features

  • Text with font size, bold, italic, underline, strikethrough, colour, and alignment
  • Shapes: rectangles, lines, circles, and custom strokes
  • Images (embedded or from disk)
  • Tables with header colours, alternating row colours, borders, and cell padding
  • Multi-page documents
  • Custom and system fonts, Unicode / RTL text
  • Password-protected PDFs with fine-grained permission flags
  • PDF merging
  • Annotations and hyperlinks
  • Page sizes: A3, A4, A5, Letter, Legal, Tabloid

Installation

Install from RubyGems:

gem install majorsilence_pdf

Or add it to your Gemfile:

gem 'majorsilence_pdf'

The gem itself has no dependency beyond fiddle (Ruby's standard FFI library). You still need the pdfnative shared library, described below.

Install Ruby

  • Linux (Debian/Ubuntu):
    sudo apt-get update && sudo apt-get install -y ruby
    ruby --version
    
  • macOS (via Homebrew):
    brew install ruby
    ruby --version
    
  • Windows — download the installer from rubyinstaller.org or use winget:
    winget install RubyInstallerTeam.Ruby
    ruby --version
    

Get the pdfnative shared library

Download the native library from a Majorsilence Reporting release (majorsilence-pdf-pdfnative-linux.zip, -osx.zip, or -windows.zip) and extract it. The directory contains the shared library and all its sibling libraries.

Platform Library filename
Linux libpdfnative.so
macOS libpdfnative.dylib
Windows pdfnative.dll

Quick start

require 'majorsilence_pdf'

lib = PdfLibrary.load('/path/to/libpdfnative.so')

doc = PdfDocument.new(lib)
doc.set_title('Hello World')
doc.set_author('My App')

canvas = doc.add_page(*PAGE_A4)

heading = PdfStyle.new(lib)
heading.set_size(24).set_bold
canvas.draw_text('Hello, PDF!', 72, 80, heading.handle)
heading.close

body = PdfStyle.new(lib)
body.set_size(12)
canvas.draw_text('Created with majorsilence_pdf -- no .NET runtime required.', 72, 120, body.handle)
body.close

canvas.close
doc.save('hello.pdf')
doc.close

Tables

require 'majorsilence_pdf'

lib = PdfLibrary.load('/path/to/libpdfnative.so')

doc = PdfDocument.new(lib)
canvas = doc.add_page(*PAGE_A4)

table = PdfTable.new(lib, [180, 80, 90, 90])
table.set_header_bg(26, 86, 160)
      .set_alternate_bg(240, 245, 252)
      .set_border(200, 200, 200, 0.5)
      .set_cell_padding(5)
      .add_row('Product', 'Qty', 'Unit Price', 'Total')
      .add_row('PDF Library Pro', '3', '$400.00', '$1,200.00')
      .add_row('Report Designer', '1', '$250.00', '$250.00')

canvas.draw_table(table.handle, 72, 92)
table.close

canvas.close
doc.save('report.pdf')
doc.close

Or write to memory instead of a file with doc.save_to_memory, which returns the PDF as a binary String.

On Linux, pre-load the library directory before starting Ruby:

export LD_LIBRARY_PATH=/path/to/pdfnative-dir:$LD_LIBRARY_PATH
ruby your_script.rb

More examples

See the Examples/ directory for 18 ready-to-run scripts covering text styles, shapes, images, custom fonts, Unicode/RTL text, invoices, dashboards, password protection, table layout, and PDF merging. Each expects PDFNATIVE_LIB set to the path of the shared library:

PDFNATIVE_LIB=/path/to/libpdfnative.so ruby Examples/example_01_hello_world.rb

Releasing (maintainers)

Releases are published to RubyGems by .github/workflows/publish.yml using Trusted Publishing (OIDC) -- no API key is stored in this repo.

One-time setup on rubygems.org, under Profile -> Trusted publishers (or "Pending trusted publishers" before the gem's first release):

Field Value
Gem name majorsilence_pdf
Repository owner majorsilence
Repository name pdf-ruby
Workflow filename publish.yml
Environment release

To cut a release:

# Bump the version
$EDITOR lib/majorsilence_pdf/version.rb

git commit -am "Release vX.Y.Z"
git tag vX.Y.Z
git push origin main --tags

Pushing the vX.Y.Z tag triggers the workflow, which runs the test suite and then uses rubygems/release-gem to build and push the gem.


License

Triple-licensed under MIT, Apache-2.0, and BSD-2-Clause. Choose whichever suits your project.