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