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