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