Re: drawRect runs twice, bounds are changed in between
Re: drawRect runs twice, bounds are changed in between
- Subject: Re: drawRect runs twice, bounds are changed in between
- From: Quincey Morris <email@hidden>
- Date: Thu, 15 Jan 2015 06:58:27 +0000
On Jan 14, 2015, at 20:39 , N!K <email@hidden> wrote:
>
> I’m trying to learn more about drawing. One stumbling block was getting an NSBezierPath to change size proportional to the window size when the corner is dragged.
This is the wrong way to approach the problem. Scaling the bezier path itself is a bad idea, for two unrelated reasons:
1. Each time you apply a transform to the path, you’re doing floating point arithmetic, so you’re introducing errors. Possibly, in most circumstances, you won’t notice much, but the fact of accumulating error tells you that the approach is wrong.
2. A bezier path’s coordinates are dimensionless (that is, unit-less) numbers. They have no meaning in terms of points or pixels.
They are *given* a meaning by the current transform matrix (CTM) of a context you draw the path into. When the CTM is the identity matrix, 1 unit in the Bezier path’s coordinates equals one point, but that’s a byproduct of the way the graphics system was designed — a mere convenience.
Putting those two ideas together leads to a better approach. Create the bezier path once, relative to an arbitrary bounding rect — say 1000 x 1000. (But any rect would do.) When you need to draw the path, set the CTM of the context to scale 1000 x 1000 (the reference bounds) to the context’s width x height (the view bounds). Then just draw the original path and AppKit will scale the bezier path for you.
This will work for all graphics in the view. Create all the elements relative to the same 1000 x 1000 bounds you used for the first bezier path, and everything will come out the correct size.
It’s a little more complicated for “bitmap” graphics, because they intrinsically contain pixels. That may, but does not necessarily, mean that the bitmaps have an absolute size. This is important when you want to avoid having your bitmaps scaled when they’re drawn to the screen. However, in your case, you’re allowing the view to get resized to any size, which means bitmap scaling is going to happen most of the time. In this case, you can set your NSImage sizes (which are an abstract quantity) relative to the same 1000 x 1000 bounds you used before. Then, drawing NSImages will automatically scale the underlying bitmaps (regardless of their actual pixel dimensions) to the correct size for the view.
The last point I want make is that if your goal is to scale *everything* in the view by the same amount, according to the size of the view, then you can use ‘setBoundsSize:’ to set the bounds size relative to the view frame size, which effectively causes everything in the view to be scaled automatically. If your ultimate goal is this uniform, bounds scaling is the easiest way to get there.
The reference for all of this is the Cocoa Drawing Guide:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Introduction/Introduction.html <https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Introduction/Introduction.html>
If you’re trying to gain expertise in custom drawing in custom views, you’re going to need to be familiar with pretty much everything in this document.
P.S. ‘drawRect:’ never really had any relevance to what you’re trying to do. Even the NSView doesn’t really matter, except for telling you what absolute size to scale your graphics to.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden