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