2010/4/24 Krzysztof Kosiński <tweenk.pl@...400...>:
W dniu 24 kwietnia 2010 14:51 użytkownik bulia byak <buliabyak@...400...> napisał:
Tests are good, but they will never catch problems with rendering interruption and other interactive aspects.
If interruption is a problem, maybe we need to design the renderer in a way that allows it to throw away the results at any point in time and start working on something else?
That's the ideal. In practice, "any point in time" will in any case be limited to a limited number of code junctions, and if we space them too densely, we will lose too much time on the constant checks "do we have an interrupting event?" So we need to find a compromise between granularity of interruption points and responsiveness to events.
For me an important goal would be to to never show a partially redrawn screen. The kind of artifacts that tiled redraw introduces aren't nice.
I don't think this goal is realistic. There _always_ will be documents that render for minutes, and failure to interrupt this rendering is much worse, usability-wise, than temporary artefacts that the next redraw will remove anyway.
So, most vector editors render in parts, and allow you to interrupt rendering between the parts. There are two main approaches here. Illustrator renders by objects, and so you can never see a partially rendered object, but you can see a drawing that's missing part of its objects. The other approach is that we use: we never show an incomplete stack of objects at any point, but we show a partially repainted area.
To me, our approach is preferable, because it allows me to more easily perceive artifacts as artifacts - it sends a clear visual signal that what you see is partial rendering, and you have no problems to guess which part of it is rendered and which is not. With Illustrator on a slow machine, on the other hand, it is rather disconcerting to watch as more and more objects pop up in unpredictable places (depending on z-order) and to think, is this all? is it finished now? or will one more object jump one me and cover what I'm seeing?
Also, in Illustrator's approach, the maximum time between interruption points depends on the complexity of a single object and so can more easily run out of control, especially where blur is involved - in which zooming stretches the blur radius, and speed of blur sharply depends on radius. For example in Xara, which has a very fast renderer but Illustrator's per-object strategy, viewing an object with large blurred shadow in zoom-in may make it irresponsible for long long seconds. In Inkscape, it is never as bad as that, because rendering blur in a narrow strip is much faster than in the entire screen (and screen resolutions keep growing, making this problem worse all the time). Also, Xara considers a single object a stroke which uses a "brush" composed of multiple objects scattered along a path, and strives to render it all at once - as a result, when my kids tried to make a not very complex drawing with such strokes, it quickly grew unusably slow.
Definitely, both methods are wasteful. With our method, we have to tesselate, stroke etc. each touched path for each buffer. With Illustrator, entire screen may have to be repainted multiple times even if these repaints will be covered by a top opaque object. In both cases, various smart strategies can be invented to reduce this waste.
So, it may be that something - like the hardware-accelerated rendering - forces us to switch to Illustrator repaint method. But in any case please don't do this switch without careful consideration and testing. Our method has served us very well, and what you call "artefacts" are in fact, after you get used to them, useful hints that enable you to work much faster than what our slow renderer would alow otherwise.
By the way, when dragging, we force the redraw to complete every 5 motion events; instead of doing that we could interrupt the drawing at most 5 times during a drag and then force a redraw.
I think this is exactly what it does now. The method is called "force_redraw_after_interruptions"; it counts the number of times render was interrupted, and does not directly depend on motion events.