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