使用Batik开发SVG应用程序(一)

使用Batik开发SVG应用程序

翻译时间 2007-2-6

修订记录 2007-2-23 语言修改

Thierry Kormann
ILOG

ILOG
Les Taissounières HB2
1681 route des dolines
06560 Valbonne
France
e-mail: [email protected]
fax: +33 4 92 96 61 62
主页: http://www.ilog.com

关键词: SVG, Batik, Toolkit, Developing, Applications

摘要

BatikApache软件基金会(Apache Software Foundation)开发的一个开源项目。该项目的目标是提供一组核心模块,通过使用这些模块可以实现特定的SVG解决方案。本文将介绍如何使用Batik组件开发具有SVG功能的JavaTM应用程序。

介绍

Batik是基于JavaTM技术的工具集,用于使用Scalable Vector Graphics (SVG) [1] 图像的应用程序,其功能范围包括图像显示、生成和操作。工具集提供了一组核心模块,包括:

  • SVG 文档对象模型的实现( SVG DOM, W 3C /SVG 工作组定义的标准应用程序接口),用于其生成和操作 SVG 内容;
  • transcoder 模块能够将 SVG 文档转换为光栅图像;
  • JSVGCanvas 模块,一个 swing 组件,可以用于渲染静态或动态的 SVG 内容。

本文的目的是介绍如何使用Batik组件开发具有SVG功能的JavaTM应用程序。文章包括三个部分。第一部分介绍在应用程序中如何创建和操作SVG内容。第二部分描述如何将SVG图像转换为其它图像格式,例如JPGPNG。最后一部分介绍如何在JavaTM应用程序中增加SVG显示功能。

使用Batik创建SVG内容

Batik提供了两个模块创建或操作SVG内容,两个模块可以单独或组合使用。其中SVG Generator模块能够以SVG格式输出图像,而SVG DOM的实现提供了操作SVG内容的标准API

SVG Generator模块

JavaTM 平台中,所有的渲染操作通过java.awt.Graphics2D 抽象类完成,类中提供了drawRectfillRect drawString等操作。不同类型的显示输出有其特定的具体实现,例如对显示器和打印机输出。JavaTM平台将根据渲染操作的上下文自动选择使用何种具体的实现。因此,开发人员仅仅需要关注Graphics2D 抽象类中的一般API

Batik工具集中提供了一个新的Graphics2D实现类,名为SVGGraphics2D。在SVGGraphics2D中实现的Graphics2D一般API用于生成SVG内容,而不是输出到显示器或打印机。换一种说法,每当JavaTM 调用一个渲染方法,例如drawRectSVGGraphics2D将生成对应的SVG内容(在此为一个<rect>元素)并追加到DOM [2] 树中。最终,一系列渲染操作生成的DOM树表达了开发人员创建的图形,图形内容与其它实现完全一致,唯一的不同是用SVG描述的。下图(图1)显示了SVGGraphics2DDOM树之间的关系。

使用Batik开发SVG应用程序(一)_第1张图片
1: SVG Generator 模块架构图

为了说明SVG Generator 是如何工作的,下面的例子演示如何创建SVGGraphics2D实例,并且象使用常规Graphics2D对象一样绘制图形。之后演示了如何输出生成的DOM树(DOM树不仅仅是SVG文档在内存中的表示,同时也是图形的内存表示)。

 

import java.awt.Rectangle;

import java.awt.Graphics2D;

import java.awt.Color;

import java.io.Writer;

import java.io.OutputStreamWriter;

import java.io.IOException;

 

import org.apache.batik.svggen.SVGGraphics2D;

import org.apache.batik.dom.GenericDOMImplementation;

 

import org.w 3c .dom.Document;

import org.w 3c .dom.DOMImplementation;

 

public class TestSVGGenerator {

 

    public void paint(Graphics2D g2d) {

        g2d.setPaint(Color.red);

        g2d.fill(new Rectangle(10, 10, 100, 100));

    }

 

    public static void main(String [] args) throws IOException {

        // Get a DOMImplementation

        DOMImplementation domImpl =

            GenericDOMImplementation.getDOMImplementation();

        String svgNamespaceURI = "http://www.w3.org/2000/svg";

 

        // Create an instance of org.w 3c .dom.Document

        Document document =

            domImpl.createDocument(svgNamespaceURI, "svg", null);

 

        // Create an instance of the SVG Generator

        SVGGraphics2D svgGenerator = new SVGGraphics2D(document);

 

        // Render into the SVG Graphics2D implementation

        TestSVGGenerator test = new TestSVGGenerator();

        test.paint(svgGenerator);

 

        // Finally, stream out SVG to the standard output using UTF-8

        // character to byte encoding

        boolean useCSS = true; // we want to use CSS style attribute

        Writer out = new OutputStreamWriter(System.out, "UTF-8");

        svgGenerator.stream(out, useCSS);

    }

}

综上所述,SVG Generator能够以SVG格式输出图形。采用SVGGraphics2D类的应用程序不需要修改任何图形代码,简单的用SVGGraphics2D实例代替内建的Graphics2D实现就可以了。

使用SVG Generator,开发人员可以访问生成的DOM树以便进一步操作它,或者直接将其内容写入一个输出流。SVGGraphics2D类可以以很多方式进行定制。例如,用户可以选择自己需要的风格生成方式(使用style属性或XML表达属性),他们还可以改变SVG文档的大小,或者扩展生成器以支持定制的图形格式。更多关于SVG Generator的内容请参见Batik SVG Generator Tutorial [3]

 

SVG文档对象模型

“文档对象模型是一个与平台和语言无关的接口,通过该接口,程序和脚本能够动态访问和更新文档内容、结构和风格。文档可以被进一步处理,处理结果能够与当前显示的页面合成。这就是对W 3C WEB中的DOM相关技术的概述。

-- DOM工作组(W 3C )

SVG中,DOM用于在内存中描述一个SVG文档。它是用于创建和操作<rect> <cirle> 等元素的标准APISVG工作组设计了DOM的扩展,称为SVG DOMSVG DOMSVG规范的一部分,提供了与SVG相关的额外的操作,帮助SVG开发人员完成诸如处理几何体或图形对象,得到字符串长度,或取得一个属性变化值等操作。

Batik提供了一个SVG DOM的实现,可以用于SVG内容的创建和操作。在Batik1.5beta2版本中实现了所有DOM特性,并支持一部分SVG DOM功能。下面的例子说明如何得到Batik SVG DOM实现。

import org.w 3c .dom.DOMImplementation;

import org.apache.batik.dom.svg.SVGDOMImplementation;

 

DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();

通过DOMImplementation能够创建一个Document。下面的例子说明如何使用createDocument方法创建SVG文档,其输入参数中包括SVG名字空间URISVG根元素名称。

import org.apache.batik.dom.svg.SVGDOMImplementation;

import org.w 3c .dom.Document;

 

DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();

String svgNS = "http://www.w3.org/2000/svg";

Document doc = impl.createDocument(svgNS, "svg", null);

最后,通过Document 对象,开发人员能够创建SVG内容。尽管Batik DOM实现是一个针对SVG DOM的实现,但是也能够支持一般的XML文档。下例中在(10, 20)处创建了一个大小为(100, 50)的红色矩形。

 

import org.apache.batik.dom.svg.SVGDOMImplementation;

import org.w 3c .dom.Document;

import org.w 3c .dom.Element;

 

DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();

String svgNS = "http://www.w3.org/2000/svg";

Document doc = impl.createDocument(svgNS, "svg", null);

 

// get the root element (the svg element)

Element svgRoot = doc.getDocumentElement();

 

// set the width and height attribute on the svg root element

svgRoot.setAttributeNS(null, "width", "400");

svgRoot.setAttributeNS(null, "height", "450");

 

// create the rectangle

Element rect = doc.createElementNS(svgNS, "rect");

rect.setAttributeNS(null, "x", "10");

rect.setAttributeNS(null, "y", "20");

rect.setAttributeNS(null, "width", "100");

rect.setAttributeNS(null, "height", "50");

rect.setAttributeNS(null, "style", "fill:red");

 

// attach the rectangle to the svg root element

svgRoot.appendChild(rect);

生成的SVG内容如下:

<svg width="400" height="450">

    <rect x="10" y="20" width="100" height="50" style="fill:red"/>

</svg>

最后,Batik提供了几个使用SVG DOM树的方法。下列两个模块可以用于渲染SVG文档,Transcoder 模块(见“使用Batik渲染SVG内容”一节)和 JSVGCanvas模块(见“使用Batik创建SVG应用程序”一节)。

使用Batik渲染SVG内容

Batik工具集提供了一个Transcoder 模块,其中ImageTranscoder类能够将SVG文档转换为PNGJPG格式的光栅图像。TranscoderInput类和TranscoderOutput类分别对应转换的输入数据和输出数据。Transcoder支持几种不同的输入方式,例如InputStreamDocumentReader,以及不同的输出方式如OutputStream Writer 下面使用PNGTranscoder演示如何将一个SVG文档转换为PNG图像。

import java.io.*;

import org.apache.batik.transcoder.image.PNGTranscoder;

import org.apache.batik.transcoder.TranscoderInput;

import org.apache.batik.transcoder.TranscoderOutput;

 

// Create a PNG transcoder

PNGTranscoder transcoder = new PNGTranscoder();

 

// Create the transcoder input

String svgInputURI = ...;

TranscoderInput input = new TranscoderInput(svgInputURI);

 

// Create the transcoder output

OutputStream ostream = ...;

TranscoderOutput output = new TranscoderOutput(ostream);

 

// Transform the svg document into a PNG image

transcoder.transcode(input, output);

 

// Flush and close the stream

ostream.flush();

ostream.close();

开发人员可以通过TranscodingHints类控制所转换SVG文档的渲染方式(例如使用的CSS媒体或CSS替代风格页),以及转换结果图像的不同选项(例如JPG的编码质量,图像格式的背景色是否支持透明,或图像大小)。为了设置或改变转换选项,用户应创建新的TranscodingHints对象并传给ImageTranscoder。如果只需要设置少量选项,可以通过ImageTranscoder类的addTranscodingHint方法完成。例如可以使用JPEGTranscoder设置JPG的编码质量:

// Create a JPG transcoder

JPEGTranscoder transcoder = new JPEGTranscoder();

transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(.8));

// ...

下面的代码能够控制图像的大小,并可以在所有类型ImageTranscoder中使用:

// Create an ImageTranscoder

ImageTranscoder transcoder = new ...;

transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, new Integer(100));

此外,ImageTranscoder也可以用于处理动态SVG内容。用户可以选择转换选项KEY_EXECUTE_ONLOAD以保证SVG文件渲染处理完成。渲染可以在onload事件派发之前或之后进行,onload事件处理函数将在渲染前执行。因此,脚本可以在SVG内容渲染前对内容进行修改。下例中演示了一个简单的动态SVG文档,其结果图像见图2

<?xml version="1.0" standalone="no"?>

<!DOCTYPE svg PUBLIC "-//W 3C //DTD SVG 1.0//EN"

  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg xmlns="http://www.w3.org/2000/svg"

     xmlns:xlink="http://www.w3.org/1999/xlink"

     width="300" height="300" viewBox="0 0 300 300">

 

    <script type="text/ecmascript"><![CDATA[

    function build(evt) {

        var document = evt.target.ownerDocument;

        var svgNamespaceURI = "http://www.w3.org/2000/svg";

        var e = document.createElementNS(svgNamespaceURI, "rect");

        e.setAttributeNS(null, "x", "50");

        e.setAttributeNS(null, "y", "50");

        e.setAttributeNS(null, "width", "200");

        e.setAttributeNS(null, "height", "200");

        e.setAttributeNS(null, "style", "fill:crimson");

        evt.target.appendChild(e);

    }

   ]]></script>

   <g onload="build(evt)" />

</svg>

使用Batik开发SVG应用程序(一)_第2张图片
2:'onload'事件派发后的结果图像

// Create an ImageTranscoder

ImageTranscoder transcoder = new ...;

transcoder.addTranscodingHint(ImageTranscoder.KEY_EXECUTE_ONLOAD, Boolean.TRUE);

// ...

总结一下,transcoder模块中提供了从SVG文档转换为其它格式的APIImageTranscodertranscoder中的一种,能够将静态或动态SVG内容转换为光栅图像例如PNGJPG。通过设置名为TranscodingHints的某些选项可以控制或修改SVG文档的转换方式。该模块在SVG不能被内置处理的情况下特别有用,例如在IE浏览器中,当然也可以在服务器端的应用程序中使用。

 

你可能感兴趣的:(String,null,文档,import,generator,图形)