Commit f64450a3 authored by RazrFalcon's avatar RazrFalcon

Added nested 'clipPath' support.

parent 128e38b7
......@@ -8,11 +8,12 @@ This changelog also contains an important changes in dependencies.
## [Unreleased]
### Added
- (resvg) Nested `clipPath` support.
- (rendersvg) `font-family`, `font-size` and `languages` to args.
- (usvg) `systemLanguage` attribute support.
- (usvg) Default font family and size is configurable now.
- (c-api) `RESVG_ERROR_PARSING_FAILED`.
- (c-api) `font_family`, `font_size` and `languages` to `resvg_options`.
- (usvg) Default font family and size is configurable now.
- (usvg) `systemLanguage` attribute support.
- (rendersvg) `font-family`, `font-size` and `languages` to args.
### Changed
- (rendersvg) Use `gumdrop` instead of `getopts`.
......
......@@ -30,7 +30,7 @@ travis-ci = { repository = "RazrFalcon/resvg" }
[dependencies]
log = "0.4.5"
#usvg = "0.2"
usvg = { git = "https://github.com/RazrFalcon/usvg", rev = "82e83bb" }
usvg = { git = "https://github.com/RazrFalcon/usvg", rev = "9b7699a" }
#usvg = { path = "../usvg" }
# cairo backend
cairo-rs = { version = "0.5", features = ["png"], optional = true }
......
......@@ -66,12 +66,23 @@ pub fn apply(
// e-clipPath-012.svg
text::draw(&node.tree(), text, opt, &clip_cr);
}
usvg::NodeKind::Group(ref g) => {
clip_group(&node, g, opt, bbox, layers, &clip_cr);
}
_ => {}
}
clip_cr.set_matrix(matrix);
}
if let Some(ref id) = cp.clip_path {
if let Some(ref clip_node) = node.tree().defs_by_id(id) {
if let usvg::NodeKind::ClipPath(ref cp) = *clip_node.borrow() {
apply(clip_node, cp, opt, bbox, layers, cr);
}
}
}
cr.set_matrix(cairo::Matrix::identity());
cr.set_source_surface(&*clip_surface, 0.0, 0.0);
cr.set_operator(cairo::Operator::DestOut);
......@@ -83,3 +94,62 @@ pub fn apply(
// Reset source to unborrow the `clip_surface` from the `Context`.
cr.reset_source_rgba();
}
fn clip_group(
node: &usvg::Node,
g: &usvg::Group,
opt: &Options,
bbox: Rect,
layers: &mut CairoLayers,
cr: &cairo::Context,
) {
if let Some(ref id) = g.clip_path {
if let Some(ref clip_node) = node.tree().defs_by_id(id) {
if let usvg::NodeKind::ClipPath(ref cp) = *clip_node.borrow() {
// If a `clipPath` child also has a `clip-path`
// then we should render this child on a new canvas,
// clip it, and only then draw it to the `clipPath`.
let clip_surface = try_opt!(layers.get(), ());
let clip_surface = clip_surface.borrow_mut();
let clip_cr = cairo::Context::new(&*clip_surface);
clip_cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
clip_cr.paint();
clip_cr.set_matrix(cr.get_matrix());
draw_group_child(&node, opt, &clip_cr);
apply(clip_node, cp, opt, bbox, layers, &clip_cr);
cr.set_matrix(cairo::Matrix::identity());
cr.set_operator(cairo::Operator::Xor);
cr.set_source_surface(&*clip_surface, 0.0, 0.0);
cr.set_operator(cairo::Operator::DestOut);
cr.paint();
}
}
}
// TODO: mask
}
fn draw_group_child(
node: &usvg::Node,
opt: &Options,
cr: &cairo::Context,
) {
if let Some(child) = node.first_child() {
cr.transform(child.transform().to_native());
match *child.borrow() {
usvg::NodeKind::Path(ref path_node) => {
path::draw(&child.tree(), path_node, opt, cr);
}
usvg::NodeKind::Text(ref text) => {
text::draw(&child.tree(), text, opt, cr);
}
_ => {}
}
}
}
......@@ -57,6 +57,9 @@ pub fn apply(
usvg::NodeKind::Text(ref text) => {
text::draw(&node.tree(), text, opt, &clip_p);
}
usvg::NodeKind::Group(ref g) => {
clip_group(&node, g, opt, bbox, layers, &clip_p);
}
_ => {}
}
......@@ -65,7 +68,71 @@ pub fn apply(
clip_p.end();
if let Some(ref id) = cp.clip_path {
if let Some(ref clip_node) = node.tree().defs_by_id(id) {
if let usvg::NodeKind::ClipPath(ref cp) = *clip_node.borrow() {
apply(clip_node, cp, opt, bbox, layers, &p);
}
}
}
p.set_transform(&qt::Transform::default());
p.set_composition_mode(qt::CompositionMode::CompositionMode_DestinationOut);
p.draw_image(0.0, 0.0, &clip_img);
}
fn clip_group(
node: &usvg::Node,
g: &usvg::Group,
opt: &Options,
bbox: Rect,
layers: &mut QtLayers,
p: &qt::Painter,
) {
if let Some(ref id) = g.clip_path {
if let Some(ref clip_node) = node.tree().defs_by_id(id) {
if let usvg::NodeKind::ClipPath(ref cp) = *clip_node.borrow() {
// If a `clipPath` child also has a `clip-path`
// then we should render this child on a new canvas,
// clip it, and only then draw it to the `clipPath`.
let clip_img = try_opt!(layers.get(), ());
let mut clip_img = clip_img.borrow_mut();
clip_img.fill(0, 0, 0, 0);
let clip_p = qt::Painter::new(&clip_img);
clip_p.set_transform(&p.get_transform());
draw_group_child(&node, opt, &clip_p);
apply(clip_node, cp, opt, bbox, layers, &clip_p);
clip_p.end();
p.set_transform(&qt::Transform::default());
p.set_composition_mode(qt::CompositionMode::CompositionMode_Xor);
p.draw_image(0.0, 0.0, &clip_img);
}
}
}
// TODO: mask
}
fn draw_group_child(
node: &usvg::Node,
opt: &Options,
p: &qt::Painter,
) {
if let Some(child) = node.first_child() {
p.apply_transform(&child.transform().to_native());
match *child.borrow() {
usvg::NodeKind::Path(ref path_node) => {
path::draw(&child.tree(), path_node, opt, p);
}
usvg::NodeKind::Text(ref text) => {
text::draw(&child.tree(), text, opt, p);
}
_ => {}
}
}
}
e-clipPath-019.svg
e-clipPath-020.svg
e-clipPath-029.svg
e-clipPath-031.svg
e-clipPath-032.svg
e-clipPath-033.svg
e-clipPath-034.svg
e-clipPath-036.svg
e-clipPath-037.svg
e-mask-022.svg
e-clipPath-019.svg
e-clipPath-020.svg
e-clipPath-029.svg
e-clipPath-031.svg
e-clipPath-032.svg
e-clipPath-033.svg
e-clipPath-034.svg
e-clipPath-036.svg
e-clipPath-037.svg
e-mask-022.svg
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment