|
|
|
This document describes the plugin import/export filter mechanism in XaraLX. Xara LX supports a mechansim that allows third parties to implement and test plug-in import and export filters, without building or changing Xara LX itself. This has been implemented by creating a special Xar format filter in XaraLX that communicates with the external filter, passing Xar format data to it when exporting and receiving Xar format data from it when importing. When exporting, the external filter can ask XaraLX to convert complex objects into simpler ones that are a better match for features of the external format. This means export filters only need to handle those Xar format objects that they can usefully process. Overview of filter operationsThe mechanism uses the Xar format as an intermediate format, so a plugin filter is basically a translator between the filter’s format and the Xar format. See the Xar PDF document for a comprehensive description of the Xar format. There is also a library called XarLib available which helps filter developers process XAR data (import and export). See the XarLib page for details. Import processThe import process inserts whatever is imported into the current document. The plugin mechanism requires that the filter loads the data in the filter’s format and outputs the corresponding Xar format data for XaraLX to load. It is also necessary for XaraLX to be able to determine the best filter to use for a particular file. When a file is imported without the file format being specified (or if a file is imported via drag and drop) XaraLX asks all of the import filters to rate their ability to handle the file and then uses the best one. The import process is also used when opening a file directly rather than importing. In this case, there is no existing document framework to insert the data into. For this reason, the filter must generate enough of the document structure in the Xar format data for the document to be properly usable in Xtreme. This means that a spread record should be output and the TAG_SPREADINFORMATION record should specify a sensible page size and a reasonably large margin so that a decent sized pasteboard appears (the default is 8 inches or 576000 milipoints). Export processThe export process outputs the document (or the selection) to a file. The plugin mechanism requires that the filter loads the Xar format data provided by XaraLX and outputs the corresponding data in its own format. It is necessary for filters to be able to provide UI for the user to select options and also for the filter to be able to control how complex objects in the document are represented in the Xar format data (e.g. a bitmap based format could ask for a single bitmap rendered at a specific resolution or a vector filter could provide a checkbox to convert text objects to simple paths). The process, therefore, has two stages: PrepareExport. The filter is asked how it wants the document represented. The filter returns an XML document that controls the conversion of objects. The filter can provide UI during this stage and modify the XML according to the user’s choices. DoExport. The filter is sent the Xar format data it requested and outputs its own format. Filter Configuration XMLA filter is registered by providing a configuration XML file that specifies the name of the filter, the file extension(s) it uses and the commands necessary to provide the four basic filter operations. This file must be installed in /usr/share/xaralx/filters. The format of this XML is as follows: <FilterConfig> The file can contain multiple Filter elements allowing a single file to register multiple filters. The name attribute of the Filter element must consist only of letters and numbers and must start with a letter. The child elements of the Filter element have the following meanings: DisplayName. This is the name of the filter that gets shown to the user in the import and export dialogs. Extensions. This is a comma separated list of file extensions that the file dialogs should show when this filter is selected. CanImport. This is set to a command that will read the file specified by %IN% and output a single integer score value to stdout. The score can range from 0 meaning not compatible at all to 10 meaning this is the best filter for the file. If the filter can handle the file but some features are not fully supported then an intermediate score should be given. DoImport. This is set to a command that will read the file specified by %IN% and output the corresponding Xar format data to stdout. It should also output progress indication to stderr as described below. PrepareExport. This is set to a command that is passed the output filename as %OUT% and the filename of the last capabilities XML for this filter and user as %XML%. It must update the XML file to contain whatever settings are required for this export. The previous XML is given so that any UI can start with the same settings as the previous export. DoExport. This is set to a command that is given the capabilities XML file returned from PrepareExport as %XML% and must read the Xar format data from stdin and write the output format to the filename given by %OUT% Exit valueThe commands must return zero if import/export was successful (even if there are some warnings) and a non-zero value if the conversion fails. In the case of a non-zero return value an informative error message, suitable for display to the end user, must be output on stderr. Progress MechanismThe DoImport and DoExport commands should output a progress complete indication to stderr. This is to be an integer between 0 and 100 followed by a ‘%’ and prefixed by "PROGRESS: " so that it can be distinguished from other output on stderr. Or in regexp terms: /^PROGRESS: *(\d+)%/ Eg. PROGRESS: 10% The progress mechanism should be implemented so that progress reporting is as uniform as possible throughout the conversion process, with regular updates provided. Output MessagesWarning messages are to be prefixed by "WARNING:". Warnings do not terminate the conversion nor trigger a non-zero program exit value. Error messages are to be prefixed by "ERROR:". Errors terminate the conversion and cause a non-zero program exit value. All other output on stderr will be ignored. Warnings should be issued for dropped entities, unexpected data and anything else a user may be interested in if the conversion is not 100% accurate. All messages must be suitable for display to the end user and must be internationalisable, see section 4.4. Settings dialogDuring PrepareExport it will usually be necessary to show a dialog to the user that allows them to choose export options. The dialog must be in the same style as Xara LX so that it looks like it is part of that application. If there are a lot of user options, the dialog should be appropriately tabbed. User InterruptionIf the user attempts to abort a long DoExport or DoImport operation, Xara LX will terminate the external filter process send a signal to the filter program and it must perform any necessary tidy-ups before exiting with a non-zero exit value. Implementing a plugin filterThe easiest way to build a plugin filter is to base it on the XPFilter project using the XarLib library to handle the reading and writing of the Xar format data. The source for this project can be downloaded here. If you are going to be using XarLib then you must build and install it as described here. This provides 2 simple filters using a configure parameter to control which one is built. The first, called XPFilter, simply imports and exports Xar format data by passing the data straight through to/from XaraLX. During the PrepareExport stage it shows a standard file loading dialog to allow the user to select an XML file to use as the XML that is returned to XaraLX. This allows filter developers to easily examine how the conversion system represents complex objects in the Xar data. The second filter, called XPXLFilter shows how to use the XarLib library to read and write Xar format data. It reads and writes text files. On export it simply outputs a text file containing a list of which Xar format record tags are used in the file and how many of each there are. It uses the same program for the PrepareExport stage as XPFilter so it also allows the selection of the conversion XML. On import it reads in the text file and uses XarLib to build a simple text story in the Xar format data so it can be used as a simple plain text import filter. The filter framework also supports using the same program for the PrepareExport stage as for the other stages if no UI is actually required. Typically, though, most filters should provide a UI to allow the user to select whether the whole document or just the current selection is exported. Building the XPFilter projectThe XPFilter project is built in the standard way. Unpack the tarball using: tar -xjf XPFilter-0.2.tar.bz2 This will create a XPFilter-0.2 directory. Change into this directory and do the following: autoreconf -f -i -s ./configure make To install the built filter for use in XaraLX simply run the following as root: make install The default configure options will build a unicode release version of the XarLib based filter. The configure options are: --enable-debug=yes Build a debug version of the filter So, to build a debug unicode version of the non-xarlib filter you would use: ./configure --enable-debug=yes --enable-xarlib=no The different configurations can be built in subdirectories in the standard way. Building your own filter based on XPFilterTo build a new filter based on the XPFilter project will require creating a new copy of the source directory called something sensible for your filter, renaming (and editing) the configuration XML file and modifying some parts of the configure.in script and Makefile.am As the example filter is still under development (various extensions will be added to it as time goes by) it is recommended that you try to alter as little of the build framework as possible to make merging in new versions as painless as possible. For a hypothetical SVG filter that uses XarLib, the necessary changes would be as follows: Copy the XPFilter-0.2 directory as SVGFilter. Copy the xpxlfilter.xml file as svgfilter.xml and edit the contents appropriately. E.g. <FilterConfig> Edit configure.in
Edit Makefile.am
The top of Makefile.am would then look something like this: bin_PROGRAMS = svgfilter svgfilterui svgfilter_SOURCES = xpfilter.cpp xarlibfilter.cpp svgfilterui_SOURCES = xpfilterui.cpp install-data-local: The implementaion would then be done by replacing the content of the functions in xarlibfilter.cpp and xpfilterui.cpp. If additional source files are required then they are simply added to the relevant _SOURCES line. The framework handles all the command line parsing, XarLib initialisation etc, leaving you to concentrate just on reading and writing Xar format records. Capabilities XML FormatThe root element of the Capabilites XML is an XPFilterConfig element. The general structure of the document is as follows: <XPFilterConfig> In the following element descriptions the default attribute values appear in bold. PrivateThis element can contain anything the filter wants to put in it. As the XML is returned to the filter when DoExport is called, this allows the filter to store internal parameters for the export. E.g. if the filter has an option that controls how it represents something but it doesn't need to change the conversion options then the setting can be stored in here so that it is available to the DoExport code. OptionsThis element is used to specify various options global to the conversion process. It allows the filter to specify that it only wants the selected objects to be exported, which pages are to be exported, if multipage spreads should be converted to single pages, whether a preview bitmap (of the first spread) shoudl be included and whether extra bounding box records are output with compound or all objects.
Rasterise This element is used to specify the properties of bitmaps generated by the conversion system. It allows the filter to specify the resolution of the generated bitmaps and whether the filter can support alpha channel bitmaps. If the objects that are being rendered as a bitmap use non-mix transparency (or any transparency if the bitmaps are specified as non-transparent) then the objects behind are rendered into the bitmap first to ensure the correct appearance.
Conversion Elements
The following elements all have as "as" attribute that specifies how the object will be represented in the XML. The allowable values for the "as" attribute are as follows:
Not all of the values are relevant to all objects. The allowable values for each element are listed with the element description (native and remove are allowed for all objects). There are also some specialised "as" values (e.g. for colour and text records) that are described with their element description below. Many of the objects may need to be converted differently depending on their properties (e.g. a format might only support wall shadows) and this is specified by a tree of elements. E.g. <Shadow as="simple"> This specifies that wall shadows should be output as native but all other shadows should be output as simple. See the examples at the end of this document for more samples. Objects This element is a container for all of the object conversion elements. Spread This element is used to control the conversion of the entire document to a bitmap. The "as" attribute can be set to the following:
This element can also have the following property attributes:
Layer This element is used to control the conversion of individual layers to bitmaps. The "as" attribute can be set to the following:
This element can also have the following property attributes:
Contour This element controls the conversion of contour objects.
Shadow This element controls the conversion of shadow objects.
This element can also have the following property attributes:
Bevel This element controls the conversion of bevel objects.
This element can also have the following property attributes:
Blend This element controls the conversion of blend objects.
This element can have the following property attributes:
Mould This element controls the conversion of mould objects.
This element can have the following property attributes:
Rectangle This element controls the conversion of rectangles.
This element can have the following property attributes:
The complex property indicates whether the object has a complex transformation or only simple scaling. Ellipse This element controls the conversion of ellipses.
This element can have the following property attributes:
The complex property indicates whether the object has a complex transformation or only simple scaling. RegularShape This element controls the conversion of other regular shapes
This element can have the following property attributes:
Bitmap This element controls the conversion of bitmap objects
This element can have the following property attributes:
The complex property indicates whether the object has a complex transformation or only simple scaling. The contone property indicates a contoned bitmap. Text This element controls the conversion of text stories
This element can have the following property attributes:
The complex property indicates the story has a complex transformation (e.g. it would be represented as a TAG_TEXT_STORY_COMPLEX rather than a TAG_TEXT_STORY_SIMPLE). The plain property indicates that the whole story only has plain text (e.g. flat fill, no line colour, no transparency, no feather etc.). This allows stories that have complex attributes applied to be converted to simple shapes but plain text to be maintained as text. If this property doesn’t prove to give fine enough control then it will be replaced with multiple properties (or possibly a separate TextAttributes tree). ClipView This element controls the conversion of ClipViews.
BitmapEffect This element controls the conversion of bitmap effect objects.
Feather This element controls the conversion of feathered objects. Note, this element can also appear in the attributes section.
Attributes This element is a container for all of the attribute conversion elements. It allows the default "as" attribute to be set to native, bitmap or bitmapspan.
Fill This element controls the conversion of objects based on their fill attribute.
This element can have the following property attributes:
FillTrans This element controls the conversion of objects based on their fill transparency attribute.
This element can have the following property attributes:
Line This element controls the conversion of objects based on their line attributes.
This element can have the following property attributes:
LineTrans This element controls the conversion of objects based on their line transparency.
This element can have the following property attributes:
Feather This element controls the conversion of objects based on their feather attribute.
Colour This element controls how colours are represented.
This element can have the following property attributes:
Example XML There follow various examples of XML with descriptions of what they do. Output just the selected spread <XPFilterConfig> Convert each spread into a single bitmap <XPFilterConfig> Convert each layer into a separate alpha channel bitmap E.g. for a layer-capable Photoshop filter <XPFilterConfig> More compex conversion Output all visible layers. Convert complex objects except rectangles (non-rounded), ellipses and plain text stories to simple shapes. Convert all bitmap objects to non-transformed and non-contoned bitmaps. Convert all fills except simple 2-colour linear and radial (both circular and elliptical) into bitmap fills. Convert all use of non-flat non-mix transparency to bitmap spans. Stroke any objects that have arrows, dash patterns, variable width or brushes. Generate bitmaps at 200 dpi. Convert all colours to simple RGB colours. <XPFilterConfig>
The Conversion Process
The conversion process works as follows: A copy of the document root down to the chapter is created. Each spread is then rendered using a special render callback that performs the conversions for pass 1. Before navigating into each subtree during the render, the Objects element of the capabilities XML is scanned to determine the conversion type to use. This works by scanning each child of the Objects element and if it matches the node being scanned then the conversion type is remembered (if not unknown). Where there are nested items, if the parent item matches then its type is remembered and then the children are scanned to see if any of them override this conversion. If the conversion type is native then the node is simply copied and the render scan is continued down into the subtree. If the conversion type is simple then the whole subtree is copied and then converted to editable shapes using the standard BecomeA mechanism. If the conversion type is bitmap then the entire subtree is rendered to a bitmap and a new NodeBitmap is added to the tree (if the object being converted is a spread or a layer then the spread or layer is also copied). If the conversion type is reformat then a reformatted copy of the text story is created and added to the tree. If the conversion type is remove then the subtree is skipped. Passes 2 to 5 all work in a similar way but the copy of the tree is rendered instead. During the render, things found to require conversion are added to a list and the conversions are done after the render loop is complete to avoid problems with the tree changing while we are scanning through it. Pass 2 handles the stroked conversion type. Any non-compound objects are checked to see if the attributes that are current in the render region specify the stroked conversion type (this check is done in the same way as above but the Attributes element is scanned instead and the conversion is only used if it is stroked). Any object that needs the stroked conversion is added to the list and the ConvertPathToShapes code is done on each object in the list.
Pass 3 is concerned with the bitmapfill, bitmaptrans and bitmapfilltrans conversions. This works in the same way as pass 2 scanning the Attributes element but all three types are tracked simultaneously. Matching objects are stored in the list along with three flags for the different conversions. If the bitmapfilltrans conversion is required then the fill and transparency of the object are rendered into a bitmap (including all the background objects if the object uses a non-alpha compatible transparency) and all the existing fill and transparency attributes are removed and replaced with a simple fill using this bitmap. If bitmapfilltrans is not required then the other two conversion types are done as required. The bitmapfill conversion simply renders the fill of the object as a bitmap and replaces the fill attributes with a simple bitmap fill. The bitmaptrans conversion renders the object with a flat black fill and a mix version of its transparency into a bitmap and replaces the transparency attributes of the object with a bitmap transparency using this bitmap and the transparency type of the original transparency.
Pass 4 is concerned with the conversion of objects to bitmaps. It is mainly intended to catch group transparency. It checks the Objects element for the conversion type of bitmap and renders each object into a bitmap. It specifically ignores layer and spread nodes during this pass as they will have been converted during phase 1 if appropriate but the layer or spread node will still exist in the tree and would be converted again.
Pass 5 is concerned with the bitmapspan conversion. The attributes in the render region for each object are checked against the Attributes element and any requiring the bitmapspan conversion are added to a bitmapspan object. A bitmapspan is defined as a run of objects that all require the bitmapspan conversion and all have the same parent node. Where all the children of an object (e.g. a group) require the bitmapspan conversion the span is removed and the parent object is treated as if it requires bitmapspan. This allows bitmapspans to include whole groups e.g. if there is a rectangle, a group consisting of 2 rectangles and another rectangle and all the rectangles require the bitmapspan conversion then only one span will be created going from the first rectangle to the last one and including the group in the middle. This can generate substantially fewer spans for some documents. Each bitmap span is then rendered into a bitmap.
The resample option is handled after all the other passes. The minimum effective resolution of each bitmap in the document is calculated and if this is greater than the Rasterisation resolution then the bitmap is replaced throughout the document with a lower resolution version.
Both the bitmap and bitmapspan conversions use a function called RenderNodesToBitmap that takes a start node and an end node and renders them, creating a new NodeBitmap. The function actually returns a generic Node* so that it can return a tree of nodes if required. If a single layer or a single spread are being rendered then it actually returns the same type of Node (e.g. for a layer, it will create a copy of the rendered layer object and insert the new NodeBitmap as a child of the layer). The function can also apply a transparency attribute to the generated NodeBitmap which allows the alpha channel of an RGBA bitmap to actually use a different transparency blend mode (e.g. stained glass or bleach).
The RenderNodesToBitmap function works as follows: alpha and commontrans are attributes of the Rasterise element. If alpha is false then Render as non-alpha with background objects included (as now).
Else If objects have a common trans type listed in commontrans attribute then Render as alpha without background objects but render all transparencies as mix and apply correct type of transparency attribute to resultant bitmap. Else If objects use NonAlpha then Render as non-alpha with background objects and also render just the specified objects to a 32bpp RGBA “mask” bitmap. Then combine it with the non-alpha bitmap to remove unnecessary parts of the background. Else Render as alpha without background and no transparency attribute. End If End If
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Last Updated ( Tuesday, 22 August 2006 ) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

