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