dbuenzli / vg

Declarative 2D vector graphics for OCaml
http://erratique.ch/software/vg
ISC License
88 stars 12 forks source link

Cairo backend: Rendering out of bounds #19

Closed Alpiek closed 5 years ago

Alpiek commented 6 years ago

Hello, This might be a simple question but I don't see a solution. I have this program:

open Gg
open Vg

let scene () =
  let boundary_box (pts) =
    List.fold_left (fun acc (pt, _) -> Box2.add_pt acc pt) Box2.zero pts in

  let dot (c: color) =
    let circle = P.empty >> P.circle P2.o 0.05 in
    I.const c >> I.cut circle in

  let mark (pt, c) = (dot c) >> I.move pt in
  let plot_points pts =
    let blend_mark acc pt = acc >> I.blend (mark pt) in
    List.fold_left blend_mark I.void pts in

  let pts = [
    (P2.v (-1.0) (-1.0), Color.red);
    (P2.v 0. 0., Color.green);
    (P2.v 1.0 1.0, Color.blue)
  ]
  and output = "./output/x.png"

  and size = Size2.v 100.0 100.0 in
  let view = boundary_box pts in
  try
    let oc = open_out output
    and res = 300. /. 0.0254 in  (* 300dpi in dots per meters *)
    let fmt = `Png (Size2.v res res) in
    let r = Vgr.create (Vgr_cairo.stored_target fmt) (`Channel oc) in
    let img = plot_points pts in
    try
      ignore (Vgr.render r (`Image (size, view, img)));
      ignore (Vgr.render r `End);
      close_out oc;
    with e -> close_out oc; raise e
  with Sys_error e -> prerr_endline e

So basically it should render 3 points with negative axes. However the output I'm getting is this: x

As you can see, I only get 2 points and it seems that a box (0, 0) - (1, 1) cuts the whole image. How can I draw a picture with view of (-1, -1) - (1, 1)?

dbuenzli commented 6 years ago

Something indeed seems wrong. Tried with points (0,0) (1,1) and (2,2) and the expected picture shows up.

@art-w (the cairo backend contributor) could you please have a look this ? I guess something might be wrong in the initial transform setup but I don't have the time to look into it right now.

dbuenzli commented 6 years ago

@Alpiek could you please confirm this happens with other Cairo formats too ? And possibly try with the pure OCaml svg or pdf backend to confirm you get the right thing in these cases.

CGenie commented 6 years ago
open Gg
open Vg

let scene () =
  let boundary_box (pts) =
    List.fold_left (fun acc (pt, _) -> Box2.add_pt acc pt) Box2.zero pts in

  let dot (c: color) =
    let circle = P.empty >> P.circle P2.o 0.05 in
    I.const c >> I.cut circle in

  let mark (pt, c) = (dot c) >> I.move pt in
  let plot_points pts =
    let blend_mark acc pt = acc >> I.blend (mark pt) in
    List.fold_left blend_mark I.void pts in

  let pts = [
    (P2.v (-1.0) (-1.0), Color.red);
    (P2.v 0. 0., Color.green);
    (P2.v 1.0 1.0, Color.blue)
  ]
  and output = "./output/x.svg"

  and size = Size2.v 100.0 100.0 in
  let view = boundary_box pts in
  try
    let oc = open_out output in
    (* and res = 300. /. 0.0254 in  (\* 300dpi in dots per meters *\) *)
    (* let fmt = `Png (Size2.v res res) in *)
    (* let r = Vgr.create (Vgr_cairo.stored_target fmt) (`Channel oc) in *)
    let r = Vgr.create (Vgr_svg.target ()) (`Channel oc) in
    let img = plot_points pts in
    try
      ignore (Vgr.render r (`Image (size, view, img)));
      ignore (Vgr.render r `End);
      close_out oc;
    with e -> close_out oc; raise e
  with Sys_error e -> prerr_endline e

This seems to work OK. x svg So indeed this has something to do with cairo.

BTW sorry I forgot to log out of company's account, this is my private one, more preferable for this issue :)

dbuenzli commented 5 years ago

@CGenie the cairo backend implementer seems to be MIA, I don't have the time right now to investigate this. Maybe you can try to have a look yourself in the area I pointed above also it would be nice to first answer that question:

@Alpiek could you please confirm this happens with other Cairo formats too ?

CGenie commented 5 years ago

I don't have much free time as well, but I'll try to answer your questions when I sit to it :) Will try to look in the code you showed me as well and make fix if I can :)

CGenie commented 5 years ago

Well I tried to look (sorry it took me time to figure out that I have to use opam pin functionality, I'm new to Ocaml :)). I don't see a solution however I wonder why these equations aren't similar: https://github.com/dbuenzli/vg/blob/da3b840da6c9d1f0ed22413dfcb7a6c7e4cdb27d/src/vgr_cairo.ml#L310-L311

dbuenzli commented 5 years ago

So I confirm this happens with other cairo backends. The area seems rights so I rather suspect something related to clip state.

dbuenzli commented 5 years ago

This looks suspicious the clip region setup and clearing is performed on a rectangle whose bottom left point is at the origin after the view transform has been setup.

dbuenzli commented 5 years ago

That was it. Thanks @CGenie for the report.

dbuenzli commented 5 years ago

0.9.2 has been released with the fix.

CGenie commented 5 years ago

Splendid thank you!