[Drawkit] Scaling issues
Graham Cox
graham.cox at bigpond.com
Fri May 23 17:47:27 PDT 2008
On 24 May 2008, at 9:05 am, Brad Larson wrote:
> The problem is more that 1-point-wide grid lines get blown up into
> 50-pixel-wide lines at that zoom factor. This will happen to a
> lesser degree with anyone zooming in on a fine feature at a higher
> magnification than the one at which the grid lines were originally
> drawn. Scaling the entire grid, including linewidth, can be
> problematic, which is why I think redrawing the grid at a
> magnification change is the way to go. Testing it out, I don't
> think it will be that much of a performance hog.
Actually they are not that wide, but the point is valid. Since the
linewidth can be set independently of actually constructing the grid
cache it would be easy to set this on the fly taking into account the
zoom without invalidating the cache itself. I'll have a look at that
this morning.
> Sorry, zoomed out. After running the program through Instruments,
> it looks like the a whole lot of processor cycles are being spent in
> [DKDrawableObject pathBitmapInRect]. That method appears to
> rasterize the object shapes to perform hit detection, and the size
> of the bitmap seems to be set by the original zoom factor, so huge
> bitmaps are being created as you drag the mouse for the selection
> rectangle on this drawing. Maybe the bitmap hit testing could take
> the scale into account, creating bitmaps whose size only matches the
> size in pixels of that area at the current scale factor, then
> translate that scaled bitmap to the hit testing coordinates being
> fed in.
Yes, the bitmap creation is a bottleneck. It has got a lot better
though, since the bitmaps are formed from the intersection of the
selection rect and the object and then *only* when they overlap, not
if one wholly contains the other. And the "hit" is detected as soon as
a pixel is found to be set, which very often means that only a couple
need to be tested. However, there's no easy way to avoid the need to
make the bitmap in the first place and that's where you are seeing
time spent.
Currently the bitmap creation just uses the native object co-ordinate
space, so zoom is ignored altogether. This is a great advantage when
you are zoomed well *in*, because the objects are not being rendered
at the blown-up size you see, but their original size. However, for
the zoomed *out* case, you are right that this means a large area of
the drawing is being considered. If you have many small objects it's
probably fine, but large ones will hurt you if they overlap the
selection rect. So your suggestion for taking the zoom into account is
probably worthwhile for scales < 1, especially as in this case very
fine hit detection is not really necessary. Again, I'll look into it.
> What caused you to go with a variant of the method described here: http://lists.apple.com/archives/cocoa-dev/2004/Sep/msg00698.html
> as opposed to the mathematical model you proposed here: http://lists.apple.com/archives/cocoa-dev/2004/Sep/msg00696.html
> ? I haven't checked fully, but did you go with some of the
> optimizations that Uli Kusterer suggested in that thread?
Wow, that's an old thread ;-) At that time I was working on a very
early bit of code that eventually evolved into DrawKit. At that time,
I thought that plain strokes and fills would be all I'd end up using.
As they grew more complex, the mathematical hit testing got less
usable, so I switched over to using pixel-oriented hit testing, which
always works regardless of the stylistic variations, with the drawback
that it can be slower. The short story: I realised I was wrong and the
alternative approach was better.
DrawKit currently optimises to only perform the bitmap hit test after
culling the bounds rect for both exclusion and complete inclusion -
only the cases where an object overlaps the edge of the selection rect
generates a bitmap. The zoom is ignored, so there's a potential
optimisation I've missed. The bitmap isn't cached, it's created for
each hit test. That's another potential place to make an improvement,
though the cache management gets complicated-ish. I guess I could flag
the need to cache at the start of the selection drag and simply
discard at the end - that way *during* the drag the bitmaps are only
ever created once. That might be a good compromise between the complex
cache management I used to have and the current "hands free" approach.
I imagine applying both of these optimisations would speed things
substantially especially for your situation.
Anyway, this is the sort of feedback I've been hoping this list would
help generate - real world cases and a flagging up of the bottlenecks
they show up.
cheers, Graham
More information about the Drawkit
mailing list