root / ImageMagick / trunk / wand / drawing-wand.c

Revision 11686, 245.7 kB (checked in by cristy, 5 weeks ago)
Line 
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%                   ImageMagick Image Vector Drawing Methods                  %
20%                                                                             %
21%                              Software Design                                %
22%                              Bob Friesenhahn                                %
23%                                March 2002                                   %
24%                                                                             %
25%                                                                             %
26%  Copyright 1999-2008 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%    http://www.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
54/*
55  Define declarations.
56*/
57#define DRAW_BINARY_IMPLEMENTATION 0
58
59#define CurrentContext  (wand->graphic_context[wand->index])
60#define DrawingWandId  "DrawingWand"
61#define ThrowDrawException(severity,tag,reason) (void) ThrowMagickException( \
62  wand->exception,GetMagickModule(),severity,tag,"`%s'",reason);
63
64/*
65  Typedef declarations.
66*/
67typedef enum
68{
69  PathDefaultOperation,
70  PathCloseOperation,                        /* Z|z (none) */
71  PathCurveToOperation,                      /* C|c (x1 y1 x2 y2 x y)+ */
72  PathCurveToQuadraticBezierOperation,       /* Q|q (x1 y1 x y)+ */
73  PathCurveToQuadraticBezierSmoothOperation, /* T|t (x y)+ */
74  PathCurveToSmoothOperation,                /* S|s (x2 y2 x y)+ */
75  PathEllipticArcOperation,                  /* A|a (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ */
76  PathLineToHorizontalOperation,             /* H|h x+ */
77  PathLineToOperation,                       /* L|l (x y)+ */
78  PathLineToVerticalOperation,               /* V|v y+ */
79  PathMoveToOperation                        /* M|m (x y)+ */
80} PathOperation;
81
82typedef enum
83{
84  DefaultPathMode,
85  AbsolutePathMode,
86  RelativePathMode
87} PathMode;
88
89struct _DrawingWand
90{
91  unsigned long
92    id;
93
94  char
95    name[MaxTextExtent];
96
97  /* Support structures */
98  Image
99    *image;
100
101  ExceptionInfo
102    *exception;
103
104  /* MVG output string and housekeeping */
105  char
106    *mvg;               /* MVG data */
107
108  size_t
109    mvg_alloc,          /* total allocated memory */
110    mvg_length;         /* total MVG length */
111
112  unsigned long
113    mvg_width;          /* current line width */
114
115  /* Pattern support */
116  char
117    *pattern_id;
118
119  RectangleInfo
120    pattern_bounds;
121
122  size_t
123    pattern_offset;
124
125  /* Graphic wand */
126  unsigned long
127    index;              /* array index */
128
129  DrawInfo
130    **graphic_context;
131
132  MagickBooleanType
133    filter_off;         /* true if not filtering attributes */
134
135  /* Pretty-printing depth */
136  unsigned long
137    indent_depth;       /* number of left-hand pad characters */
138
139  /* Path operation support */
140  PathOperation
141    path_operation;
142
143  PathMode
144    path_mode;
145
146  MagickBooleanType
147    destroy,
148    debug;
149
150  unsigned long
151    signature;
152};
153
154/* Vector table for invoking subordinate renderers */
155struct _DrawVTable
156{
157  DrawingWand *(*DestroyDrawingWand) (DrawingWand *);
158  void (*DrawAnnotation)(DrawingWand *,const double,const double,
159    const unsigned char *);
160  void (*DrawArc)(DrawingWand *,const double,const double,const double,
161    const double,const double,const double);
162  void (*DrawBezier)(DrawingWand *,const unsigned long,const PointInfo *);
163  void (*DrawCircle)(DrawingWand *,const double,const double,const double,
164    const double);
165  void (*DrawColor)(DrawingWand *,const double,const double,const PaintMethod);
166  void (*DrawComment)(DrawingWand *,const char *);
167  void (*DrawEllipse)(DrawingWand *,const double,const double,const double,
168    const double,const double,const double);
169  MagickBooleanType (*DrawComposite)(DrawingWand *,const CompositeOperator,
170    const double,const double,const double,const double,const Image *);
171  void (*DrawLine)(DrawingWand *,const double,const double,const double,
172    const double);
173  void (*DrawMatte)(DrawingWand *,const double,const double,const PaintMethod);
174  void (*DrawPathClose)(DrawingWand *);
175  void (*DrawPathCurveToAbsolute)(DrawingWand *,const double,const double,
176    const double,const double,const double,const double);
177  void (*DrawPathCurveToRelative)(DrawingWand *,const double,const double,
178    const double,const double,const double,const double);
179  void (*DrawPathCurveToQuadraticBezierAbsolute)(DrawingWand *,const double,
180    const double,const double,const double);
181  void (*DrawPathCurveToQuadraticBezierRelative)(DrawingWand *,const double,
182    const double,const double,const double);
183  void (*DrawPathCurveToQuadraticBezierSmoothAbsolute)(DrawingWand *,
184    const double,const double);
185  void (*DrawPathCurveToQuadraticBezierSmoothRelative)(DrawingWand *,
186    const double,const double);
187  void (*DrawPathCurveToSmoothAbsolute)(DrawingWand *,const double,
188    const double,const double,const double);
189  void (*DrawPathCurveToSmoothRelative)(DrawingWand *,const double,
190    const double,const double,const double);
191  void (*DrawPathEllipticArcAbsolute)(DrawingWand *,const double,const double,
192    const double,const MagickBooleanType,const MagickBooleanType,const double,
193    const double);
194  void (*DrawPathEllipticArcRelative)(DrawingWand *,const double,const double,
195    const double,const MagickBooleanType,const MagickBooleanType,const double,
196    const double);
197  void (*DrawPathFinish)(DrawingWand *);
198  void (*DrawPathLineToAbsolute)(DrawingWand *,const double,const double);
199  void (*DrawPathLineToRelative)(DrawingWand *,const double,const double);
200  void (*DrawPathLineToHorizontalAbsolute)(DrawingWand *,const double);
201  void (*DrawPathLineToHorizontalRelative)(DrawingWand *,const double);
202  void (*DrawPathLineToVerticalAbsolute)(DrawingWand *,const double);
203  void (*DrawPathLineToVerticalRelative)(DrawingWand *,const double);
204  void (*DrawPathMoveToAbsolute)(DrawingWand *,const double,const double);
205  void (*DrawPathMoveToRelative)(DrawingWand *,const double,const double);
206  void (*DrawPathStart)(DrawingWand *);
207  void (*DrawPoint)(DrawingWand *,const double,const double);
208  void (*DrawPolygon)(DrawingWand *,const unsigned long,const PointInfo *);
209  void (*DrawPolyline)(DrawingWand *,const unsigned long,const PointInfo *);
210  void (*DrawPopClipPath)(DrawingWand *);
211  void (*DrawPopDefs)(DrawingWand *);
212  MagickBooleanType (*DrawPopPattern)(DrawingWand *);
213  void (*DrawPushClipPath)(DrawingWand *,const char *);
214  void (*DrawPushDefs)(DrawingWand *);
215  MagickBooleanType (*DrawPushPattern)(DrawingWand *,const char *,const double,
216    const double,const double,const double);
217  void (*DrawRectangle)(DrawingWand *,const double,const double,const double,
218    const double);
219  void (*DrawRoundRectangle)(DrawingWand *,double,double,double,double,
220    double,double);
221  void (*DrawAffine)(DrawingWand *,const AffineMatrix *);
222  MagickBooleanType (*DrawSetClipPath)(DrawingWand *,const char *);
223  void (*DrawSetClipRule)(DrawingWand *,const FillRule);
224  void (*DrawSetClipUnits)(DrawingWand *,const ClipPathUnits);
225  void (*DrawSetFillColor)(DrawingWand *,const PixelWand *);
226  void (*DrawSetFillRule)(DrawingWand *,const FillRule);
227  MagickBooleanType (*DrawSetFillPatternURL)(DrawingWand *,const char *);
228  MagickBooleanType (*DrawSetFont)(DrawingWand *,const char *);
229  MagickBooleanType (*DrawSetFontFamily)(DrawingWand *,const char *);
230  void (*DrawSetFontSize)(DrawingWand *,const double);
231  void (*DrawSetFontStretch)(DrawingWand *,const StretchType);
232  void (*DrawSetFontStyle)(DrawingWand *,const StyleType);
233  void (*DrawSetFontWeight)(DrawingWand *,const unsigned long);
234  void (*DrawSetGravity)(DrawingWand *,const GravityType);
235  void (*DrawRotate)(DrawingWand *,const double);
236  void (*DrawScale)(DrawingWand *,const double,const double);
237  void (*DrawSkewX)(DrawingWand *,const double);
238  void (*DrawSkewY)(DrawingWand *,const double);
239  void (*DrawSetStrokeAntialias)(DrawingWand *,const MagickBooleanType);
240  void (*DrawSetStrokeColor)(DrawingWand *,const PixelWand *);
241  MagickBooleanType (*DrawSetStrokeDashArray)(DrawingWand *,const double *);
242  void (*DrawSetStrokeDashOffset)(DrawingWand *,const double);
243  void (*DrawSetStrokeLineCap)(DrawingWand *,const LineCap);
244  void (*DrawSetStrokeLineJoin)(DrawingWand *,const LineJoin);
245  void (*DrawSetStrokeMiterLimit)(DrawingWand *,const unsigned long);
246  MagickBooleanType (*DrawSetStrokePatternURL)(DrawingWand *,const char *);
247  void (*DrawSetStrokeWidth)(DrawingWand *,const double);
248  void (*DrawSetTextAntialias)(DrawingWand *,const MagickBooleanType);
249  void (*DrawSetTextDecoration)(DrawingWand *,const DecorationType);
250  void (*DrawSetTextUnderColor)(DrawingWand *,const PixelWand *);
251  void (*DrawTranslate)(DrawingWand *,const double,const double);
252  void (*DrawSetViewbox)(DrawingWand *,unsigned long,unsigned long,
253    unsigned long,unsigned long);
254  void (*PeekDrawingWand)(DrawingWand *);
255  MagickBooleanType (*PopDrawingWand)(DrawingWand *);
256  MagickBooleanType (*PushDrawingWand)(DrawingWand *);
257};
258
259/*
260  Forward declarations.
261*/
262static int
263  MvgPrintf(DrawingWand *,const char *,...) wand_attribute((format
264    (printf,2,3))),
265  MvgAutoWrapPrintf(DrawingWand *,const char *,...) wand_attribute((format
266    (printf,2,3)));
267
268static void
269  MvgAppendColor(DrawingWand *,const PixelPacket *);
270
271/*
272  "Printf" for MVG commands
273*/
274static int MvgPrintf(DrawingWand *wand,const char *format,...)
275{
276  size_t
277    alloc_size;
278
279  if (wand->debug != MagickFalse)
280    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",format);
281  assert(wand != (DrawingWand *) NULL);
282  assert(wand->signature == WandSignature);
283  alloc_size=20UL*MaxTextExtent;
284  if (wand->mvg == (char *) NULL)
285    {
286      wand->mvg=(char *) AcquireQuantumMemory(alloc_size,sizeof(*wand->mvg));
287      if (wand->mvg == (char *) NULL)
288        {
289          ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
290            wand->name);
291          return(-1);
292        }
293      wand->mvg_alloc=alloc_size;
294      wand->mvg_length=0;
295    }
296  if (wand->mvg_alloc < (wand->mvg_length+10*MaxTextExtent))
297    {
298      size_t
299        realloc_size;
300
301      realloc_size=wand->mvg_alloc+alloc_size;
302      wand->mvg=(char *) ResizeQuantumMemory(wand->mvg,realloc_size,
303        sizeof(*wand->mvg));
304      if (wand->mvg == (char *) NULL)
305        {
306          ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
307            wand->name);
308          return -1;
309        }
310      wand->mvg_alloc=realloc_size;
311    }
312  {
313    int
314      formatted_length;
315
316    va_list
317      argp;
318
319    while (wand->mvg_width < wand->indent_depth)
320    {
321      wand->mvg[wand->mvg_length]=' ';
322      wand->mvg_length++;
323      wand->mvg_width++;
324    }
325    wand->mvg[wand->mvg_length]='\0';
326    va_start(argp, format);
327#if defined(MAGICKCORE_HAVE_VSNPRINTF)
328    formatted_length=vsnprintf(wand->mvg+wand->mvg_length,
329      wand->mvg_alloc-wand->mvg_length-1,format,argp);
330#else
331    formatted_length=vsprintf(wand->mvg+wand->mvg_length,
332      format,argp);
333#endif
334    va_end(argp);
335    if (formatted_length < 0)
336      ThrowDrawException(DrawError,"UnableToPrint",format)
337    else
338      {
339        wand->mvg_length+=formatted_length;
340        wand->mvg_width+=formatted_length;
341      }
342    wand->mvg[wand->mvg_length]='\0';
343    if ((wand->mvg_length > 1) &&
344        (wand->mvg[wand->mvg_length-1] == '\n'))
345      wand->mvg_width=0;
346    assert((wand->mvg_length+1) < wand->mvg_alloc);
347    return formatted_length;
348  }
349}
350
351static int MvgAutoWrapPrintf(DrawingWand *wand,const char *format,...)
352{
353  char
354    buffer[MaxTextExtent];
355
356  int
357    formatted_length;
358
359  va_list
360    argp;
361
362  va_start(argp,format);
363#if defined(MAGICKCORE_HAVE_VSNPRINTF)
364  formatted_length=vsnprintf(buffer,sizeof(buffer)-1,format,argp);
365#else
366  formatted_length=vsprintf(buffer,format,argp);
367#endif
368  va_end(argp);
369  *(buffer+sizeof(buffer)-1)='\0';
370  if (formatted_length < 0)
371    ThrowDrawException(DrawError,"UnableToPrint",format)
372  else
373    {
374      if (((wand->mvg_width + formatted_length) > 78) &&
375          (buffer[formatted_length-1] != '\n'))
376        (void) MvgPrintf(wand, "\n");
377      (void) MvgPrintf(wand,"%s",buffer);
378    }
379  return(formatted_length);
380}
381
382static void MvgAppendColor(DrawingWand *wand,const PixelPacket *color)
383{
384  if ((color->red == 0) && (color->green == 0) && (color->blue == 0) &&
385     (color->opacity == (Quantum) TransparentOpacity))
386    (void) MvgPrintf(wand,"none");
387  else
388    {
389      char
390        tuple[MaxTextExtent];
391
392      MagickPixelPacket
393        pixel;
394
395      GetMagickPixelPacket(wand->image,&pixel);
396      pixel.colorspace=RGBColorspace;
397      pixel.matte=color->opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
398      pixel.red=(MagickRealType) color->red;
399      pixel.green=(MagickRealType) color->green;
400      pixel.blue=(MagickRealType) color->blue;
401      pixel.opacity=(MagickRealType) color->opacity;
402      GetColorTuple(&pixel,MagickTrue,tuple);
403      (void) MvgPrintf(wand,"%s",tuple);
404    }
405}
406
407static void MvgAppendPointsCommand(DrawingWand *wand,const char *command,
408  const unsigned long number_coordinates,const PointInfo *coordinates)
409{
410  const PointInfo
411    *coordinate;
412
413  unsigned long
414    i;
415
416  (void) MvgPrintf(wand,"%s",command);
417  for (i=number_coordinates, coordinate=coordinates; i != 0; i--)
418  {
419    (void) MvgAutoWrapPrintf(wand," %g,%g",coordinate->x,coordinate->y);
420    coordinate++;
421  }
422  (void) MvgPrintf(wand, "\n");
423}
424
425static void AdjustAffine(DrawingWand *wand,const AffineMatrix *affine)
426{
427  assert(wand != (DrawingWand *) NULL);
428  assert(wand->signature == WandSignature);
429  if (wand->debug != MagickFalse)
430    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
431  if ((affine->sx != 1.0) || (affine->rx != 0.0) || (affine->ry != 0.0) ||
432      (affine->sy != 1.0) || (affine->tx != 0.0) || (affine->ty != 0.0))
433    {
434      AffineMatrix
435        current;
436
437      current=CurrentContext->affine;
438      CurrentContext->affine.sx=current.sx*affine->sx+current.ry*affine->rx;
439      CurrentContext->affine.rx=current.rx*affine->sx+current.sy*affine->rx;
440      CurrentContext->affine.ry=current.sx*affine->ry+current.ry*affine->sy;
441      CurrentContext->affine.sy=current.rx*affine->ry+current.sy*affine->sy;
442      CurrentContext->affine.tx=current.sx*affine->tx+current.ry*affine->ty+
443        current.tx;
444      CurrentContext->affine.ty=current.rx*affine->tx+current.sy*affine->ty+
445        current.ty;
446    }
447}
448
449/*
450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451%                                                                             %
452%                                                                             %
453%                                                                             %
454%   C l e a r D r a w i n g W a n d                                           %
455%                                                                             %
456%                                                                             %
457%                                                                             %
458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459%
460%  ClearDrawingWand() clear resources associated with the drawing wand.
461%
462%  The format of the ClearDrawingWand method is:
463%
464%      DrawingWand *ClearDrawingWand(DrawingWand *wand)
465%
466%  A description of each parameter follows:
467%
468%    o wand: the drawing wand. to destroy
469%
470*/
471WandExport void ClearDrawingWand(DrawingWand *wand)
472{
473  assert(wand != (DrawingWand *) NULL);
474  assert(wand->signature == WandSignature);
475  if (wand->debug != MagickFalse)
476    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
477  for ( ; wand->index > 0; wand->index--)
478    CurrentContext=DestroyDrawInfo(CurrentContext);
479  CurrentContext=DestroyDrawInfo(CurrentContext);
480  wand->graphic_context=(DrawInfo **) RelinquishMagickMemory(
481    wand->graphic_context);
482  if (wand->pattern_id != (char *) NULL)
483    wand->pattern_id=DestroyString(wand->pattern_id);
484  wand->mvg=DestroyString(wand->mvg);
485  if ((wand->destroy != MagickFalse) && (wand->image != (Image *) NULL))
486    wand->image=DestroyImage(wand->image);
487  else
488    wand->image=(Image *) NULL;
489  wand->mvg=(char *) NULL;
490  wand->mvg_alloc=0;
491  wand->mvg_length=0;
492  wand->mvg_width=0;
493  wand->pattern_id=(char *) NULL;
494  wand->pattern_offset=0;
495  wand->pattern_bounds.x=0;
496  wand->pattern_bounds.y=0;
497  wand->pattern_bounds.width=0;
498  wand->pattern_bounds.height=0;
499  wand->index=0;
500  wand->graphic_context=(DrawInfo **) AcquireMagickMemory(
501    sizeof(*wand->graphic_context));
502  if (wand->graphic_context == (DrawInfo **) NULL)
503    {
504      ThrowDrawException(ResourceLimitError,"MemoryAllocationFailed",
505        wand->name);
506      return;
507    }
508  CurrentContext=CloneDrawInfo((ImageInfo *) NULL,(DrawInfo *) NULL);
509  wand->filter_off=MagickFalse;
510  wand->indent_depth=0;
511  wand->path_operation=PathDefaultOperation;
512  wand->path_mode=DefaultPathMode;
513  wand->image=AcquireImage((const ImageInfo *) NULL);
514  ClearMagickException(wand->exception);
515  wand->destroy=MagickTrue;
516  wand->debug=IsEventLogging();
517}
518
519/*
520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521%                                                                             %
522%                                                                             %
523%                                                                             %
524%   C l o n e D r a w i n g W a n d                                           %
525%                                                                             %
526%                                                                             %
527%                                                                             %
528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
529%
530%  CloneDrawingWand() makes an exact copy of the specified wand.
531%
532%  The format of the CloneDrawingWand method is:
533%
534%      DrawingWand *CloneDrawingWand(const DrawingWand *wand)
535%
536%  A description of each parameter follows:
537%
538%    o wand: the magick wand.
539%
540%
541*/
542WandExport DrawingWand *CloneDrawingWand(const DrawingWand *wand)
543{
544  DrawingWand
545    *clone_wand;
546
547  register long
548    i;
549
550  assert(wand != (DrawingWand *) NULL);
551  assert(wand->signature == WandSignature);
552  if (wand->debug != MagickFalse)
553    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
554  clone_wand=(DrawingWand *) AcquireMagickMemory(sizeof(*clone_wand));
555  if (clone_wand == (DrawingWand *) NULL)
556    ThrowWandFatalException(ResourceLimitFatalError,
557      "MemoryAllocationFailed",strerror(errno));
558  (void) ResetMagickMemory(clone_wand,0,sizeof(*clone_wand));
559  clone_wand->id=AcquireWandId();
560  (void) FormatMagickString(clone_wand->name,MaxTextExtent,"DrawingWand-%lu",
561    clone_wand->id);
562  clone_wand->exception=AcquireExceptionInfo();
563  InheritException(clone_wand->exception,wand->exception);
564  clone_wand->mvg=AcquireString(wand->mvg);
565  clone_wand->mvg_length=strlen(clone_wand->mvg);
566  clone_wand->mvg_alloc=wand->mvg_length+1;
567  clone_wand->mvg_width=wand->mvg_width;
568  clone_wand->pattern_id=AcquireString(wand->pattern_id);
569  clone_wand->pattern_offset=wand->pattern_offset;
570  clone_wand->pattern_bounds=wand->pattern_bounds;
571  clone_wand->index=wand->index;
572  clone_wand->graphic_context=(DrawInfo **) AcquireQuantumMemory((size_t)
573    wand->index+1UL,sizeof(*wand->graphic_context));
574  if (clone_wand->graphic_context == (DrawInfo **) NULL)
575    ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
576      strerror(errno));
577  for (i=0; i <= (long) wand->index; i++)
578    clone_wand->graphic_context[i]=
579      CloneDrawInfo((ImageInfo *) NULL,wand->graphic_context[i]);
580  clone_wand->filter_off=wand->filter_off;
581  clone_wand->indent_depth=wand->indent_depth;
582  clone_wand->path_operation=wand->path_operation;
583  clone_wand->path_mode=wand->path_mode;
584  clone_wand->image=wand->image;
585  if (wand->image != (Image *) NULL)
586    clone_wand->image=CloneImage(wand->image,0,0,MagickTrue,
587      clone_wand->exception);
588  clone_wand->destroy=wand->destroy;
589  clone_wand->debug=IsEventLogging();
590  if (clone_wand->debug != MagickFalse)
591    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_wand->name);
592  clone_wand->signature=WandSignature;
593  return(clone_wand);
594}
595
596/*
597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598%                                                                             %
599%                                                                             %
600%                                                                             %
601%   D e s t r o y D r a w i n g W a n d                                       %
602%                                                                             %
603%                                                                             %
604%                                                                             %
605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606%
607%  DestroyDrawingWand() frees all resources associated with the drawing wand.
608%  Once the drawing wand has been freed, it should not be used and further
609%  unless it re-allocated.
610%
611%  The format of the DestroyDrawingWand method is:
612%
613%      DrawingWand *DestroyDrawingWand(DrawingWand *wand)
614%
615%  A description of each parameter follows:
616%
617%    o wand: the drawing wand. to destroy
618%
619*/
620WandExport DrawingWand *DestroyDrawingWand(DrawingWand *wand)
621{
622  assert(wand != (DrawingWand *) NULL);
623  assert(wand->signature == WandSignature);
624  if (wand->debug != MagickFalse)
625    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
626  for ( ; wand->index > 0; wand->index--)
627    CurrentContext=DestroyDrawInfo(CurrentContext);
628  CurrentContext=DestroyDrawInfo(CurrentContext);
629  wand->graphic_context=(DrawInfo **) RelinquishMagickMemory(
630    wand->graphic_context);
631  if (wand->pattern_id != (char *) NULL)
632    wand->pattern_id=DestroyString(wand->pattern_id);
633  wand->mvg=DestroyString(wand->mvg);
634  if ((wand->destroy != MagickFalse) && (wand->image != (Image *) NULL))
635    wand->image=DestroyImage(wand->image);
636  wand->image=(Image *) NULL;
637  wand->exception=DestroyExceptionInfo(wand->exception);
638  wand->signature=(~WandSignature);
639  RelinquishWandId(wand->id);
640  wand=(DrawingWand *) RelinquishMagickMemory(wand);
641  return(wand);
642}
643
644/*
645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646%                                                                             %
647%                                                                             %
648%                                                                             %
649%   D r a w A f f i n e                                                       %
650%                                                                             %
651%                                                                             %
652%                                                                             %
653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654%
655%  DrawAffine() adjusts the current affine transformation matrix with
656%  the specified affine transformation matrix. Note that the current affine
657%  transform is adjusted rather than replaced.
658%
659%  The format of the DrawAffine method is:
660%
661%      void DrawAffine(DrawingWand *wand,const AffineMatrix *affine)
662%
663%  A description of each parameter follows:
664%
665%    o wand: Drawing wand
666%
667%    o affine: Affine matrix parameters
668%
669*/
670WandExport void DrawAffine(DrawingWand *wand,const AffineMatrix *affine)
671{
672  assert(wand != (DrawingWand *) NULL);
673  assert(wand->signature == WandSignature);
674  if (wand->debug != MagickFalse)
675    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
676  assert(affine != (const AffineMatrix *) NULL);
677  AdjustAffine(wand,affine);
678  (void) MvgPrintf(wand,"affine %g,%g,%g,%g,%g,%g\n",affine->sx,affine->rx,
679    affine->ry,affine->sy,affine->tx,affine->ty);
680}
681
682/*
683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684%                                                                             %
685%                                                                             %
686%                                                                             %
687+   D r a w A l l o c a t e W a n d                                           %
688%                                                                             %
689%                                                                             %
690%                                                                             %
691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692%
693%  DrawAllocateWand() allocates an initial drawing wand which is an
694%  opaque handle required by the remaining drawing methods.
695%
696%  The format of the DrawAllocateWand method is:
697%
698%      DrawingWand DrawAllocateWand(const DrawInfo *draw_info,Image *image)
699%
700%  A description of each parameter follows:
701%
702%    o draw_info: Initial drawing defaults. Set to NULL to use
703%                 ImageMagick defaults.
704%
705%    o image: the image to draw on.
706%
707*/
708WandExport DrawingWand *DrawAllocateWand(const DrawInfo *draw_info,Image *image)
709{
710  DrawingWand
711    *wand;
712
713  wand=NewDrawingWand();
714  if (draw_info != (const DrawInfo *) NULL)
715    {
716      CurrentContext=DestroyDrawInfo(CurrentContext);
717      CurrentContext=CloneDrawInfo((ImageInfo *) NULL,draw_info);
718    }
719  if (image != (Image *) NULL)
720    {
721      wand->image=DestroyImage(wand->image);
722      wand->destroy=MagickFalse;
723    }
724  wand->image=image;
725  return(wand);
726}
727
728/*
729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730%                                                                             %
731%                                                                             %
732%                                                                             %
733%   D r a w A n n o t a t i o n                                               %
734%                                                                             %
735%                                                                             %
736%                                                                             %
737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
738%
739%  DrawAnnotation() draws text on the image.
740%
741%  The format of the DrawAnnotation method is:
742%
743%      void DrawAnnotation(DrawingWand *wand,const double x,
744%        const double y,const unsigned char *text)
745%
746%  A description of each parameter follows:
747%
748%    o wand: the drawing wand.
749%
750%    o x: x ordinate to left of text
751%
752%    o y: y ordinate to text baseline
753%
754%    o text: text to draw
755%
756*/
757WandExport void DrawAnnotation(DrawingWand *wand,const double x,const double y,
758  const unsigned char *text)
759{
760  char
761    *escaped_text;
762
763  assert(wand != (DrawingWand *) NULL);
764  assert(wand->signature == WandSignature);
765  if (wand->debug != MagickFalse)
766    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
767  assert(text != (const unsigned char *) NULL);
768  escaped_text=EscapeString((const char *) text,'\'');
769  (void) MvgPrintf(wand,"text %g,%g '%s'\n",x,y,escaped_text);
770  escaped_text=DestroyString(escaped_text);
771}
772
773/*
774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
775%                                                                             %
776%                                                                             %
777%                                                                             %
778%   D r a w A r c                                                             %
779%                                                                             %
780%                                                                             %
781%                                                                             %
782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783%
784%  DrawArc() draws an arc falling within a specified bounding rectangle on the
785%  image.
786%
787%  The format of the DrawArc method is:
788%
789%      void DrawArc(DrawingWand *wand,const double sx,const double sy,
790%        const double ex,const double ey,const double sd,const double ed)
791%
792%  A description of each parameter follows:
793%
794%    o wand: the drawing wand.
795%
796%    o sx: starting x ordinate of bounding rectangle
797%
798%    o sy: starting y ordinate of bounding rectangle
799%
800%    o ex: ending x ordinate of bounding rectangle
801%
802%    o ey: ending y ordinate of bounding rectangle
803%
804%    o sd: starting degrees of rotation
805%
806%    o ed: ending degrees of rotation
807%
808*/
809WandExport void DrawArc(DrawingWand *wand,const double sx,const double sy,
810  const double ex,const double ey,const double sd,const double ed)
811{
812  assert(wand != (DrawingWand *) NULL);
813  assert(wand->signature == WandSignature);
814  if (wand->debug != MagickFalse)
815    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
816  (void) MvgPrintf(wand,"arc %g,%g %g,%g %g,%g\n",sx,sy,ex,ey,sd,ed);
817}
818
819/*
820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821%                                                                             %
822%                                                                             %
823%                                                                             %
824%   D r a w B e z i e r                                                       %
825%                                                                             %
826%                                                                             %
827%                                                                             %
828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829%
830%  DrawBezier() draws a bezier curve through a set of points on the image.
831%
832%  The format of the DrawBezier method is:
833%
834%      void DrawBezier(DrawingWand *wand,
835%        const unsigned long number_coordinates,const PointInfo *coordinates)
836%
837%  A description of each parameter follows:
838%
839%    o wand: the drawing wand.
840%
841%    o number_coordinates: number of coordinates
842%
843%    o coordinates: coordinates
844%
845*/
846WandExport void DrawBezier(DrawingWand *wand,
847  const unsigned long number_coordinates,const PointInfo *coordinates)
848{
849  assert(wand != (DrawingWand *) NULL);
850  assert(wand->signature == WandSignature);
851  if (wand->debug != MagickFalse)
852    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
853  assert(coordinates != (const PointInfo *) NULL);
854  MvgAppendPointsCommand(wand,"bezier",number_coordinates,coordinates);
855}
856
857/*
858%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
859%                                                                             %
860%                                                                             %
861%                                                                             %
862%   D r a w C i r c l e                                                       %
863%