How to use -[DOMNode boundingBox]

I thought I'd take a brief moment out from work on Sandvox to fill a hole in Apple's documentation. (Hopefully they'll catch up at some point, I do have rdar://problem/7194210 filed on the subject)

So you're browsing through the WebKit docs and come across this method: -[DOMNode boundingBox]. Sounds pretty neat right? Well it certainly is, but the documentation only goes so far as:

The rectangle that represents the bounding box of the onscreen rendering of the node.

Well, great! But, er, you're missing something pretty crucial; what coordinate system is this in? Without that, it's just a meaningless bit of data.

Well, empirically, the answer turns out to be the document view's coordinate system. This makes pretty good sense I think, especially when you consider a webpage with multiple frames etc. coming into play. How do you get hold of this view?

NSRect boundingBox = [node boundingBox];
											NSView *docView = [[[[node ownerDocument] webFrame] frameView] documentView];

Pretty straightforward, if a little longwinded.

I've also seen a fair bit of confusion on the web as to what to do with that next. The key is to convert the box into another view's (or window's) coordinate system where it's more useful to you. Unfortunately there seem to be plenty of developers ignorant of the built-in support for this and are trying to do the math themselves. So let's say you just wanted to take a screenshot of that bit of the WebView (the most common use for this I've noticed):

NSRect boundingBox = [node boundingBox];
											NSView *docView = [[[[node ownerDocument] webFrame] frameView] documentView];
											NSRect screenshotRect = [webView convertRect:boundingBox fromView:docView];
											NSBitmapImageRep *screenshot =
											   [webView bitmapImageRepForCachingDisplayInRect:screenshotRect];
											[webView cacheDisplayInRect:screenshotRect toBitmapImageRep:screenshot];

Or of course you could convert it to pretty much any other view's coordinate system using the same technique. Even the window's system (use -convertRect:toView: with a nil view) or the base coordinate system (use -convertRectToBase:).

© Mike Abdullah 2007-2015