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