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