summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/cld/cld-backendcode.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/context/sources/general/manuals/cld/cld-backendcode.tex')
-rw-r--r--doc/context/sources/general/manuals/cld/cld-backendcode.tex388
1 files changed, 388 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/cld/cld-backendcode.tex b/doc/context/sources/general/manuals/cld/cld-backendcode.tex
new file mode 100644
index 000000000..9c1284baa
--- /dev/null
+++ b/doc/context/sources/general/manuals/cld/cld-backendcode.tex
@@ -0,0 +1,388 @@
+% language=uk
+
+\startcomponent cld-backendcode
+
+\environment cld-environment
+
+% derived from hybrid
+
+\startchapter[title={Backend code}]
+
+\startsection [title={Introduction}]
+
+In \CONTEXT\ we've always separated the backend code in so called driver files.
+This means that in the code related to typesetting only calls to the \API\ take
+place, and no backend specific code is to be used. Currently a \PDF\ backend is
+supported as well as an \XML\ export. \footnote {This chapter is derived from an
+article on these matters. You can find nore information in \type {hybrid.pdf}.}
+
+Some \CONTEXT\ users like to add their own \PDF\ specific code to their styles or
+modules. However, such extensions can interfere with existing code, especially
+when resources are involved. Therefore the construction of \PDF\ data structures
+and resources is rather controlled and has to be done via the official helper
+macros.
+
+\stopsection
+
+\startsection [title={Structure}]
+
+A \PDF\ file is a tree of indirect objects. Each object has a number and the file
+contains a table (or multiple tables) that relates these numbers to positions in
+a file (or position in a compressed object stream). That way a file can be viewed
+without reading all data: a viewer only loads what is needed.
+
+\starttyping
+1 0 obj <<
+ /Name (test) /Address 2 0 R
+>>
+2 0 obj [
+ (Main Street) (24) (postal code) (MyPlace)
+]
+\stoptyping
+
+For the sake of the discussion we consider strings like \type {(test)} also to be
+objects. In the next table we list what we can encounter in a \PDF\ file. There
+can be indirect objects in which case a reference is used (\type{2 0 R}) and
+direct ones.
+
+It all starts in the document's root object. From there we access the page tree
+and resources. Each page carries its own resource information which makes random
+access easier. A page has a page stream and there we find the to be rendered
+content as a mixture of (\UNICODE) strings and special drawing and rendering
+operators. Here we will not discuss them as they are mostly generated by the
+engine itself or dedicated subsystems like the \METAPOST\ converter. There we use
+literal or \type {\latelua} whatsits to inject code into the current stream.
+
+\stopsection
+
+\startsection [title={Data types}]
+
+There are several datatypes in \PDF\ and we support all of them one way or the
+other.
+
+\starttabulate[|l|l|p|]
+\FL
+\NC \bf type \NC \bf form \NC \bf meaning \NC \NR
+\TL
+\NC constant \NC \type{/...} \NC A symbol (prescribed string). \NC \NR
+\NC string \NC \type{(...)} \NC A sequence of characters in pdfdoc
+ encoding \NC \NR
+\NC unicode \NC \type{<...>} \NC A sequence of characters in utf16
+ encoding \NC \NR
+\NC number \NC \type{3.1415} \NC A number constant. \NC \NR
+\NC boolean \NC \type{true/false} \NC A boolean constant. \NC \NR
+\NC reference \NC \type{N 0 R} \NC A reference to an object \NC \NR
+\NC dictionary \NC \type{<< ... >>} \NC A collection of key value pairs
+ where the value itself is an (indirect) object.
+ \NC \NR
+\NC array \NC \type{[ ... ]} \NC A list of objects or references to
+ objects. \NC \NR
+\NC stream \NC \NC A sequence of bytes either or not packaged with
+ a dictionary that contains descriptive data. \NC \NR
+\NC xform \NC \NC A special kind of object containing an reusable
+ blob of data, for example an image. \NC \NR
+\LL
+\stoptabulate
+
+While writing additional backend code, we mostly create dictionaries.
+
+\starttyping
+<< /Name (test) /Address 2 0 R >>
+\stoptyping
+
+In this case the indirect object can look like:
+
+\starttyping
+[ (Main Street) (24) (postal code) (MyPlace) ]
+\stoptyping
+
+The \LUATEX\ manual mentions primitives like \type {\pdfobj}, \type {\pdfannot},
+\type {\pdfcatalog}, etc. However, in \MKIV\ no such primitives are used. You can
+still use many of them but those that push data into document or page related
+resources are overloaded to do nothing at all.
+
+In the \LUA\ backend code you will find function calls like:
+
+\starttyping
+local d = lpdf.dictionary {
+ Name = lpdf.string("test"),
+ Address = lpdf.array {
+ "Main Street", "24", "postal code", "MyPlace",
+ }
+}
+\stoptyping
+
+Equaly valid is:
+
+\starttyping
+local d = lpdf.dictionary()
+d.Name = "test"
+\stoptyping
+
+Eventually the object will end up in the file using calls like:
+
+\starttyping
+local r = lpdf.immediateobject(tostring(d))
+\stoptyping
+
+or using the wrapper (which permits tracing):
+
+\starttyping
+local r = lpdf.flushobject(d)
+\stoptyping
+
+The object content will be serialized according to the formal specification so
+the proper \type {<< >>} etc.\ are added. If you want the content instead you can
+use a function call:
+
+\starttyping
+local dict = d()
+\stoptyping
+
+An example of using references is:
+
+\starttyping
+local a = lpdf.array {
+ "Main Street", "24", "postal code", "MyPlace",
+}
+local d = lpdf.dictionary {
+ Name = lpdf.string("test"),
+ Address = lpdf.reference(a),
+}
+local r = lpdf.flushobject(d)
+\stoptyping
+
+\stopsection
+
+We have the following creators. Their arguments are optional.
+
+\starttabulate[|l|p|]
+\FL
+\NC \bf function \NC \bf optional parameter \NC \NR
+\TL
+\NC \type{lpdf.null} \NC \NC \NR
+\NC \type{lpdf.number} \NC number \NC \NR
+\NC \type{lpdf.constant} \NC string \NC \NR
+\NC \type{lpdf.string} \NC string \NC \NR
+\NC \type{lpdf.unicode} \NC string \NC \NR
+\NC \type{lpdf.boolean} \NC boolean \NC \NR
+\NC \type{lpdf.array} \NC indexed table of objects \NC \NR
+\NC \type{lpdf.dictionary} \NC hash with key/values \NC \NR
+%NC \type{lpdf.stream} \NC indexed table of operators \NC \NR
+\NC \type{lpdf.reference} \NC string \NC \NR
+\NC \type{lpdf.verbose} \NC indexed table of strings \NC \NR
+\LL
+\stoptabulate
+
+\ShowLuaExampleString{tostring(lpdf.null())}
+\ShowLuaExampleString{tostring(lpdf.number(123))}
+\ShowLuaExampleString{tostring(lpdf.constant("whatever"))}
+\ShowLuaExampleString{tostring(lpdf.string("just a string"))}
+\ShowLuaExampleString{tostring(lpdf.unicode("just a string"))}
+\ShowLuaExampleString{tostring(lpdf.boolean(true))}
+\ShowLuaExampleString{tostring(lpdf.array { 1, lpdf.constant("c"), true, "str" })}
+\ShowLuaExampleString{tostring(lpdf.dictionary { a=1, b=lpdf.constant("c"), d=true, e="str" })}
+%ShowLuaExampleString{tostring(lpdf.stream("whatever"))}
+\ShowLuaExampleString{tostring(lpdf.reference(123))}
+\ShowLuaExampleString{tostring(lpdf.verbose("whatever"))}
+
+\stopsection
+
+\startsection[title={Managing objects}]
+
+Flushing objects is done with:
+
+\starttyping
+lpdf.flushobject(obj)
+\stoptyping
+
+Reserving object is or course possible and done with:
+
+\starttyping
+local r = lpdf.reserveobject()
+\stoptyping
+
+Such an object is flushed with:
+
+\starttyping
+lpdf.flushobject(r,obj)
+\stoptyping
+
+We also support named objects:
+
+\starttyping
+lpdf.reserveobject("myobject")
+
+lpdf.flushobject("myobject",obj)
+\stoptyping
+
+A delayed object is created with:
+
+\starttyping
+local ref = pdf.delayedobject(data)
+\stoptyping
+
+The data will be flushed later using the object number that is returned (\type
+{ref}). When you expect that many object with the same content are used, you can
+use:
+
+\starttyping
+local obj = lpdf.shareobject(data)
+local ref = lpdf.shareobjectreference(data)
+\stoptyping
+
+This one flushes the object and returns the object number. Already defined
+objects are reused. In addition to this code driven optimization, some other
+optimization and reuse takes place but all that happens without user
+intervention. Only use this when it's really needed as it might consume more
+memory and needs more processing time.
+
+\startsection [title={Resources}]
+
+While \LUATEX\ itself will embed all resources related to regular typesetting,
+\MKIV\ has to take care of embedding those related to special tricks, like
+annotations, spot colors, layers, shades, transparencies, metadata, etc. Because
+third party modules (like tikz) also can add resources we provide some macros
+that makes sure that no interference takes place:
+
+\starttyping
+\pdfbackendsetcatalog {key}{string}
+\pdfbackendsetinfo {key}{string}
+\pdfbackendsetname {key}{string}
+
+\pdfbackendsetpageattribute {key}{string}
+\pdfbackendsetpagesattribute{key}{string}
+\pdfbackendsetpageresource {key}{string}
+
+\pdfbackendsetextgstate {key}{pdfdata}
+\pdfbackendsetcolorspace {key}{pdfdata}
+\pdfbackendsetpattern {key}{pdfdata}
+\pdfbackendsetshade {key}{pdfdata}
+\stoptyping
+
+One is free to use the \LUA\ interface instead, as there one has more
+possibilities but when code is shared with other macro packages the macro
+interface makes more sense. The names of the \LUA\ functions are similar, like:
+
+\starttyping
+lpdf.addtoinfo(key,anything_valid_pdf)
+\stoptyping
+
+Currently we expose a bit more of the backend code than we like and
+future versions will have a more restricted access. The following
+function will stay public:
+
+\starttyping
+lpdf.addtopageresources (key,value)
+lpdf.addtopageattributes (key,value)
+lpdf.addtopagesattributes(key,value)
+
+lpdf.adddocumentextgstate(key,value)
+lpdf.adddocumentcolorspac(key,value)
+lpdf.adddocumentpattern (key,value)
+lpdf.adddocumentshade (key,value)
+
+lpdf.addtocatalog (key,value)
+lpdf.addtoinfo (key,value)
+lpdf.addtonames (key,value)
+\stoptyping
+
+\stopsection
+
+\startsection [title={Annotations}]
+
+You can use the \LUA\ functions that relate to annotations etc.\ but normally you
+will use the regular \CONTEXT\ user interface. You can look into some of the
+\type {lpdf-*} modules to see how special annotations can be dealt with.
+
+\stopsection
+
+\startsection [title={Tracing}]
+
+There are several tracing options built in and some more will be added in due
+time:
+
+\starttyping
+\enabletrackers
+ [backend.finalizers,
+ backend.resources,
+ backend.objects,
+ backend.detail]
+\stoptyping
+
+As with all trackers you can also pass them on the command line, for example:
+
+\starttyping
+context --trackers=backend.* yourfile
+\stoptyping
+
+The reference related backend mechanisms have their own trackers. When you write
+code that generates \PDF, it also helps to look in the \PDF\ file so see if
+things are done right. In that case you need to disable compression:
+
+\starttyping
+\nopdfcompression
+\stoptyping
+
+\stopsection
+
+\startsection[title={Analyzing}]
+
+The \type {epdf} library that comes with \LUATEX\ offers a userdata interface to
+\PDF\ files. On top of that \CONTEXT\ provides a more \LUA-ish access, using
+tables. You can open a \PDF\ file with:
+
+\starttyping
+local mypdf = lpdf.epdf.load(filename)
+\stoptyping
+
+When opening is successful, you have access to a couple of tables:
+
+\starttyping
+\NC \type{pages} \NC indexed \NC \NR
+\NC \type{destinations} \NC hashed \NC \NR
+\NC \type{javascripts} \NC hashed \NC \NR
+\NC \type{widgets} \NC hashed \NC \NR
+\NC \type{embeddedfiles} \NC hashed \NC \NR
+\NC \type{layers} \NC indexed \NC \NR
+\stoptyping
+
+These provide efficient access to some data that otherwise would take a bit of
+code to deal with. Another top level table is the for \PDF\ characteristic \type
+{Catalog}. Watch the capitalization: as with other native \PDF\ data structures,
+keys are case sensitive and match the standard.
+
+Here is an example of usage:
+
+\starttyping
+local MyDocument = lpdf.epdf.load("somefile.pdf")
+
+context.starttext()
+
+ local pages = MyDocument.pages
+ local nofpages = pages.n
+
+ context.starttabulate { "|c|c|c|" }
+
+ context.NC() context("page")
+ context.NC() context("width")
+ context.NC() context("height") context.NR()
+
+ for i=1, nofpages do
+ local page = pages[i]
+ local bbox = page.CropBox or page.MediaBox
+ context.NC() context(i)
+ context.NC() context(bbox[4]-bbox[2])
+ context.NC() context(bbox[3]-bbox[1]) context.NR()
+ end
+
+ context.stoptabulate()
+
+context.stoptext()
+\stoptyping
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent