This is our list of frequently-asked questions. For a more comprehensive guide, see our User's Guide. Please contact us on our mailing list if you have more questions.
Flying Saucer is an XHTML renderer written in Java. It's 100% Java, not a native wrapper, and it only handles well-formed XHTML + CSS. It is intended for embedding web-based user interfaces into Java applications (ex. web photo album generator, help viewer, iTunes Music Store clone). It cannot be used as a general purpose web browser since it does not support the malformed legacy HTML found on the web, though recent work on compatibility libraries may be enough to do what you need. You may be able to work with legacy HTML (e.g. HTML that is not well-formed XML) by using a pre-processor that cleans it up; there are several of these, including JTidy and TagSoup. See our User's Guide for details.
Flying Saucer takes well-formed XML (or a DOM Document) as input, matches it with CSS (linked, inline, attributed) and renders it. That XML could, for example, be XHTML (strict). We figure most of you are interested in rendering some form of XHTML, so in these docs we use "XHTML" as short for "well-formed XML, for example, XHTML (strict)".
You can render any XML, in fact, as long as you have CSS for it. For XHTML, we have out-of-the-box default CSS styling; for any other XML, you'll need to bring your own.
Flying Saucer is not an HTML component. It is a rendering component for XHTML content, but it cannot handle the malformed HTML 4.0 of general webpages, and it has no support for purely stylistic markup like FONT and CENTER. You have to use valid XHTML and CSS. For most embedded uses this is fine since the application author usually has control over the documents to be loaded. If you really need full IE/Mozilla/Safari-like fidelity for general purpose webpages you should look into a webbrowser wrapper like JDIC's Browser component, or a commercial component like WebRenderer. Sun's Swing team has said they are working on a Java wrapper for WebKit called JWebPane, but there is no release schedule announced so far.
The core renderer just handles XHTML and CSS. It doesn't know anything about form submission, managing cookies, or tracki ng the browsing history. It just renders XHTML/CSS to the screen. However, Flying Saucer does include a (very simple) Browser application which shows how you might develop these features yourself. You can use this as a good starting point for your own applications.
Flying Saucer can be used for any Java application that requires some sort of styled content, to generate high-quality PDF output based on XHTML and CSS documents, or to layout and render images based on XHTML and CSS.
An application using Flying Saucer can be as simple as a chat program or as complicated as a complete ebook reader with dynamic stylesheets. Flying Saucer is very forward- thinking and is designed to be a part of the next generation of applications that combine rich desktop clients with web content. Some examples of application types are:
Flying Saucer has become a favorite recently for people who need to render clean XHTML to PDF; we support PDF output via the iText library.
Flying Saucer supports all of CSS 2.1 with a few exceptions. Consult the issue tracker for more information on what is not supported (in particular, the issues with a summary of "Support ...") or ask on the mailing list.
If you do encounter a compliance bug or other unexpected behavior, please open a bug or post to the mailing list. Our goal is 100% compliance with the CSS 2.1 specification.
Check the issue tracker for a list or ask on the mailing list if you aren't sure.
Among other things there is no support for things outside the scope of XHTML/CSS such as Javascript, Flash, or legacy HTML (though there is interest in all of those).
Our core developer in the R7 development cycle, Pete Brant, reported that it was possible to render Acid2 pretty well, with some caveats. Quoting from him in the developer's email list:
begin quote
"Save for the changes below, test_as_xml.xml is an unmodified version of http://hixie.ch/tests/evil/acid/002-no-data/. All in all things are looking good!
Changes to original test:
<style>
tag in CDATA<p>
and table related tags in row 1 [as referenced from the test guide], <link>
in header, and bottom <img>
(after row 14 in guide)<object data="data007">ERROR</object>
with <img src="data007">ERROR</img>
(since we don't support HTML's <object>
)<img>
uses a data URL even in the non-data URL version (I assume it was just missed). Save data URL contents to disk (as data008) and update src attributeOf course, these changes mean that we cannot claim Acid2 compliance, but nothing there changes the nature of the test (at least as far as a CSS torture test goes).
Besides those changes above, there are still the following compliance problems:
end quote
The resulting image is available on our project home page, as an Easter egg. See if you can find the little bandit.
setDocument(dom, url)
constructor, what should the url parameter point to?You need a mouse listener that detects link clicks and does the HTTP request. The BasicPanel
supports tracking mouse events and delegating them to FSMouseListener
instances. You can use the org.xhtmlrenderer.swing.LinkListener
class, which implements FSMouseListener
, for basic hyperlink navigation support.
Take a look at the org.xhtmlrenderer.simple.extend.XhtmlForm
class. Form elements are "replaced" at runtime by the org.xhtmlrenderer.swing.SwingReplacedElementFactory
if you're using the XHTMLPanel
class for rendering. The factory actually creates a new XhtmlForm
class which creates and tracks the components. To receive a callback when the user submits a form, add a FormSubmissionListener
instance to your BasicPanel
.
It's been tricky for us to come up with a decent set of method calls to cover initilizing the panel without creating tons of little methods.
In Java APIs, there is some confusion on usage between a String that represents an address (like a URI or a file path) and strings that represent content. Our API tends to expect that Strings will represent addresses.
You can use panel.setDocumentFromString()
to render a document from a string containing XHTML content. The String will be passed to the standard XML parser and treated as a regular document.
It's important to remember that FS expects well-formed XML documents, and we don't have an extremely friendly relationship with the XML parsers; it's always a good idea to test that your document can be loaded outside of FS, without error, using Java XML APIs, before loading them in FS. This is especially true if you are generating XHTML on-the-fly.
Either
* Set the appropriate configuration properties: xr.text.aa-fontsize-threshhold
* Get the Java2DTextRenderer
reference from the XHTMLPanel's SharedContext
property, then call setSmoothingThreshold()
The threshold is the font size at which AA should kick in, for text; font sizes below that size will not be drawn with AA. A threshold of -1 turns AA off completely.
Note that on some platforms and JREs, AA can slow things down considerably. It appears to be much better with more recent Sun JREs, such as Java 6.
setDocument(dom, url)
constructor, what should the url parameter point to?The url is the "base", which for a normal URL would be the parent location—the parent directory, or the location where the document you are rendering is located.
If your document has absolute URIs for CSS and images, or it has no external references at all, then the base url can be null.
If your document has any relative URIs for CSS or images, then the base URL should not be null, but rather should point to the directory or address where the current document is located.
_I am using the selection / highlighting capabilities in Flying Saucer. Hightlighting works fine, but I need to have the index of the selection. Is this possible?
That's not possible out of the box. The DOM interface doesn't provide position information. An option is to walk through the nodes of the document to the left of the start of the selected range and then adding all the text content lengths.
Either use the background property inside of @page
or PdfStamper
after the PDF is already created. PdfStamper
is part of the iText API.
Make sure the element has it's display style as inline-block or block. Only block-level elements can be replaced.
PDF is treated as "print" media; see the CSS 2.1 specification section on media types. Make sure you have specified the media type for your CSS when you link or embed it; use type "print" or "all".
For the first document in the set (e.g. starting with the first page in the PDF you want to render) take an ITextRenderer and call setDocument()
, layout()
and createPDF()
; for each subsequent document, use the same renderer and call setDocument()
, layout()
, and writeNextDocument()
. Call finishPDF()
to complete the process. A sample follows below; a cleaned-up example, PDFRenderToMultiplePages
, is in our demos/samples directory in our source distribution.
String root = "J:/Temp/fs";
String[] inputs = new String[] { "input1.html", "input2.html",
"input3.html" };
String output = "output.pdf";
OutputStream os = null;
try
{
os = new FileOutputStream(new File(root, output));
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(new File(root, inputs[0]));
renderer.layout();
renderer.createPDF(os, false);
for (int i = 1; i < inputs.length; i++)
{
renderer.setDocument(new File(root, inputs[i]));
renderer.layout();
renderer.writeNextDocument();
}
renderer.finishPDF();
os.close();
os = null;
}
finally
{
if (os != null)
{
try
{
os.close();
}
catch (IOException e)
{
// ignore
}
}
}
If you're trying to output to an SWT canvas—there is an early mockup by Vianney le Clément which we plan to merge in the R8 release. See the mailing list thread starting with:
https://xhtmlrenderer.dev.java.net/servlets/ReadMsg?listName=dev&msgNo=3452
There are patches attached to that mail thread which provide initial support for SWT; some things are still missing, but it's a good start.
The values of -fs-flow-top/right/bottom/left
and -fs-move-to-flow
must
be strings and not keywords (e.g. -fs-flow-top: 'header'
instead of
-fs-flow-top: header
).
The new CSS parser validates this (and will give you a warning message if you have logging turned on).
ITextRenderer renderer = new ITextRenderer();
ITextUserAgent callback = new ITextUserAgent(renderer.getOutputDevice());
callback.setSharedContext(renderer.getSharedContext());
renderer.getSharedContext().setUserAgentCallback(callback);
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
The rules are that the document size is calculated after a layout takes place; for rendering to a Swing panel, this can only happen if the container for the panel (e.g. the window) is displayable. See this email thread in our mailing list for a discussion. In our demos/samples directory in the source distribution, the PanelResizeToPreferredSize
and JPanelSizeToDocument
show how this is done. Basically (quoting from the mail thread):
"So basically you want to:
f.pack()
to make them displayableXHTMLPanel
instances using doDocumentLayout(graphics)
f.pack()
again now that the preferred size of the XHTMLPanel
instances has been calculated"If you are relying on a layout manager that itself relies on its components' preferred sizes (like FlowLayout) you need to make sure to follow the rules above in order for the layout manager to pick up the size of the panel after it has been layed out. The second call to pack()
after doDocumentLayout()
takes care of doing this. See PanelResizeToPreferredSize
for an example using FlowLayout
.
You only need the
core-renderer.jar
(required)${itext.jar}
The first two are required; iText is needed for PDF rendering.
In earlier releases, you needed to include a CSS parser in the CLASSPATH. This is no longer necessary, as Flying Saucer now includes a fast, compliant CSS parser.
That is all you need for your own programs. You also need an XML parser to be in your classpath, but this already included in recent versions of the JRE.
To run the browser or use any of it's support classes you will need the browser.jar
file.
Our Ant build.xml
file includes all JAR files in the /lib
directory, plus the /resources
directory tree in the classpath. The compile target also copies CSS and properties resources from /src/css
and src/conf
to /build/resources
. If running from an IDE, you will need to synchronize this yourself.