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