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