iphone - Clipping a CGGradient to a CGPath -
i've been banging head against wall long while trying figure out why not working.
basically, trying plot graph (chart) cgpath , use clip gradient. end effect should stocks app comes iphone.
the gradient , path draw fine separately 2 layered (unclipped) elements. if comment out cgcontextdrawpath, neither line nor gradient draw screen.
here's drawrect code:
cgcontextref context = uigraphicsgetcurrentcontext(); [[uicolor whitecolor] set]; cgcontextsetlinewidth(context, 2.0f); cgpoint lastdrawnpt = [[points objectatindex:0] cgpointvalue]; cgpoint firstdrawnpt = lastdrawnpt; //create path gradient cgmutablepathref thepath = cgpathcreatemutable(); cgpathmovetopoint(thepath, null, lastdrawnpt.x, self.bounds.size.height); // bottom left cgpathaddlinetopoint(thepath, null, lastdrawnpt.x, lastdrawnpt.y); (int i=0; i<(points.count-1); i++) { //cgpoint pt1 = [[points objectatindex:i] cgpointvalue]; cgpoint pt2 = [[points objectatindex:i+1] cgpointvalue]; if (pt2.x > lastdrawnpt.x+2) { // draw if we've moved sunstantially right //for gradient cgpathmovetopoint(thepath, null, lastdrawnpt.x, lastdrawnpt.y); cgpathaddlinetopoint(thepath, null, pt2.x, pt2.y); lastdrawnpt = pt2; } } //finish gradient clipping path cgpathmovetopoint(thepath, null, lastdrawnpt.x, lastdrawnpt.y); cgpathaddlinetopoint(thepath, null, lastdrawnpt.x, self.bounds.size.height); // bottom right cgpathmovetopoint(thepath, null, lastdrawnpt.x, self.bounds.size.height); cgpathaddlinetopoint(thepath, null, firstdrawnpt.x, self.bounds.size.height); // bottom right cgpathclosesubpath(thepath); //add gradient clipping path context cgcontextsavegstate(context); cgcontextaddpath(context, thepath); //draw path float components[4] = {1.0, 1.0, 1.0, 1.0}; cgcontextsetstrokecolor(context, components); cgcontextdrawpath(context,kcgpathstroke); //clip path cgcontextclip(context); //draw gradient uicolor *topcolor = [uicolor colorwithred: 1.0 green:1.0 blue:1.0 alpha:1.0]; uicolor *bottomcolor = [uicolor colorwithred:1.0 green:1.0 blue:1.0 alpha:0.0]; cgcolorref colorref[] = { [topcolor cgcolor], [bottomcolor cgcolor] }; cfarrayref colors = cfarraycreate(null, (const void**)colorref, sizeof(colorref) / sizeof(cgcolorref), &kcftypearraycallbacks); cgcolorspaceref colorspace = cgcolorspacecreatedevicergb(); cggradientref gradient = cggradientcreatewithcolors(colorspace, colors, null); cfrelease(colorspace); cfrelease(colors); // draw linear gradient top bottom cgpoint gradstartpoint = cgpointmake(50.0, self.bounds.size.height); cgpoint gradendpoint = cgpointmake(50.0, 0.0); cgcontextdrawlineargradient(context, gradient, gradstartpoint, gradendpoint, 0); cfrelease(gradient); // cleanup cgcolorspacerelease(colorspace); cgcontextrestoregstate(context);
cgpathmovetopoint(thepath, null, lastdrawnpt.x, self.bounds.size.height); // bottom left cgpathaddlinetopoint(thepath, null, lastdrawnpt.x, lastdrawnpt.y); (int i=0; i<(points.count-1); i++) { //cgpoint pt1 = [[points objectatindex:i] cgpointvalue]; cgpoint pt2 = [[points objectatindex:i+1] cgpointvalue]; if (pt2.x > lastdrawnpt.x+2) { // draw if we've moved sunstantially right //for gradient cgpathmovetopoint(thepath, null, lastdrawnpt.x, lastdrawnpt.y); cgpathaddlinetopoint(thepath, null, pt2.x, pt2.y); lastdrawnpt = pt2; } } //finish gradient clipping path cgpathmovetopoint(thepath, null, lastdrawnpt.x, lastdrawnpt.y); cgpathaddlinetopoint(thepath, null, lastdrawnpt.x, self.bounds.size.height); // bottom right cgpathmovetopoint(thepath, null, lastdrawnpt.x, self.bounds.size.height); cgpathaddlinetopoint(thepath, null, firstdrawnpt.x, self.bounds.size.height); // bottom right
this plots series of line segments. point values, might this:
| |||| |
it not plot single continuous shape. such, path useless clipping, empty; you've seen, clipping result in no further drawing being inside clipping path.
every lineto
, curveto
, arc
, etc. works current point. set initially moveto
, each lineto
, curveto
, arc
, etc. not clear current point, updates it. thus, create single shape, 1 moveto
followed succession of lineto
(or curveto
or arc
), followed closepath
.
speaking of closepath
…
cgpathclosesubpath(thepath);
this creates closed shape in path, since shape has 0 area (being only line segment doubles on itself), still not helpful clipping purposes.
i suspect need cut out @ least 1 of moveto
segments (the 1 in loop, if not 1 after it). then, can simplify loop—use fast enumeration on array, instead of using indexes, , cut out keeping track of “last drawn point”.
also, correct type indexes nsarray nsuinteger
, not int
. keep types matched—it avoids pain later down road.
Comments
Post a Comment