]> granicus.if.org Git - imagemagick/blob - Magick++/lib/Options.cpp
Added text kerning/spacing to Magick++.
[imagemagick] / Magick++ / lib / Options.cpp
1 // This may look like C code, but it is really -*- C++ -*-
2 //
3 // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003
4 //
5 // Implementation of Options
6 //
7 // A wrapper around DrawInfo, ImageInfo, and QuantizeInfo
8 //
9
10 #define MAGICKCORE_IMPLEMENTATION  1
11 #define MAGICK_PLUSPLUS_IMPLEMENTATION 1
12
13 #include "Magick++/Include.h"
14 #include <string>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <math.h>
18
19 #include "Magick++/Options.h"
20 #include "Magick++/Functions.h"
21 #include "Magick++/Exception.h"
22
23 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
24 #define GetPPException \
25   ExceptionInfo \
26     exceptionInfo; \
27   GetExceptionInfo(&exceptionInfo)
28 #define ThrowPPException \
29   throwException(exceptionInfo); \
30   (void) DestroyExceptionInfo(&exceptionInfo)
31
32 Magick::Options::Options(void)
33   : _imageInfo(static_cast<ImageInfo*>(AcquireMagickMemory(
34       sizeof(ImageInfo)))),
35     _quantizeInfo(static_cast<QuantizeInfo*>(AcquireMagickMemory(
36       sizeof(QuantizeInfo)))),
37     _drawInfo(static_cast<DrawInfo*>(AcquireMagickMemory(sizeof(DrawInfo))))
38 {
39   // Initialize image info with defaults
40   GetImageInfo(_imageInfo);
41
42   // Initialize quantization info
43   GetQuantizeInfo(_quantizeInfo);
44
45   // Initialize drawing info
46   GetDrawInfo(_imageInfo,_drawInfo);
47 }
48
49 Magick::Options::Options(const Magick::Options& options_)
50   : _imageInfo(CloneImageInfo(options_._imageInfo )),
51     _quantizeInfo(CloneQuantizeInfo(options_._quantizeInfo)),
52     _drawInfo(CloneDrawInfo(_imageInfo,options_._drawInfo))
53 {
54 }
55
56 Magick::Options::~Options()
57 {
58   // Destroy image info
59    _imageInfo=DestroyImageInfo(_imageInfo);
60
61   // Destroy quantization info
62    _quantizeInfo=DestroyQuantizeInfo(_quantizeInfo);
63
64   // Destroy drawing info
65    _drawInfo=DestroyDrawInfo(_drawInfo);
66 }
67
68 void Magick::Options::antiAlias(bool flag_)
69 {
70   _drawInfo->text_antialias=static_cast<MagickBooleanType>(
71     flag_ ? MagickTrue : MagickFalse);
72 }
73
74 bool Magick::Options::antiAlias(void) const
75 {
76   return(static_cast<bool>(_drawInfo->text_antialias));
77 }
78
79 void Magick::Options::adjoin(bool flag_)
80 {
81   _imageInfo->adjoin=static_cast<MagickBooleanType>(
82     flag_ ? MagickTrue : MagickFalse);
83 }
84
85 bool Magick::Options::adjoin(void) const
86 {
87   return(static_cast<bool>(_imageInfo->adjoin));
88 }
89
90 void Magick::Options::backgroundColor(const Magick::Color &color_)
91 {
92   _imageInfo->background_color=color_;
93 }
94
95 Magick::Color Magick::Options::backgroundColor(void) const
96 {
97   return(Magick::Color(_imageInfo->background_color));
98 }
99
100 void Magick::Options::backgroundTexture(const std::string &backgroundTexture_)
101 {
102   if (backgroundTexture_.length() == 0)
103     _imageInfo->texture=(char *) RelinquishMagickMemory(_imageInfo->texture);
104   else
105     Magick::CloneString(&_imageInfo->texture,backgroundTexture_);
106 }
107
108 std::string Magick::Options::backgroundTexture(void) const
109 {
110   if (_imageInfo->texture)
111     return(std::string(_imageInfo->texture));
112   else
113     return(std::string());
114 }
115
116 void Magick::Options::borderColor(const Color &color_)
117 {
118   _imageInfo->border_color=color_;
119   _drawInfo->border_color=color_;
120 }
121
122 Magick::Color Magick::Options::borderColor(void) const
123 {
124   return(Magick::Color(_imageInfo->border_color));
125 }
126
127 void Magick::Options::boxColor(const Magick::Color &boxColor_)
128 {
129   _drawInfo->undercolor=boxColor_;
130 }
131
132 Magick::Color Magick::Options::boxColor(void) const
133 {
134   return(Magick::Color(_drawInfo->undercolor));
135 }
136
137 void Magick::Options::colorspaceType(Magick::ColorspaceType colorspace_)
138 {
139   _imageInfo->colorspace=colorspace_;
140 }
141
142 Magick::ColorspaceType Magick::Options::colorspaceType(void) const
143 {
144   return(static_cast<Magick::ColorspaceType>(_imageInfo->colorspace));
145 }
146
147 void Magick::Options::compressType(CompressionType compressType_)
148 {
149   _imageInfo->compression=compressType_;
150 }
151
152 Magick::CompressionType Magick::Options::compressType(void) const
153 {
154   return(static_cast<Magick::CompressionType>(_imageInfo->compression));
155 }
156
157 void Magick::Options::colorFuzz(double fuzz_)
158 {
159   _imageInfo->fuzz=fuzz_;
160 }
161
162 double Magick::Options::colorFuzz(void) const
163 {
164   return(_imageInfo->fuzz);
165 }
166
167 void Magick::Options::debug(bool flag_)
168 {
169   if  (flag_)
170     SetLogEventMask("All");
171   else
172     SetLogEventMask("None");
173 }
174
175 bool Magick::Options::debug(void) const
176 {
177   if (IsEventLogging())
178     return(true);
179   return(false);
180 }
181
182 void Magick::Options::density(const Magick::Geometry &density_)
183 {
184   if ( !density_.isValid() )
185     _imageInfo->density=(char *) RelinquishMagickMemory(_imageInfo->density);
186   else
187     Magick::CloneString(&_imageInfo->density,density_);
188 }
189
190 Magick::Geometry Magick::Options::density(void) const
191 {
192   if (_imageInfo->density)
193     return(Geometry(_imageInfo->density));
194
195   return(Geometry());
196 }
197
198 void Magick::Options::depth(size_t depth_)
199 {
200   _imageInfo->depth=depth_;
201 }
202
203 size_t Magick::Options::depth(void) const
204 {
205   return(_imageInfo->depth);
206 }
207
208 void Magick::Options::endian(Magick::EndianType endian_)
209 {
210   _imageInfo->endian=endian_;
211 }
212
213 Magick::EndianType Magick::Options::endian(void) const
214 {
215   return(_imageInfo->endian);
216 }
217
218 void Magick::Options::file(FILE *file_)
219 {
220   SetImageInfoFile(_imageInfo,file_);
221 }
222
223 FILE *Magick::Options::file(void) const
224 {
225   return(GetImageInfoFile(_imageInfo));
226 }
227
228 void Magick::Options::fileName(const std::string &fileName_)
229 {
230   fileName_.copy(_imageInfo->filename,MaxTextExtent-1);
231   if (fileName_.length() > MaxTextExtent-1)
232     _imageInfo->filename[MaxTextExtent-1]=0;
233   else
234     _imageInfo->filename[fileName_.length()]=0;
235 }
236
237 std::string Magick::Options::fileName(void) const
238 {
239   return(std::string(_imageInfo->filename));
240 }
241
242 void Magick::Options::fillColor(const Magick::Color &fillColor_)
243 {
244   _drawInfo->fill=fillColor_;
245   if (fillColor_ == Magick::Color())
246     fillPattern((const MagickCore::Image*) NULL);
247 }
248
249 Magick::Color Magick::Options::fillColor(void) const
250 {
251   return(_drawInfo->fill);
252 }
253
254 void Magick::Options::fillPattern(const MagickCore::Image *fillPattern_)
255 {
256   if (_drawInfo->fill_pattern)
257       _drawInfo->fill_pattern=DestroyImageList(_drawInfo->fill_pattern);
258
259   if (fillPattern_)
260     {
261       GetPPException;
262       _drawInfo->fill_pattern=CloneImage(const_cast<MagickCore::Image*>(
263         fillPattern_),0,0,static_cast<MagickBooleanType>(MagickTrue),
264         &exceptionInfo);
265       ThrowPPException;
266     }
267 }
268
269 const MagickCore::Image *Magick::Options::fillPattern(void) const
270 {
271   return(_drawInfo->fill_pattern);
272 }
273
274 void Magick::Options::fillRule(const Magick::FillRule &fillRule_)
275 {
276   _drawInfo->fill_rule=fillRule_;
277 }
278
279 Magick::FillRule Magick::Options::fillRule(void) const
280 {
281   return(_drawInfo->fill_rule);
282 }
283
284 void Magick::Options::font(const std::string &font_)
285 {
286   if (font_.length() == 0)
287     {
288       _imageInfo->font=(char *) RelinquishMagickMemory(_imageInfo->font);
289       _drawInfo->font=(char *) RelinquishMagickMemory(_drawInfo->font);
290     }
291   else
292     {
293       Magick::CloneString(&_imageInfo->font,font_);
294       Magick::CloneString(&_drawInfo->font,font_);
295     }
296 }
297
298 std::string Magick::Options::font(void) const
299 {
300   if (_imageInfo->font)
301     return(std::string(_imageInfo->font));
302   
303   return(std::string());
304 }
305
306 void Magick::Options::fontPointsize(double pointSize_)
307 {
308   _imageInfo->pointsize=pointSize_;
309   _drawInfo->pointsize=pointSize_;
310 }
311
312 double Magick::Options::fontPointsize(void) const
313 {
314   return(_imageInfo->pointsize);
315 }
316
317 std::string Magick::Options::format(void) const
318 {
319   const MagickInfo
320     *magick_info=0;
321
322   GetPPException;
323   if (*_imageInfo->magick != '\0' )
324     magick_info = GetMagickInfo(_imageInfo->magick,&exceptionInfo);
325   ThrowPPException;
326
327   if ((magick_info != 0) && (*magick_info->description != '\0'))
328     return(std::string( magick_info->description));
329   
330   return(std::string());
331 }
332
333 void Magick::Options::interlaceType(Magick::InterlaceType interlace_)
334 {
335   _imageInfo->interlace=interlace_;
336 }
337
338 Magick::InterlaceType Magick::Options::interlaceType(void) const
339 {
340   return(static_cast<Magick::InterlaceType>(_imageInfo->interlace));
341 }
342
343 void Magick::Options::magick(const std::string &magick_)
344 {
345   FormatLocaleString(_imageInfo->filename,MaxTextExtent,"%.1024s:",
346     magick_.c_str());
347   GetPPException;
348   SetImageInfo(_imageInfo,1,&exceptionInfo);
349   if (*_imageInfo->magick == '\0')
350     throwExceptionExplicit(OptionWarning, "Unrecognized image format",
351       magick_.c_str());
352   (void) DestroyExceptionInfo(&exceptionInfo);
353 }
354
355 std::string Magick::Options::magick(void) const
356 {
357   if (_imageInfo->magick && *_imageInfo->magick)
358     return(std::string(_imageInfo->magick));
359
360   return(std::string());
361 }
362
363 void Magick::Options::matteColor(const Magick::Color &matteColor_)
364 {
365   _imageInfo->matte_color=matteColor_;
366 }
367
368 Magick::Color Magick::Options::matteColor(void) const
369 {
370   return(Magick::Color(_imageInfo->matte_color));
371 }
372
373 void Magick::Options::monochrome(bool monochromeFlag_)
374 {
375   _imageInfo->monochrome=(MagickBooleanType) monochromeFlag_;
376 }
377
378 bool Magick::Options::monochrome(void) const
379 {
380   return(static_cast<bool>(_imageInfo->monochrome));
381 }
382
383 void Magick::Options::page(const Magick::Geometry &pageSize_)
384 {
385   if (!pageSize_.isValid())
386     _imageInfo->page=(char *) RelinquishMagickMemory(_imageInfo->page);
387   else
388     Magick::CloneString(&_imageInfo->page,pageSize_);
389 }
390
391 Magick::Geometry Magick::Options::page(void) const
392 {
393   if (_imageInfo->page)
394     return(Geometry(_imageInfo->page));
395
396   return(Geometry());
397 }
398
399 void Magick::Options::quality(size_t quality_)
400 {
401   _imageInfo->quality=quality_;
402 }
403
404 size_t Magick::Options::quality(void) const
405 {
406   return(_imageInfo->quality);
407 }
408
409 void Magick::Options::quantizeColors(size_t colors_)
410 {
411   _quantizeInfo->number_colors=colors_;
412 }
413
414 size_t Magick::Options::quantizeColors(void) const
415 {
416   return(_quantizeInfo->number_colors);
417 }
418
419 void Magick::Options::quantizeColorSpace(Magick::ColorspaceType colorSpace_)
420 {
421   _quantizeInfo->colorspace=colorSpace_;
422 }
423
424 Magick::ColorspaceType Magick::Options::quantizeColorSpace(void) const
425 {
426   return(static_cast<Magick::ColorspaceType>(_quantizeInfo->colorspace));
427 }
428
429 void Magick::Options::quantizeDither(bool ditherFlag_)
430 {
431   _imageInfo->dither=(MagickBooleanType) ditherFlag_;
432   _quantizeInfo->dither_method=ditherFlag_ ? RiemersmaDitherMethod :
433     NoDitherMethod;
434 }
435
436 bool Magick::Options::quantizeDither(void) const
437 {
438   return(static_cast<bool>(_imageInfo->dither));
439 }
440
441 void Magick::Options::quantizeTreeDepth(size_t treeDepth_)
442 {
443   _quantizeInfo->tree_depth=treeDepth_;
444 }
445
446 size_t Magick::Options::quantizeTreeDepth(void) const
447 {
448   return(_quantizeInfo->tree_depth);
449 }
450
451 void Magick::Options::resolutionUnits(Magick::ResolutionType resolutionUnits_)
452 {
453   _imageInfo->units=resolutionUnits_;
454 }
455
456 Magick::ResolutionType Magick::Options::resolutionUnits(void) const
457 {
458   return(static_cast<Magick::ResolutionType>(_imageInfo->units));
459 }
460
461 void Magick::Options::samplingFactor(const std::string &samplingFactor_)
462 {
463   if (samplingFactor_.length() == 0)
464     _imageInfo->sampling_factor=(char *) RelinquishMagickMemory(
465       _imageInfo->sampling_factor);
466   else
467     Magick::CloneString(&_imageInfo->sampling_factor,samplingFactor_);
468 }
469
470 std::string Magick::Options::samplingFactor(void) const
471 {
472   if (_imageInfo->sampling_factor)
473     return(std::string(_imageInfo->sampling_factor));
474
475   return(std::string());
476 }
477
478 void Magick::Options::size(const Geometry &geometry_)
479 {
480   _imageInfo->size=(char *) RelinquishMagickMemory(_imageInfo->size);
481
482   if (geometry_.isValid())
483     Magick::CloneString(&_imageInfo->size,geometry_);
484 }
485
486 Magick::Geometry Magick::Options::size(void) const
487 {
488   if (_imageInfo->size)
489     return(Geometry(_imageInfo->size));
490
491   return(Geometry());
492 }
493
494 void Magick::Options::strokeAntiAlias(bool flag_)
495 {
496   flag_ ? _drawInfo->stroke_antialias=MagickTrue :
497     _drawInfo->stroke_antialias=MagickFalse;
498 }
499
500 bool Magick::Options::strokeAntiAlias(void) const
501 {
502   return(_drawInfo->stroke_antialias != 0 ? true : false);
503 }
504
505 void Magick::Options::strokeColor(const Magick::Color &strokeColor_)
506 {
507   _drawInfo->stroke=strokeColor_;
508 }
509
510 Magick::Color Magick::Options::strokeColor(void) const
511 {
512   return(_drawInfo->stroke);
513 }
514
515 void Magick::Options::strokeDashArray(const double *strokeDashArray_)
516 {
517   _drawInfo->dash_pattern=(double *) RelinquishMagickMemory(
518     _drawInfo->dash_pattern);
519
520   if(strokeDashArray_)
521     {
522       size_t
523         x;
524       // Count elements in dash array
525       for (x=0; strokeDashArray_[x]; x++) ;
526       // Allocate elements
527       _drawInfo->dash_pattern=static_cast<double*>(AcquireMagickMemory((x+1)*
528         sizeof(double)));
529       // Copy elements
530       memcpy(_drawInfo->dash_pattern,strokeDashArray_,(x+1)*sizeof(double));
531     }
532 }
533
534 const double *Magick::Options::strokeDashArray(void) const
535 {
536   return(_drawInfo->dash_pattern);
537 }
538
539 void Magick::Options::strokeDashOffset(double strokeDashOffset_)
540 {
541   _drawInfo->dash_offset=strokeDashOffset_;
542 }
543
544 double Magick::Options::strokeDashOffset(void) const
545 {
546   return(_drawInfo->dash_offset);
547 }
548
549 void Magick::Options::strokeLineCap(Magick::LineCap lineCap_)
550 {
551   _drawInfo->linecap=lineCap_;
552 }
553
554 Magick::LineCap Magick::Options::strokeLineCap(void) const
555 {
556   return(_drawInfo->linecap);
557 }
558
559 void Magick::Options::strokeLineJoin(Magick::LineJoin lineJoin_)
560 {
561   _drawInfo->linejoin=lineJoin_;
562 }
563
564 Magick::LineJoin Magick::Options::strokeLineJoin(void) const
565 {
566   return(_drawInfo->linejoin);
567 }
568
569 void Magick::Options::strokeMiterLimit(size_t miterLimit_)
570 {
571   _drawInfo->miterlimit=miterLimit_;
572 }
573
574 size_t Magick::Options::strokeMiterLimit(void) const
575 {
576   return(_drawInfo->miterlimit);
577 }
578
579 void Magick::Options::strokePattern(const MagickCore::Image *strokePattern_)
580 {
581   if (_drawInfo->stroke_pattern)
582     _drawInfo->stroke_pattern=DestroyImageList(_drawInfo->stroke_pattern);
583
584   if (strokePattern_)
585     {
586       GetPPException;
587       _drawInfo->stroke_pattern=CloneImage( const_cast<MagickCore::Image*>(
588         strokePattern_),0,0,MagickTrue,&exceptionInfo);
589       ThrowPPException;
590     }
591 }
592
593 const MagickCore::Image *Magick::Options::strokePattern(void) const
594 {
595   return(_drawInfo->stroke_pattern);
596 }
597
598 void Magick::Options::strokeWidth(double strokeWidth_)
599 {
600   _drawInfo->stroke_width=strokeWidth_;
601 }
602
603 double Magick::Options::strokeWidth(void) const
604 {
605   return(_drawInfo->stroke_width);
606 }
607
608 void Magick::Options::subImage(size_t subImage_)
609 {
610   _imageInfo->scene=subImage_;
611 }
612
613 size_t Magick::Options::subImage(void) const
614 {
615   return(_imageInfo->scene);
616 }
617
618 void Magick::Options::subRange(size_t subRange_)
619 {
620   _imageInfo->number_scenes=subRange_;
621 }
622
623 size_t Magick::Options::subRange(void) const
624 {
625   return(_imageInfo->number_scenes);
626 }
627
628 void Magick::Options::textEncoding(const std::string &encoding_)
629 {
630   CloneString(&_drawInfo->encoding, encoding_.c_str());
631 }
632
633 std::string Magick::Options::textEncoding(void) const
634 {
635   if (_drawInfo->encoding && *_drawInfo->encoding)
636     return(std::string(_drawInfo->encoding));
637
638   return(std::string());
639 }
640
641 void Magick::Options::textInterlineSpacing(double spacing_)
642 {
643   _drawInfo->interline_spacing=spacing_;
644 }
645
646 double Magick::Options::textInterlineSpacing(void) const
647 {
648   return(_drawInfo->interline_spacing);
649 }
650
651 void Magick::Options::textInterwordSpacing(double spacing_)
652 {
653   _drawInfo->interword_spacing=spacing_;
654 }
655
656 double Magick::Options::textInterwordSpacing(void) const
657 {
658   return(_drawInfo->interword_spacing);
659 }
660
661 void Magick::Options::textKerning(double kerning_)
662 {
663   _drawInfo->kerning=kerning_;
664 }
665
666 double Magick::Options::textKerning(void) const
667 {
668   return(_drawInfo->kerning);
669 }
670
671 void Magick::Options::transformOrigin(double tx_,double ty_)
672 {
673   AffineMatrix
674     affine,
675     current=_drawInfo->affine;
676
677   affine.sx=1.0;
678   affine.rx=0.0;
679   affine.ry=0.0;
680   affine.sy=1.0;
681   affine.tx=0.0;
682   affine.ty=0.0;
683
684   affine.tx=tx_;
685   affine.ty=ty_;
686
687   _drawInfo->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
688   _drawInfo->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
689   _drawInfo->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
690   _drawInfo->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
691   _drawInfo->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
692   _drawInfo->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
693 }
694
695 void Magick::Options::transformReset(void)
696 {
697   _drawInfo->affine.sx=1.0;
698   _drawInfo->affine.rx=0.0;
699   _drawInfo->affine.ry=0.0;
700   _drawInfo->affine.sy=1.0;
701   _drawInfo->affine.tx=0.0;
702   _drawInfo->affine.ty=0.0;
703 }
704
705 void Magick::Options::transformRotation(double angle_)
706 {
707   AffineMatrix
708     affine,
709     current=_drawInfo->affine;
710
711   affine.sx=1.0;
712   affine.rx=0.0;
713   affine.ry=0.0;
714   affine.sy=1.0;
715   affine.tx=0.0;
716   affine.ty=0.0;
717
718   affine.sx=cos(DegreesToRadians(fmod(angle_,360.0)));
719   affine.rx=(-sin(DegreesToRadians(fmod(angle_,360.0))));
720   affine.ry=sin(DegreesToRadians(fmod(angle_,360.0)));
721   affine.sy=cos(DegreesToRadians(fmod(angle_,360.0)));
722
723   _drawInfo->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
724   _drawInfo->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
725   _drawInfo->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
726   _drawInfo->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
727   _drawInfo->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
728   _drawInfo->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
729 }
730
731 void Magick::Options::transformScale(double sx_,double sy_)
732 {
733   AffineMatrix
734     affine,
735     current=_drawInfo->affine;
736
737   affine.sx=1.0;
738   affine.rx=0.0;
739   affine.ry=0.0;
740   affine.sy=1.0;
741   affine.tx=0.0;
742   affine.ty=0.0;
743
744   affine.sx=sx_;
745   affine.sy=sy_;
746
747   _drawInfo->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
748   _drawInfo->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
749   _drawInfo->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
750   _drawInfo->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
751   _drawInfo->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
752   _drawInfo->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
753 }
754
755 void Magick::Options::transformSkewX(double skewx_)
756 {
757   AffineMatrix
758     affine,
759     current=_drawInfo->affine;
760
761   affine.sx=1.0;
762   affine.rx=0.0;
763   affine.ry=0.0;
764   affine.sy=1.0;
765   affine.tx=0.0;
766   affine.ty=0.0;
767
768   affine.sx=1.0;
769   affine.ry=tan(DegreesToRadians(fmod(skewx_,360.0)));
770   affine.sy=1.0;
771
772   _drawInfo->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
773   _drawInfo->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
774   _drawInfo->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
775   _drawInfo->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
776   _drawInfo->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
777   _drawInfo->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
778 }
779
780 void Magick::Options::transformSkewY(double skewy_)
781 {
782   AffineMatrix
783     affine,
784     current=_drawInfo->affine;
785
786   affine.sx=1.0;
787   affine.rx=0.0;
788   affine.ry=0.0;
789   affine.sy=1.0;
790   affine.tx=0.0;
791   affine.ty=0.0;
792
793   affine.sx=1.0;
794   affine.rx=tan(DegreesToRadians(fmod(skewy_,360.0)));
795   affine.sy=1.0;
796
797   _drawInfo->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
798   _drawInfo->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
799   _drawInfo->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
800   _drawInfo->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
801   _drawInfo->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
802   _drawInfo->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
803 }
804
805 void Magick::Options::type(const Magick::ImageType type_)
806 {
807   _imageInfo->type=type_;
808 }
809
810 Magick::ImageType Magick::Options::type(void) const
811 {
812   return(_imageInfo->type);
813 }
814
815 void Magick::Options::verbose(bool verboseFlag_)
816 {
817   _imageInfo->verbose=(MagickBooleanType) verboseFlag_;
818 }
819
820 bool Magick::Options::verbose(void) const
821 {
822   return(static_cast<bool>(_imageInfo->verbose));
823 }
824
825 void Magick::Options::view(const std::string &view_)
826 {
827   if (view_.length() == 0)
828     _imageInfo->view=(char *) RelinquishMagickMemory(_imageInfo->view);
829   else
830     Magick::CloneString(&_imageInfo->view, view_);
831 }
832
833 std::string Magick::Options::view(void) const
834 {
835   if (_imageInfo->view)
836     return(std::string(_imageInfo->view));
837
838   return(std::string());
839 }
840
841 void Magick::Options::x11Display(const std::string &display_)
842 {
843   if (display_.length() == 0)
844     _imageInfo->server_name=(char *) RelinquishMagickMemory(
845       _imageInfo->server_name);
846   else
847     Magick::CloneString(&_imageInfo->server_name,display_);
848 }
849
850 std::string Magick::Options::x11Display(void) const
851 {
852   if (_imageInfo->server_name)
853     return(std::string( _imageInfo->server_name));
854
855   return(std::string());
856 }
857
858 MagickCore::DrawInfo *Magick::Options::drawInfo(void)
859 {
860   return(_drawInfo);
861 }
862
863 MagickCore::ImageInfo *Magick::Options::imageInfo(void)
864 {
865   return(_imageInfo);
866 }
867
868 MagickCore::QuantizeInfo *Magick::Options::quantizeInfo(void)
869 {
870   return(_quantizeInfo);
871 }
872
873 Magick::Options::Options(const MagickCore::ImageInfo* imageInfo_,
874   const MagickCore::QuantizeInfo* quantizeInfo_,
875   const MagickCore::DrawInfo* drawInfo_)
876 : _imageInfo(0),
877   _quantizeInfo(0),
878   _drawInfo(0)
879 {
880   _imageInfo=CloneImageInfo(imageInfo_);
881   _quantizeInfo=CloneQuantizeInfo(quantizeInfo_);
882   _drawInfo=CloneDrawInfo(imageInfo_,drawInfo_);
883 }