]> granicus.if.org Git - imagemagick/blob - wand/drawing-wand.c
(no commit message)
[imagemagick] / wand / drawing-wand.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %               DDDD   RRRR    AAA   W   W  IIIII  N   N    GGGG              %
7 %               D   D  R   R  A   A  W   W    I    NN  N   G                  %
8 %               D   D  RRRR   AAAAA  W   W    I    N N N   G  GG              %
9 %               D   D  R R    A   A  W W W    I    N  NN   G   G              %
10 %               DDDD   R  R   A   A   W W   IIIII  N   N    GGG               %
11 %                                                                             %
12 %                         W   W   AAA   N   N  DDDD                           %
13 %                         W   W  A   A  NN  N  D   D                          %
14 %                         W W W  AAAAA  N N N  D   D                          %
15 %                         WW WW  A   A  N  NN  D   D                          %
16 %                         W   W  A   A  N   N  DDDD                           %
17 %                                                                             %
18 %                                                                             %
19 %                   MagickWand Image Vector Drawing Methods                   %
20 %                                                                             %
21 %                              Software Design                                %
22 %                              Bob Friesenhahn                                %
23 %                                March 2002                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %
43 %
44 */
45 \f
46 /*
47   Include declarations.
48 */
49 #include "wand/studio.h"
50 #include "wand/MagickWand.h"
51 #include "wand/magick-wand-private.h"
52 #include "wand/wand.h"
53 #include "magick/string-private.h"
54 \f
55 /*
56   Define declarations.
57 */
58 #define DRAW_BINARY_IMPLEMENTATION 0
59
60 #define CurrentContext  (wand->graphic_context[wand->index])
61 #define DrawingWandId  "DrawingWand"
62 #define ThrowDrawException(severity,tag,reason) (void) ThrowMagickException( \
63   wand->exception,GetMagickModule(),severity,tag,"`%s'",reason);
64 \f
65 /*
66   Typedef declarations.
67 */
68 typedef enum
69 {
70   PathDefaultOperation,
71   PathCloseOperation,                        /* Z|z (none) */
72   PathCurveToOperation,                      /* C|c (x1 y1 x2 y2 x y)+ */
73   PathCurveToQuadraticBezierOperation,       /* Q|q (x1 y1 x y)+ */
74   PathCurveToQuadraticBezierSmoothOperation, /* T|t (x y)+ */
75   PathCurveToSmoothOperation,                /* S|s (x2 y2 x y)+ */
76   PathEllipticArcOperation,                  /* A|a (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ */
77   PathLineToHorizontalOperation,             /* H|h x+ */
78   PathLineToOperation,                       /* L|l (x y)+ */
79   PathLineToVerticalOperation,               /* V|v y+ */
80   PathMoveToOperation                        /* M|m (x y)+ */
81 } PathOperation;
82
83 typedef enum
84 {
85   DefaultPathMode,
86   AbsolutePathMode,
87   RelativePathMode
88 } PathMode;
89
90 struct _DrawingWand
91 {
92   unsigned long
93     id;
94
95   char
96     name[MaxTextExtent];
97
98   /* Support structures */
99   Image
100     *image;
101
102   ExceptionInfo
103     *exception;
104
105   /* MVG output string and housekeeping */
106   char
107     *mvg;               /* MVG data */
108
109   size_t
110     mvg_alloc,          /* total allocated memory */
111     mvg_length;         /* total MVG length */
112
113   unsigned long
114     mvg_width;          /* current line width */
115
116   /* Pattern support */
117   char
118     *pattern_id;
119
120   RectangleInfo
121     pattern_bounds;
122
123   size_t
124     pattern_offset;
125
126   /* Graphic wand */
127   unsigned long
128     index;              /* array index */
129
130   DrawInfo
131     **graphic_context;
132
133   MagickBooleanType
134     filter_off;         /* true if not filtering attributes */
135
136   /* Pretty-printing depth */
137   unsigned long
138     indent_depth;       /* number of left-hand pad characters */
139
140   /* Path operation support */
141   PathOperation
142     path_operation;
143
144   PathMode
145     path_mode;
146
147   MagickBooleanType
148     destroy,
149     debug;
150
151   unsigned long
152     signature;
153 };
154
155 /* Vector table for invoking subordinate renderers */
156 struct _DrawVTable
157 {
158   DrawingWand *(*DestroyDrawingWand) (DrawingWand *);
159   void (*DrawAnnotation)(DrawingWand *,const double,const double,
160     const unsigned char *);
161   void (*DrawArc)(DrawingWand *,const double,const double,const double,
162     const double,const double,const double);
163   void (*DrawBezier)(DrawingWand *,const unsigned long,const PointInfo *);
164   void (*DrawCircle)(DrawingWand *,const double,const double,const double,
165     const double);
166   void (*DrawColor)(DrawingWand *,const double,const double,const PaintMethod);
167   void (*DrawComment)(DrawingWand *,const char *);
168   void (*DrawEllipse)(DrawingWand *,const double,const double,const double,
169     const double,const double,const double);
170   MagickBooleanType (*DrawComposite)(DrawingWand *,const CompositeOperator,
171     const double,const double,const double,const double,const Image *);
172   void (*DrawLine)(DrawingWand *,const double,const double,const double,
173     const double);
174   void (*DrawMatte)(DrawingWand *,const double,const double,const PaintMethod);
175   void (*DrawPathClose)(DrawingWand *);
176   void (*DrawPathCurveToAbsolute)(DrawingWand *,const double,const double,
177     const double,const double,const double,const double);
178   void (*DrawPathCurveToRelative)(DrawingWand *,const double,const double,
179     const double,const double,const double,const double);
180   void (*DrawPathCurveToQuadraticBezierAbsolute)(DrawingWand *,const double,
181     const double,const double,const double);
182   void (*DrawPathCurveToQuadraticBezierRelative)(DrawingWand *,const double,
183     const double,const double,const double);
184   void (*DrawPathCurveToQuadraticBezierSmoothAbsolute)(DrawingWand *,
185     const double,const double);
186   void (*DrawPathCurveToQuadraticBezierSmoothRelative)(DrawingWand *,
187     const double,const double);
188   void (*DrawPathCurveToSmoothAbsolute)(DrawingWand *,const double,
189     const double,const double,const double);
190   void (*DrawPathCurveToSmoothRelative)(DrawingWand *,const double,
191     const double,const double,const double);
192   void (*DrawPathEllipticArcAbsolute)(DrawingWand *,const double,const double,
193     const double,const MagickBooleanType,const MagickBooleanType,const double,
194     const double);
195   void (*DrawPathEllipticArcRelative)(DrawingWand *,const double,const double,
196     const double,const MagickBooleanType,const MagickBooleanType,const double,
197     const double);
198   void (*DrawPathFinish)(DrawingWand *);
199   void (*DrawPathLineToAbsolute)(DrawingWand *,const double,const double);
200   void (*DrawPathLineToRelative)(DrawingWand *,const double,const double);
201   void (*DrawPathLineToHorizontalAbsolute)(DrawingWand *,const double);
202   void (*DrawPathLineToHorizontalRelative)(DrawingWand *,const double);
203   void (*DrawPathLineToVerticalAbsolute)(DrawingWand *,const double);
204   void (*DrawPathLineToVerticalRelative)(DrawingWand *,const double);
205   void (*DrawPathMoveToAbsolute)(DrawingWand *,const double,const double);
206   void (*DrawPathMoveToRelative)(DrawingWand *,const double,const double);
207   void (*DrawPathStart)(DrawingWand *);
208   void (*DrawPoint)(DrawingWand *,const double,const double);
209   void (*DrawPolygon)(DrawingWand *,const unsigned long,const PointInfo *);
210   void (*DrawPolyline)(DrawingWand *,const unsigned long,const PointInfo *);
211   void (*DrawPopClipPath)(DrawingWand *);
212   void (*DrawPopDefs)(DrawingWand *);
213   MagickBooleanType (*DrawPopPattern)(DrawingWand *);
214   void (*DrawPushClipPath)(DrawingWand *,const char *);
215   void (*DrawPushDefs)(DrawingWand *);
216   MagickBooleanType (*DrawPushPattern)(DrawingWand *,const char *,const double,
217     const double,const double,const double);
218   void (*DrawRectangle)(DrawingWand *,const double,const double,const double,
219     const double);
220   void (*DrawRoundRectangle)(DrawingWand *,double,double,double,double,
221     double,double);
222   void (*DrawAffine)(DrawingWand *,const AffineMatrix *);
223   MagickBooleanType (*DrawSetClipPath)(DrawingWand *,const char *);
224   void (*DrawSetBorderColor)(DrawingWand *,const PixelWand *);
225   void (*DrawSetClipRule)(DrawingWand *,const FillRule);
226   void (*DrawSetClipUnits)(DrawingWand *,const ClipPathUnits);
227   void (*DrawSetFillColor)(DrawingWand *,const PixelWand *);
228   void (*DrawSetFillRule)(DrawingWand *,const FillRule);
229   MagickBooleanType (*DrawSetFillPatternURL)(DrawingWand *,const char *);
230   MagickBooleanType (*DrawSetFont)(DrawingWand *,const char *);
231   MagickBooleanType (*DrawSetFontFamily)(DrawingWand *,const char *);
232   void (*DrawSetTextKerning)(DrawingWand *,const double);
233   void (*DrawSetTextInterwordSpacing)(DrawingWand *,const double);
234   double (*DrawGetTextKerning)(DrawingWand *);
235   double (*DrawGetTextInterwordSpacing)(DrawingWand *);
236   void (*DrawSetFontSize)(DrawingWand *,const double);
237   void (*DrawSetFontStretch)(DrawingWand *,const StretchType);
238   void (*DrawSetFontStyle)(DrawingWand *,const StyleType);
239   void (*DrawSetFontWeight)(DrawingWand *,const unsigned long);
240   void (*DrawSetGravity)(DrawingWand *,const GravityType);
241   void (*DrawRotate)(DrawingWand *,const double);
242   void (*DrawScale)(DrawingWand *,const double,const double);
243   void (*DrawSkewX)(DrawingWand *,const double);
244   void (*DrawSkewY)(DrawingWand *,const double);
245   void (*DrawSetStrokeAntialias)(DrawingWand *,const MagickBooleanType);
246   void (*DrawSetStrokeColor)(DrawingWand *,const PixelWand *);
247   MagickBooleanType (*DrawSetStrokeDashArray)(DrawingWand *,const double *);
248   void (*DrawSetStrokeDashOffset)(DrawingWand *,const double);
249   void (*DrawSetStrokeLineCap)(DrawingWand *,const LineCap);
250   void (*DrawSetStrokeLineJoin)(DrawingWand *,const LineJoin);
251   void (*DrawSetStrokeMiterLimit)(DrawingWand *,const unsigned long);
252   MagickBooleanType (*DrawSetStrokePatternURL)(DrawingWand *,const char *);
253   void (*DrawSetStrokeWidth)(DrawingWand *,const double);
254   void (*DrawSetTextAntialias)(DrawingWand *,const MagickBooleanType);
255   void (*DrawSetTextDecoration)(DrawingWand *,const DecorationType);
256   void (*DrawSetTextUnderColor)(DrawingWand *,const PixelWand *);
257   void (*DrawTranslate)(DrawingWand *,const double,const double);
258   void (*DrawSetViewbox)(DrawingWand *,unsigned long,unsigned long,
259     unsigned long,unsigned long);
260   void (*PeekDrawingWand)(DrawingWand *);
261   MagickBooleanType (*PopDrawingWand)(DrawingWand *);
262   MagickBooleanType (*PushDrawingWand)(DrawingWand *);
263 };
264 \f
265 /*
266   Forward declarations.
267 */
268 static int
269   MvgPrintf(DrawingWand *,const char *,...) wand_attribute((format
270     (printf,2,3))),
271   MvgAutoWrapPrintf(DrawingWand *,const char *,...) wand_attribute((format
272     (printf,2,3)));
273
274 static void
275   MvgAppendColor(DrawingWand *,const PixelPacket *);
276 \f
277 /*
278   "Printf" for MVG commands
279 */
280 static int MvgPrintf(DrawingWand *wand,const char *format,...)
281 {
282   size_t
283     alloc_size;
284
285   if (wand->debug != MagickFalse)
286     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",format);
287   assert(wand != (DrawingWand *) NULL);
288   assert(wand->signature == WandSignature);
289   alloc_size=20UL*MaxTextExtent;
290   if (wand->mvg == (char *) NULL)
291     {
292       wand->mvg=(char *) AcquireQuantumMemory(alloc_size,sizeof(*wand->mvg));
293       if (wand->mvg == (char *) NULL)
294         {
295           ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
296             wand->name);
297           return(-1);
298         }
299       wand->mvg_alloc=alloc_size;
300       wand->mvg_length=0;
301     }
302   if (wand->mvg_alloc < (wand->mvg_length+10*MaxTextExtent))
303     {
304       size_t
305         realloc_size;
306
307       realloc_size=wand->mvg_alloc+alloc_size;
308       wand->mvg=(char *) ResizeQuantumMemory(wand->mvg,realloc_size,
309         sizeof(*wand->mvg));
310       if (wand->mvg == (char *) NULL)
311         {
312           ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
313             wand->name);
314           return -1;
315         }
316       wand->mvg_alloc=realloc_size;
317     }
318   {
319     int
320       formatted_length;
321
322     va_list
323       argp;
324
325     while (wand->mvg_width < wand->indent_depth)
326     {
327       wand->mvg[wand->mvg_length]=' ';
328       wand->mvg_length++;
329       wand->mvg_width++;
330     }
331     wand->mvg[wand->mvg_length]='\0';
332     va_start(argp, format);
333 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
334     formatted_length=vsnprintf(wand->mvg+wand->mvg_length,
335       wand->mvg_alloc-wand->mvg_length-1,format,argp);
336 #else
337     formatted_length=vsprintf(wand->mvg+wand->mvg_length,
338       format,argp);
339 #endif
340     va_end(argp);
341     if (formatted_length < 0)
342       ThrowDrawException(DrawError,"UnableToPrint",format)
343     else
344       {
345         wand->mvg_length+=formatted_length;
346         wand->mvg_width+=formatted_length;
347       }
348     wand->mvg[wand->mvg_length]='\0';
349     if ((wand->mvg_length > 1) &&
350         (wand->mvg[wand->mvg_length-1] == '\n'))
351       wand->mvg_width=0;
352     assert((wand->mvg_length+1) < wand->mvg_alloc);
353     return formatted_length;
354   }
355 }
356
357 static int MvgAutoWrapPrintf(DrawingWand *wand,const char *format,...)
358 {
359   char
360     buffer[MaxTextExtent];
361
362   int
363     formatted_length;
364
365   va_list
366     argp;
367
368   va_start(argp,format);
369 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
370   formatted_length=vsnprintf(buffer,sizeof(buffer)-1,format,argp);
371 #else
372   formatted_length=vsprintf(buffer,format,argp);
373 #endif
374   va_end(argp);
375   *(buffer+sizeof(buffer)-1)='\0';
376   if (formatted_length < 0)
377     ThrowDrawException(DrawError,"UnableToPrint",format)
378   else
379     {
380       if (((wand->mvg_width + formatted_length) > 78) &&
381           (buffer[formatted_length-1] != '\n'))
382         (void) MvgPrintf(wand, "\n");
383       (void) MvgPrintf(wand,"%s",buffer);
384     }
385   return(formatted_length);
386 }
387
388 static void MvgAppendColor(DrawingWand *wand,const PixelPacket *color)
389 {
390   if ((color->red == 0) && (color->green == 0) && (color->blue == 0) &&
391      (color->opacity == (Quantum) TransparentOpacity))
392     (void) MvgPrintf(wand,"none");
393   else
394     {
395       char
396         tuple[MaxTextExtent];
397
398       MagickPixelPacket
399         pixel;
400
401       GetMagickPixelPacket(wand->image,&pixel);
402       pixel.colorspace=RGBColorspace;
403       pixel.matte=color->opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
404       pixel.red=(MagickRealType) color->red;
405       pixel.green=(MagickRealType) color->green;
406       pixel.blue=(MagickRealType) color->blue;
407       pixel.opacity=(MagickRealType) color->opacity;
408       GetColorTuple(&pixel,MagickTrue,tuple);
409       (void) MvgPrintf(wand,"%s",tuple);
410     }
411 }
412
413 static void MvgAppendPointsCommand(DrawingWand *wand,const char *command,
414   const unsigned long number_coordinates,const PointInfo *coordinates)
415 {
416   const PointInfo
417     *coordinate;
418
419   unsigned long
420     i;
421
422   (void) MvgPrintf(wand,"%s",command);
423   for (i=number_coordinates, coordinate=coordinates; i != 0; i--)
424   {
425     (void) MvgAutoWrapPrintf(wand," %g,%g",coordinate->x,coordinate->y);
426     coordinate++;
427   }
428   (void) MvgPrintf(wand, "\n");
429 }
430
431 static void AdjustAffine(DrawingWand *wand,const AffineMatrix *affine)
432 {
433   assert(wand != (DrawingWand *) NULL);
434   assert(wand->signature == WandSignature);
435   if (wand->debug != MagickFalse)
436     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
437   if ((affine->sx != 1.0) || (affine->rx != 0.0) || (affine->ry != 0.0) ||
438       (affine->sy != 1.0) || (affine->tx != 0.0) || (affine->ty != 0.0))
439     {
440       AffineMatrix
441         current;
442
443       current=CurrentContext->affine;
444       CurrentContext->affine.sx=current.sx*affine->sx+current.ry*affine->rx;
445       CurrentContext->affine.rx=current.rx*affine->sx+current.sy*affine->rx;
446       CurrentContext->affine.ry=current.sx*affine->ry+current.ry*affine->sy;
447       CurrentContext->affine.sy=current.rx*affine->ry+current.sy*affine->sy;
448       CurrentContext->affine.tx=current.sx*affine->tx+current.ry*affine->ty+
449         current.tx;
450       CurrentContext->affine.ty=current.rx*affine->tx+current.sy*affine->ty+
451         current.ty;
452     }
453 }
454 \f
455 /*
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 %                                                                             %
458 %                                                                             %
459 %                                                                             %
460 %   C l e a r D r a w i n g W a n d                                           %
461 %                                                                             %
462 %                                                                             %
463 %                                                                             %
464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465 %
466 %  ClearDrawingWand() clear resources associated with the drawing wand.
467 %
468 %  The format of the ClearDrawingWand method is:
469 %
470 %      DrawingWand *ClearDrawingWand(DrawingWand *wand)
471 %
472 %  A description of each parameter follows:
473 %
474 %    o wand: the drawing wand. to destroy
475 %
476 */
477 WandExport void ClearDrawingWand(DrawingWand *wand)
478 {
479   assert(wand != (DrawingWand *) NULL);
480   assert(wand->signature == WandSignature);
481   if (wand->debug != MagickFalse)
482     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
483   for ( ; wand->index > 0; wand->index--)
484     CurrentContext=DestroyDrawInfo(CurrentContext);
485   CurrentContext=DestroyDrawInfo(CurrentContext);
486   wand->graphic_context=(DrawInfo **) RelinquishMagickMemory(
487     wand->graphic_context);
488   if (wand->pattern_id != (char *) NULL)
489     wand->pattern_id=DestroyString(wand->pattern_id);
490   wand->mvg=DestroyString(wand->mvg);
491   if ((wand->destroy != MagickFalse) && (wand->image != (Image *) NULL))
492     wand->image=DestroyImage(wand->image);
493   else
494     wand->image=(Image *) NULL;
495   wand->mvg=(char *) NULL;
496   wand->mvg_alloc=0;
497   wand->mvg_length=0;
498   wand->mvg_width=0;
499   wand->pattern_id=(char *) NULL;
500   wand->pattern_offset=0;
501   wand->pattern_bounds.x=0;
502   wand->pattern_bounds.y=0;
503   wand->pattern_bounds.width=0;
504   wand->pattern_bounds.height=0;
505   wand->index=0;
506   wand->graphic_context=(DrawInfo **) AcquireMagickMemory(
507     sizeof(*wand->graphic_context));
508   if (wand->graphic_context == (DrawInfo **) NULL)
509     {
510       ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
511         wand->name);
512       return;
513     }
514   CurrentContext=CloneDrawInfo((ImageInfo *) NULL,(DrawInfo *) NULL);
515   wand->filter_off=MagickTrue;
516   wand->indent_depth=0;
517   wand->path_operation=PathDefaultOperation;
518   wand->path_mode=DefaultPathMode;
519   wand->image=AcquireImage((const ImageInfo *) NULL);
520   ClearMagickException(wand->exception);
521   wand->destroy=MagickTrue;
522   wand->debug=IsEventLogging();
523 }
524 \f
525 /*
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527 %                                                                             %
528 %                                                                             %
529 %                                                                             %
530 %   C l o n e D r a w i n g W a n d                                           %
531 %                                                                             %
532 %                                                                             %
533 %                                                                             %
534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535 %
536 %  CloneDrawingWand() makes an exact copy of the specified wand.
537 %
538 %  The format of the CloneDrawingWand method is:
539 %
540 %      DrawingWand *CloneDrawingWand(const DrawingWand *wand)
541 %
542 %  A description of each parameter follows:
543 %
544 %    o wand: the magick wand.
545 %
546 */
547 WandExport DrawingWand *CloneDrawingWand(const DrawingWand *wand)
548 {
549   DrawingWand
550     *clone_wand;
551
552   register long
553     i;
554
555   assert(wand != (DrawingWand *) NULL);
556   assert(wand->signature == WandSignature);
557   if (wand->debug != MagickFalse)
558     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
559   clone_wand=(DrawingWand *) AcquireAlignedMemory(1,sizeof(*clone_wand));
560   if (clone_wand == (DrawingWand *) NULL)
561     ThrowWandFatalException(ResourceLimitFatalError,
562       "MemoryAllocationFailed",GetExceptionMessage(errno));
563   (void) ResetMagickMemory(clone_wand,0,sizeof(*clone_wand));
564   clone_wand->id=AcquireWandId();
565   (void) FormatMagickString(clone_wand->name,MaxTextExtent,"DrawingWand-%lu",
566     clone_wand->id);
567   clone_wand->exception=AcquireExceptionInfo();
568   InheritException(clone_wand->exception,wand->exception);
569   clone_wand->mvg=AcquireString(wand->mvg);
570   clone_wand->mvg_length=strlen(clone_wand->mvg);
571   clone_wand->mvg_alloc=wand->mvg_length+1;
572   clone_wand->mvg_width=wand->mvg_width;
573   clone_wand->pattern_id=AcquireString(wand->pattern_id);
574   clone_wand->pattern_offset=wand->pattern_offset;
575   clone_wand->pattern_bounds=wand->pattern_bounds;
576   clone_wand->index=wand->index;
577   clone_wand->graphic_context=(DrawInfo **) AcquireQuantumMemory((size_t)
578     wand->index+1UL,sizeof(*wand->graphic_context));
579   if (clone_wand->graphic_context == (DrawInfo **) NULL)
580     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
581       GetExceptionMessage(errno));
582   for (i=0; i <= (long) wand->index; i++)
583     clone_wand->graphic_context[i]=
584       CloneDrawInfo((ImageInfo *) NULL,wand->graphic_context[i]);
585   clone_wand->filter_off=wand->filter_off;
586   clone_wand->indent_depth=wand->indent_depth;
587   clone_wand->path_operation=wand->path_operation;
588   clone_wand->path_mode=wand->path_mode;
589   clone_wand->image=wand->image;
590   if (wand->image != (Image *) NULL)
591     clone_wand->image=CloneImage(wand->image,0,0,MagickTrue,
592       clone_wand->exception);
593   clone_wand->destroy=MagickTrue;
594   clone_wand->debug=IsEventLogging();
595   if (clone_wand->debug != MagickFalse)
596     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_wand->name);
597   clone_wand->signature=WandSignature;
598   return(clone_wand);
599 }
600 \f
601 /*
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 %                                                                             %
604 %                                                                             %
605 %                                                                             %
606 %   D e s t r o y D r a w i n g W a n d                                       %
607 %                                                                             %
608 %                                                                             %
609 %                                                                             %
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %
612 %  DestroyDrawingWand() frees all resources associated with the drawing wand.
613 %  Once the drawing wand has been freed, it should not be used and further
614 %  unless it re-allocated.
615 %
616 %  The format of the DestroyDrawingWand method is:
617 %
618 %      DrawingWand *DestroyDrawingWand(DrawingWand *wand)
619 %
620 %  A description of each parameter follows:
621 %
622 %    o wand: the drawing wand. to destroy
623 %
624 */
625 WandExport DrawingWand *DestroyDrawingWand(DrawingWand *wand)
626 {
627   assert(wand != (DrawingWand *) NULL);
628   assert(wand->signature == WandSignature);
629   if (wand->debug != MagickFalse)
630     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
631   for ( ; wand->index > 0; wand->index--)
632     CurrentContext=DestroyDrawInfo(CurrentContext);
633   CurrentContext=DestroyDrawInfo(CurrentContext);
634   wand->graphic_context=(DrawInfo **) RelinquishMagickMemory(
635     wand->graphic_context);
636   if (wand->pattern_id != (char *) NULL)
637     wand->pattern_id=DestroyString(wand->pattern_id);
638   wand->mvg=DestroyString(wand->mvg);
639   if ((wand->destroy != MagickFalse) && (wand->image != (Image *) NULL))
640     wand->image=DestroyImage(wand->image);
641   wand->image=(Image *) NULL;
642   wand->exception=DestroyExceptionInfo(wand->exception);
643   wand->signature=(~WandSignature);
644   RelinquishWandId(wand->id);
645   wand=(DrawingWand *) RelinquishMagickMemory(wand);
646   return(wand);
647 }
648 \f
649 /*
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 %                                                                             %
652 %                                                                             %
653 %                                                                             %
654 %   D r a w A f f i n e                                                       %
655 %                                                                             %
656 %                                                                             %
657 %                                                                             %
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 %
660 %  DrawAffine() adjusts the current affine transformation matrix with
661 %  the specified affine transformation matrix. Note that the current affine
662 %  transform is adjusted rather than replaced.
663 %
664 %  The format of the DrawAffine method is:
665 %
666 %      void DrawAffine(DrawingWand *wand,const AffineMatrix *affine)
667 %
668 %  A description of each parameter follows:
669 %
670 %    o wand: Drawing wand
671 %
672 %    o affine: Affine matrix parameters
673 %
674 */
675 WandExport void DrawAffine(DrawingWand *wand,const AffineMatrix *affine)
676 {
677   assert(wand != (DrawingWand *) NULL);
678   assert(wand->signature == WandSignature);
679   if (wand->debug != MagickFalse)
680     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
681   assert(affine != (const AffineMatrix *) NULL);
682   AdjustAffine(wand,affine);
683   (void) MvgPrintf(wand,"affine %g,%g,%g,%g,%g,%g\n",affine->sx,affine->rx,
684     affine->ry,affine->sy,affine->tx,affine->ty);
685 }
686 \f
687 /*
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %                                                                             %
690 %                                                                             %
691 %                                                                             %
692 +   D r a w A l l o c a t e W a n d                                           %
693 %                                                                             %
694 %                                                                             %
695 %                                                                             %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 %
698 %  DrawAllocateWand() allocates an initial drawing wand which is an opaque
699 %  handle required by the remaining drawing methods.
700 %
701 %  The format of the DrawAllocateWand method is:
702 %
703 %      DrawingWand DrawAllocateWand(const DrawInfo *draw_info,Image *image)
704 %
705 %  A description of each parameter follows:
706 %
707 %    o draw_info: Initial drawing defaults. Set to NULL to use defaults.
708 %
709 %    o image: the image to draw on.
710 %
711 */
712 WandExport DrawingWand *DrawAllocateWand(const DrawInfo *draw_info,Image *image)
713 {
714   DrawingWand
715     *wand;
716
717   wand=NewDrawingWand();
718   if (draw_info != (const DrawInfo *) NULL)
719     {
720       CurrentContext=DestroyDrawInfo(CurrentContext);
721       CurrentContext=CloneDrawInfo((ImageInfo *) NULL,draw_info);
722     }
723   if (image != (Image *) NULL)
724     {
725       wand->image=DestroyImage(wand->image);
726       wand->destroy=MagickFalse;
727     }
728   wand->image=image;
729   return(wand);
730 }
731 \f
732 /*
733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
734 %                                                                             %
735 %                                                                             %
736 %                                                                             %
737 %   D r a w A n n o t a t i o n                                               %
738 %                                                                             %
739 %                                                                             %
740 %                                                                             %
741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
742 %
743 %  DrawAnnotation() draws text on the image.
744 %
745 %  The format of the DrawAnnotation method is:
746 %
747 %      void DrawAnnotation(DrawingWand *wand,const double x,
748 %        const double y,const unsigned char *text)
749 %
750 %  A description of each parameter follows:
751 %
752 %    o wand: the drawing wand.
753 %
754 %    o x: x ordinate to left of text
755 %
756 %    o y: y ordinate to text baseline
757 %
758 %    o text: text to draw
759 %
760 */
761 WandExport void DrawAnnotation(DrawingWand *wand,const double x,const double y,
762   const unsigned char *text)
763 {
764   char
765     *escaped_text;
766
767   assert(wand != (DrawingWand *) NULL);
768   assert(wand->signature == WandSignature);
769   if (wand->debug != MagickFalse)
770     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
771   assert(text != (const unsigned char *) NULL);
772   escaped_text=EscapeString((const char *) text,'\'');
773   (void) MvgPrintf(wand,"text %g,%g '%s'\n",x,y,escaped_text);
774   escaped_text=DestroyString(escaped_text);
775 }
776 \f
777 /*
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779 %                                                                             %
780 %                                                                             %
781 %                                                                             %
782 %   D r a w A r c                                                             %
783 %                                                                             %
784 %                                                                             %
785 %                                                                             %
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787 %
788 %  DrawArc() draws an arc falling within a specified bounding rectangle on the
789 %  image.
790 %
791 %  The format of the DrawArc method is:
792 %
793 %      void DrawArc(DrawingWand *wand,const double sx,const double sy,
794 %        const double ex,const double ey,const double sd,const double ed)
795 %
796 %  A description of each parameter follows:
797 %
798 %    o wand: the drawing wand.
799 %
800 %    o sx: starting x ordinate of bounding rectangle
801 %
802 %    o sy: starting y ordinate of bounding rectangle
803 %
804 %    o ex: ending x ordinate of bounding rectangle
805 %
806 %    o ey: ending y ordinate of bounding rectangle
807 %
808 %    o sd: starting degrees of rotation
809 %
810 %    o ed: ending degrees of rotation
811 %
812 */
813 WandExport void DrawArc(DrawingWand *wand,const double sx,const double sy,
814   const double ex,const double ey,const double sd,const double ed)
815 {
816   assert(wand != (DrawingWand *) NULL);
817   assert(wand->signature == WandSignature);
818   if (wand->debug != MagickFalse)
819     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
820   (void) MvgPrintf(wand,"arc %g,%g %g,%g %g,%g\n",sx,sy,ex,ey,sd,ed);
821 }
822 \f
823 /*
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %   D r a w B e z i e r                                                       %
829 %                                                                             %
830 %                                                                             %
831 %                                                                             %
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %
834 %  DrawBezier() draws a bezier curve through a set of points on the image.
835 %
836 %  The format of the DrawBezier method is:
837 %
838 %      void DrawBezier(DrawingWand *wand,
839 %        const unsigned long number_coordinates,const PointInfo *coordinates)
840 %
841 %  A description of each parameter follows:
842 %
843 %    o wand: the drawing wand.
844 %
845 %    o number_coordinates: number of coordinates
846 %
847 %    o coordinates: coordinates
848 %
849 */
850 WandExport void DrawBezier(DrawingWand *wand,
851   const unsigned long number_coordinates,const PointInfo *coordinates)
852 {
853   assert(wand != (DrawingWand *) NULL);
854   assert(wand->signature == WandSignature);
855   if (wand->debug != MagickFalse)
856     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
857   assert(coordinates != (const PointInfo *) NULL);
858   MvgAppendPointsCommand(wand,"bezier",number_coordinates,coordinates);
859 }
860 \f
861 /*
862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 %                                                                             %
864 %                                                                             %
865 %                                                                             %
866 %   D r a w C i r c l e                                                       %
867 %                                                                             %
868 %                                                                             %
869 %                                                                             %
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 %
872 %  DrawCircle() draws a circle on the image.
873 %
874 %  The format of the DrawCircle method is:
875 %
876 %      void DrawCircle(DrawingWand *wand,const double ox,
877 %        const double oy,const double px, const double py)
878 %
879 %  A description of each parameter follows:
880 %
881 %    o wand: the drawing wand.
882 %
883 %    o ox: origin x ordinate
884 %
885 %    o oy: origin y ordinate
886 %
887 %    o px: perimeter x ordinate
888 %
889 %    o py: perimeter y ordinate
890 %
891 */
892 WandExport void DrawCircle(DrawingWand *wand,const double ox,const double oy,
893   const double px,const double py)
894 {
895   assert(wand != (DrawingWand *) NULL);
896   assert(wand->signature == WandSignature);
897   if (wand->debug != MagickFalse)
898     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
899   (void) MvgPrintf(wand,"circle %g,%g %g,%g\n",ox,oy,px,py);
900 }
901 \f
902 /*
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904 %                                                                             %
905 %                                                                             %
906 %                                                                             %
907 %   D r a w C l e a r E x c e p t i o n                                       %
908 %                                                                             %
909 %                                                                             %
910 %                                                                             %
911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912 %
913 %  DrawClearException() clear any exceptions associated with the wand.
914 %
915 %  The format of the DrawClearException method is:
916 %
917 %      MagickBooleanType DrawClearException(DrawWand *wand)
918 %
919 %  A description of each parameter follows:
920 %
921 %    o wand: the drawing wand.
922 %
923 */
924 WandExport MagickBooleanType DrawClearException(DrawingWand *wand)
925 {
926   assert(wand != (DrawingWand *) NULL);
927   assert(wand->signature == WandSignature);
928   if (wand->debug != MagickFalse)
929     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
930   ClearMagickException(wand->exception);
931   return(MagickTrue);
932 }
933 \f
934 /*
935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936 %                                                                             %
937 %                                                                             %
938 %                                                                             %
939 %   D r a w C o m p o s i t e                                                 %
940 %                                                                             %
941 %                                                                             %
942 %                                                                             %
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 %
945 %  DrawComposite() composites an image onto the current image, using the
946 %  specified composition operator, specified position, and at the specified
947 %  size.
948 %
949 %  The format of the DrawComposite method is:
950 %
951 %      MagickBooleanType DrawComposite(DrawingWand *wand,
952 %        const CompositeOperator compose,const double x,
953 %        const double y,const double width,const double height,
954 %        MagickWand *magick_wand)
955 %
956 %  A description of each parameter follows:
957 %
958 %    o wand: the drawing wand.
959 %
960 %    o compose: composition operator
961 %
962 %    o x: x ordinate of top left corner
963 %
964 %    o y: y ordinate of top left corner
965 %
966 %    o width: Width to resize image to prior to compositing.  Specify zero to
967 %      use existing width.
968 %
969 %    o height: Height to resize image to prior to compositing.  Specify zero
970 %      to use existing height.
971 %
972 %    o magick_wand: Image to composite is obtained from this wand.
973 %
974 */
975 WandExport MagickBooleanType DrawComposite(DrawingWand *wand,
976   const CompositeOperator compose,const double x,const double y,
977   const double width,const double height,MagickWand *magick_wand)
978
979 {
980   char
981     *base64,
982     *media_type;
983
984   const char
985     *mode;
986
987   ImageInfo
988     *image_info;
989
990   Image
991     *clone_image,
992     *image;
993
994   register char
995     *p;
996
997   register long
998     i;
999
1000   size_t
1001     blob_length,
1002     encoded_length;
1003
1004   unsigned char
1005     *blob;
1006
1007   assert(wand != (DrawingWand *) NULL);
1008   assert(wand->signature == WandSignature);
1009   if (wand->debug != MagickFalse)
1010     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1011   assert(magick_wand != (MagickWand *) NULL);
1012   image=GetImageFromMagickWand(magick_wand);
1013   if (image == (Image *) NULL)
1014     return(MagickFalse);
1015   clone_image=CloneImage(image,0,0,MagickTrue,wand->exception);
1016   if (clone_image == (Image *) NULL)
1017     return(MagickFalse);
1018   image_info=AcquireImageInfo();
1019   (void) CopyMagickString(image_info->magick,"MIFF",MaxTextExtent);
1020   blob_length=2048;
1021   blob=(unsigned char *) ImageToBlob(image_info,clone_image,&blob_length,
1022     wand->exception);
1023   image_info=DestroyImageInfo(image_info);
1024   clone_image=DestroyImageList(clone_image);
1025   if (blob == (void *) NULL)
1026     return(MagickFalse);
1027   encoded_length=0;
1028   base64=Base64Encode(blob,blob_length,&encoded_length);
1029   blob=(unsigned char *) RelinquishMagickMemory(blob);
1030   if (base64 == (char *) NULL)
1031     {
1032       char
1033         buffer[MaxTextExtent];
1034
1035       (void) FormatMagickString(buffer,MaxTextExtent,"%ld bytes",
1036         (4L*blob_length/3L+4L));
1037       ThrowDrawException(ResourceLimitWarning,"MemoryAllocationFailed",
1038         wand->name);
1039       return(MagickFalse);
1040     }
1041   mode=MagickOptionToMnemonic(MagickComposeOptions,(long) compose);
1042   media_type=MagickToMime(image->magick);
1043   (void) MvgPrintf(wand,"image %s %g,%g %g,%g 'data:%s;base64,\n",mode,x,y,
1044     width,height,media_type);
1045   p=base64;
1046   for (i=(long) encoded_length; i > 0; i-=76)
1047   {
1048     (void) MvgPrintf(wand,"%.76s",p);
1049     p+=76;
1050     if (i > 76)
1051       (void) MvgPrintf(wand,"\n");
1052   }
1053   (void) MvgPrintf(wand,"'\n");
1054   media_type=DestroyString(media_type);
1055   base64=DestroyString(base64);
1056   return(MagickTrue);
1057 }
1058 \f
1059 /*
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 %                                                                             %
1062 %                                                                             %
1063 %                                                                             %
1064 %   D r a w C o l o r                                                         %
1065 %                                                                             %
1066 %                                                                             %
1067 %                                                                             %
1068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 %
1070 %  DrawColor() draws color on image using the current fill color, starting at
1071 %  specified position, and using specified paint method. The available paint
1072 %  methods are:
1073 %
1074 %    PointMethod: Recolors the target pixel
1075 %    ReplaceMethod: Recolor any pixel that matches the target pixel.
1076 %    FloodfillMethod: Recolors target pixels and matching neighbors.
1077 %    ResetMethod: Recolor all pixels.
1078 %
1079 %  The format of the DrawColor method is:
1080 %
1081 %      void DrawColor(DrawingWand *wand,const double x,const double y,
1082 %        const PaintMethod paint_method)
1083 %
1084 %  A description of each parameter follows:
1085 %
1086 %    o wand: the drawing wand.
1087 %
1088 %    o x: x ordinate.
1089 %
1090 %    o y: y ordinate.
1091 %
1092 %    o paint_method: paint method.
1093 %
1094 */
1095 WandExport void DrawColor(DrawingWand *wand,const double x,const double y,
1096   const PaintMethod paint_method)
1097 {
1098   assert(wand != (DrawingWand *) NULL);
1099   assert(wand->signature == WandSignature);
1100   if (wand->debug != MagickFalse)
1101     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1102   (void) MvgPrintf(wand,"color %g,%g '%s'\n",x,y,MagickOptionToMnemonic(
1103     MagickMethodOptions,(long) paint_method));
1104 }
1105 \f
1106 /*
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108 %                                                                             %
1109 %                                                                             %
1110 %                                                                             %
1111 %   D r a w C o m m e n t                                                     %
1112 %                                                                             %
1113 %                                                                             %
1114 %                                                                             %
1115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1116 %
1117 %  DrawComment() adds a comment to a vector output stream.
1118 %
1119 %  The format of the DrawComment method is:
1120 %
1121 %      void DrawComment(DrawingWand *wand,const char *comment)
1122 %
1123 %  A description of each parameter follows:
1124 %
1125 %    o wand: the drawing wand.
1126 %
1127 %    o comment: comment text
1128 %
1129 */
1130 WandExport void DrawComment(DrawingWand *wand,const char *comment)
1131 {
1132   (void) MvgPrintf(wand,"#%s\n",comment);
1133 }
1134 \f
1135 /*
1136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1137 %                                                                             %
1138 %                                                                             %
1139 %                                                                             %
1140 %   D r a w E l l i p s e                                                     %
1141 %                                                                             %
1142 %                                                                             %
1143 %                                                                             %
1144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1145 %
1146 %  DrawEllipse() draws an ellipse on the image.
1147 %
1148 %  The format of the DrawEllipse method is:
1149 %
1150 %       void DrawEllipse(DrawingWand *wand,const double ox,const double oy,
1151 %         const double rx,const double ry,const double start,const double end)
1152 %
1153 %  A description of each parameter follows:
1154 %
1155 %    o wand: the drawing wand.
1156 %
1157 %    o ox: origin x ordinate
1158 %
1159 %    o oy: origin y ordinate
1160 %
1161 %    o rx: radius in x
1162 %
1163 %    o ry: radius in y
1164 %
1165 %    o start: starting rotation in degrees
1166 %
1167 %    o end: ending rotation in degrees
1168 %
1169 */
1170 WandExport void DrawEllipse(DrawingWand *wand,const double ox,const double oy,
1171   const double rx,const double ry,const double start,const double end)
1172 {
1173   assert(wand != (DrawingWand *) NULL);
1174   assert(wand->signature == WandSignature);
1175   if (wand->debug != MagickFalse)
1176     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1177   (void) MvgPrintf(wand,"ellipse %g,%g %g,%g %g,%g\n",ox,oy,rx,ry,start,end);
1178 }
1179 \f
1180 /*
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1182 %                                                                             %
1183 %                                                                             %
1184 %                                                                             %
1185 %   D r a w G e t B o r d e r C o l o r                                       %
1186 %                                                                             %
1187 %                                                                             %
1188 %                                                                             %
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 %
1191 %  DrawGetBorderColor() returns the border color used for drawing bordered
1192 %  objects.
1193 %
1194 %  The format of the DrawGetBorderColor method is:
1195 %
1196 %      void DrawGetBorderColor(const DrawingWand *wand,
1197 %        PixelWand *border_color)
1198 %
1199 %  A description of each parameter follows:
1200 %
1201 %    o wand: the drawing wand.
1202 %
1203 %    o border_color: Return the border color.
1204 %
1205 */
1206 WandExport void DrawGetBorderColor(const DrawingWand *wand,
1207   PixelWand *border_color)
1208 {
1209   assert(wand != (const DrawingWand *) NULL);
1210   assert(wand->signature == WandSignature);
1211   assert(border_color != (PixelWand *) NULL);
1212   if (wand->debug != MagickFalse)
1213     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1214   PixelSetQuantumColor(border_color,&CurrentContext->border_color);
1215 }
1216 \f
1217 /*
1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1219 %                                                                             %
1220 %                                                                             %
1221 %                                                                             %
1222 %   D r a w G e t C l i p P a t h                                             %
1223 %                                                                             %
1224 %                                                                             %
1225 %                                                                             %
1226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1227 %
1228 %  DrawGetClipPath() obtains the current clipping path ID. The value returned
1229 %  must be deallocated by the user when it is no longer needed.
1230 %
1231 %  The format of the DrawGetClipPath method is:
1232 %
1233 %      char *DrawGetClipPath(const DrawingWand *wand)
1234 %
1235 %  A description of each parameter follows:
1236 %
1237 %    o wand: the drawing wand.
1238 %
1239 */
1240 WandExport char *DrawGetClipPath(const DrawingWand *wand)
1241 {
1242   assert(wand != (const DrawingWand *) NULL);
1243   assert(wand->signature == WandSignature);
1244   if (wand->debug != MagickFalse)
1245     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1246   if (CurrentContext->clip_mask != (char *) NULL)
1247     return((char *) AcquireString(CurrentContext->clip_mask));
1248   return((char *) NULL);
1249 }
1250 \f
1251 /*
1252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253 %                                                                             %
1254 %                                                                             %
1255 %                                                                             %
1256 %   D r a w G e t C l i p R u l e                                             %
1257 %                                                                             %
1258 %                                                                             %
1259 %                                                                             %
1260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1261 %
1262 %  DrawGetClipRule() returns the current polygon fill rule to be used by the
1263 %  clipping path.
1264 %
1265 %  The format of the DrawGetClipRule method is:
1266 %
1267 %     FillRule DrawGetClipRule(const DrawingWand *wand)
1268 %
1269 %  A description of each parameter follows:
1270 %
1271 %    o wand: the drawing wand.
1272 %
1273 */
1274 WandExport FillRule DrawGetClipRule(const DrawingWand *wand)
1275 {
1276   assert(wand != (const DrawingWand *) NULL);
1277   assert(wand->signature == WandSignature);
1278   if (wand->debug != MagickFalse)
1279     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1280   return(CurrentContext->fill_rule);
1281 }
1282 \f
1283 /*
1284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1285 %                                                                             %
1286 %                                                                             %
1287 %                                                                             %
1288 %   D r a w G e t C l i p U n i t s                                           %
1289 %                                                                             %
1290 %                                                                             %
1291 %                                                                             %
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %
1294 %  DrawGetClipUnits() returns the interpretation of clip path units.
1295 %
1296 %  The format of the DrawGetClipUnits method is:
1297 %
1298 %      ClipPathUnits DrawGetClipUnits(const DrawingWand *wand)
1299 %
1300 %  A description of each parameter follows:
1301 %
1302 %    o wand: the drawing wand.
1303 %
1304 */
1305 WandExport ClipPathUnits DrawGetClipUnits(const DrawingWand *wand)
1306 {
1307   assert(wand != (const DrawingWand *) NULL);
1308   assert(wand->signature == WandSignature);
1309   if (wand->debug != MagickFalse)
1310     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1311   return(CurrentContext->clip_units);
1312 }
1313 \f
1314 /*
1315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316 %                                                                             %
1317 %                                                                             %
1318 %                                                                             %
1319 %   D r a w G e t E x c e p t i o n                                           %
1320 %                                                                             %
1321 %                                                                             %
1322 %                                                                             %
1323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1324 %
1325 %  DrawGetException() returns the severity, reason, and description of any
1326 %  error that occurs when using other methods in this API.
1327 %
1328 %  The format of the DrawGetException method is:
1329 %
1330 %      char *DrawGetException(const DrawWand *wand,
1331 %        ExceptionType *severity)
1332 %
1333 %  A description of each parameter follows:
1334 %
1335 %    o wand: the drawing wand.
1336 %
1337 %    o severity: the severity of the error is returned here.
1338 %
1339 */
1340 WandExport char *DrawGetException(const DrawingWand *wand,
1341   ExceptionType *severity)
1342 {
1343   char
1344     *description;
1345
1346   assert(wand != (const DrawingWand *) NULL);
1347   assert(wand->signature == WandSignature);
1348   if (wand->debug != MagickFalse)
1349     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1350   assert(severity != (ExceptionType *) NULL);
1351   *severity=wand->exception->severity;
1352   description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
1353     sizeof(*description));
1354   if (description == (char *) NULL)
1355     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1356       wand->name);
1357   *description='\0';
1358   if (wand->exception->reason != (char *) NULL)
1359     (void) CopyMagickString(description,GetLocaleExceptionMessage(
1360       wand->exception->severity,wand->exception->reason),
1361       MaxTextExtent);
1362   if (wand->exception->description != (char *) NULL)
1363     {
1364       (void) ConcatenateMagickString(description," (",MaxTextExtent);
1365       (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
1366         wand->exception->severity,wand->exception->description),
1367         MaxTextExtent);
1368       (void) ConcatenateMagickString(description,")",MaxTextExtent);
1369     }
1370   return(description);
1371 }
1372 \f
1373 /*
1374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1375 %                                                                             %
1376 %                                                                             %
1377 %                                                                             %
1378 %   P i x e l G e t E x c e p t i o n T y p e                                 %
1379 %                                                                             %
1380 %                                                                             %
1381 %                                                                             %
1382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1383 %
1384 %  DrawGetExceptionType() the exception type associated with the wand.  If
1385 %  no exception has occurred, UndefinedExceptionType is returned.
1386 %
1387 %  The format of the DrawGetExceptionType method is:
1388 %
1389 %      ExceptionType DrawGetExceptionType(const DrawWand *wand)
1390 %
1391 %  A description of each parameter follows:
1392 %
1393 %    o wand: the magick wand.
1394 %
1395 */
1396 WandExport ExceptionType DrawGetExceptionType(const DrawingWand *wand)
1397 {
1398   assert(wand != (const DrawingWand *) NULL);
1399   assert(wand->signature == WandSignature);
1400   if (wand->debug != MagickFalse)
1401     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1402   return(wand->exception->severity);
1403 }
1404 \f
1405 /*
1406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407 %                                                                             %
1408 %                                                                             %
1409 %                                                                             %
1410 %   D r a w G e t F i l l C o l o r                                           %
1411 %                                                                             %
1412 %                                                                             %
1413 %                                                                             %
1414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1415 %
1416 %  DrawGetFillColor() returns the fill color used for drawing filled objects.
1417 %
1418 %  The format of the DrawGetFillColor method is:
1419 %
1420 %      void DrawGetFillColor(const DrawingWand *wand,
1421 %        PixelWand *fill_color)
1422 %
1423 %  A description of each parameter follows:
1424 %
1425 %    o wand: the drawing wand.
1426 %
1427 %    o fill_color: Return the fill color.
1428 %
1429 */
1430 WandExport void DrawGetFillColor(const DrawingWand *wand,PixelWand *fill_color)
1431 {
1432   assert(wand != (const DrawingWand *) NULL);
1433   assert(wand->signature == WandSignature);
1434   assert(fill_color != (PixelWand *) NULL);
1435   if (wand->debug != MagickFalse)
1436     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1437   PixelSetQuantumColor(fill_color,&CurrentContext->fill);
1438 }
1439 \f
1440 /*
1441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1442 %                                                                             %
1443 %                                                                             %
1444 %                                                                             %
1445 %   D r a w G e t F i l l O p a c i t y                                       %
1446 %                                                                             %
1447 %                                                                             %
1448 %                                                                             %
1449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1450 %
1451 %  DrawGetFillOpacity() returns the opacity used when drawing using the fill
1452 %  color or fill texture.  Fully opaque is 1.0.
1453 %
1454 %  The format of the DrawGetFillOpacity method is:
1455 %
1456 %      double DrawGetFillOpacity(const DrawingWand *wand)
1457 %
1458 %  A description of each parameter follows:
1459 %
1460 %    o wand: the drawing wand.
1461 %
1462 */
1463 WandExport double DrawGetFillOpacity(const DrawingWand *wand)
1464 {
1465   double
1466     alpha;
1467
1468   assert(wand != (const DrawingWand *) NULL);
1469   assert(wand->signature == WandSignature);
1470   if (wand->debug != MagickFalse)
1471     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1472   alpha=(double) QuantumScale*(QuantumRange-CurrentContext->fill.opacity);
1473   return(alpha);
1474 }
1475 \f
1476 /*
1477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478 %                                                                             %
1479 %                                                                             %
1480 %                                                                             %
1481 %   D r a w G e t F i l l R u l e                                             %
1482 %                                                                             %
1483 %                                                                             %
1484 %                                                                             %
1485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486 %
1487 %  DrawGetFillRule() returns the fill rule used while drawing polygons.
1488 %
1489 %  The format of the DrawGetFillRule method is:
1490 %
1491 %      FillRule DrawGetFillRule(const DrawingWand *wand)
1492 %
1493 %  A description of each parameter follows:
1494 %
1495 %    o wand: the drawing wand.
1496 %
1497 */
1498 WandExport FillRule DrawGetFillRule(const DrawingWand *wand)
1499 {
1500   assert(wand != (const DrawingWand *) NULL);
1501   assert(wand->signature == WandSignature);
1502   if (wand->debug != MagickFalse)
1503     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1504   return(CurrentContext->fill_rule);
1505 }
1506 \f
1507 /*
1508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1509 %                                                                             %
1510 %                                                                             %
1511 %                                                                             %
1512 %   D r a w G e t F o n t                                                     %
1513 %                                                                             %
1514 %                                                                             %
1515 %                                                                             %
1516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1517 %
1518 %  DrawGetFont() returns a null-terminaged string specifying the font used
1519 %  when annotating with text. The value returned must be freed by the user
1520 %  when no longer needed.
1521 %
1522 %  The format of the DrawGetFont method is:
1523 %
1524 %      char *DrawGetFont(const DrawingWand *wand)
1525 %
1526 %  A description of each parameter follows:
1527 %
1528 %    o wand: the drawing wand.
1529 %
1530 */
1531 WandExport char *DrawGetFont(const DrawingWand *wand)
1532 {
1533   assert(wand != (const DrawingWand *) NULL);
1534   assert(wand->signature == WandSignature);
1535   if (wand->debug != MagickFalse)
1536     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1537   if (CurrentContext->font != (char *) NULL)
1538     return(AcquireString(CurrentContext->font));
1539   return((char *) NULL);
1540 }
1541 \f
1542 /*
1543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1544 %                                                                             %
1545 %                                                                             %
1546 %                                                                             %
1547 %   D r a w G e t F o n t F a m i l y                                         %
1548 %                                                                             %
1549 %                                                                             %
1550 %                                                                             %
1551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1552 %
1553 %  DrawGetFontFamily() returns the font family to use when annotating with text.
1554 %  The value returned must be freed by the user when it is no longer needed.
1555 %
1556 %  The format of the DrawGetFontFamily method is:
1557 %
1558 %      char *DrawGetFontFamily(const DrawingWand *wand)
1559 %
1560 %  A description of each parameter follows:
1561 %
1562 %    o wand: the drawing wand.
1563 %
1564 */
1565 WandExport char *DrawGetFontFamily(const DrawingWand *wand)
1566 {
1567   assert(wand != (const DrawingWand *) NULL);
1568   assert(wand->signature == WandSignature);
1569   if (wand->debug != MagickFalse)
1570     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1571   if (CurrentContext->family != NULL)
1572     return(AcquireString(CurrentContext->family));
1573   return((char *) NULL);
1574 }
1575 \f
1576 /*
1577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578 %                                                                             %
1579 %                                                                             %
1580 %                                                                             %
1581 %   D r a w G e t F o n t S i z e                                             %
1582 %                                                                             %
1583 %                                                                             %
1584 %                                                                             %
1585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1586 %
1587 %  DrawGetFontSize() returns the font pointsize used when annotating with text.
1588 %
1589 %  The format of the DrawGetFontSize method is:
1590 %
1591 %      double DrawGetFontSize(const DrawingWand *wand)
1592 %
1593 %  A description of each parameter follows:
1594 %
1595 %    o wand: the drawing wand.
1596 %
1597 */
1598 WandExport double DrawGetFontSize(const DrawingWand *wand)
1599 {
1600   assert(wand != (const DrawingWand *) NULL);
1601   assert(wand->signature == WandSignature);
1602   if (wand->debug != MagickFalse)
1603     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1604   return(CurrentContext->pointsize);
1605 }
1606 \f
1607 /*
1608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1609 %                                                                             %
1610 %                                                                             %
1611 %                                                                             %
1612 %   D r a w G e t F o n t S t r e t c h                                       %
1613 %                                                                             %
1614 %                                                                             %
1615 %                                                                             %
1616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1617 %
1618 %  DrawGetFontStretch() returns the font stretch used when annotating with text.
1619 %
1620 %  The format of the DrawGetFontStretch method is:
1621 %
1622 %      StretchType DrawGetFontStretch(const DrawingWand *wand)
1623 %
1624 %  A description of each parameter follows:
1625 %
1626 %    o wand: the drawing wand.
1627 %
1628 */
1629 WandExport StretchType DrawGetFontStretch(const DrawingWand *wand)
1630 {
1631   assert(wand != (const DrawingWand *) NULL);
1632   assert(wand->signature == WandSignature);
1633   if (wand->debug != MagickFalse)
1634     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1635   return(CurrentContext->stretch);
1636 }
1637 \f
1638 /*
1639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1640 %                                                                             %
1641 %                                                                             %
1642 %                                                                             %
1643 %   D r a w G e t F o n t S t y l e                                           %
1644 %                                                                             %
1645 %                                                                             %
1646 %                                                                             %
1647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1648 %
1649 %  DrawGetFontStyle() returns the font style used when annotating with text.
1650 %
1651 %  The format of the DrawGetFontStyle method is:
1652 %
1653 %      StyleType DrawGetFontStyle(const DrawingWand *wand)
1654 %
1655 %  A description of each parameter follows:
1656 %
1657 %    o wand: the drawing wand.
1658 %
1659 */
1660 WandExport StyleType DrawGetFontStyle(const DrawingWand *wand)
1661 {
1662   assert(wand != (const DrawingWand *) NULL);
1663   assert(wand->signature == WandSignature);
1664   if (wand->debug != MagickFalse)
1665     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1666   return(CurrentContext->style);
1667 }
1668 \f
1669 /*
1670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1671 %                                                                             %
1672 %                                                                             %
1673 %                                                                             %
1674 %   D r a w G e t F o n t W e i g h t                                         %
1675 %                                                                             %
1676 %                                                                             %
1677 %                                                                             %
1678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679 %
1680 %  DrawGetFontWeight() returns the font weight used when annotating with text.
1681 %
1682 %  The format of the DrawGetFontWeight method is:
1683 %
1684 %      unsigned long DrawGetFontWeight(const DrawingWand *wand)
1685 %
1686 %  A description of each parameter follows:
1687 %
1688 %    o wand: the drawing wand.
1689 %
1690 */
1691 WandExport unsigned long DrawGetFontWeight(const DrawingWand *wand)
1692 {
1693   assert(wand != (const DrawingWand *) NULL);
1694   assert(wand->signature == WandSignature);
1695   if (wand->debug != MagickFalse)
1696     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1697   return(CurrentContext->weight);
1698 }
1699 \f
1700 /*
1701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1702 %                                                                             %
1703 %                                                                             %
1704 %                                                                             %
1705 %   D r a w G e t G r a v i t y                                               %
1706 %                                                                             %
1707 %                                                                             %
1708 %                                                                             %
1709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1710 %
1711 %  DrawGetGravity() returns the text placement gravity used when annotating
1712 %  with text.
1713 %
1714 %  The format of the DrawGetGravity method is:
1715 %
1716 %      GravityType DrawGetGravity(const DrawingWand *wand)
1717 %
1718 %  A description of each parameter follows:
1719 %
1720 %    o wand: the drawing wand.
1721 %
1722 */
1723 WandExport GravityType DrawGetGravity(const DrawingWand *wand)
1724 {
1725   assert(wand != (const DrawingWand *) NULL);
1726   assert(wand->signature == WandSignature);
1727   if (wand->debug != MagickFalse)
1728     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1729   return(CurrentContext->gravity);
1730 }
1731 \f
1732 /*
1733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1734 %                                                                             %
1735 %                                                                             %
1736 %                                                                             %
1737 %   D r a w G e t O p a c i t y                                               %
1738 %                                                                             %
1739 %                                                                             %
1740 %                                                                             %
1741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1742 %
1743 %  DrawGetOpacity() returns the opacity used when drawing with the fill
1744 %  or stroke color or texture.  Fully opaque is 1.0.
1745 %
1746 %  The format of the DrawGetOpacity method is:
1747 %
1748 %      double DrawGetOpacity(const DrawingWand *wand)
1749 %
1750 %  A description of each parameter follows:
1751 %
1752 %    o wand: the drawing wand.
1753 %
1754 */
1755 WandExport double DrawGetOpacity(const DrawingWand *wand)
1756 {
1757   double
1758     alpha;
1759
1760   assert(wand != (const DrawingWand *) NULL);
1761   assert(wand->signature == WandSignature);
1762   if (wand->debug != MagickFalse)
1763     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1764   alpha=(double) QuantumScale*(QuantumRange-CurrentContext->opacity);
1765   return(alpha);
1766 }
1767 \f
1768 /*
1769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1770 %                                                                             %
1771 %                                                                             %
1772 %                                                                             %
1773 %   D r a w G e t S t r o k e A n t i a l i a s                               %
1774 %                                                                             %
1775 %                                                                             %
1776 %                                                                             %
1777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1778 %
1779 %  DrawGetStrokeAntialias() returns the current stroke antialias setting.
1780 %  Stroked outlines are antialiased by default.  When antialiasing is disabled
1781 %  stroked pixels are thresholded to determine if the stroke color or
1782 %  underlying canvas color should be used.
1783 %
1784 %  The format of the DrawGetStrokeAntialias method is:
1785 %
1786 %      MagickBooleanType DrawGetStrokeAntialias(const DrawingWand *wand)
1787 %
1788 %  A description of each parameter follows:
1789 %
1790 %    o wand: the drawing wand.
1791 %
1792 */
1793 WandExport MagickBooleanType DrawGetStrokeAntialias(const DrawingWand *wand)
1794 {
1795   assert(wand != (const DrawingWand *) NULL);
1796   assert(wand->signature == WandSignature);
1797   if (wand->debug != MagickFalse)
1798     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1799   return(CurrentContext->stroke_antialias);
1800 }
1801 \f
1802 /*
1803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1804 %                                                                             %
1805 %                                                                             %
1806 %                                                                             %
1807 %   D r a w G e t S t r o k e C o l o r                                       %
1808 %                                                                             %
1809 %                                                                             %
1810 %                                                                             %
1811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1812 %
1813 %  DrawGetStrokeColor() returns the color used for stroking object outlines.
1814 %
1815 %  The format of the DrawGetStrokeColor method is:
1816 %
1817 %      void DrawGetStrokeColor(const DrawingWand *wand,
1818 $        PixelWand *stroke_color)
1819 %
1820 %  A description of each parameter follows:
1821 %
1822 %    o wand: the drawing wand.
1823 %
1824 %    o stroke_color: Return the stroke color.
1825 %
1826 */
1827 WandExport void DrawGetStrokeColor(const DrawingWand *wand,
1828   PixelWand *stroke_color)
1829 {
1830   assert(wand != (const DrawingWand *) NULL);
1831   assert(wand->signature == WandSignature);
1832   assert(stroke_color != (PixelWand *) NULL);
1833   if (wand->debug != MagickFalse)
1834     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1835   PixelSetQuantumColor(stroke_color,&CurrentContext->stroke);
1836 }
1837 \f
1838 /*
1839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1840 %                                                                             %
1841 %                                                                             %
1842 %                                                                             %
1843 %   D r a w G e t S t r o k e D a s h A r r a y                               %
1844 %                                                                             %
1845 %                                                                             %
1846 %                                                                             %
1847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1848 %
1849 %  DrawGetStrokeDashArray() returns an array representing the pattern of
1850 %  dashes and gaps used to stroke paths (see DrawSetStrokeDashArray). The
1851 %  array must be freed once it is no longer required by the user.
1852 %
1853 %  The format of the DrawGetStrokeDashArray method is:
1854 %
1855 %      double *DrawGetStrokeDashArray(const DrawingWand *wand,
1856 %        unsigned long *number_elements)
1857 %
1858 %  A description of each parameter follows:
1859 %
1860 %    o wand: the drawing wand.
1861 %
1862 %    o number_elements: address to place number of elements in dash array
1863 %
1864 */
1865 WandExport double *DrawGetStrokeDashArray(const DrawingWand *wand,
1866   unsigned long *number_elements)
1867 {
1868   double
1869     *dash_array;
1870
1871   register const double
1872     *p;
1873
1874   register double
1875     *q;
1876
1877   register long
1878     i;
1879
1880   unsigned long
1881     n;
1882
1883   assert(wand != (const DrawingWand *) NULL);
1884   assert(wand->signature == WandSignature);
1885   if (wand->debug != MagickFalse)
1886     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1887   assert(number_elements != (unsigned long *) NULL);
1888   n=0;
1889   p=CurrentContext->dash_pattern;
1890   if (p != (const double *) NULL)
1891     while (*p++ != 0.0)
1892       n++;
1893   *number_elements=n;
1894   dash_array=(double *) NULL;
1895   if (n != 0)
1896     {
1897       dash_array=(double *) AcquireQuantumMemory((size_t) n,
1898         sizeof(*dash_array));
1899       p=CurrentContext->dash_pattern;
1900       q=dash_array;
1901       for (i=0; i < (long) n; i++)
1902         *q++=(*p++);
1903     }
1904   return(dash_array);
1905 }
1906 \f
1907 /*
1908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1909 %                                                                             %
1910 %                                                                             %
1911 %                                                                             %
1912 %   D r a w G e t S t r o k e D a s h O f f s e t                             %
1913 %                                                                             %
1914 %                                                                             %
1915 %                                                                             %
1916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1917 %
1918 %  DrawGetStrokeDashOffset() returns the offset into the dash pattern to
1919 %  start the dash.
1920 %
1921 %  The format of the DrawGetStrokeDashOffset method is:
1922 %
1923 %      double DrawGetStrokeDashOffset(const DrawingWand *wand)
1924 %
1925 %  A description of each parameter follows:
1926 %
1927 %    o wand: the drawing wand.
1928 %
1929 */
1930 WandExport double DrawGetStrokeDashOffset(const DrawingWand *wand)
1931 {
1932   assert(wand != (const DrawingWand *) NULL);
1933   assert(wand->signature == WandSignature);
1934   if (wand->debug != MagickFalse)
1935     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1936   return(CurrentContext->dash_offset);
1937 }
1938 \f
1939 /*
1940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941 %                                                                             %
1942 %                                                                             %
1943 %                                                                             %
1944 %   D r a w G e t S t r o k e L i n e C a p                                   %
1945 %                                                                             %
1946 %                                                                             %
1947 %                                                                             %
1948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1949 %
1950 %  DrawGetStrokeLineCap() returns the shape to be used at the end of
1951 %  open subpaths when they are stroked. Values of LineCap are
1952 %  UndefinedCap, ButtCap, RoundCap, and SquareCap.
1953 %
1954 %  The format of the DrawGetStrokeLineCap method is:
1955 %
1956 %      LineCap DrawGetStrokeLineCap(const DrawingWand *wand)
1957 %
1958 %  A description of each parameter follows:
1959 %
1960 %    o wand: the drawing wand.
1961 %
1962 */
1963 WandExport LineCap DrawGetStrokeLineCap(const DrawingWand *wand)
1964 {
1965   assert(wand != (const DrawingWand *) NULL);
1966   assert(wand->signature == WandSignature);
1967   if (wand->debug != MagickFalse)
1968     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
1969   return(CurrentContext->linecap);
1970 }
1971 \f
1972 /*
1973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1974 %                                                                             %
1975 %                                                                             %
1976 %                                                                             %
1977 %   D r a w G e t S t r o k e L i n e J o i n                                 %
1978 %                                                                             %
1979 %                                                                             %
1980 %                                                                             %
1981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1982 %
1983 %  DrawGetStrokeLineJoin() returns the shape to be used at the
1984 %  corners of paths (or other vector shapes) when they are
1985 %  stroked. Values of LineJoin are UndefinedJoin, MiterJoin, RoundJoin,
1986 %  and BevelJoin.
1987 %
1988 %  The format of the DrawGetStrokeLineJoin method is:
1989 %
1990 %      LineJoin DrawGetStrokeLineJoin(const DrawingWand *wand)
1991 %
1992 %  A description of each parameter follows:
1993 %
1994 %    o wand: the drawing wand.
1995 %
1996 */
1997 WandExport LineJoin DrawGetStrokeLineJoin(const DrawingWand *wand)
1998 {
1999   assert(wand != (const DrawingWand *) NULL);
2000   assert(wand->signature == WandSignature);
2001   if (wand->debug != MagickFalse)
2002     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2003   return(CurrentContext->linejoin);
2004 }
2005 \f
2006 /*
2007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2008 %                                                                             %
2009 %                                                                             %
2010 %                                                                             %
2011 %   D r a w G e t S t r o k e M i t e r L i m i t                             %
2012 %                                                                             %
2013 %                                                                             %
2014 %                                                                             %
2015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016 %
2017 %  DrawGetStrokeMiterLimit() returns the miter limit. When two line
2018 %  segments meet at a sharp angle and miter joins have been specified for
2019 %  'lineJoin', it is possible for the miter to extend far beyond the
2020 %  thickness of the line stroking the path. The miterLimit' imposes a
2021 %  limit on the ratio of the miter length to the 'lineWidth'.
2022 %
2023 %  The format of the DrawGetStrokeMiterLimit method is:
2024 %
2025 %      unsigned long DrawGetStrokeMiterLimit(const DrawingWand *wand)
2026 %
2027 %  A description of each parameter follows:
2028 %
2029 %    o wand: the drawing wand.
2030 %
2031 */
2032 WandExport unsigned long DrawGetStrokeMiterLimit(const DrawingWand *wand)
2033 {
2034   assert(wand != (const DrawingWand *) NULL);
2035   assert(wand->signature == WandSignature);
2036   if (wand->debug != MagickFalse)
2037     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2038   return CurrentContext->miterlimit;
2039 }
2040 \f
2041 /*
2042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2043 %                                                                             %
2044 %                                                                             %
2045 %                                                                             %
2046 %   D r a w G e t S t r o k e O p a c i t y                                   %
2047 %                                                                             %
2048 %                                                                             %
2049 %                                                                             %
2050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2051 %
2052 %  DrawGetStrokeOpacity() returns the opacity of stroked object outlines.
2053 %
2054 %  The format of the DrawGetStrokeOpacity method is:
2055 %
2056 %      double DrawGetStrokeOpacity(const DrawingWand *wand)
2057 %
2058 %  A description of each parameter follows:
2059 %
2060 %    o wand: the drawing wand.
2061 %
2062 */
2063 WandExport double DrawGetStrokeOpacity(const DrawingWand *wand)
2064 {
2065   double
2066     alpha;
2067
2068   assert(wand != (const DrawingWand *) NULL);
2069   assert(wand->signature == WandSignature);
2070   if (wand->debug != MagickFalse)
2071     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2072   alpha=(double) QuantumScale*(QuantumRange-CurrentContext->stroke.opacity);
2073   return(alpha);
2074 }
2075 \f
2076 /*
2077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2078 %                                                                             %
2079 %                                                                             %
2080 %                                                                             %
2081 %   D r a w G e t S t r o k e W i d t h                                       %
2082 %                                                                             %
2083 %                                                                             %
2084 %                                                                             %
2085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086 %
2087 %  DrawGetStrokeWidth() returns the width of the stroke used to draw object
2088 %  outlines.
2089 %
2090 %  The format of the DrawGetStrokeWidth method is:
2091 %
2092 %      double DrawGetStrokeWidth(const DrawingWand *wand)
2093 %
2094 %  A description of each parameter follows:
2095 %
2096 %    o wand: the drawing wand.
2097 %
2098 */
2099 WandExport double DrawGetStrokeWidth(const DrawingWand *wand)
2100 {
2101   assert(wand != (const DrawingWand *) NULL);
2102   assert(wand->signature == WandSignature);
2103   if (wand->debug != MagickFalse)
2104     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2105   return(CurrentContext->stroke_width);
2106 }
2107 \f
2108 /*
2109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2110 %                                                                             %
2111 %                                                                             %
2112 %                                                                             %
2113 %   D r a w G e t T e x t A l i g n m e n t                                   %
2114 %                                                                             %
2115 %                                                                             %
2116 %                                                                             %
2117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2118 %
2119 %  DrawGetTextAlignment() returns the alignment applied when annotating with
2120 %  text.
2121 %
2122 %  The format of the DrawGetTextAlignment method is:
2123 %
2124 %      AlignType DrawGetTextAlignment(DrawingWand *wand)
2125 %
2126 %  A description of each parameter follows:
2127 %
2128 %    o wand: the drawing wand.
2129 %
2130 */
2131 WandExport AlignType DrawGetTextAlignment(const DrawingWand *wand)
2132 {
2133   assert(wand != (const DrawingWand *) NULL);
2134   assert(wand->signature == WandSignature);
2135   if (wand->debug != MagickFalse)
2136     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2137   return(CurrentContext->align);
2138 }
2139 \f
2140 /*
2141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2142 %                                                                             %
2143 %                                                                             %
2144 %                                                                             %
2145 %   D r a w G e t T e x t A n t i a l i a s                                   %
2146 %                                                                             %
2147 %                                                                             %
2148 %                                                                             %
2149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2150 %
2151 %  DrawGetTextAntialias() returns the current text antialias setting, which
2152 %  determines whether text is antialiased.  Text is antialiased by default.
2153 %
2154 %  The format of the DrawGetTextAntialias method is:
2155 %
2156 %      MagickBooleanType DrawGetTextAntialias(const DrawingWand *wand)
2157 %
2158 %  A description of each parameter follows:
2159 %
2160 %    o wand: the drawing wand.
2161 %
2162 */
2163 WandExport MagickBooleanType DrawGetTextAntialias(const DrawingWand *wand)
2164 {
2165   assert(wand != (const DrawingWand *) NULL);
2166   assert(wand->signature == WandSignature);
2167   if (wand->debug != MagickFalse)
2168     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2169   return(CurrentContext->text_antialias);
2170 }
2171 \f
2172 /*
2173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2174 %                                                                             %
2175 %                                                                             %
2176 %                                                                             %
2177 %   D r a w G e t T e x t D e c o r a t i o n                                 %
2178 %                                                                             %
2179 %                                                                             %
2180 %                                                                             %
2181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2182 %
2183 %  DrawGetTextDecoration() returns the decoration applied when annotating with
2184 %  text.
2185 %
2186 %  The format of the DrawGetTextDecoration method is:
2187 %
2188 %      DecorationType DrawGetTextDecoration(DrawingWand *wand)
2189 %
2190 %  A description of each parameter follows:
2191 %
2192 %    o wand: the drawing wand.
2193 %
2194 */
2195 WandExport DecorationType DrawGetTextDecoration(const DrawingWand *wand)
2196 {
2197   assert(wand != (const DrawingWand *) NULL);
2198   assert(wand->signature == WandSignature);
2199   if (wand->debug != MagickFalse)
2200     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2201   return(CurrentContext->decorate);
2202 }
2203 \f
2204 /*
2205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2206 %                                                                             %
2207 %                                                                             %
2208 %                                                                             %
2209 %   D r a w G e t T e x t E n c o d i n g                                     %
2210 %                                                                             %
2211 %                                                                             %
2212 %                                                                             %
2213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2214 %
2215 %  DrawGetTextEncoding() returns a null-terminated string which specifies the
2216 %  code set used for text annotations. The string must be freed by the user
2217 %  once it is no longer required.
2218 %
2219 %  The format of the DrawGetTextEncoding method is:
2220 %
2221 %      char *DrawGetTextEncoding(const DrawingWand *wand)
2222 %
2223 %  A description of each parameter follows:
2224 %
2225 %    o wand: the drawing wand.
2226 %
2227 */
2228 WandExport char *DrawGetTextEncoding(const DrawingWand *wand)
2229 {
2230   assert(wand != (const DrawingWand *) NULL);
2231   assert(wand->signature == WandSignature);
2232   if (wand->debug != MagickFalse)
2233     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2234   if (CurrentContext->encoding != (char *) NULL)
2235     return((char *) AcquireString(CurrentContext->encoding));
2236   return((char *) NULL);
2237 }
2238 \f
2239 /*
2240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2241 %                                                                             %
2242 %                                                                             %
2243 %                                                                             %
2244 %   D r a w G e t T e x t K e r n i n g                                       %
2245 %                                                                             %
2246 %                                                                             %
2247 %                                                                             %
2248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2249 %
2250 %  DrawGetTextKerning() gets the spacing between characters in text.
2251 %
2252 %  The format of the DrawSetFontKerning method is:
2253 %
2254 %      double DrawGetTextKerning(DrawingWand *wand)
2255 %
2256 %  A description of each parameter follows:
2257 %
2258 %    o wand: the drawing wand.
2259 %
2260 */
2261 WandExport double DrawGetTextKerning(DrawingWand *wand)
2262 {
2263   assert(wand != (DrawingWand *) NULL);
2264   assert(wand->signature == WandSignature);
2265
2266   if (wand->debug != MagickFalse)
2267     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2268   return(CurrentContext->kerning);
2269 }
2270 \f
2271 /*
2272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2273 %                                                                             %
2274 %                                                                             %
2275 %                                                                             %
2276 %   D r a w G e t T e x t I n t e r L i n e S p a c i n g                     %
2277 %                                                                             %
2278 %                                                                             %
2279 %                                                                             %
2280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281 %
2282 %  DrawGetTextInterwordSpacing() gets the spacing between lines in text.
2283 %
2284 %  The format of the DrawSetFontKerning method is:
2285 %
2286 %      double DrawGetTextInterwordSpacing(DrawingWand *wand)
2287 %
2288 %  A description of each parameter follows:
2289 %
2290 %    o wand: the drawing wand.
2291 %
2292 */
2293 WandExport double DrawGetTextInterlineSpacing(DrawingWand *wand)
2294 {
2295   assert(wand != (DrawingWand *) NULL);
2296   assert(wand->signature == WandSignature);
2297   if (wand->debug != MagickFalse)
2298     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2299   return(CurrentContext->interline_spacing);
2300 }
2301 \f
2302 /*
2303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2304 %                                                                             %
2305 %                                                                             %
2306 %                                                                             %
2307 %   D r a w G e t T e x t I n t e r w o r d S p a c i n g                     %
2308 %                                                                             %
2309 %                                                                             %
2310 %                                                                             %
2311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2312 %
2313 %  DrawGetTextInterwordSpacing() gets the spacing between words in text.
2314 %
2315 %  The format of the DrawSetFontKerning method is:
2316 %
2317 %      double DrawGetTextInterwordSpacing(DrawingWand *wand)
2318 %
2319 %  A description of each parameter follows:
2320 %
2321 %    o wand: the drawing wand.
2322 %
2323 */
2324 WandExport double DrawGetTextInterwordSpacing(DrawingWand *wand)
2325 {
2326   assert(wand != (DrawingWand *) NULL);
2327   assert(wand->signature == WandSignature);
2328   if (wand->debug != MagickFalse)
2329     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2330   return(CurrentContext->interword_spacing);
2331 }
2332 \f
2333 /*
2334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335 %                                                                             %
2336 %                                                                             %
2337 %                                                                             %
2338 %   D r a w G e t V e c t o r G r a p h i c s                                 %
2339 %                                                                             %
2340 %                                                                             %
2341 %                                                                             %
2342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2343 %
2344 %  DrawGetVectorGraphics() returns a null-terminated string which specifies the
2345 %  vector graphics generated by any graphics calls made since the wand was
2346 %  instantiated.  The string must be freed by the user once it is no longer
2347 %  required.
2348 %
2349 %  The format of the DrawGetVectorGraphics method is:
2350 %
2351 %      char *DrawGetVectorGraphics(const DrawingWand *wand)
2352 %
2353 %  A description of each parameter follows:
2354 %
2355 %    o wand: the drawing wand.
2356 %
2357 */
2358
2359 static inline void SetMagickPixelPacket(const Image *image,
2360   const PixelPacket *color,const IndexPacket *index,MagickPixelPacket *pixel)
2361 {
2362   pixel->red=(MagickRealType) color->red;
2363   pixel->green=(MagickRealType) color->green;
2364   pixel->blue=(MagickRealType) color->blue;
2365   if (image->matte != MagickFalse)
2366     pixel->opacity=(MagickRealType) color->opacity;
2367   if (((image->colorspace == CMYKColorspace) ||
2368        (image->storage_class == PseudoClass)) &&
2369       (index != (const IndexPacket *) NULL))
2370     pixel->index=(MagickRealType) *index;
2371 }
2372
2373 WandExport char *DrawGetVectorGraphics(DrawingWand *wand)
2374 {
2375   char
2376     value[MaxTextExtent],
2377     *xml;
2378
2379   MagickPixelPacket
2380     pixel;
2381
2382   register long
2383     i;
2384
2385   XMLTreeInfo
2386     *child,
2387     *xml_info;
2388
2389   assert(wand != (const DrawingWand *) NULL);
2390   assert(wand->signature == WandSignature);
2391   if (wand->debug != MagickFalse)
2392     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2393   xml_info=NewXMLTreeTag("drawing-wand");
2394   if (xml_info == (XMLTreeInfo *) NULL)
2395     return(char *) NULL;
2396   GetMagickPixelPacket(wand->image,&pixel);
2397   child=AddChildToXMLTree(xml_info,"clip-path",0);
2398   if (child != (XMLTreeInfo *) NULL)
2399     (void) SetXMLTreeContent(child,CurrentContext->clip_mask);
2400   child=AddChildToXMLTree(xml_info,"clip-units",0);
2401   if (child != (XMLTreeInfo *) NULL)
2402     {
2403       (void) CopyMagickString(value,MagickOptionToMnemonic(
2404         MagickClipPathOptions,(long) CurrentContext->clip_units),MaxTextExtent);
2405       (void) SetXMLTreeContent(child,value);
2406     }
2407   child=AddChildToXMLTree(xml_info,"decorate",0);
2408   if (child != (XMLTreeInfo *) NULL)
2409     {
2410       (void) CopyMagickString(value,MagickOptionToMnemonic(
2411         MagickDecorateOptions,(long) CurrentContext->decorate),MaxTextExtent);
2412       (void) SetXMLTreeContent(child,value);
2413     }
2414   child=AddChildToXMLTree(xml_info,"encoding",0);
2415   if (child != (XMLTreeInfo *) NULL)
2416     (void) SetXMLTreeContent(child,CurrentContext->encoding);
2417   child=AddChildToXMLTree(xml_info,"fill",0);
2418   if (child != (XMLTreeInfo *) NULL)
2419     {
2420       if (CurrentContext->fill.opacity != OpaqueOpacity)
2421         pixel.matte=CurrentContext->fill.opacity != OpaqueOpacity ?
2422           MagickTrue : MagickFalse;
2423       SetMagickPixelPacket(wand->image,&CurrentContext->fill,
2424         (const IndexPacket *) NULL,&pixel);
2425       GetColorTuple(&pixel,MagickTrue,value);
2426       (void) SetXMLTreeContent(child,value);
2427     }
2428   child=AddChildToXMLTree(xml_info,"fill-opacity",0);
2429   if (child != (XMLTreeInfo *) NULL)
2430     {
2431       (void) FormatMagickString(value,MaxTextExtent,"%g",
2432         (double) QuantumScale*(QuantumRange-CurrentContext->fill.opacity));
2433       (void) SetXMLTreeContent(child,value);
2434     }
2435   child=AddChildToXMLTree(xml_info,"fill-rule",0);
2436   if (child != (XMLTreeInfo *) NULL)
2437     {
2438       (void) CopyMagickString(value,MagickOptionToMnemonic(
2439         MagickFillRuleOptions,(long) CurrentContext->fill_rule),MaxTextExtent);
2440       (void) SetXMLTreeContent(child,value);
2441     }
2442   child=AddChildToXMLTree(xml_info,"font",0);
2443   if (child != (XMLTreeInfo *) NULL)
2444     (void) SetXMLTreeContent(child,CurrentContext->font);
2445   child=AddChildToXMLTree(xml_info,"font-family",0);
2446   if (child != (XMLTreeInfo *) NULL)
2447     (void) SetXMLTreeContent(child,CurrentContext->family);
2448   child=AddChildToXMLTree(xml_info,"font-size",0);
2449   if (child != (XMLTreeInfo *) NULL)
2450     {
2451       (void) FormatMagickString(value,MaxTextExtent,"%g",
2452         CurrentContext->pointsize);
2453       (void) SetXMLTreeContent(child,value);
2454     }
2455   child=AddChildToXMLTree(xml_info,"font-stretch",0);
2456   if (child != (XMLTreeInfo *) NULL)
2457     {
2458       (void) CopyMagickString(value,MagickOptionToMnemonic(
2459         MagickStretchOptions,(long) CurrentContext->stretch),MaxTextExtent);
2460       (void) SetXMLTreeContent(child,value);
2461     }
2462   child=AddChildToXMLTree(xml_info,"font-style",0);
2463   if (child != (XMLTreeInfo *) NULL)
2464     {
2465       (void) CopyMagickString(value,MagickOptionToMnemonic(
2466         MagickStyleOptions,(long) CurrentContext->style),MaxTextExtent);
2467       (void) SetXMLTreeContent(child,value);
2468     }
2469   child=AddChildToXMLTree(xml_info,"font-weight",0);
2470   if (child != (XMLTreeInfo *) NULL)
2471     {
2472       (void) FormatMagickString(value,MaxTextExtent,"%lu",
2473         CurrentContext->weight);
2474       (void) SetXMLTreeContent(child,value);
2475     }
2476   child=AddChildToXMLTree(xml_info,"gravity",0);
2477   if (child != (XMLTreeInfo *) NULL)
2478     {
2479       (void) CopyMagickString(value,MagickOptionToMnemonic(MagickGravityOptions,
2480         (long) CurrentContext->gravity),MaxTextExtent);
2481       (void) SetXMLTreeContent(child,value);
2482     }
2483   child=AddChildToXMLTree(xml_info,"stroke",0);
2484   if (child != (XMLTreeInfo *) NULL)
2485     {
2486       if (CurrentContext->stroke.opacity != OpaqueOpacity)
2487         pixel.matte=CurrentContext->stroke.opacity != OpaqueOpacity ?
2488           MagickTrue : MagickFalse;
2489       SetMagickPixelPacket(wand->image,&CurrentContext->stroke,
2490         (const IndexPacket *) NULL,&pixel);
2491       GetColorTuple(&pixel,MagickTrue,value);
2492       (void) SetXMLTreeContent(child,value);
2493     }
2494   child=AddChildToXMLTree(xml_info,"stroke-antialias",0);
2495   if (child != (XMLTreeInfo *) NULL)
2496     {
2497       (void) FormatMagickString(value,MaxTextExtent,"%d",
2498         CurrentContext->stroke_antialias != MagickFalse ? 1 : 0);
2499       (void) SetXMLTreeContent(child,value);
2500     }
2501   child=AddChildToXMLTree(xml_info,"stroke-dasharray",0);
2502   if ((child != (XMLTreeInfo *) NULL) &&
2503       (CurrentContext->dash_pattern != (double *) NULL))
2504     {
2505       char
2506         *dash_pattern;
2507
2508       dash_pattern=AcquireString((char *) NULL);
2509       for (i=0; CurrentContext->dash_pattern[i] != 0.0; i++)
2510       {
2511         if (i != 0)
2512           (void) ConcatenateString(&dash_pattern,",");
2513         (void) FormatMagickString(value,MaxTextExtent,"%g",
2514           CurrentContext->dash_pattern[i]);
2515         (void) ConcatenateString(&dash_pattern,value);
2516       }
2517       (void) SetXMLTreeContent(child,dash_pattern);
2518       dash_pattern=DestroyString(dash_pattern);
2519     }
2520   child=AddChildToXMLTree(xml_info,"stroke-dashoffset",0);
2521   if (child != (XMLTreeInfo *) NULL)
2522     {
2523       (void) FormatMagickString(value,MaxTextExtent,"%g",
2524         CurrentContext->dash_offset);
2525       (void) SetXMLTreeContent(child,value);
2526     }
2527   child=AddChildToXMLTree(xml_info,"stroke-linecap",0);
2528   if (child != (XMLTreeInfo *) NULL)
2529     {
2530       (void) CopyMagickString(value,MagickOptionToMnemonic(MagickLineCapOptions,
2531         (long) CurrentContext->linecap),MaxTextExtent);
2532       (void) SetXMLTreeContent(child,value);
2533     }
2534   child=AddChildToXMLTree(xml_info,"stroke-linejoin",0);
2535   if (child != (XMLTreeInfo *) NULL)
2536     {
2537       (void) CopyMagickString(value,MagickOptionToMnemonic(
2538         MagickLineJoinOptions,(long) CurrentContext->linejoin),MaxTextExtent);
2539       (void) SetXMLTreeContent(child,value);
2540     }
2541   child=AddChildToXMLTree(xml_info,"stroke-miterlimit",0);
2542   if (child != (XMLTreeInfo *) NULL)
2543     {
2544       (void) FormatMagickString(value,MaxTextExtent,"%lu",
2545         CurrentContext->miterlimit);
2546       (void) SetXMLTreeContent(child,value);
2547     }
2548   child=AddChildToXMLTree(xml_info,"stroke-opacity",0);
2549   if (child != (XMLTreeInfo *) NULL)
2550     {
2551       (void) FormatMagickString(value,MaxTextExtent,"%g",
2552         (double) QuantumScale*(QuantumRange-CurrentContext->stroke.opacity));
2553       (void) SetXMLTreeContent(child,value);
2554     }
2555   child=AddChildToXMLTree(xml_info,"stroke-width",0);
2556   if (child != (XMLTreeInfo *) NULL)
2557     {
2558       (void) FormatMagickString(value,MaxTextExtent,"%g",
2559         CurrentContext->stroke_width);
2560       (void) SetXMLTreeContent(child,value);
2561     }
2562   child=AddChildToXMLTree(xml_info,"text-align",0);
2563   if (child != (XMLTreeInfo *) NULL)
2564     {
2565       (void) CopyMagickString(value,MagickOptionToMnemonic(MagickAlignOptions,
2566         (long) CurrentContext->align),MaxTextExtent);
2567       (void) SetXMLTreeContent(child,value);
2568     }
2569   child=AddChildToXMLTree(xml_info,"text-antialias",0);
2570   if (child != (XMLTreeInfo *) NULL)
2571     {
2572       (void) FormatMagickString(value,MaxTextExtent,"%d",
2573         CurrentContext->text_antialias != MagickFalse ? 1 : 0);
2574       (void) SetXMLTreeContent(child,value);
2575     }
2576   child=AddChildToXMLTree(xml_info,"text-undercolor",0);
2577   if (child != (XMLTreeInfo *) NULL)
2578     {
2579       if (CurrentContext->undercolor.opacity != OpaqueOpacity)
2580         pixel.matte=CurrentContext->undercolor.opacity != OpaqueOpacity ?
2581           MagickTrue : MagickFalse;
2582       SetMagickPixelPacket(wand->image,&CurrentContext->undercolor,
2583         (const IndexPacket *) NULL,&pixel);
2584       GetColorTuple(&pixel,MagickTrue,value);
2585       (void) SetXMLTreeContent(child,value);
2586     }
2587   child=AddChildToXMLTree(xml_info,"vector-graphics",0);
2588   if (child != (XMLTreeInfo *) NULL)
2589     (void) SetXMLTreeContent(child,wand->mvg);
2590   xml=XMLTreeInfoToXML(xml_info);
2591   xml_info=DestroyXMLTree(xml_info);
2592   return(xml);
2593 }
2594 \f
2595 /*
2596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2597 %                                                                             %
2598 %                                                                             %
2599 %                                                                             %
2600 %   D r a w G e t T e x t U n d e r C o l o r                                 %
2601 %                                                                             %
2602 %                                                                             %
2603 %                                                                             %
2604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2605 %
2606 %  DrawGetTextUnderColor() returns the color of a background rectangle
2607 %  to place under text annotations.
2608 %
2609 %  The format of the DrawGetTextUnderColor method is:
2610 %
2611 %      void DrawGetTextUnderColor(const DrawingWand *wand,
2612 %        PixelWand *under_color)
2613 %
2614 %  A description of each parameter follows:
2615 %
2616 %    o wand: the drawing wand.
2617 %
2618 %    o under_color: Return the under color.
2619 %
2620 */
2621 WandExport void DrawGetTextUnderColor(const DrawingWand *wand,
2622   PixelWand *under_color)
2623 {
2624   assert(wand != (const DrawingWand *) NULL);
2625   assert(wand->signature == WandSignature);
2626   assert(under_color != (PixelWand *) NULL);
2627   if (wand->debug != MagickFalse)
2628     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2629   PixelSetQuantumColor(under_color,&CurrentContext->undercolor);
2630 }
2631 \f
2632 /*
2633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634 %                                                                             %
2635 %                                                                             %
2636 %                                                                             %
2637 %   D r a w L i n e                                                           %
2638 %                                                                             %
2639 %                                                                             %
2640 %                                                                             %
2641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642 %
2643 %  DrawLine() draws a line on the image using the current stroke color,
2644 %  stroke opacity, and stroke width.
2645 %
2646 %  The format of the DrawLine method is:
2647 %
2648 %      void DrawLine(DrawingWand *wand,const double sx,const double sy,
2649 %        const double ex,const double ey)
2650 %
2651 %  A description of each parameter follows:
2652 %
2653 %    o wand: the drawing wand.
2654 %
2655 %    o sx: starting x ordinate
2656 %
2657 %    o sy: starting y ordinate
2658 %
2659 %    o ex: ending x ordinate
2660 %
2661 %    o ey: ending y ordinate
2662 %
2663 */
2664 WandExport void DrawLine(DrawingWand *wand,const double sx,const double sy,
2665   const double ex,const double ey)
2666 {
2667   assert(wand != (DrawingWand *) NULL);
2668   assert(wand->signature == WandSignature);
2669   if (wand->debug != MagickFalse)
2670     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2671   (void) MvgPrintf(wand,"line %g,%g %g,%g\n",sx,sy,ex,ey);
2672 }
2673 \f
2674 /*
2675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2676 %                                                                             %
2677 %                                                                             %
2678 %                                                                             %
2679 %   D r a w M a t t e                                                         %
2680 %                                                                             %
2681 %                                                                             %
2682 %                                                                             %
2683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2684 %
2685 %  DrawMatte() paints on the image's opacity channel in order to set effected
2686 %  pixels to transparent.
2687 %  to influence the opacity of pixels. The available paint
2688 %  methods are:
2689 %
2690 %    PointMethod: Select the target pixel
2691 %    ReplaceMethod: Select any pixel that matches the target pixel.
2692 %    FloodfillMethod: Select the target pixel and matching neighbors.
2693 %    FillToBorderMethod: Select the target pixel and neighbors not matching
2694 %      border color.
2695 %    ResetMethod: Select all pixels.
2696 %
2697 %  The format of the DrawMatte method is:
2698 %
2699 %      void DrawMatte(DrawingWand *wand,const double x,const double y,
2700 %        const PaintMethod paint_method)
2701 %
2702 %  A description of each parameter follows:
2703 %
2704 %    o wand: the drawing wand.
2705 %
2706 %    o x: x ordinate
2707 %
2708 %    o y: y ordinate
2709 %
2710 %    o paint_method: paint method.
2711 %
2712 */
2713 WandExport void DrawMatte(DrawingWand *wand,const double x,const double y,
2714   const PaintMethod paint_method)
2715 {
2716   assert(wand != (DrawingWand *) NULL);
2717   assert(wand->signature == WandSignature);
2718   if (wand->debug != MagickFalse)
2719     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2720   (void) MvgPrintf(wand,"matte %g,%g '%s'\n",x,y,MagickOptionToMnemonic(
2721     MagickMethodOptions,(long) paint_method));
2722 }
2723 \f
2724 /*
2725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2726 %                                                                             %
2727 %                                                                             %
2728 %                                                                             %
2729 %   D r a w P a t h C l o s e                                                 %
2730 %                                                                             %
2731 %                                                                             %
2732 %                                                                             %
2733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2734 %
2735 %  DrawPathClose() adds a path element to the current path which closes the
2736 %  current subpath by drawing a straight line from the current point to the
2737 %  current subpath's most recent starting point (usually, the most recent
2738 %  moveto point).
2739 %
2740 %  The format of the DrawPathClose method is:
2741 %
2742 %      void DrawPathClose(DrawingWand *wand)
2743 %
2744 %  A description of each parameter follows:
2745 %
2746 %    o wand: the drawing wand.
2747 %
2748 */
2749 WandExport void DrawPathClose(DrawingWand *wand)
2750 {
2751   assert(wand != (DrawingWand *) NULL);
2752   assert(wand->signature == WandSignature);
2753   if (wand->debug != MagickFalse)
2754     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2755   (void) MvgAutoWrapPrintf(wand,"%s",wand->path_mode == AbsolutePathMode ?
2756     "Z" : "z");
2757 }
2758 \f
2759 /*
2760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2761 %                                                                             %
2762 %                                                                             %
2763 %                                                                             %
2764 %   D r a w P a t h C u r v e T o A b s o l u t e                             %
2765 %                                                                             %
2766 %                                                                             %
2767 %                                                                             %
2768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2769 %
2770 %  DrawPathCurveToAbsolute() draws a cubic Bezier curve from the current
2771 %  point to (x,y) using (x1,y1) as the control point at the beginning of
2772 %  the curve and (x2,y2) as the control point at the end of the curve using
2773 %  absolute coordinates. At the end of the command, the new current point
2774 %  becomes the final (x,y) coordinate pair used in the polybezier.
2775 %
2776 %  The format of the DrawPathCurveToAbsolute method is:
2777 %
2778 %      void DrawPathCurveToAbsolute(DrawingWand *wand,const double x1,
2779 %        const double y1,const double x2,const double y2,const double x,
2780 %        const double y)
2781 %
2782 %  A description of each parameter follows:
2783 %
2784 %    o wand: the drawing wand.
2785 %
2786 %    o x1: x ordinate of control point for curve beginning
2787 %
2788 %    o y1: y ordinate of control point for curve beginning
2789 %
2790 %    o x2: x ordinate of control point for curve ending
2791 %
2792 %    o y2: y ordinate of control point for curve ending
2793 %
2794 %    o x: x ordinate of the end of the curve
2795 %
2796 %    o y: y ordinate of the end of the curve
2797 %
2798 */
2799
2800 static void DrawPathCurveTo(DrawingWand *wand,const PathMode mode,
2801   const double x1,const double y1,const double x2,const double y2,
2802   const double x,const double y)
2803 {
2804   assert(wand != (DrawingWand *) NULL);
2805   assert(wand->signature == WandSignature);
2806   if (wand->debug != MagickFalse)
2807     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2808   if ((wand->path_operation != PathCurveToOperation) ||
2809       (wand->path_mode != mode))
2810     {
2811       wand->path_operation=PathCurveToOperation;
2812       wand->path_mode=mode;
2813       (void) MvgAutoWrapPrintf(wand, "%c%g,%g %g,%g %g,%g",
2814         mode == AbsolutePathMode ? 'C' : 'c',x1,y1,x2,y2,x,y);
2815     }
2816   else
2817     (void) MvgAutoWrapPrintf(wand," %g,%g %g,%g %g,%g",x1,y1,x2,y2,x,y);
2818 }
2819
2820 WandExport void DrawPathCurveToAbsolute(DrawingWand *wand,const double x1,
2821   const double y1,const double x2,const double y2,const double x,const double y)
2822 {
2823   assert(wand != (DrawingWand *) NULL);
2824   assert(wand->signature == WandSignature);
2825   if (wand->debug != MagickFalse)
2826     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2827   DrawPathCurveTo(wand,AbsolutePathMode,x1,y1,x2,y2,x,y);
2828 }
2829 \f
2830 /*
2831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2832 %                                                                             %
2833 %                                                                             %
2834 %                                                                             %
2835 %   D r a w P a t h C u r v e T o R e l a t i v e                             %
2836 %                                                                             %
2837 %                                                                             %
2838 %                                                                             %
2839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2840 %
2841 %  DrawPathCurveToRelative() draws a cubic Bezier curve from the current
2842 %  point to (x,y) using (x1,y1) as the control point at the beginning of
2843 %  the curve and (x2,y2) as the control point at the end of the curve using
2844 %  relative coordinates. At the end of the command, the new current point
2845 %  becomes the final (x,y) coordinate pair used in the polybezier.
2846 %
2847 %  The format of the DrawPathCurveToRelative method is:
2848 %
2849 %      void DrawPathCurveToRelative(DrawingWand *wand,const double x1,
2850 %        const double y1,const double x2,const double y2,const double x,
2851 %        const double y)
2852 %
2853 %  A description of each parameter follows:
2854 %
2855 %    o wand: the drawing wand.
2856 %
2857 %    o x1: x ordinate of control point for curve beginning
2858 %
2859 %    o y1: y ordinate of control point for curve beginning
2860 %
2861 %    o x2: x ordinate of control point for curve ending
2862 %
2863 %    o y2: y ordinate of control point for curve ending
2864 %
2865 %    o x: x ordinate of the end of the curve
2866 %
2867 %    o y: y ordinate of the end of the curve
2868 %
2869 */
2870 WandExport void DrawPathCurveToRelative(DrawingWand *wand,const double x1,
2871   const double y1,const double x2,const double y2,const double x,const double y)
2872 {
2873   assert(wand != (DrawingWand *) NULL);
2874   assert(wand->signature == WandSignature);
2875   if (wand->debug != MagickFalse)
2876     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2877   DrawPathCurveTo(wand,RelativePathMode,x1,y1,x2,y2,x,y);
2878 }
2879 \f
2880 /*
2881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2882 %                                                                             %
2883 %                                                                             %
2884 %                                                                             %
2885 %   D r a w P a t h C u r v e T o Q u a d r a t i c B e z i e r A b s o l u t e %
2886 %                                                                             %
2887 %                                                                             %
2888 %                                                                             %
2889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2890 %
2891 %  DrawPathCurveToQuadraticBezierAbsolute() draws a quadratic Bezier curve
2892 %  from the current point to (x,y) using (x1,y1) as the control point using
2893 %  absolute coordinates. At the end of the command, the new current point
2894 %  becomes the final (x,y) coordinate pair used in the polybezier.
2895 %
2896 %  The format of the DrawPathCurveToQuadraticBezierAbsolute method is:
2897 %
2898 %      void DrawPathCurveToQuadraticBezierAbsolute(DrawingWand *wand,
2899 %        const double x1,const double y1,onst double x,const double y)
2900 %
2901 %  A description of each parameter follows:
2902 %
2903 %    o wand: the drawing wand.
2904 %
2905 %    o x1: x ordinate of the control point
2906 %
2907 %    o y1: y ordinate of the control point
2908 %
2909 %    o x: x ordinate of final point
2910 %
2911 %    o y: y ordinate of final point
2912 %
2913 */
2914
2915 static void DrawPathCurveToQuadraticBezier(DrawingWand *wand,
2916   const PathMode mode,const double x1,double y1,const double x,const double y)
2917 {
2918   assert(wand != (DrawingWand *) NULL);
2919   assert(wand->signature == WandSignature);
2920   if (wand->debug != MagickFalse)
2921     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2922   if ((wand->path_operation != PathCurveToQuadraticBezierOperation) ||
2923       (wand->path_mode != mode))
2924     {
2925       wand->path_operation=PathCurveToQuadraticBezierOperation;
2926       wand->path_mode=mode;
2927       (void) MvgAutoWrapPrintf(wand, "%c%g,%g %g,%g",mode == AbsolutePathMode ?
2928         'Q' : 'q',x1,y1,x,y);
2929     }
2930   else
2931     (void) MvgAutoWrapPrintf(wand," %g,%g %g,%g",x1,y1,x,y);
2932 }
2933
2934 WandExport void DrawPathCurveToQuadraticBezierAbsolute(DrawingWand *wand,
2935   const double x1,const double y1,const double x,const double y)
2936 {
2937   assert(wand != (DrawingWand *) NULL);
2938   assert(wand->signature == WandSignature);
2939   if (wand->debug != MagickFalse)
2940     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2941   DrawPathCurveToQuadraticBezier(wand,AbsolutePathMode,x1,y1,x,y);
2942 }
2943 \f
2944 /*
2945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2946 %                                                                             %
2947 %                                                                             %
2948 %                                                                             %
2949 %   D r a w P a t h C u r v e T o Q u a d r a t i c B e z i e r R e l a t i v e
2950 %                                                                             %
2951 %                                                                             %
2952 %                                                                             %
2953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2954 %
2955 %  DrawPathCurveToQuadraticBezierRelative() draws a quadratic Bezier curve
2956 %  from the current point to (x,y) using (x1,y1) as the control point using
2957 %  relative coordinates. At the end of the command, the new current point
2958 %  becomes the final (x,y) coordinate pair used in the polybezier.
2959 %
2960 %  The format of the DrawPathCurveToQuadraticBezierRelative method is:
2961 %
2962 %      void DrawPathCurveToQuadraticBezierRelative(DrawingWand *wand,
2963 %        const double x1,const double y1,const double x,const double y)
2964 %
2965 %  A description of each parameter follows:
2966 %
2967 %    o wand: the drawing wand.
2968 %
2969 %    o x1: x ordinate of the control point
2970 %
2971 %    o y1: y ordinate of the control point
2972 %
2973 %    o x: x ordinate of final point
2974 %
2975 %    o y: y ordinate of final point
2976 %
2977 */
2978 WandExport void DrawPathCurveToQuadraticBezierRelative(DrawingWand *wand,
2979   const double x1,const double y1,const double x,const double y)
2980 {
2981   assert(wand != (DrawingWand *) NULL);
2982   assert(wand->signature == WandSignature);
2983   if (wand->debug != MagickFalse)
2984     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
2985   DrawPathCurveToQuadraticBezier(wand,RelativePathMode,x1,y1,x,y);
2986 }
2987 \f
2988 /*
2989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2990 %                                                                             %
2991 %                                                                             %
2992 %                                                                             %
2993 %   D r a w P a t h C u r v e T o Q u a d r a t i c B e z i e r S m o o t h   %
2994 %                                                                             %
2995 %                                                                             %
2996 %                                                                             %
2997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2998 %
2999 %  DrawPathCurveToQuadraticBezierSmoothAbsolute() draws a quadratic
3000 %  Bezier curve (using absolute coordinates) from the current point to
3001 %  (x,y). The control point is assumed to be the reflection of the
3002 %  control point on the previous command relative to the current
3003 %  point. (If there is no previous command or if the previous command was
3004 %  not a DrawPathCurveToQuadraticBezierAbsolute,
3005 %  DrawPathCurveToQuadraticBezierRelative,
3006 %  DrawPathCurveToQuadraticBezierSmoothAbsolute or
3007 %  DrawPathCurveToQuadraticBezierSmoothRelative, assume the control point
3008 %  is coincident with the current point.). At the end of the command, the
3009 %  new current point becomes the final (x,y) coordinate pair used in the
3010 %  polybezier.
3011 %
3012 %  The format of the DrawPathCurveToQuadraticBezierSmoothAbsolute method is:
3013 %
3014 %      void DrawPathCurveToQuadraticBezierSmoothAbsolute(
3015 %        DrawingWand *wand,const double x,const double y)
3016 %
3017 %  A description of each parameter follows:
3018 %
3019 %    o wand: the drawing wand.
3020 %
3021 %    o x: x ordinate of final point
3022 %
3023 %    o y: y ordinate of final point
3024 %
3025 */
3026
3027 static void DrawPathCurveToQuadraticBezierSmooth(DrawingWand *wand,
3028   const PathMode mode,const double x,const double y)
3029 {
3030   assert(wand != (DrawingWand *) NULL);
3031   assert(wand->signature == WandSignature);
3032   if (wand->debug != MagickFalse)
3033     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3034   if ((wand->path_operation != PathCurveToQuadraticBezierSmoothOperation) ||
3035       (wand->path_mode != mode))
3036     {
3037       wand->path_operation=PathCurveToQuadraticBezierSmoothOperation;
3038       wand->path_mode=mode;
3039       (void) MvgAutoWrapPrintf(wand,"%c%g,%g",mode == AbsolutePathMode ?
3040         'T' : 't',x,y);
3041     }
3042   else
3043     (void) MvgAutoWrapPrintf(wand," %g,%g",x,y);
3044 }
3045
3046 WandExport void DrawPathCurveToQuadraticBezierSmoothAbsolute(DrawingWand *wand,
3047   const double x,const double y)
3048 {
3049   assert(wand != (DrawingWand *) NULL);
3050   assert(wand->signature == WandSignature);
3051   if (wand->debug != MagickFalse)
3052     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3053   DrawPathCurveToQuadraticBezierSmooth(wand,AbsolutePathMode,x,y);
3054 }
3055 \f
3056 /*
3057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3058 %                                                                             %
3059 %                                                                             %
3060 %                                                                             %
3061 %   D r a w P a t h C u r v e T o Q u a d r a t i c B e z i e r S m o o t h   %
3062 %                                                                             %
3063 %                                                                             %
3064 %                                                                             %
3065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3066 %
3067 %  DrawPathCurveToQuadraticBezierSmoothAbsolute() draws a quadratic Bezier
3068 %  curve (using relative coordinates) from the current point to (x,y). The
3069 %  control point is assumed to be the reflection of the control point on the
3070 %  previous command relative to the current point. (If there is no previous
3071 %  command or if the previous command was not a
3072 %  DrawPathCurveToQuadraticBezierAbsolute,
3073 %  DrawPathCurveToQuadraticBezierRelative,
3074 %  DrawPathCurveToQuadraticBezierSmoothAbsolute or
3075 %  DrawPathCurveToQuadraticBezierSmoothRelative, assume the control point is
3076 %  coincident with the current point.). At the end of the command, the new
3077 %  current point becomes the final (x,y) coordinate pair used in the polybezier.
3078 %
3079 %  The format of the DrawPathCurveToQuadraticBezierSmoothRelative method is:
3080 %
3081 %      void DrawPathCurveToQuadraticBezierSmoothRelative(DrawingWand *wand,
3082 %        const double x,const double y)
3083 %
3084 %  A description of each parameter follows:
3085 %
3086 %    o wand: the drawing wand.
3087 %
3088 %    o x: x ordinate of final point
3089 %
3090 %    o y: y ordinate of final point
3091 %
3092 */
3093 WandExport void DrawPathCurveToQuadraticBezierSmoothRelative(DrawingWand *wand,
3094   const double x,const double y)
3095 {
3096   DrawPathCurveToQuadraticBezierSmooth(wand,RelativePathMode,x,y);
3097 }
3098 \f
3099 /*
3100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3101 %                                                                             %
3102 %                                                                             %
3103 %                                                                             %
3104 %   D r a w P a t h C u r v e T o S m o o t h A b s o l u t e                 %
3105 %                                                                             %
3106 %                                                                             %
3107 %                                                                             %
3108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3109 %
3110 %  DrawPathCurveToSmoothAbsolute() draws a cubic Bezier curve from the
3111 %  current point to (x,y) using absolute coordinates. The first control
3112 %  point is assumed to be the reflection of the second control point on
3113 %  the previous command relative to the current point. (If there is no
3114 %  previous command or if the previous command was not an
3115 %  DrawPathCurveToAbsolute, DrawPathCurveToRelative,
3116 %  DrawPathCurveToSmoothAbsolute or DrawPathCurveToSmoothRelative, assume
3117 %  the first control point is coincident with the current point.) (x2,y2)
3118 %  is the second control point (i.e., the control point at the end of the
3119 %  curve). At the end of the command, the new current point becomes the
3120 %  final (x,y) coordinate pair used in the polybezier.
3121 %
3122 %  The format of the DrawPathCurveToSmoothAbsolute method is:
3123 %
3124 %      void DrawPathCurveToSmoothAbsolute(DrawingWand *wand,
3125 %        const double x2const double y2,const double x,const double y)
3126 %
3127 %  A description of each parameter follows:
3128 %
3129 %    o wand: the drawing wand.
3130 %
3131 %    o x2: x ordinate of second control point
3132 %
3133 %    o y2: y ordinate of second control point
3134 %
3135 %    o x: x ordinate of termination point
3136 %
3137 %    o y: y ordinate of termination point
3138 %
3139 */
3140
3141 static void DrawPathCurveToSmooth(DrawingWand *wand,const PathMode mode,
3142   const double x2,const double y2,const double x,const double y)
3143 {
3144   assert(wand != (DrawingWand *) NULL);
3145   assert(wand->signature == WandSignature);
3146   if (wand->debug != MagickFalse)
3147     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3148   if ((wand->path_operation != PathCurveToSmoothOperation) ||
3149       (wand->path_mode != mode))
3150     {
3151       wand->path_operation=PathCurveToSmoothOperation;
3152       wand->path_mode=mode;
3153       (void) MvgAutoWrapPrintf(wand,"%c%g,%g %g,%g",mode == AbsolutePathMode ?
3154         'S' : 's',x2,y2,x,y);
3155     }
3156   else
3157     (void) MvgAutoWrapPrintf(wand," %g,%g %g,%g",x2,y2,x,y);
3158 }
3159
3160 WandExport void DrawPathCurveToSmoothAbsolute(DrawingWand *wand,const double x2,
3161   const double y2,const double x,const double y)
3162 {
3163   assert(wand != (DrawingWand *) NULL);
3164   assert(wand->signature == WandSignature);
3165   if (wand->debug != MagickFalse)
3166     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3167   DrawPathCurveToSmooth(wand,AbsolutePathMode,x2,y2,x,y);
3168 }
3169 \f
3170 /*
3171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3172 %                                                                             %
3173 %                                                                             %
3174 %                                                                             %
3175 %   D r a w P a t h C u r v e T o S m o o t h R e l a t i v e                 %
3176 %                                                                             %
3177 %                                                                             %
3178 %                                                                             %
3179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3180 %
3181 %  DrawPathCurveToSmoothRelative() draws a cubic Bezier curve from the current
3182 %  point to (x,y) using relative coordinates. The first control point is
3183 %  assumed to be the reflection of the second control point on the previous
3184 %  command relative to the current point. (If there is no previous command or
3185 %  if the previous command was not an DrawPathCurveToAbsolute,
3186 %  DrawPathCurveToRelative, DrawPathCurveToSmoothAbsolute or
3187 %  DrawPathCurveToSmoothRelative, assume the first control point is coincident
3188 %  with the current point.) (x2,y2) is the second control point (i.e., the
3189 %  control point at the end of the curve). At the end of the command, the new
3190 %  current point becomes the final (x,y) coordinate pair used in the polybezier.
3191 %
3192 %  The format of the DrawPathCurveToSmoothRelative method is:
3193 %
3194 %      void DrawPathCurveToSmoothRelative(DrawingWand *wand,
3195 %        const double x2,const double y2,const double x,const double y)
3196 %
3197 %  A description of each parameter follows:
3198 %
3199 %    o wand: the drawing wand.
3200 %
3201 %    o x2: x ordinate of second control point
3202 %
3203 %    o y2: y ordinate of second control point
3204 %
3205 %    o x: x ordinate of termination point
3206 %
3207 %    o y: y ordinate of termination point
3208 %
3209 */
3210 WandExport void DrawPathCurveToSmoothRelative(DrawingWand *wand,const double x2,
3211   const double y2,const double x,const double y)
3212 {
3213   assert(wand != (DrawingWand *) NULL);
3214   assert(wand->signature == WandSignature);
3215   if (wand->debug != MagickFalse)
3216     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3217   DrawPathCurveToSmooth(wand,RelativePathMode,x2,y2,x,y);
3218 }
3219 \f
3220 /*
3221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3222 %                                                                             %
3223 %                                                                             %
3224 %                                                                             %
3225 %   D r a w P a t h E l l i p t i c A r c A b s o l u t e                     %
3226 %                                                                             %
3227 %                                                                             %
3228 %                                                                             %
3229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3230 %
3231 %  DrawPathEllipticArcAbsolute() draws an elliptical arc from the current point
3232 %  to (x, y) using absolute coordinates. The size and orientation of the
3233 %  ellipse are defined by two radii (rx, ry) and an xAxisRotation, which
3234 %  indicates how the ellipse as a whole is rotated relative to the current
3235 %  coordinate system. The center (cx, cy) of the ellipse is calculated
3236 %  automagically to satisfy the constraints imposed by the other parameters.
3237 %  largeArcFlag and sweepFlag contribute to the automatic calculations and help
3238 %  determine how the arc is drawn. If largeArcFlag is true then draw the larger
3239 %  of the available arcs. If sweepFlag is true, then draw the arc matching a
3240 %  clock-wise rotation.
3241 %
3242 %  The format of the DrawPathEllipticArcAbsolute method is:
3243 %
3244 %      void DrawPathEllipticArcAbsolute(DrawingWand *wand,
3245 %        const double rx,const double ry,const double x_axis_rotation,
3246 %        const MagickBooleanType large_arc_flag,
3247 %        const MagickBooleanType sweep_flag,const double x,const double y)
3248 %
3249 %  A description of each parameter follows:
3250 %
3251 %    o wand: the drawing wand.
3252 %
3253 %    o rx: x radius
3254 %
3255 %    o ry: y radius
3256 %
3257 %    o x_axis_rotation: indicates how the ellipse as a whole is rotated
3258 %        relative to the current coordinate system
3259 %
3260 %    o large_arc_flag: If non-zero (true) then draw the larger of the
3261 %        available arcs
3262 %
3263 %    o sweep_flag: If non-zero (true) then draw the arc matching a
3264 %        clock-wise rotation
3265 %
3266 %
3267 */
3268
3269 static void DrawPathEllipticArc(DrawingWand *wand, const PathMode mode,
3270   const double rx,const double ry,const double x_axis_rotation,
3271   const MagickBooleanType large_arc_flag,const MagickBooleanType sweep_flag,
3272   const double x,const double y)
3273 {
3274   assert(wand != (DrawingWand *) NULL);
3275   assert(wand->signature == WandSignature);
3276   if (wand->debug != MagickFalse)
3277     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3278   if ((wand->path_operation != PathEllipticArcOperation) ||
3279       (wand->path_mode != mode))
3280     {
3281       wand->path_operation=PathEllipticArcOperation;
3282       wand->path_mode=mode;
3283       (void) MvgAutoWrapPrintf(wand, "%c%g,%g %g %u %u %g,%g",
3284         mode == AbsolutePathMode ? 'A' : 'a',rx,ry,x_axis_rotation,
3285         large_arc_flag,sweep_flag,x,y);
3286     }
3287   else
3288     (void) MvgAutoWrapPrintf(wand," %g,%g %g %u %u %g,%g",rx,ry,x_axis_rotation,
3289       large_arc_flag,sweep_flag,x,y);
3290 }
3291
3292 WandExport void DrawPathEllipticArcAbsolute(DrawingWand *wand,const double rx,
3293   const double ry,const double x_axis_rotation,
3294   const MagickBooleanType large_arc_flag,const MagickBooleanType sweep_flag,
3295   const double x,const double y)
3296 {
3297   assert(wand != (DrawingWand *) NULL);
3298   assert(wand->signature == WandSignature);
3299   if (wand->debug != MagickFalse)
3300     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3301   DrawPathEllipticArc(wand,AbsolutePathMode,rx,ry,x_axis_rotation,
3302     large_arc_flag,sweep_flag,x,y);
3303 }
3304 \f
3305 /*
3306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3307 %                                                                             %
3308 %                                                                             %
3309 %                                                                             %
3310 %   D r a w P a t h E l l i p t i c A r c R e l a t i v e                     %
3311 %                                                                             %
3312 %                                                                             %
3313 %                                                                             %
3314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3315 %
3316 %  DrawPathEllipticArcRelative() draws an elliptical arc from the current point
3317 %  to (x, y) using relative coordinates. The size and orientation of the
3318 %  ellipse are defined by two radii (rx, ry) and an xAxisRotation, which
3319 %  indicates how the ellipse as a whole is rotated relative to the current
3320 %  coordinate system. The center (cx, cy) of the ellipse is calculated
3321 %  automagically to satisfy the constraints imposed by the other parameters.
3322 %  largeArcFlag and sweepFlag contribute to the automatic calculations and help
3323 %  determine how the arc is drawn. If largeArcFlag is true then draw the larger
3324 %  of the available arcs. If sweepFlag is true, then draw the arc matching a
3325 %  clock-wise rotation.
3326 %
3327 %  The format of the DrawPathEllipticArcRelative method is:
3328 %
3329 %      void DrawPathEllipticArcRelative(DrawingWand *wand,
3330 %        const double rx,const double ry,const double x_axis_rotation,
3331 %        const MagickBooleanType large_arc_flag,
3332 %        const MagickBooleanType sweep_flag,const double x,const double y)
3333 %
3334 %  A description of each parameter follows:
3335 %
3336 %    o wand: the drawing wand.
3337 %
3338 %    o rx: x radius
3339 %
3340 %    o ry: y radius
3341 %
3342 %    o x_axis_rotation: indicates how the ellipse as a whole is rotated
3343 %                       relative to the current coordinate system
3344 %
3345 %    o large_arc_flag: If non-zero (true) then draw the larger of the
3346 %                      available arcs
3347 %
3348 %    o sweep_flag: If non-zero (true) then draw the arc matching a
3349 %                  clock-wise rotation
3350 %
3351 */
3352 WandExport void DrawPathEllipticArcRelative(DrawingWand *wand,const double rx,
3353   const double ry,const double x_axis_rotation,
3354   const MagickBooleanType large_arc_flag,const MagickBooleanType sweep_flag,
3355   const double x,const double y)
3356 {
3357   DrawPathEllipticArc(wand,RelativePathMode,rx,ry,x_axis_rotation,
3358     large_arc_flag,sweep_flag,x,y);
3359 }
3360 \f
3361 /*
3362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3363 %                                                                             %
3364 %                                                                             %
3365 %                                                                             %
3366 %   D r a w P a t h F i n i s h                                               %
3367 %                                                                             %
3368 %                                                                             %
3369 %                                                                             %
3370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3371 %
3372 %  DrawPathFinish() terminates the current path.
3373 %
3374 %  The format of the DrawPathFinish method is:
3375 %
3376 %      void DrawPathFinish(DrawingWand *wand)
3377 %
3378 %  A description of each parameter follows:
3379 %
3380 %    o wand: the drawing wand.
3381 %
3382 */
3383 WandExport void DrawPathFinish(DrawingWand *wand)
3384 {
3385   assert(wand != (DrawingWand *) NULL);
3386   assert(wand->signature == WandSignature);
3387   if (wand->debug != MagickFalse)
3388     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3389   (void) MvgPrintf(wand,"'\n");
3390   wand->path_operation=PathDefaultOperation;
3391   wand->path_mode=DefaultPathMode;
3392 }
3393 \f
3394 /*
3395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3396 %                                                                             %
3397 %                                                                             %
3398 %                                                                             %
3399 %   D r a w P a t h L i n e T o A b s o l u t e                               %
3400 %                                                                             %
3401 %                                                                             %
3402 %                                                                             %
3403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3404 %
3405 %  DrawPathLineToAbsolute() draws a line path from the current point to the
3406 %  given coordinate using absolute coordinates. The coordinate then becomes
3407 %  the new current point.
3408 %
3409 %  The format of the DrawPathLineToAbsolute method is:
3410 %
3411 %      void DrawPathLineToAbsolute(DrawingWand *wand,const double x,
3412 %        const double y)
3413 %
3414 %  A description of each parameter follows:
3415 %
3416 %    o wand: the drawing wand.
3417 %
3418 %    o x: target x ordinate
3419 %
3420 %    o y: target y ordinate
3421 %
3422 */
3423 static void DrawPathLineTo(DrawingWand *wand,const PathMode mode,
3424   const double x,const double y)
3425 {
3426   assert(wand != (DrawingWand *) NULL);
3427   assert(wand->signature == WandSignature);
3428   if (wand->debug != MagickFalse)
3429     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3430   if ((wand->path_operation != PathLineToOperation) ||
3431       (wand->path_mode != mode))
3432     {
3433       wand->path_operation=PathLineToOperation;
3434       wand->path_mode=mode;
3435       (void) MvgAutoWrapPrintf(wand,"%c%g,%g",mode == AbsolutePathMode ?
3436         'L' : 'l',x,y);
3437     }
3438   else
3439     (void) MvgAutoWrapPrintf(wand," %g,%g",x,y);
3440 }
3441
3442 WandExport void DrawPathLineToAbsolute(DrawingWand *wand,const double x,
3443   const double y)
3444 {
3445   assert(wand != (DrawingWand *) NULL);
3446   assert(wand->signature == WandSignature);
3447   if (wand->debug != MagickFalse)
3448     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3449   DrawPathLineTo(wand,AbsolutePathMode,x,y);
3450 }
3451 \f
3452 /*
3453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3454 %                                                                             %
3455 %                                                                             %
3456 %                                                                             %
3457 %   D r a w P a t h L i n e T o R e l a t i v e                               %
3458 %                                                                             %
3459 %                                                                             %
3460 %                                                                             %
3461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3462 %
3463 %  DrawPathLineToRelative() draws a line path from the current point to the
3464 %  given coordinate using relative coordinates. The coordinate then becomes
3465 %  the new current point.
3466 %
3467 %  The format of the DrawPathLineToRelative method is:
3468 %
3469 %      void DrawPathLineToRelative(DrawingWand *wand,const double x,
3470 %        const double y)
3471 %
3472 %  A description of each parameter follows:
3473 %
3474 %    o wand: the drawing wand.
3475 %
3476 %    o x: target x ordinate
3477 %
3478 %    o y: target y ordinate
3479 %
3480 */
3481 WandExport void DrawPathLineToRelative(DrawingWand *wand,const double x,
3482   const double y)
3483 {
3484   assert(wand != (DrawingWand *) NULL);
3485   assert(wand->signature == WandSignature);
3486   if (wand->debug != MagickFalse)
3487     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3488   DrawPathLineTo(wand,RelativePathMode,x,y);
3489 }
3490 \f
3491 /*
3492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3493 %                                                                             %
3494 %                                                                             %
3495 %                                                                             %
3496 %   D r a w P a t h L i n e T o H o r i z o n t a l A b s o l u t e           %
3497 %                                                                             %
3498 %                                                                             %
3499 %                                                                             %
3500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3501 %
3502 %  DrawPathLineToHorizontalAbsolute() draws a horizontal line path from the
3503 %  current point to the target point using absolute coordinates.  The target
3504 %  point then becomes the new current point.
3505 %
3506 %  The format of the DrawPathLineToHorizontalAbsolute method is:
3507 %
3508 %      void DrawPathLineToHorizontalAbsolute(DrawingWand *wand,
3509 %        const PathMode mode,const double x)
3510 %
3511 %  A description of each parameter follows:
3512 %
3513 %    o wand: the drawing wand.
3514 %
3515 %    o x: target x ordinate
3516 %
3517 */
3518
3519 static void DrawPathLineToHorizontal(DrawingWand *wand,const PathMode mode,
3520   const double x)
3521 {
3522   assert(wand != (DrawingWand *) NULL);
3523   assert(wand->signature == WandSignature);
3524   if (wand->debug != MagickFalse)
3525     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3526   if ((wand->path_operation != PathLineToHorizontalOperation) ||
3527       (wand->path_mode != mode))
3528     {
3529       wand->path_operation=PathLineToHorizontalOperation;
3530       wand->path_mode=mode;
3531       (void) MvgAutoWrapPrintf(wand,"%c%g",mode == AbsolutePathMode ?
3532         'H' : 'h',x);
3533     }
3534   else
3535     (void) MvgAutoWrapPrintf(wand," %g",x);
3536 }
3537
3538 WandExport void DrawPathLineToHorizontalAbsolute(DrawingWand *wand,
3539   const double x)
3540 {
3541   assert(wand != (DrawingWand *) NULL);
3542   assert(wand->signature == WandSignature);
3543   if (wand->debug != MagickFalse)
3544     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3545   DrawPathLineToHorizontal(wand,AbsolutePathMode,x);
3546 }
3547 \f
3548 /*
3549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3550 %                                                                             %
3551 %                                                                             %
3552 %                                                                             %
3553 %   D r a w P a t h L i n e T o H o r i z o n t a l R e l a t i v e           %
3554 %                                                                             %
3555 %                                                                             %
3556 %                                                                             %
3557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3558 %
3559 %  DrawPathLineToHorizontalRelative() draws a horizontal line path from the
3560 %  current point to the target point using relative coordinates.  The target
3561 %  point then becomes the new current point.
3562 %
3563 %  The format of the DrawPathLineToHorizontalRelative method is:
3564 %
3565 %      void DrawPathLineToHorizontalRelative(DrawingWand *wand,
3566 %        const double x)
3567 %
3568 %  A description of each parameter follows:
3569 %
3570 %    o wand: the drawing wand.
3571 %
3572 %    o x: target x ordinate
3573 %
3574 */
3575 WandExport void DrawPathLineToHorizontalRelative(DrawingWand *wand,
3576   const double x)
3577 {
3578   DrawPathLineToHorizontal(wand,RelativePathMode,x);
3579 }
3580 \f
3581 /*
3582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3583 %                                                                             %
3584 %                                                                             %
3585 %                                                                             %
3586 %   D r a w P a t h L i n e T o V e r t i c a l A b s o l u t e               %
3587 %                                                                             %
3588 %                                                                             %
3589 %                                                                             %
3590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3591 %
3592 %  DrawPathLineToVerticalAbsolute() draws a vertical line path from the
3593 %  current point to the target point using absolute coordinates.  The target
3594 %  point then becomes the new current point.
3595 %
3596 %  The format of the DrawPathLineToVerticalAbsolute method is:
3597 %
3598 %      void DrawPathLineToVerticalAbsolute(DrawingWand *wand,
3599 %        const double y)
3600 %
3601 %  A description of each parameter follows:
3602 %
3603 %    o wand: the drawing wand.
3604 %
3605 %    o y: target y ordinate
3606 %
3607 */
3608
3609 static void DrawPathLineToVertical(DrawingWand *wand,const PathMode mode,
3610   const double y)
3611 {
3612   assert(wand != (DrawingWand *) NULL);
3613   assert(wand->signature == WandSignature);
3614   if (wand->debug != MagickFalse)
3615     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3616   if ((wand->path_operation != PathLineToVerticalOperation) ||
3617       (wand->path_mode != mode))
3618     {
3619       wand->path_operation=PathLineToVerticalOperation;
3620       wand->path_mode=mode;
3621       (void) MvgAutoWrapPrintf(wand,"%c%g",mode == AbsolutePathMode ?
3622         'V' : 'v',y);
3623     }
3624   else
3625     (void) MvgAutoWrapPrintf(wand," %g",y);
3626 }
3627
3628 WandExport void DrawPathLineToVerticalAbsolute(DrawingWand *wand,const double y)
3629 {
3630   assert(wand != (DrawingWand *) NULL);
3631   assert(wand->signature == WandSignature);
3632   if (wand->debug != MagickFalse)
3633     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3634   DrawPathLineToVertical(wand,AbsolutePathMode,y);
3635 }
3636 \f
3637 /*
3638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3639 %                                                                             %
3640 %                                                                             %
3641 %                                                                             %
3642 %   D r a w P a t h L i n e T o V e r t i c a l R e l a t i v e               %
3643 %                                                                             %
3644 %                                                                             %
3645 %                                                                             %
3646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3647 %
3648 %  DrawPathLineToVerticalRelative() draws a vertical line path from the
3649 %  current point to the target point using relative coordinates.  The target
3650 %  point then becomes the new current point.
3651 %
3652 %  The format of the DrawPathLineToVerticalRelative method is:
3653 %
3654 %      void DrawPathLineToVerticalRelative(DrawingWand *wand,
3655 %        const double y)
3656 %
3657 %  A description of each parameter follows:
3658 %
3659 %    o wand: the drawing wand.
3660 %
3661 %    o y: target y ordinate
3662 %
3663 */
3664 WandExport void DrawPathLineToVerticalRelative(DrawingWand *wand,const double y)
3665 {
3666   assert(wand != (DrawingWand *) NULL);
3667   assert(wand->signature == WandSignature);
3668   if (wand->debug != MagickFalse)
3669     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3670   DrawPathLineToVertical(wand,RelativePathMode,y);
3671 }
3672 /*
3673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674 %                                                                             %
3675 %                                                                             %
3676 %                                                                             %
3677 %   D r a w P a t h M o v e T o A b s o l u t e                               %
3678 %                                                                             %
3679 %                                                                             %
3680 %                                                                             %
3681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682 %
3683 %  DrawPathMoveToAbsolute() starts a new sub-path at the given coordinate
3684 %  using absolute coordinates. The current point then becomes the
3685 %  specified coordinate.
3686 %
3687 %  The format of the DrawPathMoveToAbsolute method is:
3688 %
3689 %      void DrawPathMoveToAbsolute(DrawingWand *wand,const double x,
3690 %        const double y)
3691 %
3692 %  A description of each parameter follows:
3693 %
3694 %    o wand: the drawing wand.
3695 %
3696 %    o x: target x ordinate
3697 %
3698 %    o y: target y ordinate
3699 %
3700 */
3701
3702 static void DrawPathMoveTo(DrawingWand *wand,const PathMode mode,const double x,
3703   const double y)
3704 {
3705   assert(wand != (DrawingWand *) NULL);
3706   assert(wand->signature == WandSignature);
3707   if (wand->debug != MagickFalse)
3708     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3709   if ((wand->path_operation != PathMoveToOperation) ||
3710       (wand->path_mode != mode))
3711     {
3712       wand->path_operation=PathMoveToOperation;
3713       wand->path_mode=mode;
3714       (void) MvgAutoWrapPrintf(wand,"%c%g,%g",mode == AbsolutePathMode ?
3715         'M' : 'm',x,y);
3716     }
3717   else
3718     (void) MvgAutoWrapPrintf(wand," %g,%g",x,y);
3719 }
3720
3721 WandExport void DrawPathMoveToAbsolute(DrawingWand *wand,const double x,
3722   const double y)
3723 {
3724   assert(wand != (DrawingWand *) NULL);
3725   assert(wand->signature == WandSignature);
3726   if (wand->debug != MagickFalse)
3727     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3728   DrawPathMoveTo(wand,AbsolutePathMode,x,y);
3729 }
3730 \f
3731 /*
3732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3733 %                                                                             %
3734 %                                                                             %
3735 %                                                                             %
3736 %   D r a w P a t h M o v e T o R e l a t i v e                               %
3737 %                                                                             %
3738 %                                                                             %
3739 %                                                                             %
3740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3741 %
3742 %  DrawPathMoveToRelative() starts a new sub-path at the given coordinate using
3743 %  relative coordinates. The current point then becomes the specified
3744 %  coordinate.
3745 %
3746 %  The format of the DrawPathMoveToRelative method is:
3747 %
3748 %      void DrawPathMoveToRelative(DrawingWand *wand,const double x,
3749 %        const double y)
3750 %
3751 %  A description of each parameter follows:
3752 %
3753 %    o wand: the drawing wand.
3754 %
3755 %    o x: target x ordinate
3756 %
3757 %    o y: target y ordinate
3758 %
3759 */
3760 WandExport void DrawPathMoveToRelative(DrawingWand *wand,const double x,
3761   const double y)
3762 {
3763   assert(wand != (DrawingWand *) NULL);
3764   assert(wand->signature == WandSignature);
3765   if (wand->debug != MagickFalse)
3766     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3767   DrawPathMoveTo(wand,RelativePathMode,x,y);
3768 }
3769 \f
3770 /*
3771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3772 %                                                                             %
3773 %                                                                             %
3774 %                                                                             %
3775 %   D r a w P a t h S t a r t                                                 %
3776 %                                                                             %
3777 %                                                                             %
3778 %                                                                             %
3779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3780 %
3781 %  DrawPathStart() declares the start of a path drawing list which is terminated
3782 %  by a matching DrawPathFinish() command. All other DrawPath commands must
3783 %  be enclosed between a DrawPathStart() and a DrawPathFinish() command. This
3784 %  is because path drawing commands are subordinate commands and they do not
3785 %  function by themselves.
3786 %
3787 %  The format of the DrawPathStart method is:
3788 %
3789 %      void DrawPathStart(DrawingWand *wand)
3790 %
3791 %  A description of each parameter follows:
3792 %
3793 %    o wand: the drawing wand.
3794 %
3795 */
3796 WandExport void DrawPathStart(DrawingWand *wand)
3797 {
3798   assert(wand != (DrawingWand *) NULL);
3799   assert(wand->signature == WandSignature);
3800   if (wand->debug != MagickFalse)
3801     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3802   (void) MvgPrintf(wand,"path '");
3803   wand->path_operation=PathDefaultOperation;
3804   wand->path_mode=DefaultPathMode;
3805 }
3806 \f
3807 /*
3808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3809 %                                                                             %
3810 %                                                                             %
3811 %                                                                             %
3812 %   D r a w P o i n t                                                         %
3813 %                                                                             %
3814 %                                                                             %
3815 %                                                                             %
3816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3817 %
3818 %  DrawPoint() draws a point using the current fill color.
3819 %
3820 %  The format of the DrawPoint method is:
3821 %
3822 %      void DrawPoint(DrawingWand *wand,const double x,const double y)
3823 %
3824 %  A description of each parameter follows:
3825 %
3826 %    o wand: the drawing wand.
3827 %
3828 %    o x: target x coordinate
3829 %
3830 %    o y: target y coordinate
3831 %
3832 */
3833 WandExport void DrawPoint(DrawingWand *wand,const double x,const double y)
3834 {
3835   assert(wand != (DrawingWand *) NULL);
3836   assert(wand->signature == WandSignature);
3837   if (wand->debug != MagickFalse)
3838     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3839   (void) MvgPrintf(wand,"point %g,%g\n",x,y);
3840 }
3841 \f
3842 /*
3843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3844 %                                                                             %
3845 %                                                                             %
3846 %                                                                             %
3847 %   D r a w P o l y g o n                                                     %
3848 %                                                                             %
3849 %                                                                             %
3850 %                                                                             %
3851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3852 %
3853 %  DrawPolygon() draws a polygon using the current stroke, stroke width, and
3854 %  fill color or texture, using the specified array of coordinates.
3855 %
3856 %  The format of the DrawPolygon method is:
3857 %
3858 %      void DrawPolygon(DrawingWand *wand,
3859 %        const unsigned long number_coordinates,const PointInfo *coordinates)
3860 %
3861 %  A description of each parameter follows:
3862 %
3863 %    o wand: the drawing wand.
3864 %
3865 %    o number_coordinates: number of coordinates
3866 %
3867 %    o coordinates: coordinate array
3868 %
3869 */
3870 WandExport void DrawPolygon(DrawingWand *wand,
3871   const unsigned long number_coordinates,const PointInfo *coordinates)
3872 {
3873   assert(wand != (DrawingWand *) NULL);
3874   assert(wand->signature == WandSignature);
3875   if (wand->debug != MagickFalse)
3876     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3877   MvgAppendPointsCommand(wand,"polygon",number_coordinates,coordinates);
3878 }
3879 \f
3880 /*
3881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3882 %                                                                             %
3883 %                                                                             %
3884 %                                                                             %
3885 %   D r a w P o l y l i n e                                                   %
3886 %                                                                             %
3887 %                                                                             %
3888 %                                                                             %
3889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3890 %
3891 %  DrawPolyline() draws a polyline using the current stroke, stroke width, and
3892 %  fill color or texture, using the specified array of coordinates.
3893 %
3894 %  The format of the DrawPolyline method is:
3895 %
3896 %      void DrawPolyline(DrawingWand *wand,
3897 %        const unsigned long number_coordinates,const PointInfo *coordinates)
3898 %
3899 %  A description of each parameter follows:
3900 %
3901 %    o wand: the drawing wand.
3902 %
3903 %    o number_coordinates: number of coordinates
3904 %
3905 %    o coordinates: coordinate array
3906 %
3907 */
3908 WandExport void DrawPolyline(DrawingWand *wand,
3909   const unsigned long number_coordinates,const PointInfo *coordinates)
3910 {
3911   assert(wand != (DrawingWand *) NULL);
3912   assert(wand->signature == WandSignature);
3913   if (wand->debug != MagickFalse)
3914     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3915   MvgAppendPointsCommand(wand,"polyline",number_coordinates,coordinates);
3916 }
3917 \f
3918 /*
3919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3920 %                                                                             %
3921 %                                                                             %
3922 %                                                                             %
3923 %   D r a w P o p C l i p P a t h                                             %
3924 %                                                                             %
3925 %                                                                             %
3926 %                                                                             %
3927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3928 %
3929 %  DrawPopClipPath() terminates a clip path definition.
3930 %
3931 %  The format of the DrawPopClipPath method is:
3932 %
3933 %      void DrawPopClipPath(DrawingWand *wand)
3934 %
3935 %  A description of each parameter follows:
3936 %
3937 %    o wand: the drawing wand.
3938 %
3939 */
3940 WandExport void DrawPopClipPath(DrawingWand *wand)
3941 {
3942   assert(wand != (DrawingWand *) NULL);
3943   assert(wand->signature == WandSignature);
3944   if (wand->debug != MagickFalse)
3945     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3946   if (wand->indent_depth > 0)
3947     wand->indent_depth--;
3948   (void) MvgPrintf(wand,"pop clip-path\n");
3949 }
3950 \f
3951 /*
3952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3953 %                                                                             %
3954 %                                                                             %
3955 %                                                                             %
3956 %   D r a w P o p D e f s                                                     %
3957 %                                                                             %
3958 %                                                                             %
3959 %                                                                             %
3960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3961 %
3962 %  DrawPopDefs() terminates a definition list.
3963 %
3964 %  The format of the DrawPopDefs method is:
3965 %
3966 %      void DrawPopDefs(DrawingWand *wand)
3967 %
3968 %  A description of each parameter follows:
3969 %
3970 %    o wand: the drawing wand.
3971 %
3972 */
3973 WandExport void DrawPopDefs(DrawingWand *wand)
3974 {
3975   assert(wand != (DrawingWand *) NULL);
3976   assert(wand->signature == WandSignature);
3977   if (wand->debug != MagickFalse)
3978     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
3979   if (wand->indent_depth > 0)
3980     wand->indent_depth--;
3981   (void) MvgPrintf(wand,"pop defs\n");
3982 }
3983 \f
3984 /*
3985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3986 %                                                                             %
3987 %                                                                             %
3988 %                                                                             %
3989 %   D r a w P o p P a t t e r n                                               %
3990 %                                                                             %
3991 %                                                                             %
3992 %                                                                             %
3993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3994 %
3995 %  DrawPopPattern() terminates a pattern definition.
3996 %
3997 %  The format of the DrawPopPattern method is:
3998 %
3999 %      MagickBooleanType DrawPopPattern(DrawingWand *wand)
4000 %
4001 %  A description of each parameter follows:
4002 %
4003 %    o wand: the drawing wand.
4004 %
4005 */
4006 WandExport MagickBooleanType DrawPopPattern(DrawingWand *wand)
4007 {
4008   char
4009     geometry[MaxTextExtent],
4010     key[MaxTextExtent];
4011
4012   assert(wand != (DrawingWand *) NULL);
4013   assert(wand->signature == WandSignature);
4014   if (wand->debug != MagickFalse)
4015     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4016   if (wand->image == (Image *) NULL)
4017     ThrowDrawException(WandError,"ContainsNoImages",wand->name);
4018   if (wand->pattern_id == (const char *) NULL)
4019     {
4020       ThrowDrawException(DrawWarning,"NotCurrentlyPushingPatternDefinition",
4021         wand->name);
4022       return(MagickFalse);
4023     }
4024   (void) FormatMagickString(key,MaxTextExtent,"%s",wand->pattern_id);
4025   (void) SetImageArtifact(wand->image,key,wand->mvg+wand->pattern_offset);
4026   (void) FormatMagickString(geometry,MaxTextExtent,"%lux%lu%+ld%+ld",
4027     wand->pattern_bounds.width,wand->pattern_bounds.height,
4028     wand->pattern_bounds.x,wand->pattern_bounds.y);
4029   (void) SetImageArtifact(wand->image,key,geometry);
4030   wand->pattern_id=DestroyString(wand->pattern_id);
4031   wand->pattern_offset=0;
4032   wand->pattern_bounds.x=0;
4033   wand->pattern_bounds.y=0;
4034   wand->pattern_bounds.width=0;
4035   wand->pattern_bounds.height=0;
4036   wand->filter_off=MagickTrue;
4037   if (wand->indent_depth > 0)
4038     wand->indent_depth--;
4039   (void) MvgPrintf(wand,"pop pattern\n");
4040   return(MagickTrue);
4041 }
4042 \f
4043 /*
4044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4045 %                                                                             %
4046 %                                                                             %
4047 %                                                                             %
4048 %   D r a w P u s h C l i p P a t h                                           %
4049 %                                                                             %
4050 %                                                                             %
4051 %                                                                             %
4052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4053 %
4054 %  DrawPushClipPath() starts a clip path definition which is comprized of any
4055 %  number of drawing commands and terminated by a DrawPopClipPath() command.
4056 %
4057 %  The format of the DrawPushClipPath method is:
4058 %
4059 %      void DrawPushClipPath(DrawingWand *wand,const char *clip_mask_id)
4060 %
4061 %  A description of each parameter follows:
4062 %
4063 %    o wand: the drawing wand.
4064 %
4065 %    o clip_mask_id: string identifier to associate with the clip path for
4066 %      later use.
4067 %
4068 */
4069 WandExport void DrawPushClipPath(DrawingWand *wand,const char *clip_mask_id)
4070 {
4071   assert(wand != (DrawingWand *) NULL);
4072   assert(wand->signature == WandSignature);
4073   if (wand->debug != MagickFalse)
4074     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4075   assert(clip_mask_id != (const char *) NULL);
4076   (void) MvgPrintf(wand,"push clip-path %s\n",clip_mask_id);
4077   wand->indent_depth++;
4078 }
4079 \f
4080 /*
4081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4082 %                                                                             %
4083 %                                                                             %
4084 %                                                                             %
4085 %   D r a w P u s h D e f s                                                   %
4086 %                                                                             %
4087 %                                                                             %
4088 %                                                                             %
4089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4090 %
4091 %  DrawPushDefs() indicates that commands up to a terminating DrawPopDefs()
4092 %  command create named elements (e.g. clip-paths, textures, etc.) which
4093 %  may safely be processed earlier for the sake of efficiency.
4094 %
4095 %  The format of the DrawPushDefs method is:
4096 %
4097 %      void DrawPushDefs(DrawingWand *wand)
4098 %
4099 %  A description of each parameter follows:
4100 %
4101 %    o wand: the drawing wand.
4102 %
4103 */
4104 WandExport void DrawPushDefs(DrawingWand *wand)
4105 {
4106   assert(wand != (DrawingWand *) NULL);
4107   assert(wand->signature == WandSignature);
4108   if (wand->debug != MagickFalse)
4109     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4110   (void) MvgPrintf(wand,"push defs\n");
4111   wand->indent_depth++;
4112 }
4113 \f
4114 /*
4115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4116 %                                                                             %
4117 %                                                                             %
4118 %                                                                             %
4119 %   D r a w P u s h P a t t e r n                                             %
4120 %                                                                             %
4121 %                                                                             %
4122 %                                                                             %
4123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4124 %
4125 %  DrawPushPattern() indicates that subsequent commands up to a
4126 %  DrawPopPattern() command comprise the definition of a named pattern.
4127 %  The pattern space is assigned top left corner coordinates, a width
4128 %  and height, and becomes its own drawing space.  Anything which can
4129 %  be drawn may be used in a pattern definition.
4130 %  Named patterns may be used as stroke or brush definitions.
4131 %
4132 %  The format of the DrawPushPattern method is:
4133 %
4134 %      MagickBooleanType DrawPushPattern(DrawingWand *wand,
4135 %        const char *pattern_id,const double x,const double y,
4136 %        const double width,const double height)
4137 %
4138 %  A description of each parameter follows:
4139 %
4140 %    o wand: the drawing wand.
4141 %
4142 %    o pattern_id: pattern identification for later reference
4143 %
4144 %    o x: x ordinate of top left corner
4145 %
4146 %    o y: y ordinate of top left corner
4147 %
4148 %    o width: width of pattern space
4149 %
4150 %    o height: height of pattern space
4151 %
4152 */
4153 WandExport MagickBooleanType DrawPushPattern(DrawingWand *wand,
4154   const char *pattern_id,const double x,const double y,const double width,
4155   const double height)
4156 {
4157   assert(wand != (DrawingWand *) NULL);
4158   assert(wand->signature == WandSignature);
4159   if (wand->debug != MagickFalse)
4160     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4161   assert(pattern_id != (const char *) NULL);
4162   if (wand->pattern_id != NULL)
4163     {
4164       ThrowDrawException(DrawError,"AlreadyPushingPatternDefinition",
4165         wand->pattern_id);
4166       return(MagickFalse);
4167     }
4168   wand->filter_off=MagickTrue;
4169   (void) MvgPrintf(wand,"push pattern %s %g,%g %g,%g\n",pattern_id,x,y,
4170     width,height);
4171   wand->indent_depth++;
4172   wand->pattern_id=AcquireString(pattern_id);
4173   wand->pattern_bounds.x=(long) ceil(x-0.5);
4174   wand->pattern_bounds.y=(long) ceil(y-0.5);
4175   wand->pattern_bounds.width=(unsigned long) (width+0.5);
4176   wand->pattern_bounds.height=(unsigned long) (height+0.5);
4177   wand->pattern_offset=wand->mvg_length;
4178   return(MagickTrue);
4179 }
4180 \f
4181 /*
4182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4183 %                                                                             %
4184 %                                                                             %
4185 %                                                                             %
4186 %   D r a w R e c t a n g l e                                                 %
4187 %                                                                             %
4188 %                                                                             %
4189 %                                                                             %
4190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4191 %
4192 %  DrawRectangle() draws a rectangle given two coordinates and using the
4193 %  current stroke, stroke width, and fill settings.
4194 %
4195 %  The format of the DrawRectangle method is:
4196 %
4197 %      void DrawRectangle(DrawingWand *wand,const double x1,
4198 %        const double y1,const double x2,const double y2)
4199 %
4200 %  A description of each parameter follows:
4201 %
4202 %    o x1: x ordinate of first coordinate
4203 %
4204 %    o y1: y ordinate of first coordinate
4205 %
4206 %    o x2: x ordinate of second coordinate
4207 %
4208 %    o y2: y ordinate of second coordinate
4209 %
4210 */
4211 WandExport void DrawRectangle(DrawingWand *wand,const double x1,const double y1,
4212   const double x2,const double y2)
4213 {
4214   assert(wand != (DrawingWand *) NULL);
4215   assert(wand->signature == WandSignature);
4216   if (wand->debug != MagickFalse)
4217     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4218   (void) MvgPrintf(wand,"rectangle %g,%g %g,%g\n",x1,y1,x2,y2);
4219 }
4220 \f
4221 /*
4222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4223 %                                                                             %
4224 %                                                                             %
4225 %                                                                             %
4226 +   D r a w R e n d e r                                                       %
4227 %                                                                             %
4228 %                                                                             %
4229 %                                                                             %
4230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4231 %
4232 %  DrawRender() renders all preceding drawing commands onto the image.
4233 %
4234 %  The format of the DrawRender method is:
4235 %
4236 %      MagickBooleanType DrawRender(DrawingWand *wand)
4237 %
4238 %  A description of each parameter follows:
4239 %
4240 %    o wand: the drawing wand.
4241 %
4242 */
4243 WandExport MagickBooleanType DrawRender(DrawingWand *wand)
4244 {
4245   MagickBooleanType
4246     status;
4247
4248   assert(wand != (const DrawingWand *) NULL);
4249   assert(wand->signature == WandSignature);
4250   if (wand->debug != MagickFalse)
4251     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4252   CurrentContext->primitive=wand->mvg;
4253   if (wand->debug != MagickFalse)
4254     (void) LogMagickEvent(DrawEvent,GetMagickModule(),"MVG:\n'%s'\n",wand->mvg);
4255   if (wand->image == (Image *) NULL)
4256     ThrowDrawException(WandError,"ContainsNoImages",wand->name);
4257   status=DrawImage(wand->image,CurrentContext);
4258   InheritException(wand->exception,&wand->image->exception);
4259   CurrentContext->primitive=(char *) NULL;
4260   return(status);
4261 }
4262 \f
4263 /*
4264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4265 %                                                                             %
4266 %                                                                             %
4267 %                                                                             %
4268 %   D r a w R e s e t V e c t o r G r a p h i c s                             %
4269 %                                                                             %
4270 %                                                                             %
4271 %                                                                             %
4272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4273 %
4274 %  DrawResetVectorGraphics() resets the vector graphics associated with the
4275 %  specified wand.
4276 %
4277 %  The format of the DrawResetVectorGraphics method is:
4278 %
4279 %      void DrawResetVectorGraphics(DrawingWand *wand)
4280 %
4281 %  A description of each parameter follows:
4282 %
4283 %    o wand: the drawing wand.
4284 %
4285 */
4286 WandExport void DrawResetVectorGraphics(DrawingWand *wand)
4287 {
4288   assert(wand != (DrawingWand *) NULL);
4289   assert(wand->signature == WandSignature);
4290   if (wand->debug != MagickFalse)
4291     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4292   if (wand->mvg != (char *) NULL)
4293     wand->mvg=DestroyString(wand->mvg);
4294   wand->mvg_alloc=0;
4295   wand->mvg_length=0;
4296   wand->mvg_width=0;
4297 }
4298 \f
4299 /*
4300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4301 %                                                                             %
4302 %                                                                             %
4303 %                                                                             %
4304 %   D r a w R o t a t e                                                       %
4305 %                                                                             %
4306 %                                                                             %
4307 %                                                                             %
4308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4309 %
4310 %  DrawRotate() applies the specified rotation to the current coordinate space.
4311 %
4312 %  The format of the DrawRotate method is:
4313 %
4314 %      void DrawRotate(DrawingWand *wand,const double degrees)
4315 %
4316 %  A description of each parameter follows:
4317 %
4318 %    o wand: the drawing wand.
4319 %
4320 %    o degrees: degrees of rotation
4321 %
4322 */
4323 WandExport void DrawRotate(DrawingWand *wand,const double degrees)
4324 {
4325   AffineMatrix
4326     affine;
4327
4328   assert(wand != (DrawingWand *) NULL);
4329   assert(wand->signature == WandSignature);
4330   if (wand->debug != MagickFalse)
4331     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4332   GetAffineMatrix(&affine);
4333   affine.sx=cos(DegreesToRadians(fmod(degrees,360.0)));
4334   affine.rx=sin(DegreesToRadians(fmod(degrees,360.0)));
4335   affine.ry=(-sin(DegreesToRadians(fmod(degrees,360.0))));
4336   affine.sy=cos(DegreesToRadians(fmod(degrees,360.0)));
4337   AdjustAffine(wand,&affine);
4338   (void) MvgPrintf(wand,"rotate %g\n",degrees);
4339 }
4340 \f
4341 /*
4342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4343 %                                                                             %
4344 %                                                                             %
4345 %                                                                             %
4346 %   D r a w R o u n d R e c t a n g l e                                       %
4347 %                                                                             %
4348 %                                                                             %
4349 %                                                                             %
4350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4351 %
4352 %  DrawRoundRectangle() draws a rounted rectangle given two coordinates,
4353 %  x & y corner radiuses and using the current stroke, stroke width,
4354 %  and fill settings.
4355 %
4356 %  The format of the DrawRoundRectangle method is:
4357 %
4358 %      void DrawRoundRectangle(DrawingWand *wand,double x1,double y1,
4359 %        double x2,double y2,double rx,double ry)
4360 %
4361 %  A description of each parameter follows:
4362 %
4363 %    o wand: the drawing wand.
4364 %
4365 %    o x1: x ordinate of first coordinate
4366 %
4367 %    o y1: y ordinate of first coordinate
4368 %
4369 %    o x2: x ordinate of second coordinate
4370 %
4371 %    o y2: y ordinate of second coordinate
4372 %
4373 %    o rx: radius of corner in horizontal direction
4374 %
4375 %    o ry: radius of corner in vertical direction
4376 %
4377 */
4378 WandExport void DrawRoundRectangle(DrawingWand *wand,double x1,double y1,
4379   double x2,double y2,double rx,double ry)
4380 {
4381   assert(wand != (DrawingWand *) NULL);
4382   assert(wand->signature == WandSignature);
4383   if (wand->debug != MagickFalse)
4384     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4385   (void) MvgPrintf(wand,"roundrectangle %g,%g %g,%g %g,%g\n",x1,y1,x2,y2,rx,ry);
4386 }
4387 \f
4388 /*
4389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4390 %                                                                             %
4391 %                                                                             %
4392 %                                                                             %
4393 %   D r a w S c a l e                                                         %
4394 %                                                                             %
4395 %                                                                             %
4396 %                                                                             %
4397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4398 %
4399 %  DrawScale() adjusts the scaling factor to apply in the horizontal and
4400 %  vertical directions to the current coordinate space.
4401 %
4402 %  The format of the DrawScale method is:
4403 %
4404 %      void DrawScale(DrawingWand *wand,const double x,const double y)
4405 %
4406 %  A description of each parameter follows:
4407 %
4408 %    o wand: the drawing wand.
4409 %
4410 %    o x: horizontal scale factor
4411 %
4412 %    o y: vertical scale factor
4413 %
4414 */
4415 WandExport void DrawScale(DrawingWand *wand,const double x,const double y)
4416 {
4417   AffineMatrix
4418     affine;
4419
4420   assert(wand != (DrawingWand *) NULL);
4421   assert(wand->signature == WandSignature);
4422   if (wand->debug != MagickFalse)
4423     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4424   GetAffineMatrix(&affine);
4425   affine.sx=x;
4426   affine.sy=y;
4427   AdjustAffine(wand,&affine);
4428   (void) MvgPrintf(wand,"scale %g,%g\n",x,y);
4429 }
4430 \f
4431 /*
4432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4433 %                                                                             %
4434 %                                                                             %
4435 %                                                                             %
4436 %   D r a w S e t B o r d e r C o l o r                                       %
4437 %                                                                             %
4438 %                                                                             %
4439 %                                                                             %
4440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4441 %
4442 %  DrawSetBorderColor() sets the border color to be used for drawing bordered
4443 %  objects.
4444 %
4445 %  The format of the DrawSetBorderColor method is:
4446 %
4447 %      void DrawSetBorderColor(DrawingWand *wand,const PixelWand *border_wand)
4448 %
4449 %  A description of each parameter follows:
4450 %
4451 %    o wand: the drawing wand.
4452 %
4453 %    o border_wand: border wand.
4454 %
4455 */
4456
4457 static inline MagickBooleanType IsColorEqual(const PixelPacket *p,
4458   const PixelPacket *q)
4459 {
4460   if (p->red != q->red)
4461     return(MagickFalse);
4462   if (p->green != q->green)
4463     return(MagickFalse);
4464   if (p->blue != q->blue)
4465     return(MagickFalse);
4466   if (p->opacity != q->opacity)
4467     return(MagickFalse);
4468   return(MagickTrue);
4469 }
4470
4471 WandExport void DrawSetBorderColor(DrawingWand *wand,const PixelWand *border_wand)
4472 {
4473   PixelPacket
4474     *current_border,
4475     border_color,
4476     new_border;
4477
4478   assert(wand != (DrawingWand *) NULL);
4479   assert(wand->signature == WandSignature);
4480   if (wand->debug != MagickFalse)
4481     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4482   assert(border_wand != (const PixelWand *) NULL);
4483   PixelGetQuantumColor(border_wand,&border_color);
4484   new_border=border_color;
4485   current_border=(&CurrentContext->border_color);
4486   if ((wand->filter_off != MagickFalse) ||
4487       (IsColorEqual(current_border,&new_border) == MagickFalse))
4488     {
4489       CurrentContext->border_color=new_border;
4490       (void) MvgPrintf(wand,"border-color '");
4491       MvgAppendColor(wand,&border_color);
4492       (void) MvgPrintf(wand,"'\n");
4493     }
4494 }
4495 \f
4496 /*
4497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4498 %                                                                             %
4499 %                                                                             %
4500 %                                                                             %
4501 %   D r a w S e t C l i p P a t h                                             %
4502 %                                                                             %
4503 %                                                                             %
4504 %                                                                             %
4505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4506 %
4507 %  DrawSetClipPath() associates a named clipping path with the image.  Only
4508 %  the areas drawn on by the clipping path will be modified as long as it
4509 %  remains in effect.
4510 %
4511 %  The format of the DrawSetClipPath method is:
4512 %
4513 %      MagickBooleanType DrawSetClipPath(DrawingWand *wand,
4514 %        const char *clip_mask)
4515 %
4516 %  A description of each parameter follows:
4517 %
4518 %    o wand: the drawing wand.
4519 %
4520 %    o clip_mask: name of clipping path to associate with image
4521 %
4522 */
4523 WandExport MagickBooleanType DrawSetClipPath(DrawingWand *wand,
4524   const char *clip_mask)
4525 {
4526   if (wand->debug != MagickFalse)
4527     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clip_mask);
4528   assert(wand != (DrawingWand *) NULL);
4529   assert(wand->signature == WandSignature);
4530   assert(clip_mask != (const char *) NULL);
4531   if ((CurrentContext->clip_mask == (const char *) NULL) ||
4532       (wand->filter_off != MagickFalse) ||
4533       (LocaleCompare(CurrentContext->clip_mask,clip_mask) != 0))
4534     {
4535       (void) CloneString(&CurrentContext->clip_mask,clip_mask);
4536 #if DRAW_BINARY_IMPLEMENTATION
4537       if (wand->image == (Image *) NULL)
4538         ThrowDrawException(WandError,"ContainsNoImages",wand->name);
4539       (void) DrawClipPath(wand->image,CurrentContext,CurrentContext->clip_mask);
4540 #endif
4541       (void) MvgPrintf(wand,"clip-path url(#%s)\n",clip_mask);
4542     }
4543   return(MagickTrue);
4544 }
4545 \f
4546 /*
4547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548 %                                                                             %
4549 %                                                                             %
4550 %                                                                             %
4551 %   D r a w S e t C l i p R u l e                                             %
4552 %                                                                             %
4553 %                                                                             %
4554 %                                                                             %
4555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556 %
4557 %  DrawSetClipRule() set the polygon fill rule to be used by the clipping path.
4558 %
4559 %  The format of the DrawSetClipRule method is:
4560 %
4561 %      void DrawSetClipRule(DrawingWand *wand,const FillRule fill_rule)
4562 %
4563 %  A description of each parameter follows:
4564 %
4565 %    o wand: the drawing wand.
4566 %
4567 %    o fill_rule: fill rule (EvenOddRule or NonZeroRule)
4568 %
4569 */
4570 WandExport void DrawSetClipRule(DrawingWand *wand,const FillRule fill_rule)
4571 {
4572   assert(wand != (DrawingWand *) NULL);
4573   assert(wand->signature == WandSignature);
4574   if (wand->debug != MagickFalse)
4575     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4576   if ((wand->filter_off != MagickFalse) ||
4577       (CurrentContext->fill_rule != fill_rule))
4578     {
4579       CurrentContext->fill_rule=fill_rule;
4580       (void) MvgPrintf(wand, "clip-rule '%s'\n",MagickOptionToMnemonic(
4581         MagickFillRuleOptions,(long) fill_rule));
4582     }
4583 }
4584 \f
4585 /*
4586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4587 %                                                                             %
4588 %                                                                             %
4589 %                                                                             %
4590 %   D r a w S e t C l i p U n i t s                                           %
4591 %                                                                             %
4592 %                                                                             %
4593 %                                                                             %
4594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4595 %
4596 %  DrawSetClipUnits() sets the interpretation of clip path units.
4597 %
4598 %  The format of the DrawSetClipUnits method is:
4599 %
4600 %      void DrawSetClipUnits(DrawingWand *wand,
4601 %        const ClipPathUnits clip_units)
4602 %
4603 %  A description of each parameter follows:
4604 %
4605 %    o wand: the drawing wand.
4606 %
4607 %    o clip_units: units to use (UserSpace, UserSpaceOnUse, or
4608 %      ObjectBoundingBox)
4609 %
4610 */
4611 WandExport void DrawSetClipUnits(DrawingWand *wand,
4612   const ClipPathUnits clip_units)
4613 {
4614   assert(wand != (DrawingWand *) NULL);
4615   assert(wand->signature == WandSignature);
4616   if (wand->debug != MagickFalse)
4617     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4618   if ((wand->filter_off != MagickFalse) ||
4619       (CurrentContext->clip_units != clip_units))
4620     {
4621       CurrentContext->clip_units=clip_units;
4622       if (clip_units == ObjectBoundingBox)
4623         {
4624           AffineMatrix
4625             affine;
4626
4627           GetAffineMatrix(&affine);
4628           affine.sx=CurrentContext->bounds.x2;
4629           affine.sy=CurrentContext->bounds.y2;
4630           affine.tx=CurrentContext->bounds.x1;
4631           affine.ty=CurrentContext->bounds.y1;
4632           AdjustAffine(wand,&affine);
4633         }
4634       (void) MvgPrintf(wand, "clip-units '%s'\n",MagickOptionToMnemonic(
4635         MagickClipPathOptions,(long) clip_units));
4636     }
4637 }
4638 \f
4639 /*
4640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4641 %                                                                             %
4642 %                                                                             %
4643 %                                                                             %
4644 %   D r a w S e t F i l l C o l o r                                           %
4645 %                                                                             %
4646 %                                                                             %
4647 %                                                                             %
4648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4649 %
4650 %  DrawSetFillColor() sets the fill color to be used for drawing filled objects.
4651 %
4652 %  The format of the DrawSetFillColor method is:
4653 %
4654 %      void DrawSetFillColor(DrawingWand *wand,const PixelWand *fill_wand)
4655 %
4656 %  A description of each parameter follows:
4657 %
4658 %    o wand: the drawing wand.
4659 %
4660 %    o fill_wand: fill wand.
4661 %
4662 */
4663 WandExport void DrawSetFillColor(DrawingWand *wand,const PixelWand *fill_wand)
4664 {
4665   PixelPacket
4666     *current_fill,
4667     fill_color,
4668     new_fill;
4669
4670   assert(wand != (DrawingWand *) NULL);
4671   assert(wand->signature == WandSignature);
4672   if (wand->debug != MagickFalse)
4673     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4674   assert(fill_wand != (const PixelWand *) NULL);
4675   PixelGetQuantumColor(fill_wand,&fill_color);
4676   new_fill=fill_color;
4677   current_fill=(&CurrentContext->fill);
4678   if ((wand->filter_off != MagickFalse) ||
4679       (IsColorEqual(current_fill,&new_fill) == MagickFalse))
4680     {
4681       CurrentContext->fill=new_fill;
4682       (void) MvgPrintf(wand,"fill '");
4683       MvgAppendColor(wand,&fill_color);
4684       (void) MvgPrintf(wand,"'\n");
4685     }
4686 }
4687 \f
4688 /*
4689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4690 %                                                                             %
4691 %                                                                             %
4692 %                                                                             %
4693 %   D r a w S e t F i l l O p a c i t y                                       %
4694 %                                                                             %
4695 %                                                                             %
4696 %                                                                             %
4697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698 %
4699 %  DrawSetFillOpacity() sets the opacity to use when drawing using the fill
4700 %  color or fill texture.  Fully opaque is 1.0.
4701 %
4702 %  The format of the DrawSetFillOpacity method is:
4703 %
4704 %      void DrawSetFillOpacity(DrawingWand *wand,const double fill_opacity)
4705 %
4706 %  A description of each parameter follows:
4707 %
4708 %    o wand: the drawing wand.
4709 %
4710 %    o fill_opacity: fill opacity
4711 %
4712 */
4713 WandExport void DrawSetFillOpacity(DrawingWand *wand,const double fill_opacity)
4714 {
4715   Quantum
4716     opacity;
4717
4718   assert(wand != (DrawingWand *) NULL);
4719   assert(wand->signature == WandSignature);
4720   if (wand->debug != MagickFalse)
4721     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4722   opacity=RoundToQuantum((double) QuantumRange*(1.0-fill_opacity));
4723   if ((wand->filter_off != MagickFalse) ||
4724       (CurrentContext->fill.opacity != opacity))
4725     {
4726       CurrentContext->fill.opacity=opacity;
4727       (void) MvgPrintf(wand,"fill-opacity %g\n",fill_opacity);
4728     }
4729 }
4730 \f
4731 /*
4732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4733 %                                                                             %
4734 %                                                                             %
4735 %                                                                             %
4736 %   D r a w S e t O p a c i t y                                               %
4737 %                                                                             %
4738 %                                                                             %
4739 %                                                                             %
4740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4741 %
4742 %  DrawSetOpacity() sets the opacity to use when drawing using the fill or
4743 %  stroke color or texture.  Fully opaque is 1.0.
4744 %
4745 %  The format of the DrawSetOpacity method is:
4746 %
4747 %      void DrawSetOpacity(DrawingWand *wand,const double opacity)
4748 %
4749 %  A description of each parameter follows:
4750 %
4751 %    o wand: the drawing wand.
4752 %
4753 %    o opacity: fill opacity
4754 %
4755 */
4756 WandExport void DrawSetOpacity(DrawingWand *wand,const double opacity)
4757 {
4758   Quantum
4759     quantum_opacity;
4760
4761   assert(wand != (DrawingWand *) NULL);
4762   assert(wand->signature == WandSignature);
4763   if (wand->debug != MagickFalse)
4764     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4765   quantum_opacity=RoundToQuantum((double) QuantumRange*(1.0-opacity));
4766   if ((wand->filter_off != MagickFalse) ||
4767       (CurrentContext->opacity != quantum_opacity))
4768     {
4769       CurrentContext->opacity=opacity;
4770       (void) MvgPrintf(wand,"opacity %g\n",opacity);
4771     }
4772 }
4773 \f
4774 /*
4775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4776 %                                                                             %
4777 %                                                                             %
4778 %                                                                             %
4779 %   D r a w S e t F i l l P a t t e r n U R L                                 %
4780 %                                                                             %
4781 %                                                                             %
4782 %                                                                             %
4783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4784 %
4785 %  DrawSetFillPatternURL() sets the URL to use as a fill pattern for filling
4786 %  objects. Only local URLs ("#identifier") are supported at this time. These
4787 %  local URLs are normally created by defining a named fill pattern with
4788 %  DrawPushPattern/DrawPopPattern.
4789 %
4790 %  The format of the DrawSetFillPatternURL method is:
4791 %
4792 %      MagickBooleanType DrawSetFillPatternURL(DrawingWand *wand,
4793 %        const char *fill_url)
4794 %
4795 %  A description of each parameter follows:
4796 %
4797 %    o wand: the drawing wand.
4798 %
4799 %    o fill_url: URL to use to obtain fill pattern.
4800 %
4801 */
4802 WandExport MagickBooleanType DrawSetFillPatternURL(DrawingWand *wand,
4803   const char *fill_url)
4804 {
4805   char
4806     pattern[MaxTextExtent],
4807     pattern_spec[MaxTextExtent];
4808
4809   assert(wand != (DrawingWand *) NULL);
4810   assert(wand->signature == WandSignature);
4811   if (wand->debug != MagickFalse)
4812     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",fill_url);
4813   if (wand->image == (Image *) NULL)
4814     ThrowDrawException(WandError,"ContainsNoImages",wand->name);
4815   assert(fill_url != (const char *) NULL);
4816   if (*fill_url != '#')
4817     {
4818       ThrowDrawException(DrawError,"NotARelativeURL",fill_url);
4819       return(MagickFalse);
4820     }
4821   (void) FormatMagickString(pattern,MaxTextExtent,"%s",fill_url+1);
4822   if (GetImageArtifact(wand->image,pattern) == (const char *) NULL)
4823     {
4824       ThrowDrawException(DrawError,"URLNotFound",fill_url)
4825       return(MagickFalse);
4826     }
4827   (void) FormatMagickString(pattern_spec,MaxTextExtent,"url(%s)",fill_url);
4828 #if DRAW_BINARY_IMPLEMENTATION
4829   DrawPatternPath(wand->image,CurrentContext,pattern_spec,
4830     &CurrentContext->fill_pattern);
4831 #endif
4832   if (CurrentContext->fill.opacity != (Quantum) TransparentOpacity)
4833     CurrentContext->fill.opacity=CurrentContext->opacity;
4834   (void) MvgPrintf(wand,"fill %s\n",pattern_spec);
4835   return(MagickTrue);
4836 }
4837 \f
4838 /*
4839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4840 %                                                                             %
4841 %                                                                             %
4842 %                                                                             %
4843 %   D r a w S e t F i l l R u l e                                             %
4844 %                                                                             %
4845 %                                                                             %
4846 %                                                                             %
4847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4848 %
4849 %  DrawSetFillRule() sets the fill rule to use while drawing polygons.
4850 %
4851 %  The format of the DrawSetFillRule method is:
4852 %
4853 %      void DrawSetFillRule(DrawingWand *wand,const FillRule fill_rule)
4854 %
4855 %  A description of each parameter follows:
4856 %
4857 %    o wand: the drawing wand.
4858 %
4859 %    o fill_rule: fill rule (EvenOddRule or NonZeroRule)
4860 %
4861 */
4862 WandExport void DrawSetFillRule(DrawingWand *wand,const FillRule fill_rule)
4863 {
4864   assert(wand != (DrawingWand *) NULL);
4865   assert(wand->signature == WandSignature);
4866   if (wand->debug != MagickFalse)
4867     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4868   if ((wand->filter_off != MagickFalse) ||
4869       (CurrentContext->fill_rule != fill_rule))
4870     {
4871       CurrentContext->fill_rule=fill_rule;
4872       (void) MvgPrintf(wand, "fill-rule '%s'\n",MagickOptionToMnemonic(
4873         MagickFillRuleOptions,(long) fill_rule));
4874     }
4875 }
4876 \f
4877 /*
4878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4879 %                                                                             %
4880 %                                                                             %
4881 %                                                                             %
4882 %   D r a w S e t F o n t                                                     %
4883 %                                                                             %
4884 %                                                                             %
4885 %                                                                             %
4886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4887 %
4888 %  DrawSetFont() sets the fully-sepecified font to use when annotating with
4889 %  text.
4890 %
4891 %  The format of the DrawSetFont method is:
4892 %
4893 %      MagickBooleanType DrawSetFont(DrawingWand *wand,const char *font_name)
4894 %
4895 %  A description of each parameter follows:
4896 %
4897 %    o wand: the drawing wand.
4898 %
4899 %    o font_name: font name
4900 %
4901 */
4902 WandExport MagickBooleanType DrawSetFont(DrawingWand *wand,
4903   const char *font_name)
4904 {
4905   assert(wand != (DrawingWand *) NULL);
4906   assert(wand->signature == WandSignature);
4907   if (wand->debug != MagickFalse)
4908     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4909   assert(font_name != (const char *) NULL);
4910   if ((wand->filter_off != MagickFalse) ||
4911       (CurrentContext->font == (char *) NULL) ||
4912       (LocaleCompare(CurrentContext->font,font_name) != 0))
4913     {
4914       (void) CloneString(&CurrentContext->font,font_name);
4915       (void) MvgPrintf(wand,"font '%s'\n",font_name);
4916     }
4917   return(MagickTrue);
4918 }
4919 \f
4920 /*
4921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4922 %                                                                             %
4923 %                                                                             %
4924 %                                                                             %
4925 %   D r a w S e t F o n t F a m i l y                                         %
4926 %                                                                             %
4927 %                                                                             %
4928 %                                                                             %
4929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4930 %
4931 %  DrawSetFontFamily() sets the font family to use when annotating with text.
4932 %
4933 %  The format of the DrawSetFontFamily method is:
4934 %
4935 %      MagickBooleanType DrawSetFontFamily(DrawingWand *wand,
4936 %        const char *font_family)
4937 %
4938 %  A description of each parameter follows:
4939 %
4940 %    o wand: the drawing wand.
4941 %
4942 %    o font_family: font family
4943 %
4944 */
4945 WandExport MagickBooleanType DrawSetFontFamily(DrawingWand *wand,
4946   const char *font_family)
4947 {
4948   assert(wand != (DrawingWand *) NULL);
4949   assert(wand->signature == WandSignature);
4950   if (wand->debug != MagickFalse)
4951     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4952   assert(font_family != (const char *) NULL);
4953   if ((wand->filter_off != MagickFalse) ||
4954       (CurrentContext->family == (const char *) NULL) ||
4955       (LocaleCompare(CurrentContext->family,font_family) != 0))
4956     {
4957       (void) CloneString(&CurrentContext->family,font_family);
4958       (void) MvgPrintf(wand,"font-family '%s'\n",font_family);
4959     }
4960   return(MagickTrue);
4961 }
4962 \f
4963 /*
4964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4965 %                                                                             %
4966 %                                                                             %
4967 %                                                                             %
4968 %   D r a w S e t F o n t S i z e                                             %
4969 %                                                                             %
4970 %                                                                             %
4971 %                                                                             %
4972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4973 %
4974 %  DrawSetFontSize() sets the font pointsize to use when annotating with text.
4975 %
4976 %  The format of the DrawSetFontSize method is:
4977 %
4978 %      void DrawSetFontSize(DrawingWand *wand,const double pointsize)
4979 %
4980 %  A description of each parameter follows:
4981 %
4982 %    o wand: the drawing wand.
4983 %
4984 %    o pointsize: text pointsize
4985 %
4986 */
4987 WandExport void DrawSetFontSize(DrawingWand *wand,const double pointsize)
4988 {
4989   assert(wand != (DrawingWand *) NULL);
4990   assert(wand->signature == WandSignature);
4991   if (wand->debug != MagickFalse)
4992     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
4993   if ((wand->filter_off != MagickFalse) ||
4994       (fabs(CurrentContext->pointsize-pointsize) > MagickEpsilon))
4995     {
4996       CurrentContext->pointsize=pointsize;
4997       (void) MvgPrintf(wand,"font-size %g\n",pointsize);
4998     }
4999 }
5000 \f
5001 /*
5002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5003 %                                                                             %
5004 %                                                                             %
5005 %                                                                             %
5006 %   D r a w S e t F o n t S t r e t c h                                       %
5007 %                                                                             %
5008 %                                                                             %
5009 %                                                                             %
5010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5011 %
5012 %  DrawSetFontStretch() sets the font stretch to use when annotating with text.
5013 %  The AnyStretch enumeration acts as a wild-card "don't care" option.
5014 %
5015 %  The format of the DrawSetFontStretch method is:
5016 %
5017 %      void DrawSetFontStretch(DrawingWand *wand,
5018 %        const StretchType font_stretch)
5019 %
5020 %  A description of each parameter follows:
5021 %
5022 %    o wand: the drawing wand.
5023 %
5024 %    o font_stretch: font stretch (NormalStretch, UltraCondensedStretch,
5025 %                    CondensedStretch, SemiCondensedStretch,
5026 %                    SemiExpandedStretch, ExpandedStretch,
5027 %                    ExtraExpandedStretch, UltraExpandedStretch, AnyStretch)
5028 %
5029 */
5030 WandExport void DrawSetFontStretch(DrawingWand *wand,
5031   const StretchType font_stretch)
5032 {
5033   assert(wand != (DrawingWand *) NULL);
5034   assert(wand->signature == WandSignature);
5035   if (wand->debug != MagickFalse)
5036     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5037   if ((wand->filter_off != MagickFalse) ||
5038       (CurrentContext->stretch != font_stretch))
5039     {
5040       CurrentContext->stretch=font_stretch;
5041       (void) MvgPrintf(wand, "font-stretch '%s'\n",MagickOptionToMnemonic(
5042         MagickStretchOptions,(long) font_stretch));
5043     }
5044 }
5045 \f
5046 /*
5047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5048 %                                                                             %
5049 %                                                                             %
5050 %                                                                             %
5051 %   D r a w S e t F o n t S t y l e                                           %
5052 %                                                                             %
5053 %                                                                             %
5054 %                                                                             %
5055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5056 %
5057 %  DrawSetFontStyle() sets the font style to use when annotating with text.
5058 %  The AnyStyle enumeration acts as a wild-card "don't care" option.
5059 %
5060 %  The format of the DrawSetFontStyle method is:
5061 %
5062 %      void DrawSetFontStyle(DrawingWand *wand,const StyleType style)
5063 %
5064 %  A description of each parameter follows:
5065 %
5066 %    o wand: the drawing wand.
5067 %
5068 %    o style: font style (NormalStyle, ItalicStyle, ObliqueStyle, AnyStyle)
5069 %
5070 */
5071 WandExport void DrawSetFontStyle(DrawingWand *wand,const StyleType style)
5072 {
5073   assert(wand != (DrawingWand *) NULL);
5074   assert(wand->signature == WandSignature);
5075   if (wand->debug != MagickFalse)
5076     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5077   if ((wand->filter_off != MagickFalse) ||
5078       (CurrentContext->style != style))
5079     {
5080       CurrentContext->style=style;
5081       (void) MvgPrintf(wand, "font-style '%s'\n",MagickOptionToMnemonic(
5082         MagickStyleOptions,(long) style));
5083     }
5084 }
5085 \f
5086 /*
5087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5088 %                                                                             %
5089 %                                                                             %
5090 %                                                                             %
5091 %   D r a w S e t F o n t W e i g h t                                         %
5092 %                                                                             %
5093 %                                                                             %
5094 %                                                                             %
5095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5096 %
5097 %  DrawSetFontWeight() sets the font weight to use when annotating with text.
5098 %
5099 %  The format of the DrawSetFontWeight method is:
5100 %
5101 %      void DrawSetFontWeight(DrawingWand *wand,
5102 %        const unsigned long font_weight)
5103 %
5104 %  A description of each parameter follows:
5105 %
5106 %    o wand: the drawing wand.
5107 %
5108 %    o font_weight: font weight (valid range 100-900)
5109 %
5110 */
5111 WandExport void DrawSetFontWeight(DrawingWand *wand,
5112   const unsigned long font_weight)
5113 {
5114   assert(wand != (DrawingWand *) NULL);
5115   assert(wand->signature == WandSignature);
5116   if (wand->debug != MagickFalse)
5117     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5118   if ((wand->filter_off != MagickFalse) ||
5119       (CurrentContext->weight != font_weight))
5120     {
5121       CurrentContext->weight=font_weight;
5122       (void) MvgPrintf(wand,"font-weight %lu\n",font_weight);
5123     }
5124 }
5125 \f
5126 /*
5127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5128 %                                                                             %
5129 %                                                                             %
5130 %                                                                             %
5131 %   D r a w S e t G r a v i t y                                               %
5132 %                                                                             %
5133 %                                                                             %
5134 %                                                                             %
5135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5136 %
5137 %  DrawSetGravity() sets the text placement gravity to use when annotating
5138 %  with text.
5139 %
5140 %  The format of the DrawSetGravity method is:
5141 %
5142 %      void DrawSetGravity(DrawingWand *wand,const GravityType gravity)
5143 %
5144 %  A description of each parameter follows:
5145 %
5146 %    o wand: the drawing wand.
5147 %
5148 %    o gravity: positioning gravity (NorthWestGravity, NorthGravity,
5149 %               NorthEastGravity, WestGravity, CenterGravity,
5150 %               EastGravity, SouthWestGravity, SouthGravity,
5151 %               SouthEastGravity)
5152 %
5153 */
5154 WandExport void DrawSetGravity(DrawingWand *wand,const GravityType gravity)
5155 {
5156   assert(wand != (DrawingWand *) NULL);
5157   assert(wand->signature == WandSignature);
5158   if (wand->debug != MagickFalse)
5159     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5160   if ((wand->filter_off != MagickFalse) ||
5161       (CurrentContext->gravity != gravity) || (gravity != ForgetGravity))
5162     {
5163       CurrentContext->gravity=gravity;
5164       (void) MvgPrintf(wand,"gravity '%s'\n",MagickOptionToMnemonic(
5165         MagickGravityOptions,(long) gravity));
5166     }
5167 }
5168 \f
5169 /*
5170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5171 %                                                                             %
5172 %                                                                             %
5173 %                                                                             %
5174 %   D r a w S e t S t r o k e C o l o r                                       %
5175 %                                                                             %
5176 %                                                                             %
5177 %                                                                             %
5178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5179 %
5180 %  DrawSetStrokeColor() sets the color used for stroking object outlines.
5181 %
5182 %  The format of the DrawSetStrokeColor method is:
5183 %
5184 %      void DrawSetStrokeColor(DrawingWand *wand,
5185 %        const PixelWand *stroke_wand)
5186 %
5187 %  A description of each parameter follows:
5188 %
5189 %    o wand: the drawing wand.
5190 %
5191 %    o stroke_wand: stroke wand.
5192 %
5193 */
5194 WandExport void DrawSetStrokeColor(DrawingWand *wand,
5195   const PixelWand *stroke_wand)
5196 {
5197   PixelPacket
5198     *current_stroke,
5199     new_stroke,
5200     stroke_color;
5201
5202   assert(wand != (DrawingWand *) NULL);
5203   assert(wand->signature == WandSignature);
5204   if (wand->debug != MagickFalse)
5205     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5206   assert(stroke_wand != (const PixelWand *) NULL);
5207   PixelGetQuantumColor(stroke_wand,&stroke_color);
5208   new_stroke=stroke_color;
5209   current_stroke=(&CurrentContext->stroke);
5210   if ((wand->filter_off != MagickFalse) ||
5211       (IsColorEqual(current_stroke,&new_stroke) == MagickFalse))
5212     {
5213       CurrentContext->stroke=new_stroke;
5214       (void) MvgPrintf(wand,"stroke '");
5215       MvgAppendColor(wand,&stroke_color);
5216       (void) MvgPrintf(wand,"'\n");
5217     }
5218 }
5219 \f
5220 /*
5221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5222 %                                                                             %
5223 %                                                                             %
5224 %                                                                             %
5225 %   D r a w S e t S t r o k e P a t t e r n U R L                             %
5226 %                                                                             %
5227 %                                                                             %
5228 %                                                                             %
5229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5230 %
5231 %  DrawSetStrokePatternURL() sets the pattern used for stroking object outlines.
5232 %
5233 %  The format of the DrawSetStrokePatternURL method is:
5234 %
5235 %      MagickBooleanType DrawSetStrokePatternURL(DrawingWand *wand,
5236 %        const char *stroke_url)
5237 %
5238 %  A description of each parameter follows:
5239 %
5240 %    o wand: the drawing wand.
5241 %
5242 %    o stroke_url: URL specifying pattern ID (e.g. "#pattern_id")
5243 %
5244 */
5245 WandExport MagickBooleanType DrawSetStrokePatternURL(DrawingWand *wand,
5246   const char *stroke_url)
5247 {
5248   char
5249     pattern[MaxTextExtent],
5250     pattern_spec[MaxTextExtent];
5251
5252   assert(wand != (DrawingWand *) NULL);
5253   assert(wand->signature == WandSignature);
5254   if (wand->debug != MagickFalse)
5255     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5256   if (wand->image == (Image *) NULL)
5257     ThrowDrawException(WandError,"ContainsNoImages",wand->name);
5258   assert(stroke_url != NULL);
5259   if (stroke_url[0] != '#')
5260     ThrowDrawException(DrawError,"NotARelativeURL",stroke_url);
5261   (void) FormatMagickString(pattern,MaxTextExtent,"%s",stroke_url+1);
5262   if (GetImageArtifact(wand->image,pattern) == (const char *) NULL)
5263     {
5264       ThrowDrawException(DrawError,"URLNotFound",stroke_url)
5265       return(MagickFalse);
5266     }
5267   (void) FormatMagickString(pattern_spec,MaxTextExtent,"url(%s)",stroke_url);
5268 #if DRAW_BINARY_IMPLEMENTATION
5269   DrawPatternPath(wand->image,CurrentContext,pattern_spec,
5270     &CurrentContext->stroke_pattern);
5271 #endif
5272   if (CurrentContext->stroke.opacity != (Quantum) TransparentOpacity)
5273     CurrentContext->stroke.opacity=CurrentContext->opacity;
5274   (void) MvgPrintf(wand,"stroke %s\n",pattern_spec);
5275   return(MagickTrue);
5276 }
5277 \f
5278 /*
5279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5280 %                                                                             %
5281 %                                                                             %
5282 %                                                                             %
5283 %   D r a w S e t S t r o k e A n t i a l i a s                               %
5284 %                                                                             %
5285 %                                                                             %
5286 %                                                                             %
5287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5288 %
5289 %  DrawSetStrokeAntialias() controls whether stroked outlines are antialiased.
5290 %  Stroked outlines are antialiased by default.  When antialiasing is disabled
5291 %  stroked pixels are thresholded to determine if the stroke color or
5292 %  underlying canvas color should be used.
5293 %
5294 %  The format of the DrawSetStrokeAntialias method is:
5295 %
5296 %      void DrawSetStrokeAntialias(DrawingWand *wand,
5297 %        const MagickBooleanType stroke_antialias)
5298 %
5299 %  A description of each parameter follows:
5300 %
5301 %    o wand: the drawing wand.
5302 %
5303 %    o stroke_antialias: set to false (zero) to disable antialiasing
5304 %
5305 */
5306 WandExport void DrawSetStrokeAntialias(DrawingWand *wand,
5307   const MagickBooleanType stroke_antialias)
5308 {
5309   assert(wand != (DrawingWand *) NULL);
5310   assert(wand->signature == WandSignature);
5311   if (wand->debug != MagickFalse)
5312     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5313   if ((wand->filter_off != MagickFalse) ||
5314       (CurrentContext->stroke_antialias != stroke_antialias))
5315     {
5316       CurrentContext->stroke_antialias=stroke_antialias;
5317       (void) MvgPrintf(wand,"stroke-antialias %i\n",stroke_antialias != 0 ?
5318         1 : 0);
5319     }
5320 }
5321 \f
5322 /*
5323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5324 %                                                                             %
5325 %                                                                             %
5326 %                                                                             %
5327 %   D r a w S e t S t r o k e D a s h A r r a y                               %
5328 %                                                                             %
5329 %                                                                             %
5330 %                                                                             %
5331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5332 %
5333 %  DrawSetStrokeDashArray() specifies the pattern of dashes and gaps used to
5334 %  stroke paths. The stroke dash array represents an array of numbers that
5335 %  specify the lengths of alternating dashes and gaps in pixels. If an odd
5336 %  number of values is provided, then the list of values is repeated to yield
5337 %  an even number of values. To remove an existing dash array, pass a zero
5338 %  number_elements argument and null dash_array.  A typical stroke dash array
5339 %  might contain the members 5 3 2.
5340 %
5341 %  The format of the DrawSetStrokeDashArray method is:
5342 %
5343 %      MagickBooleanType DrawSetStrokeDashArray(DrawingWand *wand,
5344 %        const unsigned long number_elements,const double *dash_array)
5345 %
5346 %  A description of each parameter follows:
5347 %
5348 %    o wand: the drawing wand.
5349 %
5350 %    o number_elements: number of elements in dash array
5351 %
5352 %    o dash_array: dash array values
5353 %
5354 */
5355 WandExport MagickBooleanType DrawSetStrokeDashArray(DrawingWand *wand,
5356   const unsigned long number_elements,const double *dash_array)
5357 {
5358   MagickBooleanType
5359     update;
5360
5361   register const double
5362     *p;
5363
5364   register double
5365     *q;
5366
5367   register long
5368     i;
5369
5370   unsigned long
5371     n_new,
5372     n_old;
5373
5374   assert(wand != (DrawingWand *) NULL);
5375   assert(wand->signature == WandSignature);
5376   if (wand->debug != MagickFalse)
5377     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5378   n_new=number_elements;
5379   n_old=0;
5380   update=MagickFalse;
5381   q=CurrentContext->dash_pattern;
5382   if (q != (const double *) NULL)
5383     while (*q++ != 0.0)
5384       n_old++;
5385   if ((n_old == 0) && (n_new == 0))
5386     update=MagickFalse;
5387   else
5388     if (n_old != n_new)
5389       update=MagickTrue;
5390     else
5391       if ((CurrentContext->dash_pattern != (double *) NULL) &&
5392           (dash_array != (double *) NULL))
5393         {
5394           p=dash_array;
5395           q=CurrentContext->dash_pattern;
5396           for (i=0; i < (long) n_new; i++)
5397           {
5398             if (fabs((*p)-(*q)) > MagickEpsilon)
5399               {
5400                 update=MagickTrue;
5401                 break;
5402               }
5403             p++;
5404             q++;
5405           }
5406         }
5407   if ((wand->filter_off != MagickFalse) || (update != MagickFalse))
5408     {
5409       if (CurrentContext->dash_pattern != (double *) NULL)
5410         CurrentContext->dash_pattern=(double *)
5411           RelinquishMagickMemory(CurrentContext->dash_pattern);
5412       if (n_new != 0)
5413         {
5414           CurrentContext->dash_pattern=(double *) AcquireQuantumMemory((size_t)
5415             n_new+1UL,sizeof(*CurrentContext->dash_pattern));
5416           if (!CurrentContext->dash_pattern)
5417             {
5418               ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
5419                 wand->name);
5420               return(MagickFalse);
5421             }
5422           q=CurrentContext->dash_pattern;
5423           p=dash_array;
5424           for (i=0; i < (long) n_new; i++)
5425             *q++=(*p++);
5426           *q=0;
5427         }
5428       (void) MvgPrintf(wand,"stroke-dasharray ");
5429       if (n_new == 0)
5430         (void) MvgPrintf(wand,"none\n");
5431       else
5432         {
5433           p=dash_array;
5434           (void) MvgPrintf(wand,"%g",*p++);
5435           for (i=1; i < (long) n_new; i++)
5436             (void) MvgPrintf(wand,",%g",*p++);
5437           (void) MvgPrintf(wand,"\n");
5438         }
5439     }
5440   return(MagickTrue);
5441 }
5442 \f
5443 /*
5444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5445 %                                                                             %
5446 %                                                                             %
5447 %                                                                             %
5448 %   D r a w S e t S t r o k e D a s h O f f s e t                             %
5449 %                                                                             %
5450 %                                                                             %
5451 %                                                                             %
5452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5453 %
5454 %  DrawSetStrokeDashOffset() specifies the offset into the dash pattern to
5455 %  start the dash.
5456 %
5457 %  The format of the DrawSetStrokeDashOffset method is:
5458 %
5459 %      void DrawSetStrokeDashOffset(DrawingWand *wand,
5460 %        const double dash_offset)
5461 %
5462 %  A description of each parameter follows:
5463 %
5464 %    o wand: the drawing wand.
5465 %
5466 %    o dash_offset: dash offset
5467 %
5468 */
5469 WandExport void DrawSetStrokeDashOffset(DrawingWand *wand,
5470   const double dash_offset)
5471 {
5472   assert(wand != (DrawingWand *) NULL);
5473   assert(wand->signature == WandSignature);
5474   if (wand->debug != MagickFalse)
5475     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5476   if ((wand->filter_off != MagickFalse) ||
5477      (fabs(CurrentContext->dash_offset-dash_offset) > MagickEpsilon))
5478     {
5479       CurrentContext->dash_offset=dash_offset;
5480       (void) MvgPrintf(wand,"stroke-dashoffset %g\n",dash_offset);
5481     }
5482 }
5483 \f
5484 /*
5485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5486 %                                                                             %
5487 %                                                                             %
5488 %                                                                             %
5489 %   D r a w S e t S t r o k e L i n e C a p                                   %
5490 %                                                                             %
5491 %                                                                             %
5492 %                                                                             %
5493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5494 %
5495 %  DrawSetStrokeLineCap() specifies the shape to be used at the end of
5496 %  open subpaths when they are stroked. Values of LineCap are
5497 %  UndefinedCap, ButtCap, RoundCap, and SquareCap.
5498 %
5499 %  The format of the DrawSetStrokeLineCap method is:
5500 %
5501 %      void DrawSetStrokeLineCap(DrawingWand *wand,
5502 %        const LineCap linecap)
5503 %
5504 %  A description of each parameter follows:
5505 %
5506 %    o wand: the drawing wand.
5507 %
5508 %    o linecap: linecap style
5509 %
5510 */
5511 WandExport void DrawSetStrokeLineCap(DrawingWand *wand,const LineCap linecap)
5512 {
5513   assert(wand != (DrawingWand *) NULL);
5514   assert(wand->signature == WandSignature);
5515   if (wand->debug != MagickFalse)
5516     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5517   if ((wand->filter_off != MagickFalse) ||
5518       (CurrentContext->linecap != linecap))
5519     {
5520       CurrentContext->linecap=linecap;
5521       (void) MvgPrintf(wand,"stroke-linecap '%s'\n",MagickOptionToMnemonic(
5522         MagickLineCapOptions,(long) linecap));
5523     }
5524 }
5525 \f
5526 /*
5527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5528 %                                                                             %
5529 %                                                                             %
5530 %                                                                             %
5531 %   D r a w S e t S t r o k e L i n e J o i n                                 %
5532 %                                                                             %
5533 %                                                                             %
5534 %                                                                             %
5535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5536 %
5537 %  DrawSetStrokeLineJoin() specifies the shape to be used at the corners of
5538 %  paths (or other vector shapes) when they are stroked. Values of LineJoin are
5539 %  UndefinedJoin, MiterJoin, RoundJoin, and BevelJoin.
5540 %
5541 %  The format of the DrawSetStrokeLineJoin method is:
5542 %
5543 %      void DrawSetStrokeLineJoin(DrawingWand *wand,
5544 %        const LineJoin linejoin)
5545 %
5546 %  A description of each parameter follows:
5547 %
5548 %    o wand: the drawing wand.
5549 %
5550 %    o linejoin: line join style
5551 %
5552 */
5553 WandExport void DrawSetStrokeLineJoin(DrawingWand *wand,const LineJoin linejoin)
5554 {
5555   assert(wand != (DrawingWand *) NULL);
5556   assert(wand->signature == WandSignature);
5557   if (wand->debug != MagickFalse)
5558     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5559   if ((wand->filter_off != MagickFalse) ||
5560       (CurrentContext->linejoin != linejoin))
5561     {
5562       CurrentContext->linejoin=linejoin;
5563       (void) MvgPrintf(wand, "stroke-linejoin '%s'\n",MagickOptionToMnemonic(
5564         MagickLineJoinOptions,(long) linejoin));
5565     }
5566 }
5567 \f
5568 /*
5569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5570 %                                                                             %
5571 %                                                                             %
5572 %                                                                             %
5573 %   D r a w S e t S t r o k e M i t e r L i m i t                             %
5574 %                                                                             %
5575 %                                                                             %
5576 %                                                                             %
5577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5578 %
5579 %  DrawSetStrokeMiterLimit() specifies the miter limit. When two line
5580 %  segments meet at a sharp angle and miter joins have been specified for
5581 %  'lineJoin', it is possible for the miter to extend far beyond the
5582 %  thickness of the line stroking the path. The miterLimit' imposes a
5583 %  limit on the ratio of the miter length to the 'lineWidth'.
5584 %
5585 %  The format of the DrawSetStrokeMiterLimit method is:
5586 %
5587 %      void DrawSetStrokeMiterLimit(DrawingWand *wand,
5588 %        const unsigned long miterlimit)
5589 %
5590 %  A description of each parameter follows:
5591 %
5592 %    o wand: the drawing wand.
5593 %
5594 %    o miterlimit: miter limit
5595 %
5596 */
5597 WandExport void DrawSetStrokeMiterLimit(DrawingWand *wand,
5598   const unsigned long miterlimit)
5599 {
5600   assert(wand != (DrawingWand *) NULL);
5601   assert(wand->signature == WandSignature);
5602   if (wand->debug != MagickFalse)
5603     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5604   if (CurrentContext->miterlimit != miterlimit)
5605     {
5606       CurrentContext->miterlimit=miterlimit;
5607       (void) MvgPrintf(wand,"stroke-miterlimit %lu\n",miterlimit);
5608     }
5609 }
5610 \f
5611 /*
5612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5613 %                                                                             %
5614 %                                                                             %
5615 %                                                                             %
5616 %   D r a w S e t S t r o k e O p a c i t y                                   %
5617 %                                                                             %
5618 %                                                                             %
5619 %                                                                             %
5620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5621 %
5622 %  DrawSetStrokeOpacity() specifies the opacity of stroked object outlines.
5623 %
5624 %  The format of the DrawSetStrokeOpacity method is:
5625 %
5626 %      void DrawSetStrokeOpacity(DrawingWand *wand,
5627 %        const double stroke_opacity)
5628 %
5629 %  A description of each parameter follows:
5630 %
5631 %    o wand: the drawing wand.
5632 %
5633 %    o stroke_opacity: stroke opacity.  The value 1.0 is opaque.
5634 %
5635 */
5636 WandExport void DrawSetStrokeOpacity(DrawingWand *wand,
5637   const double stroke_opacity)
5638 {
5639   Quantum
5640     opacity;
5641
5642   assert(wand != (DrawingWand *) NULL);
5643   assert(wand->signature == WandSignature);
5644   if (wand->debug != MagickFalse)
5645     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5646   opacity=RoundToQuantum((double) QuantumRange*(1.0-stroke_opacity));
5647   if ((wand->filter_off != MagickFalse) ||
5648       (CurrentContext->stroke.opacity != opacity))
5649     {
5650       CurrentContext->stroke.opacity=opacity;
5651       (void) MvgPrintf(wand,"stroke-opacity %g\n",stroke_opacity);
5652     }
5653 }
5654 \f
5655 /*
5656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5657 %                                                                             %
5658 %                                                                             %
5659 %                                                                             %
5660 %   D r a w S e t S t r o k e W i d t h                                       %
5661 %                                                                             %
5662 %                                                                             %
5663 %                                                                             %
5664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5665 %
5666 %  DrawSetStrokeWidth() sets the width of the stroke used to draw object
5667 %  outlines.
5668 %
5669 %  The format of the DrawSetStrokeWidth method is:
5670 %
5671 %      void DrawSetStrokeWidth(DrawingWand *wand,
5672 %        const double stroke_width)
5673 %
5674 %  A description of each parameter follows:
5675 %
5676 %    o wand: the drawing wand.
5677 %
5678 %    o stroke_width: stroke width
5679 %
5680 */
5681 WandExport void DrawSetStrokeWidth(DrawingWand *wand,const double stroke_width)
5682 {
5683   assert(wand != (DrawingWand *) NULL);
5684   assert(wand->signature == WandSignature);
5685   if (wand->debug != MagickFalse)
5686     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5687   if ((wand->filter_off != MagickFalse) ||
5688       (fabs(CurrentContext->stroke_width-stroke_width) > MagickEpsilon))
5689     {
5690       CurrentContext->stroke_width=stroke_width;
5691       (void) MvgPrintf(wand,"stroke-width %g\n",stroke_width);
5692     }
5693 }
5694 \f
5695 /*
5696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5697 %                                                                             %
5698 %                                                                             %
5699 %                                                                             %
5700 %   D r a w S e t T e x t A l i g n m e n t                                   %
5701 %                                                                             %
5702 %                                                                             %
5703 %                                                                             %
5704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5705 %
5706 %  DrawSetTextAlignment() specifies a text alignment to be applied when
5707 %  annotating with text.
5708 %
5709 %  The format of the DrawSetTextAlignment method is:
5710 %
5711 %      void DrawSetTextAlignment(DrawingWand *wand,const AlignType alignment)
5712 %
5713 %  A description of each parameter follows:
5714 %
5715 %    o wand: the drawing wand.
5716 %
5717 %    o alignment: text alignment.  One of UndefinedAlign, LeftAlign,
5718 %      CenterAlign, or RightAlign.
5719 %
5720 */
5721 WandExport void DrawSetTextAlignment(DrawingWand *wand,
5722   const AlignType alignment)
5723 {
5724   assert(wand != (DrawingWand *) NULL);
5725   assert(wand->signature == WandSignature);
5726   if (wand->debug != MagickFalse)
5727     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5728   if ((wand->filter_off != MagickFalse) ||
5729       (CurrentContext->align != alignment))
5730     {
5731       CurrentContext->align=alignment;
5732       (void) MvgPrintf(wand,"text-align '%s'\n",MagickOptionToMnemonic(
5733         MagickAlignOptions,(long) alignment));
5734     }
5735 }
5736 \f
5737 /*
5738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5739 %                                                                             %
5740 %                                                                             %
5741 %                                                                             %
5742 %   D r a w S e t T e x t A n t i a l i a s                                   %
5743 %                                                                             %
5744 %                                                                             %
5745 %                                                                             %
5746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5747 %
5748 %  DrawSetTextAntialias() controls whether text is antialiased.  Text is
5749 %  antialiased by default.
5750 %
5751 %  The format of the DrawSetTextAntialias method is:
5752 %
5753 %      void DrawSetTextAntialias(DrawingWand *wand,
5754 %        const MagickBooleanType text_antialias)
5755 %
5756 %  A description of each parameter follows:
5757 %
5758 %    o wand: the drawing wand.
5759 %
5760 %    o text_antialias: antialias boolean. Set to false (0) to disable
5761 %      antialiasing.
5762 %
5763 */
5764 WandExport void DrawSetTextAntialias(DrawingWand *wand,
5765   const MagickBooleanType text_antialias)
5766 {
5767   assert(wand != (DrawingWand *) NULL);
5768   assert(wand->signature == WandSignature);
5769   if (wand->debug != MagickFalse)
5770     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5771   if ((wand->filter_off != MagickFalse) ||
5772       (CurrentContext->text_antialias != text_antialias))
5773     {
5774       CurrentContext->text_antialias=text_antialias;
5775       (void) MvgPrintf(wand,"text-antialias %i\n",text_antialias != 0 ? 1 : 0);
5776     }
5777 }
5778 \f
5779 /*
5780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5781 %                                                                             %
5782 %                                                                             %
5783 %                                                                             %
5784 %   D r a w S e t T e x t D e c o r a t i o n                                 %
5785 %                                                                             %
5786 %                                                                             %
5787 %                                                                             %
5788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5789 %
5790 %  DrawSetTextDecoration() specifies a decoration to be applied when
5791 %  annotating with text.
5792 %
5793 %  The format of the DrawSetTextDecoration method is:
5794 %
5795 %      void DrawSetTextDecoration(DrawingWand *wand,
5796 %        const DecorationType decoration)
5797 %
5798 %  A description of each parameter follows:
5799 %
5800 %    o wand: the drawing wand.
5801 %
5802 %    o decoration: text decoration.  One of NoDecoration, UnderlineDecoration,
5803 %      OverlineDecoration, or LineThroughDecoration
5804 %
5805 */
5806 WandExport void DrawSetTextDecoration(DrawingWand *wand,
5807   const DecorationType decoration)
5808 {
5809   assert(wand != (DrawingWand *) NULL);
5810   assert(wand->signature == WandSignature);
5811   if (wand->debug != MagickFalse)
5812     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5813   if ((wand->filter_off != MagickFalse) ||
5814       (CurrentContext->decorate != decoration))
5815     {
5816       CurrentContext->decorate=decoration;
5817       (void) MvgPrintf(wand,"decorate '%s'\n",MagickOptionToMnemonic(
5818         MagickDecorateOptions,(long) decoration));
5819     }
5820 }
5821 \f
5822 /*
5823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5824 %                                                                             %
5825 %                                                                             %
5826 %                                                                             %
5827 %   D r a w S e t T e x t E n c o d i n g                                     %
5828 %                                                                             %
5829 %                                                                             %
5830 %                                                                             %
5831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5832 %
5833 %  DrawSetTextEncoding() specifies the code set to use for text
5834 %  annotations. The only character encoding which may be specified
5835 %  at this time is "UTF-8" for representing Unicode as a sequence of
5836 %  bytes. Specify an empty string to set text encoding to the system's
5837 %  default. Successful text annotation using Unicode may require fonts
5838 %  designed to support Unicode.
5839 %
5840 %  The format of the DrawSetTextEncoding method is:
5841 %
5842 %      void DrawSetTextEncoding(DrawingWand *wand,const char *encoding)
5843 %
5844 %  A description of each parameter follows:
5845 %
5846 %    o wand: the drawing wand.
5847 %
5848 %    o encoding: character string specifying text encoding
5849 %
5850 */
5851 WandExport void DrawSetTextEncoding(DrawingWand *wand,const char *encoding)
5852 {
5853   assert(wand != (DrawingWand *) NULL);
5854   assert(wand->signature == WandSignature);
5855   if (wand->debug != MagickFalse)
5856     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5857   assert(encoding != (char *) NULL);
5858   if ((wand->filter_off != MagickFalse) ||
5859       (CurrentContext->encoding == (char *) NULL) ||
5860       (LocaleCompare(CurrentContext->encoding,encoding) != 0))
5861     {
5862       (void) CloneString(&CurrentContext->encoding,encoding);
5863       (void) MvgPrintf(wand,"encoding '%s'\n",encoding);
5864     }
5865 }
5866 \f
5867 /*
5868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5869 %                                                                             %
5870 %                                                                             %
5871 %                                                                             %
5872 %   D r a w S e t T e x t K e r n i n g                                       %
5873 %                                                                             %
5874 %                                                                             %
5875 %                                                                             %
5876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5877 %
5878 %  DrawSetTextKerning() sets the spacing between characters in text.
5879 %
5880 %  The format of the DrawSetTextKerning method is:
5881 %
5882 %      void DrawSetTextKerning(DrawingWand *wand,const double kerning)
5883 %
5884 %  A description of each parameter follows:
5885 %
5886 %    o wand: the drawing wand.
5887 %
5888 %    o kerning: text kerning
5889 %
5890 */
5891 WandExport void DrawSetTextKerning(DrawingWand *wand,const double kerning)
5892 {
5893   assert(wand != (DrawingWand *) NULL);
5894   assert(wand->signature == WandSignature);
5895
5896   if (wand->debug != MagickFalse)
5897     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5898   if ((wand->filter_off != MagickFalse) &&
5899       (CurrentContext->kerning != kerning))
5900     {
5901       CurrentContext->kerning=kerning;
5902       (void) MvgPrintf(wand,"kerning %lf\n",kerning);
5903     }
5904 }
5905 \f
5906 /*
5907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5908 %                                                                             %
5909 %                                                                             %
5910 %                                                                             %
5911 %   D r a w S e t T e x t I n t e r L i n e S p a c i n g                     %
5912 %                                                                             %
5913 %                                                                             %
5914 %                                                                             %
5915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5916 %
5917 %  DrawSetTextInterwordSpacing() sets the spacing between line in text.
5918 %
5919 %  The format of the DrawSetInterwordSpacing method is:
5920 %
5921 %      void DrawSetTextInterwordSpacing(DrawingWand *wand,
5922 %        const double interline_spacing)
5923 %
5924 %  A description of each parameter follows:
5925 %
5926 %    o wand: the drawing wand.
5927 %
5928 %    o interline_spacing: text line spacing
5929 %
5930 */
5931 WandExport void DrawSetTextInterlineSpacing(DrawingWand *wand,
5932   const double interline_spacing)
5933 {
5934   assert(wand != (DrawingWand *) NULL);
5935   assert(wand->signature == WandSignature);
5936
5937   if (wand->debug != MagickFalse)
5938     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5939   if ((wand->filter_off != MagickFalse) &&
5940       (CurrentContext->interline_spacing != interline_spacing))
5941     {
5942       CurrentContext->interline_spacing=interline_spacing;
5943       (void) MvgPrintf(wand,"interline-spacing %lf\n",interline_spacing);
5944     }
5945 }
5946 \f
5947 /*
5948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5949 %                                                                             %
5950 %                                                                             %
5951 %                                                                             %
5952 %   D r a w S e t T e x t I n t e r w o r d S p a c i n g                     %
5953 %                                                                             %
5954 %                                                                             %
5955 %                                                                             %
5956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5957 %
5958 %  DrawSetTextInterwordSpacing() sets the spacing between words in text.
5959 %
5960 %  The format of the DrawSetInterwordSpacing method is:
5961 %
5962 %      void DrawSetTextInterwordSpacing(DrawingWand *wand,
5963 %        const double interword_spacing)
5964 %
5965 %  A description of each parameter follows:
5966 %
5967 %    o wand: the drawing wand.
5968 %
5969 %    o interword_spacing: text word spacing
5970 %
5971 */
5972 WandExport void DrawSetTextInterwordSpacing(DrawingWand *wand,
5973   const double interword_spacing)
5974 {
5975   assert(wand != (DrawingWand *) NULL);
5976   assert(wand->signature == WandSignature);
5977
5978   if (wand->debug != MagickFalse)
5979     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
5980   if ((wand->filter_off != MagickFalse) &&
5981       (CurrentContext->interword_spacing != interword_spacing))
5982     {
5983       CurrentContext->interword_spacing=interword_spacing;
5984       (void) MvgPrintf(wand,"interword-spacing %lf\n",interword_spacing);
5985     }
5986 }
5987 \f
5988 /*
5989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5990 %                                                                             %
5991 %                                                                             %
5992 %                                                                             %
5993 %   D r a w S e t T e x t U n d e r C o l o r                                 %
5994 %                                                                             %
5995 %                                                                             %
5996 %                                                                             %
5997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5998 %
5999 %  DrawSetTextUnderColor() specifies the color of a background rectangle
6000 %  to place under text annotations.
6001 %
6002 %  The format of the DrawSetTextUnderColor method is:
6003 %
6004 %      void DrawSetTextUnderColor(DrawingWand *wand,
6005 %        const PixelWand *under_wand)
6006 %
6007 %  A description of each parameter follows:
6008 %
6009 %    o wand: the drawing wand.
6010 %
6011 %    o under_wand: text under wand.
6012 %
6013 */
6014 WandExport void DrawSetTextUnderColor(DrawingWand *wand,
6015   const PixelWand *under_wand)
6016 {
6017   PixelPacket
6018     under_color;
6019
6020   assert(wand != (DrawingWand *) NULL);
6021   assert(wand->signature == WandSignature);
6022   if (wand->debug != MagickFalse)
6023     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6024   assert(under_wand != (const PixelWand *) NULL);
6025   PixelGetQuantumColor(under_wand,&under_color);
6026   if ((wand->filter_off != MagickFalse) ||
6027       (IsColorEqual(&CurrentContext->undercolor,&under_color) == MagickFalse))
6028     {
6029       CurrentContext->undercolor=under_color;
6030       (void) MvgPrintf(wand,"text-undercolor '");
6031       MvgAppendColor(wand,&under_color);
6032       (void) MvgPrintf(wand,"'\n");
6033     }
6034 }
6035 \f
6036 /*
6037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6038 %                                                                             %
6039 %                                                                             %
6040 %                                                                             %
6041 %   D r a w S e t V e c t o r G r a p h i c s                                 %
6042 %                                                                             %
6043 %                                                                             %
6044 %                                                                             %
6045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6046 %
6047 %  DrawSetVectorGraphics() sets the vector graphics associated with the
6048 %  specified wand.  Use this method with DrawGetVectorGraphics() as a method
6049 %  to persist the vector graphics state.
6050 %
6051 %  The format of the DrawSetVectorGraphics method is:
6052 %
6053 %      MagickBooleanType DrawSetVectorGraphics(DrawingWand *wand,
6054 %        const char *xml)
6055 %
6056 %  A description of each parameter follows:
6057 %
6058 %    o wand: the drawing wand.
6059 %
6060 %    o xml: the drawing wand XML.
6061 %
6062 */
6063
6064 static inline MagickBooleanType IsPoint(const char *point)
6065 {
6066   char
6067     *p;
6068
6069   long
6070     value;
6071
6072   value=strtol(point,&p,10);
6073   return(p != point ? MagickTrue : MagickFalse);
6074 }
6075
6076 WandExport MagickBooleanType DrawSetVectorGraphics(DrawingWand *wand,
6077   const char *xml)
6078 {
6079   const char
6080     *value;
6081
6082   XMLTreeInfo
6083     *child,
6084     *xml_info;
6085
6086   assert(wand != (DrawingWand *) NULL);
6087   assert(wand->signature == WandSignature);
6088   if (wand->debug != MagickFalse)
6089     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6090   CurrentContext=DestroyDrawInfo(CurrentContext);
6091   CurrentContext=CloneDrawInfo((ImageInfo *) NULL,(DrawInfo *) NULL);
6092   if (xml == (const char *) NULL)
6093     return(MagickFalse);
6094   xml_info=NewXMLTree(xml,wand->exception);
6095   if (xml_info == (XMLTreeInfo *) NULL)
6096     return(MagickFalse);
6097   child=GetXMLTreeChild(xml_info,"clip-path");
6098   if (child != (XMLTreeInfo *) NULL)
6099     (void) CloneString(&CurrentContext->clip_mask,GetXMLTreeContent(child));
6100   child=GetXMLTreeChild(xml_info,"clip-units");
6101   if (child != (XMLTreeInfo *) NULL)
6102     {
6103       value=GetXMLTreeContent(child);
6104       if (value != (const char *) NULL)
6105         CurrentContext->clip_units=(ClipPathUnits) ParseMagickOption(
6106           MagickClipPathOptions,MagickFalse,value);
6107     }
6108   child=GetXMLTreeChild(xml_info,"decorate");
6109   if (child != (XMLTreeInfo *) NULL)
6110     {
6111       value=GetXMLTreeContent(child);
6112       if (value != (const char *) NULL)
6113         CurrentContext->decorate=(DecorationType) ParseMagickOption(
6114           MagickDecorateOptions,MagickFalse,value);
6115     }
6116   child=GetXMLTreeChild(xml_info,"encoding");
6117   if (child != (XMLTreeInfo *) NULL)
6118     (void) CloneString(&CurrentContext->encoding,GetXMLTreeContent(child));
6119   child=GetXMLTreeChild(xml_info,"fill");
6120   if (child != (XMLTreeInfo *) NULL)
6121     {
6122       value=GetXMLTreeContent(child);
6123       if (value != (const char *) NULL)
6124         (void) QueryColorDatabase(value,&CurrentContext->fill,wand->exception);
6125     }
6126   child=GetXMLTreeChild(xml_info,"fill-opacity");
6127   if (child != (XMLTreeInfo *) NULL)
6128     {
6129       value=GetXMLTreeContent(child);
6130       if (value != (const char *) NULL)
6131         CurrentContext->fill.opacity=RoundToQuantum((MagickRealType)
6132           QuantumRange*(1.0-StringToDouble(value)));
6133     }
6134   child=GetXMLTreeChild(xml_info,"fill-rule");
6135   if (child != (XMLTreeInfo *) NULL)
6136     {
6137       value=GetXMLTreeContent(child);
6138       if (value != (const char *) NULL)
6139         CurrentContext->fill_rule=(FillRule) ParseMagickOption(
6140           MagickFillRuleOptions,MagickFalse,value);
6141     }
6142   child=GetXMLTreeChild(xml_info,"font");
6143   if (child != (XMLTreeInfo *) NULL)
6144     (void) CloneString(&CurrentContext->font,GetXMLTreeContent(child));
6145   child=GetXMLTreeChild(xml_info,"font-family");
6146   if (child != (XMLTreeInfo *) NULL)
6147     (void) CloneString(&CurrentContext->family,GetXMLTreeContent(child));
6148   child=GetXMLTreeChild(xml_info,"font-size");
6149   if (child != (XMLTreeInfo *) NULL)
6150     {
6151       value=GetXMLTreeContent(child);
6152       if (value != (const char *) NULL)
6153         CurrentContext->pointsize=StringToDouble(value);
6154     }
6155   child=GetXMLTreeChild(xml_info,"font-stretch");
6156   if (child != (XMLTreeInfo *) NULL)
6157     {
6158       value=GetXMLTreeContent(child);
6159       if (value != (const char *) NULL)
6160         CurrentContext->stretch=(StretchType) ParseMagickOption(
6161           MagickStretchOptions,MagickFalse,value);
6162     }
6163   child=GetXMLTreeChild(xml_info,"font-style");
6164   if (child != (XMLTreeInfo *) NULL)
6165     {
6166       value=GetXMLTreeContent(child);
6167       if (value != (const char *) NULL)
6168         CurrentContext->style=(StyleType) ParseMagickOption(MagickStyleOptions,
6169           MagickFalse,value);
6170     }
6171   child=GetXMLTreeChild(xml_info,"font-weight");
6172   if (child != (XMLTreeInfo *) NULL)
6173     {
6174       value=GetXMLTreeContent(child);
6175       if (value != (const char *) NULL)
6176         CurrentContext->weight=StringToUnsignedLong(value);
6177     }
6178   child=GetXMLTreeChild(xml_info,"gravity");
6179   if (child != (XMLTreeInfo *) NULL)
6180     {
6181       value=GetXMLTreeContent(child);
6182       if (value != (const char *) NULL)
6183         CurrentContext->gravity=(GravityType) ParseMagickOption(
6184           MagickGravityOptions,MagickFalse,value);
6185     }
6186   child=GetXMLTreeChild(xml_info,"stroke");
6187   if (child != (XMLTreeInfo *) NULL)
6188     {
6189       value=GetXMLTreeContent(child);
6190       if (value != (const char *) NULL)
6191         (void) QueryColorDatabase(value,&CurrentContext->stroke,
6192           wand->exception);
6193     }
6194   child=GetXMLTreeChild(xml_info,"stroke-antialias");
6195   if (child != (XMLTreeInfo *) NULL)
6196     {
6197       value=GetXMLTreeContent(child);
6198       if (value != (const char *) NULL)
6199         CurrentContext->stroke_antialias=StringToLong(value) != 0 ? MagickTrue :
6200           MagickFalse;
6201     }
6202   child=GetXMLTreeChild(xml_info,"stroke-dasharray");
6203   if (child != (XMLTreeInfo *) NULL)
6204     {
6205       char
6206         token[MaxTextExtent];
6207
6208       const char
6209         *q;
6210
6211       long
6212         j;
6213
6214       register long
6215         x;
6216
6217       value=GetXMLTreeContent(child);
6218       if (value != (const char *) NULL)
6219         {
6220           if (CurrentContext->dash_pattern != (double *) NULL)
6221             CurrentContext->dash_pattern=(double *) RelinquishMagickMemory(
6222               CurrentContext->dash_pattern);
6223           q=(char *) value;
6224           if (IsPoint(q) != MagickFalse)
6225             {
6226               const char
6227                 *p;
6228
6229               p=q;
6230               GetMagickToken(p,&p,token);
6231               if (*token == ',')
6232                 GetMagickToken(p,&p,token);
6233               for (x=0; IsPoint(token) != MagickFalse; x++)
6234               {
6235                 GetMagickToken(p,&p,token);
6236                 if (*token == ',')
6237                   GetMagickToken(p,&p,token);
6238               }
6239               CurrentContext->dash_pattern=(double *) AcquireQuantumMemory(
6240                 (size_t) (2UL*x)+1UL,sizeof(*CurrentContext->dash_pattern));
6241               if (CurrentContext->dash_pattern == (double *) NULL)
6242                 ThrowWandFatalException(ResourceLimitFatalError,
6243                   "MemoryAllocationFailed",wand->name);
6244               for (j=0; j < x; j++)
6245               {
6246                 GetMagickToken(q,&q,token);
6247                 if (*token == ',')
6248                   GetMagickToken(q,&q,token);
6249                 CurrentContext->dash_pattern[j]=StringToDouble(token);
6250               }
6251               if ((x & 0x01) != 0)
6252                 for ( ; j < (2*x); j++)
6253                   CurrentContext->dash_pattern[j]=
6254                     CurrentContext->dash_pattern[j-x];
6255               CurrentContext->dash_pattern[j]=0.0;
6256             }
6257         }
6258     }
6259   child=GetXMLTreeChild(xml_info,"stroke-dashoffset");
6260   if (child != (XMLTreeInfo *) NULL)
6261     {
6262       value=GetXMLTreeContent(child);
6263       if (value != (const char *) NULL)
6264         CurrentContext->dash_offset=StringToDouble(value);
6265     }
6266   child=GetXMLTreeChild(xml_info,"stroke-linecap");
6267   if (child != (XMLTreeInfo *) NULL)
6268     {
6269       value=GetXMLTreeContent(child);
6270       if (value != (const char *) NULL)
6271         CurrentContext->linecap=(LineCap) ParseMagickOption(
6272           MagickLineCapOptions,MagickFalse,value);
6273     }
6274   child=GetXMLTreeChild(xml_info,"stroke-linejoin");
6275   if (child != (XMLTreeInfo *) NULL)
6276     {
6277       value=GetXMLTreeContent(child);
6278       if (value != (const char *) NULL)
6279         CurrentContext->linejoin=(LineJoin) ParseMagickOption(
6280           MagickLineJoinOptions,MagickFalse,value);
6281     }
6282   child=GetXMLTreeChild(xml_info,"stroke-miterlimit");
6283   if (child != (XMLTreeInfo *) NULL)
6284     {
6285       value=GetXMLTreeContent(child);
6286       if (value != (const char *) NULL)
6287         CurrentContext->miterlimit=StringToUnsignedLong(value);
6288     }
6289   child=GetXMLTreeChild(xml_info,"stroke-opacity");
6290   if (child != (XMLTreeInfo *) NULL)
6291     {
6292       value=GetXMLTreeContent(child);
6293       if (value != (const char *) NULL)
6294         CurrentContext->stroke.opacity=RoundToQuantum((MagickRealType)
6295           QuantumRange*(1.0-StringToDouble(value)));
6296     }
6297   child=GetXMLTreeChild(xml_info,"stroke-width");
6298   if (child != (XMLTreeInfo *) NULL)
6299     {
6300       value=GetXMLTreeContent(child);
6301       if (value != (const char *) NULL)
6302         CurrentContext->stroke_width=StringToDouble(value);
6303     }
6304   child=GetXMLTreeChild(xml_info,"text-align");
6305   if (child != (XMLTreeInfo *) NULL)
6306     {
6307       value=GetXMLTreeContent(child);
6308       if (value != (const char *) NULL)
6309         CurrentContext->align=(AlignType) ParseMagickOption(MagickAlignOptions,
6310           MagickFalse,value);
6311     }
6312   child=GetXMLTreeChild(xml_info,"text-antialias");
6313   if (child != (XMLTreeInfo *) NULL)
6314     {
6315       value=GetXMLTreeContent(child);
6316       if (value != (const char *) NULL)
6317         CurrentContext->text_antialias=StringToLong(value) != 0 ? MagickTrue :
6318           MagickFalse;
6319     }
6320   child=GetXMLTreeChild(xml_info,"text-undercolor");
6321   if (child != (XMLTreeInfo *) NULL)
6322     {
6323       value=GetXMLTreeContent(child);
6324       if (value != (const char *) NULL)
6325         (void) QueryColorDatabase(value,&CurrentContext->undercolor,
6326           wand->exception);
6327     }
6328   child=GetXMLTreeChild(xml_info,"vector-graphics");
6329   if (child != (XMLTreeInfo *) NULL)
6330     {
6331       (void) CloneString(&wand->mvg,GetXMLTreeContent(child));
6332       wand->mvg_length=strlen(wand->mvg);
6333       wand->mvg_alloc=wand->mvg_length+1;
6334     }
6335   xml_info=DestroyXMLTree(xml_info);
6336   return(MagickTrue);
6337 }
6338 \f
6339 /*
6340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6341 %                                                                             %
6342 %                                                                             %
6343 %                                                                             %
6344 %   D r a w S k e w X                                                         %
6345 %                                                                             %
6346 %                                                                             %
6347 %                                                                             %
6348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6349 %
6350 %  DrawSkewX() skews the current coordinate system in the horizontal
6351 %  direction.
6352 %
6353 %  The format of the DrawSkewX method is:
6354 %
6355 %      void DrawSkewX(DrawingWand *wand,const double degrees)
6356 %
6357 %  A description of each parameter follows:
6358 %
6359 %    o wand: the drawing wand.
6360 %
6361 %    o degrees: number of degrees to skew the coordinates
6362 %
6363 */
6364 WandExport void DrawSkewX(DrawingWand *wand,const double degrees)
6365 {
6366   AffineMatrix
6367     affine;
6368
6369   assert(wand != (DrawingWand *) NULL);
6370   assert(wand->signature == WandSignature);
6371   if (wand->debug != MagickFalse)
6372     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6373   GetAffineMatrix(&affine);
6374   affine.ry=tan(DegreesToRadians(fmod(degrees,360.0)));
6375   AdjustAffine(wand,&affine);
6376   (void) MvgPrintf(wand,"skewX %g\n",degrees);
6377 }
6378 \f
6379 /*
6380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6381 %                                                                             %
6382 %                                                                             %
6383 %                                                                             %
6384 %   D r a w S k e w Y                                                         %
6385 %                                                                             %
6386 %                                                                             %
6387 %                                                                             %
6388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6389 %
6390 %  DrawSkewY() skews the current coordinate system in the vertical
6391 %  direction.
6392 %
6393 %  The format of the DrawSkewY method is:
6394 %
6395 %      void DrawSkewY(DrawingWand *wand,const double degrees)
6396 %
6397 %  A description of each parameter follows:
6398 %
6399 %    o wand: the drawing wand.
6400 %
6401 %    o degrees: number of degrees to skew the coordinates
6402 %
6403 */
6404 WandExport void DrawSkewY(DrawingWand *wand,const double degrees)
6405 {
6406   AffineMatrix
6407     affine;
6408
6409   assert(wand != (DrawingWand *) NULL);
6410   assert(wand->signature == WandSignature);
6411   if (wand->debug != MagickFalse)
6412     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6413   GetAffineMatrix(&affine);
6414   affine.rx=tan(DegreesToRadians(fmod(degrees,360.0)));
6415   DrawAffine(wand,&affine);
6416   (void) MvgPrintf(wand,"skewY %g\n",degrees);
6417 }
6418 \f
6419 /*
6420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6421 %                                                                             %
6422 %                                                                             %
6423 %                                                                             %
6424 %   D r a w T r a n s l a t e                                                 %
6425 %                                                                             %
6426 %                                                                             %
6427 %                                                                             %
6428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6429 %
6430 %  DrawTranslate() applies a translation to the current coordinate
6431 %  system which moves the coordinate system origin to the specified
6432 %  coordinate.
6433 %
6434 %  The format of the DrawTranslate method is:
6435 %
6436 %      void DrawTranslate(DrawingWand *wand,const double x,
6437 %        const double y)
6438 %
6439 %  A description of each parameter follows:
6440 %
6441 %    o wand: the drawing wand.
6442 %
6443 %    o x: new x ordinate for coordinate system origin
6444 %
6445 %    o y: new y ordinate for coordinate system origin
6446 %
6447 */
6448 WandExport void DrawTranslate(DrawingWand *wand,const double x,const double y)
6449 {
6450   AffineMatrix
6451     affine;
6452
6453   assert(wand != (DrawingWand *) NULL);
6454   assert(wand->signature == WandSignature);
6455   if (wand->debug != MagickFalse)
6456     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6457   GetAffineMatrix(&affine);
6458   affine.tx=x;
6459   affine.ty=y;
6460   AdjustAffine(wand,&affine);
6461   (void) MvgPrintf(wand,"translate %g,%g\n",x,y);
6462 }
6463 \f
6464 /*
6465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6466 %                                                                             %
6467 %                                                                             %
6468 %                                                                             %
6469 %   D r a w S e t V i e w b o x                                               %
6470 %                                                                             %
6471 %                                                                             %
6472 %                                                                             %
6473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6474 %
6475 %  DrawSetViewbox() sets the overall canvas size to be recorded with the
6476 %  drawing vector data.  Usually this will be specified using the same
6477 %  size as the canvas image.  When the vector data is saved to SVG or MVG
6478 %  formats, the viewbox is use to specify the size of the canvas image that
6479 %  a viewer will render the vector data on.
6480 %
6481 %  The format of the DrawSetViewbox method is:
6482 %
6483 %      void DrawSetViewbox(DrawingWand *wand,unsigned long x1,
6484 %        unsigned long y1,unsigned long x2,unsigned long y2)
6485 %
6486 %  A description of each parameter follows:
6487 %
6488 %    o wand: the drawing wand.
6489 %
6490 %    o x1: left x ordinate
6491 %
6492 %    o y1: top y ordinate
6493 %
6494 %    o x2: right x ordinate
6495 %
6496 %    o y2: bottom y ordinate
6497 %
6498 */
6499 WandExport void DrawSetViewbox(DrawingWand *wand,unsigned long x1,
6500   unsigned long y1,unsigned long x2,unsigned long y2)
6501 {
6502   assert(wand != (DrawingWand *) NULL);
6503   assert(wand->signature == WandSignature);
6504   if (wand->debug != MagickFalse)
6505     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6506   (void) MvgPrintf(wand,"viewbox %lu %lu %lu %lu\n",x1,y1,x2,y2);
6507 }
6508 \f
6509 /*
6510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6511 %                                                                             %
6512 %                                                                             %
6513 %                                                                             %
6514 %   I s D r a w i n g W a n d                                                 %
6515 %                                                                             %
6516 %                                                                             %
6517 %                                                                             %
6518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6519 %
6520 %  IsDrawingWand() returns MagickTrue if the wand is verified as a drawing wand.
6521 %
6522 %  The format of the IsDrawingWand method is:
6523 %
6524 %      MagickBooleanType IsDrawingWand(const DrawingWand *wand)
6525 %
6526 %  A description of each parameter follows:
6527 %
6528 %    o wand: the drawing wand.
6529 %
6530 */
6531 WandExport MagickBooleanType IsDrawingWand(const DrawingWand *wand)
6532 {
6533   if (wand == (const DrawingWand *) NULL)
6534     return(MagickFalse);
6535   if (wand->signature != WandSignature)
6536     return(MagickFalse);
6537   if (LocaleNCompare(wand->name,DrawingWandId,strlen(DrawingWandId)) != 0)
6538     return(MagickFalse);
6539   return(MagickTrue);
6540 }
6541 \f
6542 /*
6543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6544 %                                                                             %
6545 %                                                                             %
6546 %                                                                             %
6547 %   N e w D r a w i n g W a n d                                               %
6548 %                                                                             %
6549 %                                                                             %
6550 %                                                                             %
6551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6552 %
6553 %  NewDrawingWand() returns a drawing wand required for all other methods in
6554 %  the API.
6555 %
6556 %  The format of the NewDrawingWand method is:
6557 %
6558 %      DrawingWand NewDrawingWand(void)
6559 %
6560 */
6561 WandExport DrawingWand *NewDrawingWand(void)
6562 {
6563   const char
6564     *quantum;
6565
6566   DrawingWand
6567     *wand;
6568
6569   unsigned long
6570     depth;
6571
6572   quantum=GetMagickQuantumDepth(&depth);
6573   if (depth != MAGICKCORE_QUANTUM_DEPTH)
6574     ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
6575   wand=(DrawingWand *) AcquireAlignedMemory(1,sizeof(*wand));
6576   if (wand == (DrawingWand *) NULL)
6577     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
6578       GetExceptionMessage(errno));
6579   (void) ResetMagickMemory(wand,0,sizeof(*wand));
6580   wand->id=AcquireWandId();
6581   (void) FormatMagickString(wand->name,MaxTextExtent,"%s-%lu",DrawingWandId,
6582     wand->id);
6583   if (wand->debug != MagickFalse)
6584     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6585   wand->mvg=(char *) NULL;
6586   wand->mvg_alloc=0;
6587   wand->mvg_length=0;
6588   wand->mvg_width=0;
6589   wand->pattern_id=(char *) NULL;
6590   wand->pattern_offset=0;
6591   wand->pattern_bounds.x=0;
6592   wand->pattern_bounds.y=0;
6593   wand->pattern_bounds.width=0;
6594   wand->pattern_bounds.height=0;
6595   wand->index=0;
6596   wand->graphic_context=(DrawInfo **) AcquireAlignedMemory(1,sizeof(
6597     *wand->graphic_context));
6598   if (wand->graphic_context == (DrawInfo **) NULL)
6599     ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
6600       GetExceptionMessage(errno));
6601   wand->filter_off=MagickTrue;
6602   wand->indent_depth=0;
6603   wand->path_operation=PathDefaultOperation;
6604   wand->path_mode=DefaultPathMode;
6605   wand->image=AcquireImage((const ImageInfo *) NULL);
6606   wand->exception=AcquireExceptionInfo();
6607   wand->destroy=MagickTrue;
6608   wand->debug=IsEventLogging();
6609   wand->signature=WandSignature;
6610   CurrentContext=CloneDrawInfo((ImageInfo *) NULL,(DrawInfo *) NULL);
6611   return(wand);
6612 }
6613 \f
6614 /*
6615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6616 %                                                                             %
6617 %                                                                             %
6618 %                                                                             %
6619 %   P e e k D r a w i n g W a n d                                             %
6620 %                                                                             %
6621 %                                                                             %
6622 %                                                                             %
6623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6624 %
6625 %  PeekDrawingWand() returns the current drawing wand.
6626 %
6627 %  The format of the PeekDrawingWand method is:
6628 %
6629 %      DrawInfo *PeekDrawingWand(const DrawingWand *wand)
6630 %
6631 %  A description of each parameter follows:
6632 %
6633 %    o wand: the drawing wand.
6634 %
6635 */
6636 WandExport DrawInfo *PeekDrawingWand(const DrawingWand *wand)
6637 {
6638   DrawInfo
6639     *draw_info;
6640
6641   assert(wand != (const DrawingWand *) NULL);
6642   assert(wand->signature == WandSignature);
6643   if (wand->debug != MagickFalse)
6644     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6645   draw_info=CloneDrawInfo((ImageInfo *) NULL,CurrentContext);
6646   GetAffineMatrix(&draw_info->affine);
6647   (void) CloneString(&draw_info->primitive,wand->mvg);
6648   return(draw_info);
6649 }
6650 \f
6651 /*
6652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6653 %                                                                             %
6654 %                                                                             %
6655 %                                                                             %
6656 %   P o p D r a w i n g W a n d                                               %
6657 %                                                                             %
6658 %                                                                             %
6659 %                                                                             %
6660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6661 %
6662 %  PopDrawingWand() destroys the current drawing wand and returns to the
6663 %  previously pushed drawing wand. Multiple drawing wands may exist. It is an
6664 %  error to attempt to pop more drawing wands than have been pushed, and it is
6665 %  proper form to pop all drawing wands which have been pushed.
6666 %
6667 %  The format of the PopDrawingWand method is:
6668 %
6669 %      MagickBooleanType PopDrawingWand(DrawingWand *wand)
6670 %
6671 %  A description of each parameter follows:
6672 %
6673 %    o wand: the drawing wand.
6674 %
6675 */
6676 WandExport MagickBooleanType PopDrawingWand(DrawingWand *wand)
6677 {
6678   assert(wand != (DrawingWand *) NULL);
6679   assert(wand->signature == WandSignature);
6680   if (wand->debug != MagickFalse)
6681     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6682   if (wand->index == 0)
6683     {
6684       ThrowDrawException(DrawError,"UnbalancedGraphicContextPushPop",wand->name)
6685       return(MagickFalse);
6686     }
6687   /*
6688     Destroy clip path if not same in preceding wand.
6689   */
6690 #if DRAW_BINARY_IMPLEMENTATION
6691   if (wand->image == (Image *) NULL)
6692     ThrowDrawException(WandError,"ContainsNoImages",wand->name);
6693   if (CurrentContext->clip_mask != (char *) NULL)
6694     if (LocaleCompare(CurrentContext->clip_mask,
6695         wand->graphic_context[wand->index-1]->clip_mask) != 0)
6696       (void) SetImageClipMask(wand->image,(Image *) NULL);
6697 #endif
6698   CurrentContext=DestroyDrawInfo(CurrentContext);
6699   wand->index--;
6700   if (wand->indent_depth > 0)
6701     wand->indent_depth--;
6702   (void) MvgPrintf(wand,"pop graphic-context\n");
6703   return(MagickTrue);
6704 }
6705 \f
6706 /*
6707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6708 %                                                                             %
6709 %                                                                             %
6710 %                                                                             %
6711 %   P u s h D r a w i n g W a n d                                             %
6712 %                                                                             %
6713 %                                                                             %
6714 %                                                                             %
6715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6716 %
6717 %  PushDrawingWand() clones the current drawing wand to create a new drawing
6718 %  wand.  The original drawing wand(s) may be returned to by invoking
6719 %  PopDrawingWand().  The drawing wands are stored on a drawing wand stack.
6720 %  For every Pop there must have already been an equivalent Push.
6721 %
6722 %  The format of the PushDrawingWand method is:
6723 %
6724 %      MagickBooleanType PushDrawingWand(DrawingWand *wand)
6725 %
6726 %  A description of each parameter follows:
6727 %
6728 %    o wand: the drawing wand.
6729 %
6730 */
6731 WandExport MagickBooleanType PushDrawingWand(DrawingWand *wand)
6732 {
6733   assert(wand != (DrawingWand *) NULL);
6734   assert(wand->signature == WandSignature);
6735   if (wand->debug != MagickFalse)
6736     (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
6737   wand->index++;
6738   wand->graphic_context=(DrawInfo **) ResizeQuantumMemory(wand->graphic_context,
6739     (size_t) wand->index+1UL,sizeof(*wand->graphic_context));
6740   if (wand->graphic_context == (DrawInfo **) NULL)
6741     {
6742       ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
6743         wand->name);
6744       return(MagickFalse);
6745     }
6746   CurrentContext=CloneDrawInfo((ImageInfo *) NULL,
6747     wand->graphic_context[wand->index-1]);
6748   (void) MvgPrintf(wand,"push graphic-context\n");
6749   wand->indent_depth++;
6750   return(MagickTrue);
6751 }