svg devzone

"I'll let you figure out
which one has been slow in supporting SVG." Tim Berners-Lee

Creer et afficher un SVG avec Batik

Sun, 21 Jun

Creer et afficher un graphe SVG

Nous savons importer un fichier locale SVG et l'afficher dans une zone canvas avec les librairies Batik.
Nous allons dans ce petit tutoriel, creer un simple SVG en utilisant le Java2D et l'afficher directement dans notre "frame".

Un document Svg s'appuie sur sa structure Xml et peut être manipuler grâce à l'arbre DOM.
Pour générer un tel document à partir de code Java, Batik implémente la classe abstraite java.awt.Graphics2D à travers la classe SVGGraphics2D.

Les étapes nécessaires

Elles sont simples et évidentes : le dessin (draw) et le rendu (render).
Notre SVGGraphics2D hérite de la classe AbstractGraphics2D qui elle-même hérite de java.awt.Graphics2D.

Nous pouvons donc utiliser toutes les méthodes définies dans ces classes et plus particulièrement de celle de Graphics2D.
Dans notre exemple nous utiliserons fill et draw avec comme argument une forme (shape).

Le rendu se fait dans notre canvas JSVGCanvas , composant de notre fenêtre (frame) d'application.
Cette classe comme vu dans un précédent article est un composant Swing permettant d'afficher un document Svg.

Le lien entre les deux , dessin et rendu, et le noeud racine (root) obtenu à l'aide de la méthode getRoot(Element root) et passé à notre canvas de rendu via la méthode setSvgDocument.

Il suffit d'organiser notre code autour de ces différentes étapes.

Organisation de notre code

Nous devons donc créer un objet SVGGraphic2D.
Pour cela nous avons besoin d'implémenter un document SVG. Notre méthode main se chargera de créer ce nouvel objet.

Ensuite nous dessinerons une simple forme (shape) avec notre instance SVGGraphics2D.
Nous utiliserons les méthodes héritées de Graphics2D. Nous récupererons le noeud racine (root) que nous passerons à notre document.

Pour le rendu nous ajouterons notre canvas svg à l'objet Frame en n'oubliant pas de lui passer le document.
Notre Document SVG se retrouve donc dans toute les étapes de notre application; c'est celui que nous allons commencer par initialiser.

Construction de la référence document SVG

Pour construire notre document SVG, nous allons utiliser la classe SVGDOMImplementation qui implémente l'interface DOMImplementation de org.w3c.dom.
Cet objet nous permet de créer directement un Document Svg à l'aide de la méthode createDocument.

Cette méthode prend 3 arguments : l'espace de nom, le nom qualifié,doctype.
L'espace de nom est une constante de SVGDOMIplementation , le nom est bien sûr svg, et le doctype est non spécifié soit null ( nous n'avons pas besoin de vérifier le document).

	DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
	doc = (SVGDocument) impl.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI,
	                                        "svg",
						null);

Passage de référence à l'objet SVGGraphics2D

Il faut que notre objet connaisse le document sur lequel on va travailler.
On le passe en argument de notre constructeur SVGGraphics2D.

	SVG2D = new SVGGraphics2D(doc);

Ce code est ajouté à la suite du précédent et est appellé depuis notre main

	public class SVGGraphicApp {
	 // nos variable de classe
	 SVGDocument doc = null;
	 SVGGraphics2D SVG2D = null;
	 ....
	 
	public SVGGraphicApp() {
	 DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
	 doc = (SVGDocument) impl.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI,
	                                        "svg",
						null);  
	 SVG2D = new SVGGraphics2D(doc);
	 }
	 
	 // autres methodes
	 ...
	 
	 public static void main(String[]args) {
	  SVGGraphicApp app = new SVGGraphicApp();
	  ...
	 }

Dessiner une forme

Maintenant que nous avons une instance de l'objet Graphics2D à travers notre objet SVGGraphics2D nous pouvons y appliquer les méthodes de cette API java.

Chaque fois que nous voulons modifier notre dessin, nous pouvons le faire ici.
Nous nous plaçons ici dans le cas d'une simple application statique, où nous codons en dur.

Notre objet (SVG)Graphics2D agit comme une rendering engine ou bien encore comme notre espace de dessin.
Remaque : Une fois le dessin achevé celui-ci ne sera pas encore afficher

Pour notre simple exemple nous allons dessiner du texte, un cercle et quelques lignes générées pour faire joli.
Mais ici c'est votre imagination qui doit prendre le pas.

	// on attribue une couleur
	SVG2D.setPaint(Color.black);
	// drawString(String,x,y)
	SVG2D.drawString("un cercle",20,20) 
	
	// on change la couleur
	SVG2D.setPaint(Color.red);
	// une forme elliptique
	Shape cercle = new Ellipse2D.Double(80,80,50,50); 
	SVG2D.fill(cercle);
	
	// quelques lignes pour faire joli
	// la taille de notre canvas
	Dimension d = SVG2D.getSVGCanvasSize();
	int nbreLigne = 25;
	for(int i = 0; i < nbreLigne; i++){
		double ratio = (double)i / (double)nbreLigne;
		Line2D line = new Line2D.Double(0,
						ratio * d.height,
						ratio * d.width,
						d.height);
		SVG2D.draw(line);
		}

Mais ce n'est pas suffisant.
C'est ici que nous associons notre document SVG avec nos formes dessinées.

	Element root = doc.getDocumentElement();
	SVG2D.getRoot(root);

Nous n'avons pas à nous occuper de la façon dont cela fonctionne pour l'instant. A partir de maintenant il nous suffit d'envoyer notre document SVG à notre canvas.
Le rôle de l'objet SVG2D est terminé pour notre example et il a créé la structure Dom nécessaire.

Afficher le SVG

Nous sommes en pays connu pour ceux qui ont lu mon premier article sur Batik et Svg et pour tout ceux qui connaissent Graphics2D.
Nous avons toujours besoin d'un cadre d'affichage (notre fenetre Frame) et un espace pour notre Svg (canvas).

Nous allons nous passer du Panel et implémenter notre canvas directement à la frame en utilisant la méthode getContentPanel(). Nous rendons la fenêtre visible (c'est mieux) et un comportement de fermeture de celle-ci par defaut.

Le plus important dans cette partie est l'association du document SVG et de notre zone d'affichage canvas.
Batik fournit la méthode setSVGDocument() qui failite bien la tâche.

public void renderingSVG() {
	canvas = new JSVGCanvas();
	frame = new JFrame();
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.getContentPanel().add(canvas);
	
	// on associe le document SVG au canvas
	canvas.setSVGDocument(doc);  
	
	frame.pack();
	frame.setVisible();
	} 

Le code est terminé ; ous avez tout ce qu'il faut pour le réaliser.
Je vous conseille d'utiliser un IDE tel Eclipse ou Netbeans et d'en profiter pour lire les aide de la javadoc qui s'affiche sur le différentes méthodes et propriétés.

Petites astuces pour cela

Survoler ou faites un clic gauche sur la méthode pour afficher l'aide javadoc.
F2 (focus) pour "geler la fenetre d'aide.
Echap (Escape) pour fermer la fenetre d'aide.
Cliquer sur la méthode ou propriété et appuye + ou - longuement sur CTRL pour ouvrir un lien vers celle-ci.
Tester également Ctrl + o

Le code complet

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;

import javax.swing.JFrame;

import org.apache.batik.swing.*;
import org.apache.batik.svggen.*;
import org.apache.batik.dom.svg.SVGDOMImplementation;

import org.w3c.dom.*;
import org.w3c.dom.svg.*;

public class SvgGraphicApp {
	SVGDocument doc = null;
	SVGGraphics2D SVG2d = null;
	/**
	 * 
	 */
	JFrame frame = null;
	JSVGCanvas canvas = null;
	
	public SvgGraphicApp(){
		DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
		String svgns  = SVGDOMImplementation.SVG_NAMESPACE_URI;
		doc = (SVGDocument) impl.createDocument(svgns, "svg", null);
		
		SVG2d = new SVGGraphics2D(doc);
	}
	
	public void renderingSVG(){
		canvas = new JSVGCanvas();
		frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(canvas);
		canvas.setSVGDocument(doc);
		
		frame.pack();
		frame.setVisible(true);
	}
	
	public void drawSvg(){
		SVG2d.setPaint(Color.black);
		SVG2d.drawString("un cercle",20, 20);
		
		SVG2d.setPaint(Color.red);
		Shape cercle = new Ellipse2D.Double(80,80,50,50);
		SVG2d.fill(cercle);
		SVG2d.setSVGCanvasSize(new Dimension(200,200));
		
		Dimension d = SVG2d.getSVGCanvasSize();
		for(int i = 0 ; i <25 ; i++){
			double ratio = (double)i / (double)25;
			Line2D line = new Line2D.Double(0,ratio * d.height,ratio * d.width,d.height);
			SVG2d.draw(line);
		}
		Element root = doc.getDocumentElement();
		SVG2d.getRoot(root);
	}
	
	
	public static void main(String[]args){
		SvgGraphicApp svgApp = new SvgGraphicApp();
		svgApp.drawSvg();
		svgApp.renderingSVG();
	}
}
resultat au format png de l'application java + svg + batik

Articles

svg-developers at yahoo group svg

Re: SVG in html5

Yes I want to understand how much is expected from an editing tool which does the validation and highlightling of all the tags and attributes and provides...

... lire la suite