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 Henric Rosvall <he...@opv.se> on 2006/10/12 16:51:35 UTC

flowRoot and getTransformToElement

Hi !

I'm, trying to implement multiline-text in my software by adding support for modifying flowRoot-elements.
To get information about where an element is located, I traverse down to the objects in flowRegion, and get the BBox of those objects (since flowRoot, flowRegion and such doesn't implement SVGLocatable), and it works perfectly - at least until I try to get the transform from the document root down to the obects in the flowRegion. It doesn't seem to matter how much I've moved or rotated the flowRoot-Element, getTransformToElement() still returns a SVGMatrix that shows no transformation what so ever.

Here's a cut out example of the outputted SVG after I've opened the example SVG in Batik (flowText.svg), and played around with it a bit:

      <flowRoot font-size="20" id="maintext_0" transform="matrix(0.9591868 8.604429E-4 -0.41767913 0.73524845 188.0 46.0)">
         <flowRegion>
	    <rect x="17" width="200" height="400" y="80"/>
	    <rect x="233" width="200" height="400" y="80"/>
         </flowRegion>

         <flowDiv>
	    <flowPara indent="20" margin-bottom="10">This is an <flowSpan fill="crimson" font-size="40">ex­ample</flowSpan> of a very long string that is split ‍across multi­ple lines via text wrap­ping.</flowPara>
         </flowDiv>
      </flowRoot>

As you can see there are some interesting matrix-transformations on the flowRoot-element, but when trying to get the transform to the first rect in flowRegion, it still returns a SVGMatrix without any transform - dispite the fact that the rendering works perfectly.

The call I make to get the transform to the SVGElement e (which in this case just happens to be the first rect in flowRegion): 
((SVGSVGElement)e.getOwnerDocument().getDocumentElement()).getTransformToElement((SVGElement)e);

I'm using Batik 1.6. Would it help to upgrade to the latest build, or are there some other way to solve this? Or am I simply doing something very wrong?

Regards
Henric Rosvall



---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


RE: flowRoot and getTransformToElement

Posted by th...@kodak.com.
Hi Henric,

"Henric Rosvall" <he...@opv.se> wrote on 10/13/2006 05:23:06 AM:

> I solved it, although the solution might not be 100% (only supprots 
matrix-
> transformations, not translate, scale, and skew-commands). But since I 
always 
> use matrix-tranformations in my software, it works perfectly for me.

    Just as an FYI, the org.apache.batik.dom.svg12.SVGOMFlowRootSVGElement 

in the trunk SVN version of Batik does have all of the SVGLocatible 
methods 
(although it doesn't actually implement SVGLocatible, normally we pick
the public interfaces up from the W3C DOM interface but there wasn't
one for the flow stuff and we forgot to implement the obvious SVG 
interfaces, we didn't notice sooner since for ECMAscript it doesn't 
matter).

> So if anyone is having the same problem as I had, here's a bit of code 
that 
> will solve it:
> 
> This code is extracted from a special FlowRootSVGElement-class where 
> getElement() returns the flowRoot-element.
> 
> 
> 
>    /**
>     * Retrieves the total transformation Matrix from the documents root 
to this element
>     * Since the flowRoot-object itself is not Locatable, get the first 
Element
> in flowRegion and calculate the transformation-matrix to that object 
instead. 
>     * @return
>     */
>    public SVGMatrix getDocumentTransformToThisElement()
>    {
>       try
>       {
>          NodeList nl = getFlowRegionNodes(getElement());
>          Element e = null;
>          if (nl != null && nl.getLength() > 0)
>             for (int x = 0; x < nl.getLength(); x++)
>                if (nl.item(x).getNodeType() == Node.ELEMENT_NODE)
>                {
>                   e = (Element)nl.item(x);
>                   break;
>                }
> 
>          if (e != null)
>             return getTransformToElement(e).inverse();
>       }
>       catch(Exception ex)
>       {
>            ex.printStackTrace();
>       }
> 
>       return null;
>    }
> 
> 
>    /**
>     * A number of the flowRoot:s elements doesn't support SVGLocatable, 
which 
> has the effect that
>     * that getDocumentElement().getTransformToElement() will not work. 
So this
> method retrieves
>     * all the transform-data by getting it from SVGLocatable when 
possible, 
> and otherwise extracting
>     * it from the matrix-data in the transform-tag - all the way from 
the 
> object up to the DocumentElement. 
>     * 
>     * @param e
>     * @return
>     */
>    protected SVGMatrix getTransformToElement(Element e)
>    {
>        // Initialize our node's Current Transformation Matrix
> 
> 
>        SVGMatrix CTM = new SVGOMMatrix(new AffineTransform(1d, 0d, 0d, 
1d, 0d, 0d));
>        // Work our way bacwards through the ancestor nodes stopping at 
the
>        // SVG Document
>        do
>        {
>           if (e.getNodeType() == Node.ELEMENT_NODE)
>           {
>               // Multiply the new CTM with what we've accumulated so far
>              try {
>              SVGLocatable loc_e = (SVGLocatable)e;
>               CTM = loc_e.getCTM().multiply(CTM);
>              } catch (Exception ex)
>              {
>                 // Not SVGLocatable, extract the matrix-data manually 
from the
> transform-tag
>                 AffineTransform af = 
FlowRootSvgElement.GetObjTransform(e, true);
>                 if (af != null)
>                 {
>                    SVGMatrix m = new SVGOMMatrix(af);
>                    CTM = m.multiply(CTM);
>                 }
>              }
>           }
>        }
>        while ( ( e = (Element)e.getParentNode() ) != 
e.getOwnerDocument().
> getDocumentElement() );
> 
>        return CTM;
>    }
> 
> 
>    /**
>     *  Will return the current transformation of the Element
>     * @param el
>     * @param includeTranslation If the translation-data should be 
removed from
> the translation or not
>     * @return
>     */
>    public static AffineTransform GetObjTransform(Element el, boolean 
includeTranslation)
>    {
>       float values[] = new float[] {1, 0, 0, 1, 0, 0};
> 
>       // get the value of the transform-node
>       String tmpTransform = el.getAttribute("transform");
> 
>       // if transform exists, extract the values
>       if (tmpTransform != null && tmpTransform != "")
>       {
>          try
>          {
>             Pattern p = 
Pattern.compile("matrix\\((\\-{0,1}\\d{1,}\\.{0,1}
> 
[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,
> 
1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.
> {0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\)"); 
>             Matcher m = p.matcher(tmpTransform);
>             m.find();
> 
>             for(int x = 0; x < 6; x++)
>                values[x] = Float.valueOf(m.group(x+1)).floatValue();
> 
>             if (!includeTranslation)   // Remove the translation
>                values[4] = values[5] = 0;
> 
>          }
>          catch (Exception ex)
>          {
>             System.out.println(tmpTransform);
>             ex.printStackTrace();
>             return null;
>          }
>       } 
> 
>       // Create a transformation-object from the values in transfom
>       return new AffineTransform(values);
>    }
> 
> Regards
> Henric Rosvall
> 
> 
> -----Original Message-----
> From: Henric Rosvall [mailto:henric@opv.se] 
> Sent: den 12 oktober 2006 16:52
> To: batik-users@xmlgraphics.apache.org
> Subject: flowRoot and getTransformToElement
> 
> 
> Hi !
> 
> I'm, trying to implement multiline-text in my software by adding support 
for 
> modifying flowRoot-elements. To get information about where an element 
is 
> located, I traverse down to the objects in flowRegion, and get the BBox 
of 
> those objects (since flowRoot, flowRegion and such doesn't implement 
> SVGLocatable), and it works perfectly - at least until I try to get the 
> transform from the document root down to the obects in the flowRegion. 
It 
> doesn't seem to matter how much I've moved or rotated the 
flowRoot-Element, 
> getTransformToElement() still returns a SVGMatrix that shows no 
transformation
> what so ever.
> 
> Here's a cut out example of the outputted SVG after I've opened the 
example 
> SVG in Batik (flowText.svg), and played around with it a bit:
> 
>       <flowRoot font-size="20" id="maintext_0" 
transform="matrix(0.9591868 8.
> 604429E-4 -0.41767913 0.73524845 188.0 46.0)">
>          <flowRegion>
>        <rect x="17" width="200" height="400" y="80"/>
>        <rect x="233" width="200" height="400" y="80"/>
>          </flowRegion>
> 
>          <flowDiv>
>        <flowPara indent="20" margin-bottom="10">This is an <flowSpan 
> fill="crimson" font-size="40">ex­ample</flowSpan> of a very long string 
that 
> is split �across multi­ple lines via text wrap­ping.</flowPara>
>          </flowDiv>
>       </flowRoot>
> 
> As you can see there are some interesting matrix-transformations on the 
> flowRoot-element, but when trying to get the transform to the first rect 
in 
> flowRegion, it still returns a SVGMatrix without any transform - dispite 
the 
> fact that the rendering works perfectly.
> 
> The call I make to get the transform to the SVGElement e (which in this 
case 
> just happens to be the first rect in flowRegion): 
> ((SVGSVGElement)e.getOwnerDocument().getDocumentElement()).
> getTransformToElement((SVGElement)e);
> 
> I'm using Batik 1.6. Would it help to upgrade to the latest build, or 
are 
> there some other way to solve this? Or am I simply doing something very 
wrong?
> 
> Regards
> Henric Rosvall
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
> For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
> For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


RE: flowRoot and getTransformToElement

Posted by Henric Rosvall <he...@opv.se>.
Hi again !

I solved it, although the solution might not be 100% (only supprots matrix-transformations, not translate, scale, and skew-commands). But since I always use matrix-tranformations in my software, it works perfectly for me.

So if anyone is having the same problem as I had, here's a bit of code that will solve it:

This code is extracted from a special FlowRootSVGElement-class where getElement() returns the flowRoot-element.



	/**
	 * Retrieves the total transformation Matrix from the documents root to this element
	 * Since the flowRoot-object itself is not Locatable, get the first Element in flowRegion and calculate the transformation-matrix to that object instead. 
	 * @return
	 */
	public SVGMatrix getDocumentTransformToThisElement()
	{
		try
		{
			NodeList nl = getFlowRegionNodes(getElement());
			Element e = null;
			if (nl != null && nl.getLength() > 0)
				for (int x = 0; x < nl.getLength(); x++)
					if (nl.item(x).getNodeType() == Node.ELEMENT_NODE)
					{
						e = (Element)nl.item(x);
						break;
					}
			
			if (e != null)
				return getTransformToElement(e).inverse();
		}
		catch(Exception ex)
		{
	        ex.printStackTrace();
		}
		
		return null;
	}


	/**
	 * A number of the flowRoot:s elements doesn't support SVGLocatable, which has the effect that
	 * that getDocumentElement().getTransformToElement() will not work. So this method retrieves
	 * all the transform-data by getting it from SVGLocatable when possible, and otherwise extracting
	 * it from the matrix-data in the transform-tag - all the way from the object up to the DocumentElement. 
	 *  
	 * @param e
	 * @return
	 */
	protected SVGMatrix getTransformToElement(Element e)
	{
	    // Initialize our node's Current Transformation Matrix

		
	    SVGMatrix CTM = new SVGOMMatrix(new AffineTransform(1d, 0d, 0d, 1d, 0d, 0d));
	    // Work our way bacwards through the ancestor nodes stopping at the
	    // SVG Document
	    do
	    {
	    	if (e.getNodeType() == Node.ELEMENT_NODE)
	    	{
		        // Multiply the new CTM with what we've accumulated so far
			    try {
		    	SVGLocatable loc_e = (SVGLocatable)e;
		        CTM = loc_e.getCTM().multiply(CTM);
			    } catch (Exception ex)
			    {
			    	// Not SVGLocatable, extract the matrix-data manually from the transform-tag
			    	AffineTransform af = FlowRootSvgElement.GetObjTransform(e, true);
			    	if (af != null)
			    	{
			    		SVGMatrix m = new SVGOMMatrix(af);
			    		CTM = m.multiply(CTM);
			    	}
			    }
	    	}
	    }
	    while ( ( e = (Element)e.getParentNode() ) != e.getOwnerDocument().getDocumentElement() );

	    return CTM;
	}


	/**
	 *  Will return the current transformation of the Element
	 * @param el
	 * @param includeTranslation If the translation-data should be removed from the translation or not
	 * @return
	 */
	public static AffineTransform GetObjTransform(Element el, boolean includeTranslation)
	{
		float values[] = new float[] {1, 0, 0, 1, 0, 0};

		// get the value of the transform-node
		String tmpTransform = el.getAttribute("transform");
		
		// if transform exists, extract the values
		if (tmpTransform != null && tmpTransform != "")
		{
			try
			{
				Pattern p = Pattern.compile("matrix\\((\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\s(\\-{0,1}\\d{1,}\\.{0,1}[\\dE+-]{0,})\\)");	
				Matcher m = p.matcher(tmpTransform);
				m.find();
				
				for(int x = 0; x < 6; x++)
					values[x] = Float.valueOf(m.group(x+1)).floatValue();
				
				if (!includeTranslation)	// Remove the translation
					values[4] = values[5] = 0;
				
			}
			catch (Exception ex)
			{
				System.out.println(tmpTransform);
				ex.printStackTrace();
				return null;
			}
		}	
		
		// Create a transformation-object from the values in transfom
		return new AffineTransform(values);
	}

Regards
Henric Rosvall


-----Original Message-----
From: Henric Rosvall [mailto:henric@opv.se] 
Sent: den 12 oktober 2006 16:52
To: batik-users@xmlgraphics.apache.org
Subject: flowRoot and getTransformToElement


Hi !

I'm, trying to implement multiline-text in my software by adding support for modifying flowRoot-elements. To get information about where an element is located, I traverse down to the objects in flowRegion, and get the BBox of those objects (since flowRoot, flowRegion and such doesn't implement SVGLocatable), and it works perfectly - at least until I try to get the transform from the document root down to the obects in the flowRegion. It doesn't seem to matter how much I've moved or rotated the flowRoot-Element, getTransformToElement() still returns a SVGMatrix that shows no transformation what so ever.

Here's a cut out example of the outputted SVG after I've opened the example SVG in Batik (flowText.svg), and played around with it a bit:

      <flowRoot font-size="20" id="maintext_0" transform="matrix(0.9591868 8.604429E-4 -0.41767913 0.73524845 188.0 46.0)">
         <flowRegion>
	    <rect x="17" width="200" height="400" y="80"/>
	    <rect x="233" width="200" height="400" y="80"/>
         </flowRegion>

         <flowDiv>
	    <flowPara indent="20" margin-bottom="10">This is an <flowSpan fill="crimson" font-size="40">ex­ample</flowSpan> of a very long string that is split ‍across multi­ple lines via text wrap­ping.</flowPara>
         </flowDiv>
      </flowRoot>

As you can see there are some interesting matrix-transformations on the flowRoot-element, but when trying to get the transform to the first rect in flowRegion, it still returns a SVGMatrix without any transform - dispite the fact that the rendering works perfectly.

The call I make to get the transform to the SVGElement e (which in this case just happens to be the first rect in flowRegion): 
((SVGSVGElement)e.getOwnerDocument().getDocumentElement()).getTransformToElement((SVGElement)e);

I'm using Batik 1.6. Would it help to upgrade to the latest build, or are there some other way to solve this? Or am I simply doing something very wrong?

Regards
Henric Rosvall



---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org