Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Sep 30, 2009, 09:49 PM   #1
John Baughman
macrumors member
 
Join Date: Oct 2003
How to fill a path and keep the path line

I asked this question differently in the iPhone programming forum without any answer.

I have a path that I am stroking with a dashed line set to a width of 2. If I fill the path with either a solid fill or with a linear gradient I lose the dashed line of the path.

How can I fill the path and still see the stroked line?

Code:
CGContextBeginPath(context);
.
.
    //create the path
.
.
CGContextClosePath(context);

[[UIColor colorWithRed:0.808 green:0.58 blue:0.255 alpha:1.0] setFill];
CGContextFillPath(context);

[[UIColor blackColor] setStroke];
CGContextSetLineWidth(context, 2.0);
CGFloat dash1[] = {5.0, 2.0};
CGContextSetLineDash(context, 0.0, dash1, 2);	

CGContextStrokePath(context);
John Baughman is offline   0 Reply With Quote
Old Oct 1, 2009, 12:01 AM   #2
mdeh
macrumors 6502
 
Join Date: Jan 2009
Quote:

I have a path that I am stroking with a dashed line ...... If I fill the path with either a solid fill or with a linear gradient I lose the dashed line of the path.

How can I fill the path and still see the stroked line?

Have you tried doing the fill first, then the dashed line?
mdeh is offline   0 Reply With Quote
Old Oct 1, 2009, 12:11 AM   #3
John Baughman
Thread Starter
macrumors member
 
Join Date: Oct 2003
Quote:
Originally Posted by mdeh View Post
Have you tried doing the fill first, then the dashed line?
hmmm. Isn't that how I am doing it in the example code I included in my first post? If not, how do I reset the order?
John Baughman is offline   0 Reply With Quote
Old Oct 1, 2009, 01:41 AM   #4
Catfish_Man
macrumors 68030
 
Catfish_Man's Avatar
 
Join Date: Sep 2001
Location: Portland, OR
Send a message via AIM to Catfish_Man
Offhand that looks fine to me. Not sure what's going wrong. Try making your lengths and widths really big so it's extremely obvious when you get it drawing?
Catfish_Man is offline   0 Reply With Quote
Old Oct 1, 2009, 03:45 AM   #5
John Baughman
Thread Starter
macrumors member
 
Join Date: Oct 2003
Quote:
Originally Posted by Catfish_Man View Post
Offhand that looks fine to me. Not sure what's going wrong. Try making your lengths and widths really big so it's extremely obvious when you get it drawing?
Yes I had done that, set it to 10. Shifting back and forth between filled and not filled you can see that the fill is overlapping where the line should be. In other words the fill fills out to the outer edge of the path line.

Same thing with the linear gradient where the clip clips out to the outer edge of the path line.
John Baughman is offline   0 Reply With Quote
Old Oct 1, 2009, 05:36 AM   #6
John Baughman
Thread Starter
macrumors member
 
Join Date: Oct 2003
Ok I figured out a solution to the problem with regard to the fill. The path line will be display if I use

CGContextDrawPath(context, kCGPathFillStroke);

instead of...

CGContextStrokePath(context);

Still cannot figure out the gradient fill. CGContextDrawLinearGradient does not have an option similar to kCGPathFillStroke. Here is what my code looks like for a gradient fill...

Code:
CGGradientRef gradientFill;
CGColorSpaceRef colorSpace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 0.95, 0.30, 0.30, 1.0,  // Start color
		0.93, 0.94, 0.30, 1.0 }; // End color
		
colorSpace = CGColorSpaceCreateDeviceRGB();
gradientFill = CGGradientCreateWithColorComponents (colorSpace, components,											 locations, num_locations);

CGPoint myStartPoint, myEndPoint;
myStartPoint.x = 0.0; //gradientXStart-20;
myStartPoint.y = rect.size.height / 2.0;
myEndPoint.x = rect.size.width; //gradientXEnd+20;
myEndPoint.y = rect.size.height / 2.0;
		
[[UIColor blackColor] setStroke];
CGContextSetLineWidth(context, 2.0);
if(border.selectedSegmentIndex	== 1){
	CGContextSetLineDash(context, 0.0, dash1, 2);
			
}

CGContextClip(context);		
CGContextDrawLinearGradient (context, gradientFill, myStartPoint, myEndPoint, 0);
CGColorSpaceRelease(colorSpace);

//CGContextStrokePath(context);
//CGContextDrawPath(context, kCGPathFillStroke);
I tried using both CGContextStrokePath and CGContextDrawPath and neither gives me the line path.

I did just learn that I can leave out a path draw or stroke command and still get the polygon, which I assume is just the gradient in the clipped polygon. I would have thought that then calling the draw or stroke path command would draw the path over the gradient giving it the border I am looking for.
John Baughman is offline   0 Reply With Quote
Old Oct 1, 2009, 04:28 PM   #7
kainjow
Moderator emeritus
 
kainjow's Avatar
 
Join Date: Jun 2000
I would use CGPaths instead of manipulating the path directly on the context.

Here's how I did it (you'll obviously want to modify the path, and replace the NS* classes with the UI* ones.):

Code:
// create the path
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 10.0, 10.0);
CGPathAddLineToPoint(path, NULL, 100.0, 10.0);
CGPathAddLineToPoint(path, NULL, 100.0, 100.0);
CGPathAddLineToPoint(path, NULL, 10.0, 100.0);
CGPathAddLineToPoint(path, NULL, 10.0, 10.0);

// setup the gradient
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = {
	0.95, 0.30, 0.30, 1.0,  // Start color
	0.93, 0.94, 0.30, 1.0	// End color
};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradientFill = CGGradientCreateWithColorComponents (colorSpace, components, locations, 2);

// setup gradient points
CGRect pathRect = CGPathGetBoundingBox(path);
CGPoint myStartPoint, myEndPoint;
myStartPoint.x = CGRectGetMinX(pathRect);
myStartPoint.y = CGRectGetMinY(pathRect);
myEndPoint.x = CGRectGetMaxX(pathRect);
myEndPoint.y = CGRectGetMinY(pathRect);

// draw the gradient
CGContextAddPath(context, path);
CGContextSaveGState(context);
CGContextClip(context);
CGContextDrawLinearGradient (context, gradientFill, myStartPoint, myEndPoint, 0);
CGContextRestoreGState(context);

// draw the dash
CGContextAddPath(context, path);
[[NSColor blackColor] setStroke];
CGContextSetLineWidth(context, 2.0);
CGFloat dash1[] = {5.0, 2.0};
CGContextSetLineDash(context, 0.0, dash1, 2);
CGContextStrokePath(context);

// cleanup
CGColorSpaceRelease(colorSpace);
CGGradientRelease(gradientFill);
CGPathRelease(path);
The key is to use CGContextAddPath() which adds the path back onto the context. I guess CG removes it after a fill/stroke.

Here's how it looks (draw inside an OS X window):

Name:  path.png
Views: 8659
Size:  16.1 KB
kainjow is offline   0 Reply With Quote
Old Oct 1, 2009, 05:39 PM   #8
John Baughman
Thread Starter
macrumors member
 
Join Date: Oct 2003
Quote:
Originally Posted by kainjow View Post
I would use CGPaths instead of manipulating the path directly on the context.
... snip
The key is to use CGContextAddPath() which adds the path back onto the context. I guess CG removes it after a fill/stroke.

Attachment 197106
Fantastic. That looks great. I looked at CGContextAddPath but did not recognize that with it I could add paths to a context created as CGPaths outside of a context. Good stuff.

A quick question. Why do you save the state before you clip and draw the gradient. What is actually being done when you save and restore a context's state? That is really fuzzy to me.

Thanks,

John
John Baughman is offline   0 Reply With Quote
Old Oct 1, 2009, 05:49 PM   #9
kainjow
Moderator emeritus
 
kainjow's Avatar
 
Join Date: Jun 2000
Quote:
Originally Posted by John Baughman View Post
A quick question. Why do you save the state before you clip and draw the gradient. What is actually being done when you save and restore a context's state? That is really fuzzy to me.
Usually saving/restoring the graphics state is done when you're clipping, adding a shadow or affine transformation, or other things that affect subsequent draws. More info at Graphics Contexts (see the Graphics State Information section).

So in this case, I save/restore it before drawing the dashed line, because the dashed line would be clipped also. Stroked paths are drawn centered on the path, not inside or outside it. If you remove those save/restore calls, you'll see what I mean when the path is stroked.
kainjow is offline   0 Reply With Quote
Old Apr 26, 2013, 06:23 AM   #10
vtata
macrumors newbie
 
Join Date: Apr 2013
Quote:
Originally Posted by John Baughman View Post
I asked this question differently in the iPhone programming forum without any answer.

I have a path that I am stroking with a dashed line set to a width of 2. If I fill the path with either a solid fill or with a linear gradient I lose the dashed line of the path.

How can I fill the path and still see the stroked line?

Code:
CGContextBeginPath(context);
.
.
    //create the path
.
.
CGContextClosePath(context);

[[UIColor colorWithRed:0.808 green:0.58 blue:0.255 alpha:1.0] setFill];
CGContextFillPath(context);

[[UIColor blackColor] setStroke];
CGContextSetLineWidth(context, 2.0);
CGFloat dash1[] = {5.0, 2.0};
CGContextSetLineDash(context, 0.0, dash1, 2);	

CGContextStrokePath(context);



How can I draw a gradient line on iPad.
Can any one please help me .
Thanks in advance.
vtata is offline   0 Reply With Quote
Old Apr 26, 2013, 09:44 AM   #11
gnasher729
In Time-Out
 
Join Date: Nov 2005
Quote:
Originally Posted by vtata View Post
How can I draw a gradient line on iPad.
Can any one please help me .
Thanks in advance.
Apple can help you.

Start Xcode. Press Command-Shift-2. Click on "Documentation". Enter "gradient" in the search box.
gnasher729 is offline   0 Reply With Quote
Old Apr 26, 2013, 09:51 AM   #12
xStep
macrumors 68000
 
Join Date: Jan 2003
Location: Less lost in L.A.
Quote:
Originally Posted by vtata View Post
How can I draw a gradient line on iPad.
Can any one please help me .
Thanks in advance.
You start by doing some research on gradients.

Next, when posting a more descriptive question to MR, you begin a new thread. Hijacking an old one for what is an unrelated question is not good etiquette.

When you come back to post your question, state what you have tried and your intended end goal.
xStep is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Copying two different path Betfair39 Mac Basics and Help 0 Jan 18, 2014 04:27 PM
Regarding Path Finder 5.2.2 ifrit05 Mac Applications and Mac App Store 2 Dec 27, 2013 06:12 PM
$PATH messed up. please help... tomiko iMac 1 Aug 19, 2013 01:56 PM
Career path canwe3 Community Discussion 19 Jan 28, 2013 11:09 AM
PATH and PYTHONPATH OpenCV HELP! uqarni Mac Programming 0 Sep 20, 2012 08:55 AM

Forum Jump

All times are GMT -5. The time now is 06:33 PM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC