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