Fixing svg parsing

1. Order of application of transformations: While processing a
path the order of transformations are from the inner most to the
outer most.

For example: In the graphic

<svg>
  <g transform=A>
    <g transform=B>
      <path ... />
    </g>
  </g>
</svg>

Path control points will be calculated by pre-multiplying
with A * B, not B * A as per the current code.

2. Applying transformation to clip paths: The transformations
of the ancestors are applied to the clip path property of a path.

For example:

<svg>
  <defs>
    <clipPath id="clippath">
      <path id="clipper" ... />
    <clipPath/>
  </defs>
  <g transform=A>
    <path id="clippee" clip-path="url(#clippath)" ... />
  </g>
</svg>

Then, the transform A is applied to both the clippee and
the clipper.
This commit is contained in:
vrroom 2021-05-28 00:26:41 +05:30
parent 8f63dc7e48
commit f51936d439
1 changed files with 5 additions and 5 deletions

View File

@ -97,8 +97,7 @@ impl SVGScene {
clip_outline: &mut Option<Outline>) { clip_outline: &mut Option<Outline>) {
let mut state = (*state).clone(); let mut state = (*state).clone();
let node_transform = usvg_transform_to_transform_2d(&node.transform()); let node_transform = usvg_transform_to_transform_2d(&node.transform());
state.transform = node_transform * state.transform; state.transform = state.transform * node_transform;
match *node.borrow() { match *node.borrow() {
NodeKind::Group(ref group) => { NodeKind::Group(ref group) => {
if group.filter.is_some() { if group.filter.is_some() {
@ -107,10 +106,11 @@ impl SVGScene {
if group.mask.is_some() { if group.mask.is_some() {
self.result_flags.insert(BuildResultFlags::UNSUPPORTED_MASK_ATTR); self.result_flags.insert(BuildResultFlags::UNSUPPORTED_MASK_ATTR);
} }
let mut transformed_outline = None;
if let Some(ref clip_path_name) = group.clip_path { if let Some(ref clip_path_name) = group.clip_path {
if let Some(clip_outline) = self.clip_paths.get(clip_path_name) { if let Some(clip_outline) = self.clip_paths.get(clip_path_name) {
let mut clip_path = ClipPath::new((*clip_outline).clone()); transformed_outline = Some((*clip_outline).clone().transformed(&state.transform));
let mut clip_path = ClipPath::new(transformed_outline.clone().unwrap());
clip_path.set_clip_path(state.clip_path); clip_path.set_clip_path(state.clip_path);
clip_path.set_name(format!("ClipPath({})", clip_path_name)); clip_path.set_name(format!("ClipPath({})", clip_path_name));
let clip_path_id = self.scene.push_clip_path(clip_path); let clip_path_id = self.scene.push_clip_path(clip_path);
@ -119,7 +119,7 @@ impl SVGScene {
} }
for kid in node.children() { for kid in node.children() {
self.process_node(&kid, &state, clip_outline) self.process_node(&kid, &state, &mut transformed_outline)
} }
} }
NodeKind::Path(ref path) if state.path_destination == PathDestination::Clip => { NodeKind::Path(ref path) if state.path_destination == PathDestination::Clip => {