jf barraud wrote:
The main issue I can think of is that we already released lpes with the actual xml representation, and maintaining compatibility might be painfull.
It can be taken care of in the document loading code (along XML parsing) or even implemented as an XSLT that is applied on every entry document, so that the SPObject layer never sees the old representations.
About parameters: we can already use complex objects (in particular, objects carrying lpes on theire own) as parameters using "cloned" parameters. The only limitation is that the source object has to exist somewhere in your drawing and, you generally have to hide it by hand in a separate layer or something... I think this is not a big problem. Recieving a group as parameter should not be a big deal, but since we can only output a single path, this is not very usefull, is it?
I only mentioned groups because they are used in some current effects. They would also be useful with clones (e.g. when you want to apply an effect to a group that has both clones and shapes).
About bool ops, the actual structure is to have one "ground object" and get the other operands as parameters. I think this is ok.
This introduces additional complexity when you want to edit one of the objects: the path manipulator or the shape manipulator must know that it will be editing a parameter of a path effect, not an actual shape (because the XML representation is different). In the proposed representation, the manipulators can just edit actual XML / SPObject elements that are identical to the elements they edit "normally", and you can select those elements without any hacks - they have an XML representation and a node in the XML tree so they interoperate with Inkscape::Selection without any changes.
I doubt this is a big trouble however; since we can still make an arbitrary choice of the ground object and add as many bool ops as needed. (I didn't get your proposition about making a shape 'live').
The bit about 'live' shapes is just an UI metaphor. It is a way of specifying whether the boolean operation should replace the shapes with a new path, or create a path effect while preserving the original shapes. If the selection contains a live shape, the operation creates a path effect, otherwise it creates a normal path. Note that this is compatible with how users work: you usually know which shapes in the drawing are 'important' and should not be destroyed by path operations, so you can make them "live" to avoid inadvertently destroying their editing capabilities.
However, this violates the path to path mapping paradigm, and hence goes beyond lpe purpose. In particular, this requires a completely new API.
That's the thing - the paradigm itself is limited! Thinking of an LPE as a path->path mapping is inherently limited, and can only accomodate effects taking multiple paths as input using hacks. When we think of an LPE as a shape dynamically computed from other shapes, the new representation is very natural. (Note that I do not use the word 'path' - this also includes ellipses, rectangles, etc.) I don't deny that significant changes are needed, but I think in the long run it will be worth it.
Finally, if this new lpe generation should look like filters, it might be worth organizing the inputs as "slots", like filters do: one lpe in the stack could use the result of another as a parameter(?).
This is exactly what I've demonstrated in the example and requires no special handling in the new representation: since an LPE is a shape, and LPEs accept shapes as parameters, an LPE can accept another LPE as a parameter, or even a clone of it. You can create a tree of any depth and still have all the operands selectable (from the LPE dialog) and editable.
bulia byak wrote:
This is absolutely doable with the current representation. We just need to add a trivial "copy" LPE which will link to some path and create a copy of it, just like the pattern-along-path now links to the pattern path.
With enough hacks one could probably achieve all the things I'm talking about even with the old representation. I am not talking about what is doable but what is simple and maintainable. Look at Windows 95: it was possible to do a 32-bit multitasking GUI on top of a 16-bit single-tasking DOS, but the code must have been a total abomination as evidenced by its instability and bugs.
Not really. The node tool will still have to know from which branch to take shapes (e.g. when you click or press Ctrl+A) and which branch to ignore.
This only seems like a problem now because our handling of the switch element is currently slightly wrong, and we need to fix it anyway to legalize flowtext. The SPObject layer should not know anything about switches. SP tree is a semantic representation of the document, so it should only contain the path effect representation, and the fallback path representation should not be accessible from the SP tree. In other words, the fallback path should never be selectable, and its SPObject should not exist at all. It makes no sense to edit that path in the UI anyway! If you want to do this, use Object to Path. Selecting a path effect should not edit its parameters, but the effect itself. Editing the parameters should be possible from the LPE dialog in a manner similar to an object browser.
It's not really that simple. Consider LPEs which refer to other paths, for example Pattern along path. These paths can be anywhere, on canvas or in defs.
It is possible to select and edit a path that is in defs, because it has an SPPath object. It's just not selectable by clicking on the canvas. I already do this in my node tool when I edit clips and masks (I have already implemented and it and will send it in the next patch btw, once I finish constrained dragging).
This means it will have to know how to traverse from a path with such path parameter to that path parameter, read it, and display it.
In my node tool I edit a single path with a PathManipulator. The manipulators do not need to traverse anything - they are dumb objects that take an SPShape and display the controls to edit it. It is the event context (tool) that takes care of figuring out which items need to be edited and creating manipulators for them. The LPE dialog would be responsible for creating the manipulators for parameters.
And it should use at least a different color for the parameter path, so it must be aware that it is a different kind of path.
The color of the path will be a property of the manipulator, not something the manipulator figures out on its own. The tool would be responsible for setting it. The LPE dialog would set the correct color when displaying a manipulator for its parameter, because it knows they are parameters.
Which means, you will end up with basically what we have now. I don't see where you can shave off much complexity here.
That's because you think of the node tool as a single entity, while I think of it as a wrapper for path manipulators. The node tool handles selecting objects, switching to clip editing mode, etc., while manipulators are completely oblivious of all this and edit what they are told to. This is where the complexity can be lowered.
This looks nifty, but I just don't see how this is principally different from LPE on a group that we can do now. Is it only that the implementation can be simpler with your structure?
Yes, it can be MUCH simpler, because the manipulators can be created for the internal XML elements. I can create a path manipulator for the svg:path inside the inkscape:path-effect element. Groups, rectangles, polylines, other path effects and clones do not need any special handling, because the SPObject representing the path effect treats them as SPShapes without caring about what XML elements they are actually represented with. This allows LPEs for svg:polyline, svg:ellipse, etc. without converting them to paths.
I can tell you one thing: the implementation of the current LPE seemed really simple when we were just planning it :) Most of the complexity grew upon it later - when we ran into various scenarios and thought about new possibilities. That is perfectly normal, and I don't think our LPE implementation is particularly bad as it is. But I'm pretty sure that no matter how sleek your implementation seems now in theory, in practice it will be much much hairier :)
It's not pure theory because I'm already using a similar approach when editing clipping paths that are in defs. I needed about 30 lines of code to add this feature, and half of it was related to testing whether there is something to edit at all. I just get a list of paths in the clip/mask and create manipulators for them - that's all! I did not have to modify even a single line of code in the PathManipulator. It will be really simple to do things with the new representation, for the same reason editing clipping paths is simple: they have XML and SPObject representations identical to 'normal' objects.
BTW, the clones here will not be editable by Node tool anyway, as they aren't now.
Of course they won't, the original will be editable. I thought it was obvious. When the original is edited, the LPE will update, because the clone will change. It is wrong to come up with yet another mechanism of linking to path parameters rather than copying them if we can reuse the one provided by SVG.
Your syntax would allow that too, of course, but it would mean nested switches which adds considerable complexity: the non-Inkscape branch of such a nested switch will still be inside an Inkscape branch of the parent switch! It will be cumbersome to decide what to render and what to edit with such a structure. With our current implementation, it's all in a single path element and therefore much simpler and more straightforward.
In my initial proposal there are no nested switches. Look at the example again: there is only one switch that surrounds the topmost LPE only. However, using nested switches is actually be a better idea, because it allows us to degrade gracefully when we don't understand one of the nested path effects, and would make the XML representation of the LPEs look the same regardless of whether they are topmost or not. Handling the switch does not add extra complexity to the tools - it only needs to be handled differently in the XML->SPObject code, so that an SPPathEffect object is created for the svg:switch XML node, and the SPSwitch object or the SPPath object for the fallback is not created. By the way, having SPSwitch at all feels wrong: the SPObject layer should abstract this away.
Yes, but again, it is desirable that pattern paths use a different outline color and maybe some other presentation or behavior differences (for example it would be nice to edit the pattern not where it is but moved towards the skeleton that uses it), so the node tool will have to learn all this stuff anyway.
Under the new internal implementation, they won't have to - the LPE dialog will take care of setting the appearance properties of manipulators. I will also add an externally settable outline transform to the path manipulator, so that the outline can be transformed with respect to the path manipulator. The LPE dialog / tool will know about those transforms and will set them, but the manipulators will not need to learn anything new beyond exposing a few extra parameters for external use. The complexity of being able to set a different outline color is extremely trivial when compared to that of being able to edit something that has a different XML representation.
Also, your XML example shows only boolean effects where source paths play more or less the same role. What about pattern along path, where one path is skeleton and the other is pattern? How do you identify in your structure which is which?
The same way z-order is determined, by their order in the document :) If that turns out to cause problems, I'll add an inkscape:parameter-name attribute to that says which parameter it is, but right now I don't see a case where it would be necessary.
Why "every tool"? All we need to do is: teach the Node tool to edit parameter paths (done), teach the knotholder to edit knots of an LPE (done), and make sure all these knotholders and multiple paths are editable simultaneously (is being worked on).
That last part is actually the most complex one. The first two are trivial by comparison. I can say this from experience :) Even if we have to scrap the first two parts to make the last one simpler, it will be worth it; actually the first two parts are not even necessary with the new XML representation. And why we need to edit them all at once? The new representation allows you to select and edit one parameter at a time or several of them at once.
By the way, I agree that "all tools" is a bit scary, but when I think of it not all tools will have to be modified, only the shape tools. The shape tools are simple when compared to the Node tool, so it won't take very long, and on top of that I will reuse many components I wrote for the new node tool. I could probably rewrite the Ellipse tool in a week or two at most.
Whereas with your implementation, I foresee changes at least in Selector - it will need to be taught how to select stuff inside switches and what to ignore there.
The selector is not supposed to select anything inside those switches. Selector is not the only way to select objects - for example you can select paths for editing in my node tool even tough it does not use any selector code. Any changes would be confined to sp_event_context_find_item, which is the function used to find items to select.
All export and rendering code will all have to be updated as well, otherwise it will just export both source paths and the result path on top of one another. That's quite some rewriting to do, for no clear gain that I can see.
The rendering code does not touch the XML layer, it uses the SPObject layer, so it won't need any changes. Some export plugins might need to be fixed to handle switches correctly, but we would need to do this anyway for the flowtext work. For me the gain is enormous. The new representation is generic - if we use some object as a path effect parameter, it does not change at all, and is in every respect still a normal object! The only difference is that it's not rendered on the canvas. We can exploit this to make things brilliantly simple.
With the old representation we have know that we are operating on an LPE almost everywhere. I don't say it is incapable of providing all the features we want - probably it could provide them, but only after we made a huge mess with a lot of obscure bugs and quirks and alienated everyone out of working with tool code, because every non-trivial change would break LPEs in some subtle way.
Regards, Krzysztof