| <?xml version="1.0"?> |
| <!DOCTYPE document SYSTEM "./dtd/document-v10.dtd"> |
| |
| <!-- |
| |
| Copyright 2001-2002 The Apache Software Foundation |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| --> |
| <!-- ====================================================================== --> |
| <!-- author Thomas.DeWeese@kodak.com --> |
| <!-- version $Id$ --> |
| <!-- ====================================================================== --> |
| |
| <document> |
| <header> |
| <title>Extending Batik</title> |
| <subtitle>Possible extensions</subtitle> |
| <authors> |
| <person name="Thomas DeWeese" email="thomas.deweese@kodak.com"/> |
| </authors> |
| </header> |
| |
| <body> |
| <s1 title="Introduction"> |
| <p>The goal of this section is to provide an overview of |
| the built in extension mechanisms in Batik. As an open |
| source project, people can of course make any extension |
| they feel is interesting, however Batik has been |
| designed with several forms of extension in mind.</p> |
| |
| <p>The main areas extension are anticipated are:</p> |
| <ul> |
| <li><link href="#customXMLTags"> |
| Support for custom XML Tags |
| </link></li> |
| <li><link href="#imageTagFormats"> |
| Support for new file formats in the 'image' tag. |
| </link></li> |
| <li><link href="#urlProtocols"> |
| Support for new protocols in URL references. |
| </link></li> |
| </ul> |
| |
| <p> |
| In general extensions are done through the Service |
| Provider Interface mechanism as described in the |
| <link href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service Provider"> |
| Jar file</link> documentation. |
| </p> |
| |
| <p> |
| This allows for the extension of Batik simply by adding a |
| new jar file(s) to the class path, no modification of |
| Batik source is required! |
| </p> |
| |
| <note> |
| If you feel that the Batik team has overlooked an |
| important area for extension please let your feelings be |
| known on the mailing-lists. |
| </note> |
| </s1> |
| |
| <anchor id="customXMLTags" /> |
| <s1 title="Custom XML Tags"> |
| <p> |
| First one must ask "What does it mean to support custom |
| XML tags?" |
| </p> |
| |
| <p> |
| There are three basic options Batik considers: |
| </p> |
| <dl> |
| <dt> Having your tags appear in the DOM tree. </dt> |
| <dd><br/> As long as your custom tags are well formed |
| (and preferably valid) XML they will appear in the SVG |
| DOM tree. When rendering Batik will skip branches of |
| the tree that use a tag it doesn't know about (so even |
| if standard SVG tags are child nodes they will not be |
| displayed). <br/> It is strongly suggested that you |
| make use of XML namespaces for your personal tags even |
| if you are not planning on validating the XML. <br/> |
| This can be useful if you want to add extra pieces of |
| data into the standard SVG drawing. These might be |
| annotations, or other application specific data. In |
| general this wouldn't be particularly useful with |
| squiggle (the SVG browser) or the rasterizer, but |
| might be very useful if you were writing a custom |
| browser, rasterizer, or pre/post processing tools. |
| </dd> |
| |
| <dt> Tags use a custom element in the DOM tree</dt> |
| <dd><br/> |
| |
| If you need your tags to use a custom element subclass |
| in the DOM tree (for behavioral or performance |
| reasons) then you need to provide an <link |
| href="#domExtension"> extension to the Batik |
| DOM.</link> <br/> |
| |
| Doing this gives you the opportunity to override the |
| standard methods on DOM elements, or to provide |
| additional methods to your DOM elements. For example |
| all of the SVG elements in Batik implement the |
| getAttribute methods to respect the CSS styling |
| properties. They also provide additional methods to |
| implement the SVG DOM. |
| </dd> |
| |
| <dt> Tags that get rendered.</dt> |
| <dd><br/> |
| |
| Probably the most common reason to develop custom tags |
| is to add new rendering primitives to the SVG |
| language. In this case you must provide an <link |
| href="#bridgeExtension"> extension to the Batik |
| Bridge</link>. The bridge extension is resposible for |
| constructing the class(es) that will handle the |
| rendering of the new primitive in Batik. <br/> |
| |
| In most cases it will also be necessary to write a DOM |
| extension to make the tag behave like other SVG tags |
| (most notably for support of styling). |
| </dd> |
| </dl> |
| |
| <anchor id="domExtension"/> |
| <s2 title="Writing a Batik DOM Extension"> |
| <p> |
| The ability to extend the elements used in the SVG DOM |
| tree allows users to provide implementations for nodes |
| that can be used in place of Batik's default |
| implementation of a node. This may be done for a |
| variety of reasons but is most commonly done to extend |
| the behavior of standard node calls (such as to |
| include styling in attribute lookup), or to implement |
| the DOM interface for a Tag. |
| </p> |
| |
| <p> |
| The key class for building the DOM tree is the |
| <code>ExtensibleSVGDOMImplementation</code> class. |
| When an instance of this class |
| is constructed it searches for instances of the |
| <code>org.apache.batik.dom.svg.DomExtension</code> |
| Service Provider interface. It then calls the |
| 'registerTags' method with it's self for each one. |
| This method typically calls |
| <code>registerCustomElementFactory</code> for each tag that it |
| wishes to handle. |
| </p> |
| |
| <p> |
| With Batik the most likely reason to extend a node is |
| to provide proper CSS styling of the node attributes. |
| To this end Batik provides a class you can extend: |
| <code>org.apache.batik.extension.PrefixableStylableExtensionElement</code>. |
| If you derive off this class you are only required to |
| implement three methods: <code>getLocalName</code>, |
| <code>getNamespaceURI</code>, and <code>newNode</code> |
| (plus constructors). If all you want is proper style |
| support (commonly the case) then you are done implementing |
| your elements at this point. |
| </p> |
| |
| <p> |
| The distribution comes with a number of examples |
| </p> |
| <ul> |
| <li><code>org.apache.batik.extension.svg.BatikStarElement</code></li> |
| <li><code>org.apache.batik.extension.svg.BatikRegularPolygonElement</code></li> |
| <li><code>org.apache.batik.extension.svg.BatikHistogramNormalizationElement</code></li> |
| <li><code>org.apache.batik.extension.svg.SolidColorElement</code></li> |
| <li><code>org.apache.batik.extension.svg.ColorSwitchElement</code></li> |
| </ul> |
| <p> |
| Included with these examples is |
| <code>org.apache.batik.extension.svg.BatikDomExtension</code> |
| which is the required instance of <code>DomExtension</code> |
| used to register the elements with the |
| <code>ExtensibleSVGDOMImplementation</code>. |
| </p> |
| |
| <p> |
| When your new element requires new 'presentation attributes' |
| (XML attributes that can be modified through CSS or depending |
| on your view point the other way round, CSS properties that |
| can be specified using XML attributes), you may also need to |
| extend the CSS engine. This can be done by registering a |
| custom CSS value factory. Both of the color examples do |
| this (see <code>BatikDomExtension</code>). |
| </p> |
| </s2> |
| |
| <anchor id="bridgeExtension"/> |
| <s2 title="Writing a Batik Bridge Extension"> |
| <p> |
| Before you write a bridge extension it may be useful |
| to understand what the role the bridge package plays |
| in Batik. The bridge package is responsible for |
| creating and maintaining elements in the Graphics |
| Vector Toolkit (GVT) tree based on the corresponding |
| element in the SVG DOM. This is done because for a |
| variety of reasons the SVG DOM is not well suited for |
| rendering, thus GVT tree is used for all rendering and |
| transcoding operations. |
| </p> |
| |
| <p> |
| The key class for managing this link is the |
| <code>BridgeContext</code>. This class maintains an |
| association between a tag name with namespace and a |
| particular bridge instance that will handle it. The |
| work of constructing the proper entity or entities in the |
| GVT tree is then deferred to the Bridge registered for |
| a particular tag. If no bridge is regiestered nothing is |
| done. |
| </p> |
| |
| <p> |
| New associations can be added by implementors of the |
| <code>BridgeExtension</code> Service Provider Interface. |
| This interface has a number of methods that provide |
| information about the particular extension being |
| registered (including contact information, and the |
| list of implemented extensions). It also has a |
| 'registerTags' method which is responsible for |
| registering the bridge instances with a |
| <code>BridgeContext</code>. All the built in bridges are |
| bundled with a BridgeExtension (in |
| <code>org.apache.batik.bridge</code>), |
| as are the example extensions (in |
| <code>org.apache.batik.extension.svg</code>), |
| so these are both good places to start. |
| </p> |
| |
| <p> |
| The <code>Bridge</code> interface itself is very simple. |
| It only includes methods to get the namespace and local |
| name of the tag the bridge is responsible for. This |
| interface is then extended for each of the major |
| concepts present in SVG: |
| </p> |
| <dl> |
| <dt><link href="#graphicsNodeBridge"> |
| GraphicsNodeBridge</link></dt> |
| <dd> |
| These are probably the most common SVG elements |
| they represent graphic elements in what I'll call |
| the "visible" SVG tree. These are the elements |
| most other bridges modify in some way (by clipping, |
| masking, filtering, etc). |
| <br/> |
| <em>Example tags:</em> svg, g, path, rect.<br/> |
| <em>Example Extensions:</em> BatikRegularPolygonElementBridge, BatikStarElementBridge. |
| </dd> |
| |
| <dt>FilterBridge</dt> |
| <dd> |
| Handles the SVG 'filter' element. If you wanted |
| to implement a new tag that could be referenced |
| from the 'filter' attribute on an SVG graphics |
| node then you would need to subclass this bridge. |
| However adding new types of filters to the |
| existing SVG 'filter' element is accomplished via |
| the FilterPrimitiveBridge. |
| <br/> |
| <em>Example tag:</em> filter |
| </dd> |
| |
| <dt><link href="#filterPrimitiveBridge"> |
| FilterPrimitiveBridge</link></dt> |
| <dd> |
| Constructs an element in the filter chain applied |
| to an SVG graphics node. |
| <br/> |
| <em>Example tags:</em> feBlend, feCompose, ...<br/> |
| <em>Example Extensions:</em> BatikHistogramNormalizationElementBridge |
| </dd> |
| |
| <dt><link href="#paintBridge">PaintBridge</link></dt> |
| <dd> |
| Constructs a java Paint object to be used |
| in filling or stroking graphic elements. |
| <br/> |
| <em>Example tags:</em> gradient, pattern.<br/> |
| <em>Example Extensions:</em> SolidColorBridge, ColorSwitchBridge |
| </dd> |
| |
| <dt>ClipBridge</dt> |
| <dd> |
| Constructs a ClipRable to apply to a Graphics Node. |
| This provides a path that data is clipped to. |
| <br/> |
| <em>Example tag:</em> clip-path. |
| </dd> |
| |
| <dt>MarkerBridge</dt> |
| <dd> |
| Constructs a Marker for annotating the path of a |
| GraphicsNode. |
| <br/> |
| <em>Example tag:</em> marker |
| </dd> |
| |
| <dt>MaskBridge</dt> |
| <dd> |
| Constructs a Mask Filter to apply to a Graphics |
| Node. Mask Filters typically modify the alpha |
| channel of the Graphics Node output to make |
| portions fully or partially transparent that |
| wouldn't be otherwise. |
| <br/> |
| <em>Example tag:</em> mask. |
| </dd> |
| </dl> |
| |
| <p> |
| Extension writers are free to work with any of the |
| above bridges, however the three most common are |
| likely to be the <code>GraphicsNodeBridge</code>, the |
| <code>FilterPrimitiveBridge</code>, and the |
| <code>PaintBridge</code> (each of which have example |
| extensions available for inspection). |
| Each of these interfaces has several extremely useful |
| subclasses that handle much of the common behavior |
| among elements. |
| </p> |
| |
| <p> |
| In some simple cases it is possible to only provide an |
| extension to the Bridge and get your desired effect, |
| however in most cases you will find that for your |
| element to behave like a normal SVG element (for |
| example supporting styling) you will need to provide a |
| DOM extension as well. |
| </p> |
| |
| <anchor id="graphicsNodeBridge"/> |
| <s3 title="GraphicsNodeBridge"> |
| <p> |
| The graphics node bridge is oriented around |
| constructing a new <code>GraphicsNode</code> in the GVT |
| tree. The <code>GraphicsNode</code> is the basic element |
| that makes up the GVT tree. Each <code>GraphicsNode</code> |
| has a <code>paint</code> method that is responsible for |
| painting the object (including considering clipping, |
| masking, filtering, and opacity for the node). |
| </p> |
| |
| <p> |
| If you want to you can implement |
| <code>bridge.GraphicsNodeBridge</code> interface |
| directly or subclass |
| <code>bridge.AbstractGraphicsNodeBridge</code>. |
| This gives you the most flexibility since you can |
| construct your new subclass of |
| <code>gvt.GraphicsNode</code> where you can implement |
| the paint method to do essentially anything you want, |
| this is also a lot of work (and I'm not going to |
| try and explain everything needed to pull this |
| off). |
| </p> |
| |
| <p> |
| However, if you just want to generate a custom |
| filled or stroked shape the easiest way is to |
| subclass either of the following classes. In this |
| case you are essentially only responsible for |
| constructing a standard java <code>Shape</code> object to |
| describe the desired area to operate on: |
| </p> |
| <dl> |
| <dt><code>SVGShapeElementBridge</code></dt> |
| <dd> |
| Subclasses of this class only need to implement |
| buildShape, getNamespaceURI, and getLocalName. |
| buildShape generally constructs a |
| <code>java.awt.Shape</code> object and sets it on |
| the provided <code>shapeNode</code> object, |
| however it may adjust other features of the given |
| shape node. |
| </dd> |
| <dt><code>SVGDecoratedShapeElementBridge</code></dt> |
| <dd> |
| This is very similar to SVGShapeElementBridge, |
| except it also handles the standard marker |
| properties. Markers will be place at each the |
| end of each segment of the path. |
| </dd> |
| </dl> |
| <p> |
| If you decide that you need to implement a new subclass |
| of <code>GraphicsNode</code> I strongly suggest that |
| you derive off of <code>AbstractGraphicsNode</code> |
| as this class does much of the work to behave like |
| a drawn element in SVG (like clipping, filtering, |
| masking). In this case you implement |
| the <code>primitivePaint</code> method |
| instead of the <code>paint</code> method. |
| </p> |
| </s3> |
| |
| <anchor id="filterPrimitiveBridge"/> |
| <s3 title="FilterPrimitiveBridge"> |
| <p> |
| The Filter primitive bridge is concerned with the |
| construction of individual elements of the filter |
| chain. Unlike graphics nodes which generally just |
| draw new objects on top of the destination, filters |
| take existing image data and modify it to apply |
| effects. |
| </p> |
| |
| <p> |
| This part of GVT rendering is based on the Java2D |
| <code>java.awt.image.renderable.RenderableImage</code> |
| and <code>java.awt.image.RenderedImage</code> |
| interfaces. This provides a convenient framework to |
| handle image processing (an inherently resolution |
| dependent operation) in the resolution independent |
| system defined by SVG. |
| </p> |
| |
| <p> |
| The majority of classes for part of Batik are present |
| in the <code>batik.ext.awt.image.*</code> package hierarchy |
| which contains a large set of generally useful extensions to |
| the core JDK classes and methods. |
| </p> |
| |
| <p> |
| Note that the <code>FilterPrimitiveBridge</code> is invoked |
| once for each reference to the <code><filter></code> |
| tag that the filter primitive is part of. So if a filter |
| effect is used a half dozen times the <code>createFilter</code> |
| method will be called a half dozen times, even though the |
| tag may only appear once in the file. This means that it is |
| safe for the Filters returned to be 'fixed' for a |
| particular <code>GraphicsNode</code> being filtered. |
| </p> |
| |
| <p> |
| You will notice that Batik uses extended versions of |
| the standard <code>Renderable</code> and <code>Rendered</code> |
| image classes to provide additional information about surround |
| requirements for operations as well as a few |
| convenience methods. These interfaces are called: |
| <code>java.ext.awt.image.renderable.Filter</code> and |
| <code>java.ext.awt.image.rendered.CacheableRed</code>. |
| Batik contains simple wrapper classes that can take |
| the default JDK <code>Renderable</code> and |
| <code>Rendered</code> Image interfaces. Within the code |
| base the convention 'Red' for classes implementing |
| <code>RenderedImage</code>, and 'Rable' for classes |
| implementing <code>RenderableImage</code> is commonly |
| used ('Red' is to be pronounced like the color, and |
| 'Rable' is to be pronounced like 'horrible' with a |
| silent 'h'). |
| </p> |
| |
| <p> |
| The <code>FilterPrimitiveBridge</code> really has only |
| one method right now: <code>createFilter</code> that must |
| construct an instance of <code>Filter</code> to perform |
| the required operation. This is still a fairly complex task |
| given the general need to support accessing the various |
| standard sources of image data. To this end there is |
| a provided subclass, |
| <code>AbstractSVGFilterPrimitiveElementBridge</code> |
| This provides convenience methods to handle many common |
| tasks. |
| </p> |
| |
| <p> |
| Generally the bulk of the work in writing a filter |
| extension is the writing of the Filter instance not |
| tying it into the GVT tree. Batik does contain |
| several base classes that make this processes a bit |
| easier. |
| <code>ext.awt.image.renderable.AbstractRable</code>, |
| <code>ext.awt.image.rendered.AbstractRed</code>, and |
| <code>ext.awt.image.rendered.AbstractTiledRed</code>. |
| <code>TiledRed</code> ties into the Batik tile cache |
| (use this with caution as it is a complex area of |
| the Batik code). |
| </p> |
| |
| <p> |
| The <code>ext.awt.image.rendered</code> and |
| <code>renderable</code> packages contain quite a |
| number of fairly general examples covering most common |
| cases, please refer to them for more detail. |
| </p> |
| </s3> |
| |
| <anchor id="paintBridge"/> |
| <s3 title="PaintBridge"> |
| <p> |
| The <code>PaintBridge</code> constructs an instance of the |
| <code>java.awt.Paint</code> to be used to fill or stroke |
| shapes/text (part of the paint server architecture of |
| SVG). |
| </p> |
| |
| <p> |
| Like the filter primitive bridge the <code>PaintBridge</code> |
| is invoked for each reference to the paint. This makes |
| it possible to customize the Paint returned for the |
| particular element to be painted. |
| </p> |
| |
| <p> |
| This is how the gradients and patterns are implemented |
| in Batik, so it is possible to construct rather |
| complex paint effects through this mechanism. |
| </p> |
| |
| <p> |
| For paints you are mostly on your own, because unlike |
| the other cases there aren't any really generally useful |
| base classes to derive off, the closest is the |
| <code>AbstractSVGGradientElementBridge</code> which is |
| used to handle most of the radial and linear gradient |
| attributes. |
| </p> |
| |
| <p> |
| The existing gradient paint implementations are in |
| <code>ext.awt</code>, the pattern implementation is in |
| <code>gvt</code> since it requires access to gvt |
| internals. |
| </p> |
| </s3> |
| </s2> |
| </s1> |
| |
| <anchor id="imageTagFormats" /> |
| <s1 title="New File Formats"> |
| <p> |
| When Batik encounters an 'image' element and it determines |
| the element does not reference an SVG file. It defers the |
| loading of the referenced image to |
| <code>org.apache.batik.ext.awt.image.spi.ImageTagRegistry</code>. |
| This class maintains a list of <code>RegistryEntries</code>, |
| generally one for each format. |
| </p> |
| |
| <p> |
| Since the formats supported natively by Batik are also |
| implemented through this mechanism. The |
| <code>JPEGRegistryEntry</code> and <code>PNGRegistryEntry</code> |
| should be used as good references for extensions. |
| </p> |
| <s2 title="RegistryEntry"> |
| <p> |
| There are currently two flavors of <code>RegistryEntry</code>: |
| </p> |
| |
| <dl> |
| <dt>URLRegistryEntry</dt> |
| <dd> |
| These take a <code>ParsedURL</code> and try to decide if |
| the URL is intended for them. This group of entries is |
| mostly intended to handle alternate network protocols. It |
| can also be useful for interfacing with libraries |
| that want a URL instead of a stream. |
| </dd> |
| |
| <dt>StreamRegistryEntry</dt> |
| <dd> |
| These work with a markable <code>InputStream</code>. |
| This is the preferred form of registry entry as it |
| generally avoids opening a potentially expensive connection |
| multiple times, instead it opens the stream once |
| and relies on mark and reset to allow entries to |
| check the stream. |
| </dd> |
| </dl> |
| </s2> |
| |
| <s2 title="Helper classes"> |
| <p> |
| There exists quite a number of classes to assist in |
| implementing a <code>RegistryEntry</code>. It is strongly |
| recommended that you review these classes and make use |
| of them where appropriate. They will likely save you |
| time and improve the integration with Batik. |
| </p> |
| <dl> |
| <dt>MagicNumberRegistryEntry</dt> |
| <dd> |
| An abstract class that can handle the |
| <code>isCompatibleStream</code> method for formats that |
| make use of "magic numbers". Magic numbers are a well |
| known sequence of bytes at a well known offset in the |
| file, that are commonly used to identify image file formats. |
| </dd> |
| |
| <dt>RedRable</dt> |
| <dd> |
| This takes any <code>java.awt.image.RenderedImage</code> and |
| wraps it into a <code>Filter</code> (Batik's subclass of |
| RenderableImage). This is extremely useful for |
| <em>single resolution</em> file formats. |
| </dd> |
| |
| <dt>DeferRable</dt> |
| <dd> |
| This allows one to load the image in a background |
| thread, rather than hold up the construction of the |
| GVT tree while reading the image (useful since |
| reading the image is generally I/O bound, so it |
| makes a good background task). This is used by most of |
| the current Image readers. |
| </dd> |
| |
| <dt>AbstractRable</dt> |
| <dd> |
| An abstract base class that makes it relatively |
| easy to implement the Filter interface. |
| </dd> |
| |
| <dt>AbstractRed</dt> |
| <dd> |
| An abstract base class that makes it relatively |
| easy to implement the CacheableRed interface |
| (Batik's subclass of RenderedImage). |
| </dd> |
| </dl> |
| </s2> |
| </s1> |
| |
| <anchor id="urlProtocols" /> |
| <s1 title="New URL Protocols"> |
| <p> |
| |
| For a variety of reasons (not the least of which is the |
| heavy use of the 'data:' protocol in SVG). Several parts |
| of Batik use a <code>util.ParsedURL</code> instead of the |
| JDK's <code>java.net.URL</code> class. |
| </p> |
| |
| <p> |
| <code>ParsedURL</code> offers a few advantages over the JDK's |
| URL class. First, it is designed to make minimal use of |
| exceptions, so it is possible to use it to parse a malformed |
| URL and get "the good parts". Second, it is extensible, so |
| support for new protocols can be added, even protocols that |
| change the normal parsing rules for URLs (such as our friend the |
| 'data' protocol). Third it can automatically check a stream when |
| opened for common compression types and decode them for you |
| (this behavior can also be bypassed if needed). |
| </p> |
| |
| <p> |
| The service class is |
| <code>org.apache.batik.util.ParsedURLProtocolHandler</code>. This |
| interface consists of three methods, one returns the protocol |
| to be handled, one is for parsing an absolute URL string and |
| one is for parsing relative URL strings. Both the parsing |
| methods return an object of type ParsedURLData (the instance |
| may of course be a subclass of ParsedURLData). |
| </p> |
| |
| <p> |
| The <code>ParsedURLData</code> class holds all the data and |
| implements the all the stream handling commands for the |
| ParsedURL class. This allows ProtocolHandlers to return custom |
| subclasses for particular protocols. |
| </p> |
| </s1> |
| </body> |
| </document> |