Module: Rpdfium::Raw

Extended by:
FFI::Library
Defined in:
lib/rpdfium/raw.rb

Overview

Layer 1: bindings FFI grezzi alle API C di PDFium. Mappa 1:1 con i nomi originali. Usare le classi wrapper per il codice applicativo. Le API “Experimental” di PDFium sono marcate nei commenti: in teoria potrebbero cambiare, in pratica sono stabili da anni.

Defined Under Namespace

Classes: FPDF_FORMFILLINFO, FPDF_IMAGEOBJ_METADATA, FS_MATRIX, FS_POINTF, FS_QUADPOINTSF, FS_RECTF, FS_SIZEF

Constant Summary collapse

FPDFBitmap_Unknown =

Costanti

Bitmap formats

0
FPDFBitmap_Gray =
1
FPDFBitmap_BGR =
2
FPDFBitmap_BGRx =
3
FPDFBitmap_BGRA =
4
FPDF_ANNOT =

Render flags (bit fields)

0x01
FPDF_LCD_TEXT =
0x02
FPDF_NO_NATIVETEXT =
0x04
FPDF_GRAYSCALE =
0x08
FPDF_REVERSE_BYTE_ORDER =

→ RGBA invece di BGRA

0x10
FPDF_NO_GDIPLUS =
0x40
FPDF_PRINTING =
0x800
FPDF_RENDER_NO_SMOOTHTEXT =
0x1000
FPDF_RENDER_NO_SMOOTHIMAGE =
0x2000
FPDF_RENDER_NO_SMOOTHPATH =
0x4000
PAGEOBJ_UNKNOWN =

Page object types

0
PAGEOBJ_TEXT =
1
PAGEOBJ_PATH =
2
PAGEOBJ_IMAGE =
3
PAGEOBJ_SHADING =
4
PAGEOBJ_FORM =
5
SEGMENT_UNKNOWN =

Path segment types

-1
SEGMENT_LINETO =
0
SEGMENT_BEZIERTO =
1
SEGMENT_MOVETO =
2
FILLMODE_NONE =

Path fill mode

0
FILLMODE_ALTERNATE =
1
FILLMODE_WINDING =
2
TEXT_RENDERMODE_FILL =

Text render modes

0
TEXT_RENDERMODE_STROKE =
1
TEXT_RENDERMODE_FILL_STROKE =
2
TEXT_RENDERMODE_INVISIBLE =
3
FPDF_ANNOT_UNKNOWN =

Annotation subtypes (PDF spec 12.5.6)

0
FPDF_ANNOT_TEXT =
1
2
FPDF_ANNOT_FREETEXT =
3
FPDF_ANNOT_LINE =
4
FPDF_ANNOT_SQUARE =
5
FPDF_ANNOT_CIRCLE =
6
FPDF_ANNOT_HIGHLIGHT =
9
FPDF_ANNOT_UNDERLINE =
10
FPDF_ANNOT_SQUIGGLY =
11
FPDF_ANNOT_STRIKEOUT =
12
FPDF_ANNOT_STAMP =
13
FPDF_ANNOT_INK =
15
FPDF_ANNOT_POPUP =
16
FPDF_ANNOT_FILEATTACHMENT =
17
FPDF_ANNOT_WIDGET =
20
FPDF_ANNOT_REDACT =
27
ANNOT_SUBTYPE_NAMES =
{
  FPDF_ANNOT_TEXT => "Text", FPDF_ANNOT_LINK => "Link",
  FPDF_ANNOT_FREETEXT => "FreeText", FPDF_ANNOT_LINE => "Line",
  FPDF_ANNOT_SQUARE => "Square", FPDF_ANNOT_CIRCLE => "Circle",
  FPDF_ANNOT_HIGHLIGHT => "Highlight", FPDF_ANNOT_UNDERLINE => "Underline",
  FPDF_ANNOT_SQUIGGLY => "Squiggly", FPDF_ANNOT_STRIKEOUT => "StrikeOut",
  FPDF_ANNOT_STAMP => "Stamp", FPDF_ANNOT_INK => "Ink",
  FPDF_ANNOT_POPUP => "Popup",
  FPDF_ANNOT_FILEATTACHMENT => "FileAttachment",
  FPDF_ANNOT_WIDGET => "Widget", FPDF_ANNOT_REDACT => "Redact"
}.freeze
FPDF_FORMFIELD_UNKNOWN =

Form field types (per widget annotations)

0
FPDF_FORMFIELD_PUSHBUTTON =
1
FPDF_FORMFIELD_CHECKBOX =
2
FPDF_FORMFIELD_RADIOBUTTON =
3
FPDF_FORMFIELD_COMBOBOX =
4
FPDF_FORMFIELD_LISTBOX =
5
FPDF_FORMFIELD_TEXTFIELD =
6
FPDF_FORMFIELD_SIGNATURE =
7
FPDF_MATCHCASE =

Search flags

0x01
FPDF_MATCHWHOLEWORD =
0x02
FPDF_CONSECUTIVE =
0x04
FORMTYPE_NONE =

Form types (FPDF_GetFormType)

0
FORMTYPE_ACRO_FORM =
1
FORMTYPE_XFA_FULL =
2
FORMTYPE_XFA_FOREGROUND =
3

Class Method Summary collapse

Class Method Details

.attach_function(name, *_args) ⇒ Object

Override di attach_function quando la libreria non si è caricata: non chiamare super (che esploderebbe), genera direttamente lo stub.



87
88
89
90
91
92
93
94
# File 'lib/rpdfium/raw.rb', line 87

def self.attach_function(name, *args)
  super
rescue FFI::NotFoundError, RuntimeError => e
  define_singleton_method(name) do |*_a|
    raise Rpdfium::LoadError,
          "PDFium symbol #{name} not available: #{e.message}"
  end
end

.candidate_pathsObject

Costruisce la lista di candidati che ‘ffi_lib` proverà in ordine.

ATTENZIONE: FFI auto-appende l’estensione “naturale” della piattaforma (.dylib su macOS, .so su linux, .dll su windows) quando il path passato non termina già con un’estensione conosciuta. Quindi se passiamo ‘libpdfium.so` su macOS, FFI cerca `libpdfium.so.dylib` — assurdo ma documentato. Per evitarlo, filtriamo i nomi system_library_names per OS host.

Inoltre: ENV e Rpdfium::Binary.library_path sono path ASSOLUTI/ESPLICITI: se non vengono trovati, NON facciamo fallback a nomi di sistema. Restituiamo subito un array di un solo path: in quel caso ffi_lib o riesce subito, o lancia LoadError chiaro (è ciò che vuole l’utente — gli ha dato un path esplicito).



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rpdfium/raw.rb', line 28

def self.candidate_paths
  explicit = ENV["PDFIUM_LIBRARY_PATH"]
  return [explicit] if explicit && !explicit.empty?

  if defined?(Rpdfium::Binary) && Rpdfium::Binary.respond_to?(:library_path)
    path = Rpdfium::Binary.library_path
    return [path] if path && !path.empty?
  end

  system_library_names
end

.host_osObject



56
57
58
59
60
61
62
# File 'lib/rpdfium/raw.rb', line 56

def self.host_os
  case RbConfig::CONFIG["host_os"]
  when /darwin/         then :macos
  when /linux/          then :linux
  when /mswin|mingw|cygwin/ then :windows
  end
end

.load_errorObject



68
# File 'lib/rpdfium/raw.rb', line 68

def self.load_error;     @load_error;    end

.native_loaded?Boolean

Returns:

  • (Boolean)


67
# File 'lib/rpdfium/raw.rb', line 67

def self.native_loaded?; @native_loaded; end

.read_utf16_string(method_name, *args) ⇒ Object

Helper: leggere stringhe UTF-16LE che PDFium ritorna in bytes

Convenzione PDFium: la maggior parte delle Get*Text/Get*Name ritornano ‘unsigned long` (numero BYTES, terminatore incluso). Si chiama prima con buffer NULL/0 per ottenere la dimensione, poi con buffer allocato.



964
965
966
967
968
969
970
971
972
973
# File 'lib/rpdfium/raw.rb', line 964

def self.read_utf16_string(method_name, *args)
  args_probe = args + [FFI::Pointer::NULL, 0]
  n_bytes = send(method_name, *args_probe)
  return "" if n_bytes <= 2 # solo terminatore null o errore

  buf = FFI::MemoryPointer.new(:uchar, n_bytes)
  args_real = args + [buf, n_bytes]
  send(method_name, *args_real)
  utf16_bytes_to_utf8(buf.read_bytes(n_bytes))
end

.system_library_namesObject

Nomi “di sistema” filtrati per OS host. Manteniamo ‘pdfium` / `libpdfium` (senza estensione) per primi: FFI auto-appende l’ext giusta. I nomi con estensione vengono SOLO se matchano l’OS host, così evitiamo il bug di doppia estensione.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rpdfium/raw.rb', line 44

def self.system_library_names
  base = %w[pdfium libpdfium]
  host = host_os
  ext_specific = case host
                 when :macos   then %w[libpdfium.dylib]
                 when :linux   then %w[libpdfium.so]
                 when :windows then %w[pdfium.dll libpdfium.dll]
                 else []
                 end
  base + ext_specific
end

.utf16_bytes_to_utf8(bytes) ⇒ Object

PDFium ritorna UTF-16LE little-endian con terminatore null.



976
977
978
979
980
# File 'lib/rpdfium/raw.rb', line 976

def self.utf16_bytes_to_utf8(bytes)
  bytes.force_encoding("UTF-16LE")
       .encode("UTF-8", invalid: :replace, undef: :replace)
       .delete("\x00")
end