Home | History | Annotate | Download | only in lib
      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 
     27 Magick::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 
     45 Magick::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 
     53 Magick::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 
     65 void Magick::Options::adjoin(const bool flag_)
     66 {
     67   _imageInfo->adjoin=static_cast<MagickBooleanType>(
     68     flag_ ? MagickTrue : MagickFalse);
     69 }
     70 
     71 bool Magick::Options::adjoin(void) const
     72 {
     73   return(static_cast<bool>(_imageInfo->adjoin));
     74 }
     75 
     76 void Magick::Options::alphaColor(const Color &alphaColor_)
     77 {
     78   _imageInfo->alpha_color=alphaColor_;
     79 }
     80 
     81 Magick::Color Magick::Options::alphaColor(void) const
     82 {
     83   return(Magick::Color(_imageInfo->alpha_color));
     84 }
     85 
     86 void Magick::Options::backgroundColor(const Color &color_)
     87 {
     88   _imageInfo->background_color=color_;
     89 }
     90 
     91 Magick::Color Magick::Options::backgroundColor(void) const
     92 {
     93   return(Color(_imageInfo->background_color));
     94 }
     95 
     96 void 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 
    104 std::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 
    112 void Magick::Options::borderColor(const Color &color_)
    113 {
    114   _imageInfo->border_color=color_;
    115   _drawInfo->border_color=color_;
    116 }
    117 
    118 Magick::Color Magick::Options::borderColor(void) const
    119 {
    120   return(Color(_imageInfo->border_color));
    121 }
    122 
    123 void Magick::Options::boxColor(const Color &boxColor_)
    124 {
    125   _drawInfo->undercolor=boxColor_;
    126 }
    127 
    128 Magick::Color Magick::Options::boxColor(void) const
    129 {
    130   return(Color(_drawInfo->undercolor));
    131 }
    132 
    133 void Magick::Options::colorspaceType(const ColorspaceType colorspace_)
    134 {
    135   _imageInfo->colorspace=colorspace_;
    136 }
    137 
    138 Magick::ColorspaceType Magick::Options::colorspaceType(void) const
    139 {
    140   return(static_cast<Magick::ColorspaceType>(_imageInfo->colorspace));
    141 }
    142 
    143 void Magick::Options::compressType(const CompressionType compressType_)
    144 {
    145   _imageInfo->compression=compressType_;
    146 }
    147 
    148 Magick::CompressionType Magick::Options::compressType(void) const
    149 {
    150   return(static_cast<Magick::CompressionType>(_imageInfo->compression));
    151 }
    152 
    153 void Magick::Options::colorFuzz(const double fuzz_)
    154 {
    155   _imageInfo->fuzz=fuzz_;
    156 }
    157 
    158 double Magick::Options::colorFuzz(void) const
    159 {
    160   return(_imageInfo->fuzz);
    161 }
    162 
    163 void Magick::Options::debug(const bool flag_)
    164 {
    165   if  (flag_)
    166     SetLogEventMask("All");
    167   else
    168     SetLogEventMask("None");
    169 }
    170 
    171 bool Magick::Options::debug(void) const
    172 {
    173   if (IsEventLogging())
    174     return(true);
    175   return(false);
    176 }
    177 
    178 void 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 
    186 Magick::Point Magick::Options::density(void) const
    187 {
    188   if (_imageInfo->density)
    189     return(Point(_imageInfo->density));
    190 
    191   return(Point());
    192 }
    193 
    194 void Magick::Options::depth(const size_t depth_)
    195 {
    196   _imageInfo->depth=depth_;
    197 }
    198 
    199 size_t Magick::Options::depth(void) const
    200 {
    201   return(_imageInfo->depth);
    202 }
    203 
    204 void Magick::Options::endian(const Magick::EndianType endian_)
    205 {
    206   _imageInfo->endian=endian_;
    207 }
    208 
    209 Magick::EndianType Magick::Options::endian(void) const
    210 {
    211   return(_imageInfo->endian);
    212 }
    213 
    214 void Magick::Options::file(FILE *file_)
    215 {
    216   SetImageInfoFile(_imageInfo,file_);
    217 }
    218 
    219 FILE *Magick::Options::file(void) const
    220 {
    221   return(GetImageInfoFile(_imageInfo));
    222 }
    223 
    224 void 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 
    233 std::string Magick::Options::fileName(void) const
    234 {
    235   return(std::string(_imageInfo->filename));
    236 }
    237 
    238 void 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 
    246 Magick::Color Magick::Options::fillColor(void) const
    247 {
    248   return(_drawInfo->fill);
    249 }
    250 
    251 void 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 
    266 const MagickCore::Image *Magick::Options::fillPattern(void) const
    267 {
    268   return(_drawInfo->fill_pattern);
    269 }
    270 
    271 void Magick::Options::fillRule(const FillRule &fillRule_)
    272 {
    273   _drawInfo->fill_rule=fillRule_;
    274 }
    275 
    276 Magick::FillRule Magick::Options::fillRule(void) const
    277 {
    278   return(_drawInfo->fill_rule);
    279 }
    280 
    281 void 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 
    295 std::string Magick::Options::font(void) const
    296 {
    297   if (_imageInfo->font)
    298     return(std::string(_imageInfo->font));
    299 
    300   return(std::string());
    301 }
    302 
    303 void 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 
    317 std::string Magick::Options::fontFamily(void) const
    318 {
    319   if (_drawInfo->family)
    320     return(std::string(_drawInfo->family));
    321 
    322   return(std::string());
    323 }
    324 
    325 void Magick::Options::fontPointsize(const double pointSize_)
    326 {
    327   _imageInfo->pointsize=pointSize_;
    328   _drawInfo->pointsize=pointSize_;
    329 }
    330 
    331 double Magick::Options::fontPointsize(void) const
    332 {
    333   return(_imageInfo->pointsize);
    334 }
    335 
    336 void Magick::Options::fontStyle(const StyleType style_)
    337 {
    338   _drawInfo->style=style_;
    339   (void) SetImageOption(_imageInfo,"style",CommandOptionToMnemonic(
    340     MagickStyleOptions,(ssize_t) style_));
    341 }
    342 
    343 Magick::StyleType Magick::Options::fontStyle(void) const
    344 {
    345   return(_drawInfo->style);
    346 }
    347 
    348 void Magick::Options::fontWeight(const size_t weight_)
    349 {
    350   _drawInfo->weight=weight_;
    351   setOption("weight",(double) weight_);
    352 }
    353 
    354 size_t Magick::Options::fontWeight(void) const
    355 {
    356   return(_drawInfo->weight);
    357 }
    358 
    359 std::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 
    375 void Magick::Options::interlaceType(const InterlaceType interlace_)
    376 {
    377   _imageInfo->interlace=interlace_;
    378 }
    379 
    380 Magick::InterlaceType Magick::Options::interlaceType(void) const
    381 {
    382   return(static_cast<Magick::InterlaceType>(_imageInfo->interlace));
    383 }
    384 
    385 void 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 
    403 std::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 
    411 void Magick::Options::monochrome(const bool monochromeFlag_)
    412 {
    413   _imageInfo->monochrome=(MagickBooleanType) monochromeFlag_;
    414 }
    415 
    416 bool Magick::Options::monochrome(void) const
    417 {
    418   return(static_cast<bool>(_imageInfo->monochrome));
    419 }
    420 
    421 void 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 
    429 Magick::Geometry Magick::Options::page(void) const
    430 {
    431   if (_imageInfo->page)
    432     return(Geometry(_imageInfo->page));
    433 
    434   return(Geometry());
    435 }
    436 
    437 void Magick::Options::quality(const size_t quality_)
    438 {
    439   _imageInfo->quality=quality_;
    440 }
    441 
    442 size_t Magick::Options::quality(void) const
    443 {
    444   return(_imageInfo->quality);
    445 }
    446 
    447 void Magick::Options::quantizeColors(const size_t colors_)
    448 {
    449   _quantizeInfo->number_colors=colors_;
    450 }
    451 
    452 size_t Magick::Options::quantizeColors(void) const
    453 {
    454   return(_quantizeInfo->number_colors);
    455 }
    456 
    457 void Magick::Options::quantizeColorSpace(const ColorspaceType colorSpace_)
    458 {
    459   _quantizeInfo->colorspace=colorSpace_;
    460 }
    461 
    462 Magick::ColorspaceType Magick::Options::quantizeColorSpace(void) const
    463 {
    464   return(static_cast<Magick::ColorspaceType>(_quantizeInfo->colorspace));
    465 }
    466 
    467 void Magick::Options::quantizeDither(const bool ditherFlag_)
    468 {
    469   _imageInfo->dither=(MagickBooleanType) ditherFlag_;
    470   _quantizeInfo->dither_method=ditherFlag_ ? RiemersmaDitherMethod :
    471     NoDitherMethod;
    472 }
    473 
    474 bool Magick::Options::quantizeDither(void) const
    475 {
    476   return(static_cast<bool>(_imageInfo->dither));
    477 }
    478 
    479 void Magick::Options::quantizeDitherMethod(const DitherMethod ditherMethod_)
    480 {
    481   _quantizeInfo->dither_method=ditherMethod_;
    482 }
    483 
    484 MagickCore::DitherMethod Magick::Options::quantizeDitherMethod(void) const
    485 {
    486   return(_quantizeInfo->dither_method);
    487 }
    488 
    489 void Magick::Options::quantizeTreeDepth(const size_t treeDepth_)
    490 {
    491   _quantizeInfo->tree_depth=treeDepth_;
    492 }
    493 
    494 size_t Magick::Options::quantizeTreeDepth(void) const
    495 {
    496   return(_quantizeInfo->tree_depth);
    497 }
    498 
    499 void Magick::Options::quiet(const bool quiet_)
    500 {
    501   _quiet=quiet_;
    502 }
    503 
    504 bool Magick::Options::quiet(void) const
    505 {
    506   return(_quiet);
    507 }
    508 
    509 void Magick::Options::resolutionUnits(const ResolutionType resolutionUnits_)
    510 {
    511   _imageInfo->units=resolutionUnits_;
    512 }
    513 
    514 Magick::ResolutionType Magick::Options::resolutionUnits(void) const
    515 {
    516   return(_imageInfo->units);
    517 }
    518 
    519 void 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 
    528 std::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 
    536 void 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 
    544 Magick::Geometry Magick::Options::size(void) const
    545 {
    546   if (_imageInfo->size)
    547     return(Geometry(_imageInfo->size));
    548 
    549   return(Geometry());
    550 }
    551 
    552 void Magick::Options::strokeAntiAlias(const bool flag_)
    553 {
    554   flag_ ? _drawInfo->stroke_antialias=MagickTrue :
    555     _drawInfo->stroke_antialias=MagickFalse;
    556 }
    557 
    558 bool Magick::Options::strokeAntiAlias(void) const
    559 {
    560   return(_drawInfo->stroke_antialias != 0 ? true : false);
    561 }
    562 
    563 void 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 
    571 Magick::Color Magick::Options::strokeColor(void) const
    572 {
    573   return(_drawInfo->stroke);
    574 }
    575 
    576 void 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 
    596 const double *Magick::Options::strokeDashArray(void) const
    597 {
    598   return(_drawInfo->dash_pattern);
    599 }
    600 
    601 void Magick::Options::strokeDashOffset(const double strokeDashOffset_)
    602 {
    603   _drawInfo->dash_offset=strokeDashOffset_;
    604 }
    605 
    606 double Magick::Options::strokeDashOffset(void) const
    607 {
    608   return(_drawInfo->dash_offset);
    609 }
    610 
    611 void Magick::Options::strokeLineCap(const LineCap lineCap_)
    612 {
    613   _drawInfo->linecap=lineCap_;
    614 }
    615 
    616 Magick::LineCap Magick::Options::strokeLineCap(void) const
    617 {
    618   return(_drawInfo->linecap);
    619 }
    620 
    621 void Magick::Options::strokeLineJoin(const LineJoin lineJoin_)
    622 {
    623   _drawInfo->linejoin=lineJoin_;
    624 }
    625 
    626 Magick::LineJoin Magick::Options::strokeLineJoin(void) const
    627 {
    628   return(_drawInfo->linejoin);
    629 }
    630 
    631 void Magick::Options::strokeMiterLimit(const size_t miterLimit_)
    632 {
    633   _drawInfo->miterlimit=miterLimit_;
    634 }
    635 
    636 size_t Magick::Options::strokeMiterLimit(void) const
    637 {
    638   return(_drawInfo->miterlimit);
    639 }
    640 
    641 void 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 
    655 const MagickCore::Image *Magick::Options::strokePattern(void) const
    656 {
    657   return(_drawInfo->stroke_pattern);
    658 }
    659 
    660 void Magick::Options::strokeWidth(const double strokeWidth_)
    661 {
    662   _drawInfo->stroke_width=strokeWidth_;
    663   setOption("strokewidth",strokeWidth_);
    664 }
    665 
    666 double Magick::Options::strokeWidth(void) const
    667 {
    668   return(_drawInfo->stroke_width);
    669 }
    670 
    671 void Magick::Options::subImage(const size_t subImage_)
    672 {
    673   _imageInfo->scene=subImage_;
    674 }
    675 
    676 size_t Magick::Options::subImage(void) const
    677 {
    678   return(_imageInfo->scene);
    679 }
    680 
    681 void Magick::Options::subRange(const size_t subRange_)
    682 {
    683   _imageInfo->number_scenes=subRange_;
    684 }
    685 
    686 size_t Magick::Options::subRange(void) const
    687 {
    688   return(_imageInfo->number_scenes);
    689 }
    690 
    691 void Magick::Options::textAntiAlias(const bool flag_)
    692 {
    693   _drawInfo->text_antialias=static_cast<MagickBooleanType>(
    694     flag_ ? MagickTrue : MagickFalse);
    695 }
    696 
    697 bool Magick::Options::textAntiAlias(void) const
    698 {
    699   return(static_cast<bool>(_drawInfo->text_antialias));
    700 }
    701 
    702 void Magick::Options::textDirection(const DirectionType direction_)
    703 {
    704   _drawInfo->direction=direction_;
    705   (void) SetImageOption(_imageInfo,"direction",CommandOptionToMnemonic(
    706     MagickDirectionOptions,(ssize_t) direction_));
    707 }
    708 
    709 Magick::DirectionType Magick::Options::textDirection() const
    710 {
    711   return(_drawInfo->direction);
    712 }
    713 
    714 void 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 
    720 std::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 
    728 void Magick::Options::textGravity(const GravityType gravity_)
    729 {
    730   _drawInfo->gravity=gravity_;
    731   (void) SetImageOption(_imageInfo,"gravity",CommandOptionToMnemonic(
    732     MagickGravityOptions,(ssize_t) gravity_));
    733 }
    734 
    735 Magick::GravityType Magick::Options::textGravity() const
    736 {
    737   return(_drawInfo->gravity);
    738 }
    739 
    740 void Magick::Options::textInterlineSpacing(const double spacing_)
    741 {
    742   _drawInfo->interline_spacing=spacing_;
    743   setOption("interline-spacing",spacing_);
    744 }
    745 
    746 double Magick::Options::textInterlineSpacing(void) const
    747 {
    748   return(_drawInfo->interline_spacing);
    749 }
    750 
    751 void Magick::Options::textInterwordSpacing(const double spacing_)
    752 {
    753   _drawInfo->interword_spacing=spacing_;
    754   setOption("interword-spacing",spacing_);
    755 }
    756 
    757 double Magick::Options::textInterwordSpacing(void) const
    758 {
    759   return(_drawInfo->interword_spacing);
    760 }
    761 
    762 void Magick::Options::textKerning(const double kerning_)
    763 {
    764   _drawInfo->kerning=kerning_;
    765   setOption("kerning",kerning_);
    766 }
    767 
    768 double Magick::Options::textKerning(void) const
    769 {
    770   return(_drawInfo->kerning);
    771 }
    772 
    773 void Magick::Options::textUnderColor(const Color &undercolor_)
    774 {
    775   _drawInfo->undercolor=undercolor_;
    776   setOption("undercolor",undercolor_);
    777 }
    778 
    779 Magick::Color Magick::Options::textUnderColor(void) const
    780 {
    781   return(_drawInfo->undercolor);
    782 }
    783 
    784 void 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 
    808 void 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 
    818 void 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 
    844 void 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 
    868 void 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 
    893 void 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 
    918 void Magick::Options::type(const ImageType type_)
    919 {
    920   _imageInfo->type=type_;
    921 }
    922 
    923 Magick::ImageType Magick::Options::type(void) const
    924 {
    925   return(_imageInfo->type);
    926 }
    927 
    928 void Magick::Options::verbose(const bool verboseFlag_)
    929 {
    930   _imageInfo->verbose=(MagickBooleanType) verboseFlag_;
    931 }
    932 
    933 bool Magick::Options::verbose(void) const
    934 {
    935   return(static_cast<bool>(_imageInfo->verbose));
    936 }
    937 
    938 void 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 
    947 std::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 
    955 MagickCore::DrawInfo *Magick::Options::drawInfo(void)
    956 {
    957   return(_drawInfo);
    958 }
    959 
    960 MagickCore::ImageInfo *Magick::Options::imageInfo(void)
    961 {
    962   return(_imageInfo);
    963 }
    964 
    965 MagickCore::QuantizeInfo *Magick::Options::quantizeInfo(void)
    966 {
    967   return(_quantizeInfo);
    968 }
    969 
    970 Magick::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 
    983 void 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 
    992 void 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