You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by rm <ru...@googlemail.com> on 2012/10/18 06:23:49 UTC

keeping DOM and Graphics in sync


hello list,

i am having difficulties grasping the relationship between the SvgBuilder and the DOM tree. for the 
task i am trying to implement, an svg document would travel along a pipeline with several steps,
each step adding stuff to it. 

the things added are nodes copied from other svgs, but they also need to be transformed, so the
initial approach was to create an empty SVG and boot it, then pass it along with it's bridge context,
graphics node and svg graphics 2d through this pipeline, the each step could use regular DOM 
methods to clone elements from other SVGs into the current one, then use SVG specific versions 
of the elements to do transforms etc.

the problem occurs when i try to get the SVG node associated with the "dom version" of it - i can get
a node of the correct type, but i cannot get it's BBox. below is the code i am using and it's output.

a sidenote: what's the best way to make sure that all drawing operations on SVGGraphics2D are 
reflected in the DOM? obviously, i could do stream() and then parse the output again … but that
seems like a rather expensive way to do that … 

any suggestions? what am i missing?

thanks!

.rm


---------------------------------------------------------------------------------------------------------------------------------------------------



			DOMImplementation domImpl = new SVGDOMImplementation();
			SVGDocument svg = (SVGDocument) domImpl.createDocument(
					SvgNamespaceContext.SVG_NS_URI,
					SvgNamespaceContext.SVG_NS_PREFIX, null);

			SVGGraphics2D graphics = new SVGGraphics2D(svg);
			UserAgent userAgent = new UserAgentAdapter();
			DocumentLoader loader = new DocumentLoader(userAgent);
			BridgeContext ctx = new BridgeContext(userAgent, loader);
			ctx.setDynamicState(BridgeContext.DYNAMIC);
			GVTBuilder builder = new GVTBuilder();
			GraphicsNode rootGN = builder.build(ctx, svg);

			System.err.println("===> A");

			// does not work:
			graphics.drawRect(10,10,200,300);
			Document d = ctx.getDocument();
			ctx.get
			System.err.println();
			XmlUtil.transform(ctx.getDocument(), System.err);
			System.err.println();

			System.err.println("===> B");
			
			Element n = ctx.getDocument().createElementNS(SvgNamespaceContext.SVG_NS_URI,"rect");
			SvgUtil.setSvgAttribute(n, "id", "test-circle");
			SvgUtil.setSvgAttribute(n, "x", 2);
			SvgUtil.setSvgAttribute(n, "y", 30);
			SvgUtil.setSvgAttribute(n, "width", 200);
			SvgUtil.setSvgAttribute(n, "height", 100);
			SvgUtil.setSvgAttribute(n, "style", "fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1");
			ctx.getDocument().getDocumentElement().appendChild(n);
			System.err.println();
			XmlUtil.transform(ctx.getDocument(), System.err);
			System.err.println();
			
			
			System.err.println("===> C: ");
			Node n2 = graphics.getRoot(n);
			System.err.println();
			System.err.println(" ========> "+n2);
			System.err.println(" ========> "+((SVGLocatable )n2).getBBox());
			System.err.println();


---------------------------------------------------------------------------------------------------------------------------------------------------

and the output is as follows:


===> A

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
	contentScriptType="text/ecmascript" zoomAndPan="magnify"
	contentStyleType="text/css" preserveAspectRatio="xMidYMid meet"
	version="1.0" />
===> B

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
	contentScriptType="text/ecmascript" zoomAndPan="magnify"
	contentStyleType="text/css" preserveAspectRatio="xMidYMid meet"
	version="1.0">
	<rect y="30"
		style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
		x="2" id="test-circle" width="200" height="100" />
</svg>

===> C: 

 ========> org.apache.batik.dom.svg.SVGOMRectElement@3c3a1834
	    ^^^ this is actually exactly what i expect
 ========> null
	    ^^^ this is not quite what i want … 
 




Re: keeping DOM and Graphics in sync

Posted by rm <ru...@googlemail.com>.
hi again,

some additions to this - if i transform my dom tree, then load it again, then modify attributes in the dom, getBBox works, and the changes are reflected immediately in the call … as below.

so - how can i make batik aware of a dynamically added node so that it works the same way as a node that's been there from the beginning?

.rm


------------------------------------------------------------------------------------------------------------------------------------------------------------------

// test-rect is INSIDE of test-g

Element g1 = (ctx.getDocument().getElementById("test-g"));
			
		
Element r1 = (ctx.getDocument().getElementById("test-rect"));
r1.setAttributeNS(null, "width","200");
r1.setAttributeNS(null, "height","900");
	
for(int i =0; i<5;i++) {
	
	r1.setAttributeNS(null, "transform", "rotate("+i+",0,0)");
	
	System.err.println(" ========> "+((SVGLocatable)g1).getBBox().getWidth());
	System.err.println(" ========> "+((SVGLocatable)g1).getBBox().getHeight());
	System.err.println();
}


------------------------------------------------------------------------------------------------------------------------------------------------------------------

results in a nice, expectable:

 ========> 200.0
 ========> 900.0

 ========> 215.6767
 ========> 903.3534

 ========> 231.2877
 ========> 906.43164

 ========> 246.82828
 ========> 909.23376

 ========> 262.29364
 ========> 911.7589

Re: keeping DOM and Graphics in sync

Posted by DeWeese Thomas <th...@gmail.com>.
Hi Ruben,
   Sorry w/o knowing what SvgUtil.setSvgAttribute does it's hard to know for sure but the
raw 'setAttributeNS' version looks good to me so if the SvgUtil version was different that may be it.

   Thomas

On Oct 18, 2012, at 6:57 AM, rm <ru...@googlemail.com> wrote:

> 
> 
> ***cough*** it seems to work now … if somebody knows why? this is the same code after fiddling with it:
> 
> something about attribute namespaces?
> 
> 
> 			DOMImplementation domImpl = new SVGDOMImplementation();
> 			SVGDocument svg = (SVGDocument) domImpl.createDocument(
> 					SvgNamespaceContext.SVG_NS_URI,
> 					SvgNamespaceContext.SVG_NS_PREFIX, null);
> 
> 			SVGGraphics2D graphics = new SVGGraphics2D(svg);
> 			UserAgent userAgent = new UserAgentAdapter();
> 			DocumentLoader loader = new DocumentLoader(userAgent);
> 			BridgeContext ctx = new BridgeContext(userAgent, loader);
> 			ctx.setDynamicState(BridgeContext.DYNAMIC);
> 			GVTBuilder builder = new GVTBuilder();
> 			GraphicsNode rootGN = builder.build(ctx, svg);
> 
> 			// create a G node
> 			Element g = svg.createElementNS(SvgNamespaceContext.SVG_NS_URI,SVG12Constants.SVG_G_TAG);
> 			g.setAttributeNS(null,"id", "test-g");
> 			svg.getDocumentElement().appendChild(g);
> 			
> 			Element n = svg.createElementNS(SvgNamespaceContext.SVG_NS_URI,SVG12Constants.SVG_RECT_TAG);
> 			n.setAttributeNS(null,"id", "test-rect");
> 			n.setAttributeNS(null,"x", "5");
> 			n.setAttributeNS(null,"y", "15");
> 			n.setAttributeNS(null,"width", "300");
> 			n.setAttributeNS(null,"height", "150");
> 			n.setAttributeNS(null,"fill", "orange");
> 			n.setAttributeNS(null,"transform", "rotate(10,4,2)");
> 			g.appendChild(n);
> 
> 			System.err.println(" ========> g "+((SVGLocatable)g).getBBox().getWidth());
> 			System.err.println(" ========> g "+((SVGLocatable)g).getBBox().getHeight());
> 			System.err.println(" ========> r "+((SVGLocatable)n).getBBox().getWidth());
> 			System.err.println(" ========> r "+((SVGLocatable)n).getBBox().getHeight());
> 
> 			System.err.println();
> 			XmlUtil.transform(svg, System.err);
> 			System.err.println();
> 			
> 			ByteArrayOutputStream baos = new ByteArrayOutputStream();
> 			XmlUtil.transform(ctx.getDocument(), baos);
> 			
> 			dByte = baos.toByteArray();
> 			
> 			
> 			System.err.flush(); 


Re: keeping DOM and Graphics in sync

Posted by rm <ru...@googlemail.com>.

***cough*** it seems to work now … if somebody knows why? this is the same code after fiddling with it:

something about attribute namespaces?


			DOMImplementation domImpl = new SVGDOMImplementation();
			SVGDocument svg = (SVGDocument) domImpl.createDocument(
					SvgNamespaceContext.SVG_NS_URI,
					SvgNamespaceContext.SVG_NS_PREFIX, null);

			SVGGraphics2D graphics = new SVGGraphics2D(svg);
			UserAgent userAgent = new UserAgentAdapter();
			DocumentLoader loader = new DocumentLoader(userAgent);
			BridgeContext ctx = new BridgeContext(userAgent, loader);
			ctx.setDynamicState(BridgeContext.DYNAMIC);
			GVTBuilder builder = new GVTBuilder();
			GraphicsNode rootGN = builder.build(ctx, svg);

			// create a G node
			Element g = svg.createElementNS(SvgNamespaceContext.SVG_NS_URI,SVG12Constants.SVG_G_TAG);
			g.setAttributeNS(null,"id", "test-g");
			svg.getDocumentElement().appendChild(g);
			
			Element n = svg.createElementNS(SvgNamespaceContext.SVG_NS_URI,SVG12Constants.SVG_RECT_TAG);
			n.setAttributeNS(null,"id", "test-rect");
			n.setAttributeNS(null,"x", "5");
			n.setAttributeNS(null,"y", "15");
			n.setAttributeNS(null,"width", "300");
			n.setAttributeNS(null,"height", "150");
			n.setAttributeNS(null,"fill", "orange");
			n.setAttributeNS(null,"transform", "rotate(10,4,2)");
			g.appendChild(n);

			System.err.println(" ========> g "+((SVGLocatable)g).getBBox().getWidth());
			System.err.println(" ========> g "+((SVGLocatable)g).getBBox().getHeight());
			System.err.println(" ========> r "+((SVGLocatable)n).getBBox().getWidth());
			System.err.println(" ========> r "+((SVGLocatable)n).getBBox().getHeight());

			System.err.println();
			XmlUtil.transform(svg, System.err);
			System.err.println();
			
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			XmlUtil.transform(ctx.getDocument(), baos);
			
			dByte = baos.toByteArray();
			
			
			System.err.flush();