Assignment 3 Gradient

47 views
Skip to first unread message

Joe

unread,
Apr 19, 2009, 2:16:03 AM4/19/09
to iPhone Application Development Auditors
I've been working on one of Assignment 3's bonus items, drawing the
shape with a gradient, and I can't seem to get the hang of it. I
copied the code out of the Quartz 2D Programming guide and it really
doesn't so I would expect it to.

First of all, the command to create the color context throws a
warning, and I'm guessing by the nasty yellow color that results that
it's not taking. This line:
CGColorSpaceRef myColorspace = CGColorSpaceCreateWithName
(kCGColorSpaceGenericRGB);

Throws these warnings:
warning: 'kCGColorSpaceGenericRGB' is deprecated (declared at /
Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/
iPhoneSimulator2.2.1.sdk/System/Library/Frameworks/
CoreGraphics.framework/Headers/CGColorSpace.h:46)
warning: 'kCGColorSpaceGenericRGB' is unavailable (declared at /
Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/
iPhoneSimulator2.2.1.sdk/System/Library/Frameworks/
CoreGraphics.framework/Headers/CGColorSpace.h:46)


Also, I can't get the gradient to draw inside the path I created.
When I fill the path using the following code:
[[UIColor blueColor] setFill];
[[UIColor blackColor] setStroke];
CGContextDrawPath(context, kCGPathFillStroke);

The shape draws beautifully. But when I use either of the gradient
functions, even using exactly the same context, it draws the gradient
in the background, outside the specified path.

So, I guess my question is, did anybody get this working? Any
pointers?

Joe

Sadat

unread,
Apr 19, 2009, 2:29:04 AM4/19/09
to iPhone Application Development Auditors
Have a look at lecture 5. You need to clip the region before you apply
the gradient transform.
Message has been deleted

Miguel Andrés Yáñez Barreto

unread,
Apr 19, 2009, 3:08:39 AM4/19/09
to iphone-appd...@googlegroups.com
To be honest, I applied a gradient to the background, so I might have not found the problem you're experiencing.

However, my code uses a colour space, maybe this could help you?

rgbColorspace = CGColorSpaceCreateDeviceRGB();
    glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);


Miguel Andrés Yáñez Barreto - Asistente Graduado
Especialización en Seguridad de la Información
Presidente de Maratones Uniandes

On Apr 19, 2009, at 02:05 , Mark Struik wrote:


there is nothing on clipping in lecture 5?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "iPhone Application Development Auditors" group.
To post to this group, send email to iphone-appd...@googlegroups.com
To unsubscribe from this group, send email to iphone-appdev-aud...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/iphone-appdev-auditors?hl=en
-~----------~----~----~----~------~----~------~--~---


Mark Struik

unread,
Apr 19, 2009, 4:10:06 AM4/19/09
to iPhone Application Development Auditors
nope that doesn't do the trick

i tried this:

CGRect bounds = [self bounds];

CGGradientRef gradient;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGFloat colors[] =
{
204.0 / 255.0, 224.0 / 255.0, 244.0 / 255.0, 1.00,
29.0 / 255.0, 156.0 / 255.0, 215.0 / 255.0, 1.00,
0.0 / 255.0, 50.0 / 255.0, 126.0 / 255.0, 1.00,
};
gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL,
sizeof(colors)/(sizeof(colors[0])*4));
CGColorSpaceRelease(rgb);

CGPoint start = CGPointMake(bounds.origin.x, bounds.origin.y);
CGPoint end = CGPointMake(bounds.origin.x, bounds.size.height);
CGContextDrawLinearGradient(context, gradient, start, end, 0);

On 19 apr, 09:08, Miguel Andrés Yáñez Barreto <migueland...@gmail.com>
wrote:
> To be honest, I applied a gradient to the background, so I might have  
> not found the problem you're experiencing.
>
> However, my code uses a colour space, maybe this could help you?
>
> rgbColorspace = CGColorSpaceCreateDeviceRGB();
>      glossGradient =  
> CGGradientCreateWithColorComponents(rgbColorspace, components,  
> locations, num_locations);
>
> Miguel Andrés Yáñez Barreto - Asistente Graduado
> Especialización en Seguridad de la Información
> Presidente de Maratones Uniandes
> migueland...@gmail.com
>  smime.p7s
> 3KWeergevenDownloaden

Mark Struik

unread,
Apr 19, 2009, 4:18:20 AM4/19/09
to iPhone Application Development Auditors
aha i found something about the clipping in the quarts 2d programming
guide :) that seems to do the trick :) i had it after i drawed the
polygon. so that wasn't working... but now that i moved it :)

On 19 apr, 08:29, Sadat <sadat.rah...@gmail.com> wrote:

Joe

unread,
Apr 19, 2009, 9:44:50 AM4/19/09
to iPhone Application Development Auditors
Great job, guys!

Ok, so my first problem seems to be that the iPhone doesn't like the
way I had created the colorspace, even though the iPhone documentation
doesn't say so.

Then, it was all about the clipping! After I created the path, but
before I created the gradient, you have to set the path as the
clipping path. It's all in the Quartz 2D Programming Guide -> Paths -
> Clipping to a Path.

Thanks for the help, it looks great!

Now, on to the rotation....
Joe

Mark Struik

unread,
Apr 19, 2009, 12:11:28 PM4/19/09
to iPhone Application Development Auditors
anybody got a poly with gradient and border??

Pedro Araújo

unread,
Apr 19, 2009, 6:05:50 PM4/19/09
to iphone-appd...@googlegroups.com
On Sun, Apr 19, 2009 at 13:11, Mark Struik <mark....@gmail.com> wrote:
anybody got a poly with gradient and border??

Yes, I did:

Picture 1.png
First I clipped the context along the path and drew the gradient, then I drew the stroke (same approach as to the background gradient).

Cheers,
Pedro.
Picture 1.png

tomute

unread,
Apr 21, 2009, 2:39:52 PM4/21/09
to iPhone Application Development Auditors
Thanks to Mark and Pedro's advice.
I also succeeded to draw a polygon with gradient and border.

First I created CGGradientRef with using Mark's way.
Next, from Pedro's advice, I clipped the context along the path (I use
CGContextClip()).
Then, I draw the polygon with gradient by using
CGContextDrawLinearGradient().

After that, I tried to draw the border of the polygon with UIColor
setStroke and CGContextDrawPath(), but I failed.
I think this is because I created the path with CGContext. This is not
reusable.
So, this is redundant way though, I got a current context and created
the same path again in drawRect.
Then, I draw the border with UIColor setStroke and CGContextDrawPath
(), so this time I succeeded.

If I use CGPath, it might become more simple. But I don't understand
how to use.

Regards,
tomute

Rich MacDonald

unread,
Apr 21, 2009, 3:21:46 PM4/21/09
to iphone-appd...@googlegroups.com
Start with

CGMutablePathRef path = CGPathCreateMutable();


Then use the path updating equivalents, which all take the path ref as the first argument.  

CGPathMoveToPoint(path, ....)

CGPathAddLineToPoint(path, ....)

CGPathCloseSubpath(path)


And lastly, to add the path to the context


CGContextAddPath(context, path);


The path gets removed from the context with many calls (clipping, drawingPath, saving and restoring contexts from the graphics state stack), but you can keep adding it back the CGContextAddPath() function.  


-Rich
Message has been deleted

Mark Struik

unread,
Apr 21, 2009, 5:04:05 PM4/21/09
to iPhone Application Development Auditors
of cource... ok that was obvious... why didn't i think of that... DOH!

On 20 apr, 00:05, Pedro Araújo <inc...@gmail.com> wrote:
> On Sun, Apr 19, 2009 at 13:11, Mark Struik <mark.str...@gmail.com> wrote:
> > anybody got a poly with gradient and border??
>
> Yes, I did:
>
> [image: Picture 1.png]
> First I clipped the context along the path and drew the gradient, *then *I
> drew the stroke (same approach as to the background gradient).
>
> Cheers,
> Pedro.
>
>  Picture 1.png
> 332KWeergevenDownloaden

tomute

unread,
Apr 21, 2009, 5:19:40 PM4/21/09
to iPhone Application Development Auditors
Hi Rich,

Thank you for letting me know how to use CGPath!
That makes sense to me.

Regards,
tomute

On Apr 21, 1:21 pm, Rich MacDonald <rich.macdon...@gmail.com> wrote:
> Start with
>
> CGMutablePathRef path = CGPathCreateMutable();
>
> Then use the path updating equivalents, which all take the path ref as the
> first argument.
>
> CGPathMoveToPoint(path, ....)
>
> CGPathAddLineToPoint(path, ....)
>
> CGPathCloseSubpath(path)
>
> And lastly, to add the path to the context
>
> CGContextAddPath(context, path);
>
> The path gets removed from the context with many calls (clipping,
> drawingPath, saving and restoring contexts from the graphics state stack),
> but you can keep adding it back the CGContextAddPath() function.
>
> -Rich
>

alexis

unread,
May 31, 2009, 3:09:48 AM5/31/09
to iPhone Application Development Auditors
Rich,

I'm a little confused by your comment "The path gets removed from the
context with many calls (clipping,
drawingPath, saving and restoring contexts from the graphics state
stack),
but you can keep adding it back the CGContextAddPath() function. "

Based on that, I looked around and figured why not try and use
CGContextSaveGState in order to save my context, then restore it.

However, according to the Apple docs, the path actually is not removed
after you clip. Take a look at the overview of CGContextSaveGState
http://developer.apple.com/documentation/graphicsimaging/reference/CGContext/Reference/reference.html#//apple_ref/c/func/CGContextSaveGState

It says:
"Each graphics context maintains a stack of graphics states. Note that
not all aspects of the current drawing environment are elements of the
graphics state. For example, the current path is not considered part
of the graphics state and is therefore not saved when you call the
CGContextSaveGState function. "

So I am wondering how the path is removed if its not removed from the
context?

Thanks,
Alexis
On Apr 21, 3:21 pm, Rich MacDonald <rich.macdon...@gmail.com> wrote:
> Start with
>
> CGMutablePathRef path = CGPathCreateMutable();
>
> Then use the path updating equivalents, which all take the path ref as the
> first argument.
>
> CGPathMoveToPoint(path, ....)
>
> CGPathAddLineToPoint(path, ....)
>
> CGPathCloseSubpath(path)
>
> And lastly, to add the path to the context
>
> CGContextAddPath(context, path);
>
> The path gets removed from the context with many calls (clipping,
> drawingPath, saving and restoring contexts from the graphics state stack),
> but you can keep adding it back the CGContextAddPath() function.
>
> -Rich
>

Rich MacDonald

unread,
Jun 1, 2009, 7:25:42 PM6/1/09
to iphone-appd...@googlegroups.com
Alexis, it is a bit confusing.  There is a distinction between a clipping path and current path - the former is saved as part of the context state while the latter is not.  

The documentation for CGContextClip states:

After determining the new clipping path, the function resets the context’s current path to an empty path.

So if you want to fill your shape with a gradient and then draw the outline of the shape on top of this, you need to add the path to the context again before calling  CGContextDrawPath(context, kCGPathStroke); I've tested this without adding the path and no outline is drawn, so I'm pretty sure this interpretation is correct.  

Saving the state before the clipping and then restoring it is only necessary if you want to avoid the outline stroke being cut to half its width because of the clipping path (i.e. the half outside the path won't be drawn with the clipping path still in the graphics state).  

Hope this helps.  

-Rich

perlsmith

unread,
Jul 3, 2009, 6:36:53 PM7/3/09
to iPhone Application Development Auditors
No matter what I try, I don't get any gradient at all. I'm pasting in
case someone spots something obvious. Thanks for looking.

<code>
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGFloat colors[] =
{
1.0, 0, 0, 1.0,
0.0, 0.0, 0.0, 1.0
};
myGradient = CGGradientCreateWithColorComponents (myColorspace,
colors, NULL,
sizeof(colors)/(sizeof(colors[0])*4));

CGColorSpaceRelease(myColorspace);
}
return self;
}



- (void)drawRect:(CGRect)rect {
CGRect clips[] =
{
CGRectMake(10.0, 30.0, 60.0, 90.0),
};
CGContextRef context = UIGraphicsGetCurrentContext();
polyName.text = [polygon name];
NSArray *pointsArray = [PolygonShape pointsForPolygonInRect:rect
numberOfSides:polygon.getSides];

CGContextSaveGState(context);
CGContextClipToRect(context, clips[0]);

// [[UIColor grayColor] set];
// UIRectFill([self bounds]);
CGPoint start, end;
start = CGPointMake(0.0, rect.size.height/2.0);
end = CGPointMake(rect.size.width, rect.size.height/2.0);
CGContextDrawLinearGradient(context, myGradient, start, end, 0);
CGContextRestoreGState(context);

// Drawing code

CGContextBeginPath(context);
CGPoint aPoint = [[pointsArray objectAtIndex:0] CGPointValue];
CGContextMoveToPoint(context, aPoint.x, aPoint.y);
for( id point in pointsArray){
aPoint = [point CGPointValue];
CGContextAddLineToPoint(context, aPoint.x, aPoint.y);
}
CGContextClosePath(context);
CGContextSetLineWidth(context, lineWidthCtrl.value);
if( lineStyleCtrl.selectedSegmentIndex ){
CGContextSetLineDash(context, 1.0, (float []){2.0,2.0}, 2);
}


[[UIColor brownColor] setFill];
[[UIColor blackColor] setStroke];
CGContextDrawPath(context, kCGPathFillStroke);
CGContextClip(context);
// CGContextDrawLinearGradient(context, myGradient, start, end,
kCGGradientDrawsAfterEndLocation);

}
</code>

perlsmith

unread,
Jul 5, 2009, 5:51:09 PM7/5/09
to iPhone Application Development Auditors
My problem is that the init method (or initWithFrame) of the
polygonView object is never called. Any thoughts?

If I explicitly say

[polygonView init]

within the awakeFromNib in the Controller, then I get the background
gradient, but some connections seem broken and the polygon never
updates.

perlsmith

unread,
Jul 5, 2009, 7:33:25 PM7/5/09
to iPhone Application Development Auditors
I had a couple of mistakes. One, I called my init routine "init" and
did

[super init]

which doesn't exist for UIView.

Then, in the case of loading views from nib's, it's initWithCoder

so use

- (id) initWithCoder: (NSCoder *) coder {
if( self = [super initWithCoder:coder] ){
Reply all
Reply to author
Forward
0 new messages