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