Viewport, filters, and Inkscape code structure: help needed
I am struggling a bit with the overall structure of Inkscape's code as I work on getting filter regions implemented correctly. This is how I understand the current structure to work:
XML Tree:
This represents the actual document.
SP Tree:
This is an expanded tree. For example:
<defs> <rect id="myRect"/> </defs> <use xlink:href="#myRect"/>
has two SPRect instances, one for the <rect> in the <defs> section and one generated by the <use> element. The allows for things such as style cascading and for different dimensions when the rectangles size is expressed in percent of the viewport (and there are multiple viewports in one document).
Markers and symbols may also have multiple instances generated.
The SP tree includes print functions used by the EMF, WMF, and TeX exporters. Other exporters (including Cairo PDF and PS) are independent of the SP and NR trees.
NR Tree (e.g. Cairo Renderer):
This is an expanded tree created for on-screen rendering.
(Silly questions: what does NR mean?, what does 'arena' mean?)
Now we come to filters. A filter can be applied to multiple objects. It's coordinates can be expressed in terms of the current viewport or the bounding box of the object that references it. In both cases, a filter's absolute coordinates can be different when applied to different objects. At the moment, only the bounding box case is handled and it is handled in the NR Tree. The NR tree doesn't know about the viewport but the SP tree does so I've tried to add code to handle the coordinates expressed in terms of a viewport into the SP tree. It seems more natural to handle coordinates in the SP tree as the SP print functions and other exporters can take advantage of these dimensional calculations. This works, kind of. There are a couple of problems:
1. The update functions of the filter primitives are not called. This can be fixed by adding explicit calls from SPFilter::update (following the model in the SPGroup update function).
2. The filter update function is only called once, at the beginning of the update process. So if a document has more than one viewport (due to an embedded SVG, for example), the filter coordinates are not updated for the second viewport. (This is unlike the <use> element case.)
It seems my choices for fixing filter regions for viewport based dimensions is to either follow the <use> element example, and have instances of the filter element for each use of the element or to move all coordinate handling to the NR tree (after making the viewport available in the NR tree). The former, I think, is more desirable, but the latter may be easier.
Any thoughts?
Thanks,
Tav
NR was New Renderer I believe way back in the day. Is that right guys?
Cheers
John
On Thu, Feb 27, 2014 at 3:38 PM, Tavmjong Bah <tavmjong@...8...> wrote:
I am struggling a bit with the overall structure of Inkscape's code as I work on getting filter regions implemented correctly. This is how I understand the current structure to work:
XML Tree:
This represents the actual document.
SP Tree:
This is an expanded tree. For example:
<defs> <rect id="myRect"/> </defs> <use xlink:href="#myRect"/>
has two SPRect instances, one for the <rect> in the <defs> section and one generated by the <use> element. The allows for things such as style cascading and for different dimensions when the rectangles size is expressed in percent of the viewport (and there are multiple viewports in one document).
Markers and symbols may also have multiple instances generated.
The SP tree includes print functions used by the EMF, WMF, and TeX exporters. Other exporters (including Cairo PDF and PS) are independent of the SP and NR trees.
NR Tree (e.g. Cairo Renderer):
This is an expanded tree created for on-screen rendering.
(Silly questions: what does NR mean?, what does 'arena' mean?)
Now we come to filters. A filter can be applied to multiple objects. It's coordinates can be expressed in terms of the current viewport or the bounding box of the object that references it. In both cases, a filter's absolute coordinates can be different when applied to different objects. At the moment, only the bounding box case is handled and it is handled in the NR Tree. The NR tree doesn't know about the viewport but the SP tree does so I've tried to add code to handle the coordinates expressed in terms of a viewport into the SP tree. It seems more natural to handle coordinates in the SP tree as the SP print functions and other exporters can take advantage of these dimensional calculations. This works, kind of. There are a couple of problems:
1. The update functions of the filter primitives are not called.
This can be fixed by adding explicit calls from SPFilter::update (following the model in the SPGroup update function).
2. The filter update function is only called once, at the beginning
of the update process. So if a document has more than one viewport (due to an embedded SVG, for example), the filter coordinates are not updated for the second viewport. (This is unlike the <use> element case.)
It seems my choices for fixing filter regions for viewport based dimensions is to either follow the <use> element example, and have instances of the filter element for each use of the element or to move all coordinate handling to the NR tree (after making the viewport available in the NR tree). The former, I think, is more desirable, but the latter may be easier.
Any thoughts?
Thanks,
Tav
Flow-based real-time traffic analytics software. Cisco certified tool. Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer Customize your own dashboards, set traffic alerts and generate reports. Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.cl... _______________________________________________ Inkscape-devel mailing list Inkscape-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/inkscape-devel
2014-02-27 16:38 GMT+01:00 Tavmjong Bah <tavmjong@...8...>:
I am struggling a bit with the overall structure of Inkscape's code as I work on getting filter regions implemented correctly. This is how I understand the current structure to work:
XML Tree:
This represents the actual document.
Correct. This is basically synonymous to the XML DOM tree produced by standard DOM parsers, but extended with 'observers' as a way to notify other objects about changes to the XML. This allows tying together the trees with event-driven programming.
SP Tree:
This is an expanded tree. For example:
<defs> <rect id="myRect"/> </defs> <use xlink:href="#myRect"/>
has two SPRect instances, one for the <rect> in the <defs> section and one generated by the <use> element. The allows for things such as style cascading and for different dimensions when the rectangles size is expressed in percent of the viewport (and there are multiple viewports in one document).
Correct. The SPRect which is contained in SPUse is a little special - it doesn't have its XML node, for example.
Markers and symbols may also have multiple instances generated.
Correct.
The SP tree includes print functions used by the EMF, WMF, and TeX exporters. Other exporters (including Cairo PDF and PS) are independent of the SP and NR trees.
Correct; I think these "print" functions should be replaced by a more generic visitor pattern (I discussed this some time ago on the list), and the print-based and Cairo-based renderers could then be partially unified.
NR Tree (e.g. Cairo Renderer):
This is an expanded tree created for on-screen rendering.
(Silly questions: what does NR mean?, what does 'arena' mean?)
NR means New Renderer. One SP tree object can have several NR objects generated from it. This mapping is tracked in the SPItemView, SPMaskView and SPClipView structures. As far as I understand, this is primarily to support different maskUnits / clipUnits / patternUnits for different references to the same object without lowering that complexity into the NR tree.
Now we come to filters. A filter can be applied to multiple objects. It's coordinates can be expressed in terms of the current viewport or the bounding box of the object that references it. In both cases, a filter's absolute coordinates can be different when applied to different objects. At the moment, only the bounding box case is handled and it is handled in the NR Tree. The NR tree doesn't know about the viewport but the SP tree does so I've tried to add code to handle the coordinates expressed in terms of a viewport into the SP tree. It seems more natural to handle coordinates in the SP tree as the SP print functions and other exporters can take advantage of these dimensional calculations. This works, kind of. There are a couple of problems:
Digression: the biggest problem is that the filter code does not follow the invalidation model used by Lauris in the original NR tree, which is actually very well thought out and which I carried over when rewriting this code. The "update" function for Inkscape::Display::Filter works nothing like the update function for classes derived from DrawingItem, and the filter primitves are not created when show() is called on SPFeXxx objects like everything else, but during Inkscape::Display::Filter::update(). Fixing this fundamental design flaw would go a long way towards fixing many of the filter problems.
1. The update functions of the filter primitives are not called.
This can be fixed by adding explicit calls from SPFilter::update (following the model in the SPGroup update function).
I assume by "filter primitives" you mean the SpFeXxx objects. In that case, that looks like a good idea.
2. The filter update function is only called once, at the beginning
of the update process. So if a document has more than one viewport (due to an embedded SVG, for example), the filter coordinates are not updated for the second viewport. (This is unlike the <use> element case.)
It seems my choices for fixing filter regions for viewport based dimensions is to either follow the <use> element example, and have instances of the filter element for each use of the element or to move all coordinate handling to the NR tree (after making the viewport available in the NR tree). The former, I think, is more desirable, but the latter may be easier.
The former solution (creating the filter primitives based on the information in the SP tree once per viewport) is the only correct solution. The NR tree should know as little as possible about coordinate handling; in fact, many of the hacks, such as preserving the bbox in item coordinates in the NR tree, are only necessary due to design flaws in the filter code.
Regards, Krzysztof
Krzysztof,
Thanks for your clarifications!
I will look at implementing creating filters once per viewport after 0.91 is out the door as it would probably be a rather large change in the code. At this point, filter dimensions expressed in terms of the root viewport should be working.
Tav
On Thu, 2014-02-27 at 19:00 +0100, Krzysztof Kosiński wrote:
2014-02-27 16:38 GMT+01:00 Tavmjong Bah <tavmjong@...8...>:
I am struggling a bit with the overall structure of Inkscape's code as I work on getting filter regions implemented correctly. This is how I understand the current structure to work:
XML Tree:
This represents the actual document.
Correct. This is basically synonymous to the XML DOM tree produced by standard DOM parsers, but extended with 'observers' as a way to notify other objects about changes to the XML. This allows tying together the trees with event-driven programming.
SP Tree:
This is an expanded tree. For example:
<defs> <rect id="myRect"/> </defs> <use xlink:href="#myRect"/>
has two SPRect instances, one for the <rect> in the <defs> section and one generated by the <use> element. The allows for things such as style cascading and for different dimensions when the rectangles size is expressed in percent of the viewport (and there are multiple viewports in one document).
Correct. The SPRect which is contained in SPUse is a little special - it doesn't have its XML node, for example.
Markers and symbols may also have multiple instances generated.
Correct.
The SP tree includes print functions used by the EMF, WMF, and TeX exporters. Other exporters (including Cairo PDF and PS) are independent of the SP and NR trees.
Correct; I think these "print" functions should be replaced by a more generic visitor pattern (I discussed this some time ago on the list), and the print-based and Cairo-based renderers could then be partially unified.
NR Tree (e.g. Cairo Renderer):
This is an expanded tree created for on-screen rendering.
(Silly questions: what does NR mean?, what does 'arena' mean?)
NR means New Renderer. One SP tree object can have several NR objects generated from it. This mapping is tracked in the SPItemView, SPMaskView and SPClipView structures. As far as I understand, this is primarily to support different maskUnits / clipUnits / patternUnits for different references to the same object without lowering that complexity into the NR tree.
Now we come to filters. A filter can be applied to multiple objects. It's coordinates can be expressed in terms of the current viewport or the bounding box of the object that references it. In both cases, a filter's absolute coordinates can be different when applied to different objects. At the moment, only the bounding box case is handled and it is handled in the NR Tree. The NR tree doesn't know about the viewport but the SP tree does so I've tried to add code to handle the coordinates expressed in terms of a viewport into the SP tree. It seems more natural to handle coordinates in the SP tree as the SP print functions and other exporters can take advantage of these dimensional calculations. This works, kind of. There are a couple of problems:
Digression: the biggest problem is that the filter code does not follow the invalidation model used by Lauris in the original NR tree, which is actually very well thought out and which I carried over when rewriting this code. The "update" function for Inkscape::Display::Filter works nothing like the update function for classes derived from DrawingItem, and the filter primitves are not created when show() is called on SPFeXxx objects like everything else, but during Inkscape::Display::Filter::update(). Fixing this fundamental design flaw would go a long way towards fixing many of the filter problems.
1. The update functions of the filter primitives are not called.
This can be fixed by adding explicit calls from SPFilter::update (following the model in the SPGroup update function).
I assume by "filter primitives" you mean the SpFeXxx objects. In that case, that looks like a good idea.
2. The filter update function is only called once, at the beginning
of the update process. So if a document has more than one viewport (due to an embedded SVG, for example), the filter coordinates are not updated for the second viewport. (This is unlike the <use> element case.)
It seems my choices for fixing filter regions for viewport based dimensions is to either follow the <use> element example, and have instances of the filter element for each use of the element or to move all coordinate handling to the NR tree (after making the viewport available in the NR tree). The former, I think, is more desirable, but the latter may be easier.
The former solution (creating the filter primitives based on the information in the SP tree once per viewport) is the only correct solution. The NR tree should know as little as possible about coordinate handling; in fact, many of the hacks, such as preserving the bbox in item coordinates in the NR tree, are only necessary due to design flaws in the filter code.
Regards, Krzysztof
participants (3)
-
John Cliff
-
Krzysztof Kosiński
-
Tavmjong Bah