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