Skip to content

Fix #5442: XKCD in Mac-OSX backend #5548

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

mdboom
Copy link
Member

@mdboom mdboom commented Nov 23, 2015

Cc: @mdehoon

@mdboom mdboom added this to the proposed next point release (2.1) milestone Nov 23, 2015
@mdehoon
Copy link
Contributor

mdehoon commented Nov 25, 2015

@mdboom Thanks, I'll look into this.

@mdehoon
Copy link
Contributor

mdehoon commented Nov 27, 2015

I am thinking that a cleaner approach would be to apply the sketch procedure to the path before calling gc.draw_path().

@mdboom
Copy link
Member Author

mdboom commented Nov 27, 2015

Applying it before would require allocating a buffer to store the path data. The advantage of this approach is that the path data can be converted as it is streamed to the native Quartz data structure without an extra copy in between. At least in the Agg backend, this has long been an important performance consideration.

@mdehoon
Copy link
Contributor

mdehoon commented Nov 27, 2015

The path argument that gc.draw_path receives doesn't have to be the full path; it can be an iterator. Basically, the result of get_path_iterator, suitably encapsulated as a Python object. In my understanding, get_path_iterator doesn't allocate a new buffer.

@mdboom
Copy link
Member Author

mdboom commented Nov 27, 2015

Ah. I misunderstood. Certainly, using an iterator would be fine.

@mdehoon
Copy link
Contributor

mdehoon commented Nov 27, 2015

Then can we make sketch_scale, sketch_length, sketch_randomness properties of the path instead of the graphics context?

@mdboom
Copy link
Member Author

mdboom commented Nov 27, 2015

Currently all style is passed through the graphics context. I think it makes the most sense to keep it that way for consistency.

@mdehoon
Copy link
Contributor

mdehoon commented Nov 28, 2015

The sketching parameters are not really a style property, but define the trajectory of the path. This is different from e.g. the line width, line style, color, etc. To me it makes most sense if the renderer completes the definition the path, rather than stopping in the middle and letting the graphics context take care of the sketching. The current approach may work for Agg, but makes stack-based graphics contexts unnecessarily complex, and on top of that requires each backend to reimplement the sketching procedure. If the sketching is taken out of the graphics context and is applied by the renderer before invoking the graphics context, then the sketching code becomes backend-independent, and will automatically work for the Cairo backend also without needing any changes to the backend.

@mdboom
Copy link
Member Author

mdboom commented Nov 28, 2015

What you are suggesting would be nice and was in fact the method of an earlier attempt by Jake Vanderplas to implement this. However, sketching can not be effectively done prior to the backend, because it is dependent on the resolution of the output device, which only the backend knows (the dpi known by the figure isn't exactly the same thing). In that sense, it is like any other rasterizing operation, like linewidth or dash style.

It might be helpful to change things so the path simplification pipeline takes an object with all the parameters (rather than a long list of function arguments) so that additional parameters could be added without requiring modifications to the backend. But the path simplificiation pipeline (of which sketch is only the last part) needs to happen within the backend between the input path and path rasterization.

@mdehoon
Copy link
Contributor

mdehoon commented Nov 29, 2015

I see. I'm OK with the path simplification happening in the backend; for me the problematic part is the gc.get_sketch, gc.set_sketch functions, which doesn't work well with a stack-based graphics context. Would it be possible to make the parameters to the path simplification pipeline an (optional) argument to gc.draw_path, or alternatively an attribute to the path argument? Then in the backend, gc.draw_path can run the path simplification pipeline using those parameters, and we can avoid the need for gc.get_sketch, gc.set_sketch. I agree that storing the parameters in a single object rather than a long list of function arguments would be better.

@mdehoon
Copy link
Contributor

mdehoon commented Dec 11, 2015

@mdboom Thinking about this again,

However, sketching can not be effectively done prior to the backend, because it is dependent on the resolution of the output device, which only the backend knows (the dpi known by the figure isn't exactly the same thing).

Then if the backend exposes the resolution in some way, then the sketching (and all other steps in the path simplification pipeline) can be done outside of the backend. Exposing the resolution is trivial; the resolution could for example be a read-only property of the graphics context.

@mdboom
Copy link
Member Author

mdboom commented Dec 11, 2015

Then if the backend exposes the resolution in some way, then the sketching (and all other steps in the path simplification pipeline) can be done outside of the backend. Exposing the resolution is trivial; the resolution could for example be a read-only property of the graphics context.

This means we would have to affine transform all paths before passing to the backend. That would be quite a bit slower than the current situation where we affine transform within the Agg backend, "streamed in" with all of the other path conversion steps. Thinking ahead to GL backends (of which there are a couple of experimental examples), you'd be taking that off of the GPU. I think there's good reasons to give the backends more information to optimize with and not less. It does mean the backends are responsible for more -- but that's why the path conversion module exists where all the backends can use it if desired.

I agree that storing the parameters in a single object rather than a long list of function arguments would be better.

That's basically what we already have in the passed-in GraphicsContext. I know you've advocated repeatedly for a stateful GraphicsContext in matplotlib, but it's never worked that way and it actually would be less convenient and more complex on the frontend side. I fully concede that most graphics frameworks use stateful graphics contexts, but we get along just fine with the PS, PDF and SVG backends and their stateful contexts by applying the difference between the backend-side stateful graphics context and the frontend-side stateless drawing properties. I think the real mistake here is calling matplotlib's GraphicsContext GraphicsContext which led to the Mac OSX backend being implemented as it was. It should probably just be called DrawingProperties or something to avoid the confusion. But beyond that, I don't think there's any benefit for matplotlib going to a stateful model.

@mdehoon
Copy link
Contributor

mdehoon commented Dec 27, 2015

I think the time has come to deprecate and remove the MacOSX backend from matplotlib. There are too many wrinkles between the matplotlib API and the Apple API for this to work smoothly and reliably. I understand the rationale for keeping the matplotlib API as it is, but obviously I cannot change Apple's API either. Rewriting the MacOSX backend to follow matplotlib's design philosophy is a major undertaking, and is likely to leave us with something that is not quite satisfactory from a user's perspective in terms of efficiency and reliability. The time and effort maintaining such a backend is better spent elsewhere. I'd be happy to contribute to other parts of matplotlib, though.

@matthew-brett
Copy link
Contributor

Oh, dear, that would make me very sad, I use the OSX backend almost exclusively and I think the same is true for many people using OSX.

What can I do to help this keep moving?

@mdboom
Copy link
Member Author

mdboom commented Mar 21, 2016

Fixed by #6178

@tacaswell tacaswell closed this Mar 28, 2016
@QuLogic QuLogic modified the milestones: 2.0 (style change major release), 2.1 (next point release) Mar 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants