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