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