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