Hi Noel,
Hi
There will be a variety of drawinglayer related patches going through as I work though some performance issues.
So for drawinglayer code, we generally start with a hierarchy of drawinglayer objects.
Then we call that hierarchy recursively, and it produces as output a list of more primitive drawinglayer objects.
Then we iterate over that list of "primitive" objects and do something - usually rendering, sometimes hit-testing, sometimes something else.
What I am doing is attempting to remove the intermediate creation of drawinglayer objects (which is fairly expensive), and instead use a visitor pattern (represented by the Primitive2DDecompositionVisitor abstract class)
The best way to avoid decomposition is not to call getDecomposition(). The concept is that a Processor (e.g. renderer or HitTest) *has* to implement that 7 minimal Primitives to do everything. It *can* implement higher-level ones to not need to let decompose run.
Example: HitTest for FatLines. A HitTest Processor which does not know FatLines Primitives will trigger getDecomposition() and that will create the filled PolyPolygon geometry for the FatLine. That Processor would then HitTest by checking the to-be-tested point position against PolyPolygons. If it implements FatLine, it will have to do a geometrical test against the hairline PolyPolygon using the known LineWidth.
The advantage is that Processors can be easily written, with e.g. not knowing about FatLines or Text at all.
The disadvantage is that a decomposition has to be done.
The best way to avoid decomposition is to implement handling of more complex primitives in Processors.
To allow for simple impl of Processors, keeping the getDecomposition() is necessary. Be wawre that UNO API has getDecomposition and that needs to stay.
A visitor concept would be fine and interesting - I already did something similar whit LinePatters which when handled in the renderers use a lambda now to no longer create the line pattern line snippets in memory - but I would be interested how this will look like. Especially since we need to keep UNO API - do you plan to extend hat visitor concept over the UNO API?
For the buffering: Every impl of a getDecomposition *can* decide if it implements to buffer the created decomposition primitive representation or not. Maybe using this more is feasible to fix performance stuff - plus more direct handling of higher-level primitives in Processors.
I think there are existing possibilities to fix performance
problems, but I am open to new concepts - if they fit into the
existing concepts :-)
Along the way I also intend to remove some buffering of these intermediate objects, since it is generally less expensive to just visit the higher-level tree.
As explained, this may just be added to the impls of ::getDecomposition() of the Primitives in question.
I see the advantage of *not* creating all sub-primitives, but I see no UNO API compatible way to add a visitor concept here. Of course it would be interesing, maybe even a reason to extend UNO API.
Be aware that this is not always usable: With the example of FatLines broken down to PolyPolygon representation it is *not* the same (unfortunately) to paint each single one of the decomposed geometry - these do overlap and the gaps do not add correctly on AAed modes, so these *need* to be painted in a single run to be represented correctly when the line has a transparency.
Those cases are not obvious (you find them when you do that stuff
and it looks weird/is wrong, then *have* to think about it -
sigh). Be aware that there are more such not obvious cases where
handling all single decomposed parts *is* graphically different
from handling as a whole.
Regards, Noel Grandin#
All the best,
Armin
-- -- ALG (PGP: EE1C 4B3F E751 D8BC C485 DEC1 3C59 F953 D81C F4A2)