Ipelib
Lua bindings for Document, Page, and StyleSheet

Stylesheet

A stylesheet can be constructed by reading from a file (in XML format), or by creating an empty stylesheet:

-- create from file:
-- returns sheet or nil, error message
sheet = ipe.Sheet("filename")
-- create from XML data:
-- returns sheet or nil, error message
sheet = ipe.Sheet(nil, "<ipestyle> ... </ipestyle>")
-- create empty stylesheet:
sheet = ipe.Sheet()    

Stylesheets have the following methods:

sheet:clone()            -- returns a private copy of the stylesheet
sheet:xml(with_bitmaps)  -- return XML representation 
sheet:add(kind, symbolic, value)
sheet:addFrom(other_sheet, kind, symbolic)
sheet:remove(kind, symbolic)                       
sheet:set(kind, value)
sheet:isStandard()      -- is this the built-in stylesheet?
sheet:name()            -- name of the stylesheet
sheet:setName(name)

sheet:add adds a definition for symbolic name to the stylesheet. Permissible values for kind are:

 pen, symbolsize, arrowsize, color, dashstyle, textsize, textstretch, 
 textstyle, gridsize, anglesize, opacity, symbol, 

sheet:addFrom copies a definition for a gradient, tiling, or effect from another stylesheet. This makes it possible to create such definitions by creating a temporary stylesheet from an XML string.

sheet:remove removes the definition of a symbolic name from the stylesheet. This also works for symbols, gradients, tilings, and effects. It is permissible to remove a symbolic name that is not defined in the stylesheet.

sheet:set sets a value. Permissible values for kind are:

 preamble, linecap, linejoin, fillrule

Stylesheet cascade

Documents own an entire stack of style sheets, the style sheet cascade. An empty style sheet cascade can be created like this:

sheets = ipe.Sheets()

or you can obtain one from an Ipe document.

Style sheet cascades have the following methods:

sheets1 = sheets:clone()              -- make a private copy
sheets:allNames(kind)
sheets:find(kind, symbolic)
sheets:has(kind, symbolic)
sheets:count()                        -- return number of sheets
sheets:sheet(index)                   -- return sheet at index
sheets:insert(index, style_sheet)     -- insert sheet at index
sheets:remove(index)                  -- delete a sheet
log = sheets:update(directory)        -- update style sheets from directory

sheets:allNames returns a table with all symbolic names defined in the entire stylesheet cascade. Permissible values for kind are:

 pen, symbolsize, arrowsize, color, dashstyle, textsize, textstretch, 
 textstyle, gridsize, anglesize, opacity, tiling, symbol, gradient, effect

sheet:has checks whether a symbolic name is defined in the cascade. Permissible values for kind are as for allNames.

sheet:find looks up a symbolic definition. Permissible values for kind are:

 pen, symbolsize, arrowsize, color, dashstyle, textsize, textstretch, 
 textstyle, gridsize, anglesize, opacity, symbol, 
 preamble, linecap, linejoin, fillrule, layout

Page

Page objects can be created like this:

p = ipe.Page()   -- create basic page with one layer and one view
p1 = p:clone()   -- returns a copy of the page

The following methods act on the views of a page. Note that views are indexed starting from 1, as usual in Lua.

p:countViews() 
p:effect(view)
p:setEffect(view, effect)
p:active(view)
p:setActive(view, layer)
p:insertView(view, layer)
p:removeView(view)
p:clearViews()
f = p:viewMarked(view) -- return true/false
p:setViewMarked(view, f)
name = p:viewName(view)
p:setViewName(view, name)
map = p:viewMap(view)
p:setViewMap(view, map)
lm = p:layerMatrices(view)
p:setLayerMatrices(view, lm)

The following methods act on the layers of a page. Note that layers are always accessed by name, not by index as in C++.

p:countLayers()
p:layers()        -- return table of layer names
p:isLocked(layer)
p:setLocked(layer, boolean)
p:layerData(layer)    -- free-use text for that layer
p:setLayerData(layer, data)
p:hasSnapping(layer)
p:setSnapping(layer)
p:renameLayer(oldname, newname)
-- if layer is nil, automatically create name for new layer:
p:addLayer(layer)     -- add layer at the end, return name of new layer
p:removeLayer(layer)
p:moveLayer(layer, target_index)
p:visible(view, layer)   -- is layer visible in view?
p:setVisible(view, layer, boolean)

The objects of a page can be accessed by indexing, using an iterator, or with various methods. Note that object indices start with 1, as usual in Lua.

-- objects:

#p      -- return number of objects on page
p[i]    -- return object #i, where 1 <= i <= #p

-- iterate over objects of page:
for i, obj, sel, layer in p:objects() do
  print(i, obj, sel, layer)
end

p:select(objno)              -- returns nil, 1, or 2
p:setSelect(objno, status)   -- status is nil, 1, or 2
p:layerOf(objno)
p:setLayerOf(objno, layer)
p:visible(view, objno)       -- is object visible in view?
p:bbox(objno)                -- cached by page
p:invalidateBBox(objno)      -- invalidate cached bbox
p:insert(objno, object, select, layer)  -- objno == nil means append
p:remove(objno)
p:replace(objno, object)     -- automatically clones object
p:transform(objno, matrix)

-- returns distance from pos if it is less than bound
p:distance(objno, pos, bound)

-- returns true if attribute was actually changed
p:setAttribute(objno, property, value)

Finally, there are various methods to query and modify the currently selected objects, the page title and sections, etc.:

-- selection:
obj = p:primarySelection() -- nil if no primary selection
p:hasSelection()           -- true or false
p:deselectAll()
p:ensurePrimarySelection()

-- t is a table with fields "title", "section", "subsection"
-- if section or subsection is not a string, the title is used 
t = p:titles()  
p:setTitles(t)

-- n is a string
n = p:notes()
p:setNotes(n)

-- f is true/false
f = p:marked()
p:setMarked(f)

Document

Documents have the following methods:

doc = ipe.Document()         -- empty document
doc = ipe.Document(filename) -- load from file 
-- returns either document or nil, error message, error code

#doc    -- number of pages
doc[i]  -- return page #i, where 1 <= i <= #doc

-- format == nil: guess from filename
-- flags is either nil, or a table with keys
-- "export", "nozip", "lastview", "nocolor"
doc:save(filename, format, flags)  
doc:exportPages(filename, flags, fromPage, toPage)
doc:exportView(filename, format, flags, pageNo, viewNo)

-- iterating over pages of document:
for i, p in doc:pages() do
  print("Page number",  i, p)
end

doc:set(no, page)         -- replace with a clone of page, returns old page
doc:insert(no, page)
doc:append(page)
doc:remove(no)            -- returns page and removes from document
doc:countTotalViews()
doc:sheets()              -- returns style sheet cascade
old = doc:replaceSheets(sheets)  -- replace and return old cascade
doc:has(what)  -- where what in { "truetype", "gradients", "tilings", "transparency" }
doc:runLatex(docname)     -- pass filename of Ipe document or nil
-- returns either true, nil, result code, logfile
--         or     false, error message, result code, logfile

doc:fontPool()    -- returns light userdata
doc:checkStyle()  -- returns list of undefined symbolic names
t = doc:properties()  -- returns table
doc:setProperties(t)  -- changes properties set in table

doc:properties() returns a table with the following fields (all fields exist even if their contents is an empty string):

title author subject keywords language preamble created modified creator
fullscreen cropbox numberpages sequentialtext tex

Other functions

ipe.fileFormat(filename)      -- returns one of "xml", "pdf", "eps", "ipe5", "unknown"
ipe.fileExists(filename)      -- returns true or false
ipe.realPath(filename)        -- convert relative path to absolute path
ipe.directory(path)           -- return list of files in directory
ipe.openFile(path, mode)      -- replacement for io.open
beziers = ipe.splineToBeziers(spline, is_closed, old_style)
ipelet = ipe.Ipelet(dllname)  -- loads C++ ipelet from absolute path
-- returns ipelet or nil, error message