Bounds, and frames, and position, oh my


I’m having trouble understanding the following code on page 403:

// Inset the image a bit on each side:
[boxLayer setContentsRect:CGRectMake(-0.1, -0.1, 1.2, 1.2)];

My initial thought was that it’s making the contents rect smaller, but the numbers being plugged into the CGRectMake arguments seem rather small in value: .1 and 1.2. What exactly does this line of code achieve?

Thanx in advance!


These numbers are independent of the actual size of the layer and are instead on a 0-1 scale, where 0 is 0% and 1 is 100% of the bounds.

Thus, if I inset the left edge by -.1 and my layer’s bounds have a width of 50, then the content is moved in 5 pixels from the left edge. Of course, if I keep the same inset and have a layer with a bounds of 500, I am moving the content in 50 pixels from the left edge.


I think I understand the part about the left edge inset, the negative numbers bring the left edge in by 10%. I’m not getting the second half of this, where the bottom right edge goes. Is it not extending the bounds outward? Can you explain the latter half of the parameters and what impact they have to the bounds (the 1.2, 1.2 parameters)?


Blah, the forum ate my post. I’ll try this again. Think about the contentsRect as a rectangle that is placed on the image. When the image is mapped to the layer, its actually the part of the image that falls in that rectangle that gets used.

By default, the contentsRect is (0, 0, 1, 1). Thus, entire image is mapped to fit exactly in the layer. Of course, if the layer is a different size than the image, the image has to be stretched to fit the layer, but the four corners of the image always match the four corners of the layer.

Changing the contentsRect will make it so the four corners of the image do not match the four corners of the layer. By increasing the size of the contentsRect, you are introducing whitespace to the image that gets mapped to the layer, because the rectangle is larger than the image. Of course, decreasing the size of the contentsRect will make the rectangle smaller than the image, and only a portion of the image is mapped to the layer. The origin of the contentsRect simply translates that rectangle.

So, by saying the contentsRect is 1.2x1.2 in size, you introduce whitespace to the image. Since a rects size grows from its origin, that whitespace is on the bottom and right edges of the image. Thus, you shift the rectangle to the left, which makes the whitespace uniformly distributed between each size.


Another explanation which might help those seeking clarity…
[I may be especially dense on this topic but I didn’t find Joe’s explanation very much more helpful than the documentation so I had to experiment my way to understanding. The problem, I hope, is that I have no idea what the point of contentsRect is and so the way it works is just some sort of magic. Of course the explanations (and documentation) are clear once I understood it (still don’t know what purpose it serves!), but… If the preceding posts aren’t clear for those reading the forum, perhaps a different explanation will help.]

Your image exists in what the documentation calls “the unit coordinate space” and the coordinates in that space are not pixels or points. In this space the image occupies a square with origin (upper left corner) at (0, 0) with both width and height of 1.0. The axes “scale” are relative to the size of the image – X and Y axes can be different.
The value of contentsRect specifies which rectangular area from this “unit coordinate space” should be drawn (i.e. mapped to) the layer.
This rectangle can be the whole image,
part of the image,
or, the case in the book, it can include the image and also parts of the space that lie outside the image.
The default contentsRect of (0, 0, 1, 1) is the whole image.
The contentsRect value (0.25, 0.25, 0.5 0.5), for example, would show part of the image –
a central rectangle of the image.
The contentsRect setting in the book, (-0.1, -0.1, 1.2, 1.2) includes parts of the
coordinate space outside the image itself. The corners of that rectangle are:
(-0.1, -0.1) – (1.1, -0.1)
| |
(-0.1, 1.1) – (1.1, 1.1)

So there is 0.1 of “extra space” on each border – i.e. 1/10th the dimension of the image in that axis.
When contentsRect includes space outside the image like this the pixels drawn in the layer
have to come from somewhere. Joe called it “whitespace”, and for Hypno.png that is the effect,
but what really happens is that:
“If pixels outside the unit rectangle are requested, the edge pixels of the contents image will be extended outwards.”

If this too is “clear as mud” then experimenting with various rectangles should help you.