Confused about drawing


#1

I feel like the book falls apart of me in this chapter. Up until this point, each new concept or procedure is introduced, explained, and put into context. Suddenly, in this chapter, we are thrown into drawing routines without much explanation apart from the drawRect method, and many potential questions go unanswered. Here’s my experience:

  1. Why, after working almost exclusively with object oriented frameworks, is drawing in iOS all about C structs and function calls?

  2. What the heck is a “context reference”. The API ref calls it an “opaque type”. What the heck is is that? How does it work?

  3. The book tells us that a graphics context is created before drawRect is called, and that this context is only available during the time drawRect is being executed. You then add items to the context, and I guess the system draws them whenever it’s ready. If objects and delegation is the way things are done in Cocoa, why do we call:

CGContextRef context = UIGraphicsGetCurrentContext();

Why not issue messages to a graphics context object?

  1. Why is line color set with CGContextSetLineWidth(), but the line’s color set with [[UIColor lightGrayColor] setStroke] ? This seems horribly inconsistent. If we’re calling functions and using C structs, why not CGContextSetLineColor(context, “red”)? How does the UIColor object talk to the graphics context? For that matter, what happens when you call a class method (UIColor) that returns an object, but you don’t assign it to anything? Where does the object go? Is it ever deallocated? This is the first time in this book this is done and no explanation is given.

  2. If the system calls drawRect when it is ready, and the items were added to the graphics context inside that drawRect are rendered automatically, why then does text have to manually be drawn with drawInRect:? Why not something like this:

CGContextAddText(context, text, font);

  1. Why does text have to be tendered inside a CGRect, whereas lines and shapes do not?

  2. Why is the text in this HypnosisView rendered on top of the concentric circles? I assume that this is because the drawInRect call for the text comes after the circles are “added” to the graphics context. But when does the context render the items that are “added”? immediately? At the end of drawRect?

Man, I feel like I was pushed off a cliff in this chapter.


#2

Welcome to Quartz 2D !

  1. Speed. Objects work well for a lot of things, but if speed is of the essence then they get closer to the bare metal (so to speak).

  2. Convenience. Yes, there IS a way to specify colour in CoreGraphics, but not with nice names; instead, they deal directly with red/green/blue/alpha values. And you alread know what happens with the object from [UIColor lightGrayColor]. The instance came from a method other than new, alloc, or copy, so it must already be autoreleased. We didn’t retain it, so it will be drained with the rest of the autoreleased objects the next time through the event loop.

For more answers (except to the “Why?” questions), see Apple’s Quartz 2D Programming Guide.

Incidentally, Programming with Quartz is an outstanding book with amazingly few errors, but it’s quite dense and definitely not light reading (and now six years old).

EDIT:
2) A context reference is described in the chapter as aggregating drawing commands, preserving the drawing state, and producing the image. If you use HTML5, the canvas element has a very similar concept.

  1. CoreGraphics doesn’t use Cocoa. (See the answer to item #1 above.)

  2. Items are not drawn “automatically” even in drawRect:. CGContextStrokePath() causes the circles to be rendered. And you’re right; the text could have been drawn using only CoreGraphics routines (see the last section of the Quartz 2D Programming Guide). But as you’ve seen, since CoreGraphics routines are pretty close to the metal, everything there is just a bit more cumbersome. So while everything could have been done using pure CoreGraphics calls, the code would have been that much more obtuse. (Note for example that Apple’s code snippet for drawing text uses the C string “Quartz 2D” rather than the NSString @“Quartz 2D”.)

  3. It didn’t have to be. CoreGraphics has CGContextShowTextAtPoint() and CGContextSetTextPosition(). The NSString drawing routines come from the UIKit Additions. (Search for NSString in the Xcode docs.) Those include variations on drawAtPoint: and drawInRect:. The latter set can also perform word wrapping.

  4. The concentric circles are rendered with each call to CGContextStrokePath(). The text is rendered with drawInRect:withFont:. It’s really tough to do both of these at the same time.

EDIT 2: fixed spelling error; oops.


#3

I just want to chime in on Jasons post. I agree with his concerns. It would be nice if whole CGContext was explained a bit more. Maybe include another diagram showing how it’s wired. I’m going to dissect the drawrect method a hundred ways…

Regarding RGBA: As a graphic designer, I like have control of the color, I think explaining how to implement the rgba would have been good. I have used it in UIColor.

I understand you are encouraging us on how to think, so that we may develop the skills to solve problems.


#4

Colour in Core Graphics/Quartz 2D can be pretty involved, so I suspect the authors took the easy route of using UIColor’s colour names for simplicity so they would have room to talk about other topics.

(They do use UIColor and RGBA in chapter 14 but without any real explanation. On the one hand that’s understandable since colour theory starts to get a little off topic. On the other hand they devote a full page to explaining binary numbers in chapter 9.)

You can read more about the various ways to specify colour in Core Graphics here.


#5

I do agree that this chapter was a little sparse on details. I rewrote it for the third edition, it’s about 10 pages longer, but I think it covers it better. As always, gc3182’s answers to your questions are correct and very good.