diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4c8bac1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + macos: + name: macOS / Ruby ${{ matrix.ruby }} + runs-on: macos-14 + strategy: + fail-fast: false + matrix: + ruby: ['3.2', '3.3', '3.4'] + steps: + - uses: actions/checkout@v4 + + - name: Clone libBeresta (read-only) for codegen + native build + run: | + git clone --depth=1 https://github.com/libBeresta/libBeresta.git ../libBeresta + + - name: Install build deps (cmake, libpng, zlib, pkg-config) + run: | + brew update + brew install cmake libpng pkg-config + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + + - name: Build libBeresta.dylib + run: | + cmake -S . -B build \ + -DLIBBRST_SOURCE_DIR=$(cd ../libBeresta && pwd) \ + -DCMAKE_BUILD_TYPE=Release + cmake --build build --config Release -j + + - name: Regenerate FFI bindings from .lsp + run: | + ruby generator/bin/brst-binding-ruby-gen \ + --data-dir ../libBeresta/gen/data \ + --out-dir lib/brst/binding/ruby + + - name: Verify regeneration is idempotent (no diff) + run: | + if ! git diff --quiet -- lib/brst/binding/ruby; then + echo "Regeneration produced a diff — committed bindings drifted from generator output:" + git diff --stat -- lib/brst/binding/ruby + git diff -- lib/brst/binding/ruby + exit 1 + fi + + - name: Run tests + run: bundle exec rspec + + - name: Build gem + run: gem build brst-binding-ruby.gemspec diff --git a/.gitignore b/.gitignore index c111b33..bea2641 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,19 @@ *.gem +/.bundle/ +/Gemfile.lock +/coverage/ +/pkg/ +/tmp/ +/spec/tmp/ +/spec/smoke/*.pdf +/ext/libBeresta/build/ +/ext/libBeresta/install/ +/ext/libBeresta/lib/ +/build/ +*.dylib +*.so +*.bundle +*.rbc +.DS_Store +*.gem +.rspec_status diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..7a2cc1a --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--require spec_helper +--format documentation +--color diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..13b52b7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog + +## [Unreleased] + +## [0.1.0] - TBD (pending libBeresta 1.0.0 release) + +Initial experimental release. + +### Added +- Low-level FFI bindings auto-generated from libBeresta's canonical + S-expression definitions (`gen/data/*.lsp`). +- S-expression parser and Ruby FFI renderer in `generator/`. +- Smoke test that generates a PDF on macOS. +- mandatory baseline: README.md + CMakeLists.txt at repository root + (per libBeresta org-wide `brst-binding-` family convention). + +### Known limitations +- macOS only. Linux support planned for the next release. +- Low-level surface only. An idiomatic high-level API is planned as a + separate gem. + +[0.1.0]: https://github.com/libBeresta/brst-binding-ruby/releases/tag/v0.1.0 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a753d7c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,95 @@ +# brst-binding-ruby — mandatory baseline build entry point +# +# This CMakeLists.txt fulfils the libBeresta org-wide baseline for +# `brst-binding-` repositories (README + CMakeLists.txt). It exists to +# build the libBeresta shared library so that the Ruby FFI bindings can load +# it at runtime. +# +# Two modes are supported: +# +# 1. Vendored source mode (preferred for `gem install`): +# Drop libBeresta source into ext/libBeresta/ (e.g. via git submodule or +# tarball) and build from this directory: +# cmake -S . -B build +# cmake --build build +# +# 2. External source mode (development convenience): +# Pass -DLIBBRST_SOURCE_DIR=/path/to/libBeresta clone: +# cmake -S . -B build -DLIBBRST_SOURCE_DIR=$HOME/src/libBeresta +# cmake --build build +# +# The resulting shared library (libbrst.dylib / libbrst.so) is copied into +# ext/libBeresta/lib/ where the Ruby loader looks for it. + +cmake_minimum_required(VERSION 3.16) +project(brst_binding_ruby NONE) + +set(_default_libbrst_src "${CMAKE_CURRENT_LIST_DIR}/ext/libBeresta") +set(LIBBRST_SOURCE_DIR "${_default_libbrst_src}" CACHE PATH + "Path to libBeresta source tree to build (defaults to ext/libBeresta)") + +if(NOT EXISTS "${LIBBRST_SOURCE_DIR}/CMakeLists.txt") + message(WARNING + "libBeresta source not found at ${LIBBRST_SOURCE_DIR}.\n" + "Either:\n" + " - Place libBeresta source in ext/libBeresta/ (e.g. git submodule), or\n" + " - Pass -DLIBBRST_SOURCE_DIR=/path/to/libBeresta\n" + "Skipping libBeresta build target.") + return() +endif() + +enable_language(C) + +set(LIBBRST_SHARED_LIB ON CACHE BOOL "" FORCE) +set(LIBBRST_EXAMPLES OFF CACHE BOOL "" FORCE) +set(LIBBRST_TESTS OFF CACHE BOOL "" FORCE) + +add_subdirectory("${LIBBRST_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/libBeresta-build") + +set(_outdir "${CMAKE_CURRENT_LIST_DIR}/ext/libBeresta/lib") +file(MAKE_DIRECTORY "${_outdir}") + +add_custom_target(brst_binding_ruby_stage ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + "${_outdir}/libbrst${CMAKE_SHARED_LIBRARY_SUFFIX}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + "${_outdir}/$" + DEPENDS brst + COMMENT "Staging libbrst shared library into ext/libBeresta/lib/") + +# --------------------------------------------------------------------------- +# Mandatory libBeresta org-wide CMake targets +# +# Per dmitrys99's guidance (libBeresta/libBeresta#19), every +# brst-binding- repository exposes three standard targets so that +# cross-language CI/CD pipelines can drive each binding uniformly: +# +# - binding: regenerate the FFI bindings from libBeresta/gen/data/*.lsp +# - check: run the binding's test suite +# - bundle: produce the language-native distribution archive +# +# For Ruby these shell out to ruby / bundle / gem respectively. +# --------------------------------------------------------------------------- + +set(_gen_data_dir "${LIBBRST_SOURCE_DIR}/gen/data") +set(_binding_out_dir "${CMAKE_CURRENT_LIST_DIR}/lib/brst/binding/ruby") + +add_custom_target(binding + COMMAND ruby + "${CMAKE_CURRENT_LIST_DIR}/generator/bin/brst-binding-ruby-gen" + --data-dir "${_gen_data_dir}" + --out-dir "${_binding_out_dir}" + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + COMMENT "Regenerating FFI bindings from ${_gen_data_dir}") + +add_custom_target(check + COMMAND bundle exec rspec + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + COMMENT "Running rspec to verify the bindings") + +add_custom_target(bundle + COMMAND gem build brst-binding-ruby.gemspec + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + COMMENT "Building brst-binding-ruby .gem archive") diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..b4e2a20 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gemspec diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..048a3fc --- /dev/null +++ b/LICENSE @@ -0,0 +1,31 @@ +brst-binding-ruby — Ruby FFI bindings for libBeresta + +Copyright (c) 2026 Kenta Ishizaki and contributors + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. + +---------------------------------------------------------------------- + +This gem provides bindings to libBeresta (https://github.com/libBeresta/libBeresta), +which is itself distributed under the zlib/libpng license. libBeresta is +originally a fork of libHaru (https://github.com/libharu/libharu), also under +the zlib/libpng license. Original libHaru copyright belongs to Takeshi Kanno +and contributors; libBeresta copyright belongs to Dmitry Solomennikov and +contributors. Bindings here are generated from libBeresta's canonical +S-expression definitions (gen/data/*.lsp). diff --git a/README.md b/README.md new file mode 100644 index 0000000..21b200d --- /dev/null +++ b/README.md @@ -0,0 +1,139 @@ +# brst-binding-ruby + +[![CI](https://github.com/libBeresta/brst-binding-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/libBeresta/brst-binding-ruby/actions/workflows/ci.yml) + +**Experimental, low-level Ruby FFI bindings for [libBeresta][libBeresta]**, a +free, cross-platform PDF generation C library forked from [libHaru][libHaru]. + +This is the Ruby member of the libBeresta org's `brst-binding-` family of +language bindings. Bindings are auto-generated from libBeresta's canonical +S-expression definitions in [`gen/data/*.lsp`][gen-data], so they stay faithful +to the upstream API. + +## Status: v0.1.0 — experimental + +- Auto-generated low-level FFI surface from `gen/data/*.lsp`. +- macOS-only at this version. Linux support is planned for the next release. +- An idiomatic, higher-level Ruby API is **not** part of this gem; that is + planned as a separate gem on top of these low-level bindings. +- Released in lockstep with libBeresta 1.0.0. + +## Mandatory baseline + +Per the libBeresta org-wide convention for `brst-binding-` repositories, +this repository ships: + +- `README.md` (this file) +- `CMakeLists.txt` — entry point that builds libBeresta (vendored or external) + into a shared library that the Ruby loader can `dlopen`. + +Everything else (gemspec, `lib/`, `spec/`, generator, CI) follows Ruby +community conventions on top of that baseline. + +## Quick start + +### Install (development checkout) + +This v0.1.0 is not yet on rubygems.org. To try it from a checkout: + +```sh +git clone https://github.com/libBeresta/brst-binding-ruby.git +cd brst-binding-ruby +git clone --depth=1 https://github.com/libBeresta/libBeresta.git ../libBeresta +brew install cmake libpng # macOS native deps +bundle install +cmake -S . -B build -DLIBBRST_SOURCE_DIR=$(cd ../libBeresta && pwd) \ + -DCMAKE_BUILD_TYPE=Release +cmake --build build --config Release -j +bundle exec rspec +``` + +### Hello PDF in Ruby + +```ruby +require "brst/binding/ruby" + +include Brst::Binding::Ruby + +pdf = Base.BRST_Doc_New(nil, nil) +page = DocPage.BRST_Doc_Page_Add(pdf) +PageRoutines.BRST_Page_SetSize(page, :A4, :PAGE_ORIENTATION_PORTRAIT) + +font = DocFont.BRST_Doc_Font(pdf, "Helvetica", nil) +Text.BRST_Page_BeginText(page) +Text.BRST_Page_SetFontAndSize(page, font, 20.0) +Text.BRST_Page_MoveTextPos(page, 50.0, 750.0) +Text.BRST_Page_ShowText(page, "Hello, Beresta from Ruby!") +Text.BRST_Page_EndText(page) + +DocSave.BRST_Doc_SaveToFile(pdf, "hello.pdf") +Base.BRST_Doc_Free(pdf) +``` + +## How it's built + +``` +libBeresta/gen/data/*.lsp (S-expression — Source of Truth) + │ + ▼ +generator/bin/brst-binding-ruby-gen (Ruby S-exp parser + FFI renderer) + │ + ▼ +lib/brst/binding/ruby/types.rb (consolidated typedefs / enums / structs) +lib/brst/binding/ruby/.rb (one FFI module per .lsp file) + │ + ▼ +ext/libBeresta/lib/libbrst.dylib (cmake-built native library) +``` + +The generator parses S-expressions directly. The `gen/json/*.json` files are +themselves auto-generated from the same `.lsp` files and are useful for +structural cross-checking but are **not** the source of truth. + +To regenerate after pulling new `.lsp` data: + +```sh +bundle exec rake generate +# or: +ruby generator/bin/brst-binding-ruby-gen \ + --data-dir ../libBeresta/gen/data \ + --out-dir lib/brst/binding/ruby +``` + +CI guards against generator drift: the workflow regenerates on every push and +fails if the committed bindings differ from the generator's output. + +## Library resolution + +At load time, `Brst::Binding::Ruby::Library` searches in this order: + +1. `ENV["BRST_BINDING_RUBY_LIB"]` — explicit override (path or library name). +2. `ext/libBeresta/lib/libbrst.{dylib,so}` — vendored build output. +3. `ext/libBeresta/build/src/libbrst.{dylib,so}` — in-tree cmake build output. +4. `build/libBeresta-build/src/libbrst.{dylib,so}` — alternative in-tree. +5. Falls back to `libbrst` / `brst` via the system loader. + +If a function or type referenced by upstream `.lsp` data is absent from the +loaded native library (e.g. caption / C-symbol drift, or a feature compiled +out of this build), the corresponding `attach_function` is recorded in +`::MISSING_SYMBOLS` and the rest of the gem still loads. + +## Acknowledgements + +- [@dmitrys99][dmitrys99] — libBeresta maintainer, designer of the S-expression + source-of-truth pipeline, and gracious mentor for this binding effort. The + `brst-binding-` org structure and the `README + CMakeLists.txt` + baseline come from his guidance. +- [libHaru][libHaru] — original PDF C library this work ultimately descends + from. Original copyright belongs to Takeshi Kanno and contributors. +- Russian-language docs in the upstream `.lsp` data are preserved verbatim in + the parsed tree but not surfaced in v0.1.0 bindings. + +## License + +[zlib/libpng License](LICENSE) — same as libBeresta and libHaru. + +[libBeresta]: https://github.com/libBeresta/libBeresta +[libHaru]: https://github.com/libharu/libharu +[gen-data]: https://github.com/libBeresta/libBeresta/tree/master/gen/data +[dmitrys99]: https://github.com/dmitrys99 diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..8c4dd02 --- /dev/null +++ b/Rakefile @@ -0,0 +1,19 @@ +require "bundler/gem_tasks" + +begin + require "rspec/core/rake_task" + RSpec::Core::RakeTask.new(:spec) +rescue LoadError + # rspec is a dev dependency; fine if absent in production +end + +desc "Regenerate FFI bindings from libBeresta gen/data/*.lsp" +task :generate, [:gen_data_dir] do |_, args| + data_dir = args[:gen_data_dir] || ENV["BRST_GEN_DATA_DIR"] || + File.expand_path("../libBeresta/gen/data", __dir__) + ruby "-Igenerator/lib", "generator/bin/brst-binding-ruby-gen", + "--data-dir", data_dir, + "--out-dir", "lib/brst/binding/ruby" +end + +task default: :spec diff --git a/brst-binding-ruby.gemspec b/brst-binding-ruby.gemspec new file mode 100644 index 0000000..7ed6b40 --- /dev/null +++ b/brst-binding-ruby.gemspec @@ -0,0 +1,43 @@ +require_relative "lib/brst/binding/ruby/version" + +Gem::Specification.new do |spec| + spec.name = "brst-binding-ruby" + spec.version = Brst::Binding::Ruby::VERSION + spec.authors = ["Kenta Ishizaki"] + spec.email = ["kentaishizaki@55728.jp"] + + spec.summary = "Low-level Ruby FFI bindings for libBeresta (PDF generation)" + spec.description = <<~DESC + Experimental Ruby FFI bindings for libBeresta, a free, cross-platform PDF + generation C library forked from libHaru. Bindings are auto-generated from + libBeresta's canonical S-expression definitions (gen/data/*.lsp). v0.1.0 + exposes a faithful low-level surface; an idiomatic high-level API is planned + as a separate gem. Currently tested on macOS only; Linux support is planned + for the next release. Part of the libBeresta org's brst-binding- family. + DESC + + spec.homepage = "https://github.com/libBeresta/brst-binding-ruby" + spec.license = "Zlib" + spec.required_ruby_version = ">= 3.1.0" + + spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues" + spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md" + spec.metadata["rubygems_mfa_required"] = "true" + + spec.files = Dir[ + "lib/**/*.rb", + "ext/extconf.rb", + "CMakeLists.txt", + "README.md", + "LICENSE", + "CHANGELOG.md" + ] + spec.require_paths = ["lib"] + spec.extensions = ["ext/extconf.rb"] + + spec.add_dependency "ffi", "~> 1.16" + + spec.add_development_dependency "rspec", "~> 3.13" + spec.add_development_dependency "rake", "~> 13.2" +end diff --git a/ext/extconf.rb b/ext/extconf.rb new file mode 100644 index 0000000..141c848 --- /dev/null +++ b/ext/extconf.rb @@ -0,0 +1,59 @@ +require "mkmf" +require "fileutils" + +# brst-binding-ruby ext/extconf.rb +# +# This file is **not** a traditional C extension build script. brst-binding-ruby +# is a pure-Ruby FFI gem; the native dependency is libBeresta, an external +# shared library. We declare an extension only so that `gem install` runs this +# file, giving us a hook to either: +# +# - Build libBeresta from a vendored source tree (ext/libBeresta/), or +# - Skip the build and rely on a system-installed libbrst. +# +# A no-op Makefile is always emitted so RubyGems considers the build successful. + +ROOT = File.expand_path("..", __dir__) +EXT_DIR = File.join(ROOT, "ext", "libBeresta") +SRC_CMAKE = File.join(EXT_DIR, "CMakeLists.txt") +LIB_OUT = File.join(EXT_DIR, "lib") + +def have_cmake? + system("cmake --version > /dev/null 2>&1") +end + +def build_libbrst + build_dir = File.join(EXT_DIR, "build") + FileUtils.mkdir_p(build_dir) + FileUtils.mkdir_p(LIB_OUT) + + Dir.chdir(ROOT) do + sh = ->(*cmd) { system(*cmd) || abort("[brst-binding-ruby] command failed: #{cmd.join(' ')}") } + sh.call("cmake", "-S", ".", "-B", "build", + "-DCMAKE_BUILD_TYPE=Release", + "-DLIBBRST_SOURCE_DIR=#{EXT_DIR}") + sh.call("cmake", "--build", "build", "--config", "Release") + end +end + +if File.exist?(SRC_CMAKE) + if have_cmake? + build_libbrst + else + warn "[brst-binding-ruby] cmake not found; skipping libBeresta build. " \ + "Install cmake or set BRST_BINDING_RUBY_LIB to an existing libbrst path." + end +else + warn "[brst-binding-ruby] ext/libBeresta source not vendored; skipping build. " \ + "Set BRST_BINDING_RUBY_LIB to an existing libbrst, or vendor the source." +end + +# Always emit a stub Makefile so `gem install` succeeds. +File.write(File.join(__dir__, "Makefile"), <<~MAKE) + all: + \t@true + install: + \t@true + clean: + \t@true +MAKE diff --git a/ext/libBeresta/.gitkeep b/ext/libBeresta/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/generator/bin/brst-binding-ruby-gen b/generator/bin/brst-binding-ruby-gen new file mode 100755 index 0000000..d39fc80 --- /dev/null +++ b/generator/bin/brst-binding-ruby-gen @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "optparse" +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) +require "brst_binding_ruby_gen" + +options = { lang: "en" } +OptionParser.new do |op| + op.banner = "Usage: brst-binding-ruby-gen --data-dir DIR --out-dir DIR [--lang en|ru]" + op.on("--data-dir DIR", "Path to libBeresta gen/data directory") { |v| options[:data_dir] = v } + op.on("--out-dir DIR", "Output directory for generated bindings") { |v| options[:out_dir] = v } + op.on("--lang LANG", "Doc language (en|ru), default en") { |v| options[:lang] = v } +end.parse! + +abort "missing --data-dir" unless options[:data_dir] +abort "missing --out-dir" unless options[:out_dir] + +count = BrstBindingRubyGen.run( + data_dir: options[:data_dir], + out_dir: options[:out_dir], + lang: options[:lang] +) +puts "[brst-binding-ruby-gen] processed #{count} .lsp files -> #{options[:out_dir]}" diff --git a/generator/lib/brst_binding_ruby_gen.rb b/generator/lib/brst_binding_ruby_gen.rb new file mode 100644 index 0000000..95248e8 --- /dev/null +++ b/generator/lib/brst_binding_ruby_gen.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "fileutils" +require_relative "brst_binding_ruby_gen/sexp_parser" +require_relative "brst_binding_ruby_gen/symbol_table" +require_relative "brst_binding_ruby_gen/renderer" + +# Top-level orchestrator for the brst-binding-ruby code generator. +# +# Pipeline: +# gen/data/*.lsp --SexpParser--> Ruby Hash/Array tree +# --SymbolTable--> consolidated type vocabulary +# --Renderer--> types.rb + per-file FFI modules +# +# `types.rb` is emitted from the union of every file's type declarations +# (`:types`, `:pointers`, `:definitions`, `:enums`, `:structs`) so that the +# per-file modules need not depend on each other at load time. +module BrstBindingRubyGen + module_function + + def run(data_dir:, out_dir:, lang: "en") + data_dir = File.expand_path(data_dir) + out_dir = File.expand_path(out_dir) + raise ArgumentError, "data dir does not exist: #{data_dir}" unless Dir.exist?(data_dir) + + FileUtils.mkdir_p(out_dir) + + lsp_files = Dir.glob(File.join(data_dir, "*.lsp")).sort + raise "no .lsp files found in #{data_dir}" if lsp_files.empty? + + parsed = lsp_files.map do |path| + tree = SexpParser.parse_file(path) + [path, tree] + end + + symbols = SymbolTable.from(parsed) + + # Emit consolidated types.rb first. + File.write(File.join(out_dir, "types.rb"), + Renderer.render_types(symbols, lang: lang)) + + parsed.each do |path, tree| + module_name = Renderer.module_name_from_filename(path) + next if module_name.nil? + + body = Renderer.render_file(tree, symbols, lang: lang) + next if body.nil? # nothing renderable in this file + + out_path = File.join(out_dir, "#{Renderer.snake_case(module_name)}.rb") + File.write(out_path, body) + end + + parsed.size + end +end diff --git a/generator/lib/brst_binding_ruby_gen/renderer.rb b/generator/lib/brst_binding_ruby_gen/renderer.rb new file mode 100644 index 0000000..e2bd4e8 --- /dev/null +++ b/generator/lib/brst_binding_ruby_gen/renderer.rb @@ -0,0 +1,284 @@ +# frozen_string_literal: true + +module BrstBindingRubyGen + # Emits Ruby source for the consolidated `types.rb` and per-file FFI modules. + # + # Generated layout: + # lib/brst/binding/ruby/types.rb (all typedefs, enums, structs, consts) + # lib/brst/binding/ruby/.rb (functions for that .lsp file, + # plus a Sizes table for page_sizes.lsp) + # + # The four design improvements (per danbako 366): + # #1 Consolidated `:types` renderer (typedef'd from inner→outer mapping). + # #2 Enums emitted as FFI enums (effectively `:int`-backed typedefs). + # #3 Structs registered with `Struct.by_value` aliases for value semantics. + # #4 Every typedef lives in `types.rb`, so per-file modules have no + # load-order dependency on each other. + module Renderer + BANNER = <<~RB + # frozen_string_literal: true + # + # AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). + # Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). + # DO NOT EDIT BY HAND. Re-generate with `rake generate`. + RB + + module_function + + def module_name_from_filename(path) + base = File.basename(path, ".lsp") + camelize(base) + end + + def camelize(s) + s.to_s.split(/[_\-]/).map { |p| p[0]&.upcase.to_s + p[1..].to_s }.join + end + + def snake_case(s) + s.to_s + .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') + .gsub(/([a-z\d])([A-Z])/, '\1_\2') + .downcase + end + + # ---- types.rb ----------------------------------------------------------- + + def render_types(symbols, lang: "en") + out = +BANNER.dup + out << <<~RB + + require "ffi" + require_relative "library" + + module Brst + module Binding + module Ruby + # Centralised type vocabulary for every generated FFI module. + # + # `Types.apply(mod)` registers every typedef, enum, and struct + # alias on `mod` (which must already `extend FFI::Library`). + # See generator/lib/brst_binding_ruby_gen/renderer.rb. + module Types + module_function + + # Each generated `.rb` calls `Types.apply(self)` so that + # all type symbols (`:Doc`, `:STATUS`, `:GMode`, ...) resolve + # uniformly regardless of which .lsp file they originated in. + def apply(mod) + return if mod.instance_variable_get(:@brst_types_applied) + mod.instance_variable_set(:@brst_types_applied, true) + apply_scalars(mod) + apply_pointers(mod) + apply_enums(mod) + apply_structs(mod) + apply_definitions(mod) + end + + # ---- scalars (from types.lsp :types) ---- + def apply_scalars(mod) + RB + + symbols.inner_to_ffi.each do |inner, ffi| + next if inner == "void" + next if inner.include?("*") # pointer-suffix variants are pointers + out << " mod.typedef #{ffi.inspect}, :#{ruby_type_sym(inner)}\n" + end + + out << <<~RB + end + + # ---- opaque pointers ---- + def apply_pointers(mod) + RB + symbols.pointers.each_key do |n| + out << " mod.typedef :pointer, :#{ruby_type_sym(n)}\n" + end + + out << <<~RB + end + + # ---- enums (improvement #2: each enum acts as an :int-backed typedef) ---- + def apply_enums(mod) + RB + symbols.enums.each_value do |enum_def| + elements_src = enum_def[:elements].each_with_index.flat_map do |el, _i| + v = el[:value] + sym = symbol_literal(el[:element]) + if v.is_a?(Integer) + [sym, v.to_s] + else + [sym] + end + end.join(", ") + out << " mod.enum #{symbol_literal(enum_def[:name])}, [#{elements_src}]\n" + end + + out << <<~RB + end + + # ---- structs (improvement #3: by_value alias) ---- + def apply_structs(mod) + RB + symbols.structs.each_value do |s| + klass = struct_class_name(s[:name]) + out << " unless mod.const_defined?(:#{klass}, false)\n" + out << " klass = Class.new(FFI::Struct) do\n" + layout_pairs = s[:fields].map do |f| + ":#{f[:field]}, #{symbols.resolve(f[:type]).inspect}" + end + out << " layout #{layout_pairs.join(",\n ")}\n" + out << " end\n" + out << " mod.const_set(:#{klass}, klass)\n" + out << " end\n" + out << " mod.typedef mod.const_get(:#{klass}).by_value, :#{ruby_type_sym(s[:name])}\n" + end + + out << <<~RB + end + + # ---- definitions (typedef aliases) ---- + def apply_definitions(mod) + RB + symbols.definitions.each do |name, d| + out << " mod.typedef :#{ruby_type_sym(d[:original])}, :#{ruby_type_sym(name)}\n" + end + + out << <<~RB + end + end + end + end + end + RB + + # Constants from consts.lsp — emitted as Ruby module constants under + # Brst::Binding::Ruby::Const::BRST_, mirroring libBeresta's BRST_ + # prefix convention. + out << "\nmodule Brst\n module Binding\n module Ruby\n module Const\n" + symbols.consts.each_value do |c| + next if c[:value].nil? + literal = const_literal(c[:value]) + out << " BRST_#{c[:name]} = #{literal}\n" + end + out << " end\n end\n end\nend\n" + + # Page sizes from page_sizes.lsp — emitted as a frozen Hash so callers + # can do width/height lookup without touching FFI. + if !symbols.sizes.empty? + out << "\nmodule Brst\n module Binding\n module Ruby\n module PageSizesMM\n" + out << " TABLE = {\n" + symbols.sizes.each do |s| + out << " #{s[:id].inspect} => { caption: #{s[:caption].inspect}, " \ + "origin: #{s[:origin].inspect}, width_mm: #{s[:width]}, height_mm: #{s[:height]} },\n" + end + out << " }.freeze\n" + out << " end\n end\n end\nend\n" + end + + out + end + + # ---- per-file modules --------------------------------------------------- + + def render_file(tree, symbols, lang: "en") + file_name = tree[:file].to_s + module_name = camelize(file_name.empty? ? "unknown" : file_name) + + functions = Array(tree[:functions]) + # Skip files that have only type declarations (already covered in types.rb) + return nil if functions.empty? && Array(tree[:sizes]).empty? + + out = +BANNER.dup + out << <<~RB + + require "ffi" + require_relative "library" + require_relative "types" + + module Brst + module Binding + module Ruby + module #{module_name} + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + RB + + functions.each do |fn| + next unless fn.is_a?(Hash) + next if fn[:caption].nil? + caption = fn[:caption].to_s + param_types = Array(fn[:params]).map do |p| + symbols.resolve(p[:type]).inspect + end + return_type = symbols.resolve(fn.dig(:result, :type)).inspect + + out << " safe_attach :BRST_#{caption}, [#{param_types.join(', ')}], #{return_type}\n" + end + + out << " end\n end\n end\nend\n" + out + end + + # ---- helpers ------------------------------------------------------------ + + def ruby_type_sym(name) + name.to_s.tr("-", "_").gsub(/[^A-Za-z0-9_]/, "_") + end + + # Return a Ruby source literal for a Symbol whose string contents may not + # be a bare-identifier (e.g. starts with a digit, like "4A0"). Falls back + # to the quoted-symbol form when needed. + def symbol_literal(name) + s = ruby_type_sym(name) + if s =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/ + ":#{s}" + else + ":\"#{s}\"" + end + end + + def struct_class_name(name) + camelize(name.to_s.tr("-", "_")) + "Struct" + end + + def const_literal(v) + case v + when Integer + v.to_s + when Float + v.to_s + when String + s = v.strip + if s =~ /\A-?0x[0-9A-Fa-f]+\z/ + s + elsif s =~ /\A-?\d+\z/ + s + elsif s =~ /\A-?\d+\.\d+(?:[eE][+-]?\d+)?\z/ + s + else + s.inspect + end + else + v.inspect + end + end + end +end diff --git a/generator/lib/brst_binding_ruby_gen/sexp_parser.rb b/generator/lib/brst_binding_ruby_gen/sexp_parser.rb new file mode 100644 index 0000000..d102bf4 --- /dev/null +++ b/generator/lib/brst_binding_ruby_gen/sexp_parser.rb @@ -0,0 +1,172 @@ +# frozen_string_literal: true + +require "strscan" + +module BrstBindingRubyGen + # Minimal Common-Lisp-flavoured S-expression parser tuned for libBeresta's + # gen/data/*.lsp files. Recognises: + # - lists `( ... )` + # - strings `"..."` with `\"` `\\` `\n` escapes (and tolerates raw newlines) + # - `:keyword` symbols + # - integers (`0x00`, `123`), floats (`3.14`) + # - bare identifiers (with `-`, `_`, `*`, alpha-num) + # - `;` line comments + # + # When a list looks like a property list `(:k1 v1 :k2 v2 ...)` it is converted + # into a Ruby Hash keyed by Symbol. Otherwise it stays an Array. + module SexpParser + module_function + + Sym = Struct.new(:name) do + def to_s + name + end + + def inspect + ":#{name}" + end + end + + Bare = Struct.new(:name) do + def to_s + name + end + + def inspect + name + end + end + + def parse_file(path) + parse(File.read(path, encoding: "UTF-8")) + end + + def parse(source) + sc = StringScanner.new(source) + result = read_form(sc) + skip_ws_and_comments(sc) + # Be lenient about a stray trailing `)` (encrypt.lsp ships with one + # extra close paren upstream). Warn but don't fail the whole pipeline. + while sc.peek(1) == ")" + warn "[brst-binding-ruby-gen] ignoring stray ')' at byte #{sc.pos}" + sc.getch + skip_ws_and_comments(sc) + end + raise "trailing content at offset #{sc.pos}" unless sc.eos? + plist_to_hash(result) + end + + def read_form(sc) + skip_ws_and_comments(sc) + raise "unexpected EOF" if sc.eos? + + case sc.peek(1) + when "(" + sc.getch + read_list(sc) + when ")" + raise "unexpected ')' at #{sc.pos}" + when '"' + read_string(sc) + when ":" + read_keyword(sc) + else + read_atom(sc) + end + end + + def read_list(sc) + items = [] + loop do + skip_ws_and_comments(sc) + raise "unterminated list" if sc.eos? + if sc.peek(1) == ")" + sc.getch + return items + end + items << read_form(sc) + end + end + + def read_string(sc) + sc.getch # consume opening quote + buf = +"" + loop do + raise "unterminated string at #{sc.pos}" if sc.eos? + ch = sc.getch + if ch == '"' + return buf + elsif ch == "\\" + esc = sc.getch + buf << case esc + when "n" then "\n" + when "t" then "\t" + when "r" then "\r" + when '"' then '"' + when "\\" then "\\" + when "c" then "\\c" # Doxygen \c — keep verbatim + else "\\#{esc}" + end + else + buf << ch + end + end + end + + # Permissive keyword: anything after `:` until whitespace / paren / quote / + # comment. Some libBeresta .lsp files mistakenly use Cyrillic letters in + # keyword names (e.g. `:ру` in doc_font.lsp instead of `:ru`); we don't + # want to crash on those — we just expose them as-is. + KEYWORD_RE = /:[^\s()";]+/.freeze + ATOM_RE = /[^\s()";]+/.freeze + + def read_keyword(sc) + tok = sc.scan(KEYWORD_RE) or raise "bad keyword at #{sc.pos}" + Sym.new(tok[1..]) + end + + def read_atom(sc) + tok = sc.scan(ATOM_RE) or raise "bad atom at #{sc.pos}: #{sc.peek(20).inspect}" + classify_atom(tok) + end + + def classify_atom(tok) + case tok + when /\A-?0x[0-9A-Fa-f]+\z/ then Integer(tok, 16) + when /\A-?\d+\z/ then tok.to_i + when /\A-?\d+\.\d+(?:[eE][+-]?\d+)?\z/ then tok.to_f + when "T", "t" then true + when "NIL", "nil" then nil + else Bare.new(tok) + end + end + + def skip_ws_and_comments(sc) + loop do + sc.skip(/\s+/) + if sc.peek(1) == ";" + sc.skip(/[^\n]*/) + else + break + end + end + end + + # If `arr` is a property list `(:k v :k v ...)` (even-length, every other + # element is a Sym), convert to Hash. Otherwise recurse and return Array. + def plist_to_hash(arr) + return arr unless arr.is_a?(Array) + + converted = arr.map { |e| plist_to_hash(e) } + + if converted.length.even? && converted.length.positive? && + converted.each_slice(2).all? { |k, _| k.is_a?(Sym) } + h = {} + converted.each_slice(2) { |k, v| h[k.name.to_sym] = v } + h + else + converted + end + end + end +end diff --git a/generator/lib/brst_binding_ruby_gen/symbol_table.rb b/generator/lib/brst_binding_ruby_gen/symbol_table.rb new file mode 100644 index 0000000..fcc71e0 --- /dev/null +++ b/generator/lib/brst_binding_ruby_gen/symbol_table.rb @@ -0,0 +1,239 @@ +# frozen_string_literal: true + +module BrstBindingRubyGen + # Aggregates all type vocabulary from every parsed .lsp file: + # - inner→outer scalar mappings from types.lsp + # - opaque pointers (`:pointers`) + # - aliases (`:definitions`) + # - enums (`:enums`) + # - structs (`:structs`) + # - hex/decimal constants (`:consts`) + # - page-size table (`:sizes` from page_sizes.lsp) + # + # Used both by the renderer (to emit types.rb) and to resolve function + # parameter / result types across files. + class SymbolTable + DEFAULT_INNER_MAP = { + "void" => :void + }.freeze + + attr_reader :inner_to_ffi, :pointers, :definitions, :enums, :structs, :consts, :sizes, + :enum_lookup_by_value + + def self.from(parsed_files) + st = new + parsed_files.each { |_path, tree| st.absorb(tree) } + st.finalize! + st + end + + def initialize + @inner_to_ffi = DEFAULT_INNER_MAP.dup + @pointers = {} # name(String) -> {name:} + @definitions = {} # name(String) -> {name:, original:} + @enums = {} # name(String) -> {name:, elements: [{element:, value:}]} + @structs = {} # name(String) -> {name:, fields: [{field:, type:}]} + @consts = {} # name(String) -> {name:, value:, en?, ru?} + @sizes = [] + @enum_lookup_by_value = {} # value(Integer) -> [enum_name, element] + end + + def absorb(tree) + return unless tree.is_a?(Hash) + + absorb_types(tree[:types]) if tree[:types] + absorb_pointers(tree[:pointers]) if tree[:pointers] + absorb_definitions(tree[:definitions]) if tree[:definitions] + absorb_enums(tree[:enums]) if tree[:enums] + absorb_structs(tree[:structs]) if tree[:structs] + absorb_consts(tree[:consts]) if tree[:consts] + absorb_sizes(tree[:sizes]) if tree[:sizes] + end + + # Resolve a libBeresta type name to a Ruby FFI type (Symbol). + # Falls back to `:pointer` for unknown `T*` names. + def resolve(raw) + return :void if raw.nil? + n = raw.to_s.strip + + if (mapped = @inner_to_ffi[n]) + return mapped + end + + # Hyphen↔underscore equivalence for inner mappings. + under = n.tr("-", "_") + hy = n.tr("_", "-") + [under, hy].each do |alt| + return @inner_to_ffi[alt] if @inner_to_ffi.key?(alt) + end + + # Pointer-suffix fallback: `BYTE*`, `Foo*` → :pointer + if n.end_with?("*") + return :pointer + end + + # Anything else: assume a typedef'd FFI symbol matching the name itself. + n.to_sym + end + + # All type names that get emitted as `typedef ..., :Name` in types.rb, + # in dependency order (types.lsp inner names first, then pointers, + # definitions, enums, structs). + def emitted_typedefs + out = [] + @inner_to_ffi.each do |inner, ffi| + next if inner == "void" + out << [inner, :scalar, ffi] + end + @pointers.each_key { |n| out << [n, :pointer, :pointer] } + @definitions.each { |n, d| out << [n, :alias, d[:original]] } + out + end + + def finalize! + # Merge `_`/`-` variants so resolution is symmetric (Doc_New uses + # "Error_Handler" while types.lsp registers "Error-Handler"). + additions = {} + @inner_to_ffi.each do |inner, ffi| + next if inner == "void" + under = inner.tr("-", "_") + additions[under] = ffi unless @inner_to_ffi.key?(under) + hy = inner.tr("_", "-") + additions[hy] = ffi unless @inner_to_ffi.key?(hy) + end + @inner_to_ffi.merge!(additions) + end + + private + + def absorb_types(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + inner = row[:inner].to_s + outer = row[:outer].to_s + @inner_to_ffi[inner] = outer_to_ffi_symbol(outer) + end + end + + def outer_to_ffi_symbol(outer) + case outer + when "string" then :string + when "pointer" then :pointer + when "void" then :void + when /\Aint(8|16|32|64)?\z/, /\Auint(8|16|32|64)?\z/ then outer.to_sym + when "float" then :float + when "double" then :double + when "size_t" then :size_t + when "bool" then :bool + else outer.to_sym + end + end + + def absorb_pointers(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + name = row[:name].to_s + @pointers[name] = { name: name } + end + end + + def absorb_definitions(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + name = row[:name].to_s + original = row[:original].to_s + @definitions[name] = { name: name, original: original } + end + end + + def absorb_enums(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + name = row[:name].to_s + elements = Array(row[:elements]).map do |el| + { + element: el[:element].to_s, + value: parse_numeric(el[:value]), + en: el[:en].to_s, + ru: el[:ru].to_s + } + end + @enums[name] = { name: name, elements: elements, en: row[:en].to_s, ru: row[:ru].to_s } + elements.each do |el| + next if el[:value].nil? + @enum_lookup_by_value[[name, el[:value]]] = el + end + end + end + + def absorb_structs(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + name = row[:name].to_s + fields = Array(row[:fields]).map do |f| + { field: f[:field].to_s, type: f[:type].to_s, en: f[:en].to_s, ru: f[:ru].to_s } + end + @structs[name] = { name: name, fields: fields, en: row[:en].to_s, ru: row[:ru].to_s } + end + end + + def absorb_consts(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + name = row[:name].to_s + @consts[name] = { name: name, value: row[:value], en: row[:en].to_s, ru: row[:ru].to_s } + end + end + + def absorb_sizes(rows) + Array(rows).each do |row| + next unless row.is_a?(Hash) + @sizes << { + caption: row[:caption].to_s, + id: row[:id].to_s, + origin: row[:origin].to_s, + width: row[:width].to_f, + height: row[:height].to_f + } + end + synthesize_page_sizes_enum! + end + + # `PageSizes` is referenced by functions in base.lsp and page_routines.lsp, + # but the .lsp files never declare it as an :enum. Upstream's C header + # `brst_page_sizes.h` auto-numbers every entry from 0 in the same source + # order they appear in page_sizes.lsp, spanning all origins (US Loose, + # US ANSI, US Arch, ISO 216, JIS B, etc.). Synthesise the matching FFI + # enum so callers can pass `:A4` (or `:US_LETTER`, `:US_ARCH_A`, ...) + # instead of a magic integer. + def synthesize_page_sizes_enum! + return if @sizes.empty? + elements = @sizes.each_with_index.map do |s, i| + { element: s[:id], value: i, en: "", ru: "" } + end + elements << { element: "EOF", value: @sizes.size, en: "", ru: "" } + @enums["PageSizes"] = { + name: "PageSizes", + elements: elements, + en: "Page size enum (synthesised from page_sizes.lsp, all origins).", + ru: "" + } + end + + def parse_numeric(v) + return nil if v.nil? + return v if v.is_a?(Numeric) + s = v.to_s.strip + return nil if s.empty? + if s =~ /\A-?0x[0-9A-Fa-f]+\z/ + Integer(s, 16) + elsif s =~ /\A-?\d+\z/ + s.to_i + elsif s =~ /\A-?\d+\.\d+/ + s.to_f + else + s + end + end + end +end diff --git a/lib/brst-binding-ruby.rb b/lib/brst-binding-ruby.rb new file mode 100644 index 0000000..b370ce2 --- /dev/null +++ b/lib/brst-binding-ruby.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Convenience entrypoint that mirrors the gem name (brst-binding-ruby). +# The canonical require path is "brst/binding/ruby". +require "brst/binding/ruby" diff --git a/lib/brst/binding/ruby.rb b/lib/brst/binding/ruby.rb new file mode 100644 index 0000000..5e95dd8 --- /dev/null +++ b/lib/brst/binding/ruby.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require_relative "ruby/version" +require_relative "ruby/library" +require_relative "ruby/types" + +module Brst + module Binding + # Top-level entrypoint for brst-binding-ruby. + # + # Generated FFI modules live under Brst::Binding::Ruby::, e.g. + # Brst::Binding::Ruby::Base.BRST_Doc_New(...) + # Brst::Binding::Ruby::DocSave.BRST_Doc_SaveToFile(pdf, "out.pdf") + # + # The naming follows libBeresta's gen/data/*.lsp file boundaries; this is a + # faithful low-level surface, not an idiomatic Ruby API. A higher-level + # wrapper gem is planned separately. + module Ruby + end + end +end + +# Auto-load every generated FFI module. Order is irrelevant because every type +# (pointer/enum/struct/definition) is centralized in `types.rb`, which has +# already been loaded above. +Dir[File.expand_path("ruby/*.rb", __dir__)].sort.each do |f| + base = File.basename(f, ".rb") + next if %w[version library types].include?(base) + require f +end diff --git a/lib/brst/binding/ruby/asian.rb b/lib/brst/binding/ruby/asian.rb new file mode 100644 index 0000000..bcfc02a --- /dev/null +++ b/lib/brst/binding/ruby/asian.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Asian + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_UseJPFonts, [:Doc], :uint32 + safe_attach :BRST_UseKRFonts, [:Doc], :uint32 + safe_attach :BRST_UseCNSFonts, [:Doc], :uint32 + safe_attach :BRST_UseCNTFonts, [:Doc], :uint32 + safe_attach :BRST_UseJPEncodings, [:Doc], :uint32 + safe_attach :BRST_UseKREncodings, [:Doc], :uint32 + safe_attach :BRST_UseCNSEncodings, [:Doc], :uint32 + safe_attach :BRST_UseCNTEncodings, [:Doc], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/base.rb b/lib/brst/binding/ruby/base.rb new file mode 100644 index 0000000..d376c11 --- /dev/null +++ b/lib/brst/binding/ruby/base.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Base + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_New_Ex, [:pointer, :pointer, :pointer, :uint32, :pointer], :Doc + safe_attach :BRST_Version, [], :string + safe_attach :BRST_Doc_New, [:pointer, :pointer], :Doc + safe_attach :BRST_Doc_New_Empty, [], :Doc + safe_attach :BRST_Doc_Initialize, [:Doc], :uint32 + safe_attach :BRST_Doc_Destroy, [:Doc], :void + safe_attach :BRST_Doc_Initialized, [:Doc], :int32 + safe_attach :BRST_Doc_Destroy_All, [:Doc], :void + safe_attach :BRST_Doc_MMgr, [:Doc], :MMgr + safe_attach :BRST_Doc_Free, [:Doc], :void + safe_attach :BRST_PageSize_Width, [:PageSizes, :PageOrientation], :float + safe_attach :BRST_PageSize_Height, [:PageSizes, :PageOrientation], :float + end + end + end +end diff --git a/lib/brst/binding/ruby/date.rb b/lib/brst/binding/ruby/date.rb new file mode 100644 index 0000000..0298317 --- /dev/null +++ b/lib/brst/binding/ruby/date.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Date + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Date_Now, [:Doc], :Date + safe_attach :BRST_Date_Part, [:Date, :Date_Parts], :int32 + safe_attach :BRST_Date_Validate, [:Date], :uint32 + safe_attach :BRST_Date_Free, [:Date], :void + end + end + end +end diff --git a/lib/brst/binding/ruby/destination.rb b/lib/brst/binding/ruby/destination.rb new file mode 100644 index 0000000..f710cae --- /dev/null +++ b/lib/brst/binding/ruby/destination.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Destination + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Destination_SetXYZ, [:Destination, :float, :float, :float], :uint32 + safe_attach :BRST_Destination_SetFit, [:Destination], :uint32 + safe_attach :BRST_Destination_SetFitH, [:Destination, :float], :uint32 + safe_attach :BRST_Destination_SetFitV, [:Destination, :float], :uint32 + safe_attach :BRST_Destination_SetFitR, [:Destination, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Destination_SetFitB, [:Destination], :uint32 + safe_attach :BRST_Destination_SetFitBH, [:Destination, :float], :uint32 + safe_attach :BRST_Destination_SetFitBV, [:Destination, :float], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_compression.rb b/lib/brst/binding/ruby/doc_compression.rb new file mode 100644 index 0000000..c130212 --- /dev/null +++ b/lib/brst/binding/ruby/doc_compression.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocCompression + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_SetCompressionMode, [:Doc, :CompressionMode], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_embedded_file.rb b/lib/brst/binding/ruby/doc_embedded_file.rb new file mode 100644 index 0000000..a47a1fe --- /dev/null +++ b/lib/brst/binding/ruby/doc_embedded_file.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocEmbeddedFile + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_AttachFile, [:Doc, :string], :EmbeddedFile + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_encoder.rb b/lib/brst/binding/ruby/doc_encoder.rb new file mode 100644 index 0000000..31d7c31 --- /dev/null +++ b/lib/brst/binding/ruby/doc_encoder.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocEncoder + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Encoder_SetCurrent, [:Doc, :string], :uint32 + safe_attach :BRST_Doc_Encoder_Prepare, [:Doc, :string], :Encoder + safe_attach :BRST_Doc_Encoder_Current, [:Doc], :Encoder + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_encoding_utf.rb b/lib/brst/binding/ruby/doc_encoding_utf.rb new file mode 100644 index 0000000..f5f7dd8 --- /dev/null +++ b/lib/brst/binding/ruby/doc_encoding_utf.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocEncodingUtf + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_UseUTFEncodings, [:Doc], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_ext_gstate.rb b/lib/brst/binding/ruby/doc_ext_gstate.rb new file mode 100644 index 0000000..cd5851b --- /dev/null +++ b/lib/brst/binding/ruby/doc_ext_gstate.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocExtGstate + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Create_ExtGState, [:Doc], :ExtGState + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_font.rb b/lib/brst/binding/ruby/doc_font.rb new file mode 100644 index 0000000..9732353 --- /dev/null +++ b/lib/brst/binding/ruby/doc_font.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocFont + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Font, [:Doc, :string, :string], :Font + safe_attach :BRST_Doc_TTFont_LoadFromFile, [:Doc, :string, :int32], :Font + safe_attach :BRST_Doc_Type1Font_LoadFromFile, [:Doc, :string, :string], :string + safe_attach :BRST_Doc_TTFont_LoadFromFile2, [:Doc, :string, :uint32, :int32], :string + safe_attach :BRST_Doc_TTFont_LoadFromMemory, [:Doc, :pointer, :uint32, :int32], :string + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_image_jpeg.rb b/lib/brst/binding/ruby/doc_image_jpeg.rb new file mode 100644 index 0000000..a202c18 --- /dev/null +++ b/lib/brst/binding/ruby/doc_image_jpeg.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocImageJpeg + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Image_Jpeg_LoadFromFile, [:Doc, :string], :Image + safe_attach :BRST_Doc_Image_Jpeg_LoadFromMemory, [:Doc, :pointer, :uint32], :Image + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_image_png.rb b/lib/brst/binding/ruby/doc_image_png.rb new file mode 100644 index 0000000..d0e25ce --- /dev/null +++ b/lib/brst/binding/ruby/doc_image_png.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocImagePng + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Image_Png_LoadFromMemory, [:Doc, :pointer, :uint32], :Image + safe_attach :BRST_Doc_Image_Png_LoadFromFile, [:Doc, :string], :Image + safe_attach :BRST_Doc_Image_Png_LoadFromFile2, [:Doc, :string], :Image + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_image_tiff.rb b/lib/brst/binding/ruby/doc_image_tiff.rb new file mode 100644 index 0000000..56fdde5 --- /dev/null +++ b/lib/brst/binding/ruby/doc_image_tiff.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocImageTiff + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Image_Raw1Bit_LoadFromMemory, [:Doc, :pointer, :uint32, :uint32, :uint32, :int32, :int32], :Image + safe_attach :BRST_Doc_Image_Raw_LoadFromFile, [:Doc, :string, :uint32, :uint32, :ColorSpace], :Image + safe_attach :BRST_Doc_Image_Raw_LoadFromMemory, [:Doc, :pointer, :uint32, :uint32, :ColorSpace, :uint32], :Image + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_info.rb b/lib/brst/binding/ruby/doc_info.rb new file mode 100644 index 0000000..f47e017 --- /dev/null +++ b/lib/brst/binding/ruby/doc_info.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocInfo + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_SetInfoAttr, [:Doc, :InfoType, :string], :uint32 + safe_attach :BRST_Doc_SetInfoDateAttr, [:Doc, :InfoType, :Date], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_matrix.rb b/lib/brst/binding/ruby/doc_matrix.rb new file mode 100644 index 0000000..8570cb5 --- /dev/null +++ b/lib/brst/binding/ruby/doc_matrix.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocMatrix + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Matrix_Identity, [:Doc], :Matrix + safe_attach :BRST_Doc_Matrix_Free, [:Matrix], :void + safe_attach :BRST_Doc_Matrix_Multiply, [:Doc, :Matrix, :Matrix], :Matrix + safe_attach :BRST_Doc_Matrix_Translate, [:Doc, :Matrix, :float, :float], :Matrix + safe_attach :BRST_Doc_Matrix_Scale, [:Doc, :Matrix, :float, :float], :Matrix + safe_attach :BRST_Doc_Matrix_Rotate, [:Doc, :Matrix, :float], :Matrix + safe_attach :BRST_Doc_Matrix_RotateDeg, [:Doc, :Matrix, :float], :Matrix + safe_attach :BRST_Doc_Matrix_Skew, [:Doc, :Matrix, :float, :float], :Matrix + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_output_intent.rb b/lib/brst/binding/ruby/doc_output_intent.rb new file mode 100644 index 0000000..51028f3 --- /dev/null +++ b/lib/brst/binding/ruby/doc_output_intent.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocOutputIntent + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_OutputIntent_New, [:Doc, :string, :string, :string, :string, :Array], :OutputIntent + safe_attach :BRST_Doc_OutputIntent_Add, [:Doc, :OutputIntent], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_page.rb b/lib/brst/binding/ruby/doc_page.rb new file mode 100644 index 0000000..83241c8 --- /dev/null +++ b/lib/brst/binding/ruby/doc_page.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocPage + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Pages_SetConfiguration, [:Doc, :uint32], :uint32 + safe_attach :BRST_Doc_Page_ByIndex, [:Doc, :uint32], :Page + safe_attach :BRST_Doc_Page_Layout, [:Doc], :PageLayout + safe_attach :BRST_Doc_Page_SetLayout, [:Doc, :PageLayout], :uint32 + safe_attach :BRST_Doc_Page_Mode, [:Doc], :PageMode + safe_attach :BRST_Doc_Page_SetMode, [:Doc, :PageMode], :uint32 + safe_attach :BRST_Doc_Page_Current, [:Doc], :Page + safe_attach :BRST_Doc_Page_Add, [:Doc], :Page + safe_attach :BRST_Doc_Page_Insert, [:Doc, :Page], :Page + safe_attach :BRST_Doc_Page_AddLabel, [:Doc, :uint32, :PageNumStyle, :uint32, :string], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_page_pattern.rb b/lib/brst/binding/ruby/doc_page_pattern.rb new file mode 100644 index 0000000..171cb98 --- /dev/null +++ b/lib/brst/binding/ruby/doc_page_pattern.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocPagePattern + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Pattern_Tiling_Create, [:Doc, :float, :float, :float, :float, :float, :float, :Matrix], :Pattern + safe_attach :BRST_Doc_Pattern_Stream, [:Pattern], :Stream + safe_attach :BRST_Doc_Dict_RGBPatternFill_Select, [:Doc, :Dict, :float, :float, :float, :Pattern], :uint32 + safe_attach :BRST_Doc_Dict_RGBPatternFillUint_Select, [:Doc, :Dict, :uint8, :uint8, :uint8, :Pattern], :uint32 + safe_attach :BRST_Doc_Dict_RGBPatternFillHex_Select, [:Doc, :Dict, :uint8, :Pattern], :uint32 + safe_attach :BRST_Doc_Page_RGBPatternFill_Select, [:Doc, :Page, :float, :float, :float, :Pattern], :uint32 + safe_attach :BRST_Doc_Page_RGBPatternFillUint_Select, [:Doc, :Page, :uint8, :uint8, :uint8, :Pattern], :uint32 + safe_attach :BRST_Doc_Page_RGBPatternFillHex_Select, [:Doc, :Page, :uint8, :Pattern], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_pattern.rb b/lib/brst/binding/ruby/doc_pattern.rb new file mode 100644 index 0000000..cba87e1 --- /dev/null +++ b/lib/brst/binding/ruby/doc_pattern.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocPattern + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_Pattern_Tiling_Create, [:Doc, :float, :float, :float, :float, :float, :float, :Matrix], :Pattern + safe_attach :BRST_Doc_Pattern_Stream, [:Pattern], :Stream + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_pdfa.rb b/lib/brst/binding/ruby/doc_pdfa.rb new file mode 100644 index 0000000..8deff6c --- /dev/null +++ b/lib/brst/binding/ruby/doc_pdfa.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocPdfa + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_PDFA_SetConformance, [:Doc, :PDFAType], :uint32 + safe_attach :BRST_Doc_PDFA_AddXmpExtension, [:Doc, :string], :uint32 + safe_attach :BRST_Doc_PDFA_AppendOutputIntents, [:Doc, :string, :Dict], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_save.rb b/lib/brst/binding/ruby/doc_save.rb new file mode 100644 index 0000000..88c978a --- /dev/null +++ b/lib/brst/binding/ruby/doc_save.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocSave + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_SaveToStream, [:Doc], :uint32 + safe_attach :BRST_Doc_SaveToFile, [:Doc, :string], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_security.rb b/lib/brst/binding/ruby/doc_security.rb new file mode 100644 index 0000000..1a89bfe --- /dev/null +++ b/lib/brst/binding/ruby/doc_security.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocSecurity + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_SetPassword, [:Doc, :string, :string], :uint32 + safe_attach :BRST_Doc_SetPermission, [:Doc, :Permission], :uint32 + safe_attach :BRST_Doc_SetEncryptionMode, [:Doc, :EncryptMode, :uint32], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_viewer.rb b/lib/brst/binding/ruby/doc_viewer.rb new file mode 100644 index 0000000..e76deef --- /dev/null +++ b/lib/brst/binding/ruby/doc_viewer.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocViewer + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_SetOpenAction, [:Doc, :Destination], :uint32 + safe_attach :BRST_Doc_ViewerPreference, [:Doc], :ViewerPreference + safe_attach :BRST_Doc_SetViewerPreference, [:Doc, :ViewerPreference], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/doc_xobject.rb b/lib/brst/binding/ruby/doc_xobject.rb new file mode 100644 index 0000000..0ad85da --- /dev/null +++ b/lib/brst/binding/ruby/doc_xobject.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module DocXobject + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Doc_XObject_CreateFromImage, [:Doc, :Rect, :Image, :int32], :XObject + safe_attach :BRST_Doc_XObject_CreateAsWhiteRect, [:Doc, :Rect], :XObject + safe_attach :BRST_Doc_XObject_Create, [:Doc, :float, :float, :float, :float], :XObject + end + end + end +end diff --git a/lib/brst/binding/ruby/error.rb b/lib/brst/binding/ruby/error.rb new file mode 100644 index 0000000..e1c53d3 --- /dev/null +++ b/lib/brst/binding/ruby/error.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Error + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Error_Check, [:Error], :uint32 + safe_attach :BRST_Doc_Error_Code, [:Doc], :uint32 + safe_attach :BRST_Doc_Error_DetailCode, [:Doc], :uint32 + safe_attach :BRST_Doc_Error_Reset, [:Doc], :void + safe_attach :BRST_Doc_Error_SetHandler, [:Doc, :pointer], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/ext_gstate.rb b/lib/brst/binding/ruby/ext_gstate.rb new file mode 100644 index 0000000..1b69bdd --- /dev/null +++ b/lib/brst/binding/ruby/ext_gstate.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module ExtGstate + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_ExtGState_SetAlphaStroke, [:ExtGState, :float], :uint32 + safe_attach :BRST_ExtGState_SetAlphaFill, [:ExtGState, :float], :uint32 + safe_attach :BRST_ExtGState_SetBlendMode, [:ExtGState, :BlendMode], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/font.rb b/lib/brst/binding/ruby/font.rb new file mode 100644 index 0000000..4b04895 --- /dev/null +++ b/lib/brst/binding/ruby/font.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Font + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Font_Descent, [:Font, :float], :float + safe_attach :BRST_Font_TextWidth2, [:Font, :float, :float, :float, :string], :float + end + end + end +end diff --git a/lib/brst/binding/ruby/geometry.rb b/lib/brst/binding/ruby/geometry.rb new file mode 100644 index 0000000..b986447 --- /dev/null +++ b/lib/brst/binding/ruby/geometry.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Geometry + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Page_GSave, [:Page], :uint32 + safe_attach :BRST_Page_GRestore, [:Page], :uint32 + safe_attach :BRST_Page_Concat, [:Page, :float, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_Translate, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_Scale, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_RotateDeg, [:Page, :float], :uint32 + safe_attach :BRST_Page_Rotate, [:Page, :float], :uint32 + safe_attach :BRST_Page_Skew, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_Circle, [:Page, :float, :float, :float], :uint32 + safe_attach :BRST_Page_Ellipse, [:Page, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_Arc, [:Page, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_SetGrayFill, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetGrayStroke, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetRGBFill, [:Page, :float, :float, :float], :uint32 + safe_attach :BRST_Page_SetRGBFillUint, [:Page, :uint8, :uint8, :uint8], :uint32 + safe_attach :BRST_Page_SetRGBFillHex, [:Page, :uint32], :uint32 + safe_attach :BRST_Page_SetRGBStroke, [:Page, :float, :float, :float], :uint32 + safe_attach :BRST_Page_SetRGBStrokeUint, [:Page, :uint8, :uint8, :uint8], :uint32 + safe_attach :BRST_Page_SetRGBStrokeHex, [:Page, :uint32], :uint32 + safe_attach :BRST_Page_SetCMYKFill, [:Page, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_SetCMYKStroke, [:Page, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_Clip, [:Page], :uint32 + safe_attach :BRST_Page_Eoclip, [:Page], :uint32 + safe_attach :BRST_Page_Stroke, [:Page], :uint32 + safe_attach :BRST_Page_ClosePathStroke, [:Page], :uint32 + safe_attach :BRST_Page_Fill, [:Page], :uint32 + safe_attach :BRST_Page_Eofill, [:Page], :uint32 + safe_attach :BRST_Page_FillStroke, [:Page], :uint32 + safe_attach :BRST_Page_EofillStroke, [:Page], :uint32 + safe_attach :BRST_Page_ClosePathFillStroke, [:Page], :uint32 + safe_attach :BRST_Page_ClosePathEofillStroke, [:Page], :uint32 + safe_attach :BRST_Page_EndPath, [:Page], :uint32 + safe_attach :BRST_Page_MoveTo, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_LineTo, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_CurveTo, [:Page, :float, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_CurveTo2, [:Page, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_CurveTo3, [:Page, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_ClosePath, [:Page], :uint32 + safe_attach :BRST_Page_Rectangle, [:Page, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_SetLineWidth, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetLineCap, [:Page, :LineCap], :uint32 + safe_attach :BRST_Page_SetLineJoin, [:Page, :LineJoin], :uint32 + safe_attach :BRST_Page_SetMiterLimit, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetDash, [:Page, :pointer, :uint32, :float], :uint32 + safe_attach :BRST_Page_SetFlat, [:Page, :float], :uint32 + safe_attach :BRST_Page_GrayFill, [:Page], :float + safe_attach :BRST_Page_GrayStroke, [:Page], :float + safe_attach :BRST_Page_StrokeColorSpace, [:Page], :ColorSpace + safe_attach :BRST_Page_FillColorSpace, [:Page], :ColorSpace + safe_attach :BRST_Page_LineWidth, [:Page], :float + safe_attach :BRST_Page_LineCap, [:Page], :LineCap + safe_attach :BRST_Page_LineJoin, [:Page], :LineJoin + safe_attach :BRST_Page_MiterLimit, [:Page], :float + safe_attach :BRST_Page_Flat, [:Page], :float + safe_attach :BRST_Page_Matrix, [:Page], :Matrix + end + end + end +end diff --git a/lib/brst/binding/ruby/library.rb b/lib/brst/binding/ruby/library.rb new file mode 100644 index 0000000..bb3b4e8 --- /dev/null +++ b/lib/brst/binding/ruby/library.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require "ffi" + +module Brst + module Binding + module Ruby + # Locates libBeresta's shared library so generated FFI modules can call + # `ffi_lib Brst::Binding::Ruby::Library.lib_path`. + # + # Resolution order: + # 1. ENV["BRST_BINDING_RUBY_LIB"] — explicit override (any path or name) + # 2. ext/libBeresta/lib/libbrst.{dylib,so} (vendored build output) + # 3. ext/libBeresta/build/src/libbrst.{dylib,so} (in-tree build output) + # 4. "brst" / "libbrst" — let ffi/dlopen search system paths + module Library + module_function + + def lib_path + @lib_path ||= resolve! + end + + def resolve! + if (override = ENV["BRST_BINDING_RUBY_LIB"]) && !override.empty? + return override + end + + candidates = [] + gem_root = File.expand_path("../../../..", __dir__) + + %w[dylib so].each do |ext| + candidates << File.join(gem_root, "ext", "libBeresta", "lib", "libbrst.#{ext}") + candidates << File.join(gem_root, "ext", "libBeresta", "build", "src", "libbrst.#{ext}") + candidates << File.join(gem_root, "build", "libBeresta-build", "src", "libbrst.#{ext}") + end + + found = candidates.find { |p| File.exist?(p) } + return found if found + + # Fall back to library names; FFI will search system paths. + %w[brst libbrst] + end + end + end + end +end diff --git a/lib/brst/binding/ruby/page_routines.rb b/lib/brst/binding/ruby/page_routines.rb new file mode 100644 index 0000000..a29f3d4 --- /dev/null +++ b/lib/brst/binding/ruby/page_routines.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module PageRoutines + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Page_SetWidth, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetHeight, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetBoundary, [:Page, :PageBoundary, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_SetSize, [:Page, :PageSizes, :PageOrientation], :uint32 + safe_attach :BRST_Page_SetRotate, [:Page, :uint16], :uint32 + safe_attach :BRST_Page_SetSlideShow, [:Page, :PageTransition, :float, :float], :uint32 + safe_attach :BRST_Page_SetHorizontalScaling, [:Page, :float], :uint32 + safe_attach :BRST_Page_GStateDepth, [:Page], :uint32 + safe_attach :BRST_Page_HorizontalScaling, [:Page], :float + safe_attach :BRST_Page_SetZoom, [:Page, :float], :uint32 + safe_attach :BRST_Page_Width, [:Page], :float + safe_attach :BRST_Page_Height, [:Page], :float + safe_attach :BRST_Page_GMode, [:Page], :uint16 + safe_attach :BRST_Page_MMgr, [:Page], :MMgr + safe_attach :BRST_Page_Insert_Shared_Content_Stream, [:Page, :Dict], :uint32 + safe_attach :BRST_Page_RawWrite, [:Page, :string], :uint32 + safe_attach :BRST_Page_SetExtGState, [:Page, :ExtGState], :uint32 + safe_attach :BRST_Page_CreateDestination, [:Page], :Destination + end + end + end +end diff --git a/lib/brst/binding/ruby/page_sizes.rb b/lib/brst/binding/ruby/page_sizes.rb new file mode 100644 index 0000000..a65e3ad --- /dev/null +++ b/lib/brst/binding/ruby/page_sizes.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module PageSizes + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + end + end + end +end diff --git a/lib/brst/binding/ruby/page_xobject.rb b/lib/brst/binding/ruby/page_xobject.rb new file mode 100644 index 0000000..ccd5bbe --- /dev/null +++ b/lib/brst/binding/ruby/page_xobject.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module PageXobject + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Page_XObject_Execute, [:Page, :XObject], :uint32 + safe_attach :BRST_Dict_XObject_Execute, [:Dict, :XObject], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/stream_geometry.rb b/lib/brst/binding/ruby/stream_geometry.rb new file mode 100644 index 0000000..d6245b6 --- /dev/null +++ b/lib/brst/binding/ruby/stream_geometry.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module StreamGeometry + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Stream_GSave, [:Stream], :uint32 + safe_attach :BRST_Stream_GRestore, [:Stream], :uint32 + safe_attach :BRST_Stream_Concat, [:Stream, :float, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_Translate, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_Scale, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_RotateDeg, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_Rotate, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_Skew, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_Circle, [:Stream, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_SetGrayFill, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_SetGrayStroke, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_SetRGBFill, [:Stream, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_SetRGBFillUint, [:Stream, :uint8, :uint8, :uint8], :uint32 + safe_attach :BRST_Stream_SetRGBFillHex, [:Stream, :uint32], :uint32 + safe_attach :BRST_Stream_SetRGBStroke, [:Stream, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_SetRGBStrokeUint, [:Stream, :uint8, :uint8, :uint8], :uint32 + safe_attach :BRST_Stream_SetRGBStrokeHex, [:Stream, :uint32], :uint32 + safe_attach :BRST_Stream_SetCMYKFill, [:Stream, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_SetCMYKStroke, [:Stream, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_Clip, [:Stream], :uint32 + safe_attach :BRST_Stream_Eoclip, [:Stream], :uint32 + safe_attach :BRST_Stream_Stroke, [:Stream], :uint32 + safe_attach :BRST_Stream_ClosePathStroke, [:Stream], :uint32 + safe_attach :BRST_Stream_Fill, [:Stream], :uint32 + safe_attach :BRST_Stream_Eofill, [:Stream], :uint32 + safe_attach :BRST_Stream_FillStroke, [:Stream], :uint32 + safe_attach :BRST_Stream_EofillStroke, [:Stream], :uint32 + safe_attach :BRST_Stream_ClosePathFillStroke, [:Stream], :uint32 + safe_attach :BRST_Stream_ClosePathEofillStroke, [:Stream], :uint32 + safe_attach :BRST_Stream_EndPath, [:Stream], :uint32 + safe_attach :BRST_Stream_MoveTo, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_LineTo, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_CurveTo, [:Stream, :float, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_CurveTo2, [:Stream, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_CurveTo3, [:Stream, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_ClosePath, [:Stream], :uint32 + safe_attach :BRST_Stream_Rectangle, [:Stream, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_SetLineWidth, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_SetLineCap, [:Stream, :LineCap], :uint32 + safe_attach :BRST_Stream_SetLineJoin, [:Stream, :LineJoin], :uint32 + safe_attach :BRST_Stream_SetMiterLimit, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_SetDash, [:Stream, :pointer, :uint32, :float], :uint32 + safe_attach :BRST_Stream_SetFlat, [:Stream, :float], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/stream_text.rb b/lib/brst/binding/ruby/stream_text.rb new file mode 100644 index 0000000..8a235d5 --- /dev/null +++ b/lib/brst/binding/ruby/stream_text.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module StreamText + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Stream_BeginText, [:Stream], :uint32 + safe_attach :BRST_Stream_EndText, [:Stream], :uint32 + safe_attach :BRST_Stream_SetTextLeading, [:Stream, :float], :uint32 + safe_attach :BRST_Stream_SetTextRenderingMode, [:Stream, :TextRenderingMode], :uint32 + safe_attach :BRST_Stream_MoveTextPos, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_MoveTextPos2, [:Stream, :float, :float], :uint32 + safe_attach :BRST_Stream_SetTextMatrix, [:Stream, :float, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Stream_ShowText, [:Stream, :Font, :string], :uint32 + safe_attach :BRST_Stream_TextOut, [:Stream, :Font, :float, :float, :string], :uint32 + safe_attach :BRST_Stream_MoveToNextLine, [:Stream], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/text.rb b/lib/brst/binding/ruby/text.rb new file mode 100644 index 0000000..cb0f82d --- /dev/null +++ b/lib/brst/binding/ruby/text.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Text + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_Page_BeginText, [:Page], :uint32 + safe_attach :BRST_Page_EndText, [:Page], :uint32 + safe_attach :BRST_Page_SetTextLeading, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetFontAndSize, [:Page, :Font, :float], :uint32 + safe_attach :BRST_Dict_SetFontAndSize, [:Dict, :Font, :float], :uint32 + safe_attach :BRST_Page_SetTextRenderingMode, [:Page, :TextRenderingMode], :uint32 + safe_attach :BRST_Page_SetTextRise, [:Page, :float], :uint32 + safe_attach :BRST_Page_MoveTextPos, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_MoveTextPos2, [:Page, :float, :float], :uint32 + safe_attach :BRST_Page_SetTextMatrix, [:Page, :float, :float, :float, :float, :float, :float], :uint32 + safe_attach :BRST_Page_MoveToNextLine, [:Page], :uint32 + safe_attach :BRST_Page_ShowText, [:Page, :string], :uint32 + safe_attach :BRST_Page_ShowTextNextLine, [:Page, :string], :uint32 + safe_attach :BRST_Page_ShowTextNextLineEx, [:Page, :float, :float, :string], :uint32 + safe_attach :BRST_Page_TextOut, [:Page, :float, :float, :string], :uint32 + safe_attach :BRST_Page_TextRect, [:Page, :float, :float, :float, :float, :string, :TextAlignment, :pointer], :uint32 + safe_attach :BRST_Page_SetCharSpace, [:Page, :float], :uint32 + safe_attach :BRST_Page_SetWordSpace, [:Page, :float], :uint32 + safe_attach :BRST_Page_TextMatrix, [:Page], :Matrix + safe_attach :BRST_Page_TextLeading, [:Page], :float + safe_attach :BRST_Page_TextRenderingMode, [:Page], :TextRenderingMode + safe_attach :BRST_Page_TextRise, [:Page], :float + safe_attach :BRST_Page_CharSpace, [:Page], :float + safe_attach :BRST_Page_WordSpace, [:Page], :float + safe_attach :BRST_Page_CurrentTextPos2, [:Page, :pointer], :uint32 + safe_attach :BRST_Page_CurrentFont, [:Page], :Font + safe_attach :BRST_Page_CurrentFontSize, [:Page], :float + safe_attach :BRST_Page_TextWidth, [:Page, :string], :float + safe_attach :BRST_Page_MeasureText, [:Page, :string, :float, :int32, :pointer], :uint32 + end + end + end +end diff --git a/lib/brst/binding/ruby/types.rb b/lib/brst/binding/ruby/types.rb new file mode 100644 index 0000000..eeb2514 --- /dev/null +++ b/lib/brst/binding/ruby/types.rb @@ -0,0 +1,618 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" + +module Brst + module Binding + module Ruby + # Centralised type vocabulary for every generated FFI module. + # + # `Types.apply(mod)` registers every typedef, enum, and struct + # alias on `mod` (which must already `extend FFI::Library`). + # See generator/lib/brst_binding_ruby_gen/renderer.rb. + module Types + module_function + + # Each generated `.rb` calls `Types.apply(self)` so that + # all type symbols (`:Doc`, `:STATUS`, `:GMode`, ...) resolve + # uniformly regardless of which .lsp file they originated in. + def apply(mod) + return if mod.instance_variable_get(:@brst_types_applied) + mod.instance_variable_set(:@brst_types_applied, true) + apply_scalars(mod) + apply_pointers(mod) + apply_enums(mod) + apply_structs(mod) + apply_definitions(mod) + end + + # ---- scalars (from types.lsp :types) ---- + def apply_scalars(mod) + mod.typedef :string, :CSTR + mod.typedef :int32, :INT + mod.typedef :uint32, :UINT + mod.typedef :int64, :INT64 + mod.typedef :uint64, :UINT64 + mod.typedef :int32, :INT32 + mod.typedef :uint32, :UINT32 + mod.typedef :int16, :INT16 + mod.typedef :uint16, :UINT16 + mod.typedef :int8, :INT8 + mod.typedef :uint8, :UINT8 + mod.typedef :uint8, :BYTE + mod.typedef :float, :REAL + mod.typedef :double, :DOUBLE + mod.typedef :int32, :BOOL + mod.typedef :uint32, :STATUS + mod.typedef :uint16, :CID + mod.typedef :uint16, :UNICODE + mod.typedef :pointer, :RAW_POINTER + mod.typedef :pointer, :DASH_PATTERN + mod.typedef :pointer, :Error_Handler + mod.typedef :pointer, :Alloc_Func + mod.typedef :pointer, :Free_Func + mod.typedef :pointer, :RAW_POINTER + mod.typedef :pointer, :DASH_PATTERN + mod.typedef :pointer, :Error_Handler + mod.typedef :pointer, :Alloc_Func + mod.typedef :pointer, :Free_Func +end + +# ---- opaque pointers ---- +def apply_pointers(mod) + mod.typedef :pointer, :Array + mod.typedef :pointer, :Date + mod.typedef :pointer, :Dict + mod.typedef :pointer, :Doc + mod.typedef :pointer, :Error + mod.typedef :pointer, :FontDef + mod.typedef :pointer, :Matrix + mod.typedef :pointer, :MMgr + mod.typedef :pointer, :Stream + mod.typedef :pointer, :Xref +end + +# ---- enums (improvement #2: each enum acts as an :int-backed typedef) ---- +def apply_enums(mod) + mod.enum :AnnotType, [:ANNOT_TEXT, :ANNOT_LINK, :ANNOT_FREE_TEXT, :ANNOT_LINE, :ANNOT_SQUARE, :ANNOT_CIRCLE, :ANNOT_POLYGON, :ANNOT_POLYLINE, :ANNOT_HIGHLIGHT, :ANNOT_UNDERLINE, :ANNOT_SQUIGGLY, :ANNOT_STRIKEOUT, :ANNOT_STAMP, :ANNOT_CARET, :ANNOT_INK, :ANNOT_POPUP, :ANNOT_FILE_ATTACHMENT, :ANNOT_SOUND, :ANNOT_MOVIE, :ANNOT_WIDGET, :ANNOT_SCREEN, :ANNOT_PRINTER_MARK, :ANNOT_TRAPNET, :ANNOT_WATERMARK, :ANNOT_3D, :ANNOT_REDACT] + mod.enum :AnnotFlags, [:ANNOT_FLAG_INVISIBLE, :ANNOT_FLAG_HIDDEN, :ANNOT_FLAG_PRINT, :ANNOT_FLAG_NOZOOM, :ANNOT_FLAG_NOROTATE, :ANNOT_FLAG_NOVIEW, :ANNOT_FLAG_READONLY, :ANNOT_FLAG_LOCKED, :ANNOT_FLAG_TOGGLE_NOVIEW, :ANNOT_FLAG_LOCKED_CONTENT] + mod.enum :AnnotHighlightMode, [:ANNOT_HIGHLIGHT_MODE_NONE, :ANNOT_HIGHLIGHT_MODE_INVERT, :ANNOT_HIGHLIGHT_MODE_OUTLINE, :ANNOT_HIGHLIGHT_MODE_PUSH] + mod.enum :AnnotIcon, [:ANNOT_ICON_COMMENT, :ANNOT_ICON_KEY, :ANNOT_ICON_NOTE, :ANNOT_ICON_HELP, :ANNOT_ICON_NEW_PARAGRAPH, :ANNOT_ICON_PARAGRAPH, :ANNOT_ICON_INSERT] + mod.enum :AnnotLineEnd, [:ANNOT_LINE_END_NONE, :ANNOT_LINE_END_SQUARE, :ANNOT_LINE_END_CIRCLE, :ANNOT_LINE_END_DIAMOND, :ANNOT_LINE_END_OPENARROW, :ANNOT_LINE_END_CLOSEDARROW, :ANNOT_LINE_END_BUTT, :ANNOT_LINE_END_ROPENARROW, :ANNOT_LINE_END_RCLOSEDARROW, :ANNOT_LINE_END_SLASH] + mod.enum :AnnotLineCapPosition, [:ANNOT_LINE_CAP_INLINE, :ANNOT_LINE_CAP_TOP] + mod.enum :AnnotStampStyle, [:ANNOT_STAMP_APPROVED, :ANNOT_STAMP_EXPERIMENTAL, :ANNOT_STAMP_NOTAPPROVED, :ANNOT_STAMP_ASIS, :ANNOT_STAMP_EXPIRED, :ANNOT_STAMP_NOTFORPUBLICRELEASE, :ANNOT_STAMP_CONFIDENTIAL, :ANNOT_STAMP_FINAL, :ANNOT_STAMP_SOLD, :ANNOT_STAMP_DEPARTMENTAL, :ANNOT_STAMP_FORCOMMENT, :ANNOT_STAMP_TOPSECRET, :ANNOT_STAMP_DRAFT, :ANNOT_STAMP_FORPUBLICRELEASE] + mod.enum :GMode, [:GMODE_PAGE_DESCRIPTION, 1, :GMODE_PATH_OBJECT, 2, :GMODE_TEXT_OBJECT, 4, :GMODE_CLIPPING_PATH, 8, :GMODE_SHADING, 16, :GMODE_INLINE_IMAGE, 32, :GMODE_EXTERNAL_OBJECT, 64] + mod.enum :CompressionMode, [:COMP_MODE_NONE, 0, :COMP_MODE_TEXT, 1, :COMP_MODE_IMAGE, 2, :COMP_MODE_METADATA, 4, :COMP_MODE_ALL, 15] + mod.enum :Permission, [:ENABLE_READ, 0, :ENABLE_PRINT, 4, :ENABLE_EDIT_ALL, 8, :ENABLE_COPY, 16, :ENABLE_EDIT, 32] + mod.enum :ViewerPreference, [:HIDE_TOOLBAR, 1, :HIDE_MENUBAR, 2, :HIDE_WINDOW_UI, 4, :FIT_WINDOW, 8, :CENTER_WINDOW, 16, :PRINT_SCALING_NONE, 32, :DISPLAY_DOC_TITLE, 64] + mod.enum :Date_Parts, [:DATE_PART_YEAR, :DATE_PART_MONTH, :DATE_PART_DAY, :DATE_PART_HOUR, :DATE_PART_MINUTE, :DATE_PART_SECOND, :DATE_PART_HOUR_OFFSET, :DATE_PART_MINUTE_OFFSET, :DATE_PART_UT_RELATIONSHIP] + mod.enum :UT_Relationship, [:UT_RELATIONSHIP_NONE, :UT_RELATIONSHIP_PLUS, :UT_RELATIONSHIP_MINUS, :UT_RELATIONSHIP_ZERO] + mod.enum :PdfVer, [:VER_10, :VER_11, :VER_12, :VER_13, :VER_14, :VER_15, :VER_16, :VER_17, :VER_20] + mod.enum :InfoType, [:INFO_CREATION_DATE, :INFO_MOD_DATE, :INFO_AUTHOR, :INFO_CREATOR, :INFO_PRODUCER, :INFO_TITLE, :INFO_SUBJECT, :INFO_KEYWORDS, :INFO_TRAPPED, :INFO_GTS_PDFX] + mod.enum :EncryptMode, [:ENCRYPT_R0, 0, :ENCRYPT_R1, 1, :ENCRYPT_R2, 2, :ENCRYPT_R3, 3, :ENCRYPT_R4, 4] + mod.enum :ErrorKind, [:ARRAY_COUNT_ERR, 4097, :ARRAY_ITEM_NOT_FOUND, 4098, :ARRAY_ITEM_UNEXPECTED_TYPE, 4099, :BINARY_LENGTH_ERR, 4100, :CANNOT_GET_PALETTE, 4101, :DICT_COUNT_ERR, 4103, :DICT_ITEM_NOT_FOUND, 4104, :DICT_ITEM_UNEXPECTED_TYPE, 4105, :DICT_STREAM_LENGTH_NOT_FOUND, 4106, :DOC_ENCRYPTDICT_NOT_FOUND, 4107, :DOC_INVALID_OBJECT, 4108, :DUPLICATE_REGISTRATION, 4110, :EXCEED_JWW_CODE_NUM_LIMIT, 4111, :ENCRYPT_INVALID_PASSWORD, 4113, :ERR_UNKNOWN_CLASS, 4115, :EXCEED_GSTATE_LIMIT, 4116, :FAILED_TO_ALLOC_MEM, 4117, :FILE_IO_ERROR, 4118, :FILE_OPEN_ERROR, 4119, :FONT_EXISTS, 4121, :FONT_INVALID_WIDTH_TABLE, 4122, :INVALID_AFM_HEADER, 4123, :INVALID_ANNOTATION, 4124, :INVALID_BIT_PER_COMPONENT, 4126, :INVALID_CHAR_MATRIX_DATA, 4127, :INVALID_COLOR_SPACE, 4128, :INVALID_COMPRESSION_MODE, 4129, :INVALID_DATE_TIME, 4130, :INVALID_DESTINATION, 4131, :INVALID_DOCUMENT, 4133, :INVALID_DOCUMENT_STATE, 4134, :INVALID_ENCODER, 4135, :INVALID_ENCODER_TYPE, 4136, :INVALID_ENCODING_NAME, 4139, :INVALID_ENCRYPT_KEY_LEN, 4140, :INVALID_FONTDEF_DATA, 4141, :INVALID_FONTDEF_TYPE, 4142, :INVALID_FONT_NAME, 4143, :INVALID_IMAGE, 4144, :INVALID_JPEG_DATA, 4145, :INVALID_N_DATA, 4146, :INVALID_OBJECT, 4147, :INVALID_OBJ_ID, 4148, :INVALID_OPERATION, 4149, :INVALID_OUTLINE, 4150, :INVALID_PAGE, 4151, :INVALID_PAGES, 4152, :INVALID_PARAMETER, 4153, :INVALID_PNG_IMAGE, 4155, :INVALID_STREAM, 4156, :MISSING_FILE_NAME_ENTRY, 4157, :INVALID_TTC_FILE, 4159, :INVALID_TTC_INDEX, 4160, :INVALID_WX_DATA, 4161, :ITEM_NOT_FOUND, 4162, :LIBPNG_ERROR, 4163, :NAME_INVALID_VALUE, 4164, :NAME_OUT_OF_RANGE, 4165, :PAGES_MISSING_KIDS_ENTRY, 4169, :PAGE_CANNOT_FIND_OBJECT, 4170, :PAGE_CANNOT_GET_ROOT_PAGES, 4171, :PAGE_CANNOT_RESTORE_GSTATE, 4172, :PAGE_CANNOT_SET_PARENT, 4173, :PAGE_FONT_NOT_FOUND, 4174, :PAGE_INVALID_FONT, 4175, :PAGE_INVALID_FONT_SIZE, 4176, :PAGE_INVALID_GMODE, 4177, :PAGE_INVALID_INDEX, 4178, :PAGE_INVALID_ROTATE_VALUE, 4179, :PAGE_INVALID_SIZE, 4180, :PAGE_INVALID_XOBJECT, 4181, :PAGE_OUT_OF_RANGE, 4182, :REAL_OUT_OF_RANGE, 4183, :STREAM_EOF, 4184, :STREAM_READLN_CONTINUE, 4185, :STRING_OUT_OF_RANGE, 4187, :THIS_FUNC_WAS_SKIPPED, 4188, :TTF_CANNOT_EMBED_FONT, 4189, :TTF_INVALID_CMAP, 4190, :TTF_INVALID_FORMAT, 4191, :TTF_MISSING_TABLE, 4192, :UNSUPPORTED_FONT_TYPE, 4193, :UNSUPPORTED_JPEG_FORMAT, 4195, :UNSUPPORTED_TYPE1_FONT, 4196, :XREF_COUNT_ERR, 4197, :ZLIB_ERROR, 4198, :INVALID_PAGE_INDEX, 4199, :INVALID_URI, 4200, :PAGE_LAYOUT_OUT_OF_RANGE, 4201, :PAGE_MODE_OUT_OF_RANGE, 4208, :PAGE_NUM_STYLE_OUT_OF_RANGE, 4209, :ANNOT_INVALID_ICON, 4210, :ANNOT_INVALID_BORDER_STYLE, 4211, :PAGE_INVALID_DIRECTION, 4212, :PAGE_INSUFFICIENT_SPACE, 4214, :PAGE_INVALID_DISPLAY_TIME, 4215, :PAGE_INVALID_TRANSITION_TIME, 4216, :INVALID_PAGE_SLIDESHOW_TYPE, 4217, :EXT_GSTATE_OUT_OF_RANGE, 4224, :INVALID_EXT_GSTATE, 4225, :EXT_GSTATE_READ_ONLY, 4226, :INVALID_ICC_COMPONENT_NUM, 4229, :PAGE_INVALID_BOUNDARY, 4230, :INVALID_SHADING_TYPE, 4232] + mod.enum :LineCap, [:BUTT_CAP, :ROUND_CAP, :PROJECTING_SQUARE_CAP] + mod.enum :LineJoin, [:MITER_JOIN, :ROUND_JOIN, :BEVEL_JOIN] + mod.enum :BorderStyle, [:BORDERSTYLE_SOLID, :BORDERSTYLE_DASHED, :BORDERSTYLE_BEVELED, :BORDERSTYLE_INSET, :BORDERSTYLE_UNDERLINED] + mod.enum :BlendMode, [:BLENDMODE_NORMAL, :BLENDMODE_COMPATIBLE, :BLENDMODE_MULTIPLY, :BLENDMODE_SCREEN, :BLENDMODE_OVERLAY, :BLENDMODE_DARKEN, :BLENDMODE_LIGHTEN, :BLENDMODE_COLOR_DODGE, :BLENDMODE_COLOR_BURN, :BLENDMODE_HARD_LIGHT, :BLENDMODE_SOFT_LIGHT, :BLENDMODE_DIFFERENCE, :BLENDMODE_EXCLUSION] + mod.enum :ColorSpace, [:COLORSPACE_DEVICEGRAY, :COLORSPACE_DEVICERGB, :COLORSPACE_DEVICECMYK, :COLORSPACE_CALGRAY, :COLORSPACE_CALRGB, :COLORSPACE_LAB, :COLORSPACE_ICCBASED, :COLORSPACE_SEPARATION, :COLORSPACE_DEVICEN, :COLORSPACE_INDEXED, :COLORSPACE_PATTERN] + mod.enum :PageLayout, [:PAGE_LAYOUT_SINGLE, :PAGE_LAYOUT_ONE_COLUMN, :PAGE_LAYOUT_TWO_COLUMN_LEFT, :PAGE_LAYOUT_TWO_COLUMN_RIGHT, :PAGE_LAYOUT_TWO_PAGE_LEFT, :PAGE_LAYOUT_TWO_PAGE_RIGHT] + mod.enum :PageMode, [:PAGE_MODE_USE_NONE, :PAGE_MODE_USE_OUTLINE, :PAGE_MODE_USE_THUMBS, :PAGE_MODE_FULL_SCREEN, :PAGE_MODE_USE_OC, :PAGE_MODE_USE_ATTACHMENTS] + mod.enum :PageNum, [:PAGE_NUM_DECIMAL, :PAGE_NUM_UPPER_ROMAN, :PAGE_NUM_LOWER_ROMAN, :PAGE_NUM_UPPER_LETTERS, :PAGE_NUM_LOWER_LETTERS] + mod.enum :PageBoundary, [:PAGE_MEDIABOX, :PAGE_CROPBOX, :PAGE_BLEEDBOX, :PAGE_TRIMBOX, :PAGE_ARTBOX] + mod.enum :PageTransition, [:PAGE_TRANSITION_WIPE_RIGHT, :PAGE_TRANSITION_WIPE_UP, :PAGE_TRANSITION_WIPE_LEFT, :PAGE_TRANSITION_WIPE_DOWN, :PAGE_TRANSITION_BARN_DOORS_HORIZONTAL_OUT, :PAGE_TRANSITION_BARN_DOORS_HORIZONTAL_IN, :PAGE_TRANSITION_BARN_DOORS_VERTICAL_OUT, :PAGE_TRANSITION_BARN_DOORS_VERTICAL_IN, :PAGE_TRANSITION_BOX_OUT, :PAGE_TRANSITION_BOX_IN, :PAGE_TRANSITION_BLINDS_HORIZONTAL, :PAGE_TRANSITION_BLINDS_VERTICAL, :PAGE_TRANSITION_DISSOLVE, :PAGE_TRANSITION_GLITTER_RIGHT, :PAGE_TRANSITION_GLITTER_DOWN, :PAGE_TRANSITION_GLITTER_TOP_LEFT_TO_BOTTOM_RIGHT, :PAGE_TRANSITION_REPLACE] + mod.enum :PageOrientation, [:PAGE_ORIENTATION_PORTRAIT, :PAGE_ORIENTATION_LANDSCAPE] + mod.enum :PageSizes, [:US_LETTER, 0, :US_LEGAL, 1, :US_TABLOID, 2, :US_LEDGER, 3, :US_JUNIOR_LEGAL, 4, :US_HALF_LETTER, 5, :US_GOVERNMENT_LETTER, 6, :US_GOVERNMENT_LEGAL, 7, :US_ANSI_A, 8, :US_ANSI_B, 9, :US_ANSI_C, 10, :US_ANSI_D, 11, :US_ANSI_E, 12, :US_ARCH_A, 13, :US_ARCH_B, 14, :US_ARCH_C, 15, :US_ARCH_D, 16, :US_ARCH_E, 17, :US_ARCH_E1, 18, :US_ARCH_E2, 19, :US_ARCH_E3, 20, :"4A0", 21, :"2A0", 22, :A0, 23, :A0_PLUS, 24, :A1, 25, :A1_PLUS, 26, :A2, 27, :A3, 28, :A3_PLUS, 29, :A4, 30, :A5, 31, :A6, 32, :A7, 33, :A8, 34, :A9, 35, :A10, 36, :B0, 37, :B0_PLUS, 38, :B1, 39, :B1_PLUS, 40, :B2, 41, :B2_PLUS, 42, :B3, 43, :B4, 44, :B5, 45, :B6, 46, :B7, 47, :B8, 48, :B9, 49, :B10, 50, :B11, 51, :B12, 52, :B13, 53, :C0, 54, :C1, 55, :C2, 56, :C3, 57, :C4, 58, :C5, 59, :C6, 60, :C7, 61, :C8, 62, :C9, 63, :C10, 64, :BRITISH_DUKES, 65, :BRITISH_FOOLSCAP, 66, :BRITISH_IMPERIAL, 67, :BRITISH_KINGS, 68, :BRITISH_QUARTO, 69, :US_ENVELOPE_6_1_4, 70, :US_ENVELOPE_6_3_4, 71, :US_ENVELOPE_7, 72, :US_ENVELOPE_7_3_4_MONARCH, 73, :US_ENVELOPE8_5_8, 74, :US_ENVELOPE_9, 75, :US_ENVELOPE_10, 76, :US_ENVELOPE_11, 77, :US_ENVELOPE_12, 78, :US_ENVELOPE_14, 79, :US_ENVELOPE_16, 80, :US_ENVELOPE_A1, 81, :US_ENVELOPE_A2_LADY_GREY, 82, :US_ENVELOPE_A4, 83, :US_ENVELOPE_A6_THOMPSON_S_STANDARD, 84, :US_ENVELOPE_A7_BESSELHEIM, 85, :US_ENVELOPE_A8_CARR_S, 86, :US_ENVELOPE_A9_DIPLOMAT, 87, :US_ENVELOPE_A10_WILLOW, 88, :US_ENVELOPE_A_LONG, 89, :US_ENVELOPE_1, 90, :US_ENVELOPE_1_3_4, 91, :US_ENVELOPE_3, 92, :US_ENVELOPE_6, 93, :US_ENVELOPE_8, 94, :US_ENVELOPE_9_3_4, 95, :US_ENVELOPE_10_1_2, 96, :US_ENVELOPE_12_1_2, 97, :US_ENVELOPE_13_1_2, 98, :US_ENVELOPE_14_1_2, 99, :US_ENVELOPE_15, 100, :US_ENVELOPE_15_1_2, 101, :ENVELOPE_DL, 102, :ENVELOPE_B4, 103, :ENVELOPE_B5, 104, :ENVELOPE_B6, 105, :ENVELOPE_C3, 106, :ENVELOPE_C4, 107, :ENVELOPE_C4M, 108, :ENVELOPE_C5, 109, :ENVELOPE_C6_C5, 110, :ENVELOPE_C6, 111, :ENVELOPE_C64M, 112, :ENVELOPE_C7_C6, 113, :ENVELOPE_C7, 114, :ENVELOPE_CE4, 115, :ENVELOPE_CE64, 116, :ENVELOPE_E4, 117, :ENVELOPE_EC45, 118, :ENVELOPE_EC5, 119, :ENVELOPE_E5, 120, :ENVELOPE_E56, 121, :ENVELOPE_E6, 122, :ENVELOPE_E65, 123, :ENVELOPE_R7, 124, :ENVELOPE_S4, 125, :ENVELOPE_S5, 126, :ENVELOPE_S65, 127, :ENVELOPE_X5, 128, :ENVELOPE_EX5, 129, :PHOTO_PASSPORT, 130, :PHOTO_2R, 131, :PHOTO_LD, 132, :PHOTO_DSC, 133, :PHOTO_3R, 134, :PHOTO_L, 135, :PHOTO_LW, 136, :PHOTO_KGD, 137, :PHOTO_KG, 138, :PHOTO_4R, 139, :PHOTO_2LD, 140, :PHOTO_DSCW, 141, :PHOTO_2L, 142, :PHOTO_5R, 143, :PHOTO_2LW, 144, :PHOTO_6R, 145, :PHOTO_8R, 146, :PHOTO_6P, 147, :PHOTO_6PW, 148, :PHOTO_S8R, 149, :PHOTO_11R, 150, :PHOTO_A3_PLUS, 151, :NEWSPAPER_BERLINER, 152, :NEWSPAPER_BROADSHEET, 153, :NEWSPAPER_US_BROADSHEET, 154, :NEWSPAPER_BRITISH_BROADSHEET, 155, :NEWSPAPER_SOUTH_AFRICAN_BROADSHEET, 156, :NEWSPAPER_CINER, 157, :NEWSPAPER_COMPACT, 158, :NEWSPAPER_NORDISCH, 159, :NEWSPAPER_RHENISH, 160, :NEWSPAPER_SWISS, 161, :NEWSPAPER_TABLOID, 162, :NEWSPAPER_CANADIAN_TABLOID, 163, :NEWSPAPER_NORWEGIAN_TABLOID, 164, :NEWSPAPER_NEW_YOUR_TIMES, 165, :NEWSPAPER_WALL_STREET_JOURNAL, 166, :BOOK_FOLIO, 167, :BOOK_QUARTO, 168, :BOOK_IMPERIAL_OCTAVO, 169, :BOOK_SUPER_OCTAVO, 170, :BOOK_ROYAL_OCTAVO, 171, :BOOK_MEDIUM_OCTAVO, 172, :BOOK_OCTAVO, 173, :BOOK_CROWN_OCTAVO, 174, :BOOK_12MO, 175, :BOOK_16MO, 176, :BOOK_18MO, 177, :BOOK_32MO, 178, :BOOK_48MO, 179, :BOOK_64MO, 180, :BOOK_A_FORMAT, 181, :BOOK_B_FORMAT, 182, :BOOK_C_FORMAT, 183, :BUSINESS_CARD_ISO_216, 184, :BUSINESS_CARD_US_CANADA, 185, :BUSINESS_CARD_EUROPEAN, 186, :BUSINESS_CARD_SCANDINAVIA, 187, :BUSINESS_CARD_CHINA, 188, :BUSINESS_CARD_JAPAN, 189, :BUSINESS_CARD_IRAN, 190, :BUSINESS_CARD_HUNGARY, 191, :BUSINESS_CARD_ISO_7810_ID_1, 192, :RAW_RA0, 193, :RAW_RA1, 194, :RAW_RA2, 195, :RAW_RA3, 196, :RAW_RA4, 197, :RAW_SRA0, 198, :RAW_SRA1, 199, :RAW_SRA2, 200, :RAW_SRA3, 201, :RAW_SRA4, 202, :RAW_SRA1_PLUS, 203, :RAW_SRA2_PLUS, 204, :RAW_SRA3_PLUS, 205, :RAW_SRA3_PLUS_PLUS, 206, :RAW_A0U, 207, :RAW_A1U, 208, :RAW_A2U, 209, :RAW_A3U, 210, :RAW_A4U, 211, :BILLBOARD_1_SHEET, 212, :BILLBOARD_2_SHEET, 213, :BILLBOARD_4_SHEET, 214, :BILLBOARD_6_SHEET, 215, :BILLBOARD_12_SHEET, 216, :BILLBOARD_16_SHEET, 217, :BILLBOARD_32_SHEET, 218, :BILLBOARD_48_SHEET, 219, :BILLBOARD_64_SHEET, 220, :BILLBOARD_96_SHEET, 221, :JAPANESE_JB0, 222, :JAPANESE_JB1, 223, :JAPANESE_JB2, 224, :JAPANESE_JB3, 225, :JAPANESE_JB4, 226, :JAPANESE_JB5, 227, :JAPANESE_JB6, 228, :JAPANESE_JB7, 229, :JAPANESE_JB8, 230, :JAPANESE_JB9, 231, :JAPANESE_JB10, 232, :JAPANESE_JB11, 233, :JAPANESE_JB12, 234, :JAPANESE_SHIROKU_BAN_4, 235, :JAPANESE_SHIROKU_BAN_5, 236, :JAPANESE_SHIROKU_BAN_6, 237, :JAPANESE_KIKU_4, 238, :JAPANESE_KIKU_5, 239, :CANADIAN_P1, 240, :CANADIAN_P2, 241, :CANADIAN_P3, 242, :CANADIAN_P4, 243, :CANADIAN_P5, 244, :CANADIAN_P6, 245, :DIN_D0, 246, :DIN_D1, 247, :DIN_D2, 248, :DIN_D3, 249, :DIN_D4, 250, :DIN_D5, 251, :DIN_D6, 252, :DIN_D7, 253, :DIN_D8, 254, :SIS_E0, 255, :SIS_E1, 256, :SIS_E2, 257, :SIS_E3, 258, :SIS_E4, 259, :SIS_E5, 260, :SIS_E6, 261, :SIS_E7, 262, :SIS_E8, 263, :SIS_E9, 264, :SIS_E10, 265, :SIS_F0, 266, :SIS_F1, 267, :SIS_F2, 268, :SIS_F3, 269, :SIS_F4, 270, :SIS_F5, 271, :SIS_F6, 272, :SIS_F7, 273, :SIS_F8, 274, :SIS_F9, 275, :SIS_F10, 276, :SIS_G0, 277, :SIS_G1, 278, :SIS_G2, 279, :SIS_G3, 280, :SIS_G4, 281, :SIS_G5, 282, :SIS_G6, 283, :SIS_G7, 284, :SIS_G8, 285, :SIS_G9, 286, :SIS_G10, 287, :SIS_D0, 288, :SIS_D1, 289, :SIS_D2, 290, :SIS_D3, 291, :SIS_D4, 292, :SIS_D5, 293, :SIS_D6, 294, :SIS_D7, 295, :SIS_D8, 296, :SIS_D9, 297, :SIS_D10, 298, :COLOMBIAN_CARTA, 299, :COLOMBIAN_EXTRA_TABLOIDE, 300, :COLOMBIAN_OFICIO, 301, :COLOMBIAN_1_8_PLIEGO, 302, :COLOMBIAN_1_4_PLIEGO, 303, :COLOMBIAN_1_2_PLIEGO, 304, :COLOMBIAN_PLIEGO, 305, :CHINESE_D0, 306, :CHINESE_D1, 307, :CHINESE_D2, 308, :CHINESE_D3, 309, :CHINESE_D4, 310, :CHINESE_D5, 311, :CHINESE_D6, 312, :CHINESE_RD0, 313, :CHINESE_RD1, 314, :CHINESE_RD2, 315, :CHINESE_RD3, 316, :CHINESE_RD4, 317, :CHINESE_RD5, 318, :CHINESE_RD6, 319, :TRANSITIONAL_PA0, 320, :TRANSITIONAL_PA1, 321, :TRANSITIONAL_PA2, 322, :TRANSITIONAL_PA3, 323, :TRANSITIONAL_PA4, 324, :TRANSITIONAL_PA5, 325, :TRANSITIONAL_PA6, 326, :TRANSITIONAL_PA7, 327, :TRANSITIONAL_PA8, 328, :TRANSITIONAL_PA9, 329, :TRANSITIONAL_PA10, 330, :TRANSITIONAL_F0, 331, :TRANSITIONAL_F1, 332, :TRANSITIONAL_F2, 333, :TRANSITIONAL_F3, 334, :TRANSITIONAL_F4, 335, :TRANSITIONAL_F5, 336, :TRANSITIONAL_F6, 337, :TRANSITIONAL_F7, 338, :TRANSITIONAL_F8, 339, :TRANSITIONAL_F9, 340, :TRANSITIONAL_F10, 341, :IMPERIAL_ANTIQUARIAN, 342, :IMPERIAL_ATLAS, 343, :IMPERIAL_BRIEF, 344, :IMPERIAL_BROADSHEET, 345, :IMPERIAL_CARTRIDGE, 346, :IMPERIAL_COLUMBIER, 347, :IMPERIAL_COPY_DRAUGHT, 348, :IMPERIAL_CROWN, 349, :IMPERIAL_DEMY, 350, :IMPERIAL_DOUBLE_DEMY, 351, :IMPERIAL_QUAD_DEMY, 352, :IMPERIAL_ELEPHANT, 353, :IMPERIAL_DOUBLE_ELEPHANT, 354, :IMPERIAL_EMPEROR, 355, :IMPERIAL_FOOLSCAP, 356, :IMPERIAL_SMALL_FOOLSCAP, 357, :IMPERIAL_GRAND_EAGLE, 358, :IMPERIAL_IMPERIAL, 359, :IMPERIAL_MEDIUM, 360, :IMPERIAL_MONARCH, 361, :IMPERIAL_POST, 362, :IMPERIAL_HALF_POST, 363, :IMPERIAL_PINCHED_POST, 364, :IMPERIAL_LARGE_POST, 365, :IMPERIAL_DOUBLE_LARGE_POST, 366, :IMPERIAL_DOUBLE_POST, 367, :IMPERIAL_POTT, 368, :IMPERIAL_PRINCESS, 369, :IMPERIAL_QUARTO, 370, :IMPERIAL_ROYAL, 371, :IMPERIAL_SUPER_ROYAL, 372, :FRENCH_CLOCHE, 373, :FRENCH_POT_ECOLIER, 374, :FRENCH_TELLIERE, 375, :FRENCH_COURONNE_ECRITURE, 376, :FRENCH_COURONNE_EDITION, 377, :FRENCH_ROBERTO, 378, :FRENCH_ECU, 379, :FRENCH_COQUILLE, 380, :FRENCH_CARRE, 381, :FRENCH_CAVALIER, 382, :FRENCH_DEMI_RAISIN, 383, :FRENCH_RAISIN, 384, :FRENCH_DOUBLE_RAISIN, 385, :FRENCH_JESUS, 386, :FRENCH_SOLEIL, 387, :FRENCH_COLOMBIER_AFFICHE, 388, :FRENCH_COLOMBIER_COMMERCIAL, 389, :FRENCH_PETIT_AIGLE, 390, :FRENCH_GRAND_AIGLE, 391, :FRENCH_GRAND_MONDE, 392, :FRENCH_UNIVERS, 393, :RUSSIAN_60X84_8, 394, :RUSSIAN_60X84_16, 395, :RUSSIAN_60X84_32, 396, :RUSSIAN_60X90_8, 397, :RUSSIAN_60X90_16, 398, :RUSSIAN_70X100_16, 399, :RUSSIAN_70X100_32, 400, :RUSSIAN_70X108_8, 401, :RUSSIAN_70X108_16, 402, :RUSSIAN_70X108_32, 403, :RUSSIAN_70X90_16, 404, :RUSSIAN_70X90_32, 405, :RUSSIAN_75X90_32, 406, :RUSSIAN_84X108_8, 407, :RUSSIAN_84X108_32, 408, :EOF, 409] + mod.enum :TextRenderingMode, [:TEXT_RENDERING_MODE_FILL, :TEXT_RENDERING_MODE_STROKE, :TEXT_RENDERING_MODE_FILL_THEN_STROKE, :TEXT_RENDERING_MODE_INVISIBLE, :TEXT_RENDERING_MODE_FILL_CLIPPING, :TEXT_RENDERING_MODE_STROKE_CLIPPING, :TEXT_RENDERING_MODE_FILL_STROKE_CLIPPING, :TEXT_RENDERING_MODE_CLIPPING] + mod.enum :TextAlignment, [:TEXT_ALIGN_LEFT, :TEXT_ALIGN_RIGHT, :TEXT_ALIGN_CENTER, :TEXT_ALIGN_JUSTIFY] + mod.enum :WritingMode, [:WRITING_MODE_HORIZONTAL, :WRITING_MODE_VERTICAL] +end + +# ---- structs (improvement #3: by_value alias) ---- +def apply_structs(mod) + unless mod.const_defined?(:RGBColorStruct, false) + klass = Class.new(FFI::Struct) do + layout :r, :float, + :g, :float, + :b, :float + end + mod.const_set(:RGBColorStruct, klass) + end + mod.typedef mod.const_get(:RGBColorStruct).by_value, :RGBColor + unless mod.const_defined?(:CMYKColorStruct, false) + klass = Class.new(FFI::Struct) do + layout :c, :float, + :m, :float, + :y, :float, + :k, :float + end + mod.const_set(:CMYKColorStruct, klass) + end + mod.typedef mod.const_get(:CMYKColorStruct).by_value, :CMYKColor + unless mod.const_defined?(:PointStruct, false) + klass = Class.new(FFI::Struct) do + layout :x, :float, + :y, :float + end + mod.const_set(:PointStruct, klass) + end + mod.typedef mod.const_get(:PointStruct).by_value, :Point + unless mod.const_defined?(:RectStruct, false) + klass = Class.new(FFI::Struct) do + layout :left, :float, + :bottom, :float, + :right, :float, + :top, :float + end + mod.const_set(:RectStruct, klass) + end + mod.typedef mod.const_get(:RectStruct).by_value, :Rect + unless mod.const_defined?(:TextWidthStruct, false) + klass = Class.new(FFI::Struct) do + layout :numchars, :uint32, + :numwords, :uint32, + :width, :uint32, + :numspace, :uint32 + end + mod.const_set(:TextWidthStruct, klass) + end + mod.typedef mod.const_get(:TextWidthStruct).by_value, :TextWidth +end + +# ---- definitions (typedef aliases) ---- +def apply_definitions(mod) + mod.typedef :Dict, :Annotation + mod.typedef :Array, :Destination + mod.typedef :Dict, :OutputIntent + mod.typedef :Dict, :ExData + mod.typedef :Dict, :ExtGState + mod.typedef :Dict, :Font + mod.typedef :Dict, :JavaScript + mod.typedef :Dict, :Page + mod.typedef :Dict, :Pattern + mod.typedef :Dict, :XObject + end + end + end + end +end + +module Brst + module Binding + module Ruby + module Const + BRST_TRUE = 1 + BRST_FALSE = 0 + BRST_OK = 0 + BRST_PI = 3.14159265358979323846 + BRST_MM = 2.834646 + BRST_IN = 72.00000 + end + end + end +end + +module Brst + module Binding + module Ruby + module PageSizesMM + TABLE = { + "US_LETTER" => { caption: "Letter", origin: "US Loose", width_mm: 216.0, height_mm: 279.0 }, + "US_LEGAL" => { caption: "Legal", origin: "US Loose", width_mm: 216.0, height_mm: 356.0 }, + "US_TABLOID" => { caption: "Tabloid", origin: "US Loose", width_mm: 279.0, height_mm: 432.0 }, + "US_LEDGER" => { caption: "Ledger", origin: "US Loose", width_mm: 432.0, height_mm: 279.0 }, + "US_JUNIOR_LEGAL" => { caption: "Junior Legal", origin: "US Loose", width_mm: 127.0, height_mm: 203.0 }, + "US_HALF_LETTER" => { caption: "Half Letter", origin: "US Loose", width_mm: 140.0, height_mm: 216.0 }, + "US_GOVERNMENT_LETTER" => { caption: "Government Letter", origin: "US Loose", width_mm: 203.0, height_mm: 267.0 }, + "US_GOVERNMENT_LEGAL" => { caption: "Government Legal", origin: "US Loose", width_mm: 216.0, height_mm: 330.0 }, + "US_ANSI_A" => { caption: "ANSI A", origin: "US ANSI", width_mm: 216.0, height_mm: 279.0 }, + "US_ANSI_B" => { caption: "ANSI B", origin: "US ANSI", width_mm: 279.0, height_mm: 432.0 }, + "US_ANSI_C" => { caption: "ANSI C", origin: "US ANSI", width_mm: 432.0, height_mm: 559.0 }, + "US_ANSI_D" => { caption: "ANSI D", origin: "US ANSI", width_mm: 559.0, height_mm: 864.0 }, + "US_ANSI_E" => { caption: "ANSI E", origin: "US ANSI", width_mm: 864.0, height_mm: 1118.0 }, + "US_ARCH_A" => { caption: "Arch A", origin: "US Arch", width_mm: 229.0, height_mm: 305.0 }, + "US_ARCH_B" => { caption: "Arch B", origin: "US Arch", width_mm: 305.0, height_mm: 457.0 }, + "US_ARCH_C" => { caption: "Arch C", origin: "US Arch", width_mm: 457.0, height_mm: 610.0 }, + "US_ARCH_D" => { caption: "Arch D", origin: "US Arch", width_mm: 610.0, height_mm: 914.0 }, + "US_ARCH_E" => { caption: "Arch E", origin: "US Arch", width_mm: 914.0, height_mm: 1219.0 }, + "US_ARCH_E1" => { caption: "Arch E1", origin: "US Arch", width_mm: 762.0, height_mm: 1067.0 }, + "US_ARCH_E2" => { caption: "Arch E2", origin: "US Arch", width_mm: 660.0, height_mm: 965.0 }, + "US_ARCH_E3" => { caption: "Arch E3", origin: "US Arch", width_mm: 686.0, height_mm: 991.0 }, + "4A0" => { caption: "4A0", origin: "ISO 216", width_mm: 1682.0, height_mm: 2378.0 }, + "2A0" => { caption: "2A0", origin: "ISO 216", width_mm: 1189.0, height_mm: 1682.0 }, + "A0" => { caption: "A0", origin: "ISO 216", width_mm: 841.0, height_mm: 1189.0 }, + "A0_PLUS" => { caption: "A0+", origin: "ISO 216", width_mm: 914.0, height_mm: 1292.0 }, + "A1" => { caption: "A1", origin: "ISO 216", width_mm: 594.0, height_mm: 841.0 }, + "A1_PLUS" => { caption: "A1+", origin: "ISO 216", width_mm: 609.0, height_mm: 914.0 }, + "A2" => { caption: "A2", origin: "ISO 216", width_mm: 420.0, height_mm: 594.0 }, + "A3" => { caption: "A3", origin: "ISO 216", width_mm: 297.0, height_mm: 420.0 }, + "A3_PLUS" => { caption: "A3+", origin: "ISO 216", width_mm: 329.0, height_mm: 483.0 }, + "A4" => { caption: "A4", origin: "ISO 216", width_mm: 210.0, height_mm: 297.0 }, + "A5" => { caption: "A5", origin: "ISO 216", width_mm: 148.0, height_mm: 210.0 }, + "A6" => { caption: "A6", origin: "ISO 216", width_mm: 105.0, height_mm: 148.0 }, + "A7" => { caption: "A7", origin: "ISO 216", width_mm: 74.0, height_mm: 105.0 }, + "A8" => { caption: "A8", origin: "ISO 216", width_mm: 52.0, height_mm: 74.0 }, + "A9" => { caption: "A9", origin: "ISO 216", width_mm: 37.0, height_mm: 52.0 }, + "A10" => { caption: "A10", origin: "ISO 216", width_mm: 26.0, height_mm: 37.0 }, + "B0" => { caption: "B0", origin: "ISO 216", width_mm: 1000.0, height_mm: 1414.0 }, + "B0_PLUS" => { caption: "B0+", origin: "ISO 216", width_mm: 1118.0, height_mm: 1580.0 }, + "B1" => { caption: "B1", origin: "ISO 216", width_mm: 707.0, height_mm: 1000.0 }, + "B1_PLUS" => { caption: "B1+", origin: "ISO 216", width_mm: 720.0, height_mm: 1020.0 }, + "B2" => { caption: "B2", origin: "ISO 216", width_mm: 500.0, height_mm: 707.0 }, + "B2_PLUS" => { caption: "B2+", origin: "ISO 216", width_mm: 520.0, height_mm: 720.0 }, + "B3" => { caption: "B3", origin: "ISO 216", width_mm: 353.0, height_mm: 500.0 }, + "B4" => { caption: "B4", origin: "ISO 216", width_mm: 250.0, height_mm: 353.0 }, + "B5" => { caption: "B5", origin: "ISO 216", width_mm: 176.0, height_mm: 250.0 }, + "B6" => { caption: "B6", origin: "ISO 216", width_mm: 125.0, height_mm: 176.0 }, + "B7" => { caption: "B7", origin: "ISO 216", width_mm: 88.0, height_mm: 125.0 }, + "B8" => { caption: "B8", origin: "ISO 216", width_mm: 62.0, height_mm: 88.0 }, + "B9" => { caption: "B9", origin: "ISO 216", width_mm: 44.0, height_mm: 62.0 }, + "B10" => { caption: "B10", origin: "ISO 216", width_mm: 31.0, height_mm: 44.0 }, + "B11" => { caption: "B11", origin: "ISO 216", width_mm: 22.0, height_mm: 31.0 }, + "B12" => { caption: "B12", origin: "ISO 216", width_mm: 15.0, height_mm: 22.0 }, + "B13" => { caption: "B13", origin: "ISO 216", width_mm: 11.0, height_mm: 15.0 }, + "C0" => { caption: "C0", origin: "ISO 216", width_mm: 917.0, height_mm: 1297.0 }, + "C1" => { caption: "C1", origin: "ISO 216", width_mm: 648.0, height_mm: 917.0 }, + "C2" => { caption: "C2", origin: "ISO 216", width_mm: 458.0, height_mm: 648.0 }, + "C3" => { caption: "C3", origin: "ISO 216", width_mm: 324.0, height_mm: 458.0 }, + "C4" => { caption: "C4", origin: "ISO 216", width_mm: 229.0, height_mm: 324.0 }, + "C5" => { caption: "C5", origin: "ISO 216", width_mm: 162.0, height_mm: 229.0 }, + "C6" => { caption: "C6", origin: "ISO 216", width_mm: 114.0, height_mm: 162.0 }, + "C7" => { caption: "C7", origin: "ISO 216", width_mm: 81.0, height_mm: 114.0 }, + "C8" => { caption: "C8", origin: "ISO 216", width_mm: 57.0, height_mm: 81.0 }, + "C9" => { caption: "C9", origin: "ISO 216", width_mm: 40.0, height_mm: 57.0 }, + "C10" => { caption: "C10", origin: "ISO 216", width_mm: 28.0, height_mm: 40.0 }, + "BRITISH_DUKES" => { caption: "Dukes", origin: "Traditional British", width_mm: 140.0, height_mm: 178.0 }, + "BRITISH_FOOLSCAP" => { caption: "Foolscap", origin: "Traditional British", width_mm: 203.0, height_mm: 330.0 }, + "BRITISH_IMPERIAL" => { caption: "Imperial", origin: "Traditional British", width_mm: 178.0, height_mm: 229.0 }, + "BRITISH_KINGS" => { caption: "Kings", origin: "Traditional British", width_mm: 165.0, height_mm: 203.0 }, + "BRITISH_QUARTO" => { caption: "Quarto", origin: "Traditional British", width_mm: 203.0, height_mm: 254.0 }, + "US_ENVELOPE_6_1_4" => { caption: "6¼", origin: "US Commercial envelopes", width_mm: 152.0, height_mm: 89.0 }, + "US_ENVELOPE_6_3_4" => { caption: "6¾", origin: "US Commercial envelopes", width_mm: 165.0, height_mm: 92.0 }, + "US_ENVELOPE_7" => { caption: "7", origin: "US Commercial envelopes", width_mm: 172.0, height_mm: 95.0 }, + "US_ENVELOPE_7_3_4_MONARCH" => { caption: "7¾ Monarch", origin: "US Commercial envelopes", width_mm: 191.0, height_mm: 98.0 }, + "US_ENVELOPE8_5_8" => { caption: "8⅝ ", origin: "US Commercial envelopes", width_mm: 219.0, height_mm: 92.0 }, + "US_ENVELOPE_9" => { caption: "9", origin: "US Commercial envelopes", width_mm: 225.0, height_mm: 98.0 }, + "US_ENVELOPE_10" => { caption: "10", origin: "US Commercial envelopes", width_mm: 241.0, height_mm: 104.0 }, + "US_ENVELOPE_11" => { caption: "11", origin: "US Commercial envelopes", width_mm: 264.0, height_mm: 114.0 }, + "US_ENVELOPE_12" => { caption: "12", origin: "US Commercial envelopes", width_mm: 279.0, height_mm: 121.0 }, + "US_ENVELOPE_14" => { caption: "14", origin: "US Commercial envelopes", width_mm: 292.0, height_mm: 127.0 }, + "US_ENVELOPE_16" => { caption: "16", origin: "US Commercial envelopes", width_mm: 305.0, height_mm: 152.0 }, + "US_ENVELOPE_A1" => { caption: "A1", origin: "US Announcement envelopes", width_mm: 92.0, height_mm: 130.0 }, + "US_ENVELOPE_A2_LADY_GREY" => { caption: "A2 Lady Grey", origin: "US Announcement envelopes", width_mm: 146.0, height_mm: 111.0 }, + "US_ENVELOPE_A4" => { caption: "A4", origin: "US Announcement envelopes", width_mm: 159.0, height_mm: 108.0 }, + "US_ENVELOPE_A6_THOMPSON_S_STANDARD" => { caption: "A6 Thompson's Standard", origin: "US Announcement envelopes", width_mm: 165.0, height_mm: 121.0 }, + "US_ENVELOPE_A7_BESSELHEIM" => { caption: "A7 Besselheim", origin: "US Announcement envelopes", width_mm: 184.0, height_mm: 133.0 }, + "US_ENVELOPE_A8_CARR_S" => { caption: "A8 Carr's", origin: "US Announcement envelopes", width_mm: 206.0, height_mm: 140.0 }, + "US_ENVELOPE_A9_DIPLOMAT" => { caption: "A9 Diplomat", origin: "US Announcement envelopes", width_mm: 222.0, height_mm: 146.0 }, + "US_ENVELOPE_A10_WILLOW" => { caption: "A10 Willow", origin: "US Announcement envelopes", width_mm: 241.0, height_mm: 152.0 }, + "US_ENVELOPE_A_LONG" => { caption: "A Long", origin: "US Announcement envelopes", width_mm: 225.0, height_mm: 98.0 }, + "US_ENVELOPE_1" => { caption: "1", origin: "US Catalog envelopes", width_mm: 229.0, height_mm: 152.0 }, + "US_ENVELOPE_1_3_4" => { caption: "1¾", origin: "US Catalog envelopes", width_mm: 241.0, height_mm: 152.0 }, + "US_ENVELOPE_3" => { caption: "3", origin: "US Catalog envelopes", width_mm: 254.0, height_mm: 178.0 }, + "US_ENVELOPE_6" => { caption: "6", origin: "US Catalog envelopes", width_mm: 267.0, height_mm: 191.0 }, + "US_ENVELOPE_8" => { caption: "8", origin: "US Catalog envelopes", width_mm: 286.0, height_mm: 210.0 }, + "US_ENVELOPE_9_3_4" => { caption: "9¾", origin: "US Catalog envelopes", width_mm: 286.0, height_mm: 222.0 }, + "US_ENVELOPE_10_1_2" => { caption: "10½", origin: "US Catalog envelopes", width_mm: 305.0, height_mm: 229.0 }, + "US_ENVELOPE_12_1_2" => { caption: "12½", origin: "US Catalog envelopes", width_mm: 318.0, height_mm: 241.0 }, + "US_ENVELOPE_13_1_2" => { caption: "13½", origin: "US Catalog envelopes", width_mm: 330.0, height_mm: 254.0 }, + "US_ENVELOPE_14_1_2" => { caption: "14½", origin: "US Catalog envelopes", width_mm: 368.0, height_mm: 292.0 }, + "US_ENVELOPE_15" => { caption: "15", origin: "US Catalog envelopes", width_mm: 381.0, height_mm: 254.0 }, + "US_ENVELOPE_15_1_2" => { caption: "15½", origin: "US Catalog envelopes", width_mm: 394.0, height_mm: 305.0 }, + "ENVELOPE_DL" => { caption: "DL", origin: "ISO 269", width_mm: 110.0, height_mm: 220.0 }, + "ENVELOPE_B4" => { caption: "B4", origin: "ISO 269", width_mm: 250.0, height_mm: 353.0 }, + "ENVELOPE_B5" => { caption: "B5", origin: "ISO 269", width_mm: 176.0, height_mm: 250.0 }, + "ENVELOPE_B6" => { caption: "B6", origin: "ISO 269", width_mm: 125.0, height_mm: 176.0 }, + "ENVELOPE_C3" => { caption: "C3", origin: "ISO 269", width_mm: 324.0, height_mm: 458.0 }, + "ENVELOPE_C4" => { caption: "C4", origin: "ISO 269", width_mm: 229.0, height_mm: 324.0 }, + "ENVELOPE_C4M" => { caption: "C4M", origin: "ISO 269", width_mm: 318.0, height_mm: 229.0 }, + "ENVELOPE_C5" => { caption: "C5", origin: "ISO 269", width_mm: 162.0, height_mm: 229.0 }, + "ENVELOPE_C6_C5" => { caption: "C6/C5", origin: "ISO 269", width_mm: 114.0, height_mm: 229.0 }, + "ENVELOPE_C6" => { caption: "C6", origin: "ISO 269", width_mm: 114.0, height_mm: 162.0 }, + "ENVELOPE_C64M" => { caption: "C64M", origin: "ISO 269", width_mm: 318.0, height_mm: 114.0 }, + "ENVELOPE_C7_C6" => { caption: "C7/C6", origin: "ISO 269", width_mm: 81.0, height_mm: 162.0 }, + "ENVELOPE_C7" => { caption: "C7", origin: "ISO 269", width_mm: 81.0, height_mm: 114.0 }, + "ENVELOPE_CE4" => { caption: "CE4", origin: "ISO 269", width_mm: 229.0, height_mm: 310.0 }, + "ENVELOPE_CE64" => { caption: "CE64", origin: "ISO 269", width_mm: 114.0, height_mm: 310.0 }, + "ENVELOPE_E4" => { caption: "E4", origin: "ISO 269", width_mm: 220.0, height_mm: 312.0 }, + "ENVELOPE_EC45" => { caption: "EC45", origin: "ISO 269", width_mm: 220.0, height_mm: 229.0 }, + "ENVELOPE_EC5" => { caption: "EC5", origin: "ISO 269", width_mm: 155.0, height_mm: 229.0 }, + "ENVELOPE_E5" => { caption: "E5", origin: "ISO 269", width_mm: 115.0, height_mm: 220.0 }, + "ENVELOPE_E56" => { caption: "E56", origin: "ISO 269", width_mm: 155.0, height_mm: 155.0 }, + "ENVELOPE_E6" => { caption: "E6", origin: "ISO 269", width_mm: 110.0, height_mm: 155.0 }, + "ENVELOPE_E65" => { caption: "E65", origin: "ISO 269", width_mm: 110.0, height_mm: 220.0 }, + "ENVELOPE_R7" => { caption: "R7", origin: "ISO 269", width_mm: 120.0, height_mm: 135.0 }, + "ENVELOPE_S4" => { caption: "S4", origin: "ISO 269", width_mm: 250.0, height_mm: 330.0 }, + "ENVELOPE_S5" => { caption: "S5", origin: "ISO 269", width_mm: 185.0, height_mm: 255.0 }, + "ENVELOPE_S65" => { caption: "S65", origin: "ISO 269", width_mm: 110.0, height_mm: 225.0 }, + "ENVELOPE_X5" => { caption: "X5", origin: "ISO 269", width_mm: 105.0, height_mm: 216.0 }, + "ENVELOPE_EX5" => { caption: "EX5", origin: "ISO 269", width_mm: 155.0, height_mm: 216.0 }, + "PHOTO_PASSPORT" => { caption: "Passport", origin: "Photography", width_mm: 35.0, height_mm: 45.0 }, + "PHOTO_2R" => { caption: "2R", origin: "Photography", width_mm: 64.0, height_mm: 89.0 }, + "PHOTO_LD" => { caption: "LD", origin: "Photography", width_mm: 89.0, height_mm: 119.0 }, + "PHOTO_DSC" => { caption: "DSC", origin: "Photography", width_mm: 89.0, height_mm: 119.0 }, + "PHOTO_3R" => { caption: "3R", origin: "Photography", width_mm: 89.0, height_mm: 127.0 }, + "PHOTO_L" => { caption: "L", origin: "Photography", width_mm: 89.0, height_mm: 127.0 }, + "PHOTO_LW" => { caption: "LW", origin: "Photography", width_mm: 89.0, height_mm: 133.0 }, + "PHOTO_KGD" => { caption: "KGD", origin: "Photography", width_mm: 102.0, height_mm: 136.0 }, + "PHOTO_KG" => { caption: "KG", origin: "Photography", width_mm: 102.0, height_mm: 152.0 }, + "PHOTO_4R" => { caption: "4R", origin: "Photography", width_mm: 102.0, height_mm: 152.0 }, + "PHOTO_2LD" => { caption: "2LD", origin: "Photography", width_mm: 127.0, height_mm: 169.0 }, + "PHOTO_DSCW" => { caption: "DSCW", origin: "Photography", width_mm: 127.0, height_mm: 169.0 }, + "PHOTO_2L" => { caption: "2L", origin: "Photography", width_mm: 127.0, height_mm: 178.0 }, + "PHOTO_5R" => { caption: "5R", origin: "Photography", width_mm: 127.0, height_mm: 178.0 }, + "PHOTO_2LW" => { caption: "2LW", origin: "Photography", width_mm: 127.0, height_mm: 190.0 }, + "PHOTO_6R" => { caption: "6R", origin: "Photography", width_mm: 152.0, height_mm: 203.0 }, + "PHOTO_8R" => { caption: "8R", origin: "Photography", width_mm: 203.0, height_mm: 254.0 }, + "PHOTO_6P" => { caption: "6P", origin: "Photography", width_mm: 203.0, height_mm: 254.0 }, + "PHOTO_6PW" => { caption: "6PW", origin: "Photography", width_mm: 203.0, height_mm: 305.0 }, + "PHOTO_S8R" => { caption: "S8R", origin: "Photography", width_mm: 203.0, height_mm: 305.0 }, + "PHOTO_11R" => { caption: "11R", origin: "Photography", width_mm: 279.0, height_mm: 356.0 }, + "PHOTO_A3_PLUS" => { caption: "A3+ Super B", origin: "Photography", width_mm: 330.0, height_mm: 483.0 }, + "NEWSPAPER_BERLINER" => { caption: "Berliner", origin: "Newspaper", width_mm: 315.0, height_mm: 470.0 }, + "NEWSPAPER_BROADSHEET" => { caption: "Broadsheet", origin: "Newspaper", width_mm: 597.0, height_mm: 749.0 }, + "NEWSPAPER_US_BROADSHEET" => { caption: "US Broadsheet", origin: "Newspaper", width_mm: 381.0, height_mm: 578.0 }, + "NEWSPAPER_BRITISH_BROADSHEET" => { caption: "British Broadsheet", origin: "Newspaper", width_mm: 375.0, height_mm: 597.0 }, + "NEWSPAPER_SOUTH_AFRICAN_BROADSHEET" => { caption: "South African Broadsheet", origin: "Newspaper", width_mm: 410.0, height_mm: 578.0 }, + "NEWSPAPER_CINER" => { caption: "Ciner", origin: "Newspaper", width_mm: 350.0, height_mm: 500.0 }, + "NEWSPAPER_COMPACT" => { caption: "Compact", origin: "Newspaper", width_mm: 280.0, height_mm: 430.0 }, + "NEWSPAPER_NORDISCH" => { caption: "Nordisch", origin: "Newspaper", width_mm: 400.0, height_mm: 570.0 }, + "NEWSPAPER_RHENISH" => { caption: "Rhenish", origin: "Newspaper", width_mm: 350.0, height_mm: 520.0 }, + "NEWSPAPER_SWISS" => { caption: "Swiss", origin: "Newspaper", width_mm: 320.0, height_mm: 475.0 }, + "NEWSPAPER_TABLOID" => { caption: "Tabloid", origin: "Newspaper", width_mm: 280.0, height_mm: 430.0 }, + "NEWSPAPER_CANADIAN_TABLOID" => { caption: "Canadian Tabloid", origin: "Newspaper", width_mm: 260.0, height_mm: 368.0 }, + "NEWSPAPER_NORWEGIAN_TABLOID" => { caption: "Norwegian Tabloid", origin: "Newspaper", width_mm: 280.0, height_mm: 400.0 }, + "NEWSPAPER_NEW_YOUR_TIMES" => { caption: "New York Times", origin: "Newspaper", width_mm: 305.0, height_mm: 559.0 }, + "NEWSPAPER_WALL_STREET_JOURNAL" => { caption: "Wall Street Journal", origin: "Newspaper", width_mm: 305.0, height_mm: 578.0 }, + "BOOK_FOLIO" => { caption: "Folio", origin: "Book", width_mm: 304.8, height_mm: 482.6 }, + "BOOK_QUARTO" => { caption: "Quarto", origin: "Book", width_mm: 241.3, height_mm: 304.8 }, + "BOOK_IMPERIAL_OCTAVO" => { caption: "Imperial Octavo", origin: "Book", width_mm: 209.6, height_mm: 292.1 }, + "BOOK_SUPER_OCTAVO" => { caption: "Super Octavo", origin: "Book", width_mm: 177.8, height_mm: 279.4 }, + "BOOK_ROYAL_OCTAVO" => { caption: "Royal Octavo", origin: "Book", width_mm: 165.1, height_mm: 254.0 }, + "BOOK_MEDIUM_OCTAVO" => { caption: "Medium Octavo", origin: "Book", width_mm: 165.1, height_mm: 234.9 }, + "BOOK_OCTAVO" => { caption: "Octavo", origin: "Book", width_mm: 152.4, height_mm: 228.6 }, + "BOOK_CROWN_OCTAVO" => { caption: "Crown Octavo", origin: "Book", width_mm: 136.5, height_mm: 203.2 }, + "BOOK_12MO" => { caption: "12mo", origin: "Book", width_mm: 127.0, height_mm: 187.3 }, + "BOOK_16MO" => { caption: "16mo", origin: "Book", width_mm: 101.6, height_mm: 171.4 }, + "BOOK_18MO" => { caption: "18mo", origin: "Book", width_mm: 101.6, height_mm: 165.1 }, + "BOOK_32MO" => { caption: "32mo", origin: "Book", width_mm: 88.9, height_mm: 139.7 }, + "BOOK_48MO" => { caption: "48mo", origin: "Book", width_mm: 63.5, height_mm: 101.6 }, + "BOOK_64MO" => { caption: "64mo", origin: "Book", width_mm: 50.8, height_mm: 76.2 }, + "BOOK_A_FORMAT" => { caption: "A Format", origin: "Book", width_mm: 110.0, height_mm: 178.0 }, + "BOOK_B_FORMAT" => { caption: "B Format", origin: "Book", width_mm: 129.0, height_mm: 198.0 }, + "BOOK_C_FORMAT" => { caption: "C Format", origin: "Book", width_mm: 135.0, height_mm: 216.0 }, + "BUSINESS_CARD_ISO_216" => { caption: "ISO 216", origin: "Business Card", width_mm: 74.0, height_mm: 52.0 }, + "BUSINESS_CARD_US_CANADA" => { caption: "US/Canada", origin: "Business Card", width_mm: 88.9, height_mm: 50.8 }, + "BUSINESS_CARD_EUROPEAN" => { caption: "European", origin: "Business Card", width_mm: 85.0, height_mm: 55.0 }, + "BUSINESS_CARD_SCANDINAVIA" => { caption: "Scandinavia", origin: "Business Card", width_mm: 90.0, height_mm: 55.0 }, + "BUSINESS_CARD_CHINA" => { caption: "China", origin: "Business Card", width_mm: 90.0, height_mm: 54.0 }, + "BUSINESS_CARD_JAPAN" => { caption: "Japan", origin: "Business Card", width_mm: 91.0, height_mm: 55.0 }, + "BUSINESS_CARD_IRAN" => { caption: "Iran", origin: "Business Card", width_mm: 85.0, height_mm: 48.0 }, + "BUSINESS_CARD_HUNGARY" => { caption: "Hungary", origin: "Business Card", width_mm: 90.0, height_mm: 50.0 }, + "BUSINESS_CARD_ISO_7810_ID_1" => { caption: "ISO 7810 ID-1", origin: "Business Card", width_mm: 85.6, height_mm: 54.0 }, + "RAW_RA0" => { caption: "RA0", origin: "ISO 217:1995", width_mm: 860.0, height_mm: 1220.0 }, + "RAW_RA1" => { caption: "RA1", origin: "ISO 217:1995", width_mm: 610.0, height_mm: 860.0 }, + "RAW_RA2" => { caption: "RA2", origin: "ISO 217:1995", width_mm: 430.0, height_mm: 610.0 }, + "RAW_RA3" => { caption: "RA3", origin: "ISO 217:1995", width_mm: 305.0, height_mm: 430.0 }, + "RAW_RA4" => { caption: "RA4", origin: "ISO 217:1995", width_mm: 215.0, height_mm: 305.0 }, + "RAW_SRA0" => { caption: "SRA0", origin: "ISO 217:1995", width_mm: 900.0, height_mm: 1280.0 }, + "RAW_SRA1" => { caption: "SRA1", origin: "ISO 217:1995", width_mm: 640.0, height_mm: 900.0 }, + "RAW_SRA2" => { caption: "SRA2", origin: "ISO 217:1995", width_mm: 450.0, height_mm: 640.0 }, + "RAW_SRA3" => { caption: "SRA3", origin: "ISO 217:1995", width_mm: 320.0, height_mm: 450.0 }, + "RAW_SRA4" => { caption: "SRA4", origin: "ISO 217:1995", width_mm: 225.0, height_mm: 320.0 }, + "RAW_SRA1_PLUS" => { caption: "SRA1+", origin: "ISO 217:1995", width_mm: 660.0, height_mm: 920.0 }, + "RAW_SRA2_PLUS" => { caption: "SRA2+", origin: "ISO 217:1995", width_mm: 480.0, height_mm: 650.0 }, + "RAW_SRA3_PLUS" => { caption: "SRA3+", origin: "ISO 217:1995", width_mm: 320.0, height_mm: 460.0 }, + "RAW_SRA3_PLUS_PLUS" => { caption: "SRA3++", origin: "ISO 217:1995", width_mm: 320.0, height_mm: 464.0 }, + "RAW_A0U" => { caption: "A0U", origin: "ISO 217:1995", width_mm: 880.0, height_mm: 1230.0 }, + "RAW_A1U" => { caption: "A1U", origin: "ISO 217:1995", width_mm: 625.0, height_mm: 880.0 }, + "RAW_A2U" => { caption: "A2U", origin: "ISO 217:1995", width_mm: 450.0, height_mm: 625.0 }, + "RAW_A3U" => { caption: "A3U", origin: "ISO 217:1995", width_mm: 330.0, height_mm: 450.0 }, + "RAW_A4U" => { caption: "A4U", origin: "ISO 217:1995", width_mm: 240.0, height_mm: 330.0 }, + "BILLBOARD_1_SHEET" => { caption: "1 Sheet", origin: "Billboard", width_mm: 508.0, height_mm: 762.0 }, + "BILLBOARD_2_SHEET" => { caption: "2 Sheet", origin: "Billboard", width_mm: 762.0, height_mm: 1016.0 }, + "BILLBOARD_4_SHEET" => { caption: "4 Sheet", origin: "Billboard", width_mm: 1016.0, height_mm: 1524.0 }, + "BILLBOARD_6_SHEET" => { caption: "6 Sheet", origin: "Billboard", width_mm: 1200.0, height_mm: 1800.0 }, + "BILLBOARD_12_SHEET" => { caption: "12 Sheet", origin: "Billboard", width_mm: 3048.0, height_mm: 1524.0 }, + "BILLBOARD_16_SHEET" => { caption: "16 Sheet", origin: "Billboard", width_mm: 2032.0, height_mm: 3048.0 }, + "BILLBOARD_32_SHEET" => { caption: "32 Sheet", origin: "Billboard", width_mm: 4064.0, height_mm: 3048.0 }, + "BILLBOARD_48_SHEET" => { caption: "48 Sheet", origin: "Billboard", width_mm: 6096.0, height_mm: 3048.0 }, + "BILLBOARD_64_SHEET" => { caption: "64 Sheet", origin: "Billboard", width_mm: 8128.0, height_mm: 3048.0 }, + "BILLBOARD_96_SHEET" => { caption: "96 Sheet", origin: "Billboard", width_mm: 12192.0, height_mm: 3048.0 }, + "JAPANESE_JB0" => { caption: "JB0", origin: "Japanese JIS", width_mm: 1030.0, height_mm: 1456.0 }, + "JAPANESE_JB1" => { caption: "JB1", origin: "Japanese JIS", width_mm: 728.0, height_mm: 1030.0 }, + "JAPANESE_JB2" => { caption: "JB2", origin: "Japanese JIS", width_mm: 515.0, height_mm: 728.0 }, + "JAPANESE_JB3" => { caption: "JB3", origin: "Japanese JIS", width_mm: 364.0, height_mm: 515.0 }, + "JAPANESE_JB4" => { caption: "JB4", origin: "Japanese JIS", width_mm: 257.0, height_mm: 364.0 }, + "JAPANESE_JB5" => { caption: "JB5", origin: "Japanese JIS", width_mm: 182.0, height_mm: 257.0 }, + "JAPANESE_JB6" => { caption: "JB6", origin: "Japanese JIS", width_mm: 128.0, height_mm: 182.0 }, + "JAPANESE_JB7" => { caption: "JB7", origin: "Japanese JIS", width_mm: 91.0, height_mm: 128.0 }, + "JAPANESE_JB8" => { caption: "JB8", origin: "Japanese JIS", width_mm: 64.0, height_mm: 91.0 }, + "JAPANESE_JB9" => { caption: "JB9", origin: "Japanese JIS", width_mm: 45.0, height_mm: 64.0 }, + "JAPANESE_JB10" => { caption: "JB10", origin: "Japanese JIS", width_mm: 32.0, height_mm: 45.0 }, + "JAPANESE_JB11" => { caption: "JB11", origin: "Japanese JIS", width_mm: 22.0, height_mm: 32.0 }, + "JAPANESE_JB12" => { caption: "JB12", origin: "Japanese JIS", width_mm: 16.0, height_mm: 22.0 }, + "JAPANESE_SHIROKU_BAN_4" => { caption: "Shiroku ban 4", origin: "Japanese Shiroku", width_mm: 264.0, height_mm: 379.0 }, + "JAPANESE_SHIROKU_BAN_5" => { caption: "Shiroku ban 5", origin: "Japanese Shiroku", width_mm: 189.0, height_mm: 262.0 }, + "JAPANESE_SHIROKU_BAN_6" => { caption: "Shiroku ban 6", origin: "Japanese Shiroku", width_mm: 127.0, height_mm: 188.0 }, + "JAPANESE_KIKU_4" => { caption: "Kiku 4", origin: "Japanese Kiku", width_mm: 227.0, height_mm: 306.0 }, + "JAPANESE_KIKU_5" => { caption: "Kiku 5", origin: "Japanese Kiku", width_mm: 151.0, height_mm: 227.0 }, + "CANADIAN_P1" => { caption: "P1", origin: "Canadian CAN 2-9.60M", width_mm: 560.0, height_mm: 860.0 }, + "CANADIAN_P2" => { caption: "P2", origin: "Canadian CAN 2-9.60M", width_mm: 430.0, height_mm: 560.0 }, + "CANADIAN_P3" => { caption: "P3", origin: "Canadian CAN 2-9.60M", width_mm: 280.0, height_mm: 430.0 }, + "CANADIAN_P4" => { caption: "P4", origin: "Canadian CAN 2-9.60M", width_mm: 215.0, height_mm: 280.0 }, + "CANADIAN_P5" => { caption: "P5", origin: "Canadian CAN 2-9.60M", width_mm: 140.0, height_mm: 215.0 }, + "CANADIAN_P6" => { caption: "P6", origin: "Canadian CAN 2-9.60M", width_mm: 107.0, height_mm: 140.0 }, + "DIN_D0" => { caption: "DIN D0", origin: "German DIN 476", width_mm: 771.0, height_mm: 1090.0 }, + "DIN_D1" => { caption: "DIN D1", origin: "German DIN 476", width_mm: 545.0, height_mm: 771.0 }, + "DIN_D2" => { caption: "DIN D2", origin: "German DIN 476", width_mm: 385.0, height_mm: 545.0 }, + "DIN_D3" => { caption: "DIN D3", origin: "German DIN 476", width_mm: 272.0, height_mm: 385.0 }, + "DIN_D4" => { caption: "DIN D4", origin: "German DIN 476", width_mm: 192.0, height_mm: 272.0 }, + "DIN_D5" => { caption: "DIN D5", origin: "German DIN 476", width_mm: 136.0, height_mm: 192.0 }, + "DIN_D6" => { caption: "DIN D6", origin: "German DIN 476", width_mm: 96.0, height_mm: 136.0 }, + "DIN_D7" => { caption: "DIN D7", origin: "German DIN 476", width_mm: 68.0, height_mm: 96.0 }, + "DIN_D8" => { caption: "DIN D8", origin: "German DIN 476", width_mm: 48.0, height_mm: 68.0 }, + "SIS_E0" => { caption: "SIS E0", origin: "Swedish SIS 01 47 11", width_mm: 878.0, height_mm: 1242.0 }, + "SIS_E1" => { caption: "SIS E1", origin: "Swedish SIS 01 47 11", width_mm: 621.0, height_mm: 878.0 }, + "SIS_E2" => { caption: "SIS E2", origin: "Swedish SIS 01 47 11", width_mm: 439.0, height_mm: 621.0 }, + "SIS_E3" => { caption: "SIS E3", origin: "Swedish SIS 01 47 11", width_mm: 310.0, height_mm: 439.0 }, + "SIS_E4" => { caption: "SIS E4", origin: "Swedish SIS 01 47 11", width_mm: 220.0, height_mm: 310.0 }, + "SIS_E5" => { caption: "SIS E5", origin: "Swedish SIS 01 47 11", width_mm: 155.0, height_mm: 220.0 }, + "SIS_E6" => { caption: "SIS E6", origin: "Swedish SIS 01 47 11", width_mm: 110.0, height_mm: 155.0 }, + "SIS_E7" => { caption: "SIS E7", origin: "Swedish SIS 01 47 11", width_mm: 78.0, height_mm: 110.0 }, + "SIS_E8" => { caption: "SIS E8", origin: "Swedish SIS 01 47 11", width_mm: 55.0, height_mm: 78.0 }, + "SIS_E9" => { caption: "SIS E9", origin: "Swedish SIS 01 47 11", width_mm: 39.0, height_mm: 55.0 }, + "SIS_E10" => { caption: "SIS E10", origin: "Swedish SIS 01 47 11", width_mm: 27.0, height_mm: 39.0 }, + "SIS_F0" => { caption: "SIS F0", origin: "Swedish SIS 01 47 11", width_mm: 958.0, height_mm: 1354.0 }, + "SIS_F1" => { caption: "SIS F1", origin: "Swedish SIS 01 47 11", width_mm: 677.0, height_mm: 958.0 }, + "SIS_F2" => { caption: "SIS F2", origin: "Swedish SIS 01 47 11", width_mm: 479.0, height_mm: 677.0 }, + "SIS_F3" => { caption: "SIS F3", origin: "Swedish SIS 01 47 11", width_mm: 339.0, height_mm: 479.0 }, + "SIS_F4" => { caption: "SIS F4", origin: "Swedish SIS 01 47 11", width_mm: 239.0, height_mm: 339.0 }, + "SIS_F5" => { caption: "SIS F5", origin: "Swedish SIS 01 47 11", width_mm: 169.0, height_mm: 239.0 }, + "SIS_F6" => { caption: "SIS F6", origin: "Swedish SIS 01 47 11", width_mm: 120.0, height_mm: 169.0 }, + "SIS_F7" => { caption: "SIS F7", origin: "Swedish SIS 01 47 11", width_mm: 85.0, height_mm: 120.0 }, + "SIS_F8" => { caption: "SIS F8", origin: "Swedish SIS 01 47 11", width_mm: 60.0, height_mm: 85.0 }, + "SIS_F9" => { caption: "SIS F9", origin: "Swedish SIS 01 47 11", width_mm: 42.0, height_mm: 60.0 }, + "SIS_F10" => { caption: "SIS F10", origin: "Swedish SIS 01 47 11", width_mm: 30.0, height_mm: 42.0 }, + "SIS_G0" => { caption: "SIS G0", origin: "Swedish SIS 01 47 11", width_mm: 1044.0, height_mm: 1477.0 }, + "SIS_G1" => { caption: "SIS G1", origin: "Swedish SIS 01 47 11", width_mm: 738.0, height_mm: 1044.0 }, + "SIS_G2" => { caption: "SIS G2", origin: "Swedish SIS 01 47 11", width_mm: 522.0, height_mm: 738.0 }, + "SIS_G3" => { caption: "SIS G3", origin: "Swedish SIS 01 47 11", width_mm: 369.0, height_mm: 522.0 }, + "SIS_G4" => { caption: "SIS G4", origin: "Swedish SIS 01 47 11", width_mm: 261.0, height_mm: 369.0 }, + "SIS_G5" => { caption: "SIS G5", origin: "Swedish SIS 01 47 11", width_mm: 185.0, height_mm: 261.0 }, + "SIS_G6" => { caption: "SIS G6", origin: "Swedish SIS 01 47 11", width_mm: 131.0, height_mm: 185.0 }, + "SIS_G7" => { caption: "SIS G7", origin: "Swedish SIS 01 47 11", width_mm: 92.0, height_mm: 131.0 }, + "SIS_G8" => { caption: "SIS G8", origin: "Swedish SIS 01 47 11", width_mm: 65.0, height_mm: 92.0 }, + "SIS_G9" => { caption: "SIS G9", origin: "Swedish SIS 01 47 11", width_mm: 46.0, height_mm: 65.0 }, + "SIS_G10" => { caption: "SIS G10", origin: "Swedish SIS 01 47 11", width_mm: 33.0, height_mm: 46.0 }, + "SIS_D0" => { caption: "SIS D0", origin: "Swedish SIS 01 47 11", width_mm: 1091.0, height_mm: 1542.0 }, + "SIS_D1" => { caption: "SIS D1", origin: "Swedish SIS 01 47 11", width_mm: 771.0, height_mm: 1091.0 }, + "SIS_D2" => { caption: "SIS D2", origin: "Swedish SIS 01 47 11", width_mm: 545.0, height_mm: 771.0 }, + "SIS_D3" => { caption: "SIS D3", origin: "Swedish SIS 01 47 11", width_mm: 386.0, height_mm: 545.0 }, + "SIS_D4" => { caption: "SIS D4", origin: "Swedish SIS 01 47 11", width_mm: 273.0, height_mm: 386.0 }, + "SIS_D5" => { caption: "SIS D5", origin: "Swedish SIS 01 47 11", width_mm: 193.0, height_mm: 273.0 }, + "SIS_D6" => { caption: "SIS D6", origin: "Swedish SIS 01 47 11", width_mm: 136.0, height_mm: 193.0 }, + "SIS_D7" => { caption: "SIS D7", origin: "Swedish SIS 01 47 11", width_mm: 96.0, height_mm: 136.0 }, + "SIS_D8" => { caption: "SIS D8", origin: "Swedish SIS 01 47 11", width_mm: 68.0, height_mm: 96.0 }, + "SIS_D9" => { caption: "SIS D9", origin: "Swedish SIS 01 47 11", width_mm: 48.0, height_mm: 68.0 }, + "SIS_D10" => { caption: "SIS D10", origin: "Swedish SIS 01 47 11", width_mm: 34.0, height_mm: 48.0 }, + "COLOMBIAN_CARTA" => { caption: "Carta", origin: "Colombian", width_mm: 216.0, height_mm: 279.0 }, + "COLOMBIAN_EXTRA_TABLOIDE" => { caption: "Extra Tabloide", origin: "Colombian", width_mm: 304.0, height_mm: 457.2 }, + "COLOMBIAN_OFICIO" => { caption: "Oficio", origin: "Colombian", width_mm: 216.0, height_mm: 330.0 }, + "COLOMBIAN_1_8_PLIEGO" => { caption: "1/8 pliego", origin: "Colombian", width_mm: 250.0, height_mm: 350.0 }, + "COLOMBIAN_1_4_PLIEGO" => { caption: "1/4 pliego", origin: "Colombian", width_mm: 350.0, height_mm: 500.0 }, + "COLOMBIAN_1_2_PLIEGO" => { caption: "1/2 pliego", origin: "Colombian", width_mm: 500.0, height_mm: 700.0 }, + "COLOMBIAN_PLIEGO" => { caption: "Pliego", origin: "Colombian", width_mm: 700.0, height_mm: 1000.0 }, + "CHINESE_D0" => { caption: "D0", origin: "Chinese GB/T 148-1997", width_mm: 764.0, height_mm: 1064.0 }, + "CHINESE_D1" => { caption: "D1", origin: "Chinese GB/T 148-1997", width_mm: 532.0, height_mm: 760.0 }, + "CHINESE_D2" => { caption: "D2", origin: "Chinese GB/T 148-1997", width_mm: 380.0, height_mm: 528.0 }, + "CHINESE_D3" => { caption: "D3", origin: "Chinese GB/T 148-1997", width_mm: 264.0, height_mm: 376.0 }, + "CHINESE_D4" => { caption: "D4", origin: "Chinese GB/T 148-1997", width_mm: 188.0, height_mm: 260.0 }, + "CHINESE_D5" => { caption: "D5", origin: "Chinese GB/T 148-1997", width_mm: 130.0, height_mm: 184.0 }, + "CHINESE_D6" => { caption: "D6", origin: "Chinese GB/T 148-1997", width_mm: 92.0, height_mm: 126.0 }, + "CHINESE_RD0" => { caption: "RD0", origin: "Chinese GB/T 148-1997", width_mm: 787.0, height_mm: 1092.0 }, + "CHINESE_RD1" => { caption: "RD1", origin: "Chinese GB/T 148-1997", width_mm: 546.0, height_mm: 787.0 }, + "CHINESE_RD2" => { caption: "RD2", origin: "Chinese GB/T 148-1997", width_mm: 393.0, height_mm: 546.0 }, + "CHINESE_RD3" => { caption: "RD3", origin: "Chinese GB/T 148-1997", width_mm: 273.0, height_mm: 393.0 }, + "CHINESE_RD4" => { caption: "RD4", origin: "Chinese GB/T 148-1997", width_mm: 196.0, height_mm: 273.0 }, + "CHINESE_RD5" => { caption: "RD5", origin: "Chinese GB/T 148-1997", width_mm: 136.0, height_mm: 196.0 }, + "CHINESE_RD6" => { caption: "RD6", origin: "Chinese GB/T 148-1997", width_mm: 98.0, height_mm: 136.0 }, + "TRANSITIONAL_PA0" => { caption: "PA0", origin: "Transitional PA Series", width_mm: 840.0, height_mm: 1120.0 }, + "TRANSITIONAL_PA1" => { caption: "PA1", origin: "Transitional PA Series", width_mm: 560.0, height_mm: 840.0 }, + "TRANSITIONAL_PA2" => { caption: "PA2", origin: "Transitional PA Series", width_mm: 420.0, height_mm: 560.0 }, + "TRANSITIONAL_PA3" => { caption: "PA3", origin: "Transitional PA Series", width_mm: 280.0, height_mm: 420.0 }, + "TRANSITIONAL_PA4" => { caption: "PA4", origin: "Transitional PA Series", width_mm: 210.0, height_mm: 280.0 }, + "TRANSITIONAL_PA5" => { caption: "PA5", origin: "Transitional PA Series", width_mm: 140.0, height_mm: 210.0 }, + "TRANSITIONAL_PA6" => { caption: "PA6", origin: "Transitional PA Series", width_mm: 105.0, height_mm: 140.0 }, + "TRANSITIONAL_PA7" => { caption: "PA7", origin: "Transitional PA Series", width_mm: 70.0, height_mm: 105.0 }, + "TRANSITIONAL_PA8" => { caption: "PA8", origin: "Transitional PA Series", width_mm: 52.0, height_mm: 70.0 }, + "TRANSITIONAL_PA9" => { caption: "PA9", origin: "Transitional PA Series", width_mm: 35.0, height_mm: 52.0 }, + "TRANSITIONAL_PA10" => { caption: "PA10", origin: "Transitional PA Series", width_mm: 26.0, height_mm: 35.0 }, + "TRANSITIONAL_F0" => { caption: "F0", origin: "Transitional F Series", width_mm: 841.0, height_mm: 1321.0 }, + "TRANSITIONAL_F1" => { caption: "F1", origin: "Transitional F Series", width_mm: 660.0, height_mm: 841.0 }, + "TRANSITIONAL_F2" => { caption: "F2", origin: "Transitional F Series", width_mm: 420.0, height_mm: 660.0 }, + "TRANSITIONAL_F3" => { caption: "F3", origin: "Transitional F Series", width_mm: 330.0, height_mm: 420.0 }, + "TRANSITIONAL_F4" => { caption: "F4", origin: "Transitional F Series", width_mm: 210.0, height_mm: 330.0 }, + "TRANSITIONAL_F5" => { caption: "F5", origin: "Transitional F Series", width_mm: 165.0, height_mm: 210.0 }, + "TRANSITIONAL_F6" => { caption: "F6", origin: "Transitional F Series", width_mm: 105.0, height_mm: 165.0 }, + "TRANSITIONAL_F7" => { caption: "F7", origin: "Transitional F Series", width_mm: 82.0, height_mm: 105.0 }, + "TRANSITIONAL_F8" => { caption: "F8", origin: "Transitional F Series", width_mm: 52.0, height_mm: 82.0 }, + "TRANSITIONAL_F9" => { caption: "F9", origin: "Transitional F Series", width_mm: 41.0, height_mm: 52.0 }, + "TRANSITIONAL_F10" => { caption: "F10", origin: "Transitional F Series", width_mm: 26.0, height_mm: 41.0 }, + "IMPERIAL_ANTIQUARIAN" => { caption: "Antiquarian", origin: "Imperial", width_mm: 787.0, height_mm: 1346.0 }, + "IMPERIAL_ATLAS" => { caption: "Atlas", origin: "Imperial", width_mm: 660.0, height_mm: 864.0 }, + "IMPERIAL_BRIEF" => { caption: "Brief", origin: "Imperial", width_mm: 343.0, height_mm: 406.0 }, + "IMPERIAL_BROADSHEET" => { caption: "Broadsheet", origin: "Imperial", width_mm: 457.0, height_mm: 610.0 }, + "IMPERIAL_CARTRIDGE" => { caption: "Cartridge", origin: "Imperial", width_mm: 533.0, height_mm: 660.0 }, + "IMPERIAL_COLUMBIER" => { caption: "Columbier", origin: "Imperial", width_mm: 597.0, height_mm: 876.0 }, + "IMPERIAL_COPY_DRAUGHT" => { caption: "Copy Draught", origin: "Imperial", width_mm: 406.0, height_mm: 508.0 }, + "IMPERIAL_CROWN" => { caption: "Crown", origin: "Imperial", width_mm: 381.0, height_mm: 508.0 }, + "IMPERIAL_DEMY" => { caption: "Demy", origin: "Imperial", width_mm: 445.0, height_mm: 572.0 }, + "IMPERIAL_DOUBLE_DEMY" => { caption: "Double Demy", origin: "Imperial", width_mm: 572.0, height_mm: 902.0 }, + "IMPERIAL_QUAD_DEMY" => { caption: "Quad Demy", origin: "Imperial", width_mm: 889.0, height_mm: 1143.0 }, + "IMPERIAL_ELEPHANT" => { caption: "Elephant", origin: "Imperial", width_mm: 584.0, height_mm: 711.0 }, + "IMPERIAL_DOUBLE_ELEPHANT" => { caption: "Double Elephant", origin: "Imperial", width_mm: 678.0, height_mm: 1016.0 }, + "IMPERIAL_EMPEROR" => { caption: "Emperor", origin: "Imperial", width_mm: 1219.0, height_mm: 1829.0 }, + "IMPERIAL_FOOLSCAP" => { caption: "Foolscap", origin: "Imperial", width_mm: 343.0, height_mm: 432.0 }, + "IMPERIAL_SMALL_FOOLSCAP" => { caption: "Small Foolscap", origin: "Imperial", width_mm: 337.0, height_mm: 419.0 }, + "IMPERIAL_GRAND_EAGLE" => { caption: "Grand Eagle", origin: "Imperial", width_mm: 730.0, height_mm: 1067.0 }, + "IMPERIAL_IMPERIAL" => { caption: "Imperial", origin: "Imperial", width_mm: 559.0, height_mm: 762.0 }, + "IMPERIAL_MEDIUM" => { caption: "Medium", origin: "Imperial", width_mm: 470.0, height_mm: 584.0 }, + "IMPERIAL_MONARCH" => { caption: "Monarch", origin: "Imperial", width_mm: 184.0, height_mm: 267.0 }, + "IMPERIAL_POST" => { caption: "Post", origin: "Imperial", width_mm: 394.0, height_mm: 489.0 }, + "IMPERIAL_HALF_POST" => { caption: "Sheet, Half Post", origin: "Imperial", width_mm: 495.0, height_mm: 597.0 }, + "IMPERIAL_PINCHED_POST" => { caption: "Pinched Post", origin: "Imperial", width_mm: 375.0, height_mm: 470.0 }, + "IMPERIAL_LARGE_POST" => { caption: "Large Post", origin: "Imperial", width_mm: 394.0, height_mm: 508.0 }, + "IMPERIAL_DOUBLE_LARGE_POST" => { caption: "Double Large Post", origin: "Imperial", width_mm: 533.0, height_mm: 838.0 }, + "IMPERIAL_DOUBLE_POST" => { caption: "Double Post", origin: "Imperial", width_mm: 483.0, height_mm: 762.0 }, + "IMPERIAL_POTT" => { caption: "Pott", origin: "Imperial", width_mm: 318.0, height_mm: 381.0 }, + "IMPERIAL_PRINCESS" => { caption: "Princess", origin: "Imperial", width_mm: 546.0, height_mm: 711.0 }, + "IMPERIAL_QUARTO" => { caption: "Quarto", origin: "Imperial", width_mm: 229.0, height_mm: 279.0 }, + "IMPERIAL_ROYAL" => { caption: "Royal", origin: "Imperial", width_mm: 508.0, height_mm: 635.0 }, + "IMPERIAL_SUPER_ROYAL" => { caption: "Super Royal", origin: "Imperial", width_mm: 483.0, height_mm: 686.0 }, + "FRENCH_CLOCHE" => { caption: "Cloche", origin: "French", width_mm: 300.0, height_mm: 400.0 }, + "FRENCH_POT_ECOLIER" => { caption: "Pot, écolier", origin: "French", width_mm: 310.0, height_mm: 400.0 }, + "FRENCH_TELLIERE" => { caption: "Tellière", origin: "French", width_mm: 340.0, height_mm: 440.0 }, + "FRENCH_COURONNE_ECRITURE" => { caption: "Couronne écriture", origin: "French", width_mm: 360.0, height_mm: 360.0 }, + "FRENCH_COURONNE_EDITION" => { caption: "Couronne édition", origin: "French", width_mm: 370.0, height_mm: 470.0 }, + "FRENCH_ROBERTO" => { caption: "Roberto", origin: "French", width_mm: 390.0, height_mm: 500.0 }, + "FRENCH_ECU" => { caption: "Écu", origin: "French", width_mm: 400.0, height_mm: 520.0 }, + "FRENCH_COQUILLE" => { caption: "Coquille", origin: "French", width_mm: 440.0, height_mm: 560.0 }, + "FRENCH_CARRE" => { caption: "Carré", origin: "French", width_mm: 450.0, height_mm: 560.0 }, + "FRENCH_CAVALIER" => { caption: "Cavalier", origin: "French", width_mm: 460.0, height_mm: 620.0 }, + "FRENCH_DEMI_RAISIN" => { caption: "Demi-raisin", origin: "French", width_mm: 325.0, height_mm: 500.0 }, + "FRENCH_RAISIN" => { caption: "Raisin", origin: "French", width_mm: 500.0, height_mm: 650.0 }, + "FRENCH_DOUBLE_RAISIN" => { caption: "Double Raisin", origin: "French", width_mm: 650.0, height_mm: 1000.0 }, + "FRENCH_JESUS" => { caption: "Jésus", origin: "French", width_mm: 560.0, height_mm: 760.0 }, + "FRENCH_SOLEIL" => { caption: "Soleil", origin: "French", width_mm: 600.0, height_mm: 800.0 }, + "FRENCH_COLOMBIER_AFFICHE" => { caption: "Colombier affiche", origin: "French", width_mm: 600.0, height_mm: 800.0 }, + "FRENCH_COLOMBIER_COMMERCIAL" => { caption: "Colombier commercial", origin: "French", width_mm: 630.0, height_mm: 900.0 }, + "FRENCH_PETIT_AIGLE" => { caption: "Petit Aigle", origin: "French", width_mm: 700.0, height_mm: 940.0 }, + "FRENCH_GRAND_AIGLE" => { caption: "Grand Aigle", origin: "French", width_mm: 750.0, height_mm: 1050.0 }, + "FRENCH_GRAND_MONDE" => { caption: "Grand Monde", origin: "French", width_mm: 900.0, height_mm: 1260.0 }, + "FRENCH_UNIVERS" => { caption: "Univers", origin: "French", width_mm: 1000.0, height_mm: 1130.0 }, + "RUSSIAN_60X84_8" => { caption: "60x84/8", origin: "Russian GOST 5773-90", width_mm: 205.0, height_mm: 290.0 }, + "RUSSIAN_60X84_16" => { caption: "60x84/16", origin: "Russian GOST 5773-90", width_mm: 145.0, height_mm: 200.0 }, + "RUSSIAN_60X84_32" => { caption: "60x84/32", origin: "Russian GOST 5773-90", width_mm: 100.0, height_mm: 140.0 }, + "RUSSIAN_60X90_8" => { caption: "60x90/8", origin: "Russian GOST 5773-90", width_mm: 220.0, height_mm: 290.0 }, + "RUSSIAN_60X90_16" => { caption: "60x90/16", origin: "Russian GOST 5773-90", width_mm: 145.0, height_mm: 215.0 }, + "RUSSIAN_70X100_16" => { caption: "70x100/16", origin: "Russian GOST 5773-90", width_mm: 170.0, height_mm: 240.0 }, + "RUSSIAN_70X100_32" => { caption: "70x100/32", origin: "Russian GOST 5773-90", width_mm: 120.0, height_mm: 165.0 }, + "RUSSIAN_70X108_8" => { caption: "70x108/8", origin: "Russian GOST 5773-90", width_mm: 265.0, height_mm: 340.0 }, + "RUSSIAN_70X108_16" => { caption: "70x108/16", origin: "Russian GOST 5773-90", width_mm: 170.0, height_mm: 260.0 }, + "RUSSIAN_70X108_32" => { caption: "70x108/32", origin: "Russian GOST 5773-90", width_mm: 130.0, height_mm: 165.0 }, + "RUSSIAN_70X90_16" => { caption: "70x90/16", origin: "Russian GOST 5773-90", width_mm: 170.0, height_mm: 215.0 }, + "RUSSIAN_70X90_32" => { caption: "70x90/32", origin: "Russian GOST 5773-90", width_mm: 107.0, height_mm: 165.0 }, + "RUSSIAN_75X90_32" => { caption: "75x90/32", origin: "Russian GOST 5773-90", width_mm: 107.0, height_mm: 177.0 }, + "RUSSIAN_84X108_8" => { caption: "84x108/16", origin: "Russian GOST 5773-90", width_mm: 205.0, height_mm: 260.0 }, + "RUSSIAN_84X108_32" => { caption: "84x108/32", origin: "Russian GOST 5773-90", width_mm: 130.0, height_mm: 200.0 }, + }.freeze + end + end + end +end diff --git a/lib/brst/binding/ruby/unicode_glyph.rb b/lib/brst/binding/ruby/unicode_glyph.rb new file mode 100644 index 0000000..6d699f4 --- /dev/null +++ b/lib/brst/binding/ruby/unicode_glyph.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module UnicodeGlyph + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_UnicodeToGlyphName, [:uint16], :string + safe_attach :BRST_GlyphNameToUnicode, [:string], :uint16 + end + end + end +end diff --git a/lib/brst/binding/ruby/version.rb b/lib/brst/binding/ruby/version.rb new file mode 100644 index 0000000..9624c86 --- /dev/null +++ b/lib/brst/binding/ruby/version.rb @@ -0,0 +1,7 @@ +module Brst + module Binding + module Ruby + VERSION = "0.1.0" + end + end +end diff --git a/lib/brst/binding/ruby/xobject.rb b/lib/brst/binding/ruby/xobject.rb new file mode 100644 index 0000000..2f01fa7 --- /dev/null +++ b/lib/brst/binding/ruby/xobject.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +# +# AUTO-GENERATED by brst-binding-ruby's generator (generator/bin/brst-binding-ruby-gen). +# Source of truth: libBeresta gen/data/*.lsp (S-expression definitions). +# DO NOT EDIT BY HAND. Re-generate with `rake generate`. + +require "ffi" +require_relative "library" +require_relative "types" + +module Brst + module Binding + module Ruby + module Xobject + extend FFI::Library + ffi_lib Brst::Binding::Ruby::Library.lib_path + + Brst::Binding::Ruby::Types.apply(self) + + MISSING_SYMBOLS = [] + + # Wraps `attach_function` so that captions whose actual C symbol + # is missing from the loaded libBeresta build (e.g. caption / + # symbol drift in upstream .lsp data, or features compiled + # out) — or whose declared parameter types reference a struct + # / enum the .lsp data never declared — don't break the entire + # gem load. Each miss is recorded in MISSING_SYMBOLS for + # diagnostic surfaces. + def self.safe_attach(name, args, ret) + attach_function(name, args, ret) + rescue FFI::NotFoundError, TypeError => e + MISSING_SYMBOLS << [name, e.message] + end + + safe_attach :BRST_XObject_Stream, [:XObject], :Stream + end + end + end +end diff --git a/spec/cross_check_spec.rb b/spec/cross_check_spec.rb new file mode 100644 index 0000000..9586c5a --- /dev/null +++ b/spec/cross_check_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require "spec_helper" +require "json" + +# Structural cross-check: our S-expression parser must produce the same +# function / enum / pointer / definition / struct counts as libBeresta's +# auto-generated JSON view of the same .lsp data (`gen/json/*.json`, +# emitted by ECL+Djula). The JSON form is a derived artifact — we don't +# *depend* on it (Source of Truth is .lsp), but for v0.1.0 sanity it is a +# useful structural check to ensure our parser hasn't dropped or duplicated +# any top-level entity. +# +# Skipped automatically when libBeresta is not cloned at ../libBeresta. +RSpec.describe "structural cross-check vs gen/json" do + let(:data_dir) { File.expand_path("../../libBeresta/gen/data", __dir__) } + let(:json_dir) { File.expand_path("../../libBeresta/gen/json", __dir__) } + + before do + skip "libBeresta sibling clone not present" unless Dir.exist?(data_dir) && Dir.exist?(json_dir) + require_relative "../generator/lib/brst_binding_ruby_gen" + end + + it "matches function/enum/pointer/struct counts per file" do + diffs = [] + + Dir.glob(File.join(json_dir, "*.json")).sort.each do |jpath| + base = File.basename(jpath, ".json") + lpath = File.join(data_dir, "#{base}.lsp") + next unless File.exist?(lpath) + + json_tree = JSON.parse(File.read(jpath)) + lsp_tree = BrstBindingRubyGen::SexpParser.parse_file(lpath) + + %w[functions enums pointers definitions structs consts sizes].each do |key| + json_count = (json_tree[key] || []).size + lsp_count = (Array(lsp_tree[key.to_sym])).size + if json_count != lsp_count + diffs << "#{base}.#{key}: json=#{json_count} lsp_parser=#{lsp_count}" + end + end + end + + expect(diffs).to be_empty, "mismatched counts:\n #{diffs.join("\n ")}" + end +end diff --git a/spec/smoke/minimal_spec.rb b/spec/smoke/minimal_spec.rb new file mode 100644 index 0000000..f77cd23 --- /dev/null +++ b/spec/smoke/minimal_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require "spec_helper" +require "fileutils" +require "tmpdir" + +# Smoke test mirroring libBeresta's demo/minimal.c. Verifies that: +# 1. The gem loads its generated FFI bindings. +# 2. The libBeresta shared library can be opened. +# 3. A trivial PDF round-trip (Doc_New -> Page_Add -> SetSize -> SaveToFile) +# produces a non-empty PDF on disk. +# +# Skipped automatically when libBeresta has not been built locally; CI is +# responsible for building before running specs. +RSpec.describe "smoke: minimal PDF generation" do + before(:all) do + begin + require "brst/binding/ruby" + rescue LoadError, FFI::NotFoundError, RuntimeError => e + skip "brst-binding-ruby could not load libBeresta: #{e.message}" + end + end + + let(:tmp_pdf) do + File.join(Dir.mktmpdir("brst-binding-ruby-smoke"), "test.pdf") + end + + it "writes 'Hello, Beresta from Ruby!' to an A4 portrait page" do + base = Brst::Binding::Ruby::Base + doc_page = Brst::Binding::Ruby::DocPage + page_routines = Brst::Binding::Ruby::PageRoutines + doc_save = Brst::Binding::Ruby::DocSave + doc_font = Brst::Binding::Ruby::DocFont + text = Brst::Binding::Ruby::Text + + pdf = base.BRST_Doc_New(nil, nil) + expect(pdf).not_to be_null + + begin + page = doc_page.BRST_Doc_Page_Add(pdf) + page_routines.BRST_Page_SetSize(page, :A4, :PAGE_ORIENTATION_PORTRAIT) + + font = doc_font.BRST_Doc_Font(pdf, "Helvetica", nil) + expect(font).not_to be_null + + text.BRST_Page_BeginText(page) + text.BRST_Page_SetFontAndSize(page, font, 20.0) + text.BRST_Page_MoveTextPos(page, 50.0, 750.0) + text.BRST_Page_ShowText(page, "Hello, Beresta from Ruby!") + text.BRST_Page_EndText(page) + + status = doc_save.BRST_Doc_SaveToFile(pdf, tmp_pdf) + expect(status).to eq(0) + ensure + base.BRST_Doc_Free(pdf) + end + + expect(File.size(tmp_pdf)).to be > 100 + expect(File.read(tmp_pdf, 4)).to eq("%PDF") + end + + it "generates a non-empty A4-landscape PDF (port of demo/minimal.c)" do + base = Brst::Binding::Ruby::Base + doc_page = Brst::Binding::Ruby::DocPage + page_routines = Brst::Binding::Ruby::PageRoutines + doc_save = Brst::Binding::Ruby::DocSave + + pdf = base.BRST_Doc_New(nil, nil) + expect(pdf).not_to be_null + + begin + page = doc_page.BRST_Doc_Page_Add(pdf) + expect(page).not_to be_null + + status = page_routines.BRST_Page_SetSize(page, :A4, :PAGE_ORIENTATION_LANDSCAPE) + expect(status).to eq(0) + + status = doc_save.BRST_Doc_SaveToFile(pdf, tmp_pdf) + expect(status).to eq(0) + ensure + base.BRST_Doc_Free(pdf) + end + + expect(File).to exist(tmp_pdf) + expect(File.size(tmp_pdf)).to be > 100 + expect(File.read(tmp_pdf, 4)).to eq("%PDF") + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..8501f3a --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "fileutils" +require "tmpdir" + +# Make sure the gem is loadable before the smoke test loads any FFI module — +# but allow the smoke test itself to skip gracefully when libBeresta is not +# built locally. +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) + +RSpec.configure do |config| + config.example_status_persistence_file_path = ".rspec_status" + config.disable_monkey_patching! + config.expect_with :rspec do |c| + c.syntax = :expect + end +end