Home

Awesome

lua-resty-haru

LuaJIT FFI Bindings to Haru – Free PDF Library. This library is almost done as you can see on TODO. Some missing API bindings will be added shortly, or on request.

Requirements

Synopsis

-- Some local variable declarations
local dump     = require "pl.pretty".dump
local haru     = require "resty.haru"
local hpdf     = haru.new()
local print    = print
local pages    = hpdf.pages
local fonts    = hpdf.fonts
local images   = hpdf.images
local encoders = hpdf.encoders

-- General Settings
hpdf:use "utfencodings"
hpdf:use "jpencodings"
hpdf:use "krencodings"
hpdf:use "cnsencodings"
hpdf:use "cntencodings"
hpdf:use "jpfonts"
hpdf:use "krfonts"
hpdf:use "cnsfonts"
hpdf:use "cntfonts"

-- Setting General Properties
hpdf.encoding         = "UTF-8"
hpdf.pagelayout       = "single"
hpdf.pagemode         = "outline"
hpdf.author           = "@bungle"
hpdf.creator          = "lua-resty-haru"
hpdf.title            = "Demo"
hpdf.subject          = "Testing FFI Bindings"
hpdf.keywords         = "openresty pdf haru lua luajit ffi"
hpdf.creationdate     = { 2015, 1, 1, 12, 0, 0, '+', 2, 0 }
hpdf.modificationdate = {
    year        = 2015,
    month       = 1,
    day         = 1,
    hour        = 12,
    minutes     = 0,
    seconds     = 0,
    ind         = "+",
    off_hour    = 2,
    off_minutes = 0
}

-- General Properties
print(hpdf.pagelayout)
print(hpdf.pagemode)
print(hpdf.author)
print(hpdf.creator)
print(hpdf.title)
print(hpdf.subject)
print(hpdf.keywords)
print(hpdf.creationdate)
print(hpdf.modificationdate)

-- Loading a Font
local helvetica = fonts:get "Helvetica"

-- Font Properties
print(helvetica.name)
print(helvetica.encoding)
print(helvetica.ascent)
print(helvetica.descent)
print(helvetica.xheight)
print(helvetica.capheight)
 dump(helvetica.bbox)

-- Loading a TTF Font
local name = fonts:load("DejaVuSans.ttf", true)
print(name)
local dejavu = fonts:get(name, "UTF-8")

-- Font Properties
print(dejavu.name)
print(dejavu.encoding)
print(dejavu.ascent)
print(dejavu.descent)
print(dejavu.xheight)
print(dejavu.capheight)
 dump(dejavu.bbox)

-- Current Encoder
local encoder = hpdf.encoder

-- Encoder Properties
print(encoder.type)
print(encoder.writingmode)

-- Getting an Encoder
local gbeuch = encoders:get "GB-EUC-H"

-- Encoder Properties
print(gbeuch.type)
print(gbeuch.writingmode)

-- Adding a Page
local page = pages:add()

-- Page Properties
print(page.width)
print(page.height)
print(page.grayfill)
print(page.graystroke)
print(page.charspace)
print(page.wordspace)
print(page.horizontalscaling)
print(page.textleading)
print(page.textrise)
print(page.textrenderingmode)
print(page.fontsize)
print(page.linewidth)
print(page.linecap)
print(page.linejoin)
print(page.flatness)
print(page.gmode)
print(page.gdepth)
print(page.strokingcolorspace)
print(page.fillingcolorspace)
 dump(page.rgbfill)
 dump(page.rgbstroke)
 dump(page.cmykfill)
 dump(page.cmykstroke)
 dump(page.textmatrix)
 dump(page.transmatrix)
 dump(page.dash)

local x, y = page:pos()
print(x, y)

local x, y = page:textpos()
print(x, y)

-- Setting Page Properties
page.width             = page.height
page.height            = page.width
page.grayfill          = page.grayfill
page.graystroke        = page.graystroke
page.charspace         = page.charspace
page.wordspace         = page.wordspace
page.horizontalscaling = page.horizontalscaling
page.textleading       = page.textleading
page.textrise          = page.textrise
page.textrenderingmode = page.textrenderingmode
page.linewidth         = page.linewidth
page.miterlimit        = page.miterlimit
page.linecap           = page.linecap
page.linejoin          = page.linejoin
page.rgbfill           = page.rgbfill
page.rgbstroke         = page.rgbstroke
page.cmykfill          = page.cmykfill
page.cmykstroke        = page.cmykstroke
page.dash              = page.dash
page.rotate            = 90

-- Setting Page Size
page:size("a4", "landscape")

-- Inserting a new Page before existing
page = pages:insert(page)

-- Setting a Font
page:font(dejavu, 18)

-- Getting Current Font
local font = page:font()

print(font.name)
print(font.encoding)
print(font.ascent)
print(font.descent)
print(font.xheight)
print(font.capheight)
 dump(font.bbox)

-- Writing Text
page:begintext()
page.textmatrix = page.textmatrix
page:text(50, 400, "Hello")
page:text(0, 400, 150, 200, "World", "right")
page:textmove(100, 300)
page:text "Testing"
page:ln()
page:text "... it works - How about UTF-8 ÄÖÅäöå€!"
page:text("Hey, I'm on a new line!", true)
page:endtext()

-- Writing Text (alternative)
page:begintext()
page.textmatrix = page.textmatrix
page:textout(50, 450, "Hello")
page:textrect(0, 450, 150, 200, "World", "right")
page:textmove(100, 150)
page:textshow "Testing"
page:textshow "... it works!"
page:textshow("Hey, I'm on a new line!", true)
page:endtext()

-- Measuring Text
print(page:textwidth("hello"))

-- Drawing Shapes
page:circle(100, 100, 50)
page:rectangle(150, 150, 100, 100)
page:ellipse(300, 300, 75, 50)
page:stroke()

-- Drawing Arcs
page:arc(400, 400, 50, 180, 360)
page:stroke()

-- Drawing Lines
page.linewidth = 10
page.linecap = "round"
page:move(200, 300)
page:line(400, 300)
page:closepathstroke()

-- Drawing Dashed Lines
page.linewidth = 2
page.linecap = "butt"
page.dash = {
    pattern = { 8, 7, 2, 7 },
    phase   = 0,
    n       = 4
}
page:move(200, 600)
page:line(400, 600)
page:closepathstroke()

-- Drawing Curves
page.linewidth = 10
page.linecap = "round"
page.dash = nil
page:move(200, 300)
page:curve(400, 300, 500, 550, 400, 300)
page:stroke()

-- Loading a Image
local logo = images:load "logo.png"

-- Image Properties
print(logo.width)
print(logo.height)
print(logo.colorspace)
print(logo.bitspercomponent)
 dump(logo.size)

-- Setting Image Properties
logo.colormask = {
    rmin = 50,
    rmax = 150,
    gmin = 50,
    gmax = 150,
    bmin = 50,
    bmax = 150
}

-- Drawing Image
page:image(logo, 450, 450, 100, 100)

-- Creating a Destination
local dest = page:destination();

-- Destination Properties
dest.xyz = { 10, 20, 10 }
dest.xyz = {
    left = 10,
    top  = 20,
    zoom = 10
}

-- Calling Destination Methods
dest:fit()
dest:fitb()
dest:fith(20)
dest:fitbh(20)
dest:fitbv(20)
dest:fitv(10)
dest:fitr(10, 20, 10, 20)

-- Creating Outline
local outline = hpdf:outline(nil, "Outline")

-- Setting Outline Properties
outline.destination = dest
outline.opened      = true

-- Creating Annotation
local annotation = page:textannotation(10, 600, 200, 500, "Test Annotation")

-- Setting Annotation Properties
annotation.opened = true
annotation.icon   = "help"

-- Setting Encryption and Permission
hpdf.password    = {
    owner = "owner",
    user  = "user"
}
hpdf.encryption  = "r3"
hpdf.permission  = "read"
hpdf.compression = "all"

-- Setting Page Labels
hpdf:pagelabel(0, "upperroman", 1, "");

-- Saving PDF
hpdf:save "demo.pdf"

TODO

The most of the bindings are implemented, but there are a few that are still work in progress.

Basic Functions
Pages Handling
Font Handling
Other Functions
Page
Graphics
Fonts
Encodings
Annotations
Image

License

lua-resty-haru uses two clause BSD license.

Copyright (c) 2016, Aapo Talvensaari
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.