@@ -240,11 +240,15 @@ static void _dealloc_atsui(void)
240240}
241241#endif
242242
243- static int _draw_path (CGContextRef cr, void * iterator)
243+ static int _draw_path (CGContextRef cr, void * iterator, int nmax )
244244{
245245 double x1, y1, x2, y2, x3, y3;
246+ static unsigned code = STOP;
247+ static double xs, ys;
248+ CGPoint current;
246249 int n = 0 ;
247- unsigned code;
250+
251+ if (code == MOVETO) CGContextMoveToPoint (cr, xs, ys);
248252
249253 while (true )
250254 {
@@ -261,7 +265,6 @@ static int _draw_path(CGContextRef cr, void* iterator)
261265 else if (code == MOVETO)
262266 {
263267 CGContextMoveToPoint (cr, x1, y1);
264- n++;
265268 }
266269 else if (code==LINETO)
267270 {
@@ -270,31 +273,50 @@ static int _draw_path(CGContextRef cr, void* iterator)
270273 }
271274 else if (code==CURVE3)
272275 {
273- get_vertex (iterator, &x2 , &y2 );
274- CGContextAddQuadCurveToPoint (cr, x1, y1, x2, y2 );
276+ get_vertex (iterator, &xs , &ys );
277+ CGContextAddQuadCurveToPoint (cr, x1, y1, xs, ys );
275278 n+=2 ;
276279 }
277280 else if (code==CURVE4)
278281 {
279282 get_vertex (iterator, &x2, &y2);
280- get_vertex (iterator, &x3 , &y3 );
281- CGContextAddCurveToPoint (cr, x1, y1, x2, y2, x3, y3 );
283+ get_vertex (iterator, &xs , &ys );
284+ CGContextAddCurveToPoint (cr, x1, y1, x2, y2, xs, ys );
282285 n+=3 ;
283286 }
287+ if (n >= nmax)
288+ {
289+ switch (code)
290+ {
291+ case MOVETO:
292+ case LINETO:
293+ xs = x1;
294+ ys = y1;
295+ break ;
296+ case CLOSEPOLY:
297+ current = CGContextGetPathCurrentPoint (cr);
298+ xs = current.x ;
299+ ys = current.y ;
300+ break ;
301+ /* nothing needed for CURVE3, CURVE4 */
302+ }
303+ code = MOVETO;
304+ return -n;
305+ }
284306 }
285307 return n;
286308}
287309
288310static void _draw_hatch (void *info, CGContextRef cr)
289311{
312+ int n;
290313 PyObject* hatchpath = (PyObject*)info;
291314 PyObject* transform;
292315 int nd = 2 ;
293316 npy_intp dims[2 ] = {3 , 3 };
294317 int typenum = NPY_DOUBLE;
295318 double data[9 ] = {HATCH_SIZE, 0 , 0 , 0 , HATCH_SIZE, 0 , 0 , 0 , 1 };
296319 double rect[4 ] = { 0.0 , 0.0 , HATCH_SIZE, HATCH_SIZE};
297- int n;
298320 transform = PyArray_SimpleNewFromData (nd, dims, typenum, data);
299321 if (!transform)
300322 {
@@ -320,7 +342,7 @@ static void _draw_hatch(void *info, CGContextRef cr)
320342 PyGILState_Release (gstate);
321343 return ;
322344 }
323- n = _draw_path (cr, iterator);
345+ n = _draw_path (cr, iterator, INT_MAX );
324346 free_path_iterator (iterator);
325347 if (n==0 ) return ;
326348 CGContextSetLineWidth (cr, 1.0 );
@@ -702,7 +724,7 @@ static int _get_snap(GraphicsContext* self, enum e_snap_mode* mode)
702724 " set_clip_path: failed to obtain path iterator for clipping" );
703725 return NULL ;
704726 }
705- n = _draw_path (cr, iterator);
727+ n = _draw_path (cr, iterator, INT_MAX );
706728 free_path_iterator (iterator);
707729
708730 if (n > 0 ) CGContextClip (cr);
@@ -952,89 +974,98 @@ static int _get_snap(GraphicsContext* self, enum e_snap_mode* mode)
952974 " draw_path: failed to obtain path iterator" );
953975 return NULL ;
954976 }
955- n = _draw_path (cr, iterator);
956- free_path_iterator (iterator);
957977
958- if (n > 0 )
978+ if (rgbFace )
959979 {
960- PyObject* hatchpath;
961- if (rgbFace)
980+ float r, g, b;
981+ if (!PyArg_ParseTuple (rgbFace, " fff" , &r, &g, &b))
982+ return NULL ;
983+ n = _draw_path (cr, iterator, INT_MAX);
984+ if (n > 0 )
962985 {
963- float r, g, b;
964- if (!PyArg_ParseTuple (rgbFace, " fff" , &r, &g, &b))
965- return NULL ;
966986 CGContextSaveGState (cr);
967987 CGContextSetRGBFillColor (cr, r, g, b, 1.0 );
968988 CGContextDrawPath (cr, kCGPathFillStroke );
969989 CGContextRestoreGState (cr);
970990 }
971- else CGContextStrokePath (cr);
991+ }
992+ else
993+ {
994+ const int nmax = 100 ;
995+ while (true )
996+ {
997+ n = _draw_path (cr, iterator, nmax);
998+ if (n != 0 ) CGContextStrokePath (cr);
999+ if (n >= 0 ) break ;
1000+ }
1001+ }
1002+ free_path_iterator (iterator);
9721003
973- hatchpath = PyObject_CallMethod ((PyObject*)self, " get_hatch_path" , " " );
974- if (!hatchpath)
1004+ PyObject* hatchpath;
1005+ hatchpath = PyObject_CallMethod ((PyObject*)self, " get_hatch_path" , " " );
1006+ if (!hatchpath)
1007+ {
1008+ return NULL ;
1009+ }
1010+ else if (hatchpath==Py_None)
1011+ {
1012+ Py_DECREF (hatchpath);
1013+ }
1014+ else
1015+ {
1016+ CGPatternRef pattern;
1017+ CGColorSpaceRef baseSpace;
1018+ CGColorSpaceRef patternSpace;
1019+ static const CGPatternCallbacks callbacks = {0 ,
1020+ &_draw_hatch,
1021+ &_release_hatch};
1022+ baseSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB );
1023+ if (!baseSpace)
9751024 {
1025+ Py_DECREF (hatchpath);
1026+ PyErr_SetString (PyExc_RuntimeError,
1027+ " draw_path: CGColorSpaceCreateWithName failed" );
9761028 return NULL ;
9771029 }
978- else if (hatchpath==Py_None)
1030+ patternSpace = CGColorSpaceCreatePattern (baseSpace);
1031+ CGColorSpaceRelease (baseSpace);
1032+ if (!patternSpace)
9791033 {
9801034 Py_DECREF (hatchpath);
1035+ PyErr_SetString (PyExc_RuntimeError,
1036+ " draw_path: CGColorSpaceCreatePattern failed" );
1037+ return NULL ;
9811038 }
982- else
1039+ CGContextSetFillColorSpace (cr, patternSpace);
1040+ CGColorSpaceRelease (patternSpace);
1041+
1042+ pattern = CGPatternCreate ((void *)hatchpath,
1043+ CGRectMake (0 , 0 , HATCH_SIZE, HATCH_SIZE),
1044+ CGAffineTransformIdentity,
1045+ HATCH_SIZE, HATCH_SIZE,
1046+ kCGPatternTilingNoDistortion ,
1047+ false ,
1048+ &callbacks);
1049+ CGContextSetFillPattern (cr, pattern, self->color );
1050+ CGPatternRelease (pattern);
1051+ iterator = get_path_iterator (path,
1052+ transform,
1053+ 1 ,
1054+ 0 ,
1055+ rect,
1056+ SNAP_AUTO,
1057+ linewidth,
1058+ 0 );
1059+ if (!iterator)
9831060 {
984- CGPatternRef pattern;
985- CGColorSpaceRef baseSpace;
986- CGColorSpaceRef patternSpace;
987- static const CGPatternCallbacks callbacks = {0 ,
988- &_draw_hatch,
989- &_release_hatch};
990- baseSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB );
991- if (!baseSpace)
992- {
993- Py_DECREF (hatchpath);
994- PyErr_SetString (PyExc_RuntimeError,
995- " draw_path: CGColorSpaceCreateWithName failed" );
996- return NULL ;
997- }
998- patternSpace = CGColorSpaceCreatePattern (baseSpace);
999- CGColorSpaceRelease (baseSpace);
1000- if (!patternSpace)
1001- {
1002- Py_DECREF (hatchpath);
1003- PyErr_SetString (PyExc_RuntimeError,
1004- " draw_path: CGColorSpaceCreatePattern failed" );
1005- return NULL ;
1006- }
1007- CGContextSetFillColorSpace (cr, patternSpace);
1008- CGColorSpaceRelease (patternSpace);
1009-
1010- pattern = CGPatternCreate ((void *)hatchpath,
1011- CGRectMake (0 , 0 , HATCH_SIZE, HATCH_SIZE),
1012- CGAffineTransformIdentity,
1013- HATCH_SIZE, HATCH_SIZE,
1014- kCGPatternTilingNoDistortion ,
1015- false ,
1016- &callbacks);
1017- CGContextSetFillPattern (cr, pattern, self->color );
1018- CGPatternRelease (pattern);
1019- iterator = get_path_iterator (path,
1020- transform,
1021- 1 ,
1022- 0 ,
1023- rect,
1024- SNAP_AUTO,
1025- linewidth,
1026- 0 );
1027- if (!iterator)
1028- {
1029- Py_DECREF (hatchpath);
1030- PyErr_SetString (PyExc_RuntimeError,
1031- " draw_path: failed to obtain path iterator for hatching" );
1032- return NULL ;
1033- }
1034- n = _draw_path (cr, iterator);
1035- free_path_iterator (iterator);
1036- CGContextFillPath (cr);
1061+ Py_DECREF (hatchpath);
1062+ PyErr_SetString (PyExc_RuntimeError,
1063+ " draw_path: failed to obtain path iterator for hatching" );
1064+ return NULL ;
10371065 }
1066+ n = _draw_path (cr, iterator, INT_MAX);
1067+ free_path_iterator (iterator);
1068+ if (n > 0 ) CGContextFillPath (cr);
10381069 }
10391070
10401071 Py_INCREF (Py_None);
0 commit comments