pygobject / pycairo

Python bindings for cairo
https://pycairo.readthedocs.io
Other
613 stars 83 forks source link

Context.restore() doesn't restore the current point? #273

Open nedbat opened 1 year ago

nedbat commented 1 year ago
import cairo

with cairo.SVGSurface("example.svg", 200, 200) as surface:
    context = cairo.Context(surface)
    context.move_to(100, 200)
    print(context.get_current_point())
    context.save()
    context.move_to(300, 400)
    print(context.get_current_point())
    context.restore()
    print(context.get_current_point())

This prints:

(100.0, 200.0)
(300.0, 400.0)
(300.0, 400.0)

After the context.restore(), shouldn't the current point be restored to (100, 200)?

naveen521kk commented 1 year ago

After the context.restore(), shouldn't the current point be restored to (100, 200)?

Not sure, but reading the docs the current point restored to (100, 200) seems like expected behaviour. I think you'll get better help if you ask on the Cairo mailing list, https://lists.cairographics.org/mailman/listinfo/cairo. Here is a C repro of the same you did here, https://gist.github.com/naveen521kk/fa19da383be0a15b52c947a30bbee6b3

stuaxo commented 1 year ago

This might be a documentation issue - in the docs it says "state" is saved/restored, but not what that state includes (e.g. position)... it'll be interesting to see what people say on the mailing list/

nedbat commented 1 year ago

I guess the entire path is not part of the save/restore:

import cairo

def show_path(label, context):
    path_str = str(context.copy_path())
    if path_str:
        path_str = path_str.replace("\n", "; ")
    else:
        path_str = "<empty>"
    print(f"{label}: {path_str}")

with cairo.SVGSurface("example.svg", 200, 200) as surface:
    context = cairo.Context(surface)

    show_path("Initial", context)

    context.move_to(100, 200)
    context.line_to(300, 400)
    context.close_path()

    show_path("Before save", context)

    context.save()
    show_path("Before stroke", context)
    context.stroke()
    show_path("After stroke", context)
    context.restore()

    show_path("After restore", context)

produces:

Initial: <empty>
Before save: move_to 100.000000 200.000000; line_to 300.000000 400.000000; close path; move_to 100.000000 200.000000
Before stroke: move_to 100.000000 200.000000; line_to 300.000000 400.000000; close path; move_to 100.000000 200.000000
After stroke: <empty>
After restore: <empty>