问题描述
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="2880.0px" width="2300.0px">
<g transform="matrix(1.0,0.0,1.0,0.0)">
<use height="2048.2" id="outer" transform="matrix(1.0,84.6,3841.0)" width="2048.2" xlink:href="#sprite0"/>
</g>
<defs>
<g id="sprite0" transform="matrix(1.0,1024.1,1024.1)">
<use height="2048.2" id="inner" transform="matrix(1.0,-1024.1,-1024.1)" width="2048.2" xlink:href="#sprite1"/>
</g>
<g id="sprite1" transform="matrix(1.0,1024.1)">
<use height="444.35" id="elem" transform="matrix(1.0,-368.6,-180.2)" width="335.35" xlink:href="#sprite4"/>
</g>
<g id="sprite4" transform="matrix(1.0,167.65,222.15)">
<use height="401.35" transform="matrix(0.4578,1.1071,-167.6615,-222.146)" width="732.55" xlink:href="#shape4"/>
</g>
<g id="shape4" transform="matrix(1.0,366.25,200.65)">
<path d="M366.3 -200.65 L366.3 200.7 -366.25 200.7 -366.25 -200.65 366.3 -200.65" fill="#a9a9a9" fill-rule="evenodd" stroke="none"/>
</g>
</defs>
</svg>
我的目标是获取名为 elem 的元素的变换矩阵,该元素位于 inner 内的 outer(以相对于外)。
我这样做是为了得到外部并确认它有一个我可以使用的转换(蜡染已初始化!!)
final SvgoMElement outer = (SvgoMElement)docAsSVGElement.getElementById("outer");
assert outer instanceof SVGLocatable;
assert ((SVGLocatable)outer).getCTM() != null;
assert ((SVGLocatable)outer).getCTM().getA() != 0.0;
但是要到达指定的项目 elem - 我该如何走“GVT”?树,而不是 SVG 文档树?还是我遗漏了一些其他明显的东西(似乎没有人在谈论)?
// this finds the deFinition,not the instance that is ultimately part of the visual "outer"??
final SvgoMElement inner = (SvgoMElement)docAsSVGElement.getElementById("elem");
注意:不能使用 getTransformtoElement()
- 因为 elem 不在实例树中(或似乎不在)。
解决方法
一个答案是导航 SVG 树 - 在每个点提取转换然后将它们组合在一起。
可以使用带有提取的 transform 属性值的 Batik AWTTransformProducer 为每个转换创建一个 AWT AffineTransform。例如
final String transformAttrVal = "matrix(1.0,0.0,1.0,366.25,200.65)";
final AffineTransform transform = AWTTransformProducer.createAffineTransform(transformAttrVal);
然后一直向下串联或自下而上工作(和预串联)。
final AffineTransform sprite0 = ...
final AffineTransform inner = ...
final AffineTransform combined = (AffineTransform)sprite0.clone(); // only if you need sprite0 again ..
combined.concatenate(inner);
combined.concatenate(nextLevelDown);
...
combined.concatenate(shape4);
然后最后将组合应用于每个点。