Skip to content

Commit

Permalink
fix(exporter::svg): broken clip on adjacent paths
Browse files Browse the repository at this point in the history
  • Loading branch information
Myriad-Dreamin committed Oct 31, 2023
1 parent 2a844be commit a9069f8
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
68 changes: 40 additions & 28 deletions exporter/svg/src/frontend/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,10 @@ impl<'m, 't, Feat: ExportFeature> RenderVm for RenderContext<'m, 't, Feat> {

let mut group_ctx = text.shape.add_transform(self, group_ctx, upem);

if let Some(fill) = &group_ctx.text_fill {
let width = if let Some(fill) = &group_ctx.text_fill {
// clip path rect
let clip_id = fill.as_svg_id("tc");
group_ctx.content.push(SvgText::Plain(format!(
r#"<clipPath id="{}" clipPathUnits="userSpaceOnUse">"#,
clip_id
)));
}
let width = text.render_glyphs(upem, |x, g| {
group_ctx.render_glyph(self, x, g);
});
if let Some(fill) = &group_ctx.text_fill {
let fill_id = fill.as_svg_id("tf");
let clip_id = fill.as_svg_id("tc");

// because the text is already scaled by the font size,
// we need to scale it back to the original size.
Expand All @@ -256,16 +246,26 @@ impl<'m, 't, Feat: ExportFeature> RenderVm for RenderContext<'m, 't, Feat> {
.descender
.at(TypstAbs::raw(upem.0 as f64))
.to_pt() as f32;
let width = width.0 * upem.0 / text.shape.size.0;

group_ctx.content.push(SvgText::Plain(format!(
r#"<clipPath id="{}" clipPathUnits="userSpaceOnUse">"#,
clip_id
)));

let width = text.render_glyphs(upem, |x, g| {
group_ctx.render_glyph(self, x, g);
group_ctx.content.push(SvgText::Plain("<path/>".into()));
});

group_ctx
.content
.push(SvgText::Plain(r#"</clipPath>"#.to_owned()));

// clip path rect
let scaled_width = width.0 * upem.0 / text.shape.size.0;
group_ctx.content.push(SvgText::Plain(format!(
r##"<rect fill="url(#{})" width="{:.1}" height="{:.1}" y="{:.1}" clip-path="url(#{})"/>"##,
fill_id, width, upem.0, descender, clip_id
fill_id, scaled_width, upem.0, descender, clip_id
)));

// image glyphs
Expand All @@ -276,7 +276,13 @@ impl<'m, 't, Feat: ExportFeature> RenderVm for RenderContext<'m, 't, Feat> {
}
group_ctx.render_glyph(self, x, g);
});
}

width
} else {
text.render_glyphs(upem, |x, g| {
group_ctx.render_glyph(self, x, g);
})
};

if self.should_render_text_element() {
group_ctx.render_text_semantics_inner(
Expand Down Expand Up @@ -346,35 +352,35 @@ impl<'m, 't, Feat: ExportFeature> FlatRenderVm<'m> for RenderContext<'m, 't, Fea

group_ctx = text.shape.add_transform(self, group_ctx, upem);

if let Some(fill) = &group_ctx.text_fill {
let width = if let Some(fill) = &group_ctx.text_fill {
// clip path rect
let clip_id = fill.as_svg_id("tc");
group_ctx.content.push(SvgText::Plain(format!(
r#"<clipPath id="{}" clipPathUnits="userSpaceOnUse">"#,
clip_id
)));
}
let width = text.render_glyphs(upem, |x, g| {
group_ctx.render_glyph_ref(self, x, g);
});
if let Some(fill) = &group_ctx.text_fill {
let fill_id = fill.as_svg_id("tf");
let clip_id = fill.as_svg_id("tc");

// because the text is already scaled by the font size,
// we need to scale it back to the original size.
// todo: infinite multiplication
let descender = font.descender.0 * upem.0;
let width = width.0 * upem.0 / text.shape.size.0;

group_ctx.content.push(SvgText::Plain(format!(
r#"<clipPath id="{}" clipPathUnits="userSpaceOnUse">"#,
clip_id
)));

let width = text.render_glyphs(upem, |x, g| {
group_ctx.render_glyph_ref(self, x, g);
group_ctx.content.push(SvgText::Plain("<path/>".into()));
});

group_ctx
.content
.push(SvgText::Plain(r#"</clipPath>"#.to_owned()));

// clip path rect
let scaled_width = width.0 * upem.0 / text.shape.size.0;
group_ctx.content.push(SvgText::Plain(format!(
r##"<rect fill="url(#{})" width="{:.1}" height="{:.1}" y="{:.1}" clip-path="url(#{})"/>"##,
fill_id, width, upem.0, descender, clip_id
fill_id, scaled_width, upem.0, descender, clip_id
)));

// image glyphs
Expand All @@ -388,7 +394,13 @@ impl<'m, 't, Feat: ExportFeature> FlatRenderVm<'m> for RenderContext<'m, 't, Fea
}
group_ctx.render_glyph_ref(self, x, g);
});
}

width
} else {
text.render_glyphs(upem, |x, g| {
group_ctx.render_glyph_ref(self, x, g);
})
};

if self.should_render_text_element() {
group_ctx.render_text_semantics_inner(
Expand Down
2 changes: 1 addition & 1 deletion fuzzers/corpora/visualize/gradient-official_00.typ
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


#set text(fill: gradient.linear(red, blue))
#set text(fill: gradient.linear(red, blue), font: "Open Sans")
#let rainbow(content) = {
set text(fill: gradient.linear(..color.map.rainbow))
box(content)
Expand Down

0 comments on commit a9069f8

Please sign in to comment.