48#include "MagickCore/studio.h" 
   49#include "MagickCore/annotate.h" 
   50#include "MagickCore/artifact.h" 
   51#include "MagickCore/blob.h" 
   52#include "MagickCore/cache.h" 
   53#include "MagickCore/cache-private.h" 
   54#include "MagickCore/cache-view.h" 
   55#include "MagickCore/channel.h" 
   56#include "MagickCore/color.h" 
   57#include "MagickCore/colorspace-private.h" 
   58#include "MagickCore/composite.h" 
   59#include "MagickCore/composite-private.h" 
   60#include "MagickCore/constitute.h" 
   61#include "MagickCore/draw.h" 
   62#include "MagickCore/draw-private.h" 
   63#include "MagickCore/enhance.h" 
   64#include "MagickCore/exception.h" 
   65#include "MagickCore/exception-private.h" 
   66#include "MagickCore/gem.h" 
   67#include "MagickCore/geometry.h" 
   68#include "MagickCore/image-private.h" 
   69#include "MagickCore/list.h" 
   70#include "MagickCore/log.h" 
   71#include "MagickCore/magick.h" 
   72#include "MagickCore/memory-private.h" 
   73#include "MagickCore/monitor.h" 
   74#include "MagickCore/monitor-private.h" 
   75#include "MagickCore/option.h" 
   76#include "MagickCore/paint.h" 
   77#include "MagickCore/pixel-accessor.h" 
   78#include "MagickCore/property.h" 
   79#include "MagickCore/resample.h" 
   80#include "MagickCore/resample-private.h" 
   81#include "MagickCore/resource_.h" 
   82#include "MagickCore/splay-tree.h" 
   83#include "MagickCore/string_.h" 
   84#include "MagickCore/string-private.h" 
   85#include "MagickCore/thread-private.h" 
   86#include "MagickCore/token.h" 
   87#include "MagickCore/transform-private.h" 
   88#include "MagickCore/utility.h" 
   93#define AntialiasThreshold  (1.0/3.0) 
   94#define BezierQuantum  200 
   95#define PrimitiveExtentPad  4296.0 
   96#define MaxBezierCoordinates  67108864 
   97#define ThrowPointExpectedException(token,exception) \ 
   99  (void) ThrowMagickException(exception,GetMagickModule(),DrawError, \ 
  100    "NonconformingDrawingPrimitiveDefinition","`%s'",token); \ 
  101  status=MagickFalse; \ 
  191  *DrawClippingMask(Image *,
const DrawInfo *,
const char *,
const char *,
 
  194static MagickBooleanType
 
  195  DrawStrokePolygon(Image *,
const DrawInfo *,
const PrimitiveInfo *,
 
  197  RenderMVGContent(Image *,
const DrawInfo *,
const size_t,ExceptionInfo *),
 
  198  TraceArc(MVGInfo *,
const PointInfo,
const PointInfo,
const PointInfo),
 
  199  TraceArcPath(MVGInfo *,
const PointInfo,
const PointInfo,
const PointInfo,
 
  200    const double,
const MagickBooleanType,
const MagickBooleanType),
 
  201  TraceBezier(MVGInfo *,
const size_t),
 
  202  TraceCircle(MVGInfo *,
const PointInfo,
const PointInfo),
 
  203  TraceEllipse(MVGInfo *,
const PointInfo,
const PointInfo,
const PointInfo),
 
  204  TraceLine(PrimitiveInfo *,
const PointInfo,
const PointInfo),
 
  205  TraceRectangle(PrimitiveInfo *,
const PointInfo,
const PointInfo),
 
  206  TraceRoundRectangle(MVGInfo *,
const PointInfo,
const PointInfo,PointInfo),
 
  207  TraceSquareLinecap(PrimitiveInfo *,
const size_t,
const double);
 
  210  *TraceStrokePolygon(
const DrawInfo *,
const PrimitiveInfo *,ExceptionInfo *);
 
  213  TracePath(MVGInfo *,
const char *,ExceptionInfo *);
 
  233MagickExport DrawInfo *AcquireDrawInfo(
void)
 
  238  draw_info=(DrawInfo *) AcquireCriticalMemory(
sizeof(*draw_info));
 
  239  GetDrawInfo((ImageInfo *) NULL,draw_info);
 
  270MagickExport DrawInfo *CloneDrawInfo(
const ImageInfo *image_info,
 
  271  const DrawInfo *draw_info)
 
  279  clone_info=(DrawInfo *) AcquireCriticalMemory(
sizeof(*clone_info));
 
  280  GetDrawInfo(image_info,clone_info);
 
  281  if (draw_info == (DrawInfo *) NULL)
 
  283  exception=AcquireExceptionInfo();
 
  284  if (draw_info->id != (
char *) NULL)
 
  285    (void) CloneString(&clone_info->id,draw_info->id);
 
  286  if (draw_info->primitive != (
char *) NULL)
 
  287    (void) CloneString(&clone_info->primitive,draw_info->primitive);
 
  288  if (draw_info->geometry != (
char *) NULL)
 
  289    (void) CloneString(&clone_info->geometry,draw_info->geometry);
 
  290  clone_info->compliance=draw_info->compliance;
 
  291  clone_info->viewbox=draw_info->viewbox;
 
  292  clone_info->affine=draw_info->affine;
 
  293  clone_info->gravity=draw_info->gravity;
 
  294  clone_info->fill=draw_info->fill;
 
  295  clone_info->stroke=draw_info->stroke;
 
  296  clone_info->stroke_width=draw_info->stroke_width;
 
  297  if (draw_info->fill_pattern != (Image *) NULL)
 
  298    clone_info->fill_pattern=CloneImage(draw_info->fill_pattern,0,0,MagickTrue,
 
  300  if (draw_info->stroke_pattern != (Image *) NULL)
 
  301    clone_info->stroke_pattern=CloneImage(draw_info->stroke_pattern,0,0,
 
  302      MagickTrue,exception);
 
  303  clone_info->stroke_antialias=draw_info->stroke_antialias;
 
  304  clone_info->text_antialias=draw_info->text_antialias;
 
  305  clone_info->fill_rule=draw_info->fill_rule;
 
  306  clone_info->linecap=draw_info->linecap;
 
  307  clone_info->linejoin=draw_info->linejoin;
 
  308  clone_info->miterlimit=draw_info->miterlimit;
 
  309  clone_info->dash_offset=draw_info->dash_offset;
 
  310  clone_info->decorate=draw_info->decorate;
 
  311  clone_info->compose=draw_info->compose;
 
  312  if (draw_info->text != (
char *) NULL)
 
  313    (void) CloneString(&clone_info->text,draw_info->text);
 
  314  if (draw_info->font != (
char *) NULL)
 
  315    (void) CloneString(&clone_info->font,draw_info->font);
 
  316  if (draw_info->metrics != (
char *) NULL)
 
  317    (void) CloneString(&clone_info->metrics,draw_info->metrics);
 
  318  if (draw_info->family != (
char *) NULL)
 
  319    (void) CloneString(&clone_info->family,draw_info->family);
 
  320  clone_info->style=draw_info->style;
 
  321  clone_info->stretch=draw_info->stretch;
 
  322  clone_info->weight=draw_info->weight;
 
  323  if (draw_info->encoding != (
char *) NULL)
 
  324    (void) CloneString(&clone_info->encoding,draw_info->encoding);
 
  325  clone_info->pointsize=draw_info->pointsize;
 
  326  clone_info->kerning=draw_info->kerning;
 
  327  clone_info->interline_spacing=draw_info->interline_spacing;
 
  328  clone_info->interword_spacing=draw_info->interword_spacing;
 
  329  clone_info->direction=draw_info->direction;
 
  330  clone_info->word_break=draw_info->word_break;
 
  331  if (draw_info->density != (
char *) NULL)
 
  332    (void) CloneString(&clone_info->density,draw_info->density);
 
  333  clone_info->align=draw_info->align;
 
  334  clone_info->undercolor=draw_info->undercolor;
 
  335  clone_info->border_color=draw_info->border_color;
 
  336  if (draw_info->server_name != (
char *) NULL)
 
  337    (void) CloneString(&clone_info->server_name,draw_info->server_name);
 
  338  if (draw_info->dash_pattern != (
double *) NULL)
 
  343      for (x=0; fabs(draw_info->dash_pattern[x]) >= MagickEpsilon; x++) ;
 
  344      clone_info->dash_pattern=(
double *) AcquireQuantumMemory((
size_t) (x+1),
 
  345        sizeof(*clone_info->dash_pattern));
 
  346      if (clone_info->dash_pattern == (
double *) NULL)
 
  347        ThrowFatalException(ResourceLimitFatalError,
 
  348          "UnableToAllocateDashPattern");
 
  349      (void) memset(clone_info->dash_pattern,0,(
size_t) (x+1)*
 
  350        sizeof(*clone_info->dash_pattern));
 
  351      (void) memcpy(clone_info->dash_pattern,draw_info->dash_pattern,(
size_t)
 
  352        x*
sizeof(*clone_info->dash_pattern));
 
  354  clone_info->gradient=draw_info->gradient;
 
  355  if (draw_info->gradient.stops != (StopInfo *) NULL)
 
  360      number_stops=clone_info->gradient.number_stops;
 
  361      clone_info->gradient.stops=(StopInfo *) AcquireQuantumMemory((
size_t)
 
  362        number_stops,
sizeof(*clone_info->gradient.stops));
 
  363      if (clone_info->gradient.stops == (StopInfo *) NULL)
 
  364        ThrowFatalException(ResourceLimitFatalError,
 
  365          "UnableToAllocateDashPattern");
 
  366      (void) memcpy(clone_info->gradient.stops,draw_info->gradient.stops,
 
  367        (
size_t) number_stops*
sizeof(*clone_info->gradient.stops));
 
  369  clone_info->bounds=draw_info->bounds;
 
  370  clone_info->fill_alpha=draw_info->fill_alpha;
 
  371  clone_info->stroke_alpha=draw_info->stroke_alpha;
 
  372  clone_info->element_reference=draw_info->element_reference;
 
  373  clone_info->clip_path=draw_info->clip_path;
 
  374  clone_info->clip_units=draw_info->clip_units;
 
  375  if (draw_info->clip_mask != (
char *) NULL)
 
  376    (void) CloneString(&clone_info->clip_mask,draw_info->clip_mask);
 
  377  if (draw_info->clipping_mask != (Image *) NULL)
 
  378    clone_info->clipping_mask=CloneImage(draw_info->clipping_mask,0,0,
 
  379      MagickTrue,exception);
 
  380  if (draw_info->composite_mask != (Image *) NULL)
 
  381    clone_info->composite_mask=CloneImage(draw_info->composite_mask,0,0,
 
  382      MagickTrue,exception);
 
  383  clone_info->render=draw_info->render;
 
  384  clone_info->debug=draw_info->debug;
 
  385  exception=DestroyExceptionInfo(exception);
 
  420static PolygonInfo *DestroyPolygonInfo(PolygonInfo *polygon_info)
 
  425  if (polygon_info->edges != (EdgeInfo *) NULL)
 
  427      for (i=0; i < (ssize_t) polygon_info->number_edges; i++)
 
  428        if (polygon_info->edges[i].points != (PointInfo *) NULL)
 
  429          polygon_info->edges[i].points=(PointInfo *)
 
  430            RelinquishMagickMemory(polygon_info->edges[i].points);
 
  431      polygon_info->edges=(EdgeInfo *) RelinquishMagickMemory(
 
  432        polygon_info->edges);
 
  434  return((PolygonInfo *) RelinquishMagickMemory(polygon_info));
 
  436#if defined(__cplusplus) || defined(c_plusplus) 
  440static int DrawCompareEdges(
const void *p_edge,
const void *q_edge)
 
  442#define DrawCompareEdge(p,q) \ 
  444  if (((p)-(q)) < 0.0) \ 
  446  if (((p)-(q)) > 0.0) \ 
  457  p=((
const EdgeInfo *) p_edge)->points;
 
  458  q=((
const EdgeInfo *) q_edge)->points;
 
  459  DrawCompareEdge(p[0].y,q[0].y);
 
  460  DrawCompareEdge(p[0].x,q[0].x);
 
  461  DrawCompareEdge((p[1].x-p[0].x)*(q[1].y-q[0].y),(p[1].y-p[0].y)*
 
  463  DrawCompareEdge(p[1].y,q[1].y);
 
  464  DrawCompareEdge(p[1].x,q[1].x);
 
  468#if defined(__cplusplus) || defined(c_plusplus) 
  472static void LogPolygonInfo(
const PolygonInfo *polygon_info)
 
  481  (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    begin active-edge");
 
  482  p=polygon_info->edges;
 
  483  for (i=0; i < (ssize_t) polygon_info->number_edges; i++)
 
  485    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"      edge %.20g:",
 
  487    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"      direction: %s",
 
  488      p->direction != MagickFalse ? 
"down" : 
"up");
 
  489    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"      ghostline: %s",
 
  490      p->ghostline != MagickFalse ? 
"transparent" : 
"opaque");
 
  491    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
  492      "      bounds: %g,%g - %g,%g",p->bounds.x1,p->bounds.y1,
 
  493      p->bounds.x2,p->bounds.y2);
 
  494    for (j=0; j < (ssize_t) p->number_points; j++)
 
  495      (
void) LogMagickEvent(DrawEvent,GetMagickModule(),
"        %g,%g",
 
  496        p->points[j].x,p->points[j].y);
 
  499  (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    end active-edge");
 
  502static void ReversePoints(PointInfo *points,
const size_t number_points)
 
  510  for (i=0; i < (number_points >> 1); i++)
 
  513    points[i]=points[number_points-(i+1)];
 
  514    points[number_points-(i+1)]=point;
 
  518static PolygonInfo *ConvertPathToPolygon(
const PathInfo *path_info,
 
  519  ExceptionInfo *exception)
 
  550  polygon_info=(PolygonInfo *) AcquireMagickMemory(
sizeof(*polygon_info));
 
  551  if (polygon_info == (PolygonInfo *) NULL)
 
  553      (void) ThrowMagickException(exception,GetMagickModule(),
 
  554        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  555      return((PolygonInfo *) NULL);
 
  558  polygon_info->edges=(EdgeInfo *) AcquireQuantumMemory(number_edges,
 
  559    sizeof(*polygon_info->edges));
 
  560  if (polygon_info->edges == (EdgeInfo *) NULL)
 
  562      (void) ThrowMagickException(exception,GetMagickModule(),
 
  563        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  564      return(DestroyPolygonInfo(polygon_info));
 
  566  (void) memset(polygon_info->edges,0,number_edges*
 
  567    sizeof(*polygon_info->edges));
 
  570  ghostline=MagickFalse;
 
  573  points=(PointInfo *) NULL;
 
  574  (void) memset(&point,0,
sizeof(point));
 
  575  (void) memset(&bounds,0,
sizeof(bounds));
 
  576  polygon_info->edges[edge].number_points=(size_t) n;
 
  577  polygon_info->edges[edge].scanline=0.0;
 
  578  polygon_info->edges[edge].highwater=0;
 
  579  polygon_info->edges[edge].ghostline=ghostline;
 
  580  polygon_info->edges[edge].direction=(ssize_t) direction;
 
  581  polygon_info->edges[edge].points=points;
 
  582  polygon_info->edges[edge].bounds=bounds;
 
  583  polygon_info->number_edges=0;
 
  584  for (i=0; path_info[i].code != EndCode; i++)
 
  586    if ((path_info[i].code == MoveToCode) || (path_info[i].code == OpenCode) ||
 
  587        (path_info[i].code == GhostlineCode))
 
  592        if ((points != (PointInfo *) NULL) && (n >= 2))
 
  594            if (edge == number_edges)
 
  597                polygon_info->edges=(EdgeInfo *) ResizeQuantumMemory(
 
  598                  polygon_info->edges,(
size_t) number_edges,
 
  599                  sizeof(*polygon_info->edges));
 
  600                if (polygon_info->edges == (EdgeInfo *) NULL)
 
  602                    (void) ThrowMagickException(exception,GetMagickModule(),
 
  603                      ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  604                    points=(PointInfo *) RelinquishMagickMemory(points);
 
  605                    return(DestroyPolygonInfo(polygon_info));
 
  608            polygon_info->edges[edge].number_points=(size_t) n;
 
  609            polygon_info->edges[edge].scanline=(-1.0);
 
  610            polygon_info->edges[edge].highwater=0;
 
  611            polygon_info->edges[edge].ghostline=ghostline;
 
  612            polygon_info->edges[edge].direction=(ssize_t) (direction > 0);
 
  614              ReversePoints(points,(
size_t) n);
 
  615            polygon_info->edges[edge].points=points;
 
  616            polygon_info->edges[edge].bounds=bounds;
 
  617            polygon_info->edges[edge].bounds.y1=points[0].y;
 
  618            polygon_info->edges[edge].bounds.y2=points[n-1].y;
 
  619            points=(PointInfo *) NULL;
 
  620            ghostline=MagickFalse;
 
  622            polygon_info->number_edges=edge;
 
  624        if (points == (PointInfo *) NULL)
 
  627            points=(PointInfo *) AcquireQuantumMemory((
size_t) number_points,
 
  629            if (points == (PointInfo *) NULL)
 
  631                (void) ThrowMagickException(exception,GetMagickModule(),
 
  632                  ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  633                return(DestroyPolygonInfo(polygon_info));
 
  636        ghostline=path_info[i].code == GhostlineCode ? MagickTrue : MagickFalse;
 
  637        point=path_info[i].point;
 
  648    next_direction=((path_info[i].point.y > point.y) ||
 
  649      ((fabs(path_info[i].point.y-point.y) < MagickEpsilon) &&
 
  650       (path_info[i].point.x > point.x))) ? 1 : -1;
 
  651    if ((points != (PointInfo *) NULL) && (direction != 0) &&
 
  652        (direction != next_direction))
 
  658        if (edge == number_edges)
 
  661            polygon_info->edges=(EdgeInfo *) ResizeQuantumMemory(
 
  662              polygon_info->edges,(
size_t) number_edges,
 
  663              sizeof(*polygon_info->edges));
 
  664            if (polygon_info->edges == (EdgeInfo *) NULL)
 
  666                (void) ThrowMagickException(exception,GetMagickModule(),
 
  667                  ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  668                points=(PointInfo *) RelinquishMagickMemory(points);
 
  669                return(DestroyPolygonInfo(polygon_info));
 
  672        polygon_info->edges[edge].number_points=(size_t) n;
 
  673        polygon_info->edges[edge].scanline=(-1.0);
 
  674        polygon_info->edges[edge].highwater=0;
 
  675        polygon_info->edges[edge].ghostline=ghostline;
 
  676        polygon_info->edges[edge].direction=(ssize_t) (direction > 0);
 
  678          ReversePoints(points,(
size_t) n);
 
  679        polygon_info->edges[edge].points=points;
 
  680        polygon_info->edges[edge].bounds=bounds;
 
  681        polygon_info->edges[edge].bounds.y1=points[0].y;
 
  682        polygon_info->edges[edge].bounds.y2=points[n-1].y;
 
  683        polygon_info->number_edges=edge+1;
 
  684        points=(PointInfo *) NULL;
 
  686        points=(PointInfo *) AcquireQuantumMemory((
size_t) number_points,
 
  688        if (points == (PointInfo *) NULL)
 
  690            (void) ThrowMagickException(exception,GetMagickModule(),
 
  691              ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  692            return(DestroyPolygonInfo(polygon_info));
 
  695        ghostline=MagickFalse;
 
  701    direction=next_direction;
 
  702    if (points == (PointInfo *) NULL)
 
  704    if (n == (ssize_t) number_points)
 
  707        points=(PointInfo *) ResizeQuantumMemory(points,(
size_t) number_points,
 
  709        if (points == (PointInfo *) NULL)
 
  711            (void) ThrowMagickException(exception,GetMagickModule(),
 
  712              ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  713            return(DestroyPolygonInfo(polygon_info));
 
  716    point=path_info[i].point;
 
  718    if (point.x < bounds.x1)
 
  720    if (point.x > bounds.x2)
 
  724  if (points != (PointInfo *) NULL)
 
  727        points=(PointInfo *) RelinquishMagickMemory(points);
 
  730          if (edge == number_edges)
 
  733              polygon_info->edges=(EdgeInfo *) ResizeQuantumMemory(
 
  734                polygon_info->edges,(
size_t) number_edges,
 
  735                sizeof(*polygon_info->edges));
 
  736              if (polygon_info->edges == (EdgeInfo *) NULL)
 
  738                  (void) ThrowMagickException(exception,GetMagickModule(),
 
  739                    ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  740                  return(DestroyPolygonInfo(polygon_info));
 
  743          polygon_info->edges[edge].number_points=(size_t) n;
 
  744          polygon_info->edges[edge].scanline=(-1.0);
 
  745          polygon_info->edges[edge].highwater=0;
 
  746          polygon_info->edges[edge].ghostline=ghostline;
 
  747          polygon_info->edges[edge].direction=(ssize_t) (direction > 0);
 
  749            ReversePoints(points,(
size_t) n);
 
  750          polygon_info->edges[edge].points=points;
 
  751          polygon_info->edges[edge].bounds=bounds;
 
  752          polygon_info->edges[edge].bounds.y1=points[0].y;
 
  753          polygon_info->edges[edge].bounds.y2=points[n-1].y;
 
  754          points=(PointInfo *) NULL;
 
  755          ghostline=MagickFalse;
 
  757          polygon_info->number_edges=edge;
 
  760  polygon_info->number_edges=edge;
 
  761  polygon_info->edges=(EdgeInfo *) ResizeQuantumMemory(polygon_info->edges,
 
  762    polygon_info->number_edges,
sizeof(*polygon_info->edges));
 
  763  if (polygon_info->edges == (EdgeInfo *) NULL)
 
  765      (void) ThrowMagickException(exception,GetMagickModule(),
 
  766        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  767      return(DestroyPolygonInfo(polygon_info));
 
  769  for (i=0; i < (ssize_t) polygon_info->number_edges; i++)
 
  774    edge_info=polygon_info->edges+i;
 
  775    edge_info->points=(PointInfo *) ResizeQuantumMemory(edge_info->points,
 
  776      edge_info->number_points,
sizeof(*edge_info->points));
 
  777    if (edge_info->points == (PointInfo *) NULL)
 
  779        (void) ThrowMagickException(exception,GetMagickModule(),
 
  780          ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  781        return(DestroyPolygonInfo(polygon_info));
 
  784  qsort(polygon_info->edges,(
size_t) polygon_info->number_edges,
 
  785    sizeof(*polygon_info->edges),DrawCompareEdges);
 
  786  if ((GetLogEventMask() & DrawEvent) != 0)
 
  787    LogPolygonInfo(polygon_info);
 
  788  return(polygon_info);
 
  821static void LogPathInfo(
const PathInfo *path_info)
 
  826  (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    begin vector-path");
 
  827  for (p=path_info; p->code != EndCode; p++)
 
  828    (
void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
  829      "      %g,%g %s",p->point.x,p->point.y,p->code == GhostlineCode ?
 
  830      "moveto ghostline" : p->code == OpenCode ? 
"moveto open" :
 
  831      p->code == MoveToCode ? 
"moveto" : p->code == LineToCode ? 
"lineto" :
 
  833  (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    end vector-path");
 
  836static PathInfo *ConvertPrimitiveToPath(
const PrimitiveInfo *primitive_info,
 
  837  ExceptionInfo *exception)
 
  863  switch (primitive_info->primitive)
 
  870      return((PathInfo *) NULL);
 
  874  for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++) ;
 
  875  path_info=(PathInfo *) AcquireQuantumMemory((
size_t) (3UL*i+1UL),
 
  877  if (path_info == (PathInfo *) NULL)
 
  879      (void) ThrowMagickException(exception,GetMagickModule(),
 
  880        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
  881      return((PathInfo *) NULL);
 
  884  closed_subpath=MagickFalse;
 
  891  for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++)
 
  894    if (coordinates <= 0)
 
  899        coordinates=primitive_info[i].coordinates;
 
  900        p=primitive_info[i].point;
 
  903        closed_subpath=primitive_info[i].closed_subpath;
 
  906    if ((code == MoveToCode) || (coordinates <= 0) ||
 
  907        (fabs(q.x-primitive_info[i].point.x) >= MagickEpsilon) ||
 
  908        (fabs(q.y-primitive_info[i].point.y) >= MagickEpsilon))
 
  913        path_info[n].code=code;
 
  914        path_info[n].point=primitive_info[i].point;
 
  915        q=primitive_info[i].point;
 
  920    if (closed_subpath != MagickFalse)
 
  922        closed_subpath=MagickFalse;
 
  928    path_info[start].code=OpenCode;
 
  929    path_info[n].code=GhostlineCode;
 
  930    path_info[n].point=primitive_info[i].point;
 
  932    path_info[n].code=LineToCode;
 
  933    path_info[n].point=p;
 
  936  path_info[n].code=EndCode;
 
  937  path_info[n].point.x=0.0;
 
  938  path_info[n].point.y=0.0;
 
  939  if (IsEventLogging() != MagickFalse)
 
  940    LogPathInfo(path_info);
 
  941  path_info=(PathInfo *) ResizeQuantumMemory(path_info,(
size_t) (n+1),
 
  968MagickExport DrawInfo *DestroyDrawInfo(DrawInfo *draw_info)
 
  970  assert(draw_info != (DrawInfo *) NULL);
 
  971  assert(draw_info->signature == MagickCoreSignature);
 
  972  if (IsEventLogging() != MagickFalse)
 
  973    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
 
  974  if (draw_info->id != (
char *) NULL)
 
  975    draw_info->id=DestroyString(draw_info->id);
 
  976  if (draw_info->primitive != (
char *) NULL)
 
  977    draw_info->primitive=DestroyString(draw_info->primitive);
 
  978  if (draw_info->text != (
char *) NULL)
 
  979    draw_info->text=DestroyString(draw_info->text);
 
  980  if (draw_info->geometry != (
char *) NULL)
 
  981    draw_info->geometry=DestroyString(draw_info->geometry);
 
  982  if (draw_info->fill_pattern != (Image *) NULL)
 
  983    draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
 
  984  if (draw_info->stroke_pattern != (Image *) NULL)
 
  985    draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
 
  986  if (draw_info->font != (
char *) NULL)
 
  987    draw_info->font=DestroyString(draw_info->font);
 
  988  if (draw_info->metrics != (
char *) NULL)
 
  989    draw_info->metrics=DestroyString(draw_info->metrics);
 
  990  if (draw_info->family != (
char *) NULL)
 
  991    draw_info->family=DestroyString(draw_info->family);
 
  992  if (draw_info->encoding != (
char *) NULL)
 
  993    draw_info->encoding=DestroyString(draw_info->encoding);
 
  994  if (draw_info->density != (
char *) NULL)
 
  995    draw_info->density=DestroyString(draw_info->density);
 
  996  if (draw_info->server_name != (
char *) NULL)
 
  997    draw_info->server_name=(
char *)
 
  998     RelinquishMagickMemory(draw_info->server_name);
 
  999  if (draw_info->dash_pattern != (
double *) NULL)
 
 1000    draw_info->dash_pattern=(
double *) RelinquishMagickMemory(
 
 1001      draw_info->dash_pattern);
 
 1002  if (draw_info->gradient.stops != (StopInfo *) NULL)
 
 1003    draw_info->gradient.stops=(StopInfo *) RelinquishMagickMemory(
 
 1004      draw_info->gradient.stops);
 
 1005  if (draw_info->clip_mask != (
char *) NULL)
 
 1006    draw_info->clip_mask=DestroyString(draw_info->clip_mask);
 
 1007  if (draw_info->clipping_mask != (Image *) NULL)
 
 1008    draw_info->clipping_mask=DestroyImage(draw_info->clipping_mask);
 
 1009  if (draw_info->composite_mask != (Image *) NULL)
 
 1010    draw_info->composite_mask=DestroyImage(draw_info->composite_mask);
 
 1011  if (draw_info->image_info != (ImageInfo *) NULL)
 
 1012    draw_info->image_info=DestroyImageInfo(draw_info->image_info);
 
 1013  draw_info->signature=(~MagickCoreSignature);
 
 1014  draw_info=(DrawInfo *) RelinquishMagickMemory(draw_info);
 
 1049static SegmentInfo AffineEdge(
const Image *image,
const AffineMatrix *affine,
 
 1050  const double y,
const SegmentInfo *edge)
 
 1065  inverse_edge.x1=edge->x1;
 
 1066  inverse_edge.y1=edge->y1;
 
 1067  inverse_edge.x2=edge->x2;
 
 1068  inverse_edge.y2=edge->y2;
 
 1069  z=affine->ry*y+affine->tx;
 
 1070  if (affine->sx >= MagickEpsilon)
 
 1072      intercept=(-z/affine->sx);
 
 1074      if (x > inverse_edge.x1)
 
 1076      intercept=(-z+(double) image->columns)/affine->sx;
 
 1078      if (x < inverse_edge.x2)
 
 1082    if (affine->sx < -MagickEpsilon)
 
 1084        intercept=(-z+(double) image->columns)/affine->sx;
 
 1086        if (x > inverse_edge.x1)
 
 1088        intercept=(-z/affine->sx);
 
 1090        if (x < inverse_edge.x2)
 
 1094      if ((z < 0.0) || ((
size_t) floor(z+0.5) >= image->columns))
 
 1096          inverse_edge.x2=edge->x1;
 
 1097          return(inverse_edge);
 
 1102  z=affine->sy*y+affine->ty;
 
 1103  if (affine->rx >= MagickEpsilon)
 
 1105      intercept=(-z/affine->rx);
 
 1107      if (x > inverse_edge.x1)
 
 1109      intercept=(-z+(double) image->rows)/affine->rx;
 
 1111      if (x < inverse_edge.x2)
 
 1115    if (affine->rx < -MagickEpsilon)
 
 1117        intercept=(-z+(double) image->rows)/affine->rx;
 
 1119        if (x > inverse_edge.x1)
 
 1121        intercept=(-z/affine->rx);
 
 1123        if (x < inverse_edge.x2)
 
 1127      if ((z < 0.0) || ((
size_t) floor(z+0.5) >= image->rows))
 
 1129          inverse_edge.x2=edge->x2;
 
 1130          return(inverse_edge);
 
 1132  return(inverse_edge);
 
 1135static AffineMatrix InverseAffineMatrix(
const AffineMatrix *affine)
 
 1143  determinant=MagickSafeReciprocal(affine->sx*affine->sy-affine->rx*
 
 1145  inverse_affine.sx=determinant*affine->sy;
 
 1146  inverse_affine.rx=determinant*(-affine->rx);
 
 1147  inverse_affine.ry=determinant*(-affine->ry);
 
 1148  inverse_affine.sy=determinant*affine->sx;
 
 1149  inverse_affine.tx=(-affine->tx)*inverse_affine.sx-affine->ty*
 
 1151  inverse_affine.ty=(-affine->tx)*inverse_affine.rx-affine->ty*
 
 1153  return(inverse_affine);
 
 1156MagickExport MagickBooleanType DrawAffineImage(Image *image,
 
 1157  const Image *source,
const AffineMatrix *affine,ExceptionInfo *exception)
 
 1191  assert(image != (Image *) NULL);
 
 1192  assert(image->signature == MagickCoreSignature);
 
 1193  if (IsEventLogging() != MagickFalse)
 
 1194    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 1195  assert(source != (
const Image *) NULL);
 
 1196  assert(source->signature == MagickCoreSignature);
 
 1197  assert(affine != (AffineMatrix *) NULL);
 
 1200  extent[1].x=(double) source->columns;
 
 1202  extent[2].x=(double) source->columns;
 
 1203  extent[2].y=(double) source->rows;
 
 1205  extent[3].y=(double) source->rows;
 
 1206  for (i=0; i < 4; i++)
 
 1212    extent[i].x=point.x*affine->sx+point.y*affine->ry+affine->tx;
 
 1213    extent[i].y=point.x*affine->rx+point.y*affine->sy+affine->ty;
 
 1217  for (i=1; i < 4; i++)
 
 1219    if (min.x > extent[i].x)
 
 1221    if (min.y > extent[i].y)
 
 1223    if (max.x < extent[i].x)
 
 1225    if (max.y < extent[i].y)
 
 1231  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
 
 1232    return(MagickFalse);
 
 1238  inverse_affine=InverseAffineMatrix(affine);
 
 1241  if (edge.y2 > ((
double) image->rows-1.0))
 
 1242    edge.y2=(double) image->rows-1.0;
 
 1243  GetPixelInfo(image,&zero);
 
 1244  start=CastDoubleToSsizeT(ceil(edge.y1-0.5));
 
 1245  stop=CastDoubleToSsizeT(floor(edge.y2+0.5));
 
 1246  source_view=AcquireVirtualCacheView(source,exception);
 
 1247  image_view=AcquireAuthenticCacheView(image,exception);
 
 1248#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 1249  #pragma omp parallel for schedule(static) shared(status) \ 
 1250    magick_number_threads(source,image,(size_t) (stop-start),2) 
 1252  for (y=start; y <= stop; y++)
 
 1270    if (status == MagickFalse)
 
 1272    inverse_edge=AffineEdge(source,&inverse_affine,(
double) y,&edge);
 
 1273    if (inverse_edge.x2 < inverse_edge.x1)
 
 1275    if (inverse_edge.x1 < 0.0)
 
 1276      inverse_edge.x1=0.0;
 
 1277    if (inverse_edge.x2 > ((
double) image->columns-1.0))
 
 1278      inverse_edge.x2=(double) image->columns-1.0;
 
 1279    q=GetCacheViewAuthenticPixels(image_view,CastDoubleToSsizeT(
 
 1280      ceil(inverse_edge.x1-0.5)),y,(
size_t) CastDoubleToSsizeT(floor(
 
 1281      inverse_edge.x2+0.5)-ceil(inverse_edge.x1-0.5)+1),1,exception);
 
 1282    if (q == (Quantum *) NULL)
 
 1286    for (x=CastDoubleToSsizeT(ceil(inverse_edge.x1-0.5));
 
 1287         x <= CastDoubleToSsizeT(floor(inverse_edge.x2+0.5)); x++)
 
 1289      point.x=(double) x*inverse_affine.sx+y*inverse_affine.ry+
 
 1291      point.y=(double) x*inverse_affine.rx+y*inverse_affine.sy+
 
 1293      status=InterpolatePixelInfo(source,source_view,UndefinedInterpolatePixel,
 
 1294        point.x,point.y,&pixel,exception);
 
 1295      if (status == MagickFalse)
 
 1297      GetPixelInfoPixel(image,q,&composite);
 
 1298      CompositePixelInfoOver(&pixel,pixel.alpha,&composite,composite.alpha,
 
 1300      SetPixelViaPixelInfo(image,&composite,q);
 
 1301      q+=(ptrdiff_t) GetPixelChannels(image);
 
 1303    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
 
 1306  source_view=DestroyCacheView(source_view);
 
 1307  image_view=DestroyCacheView(image_view);
 
 1343static MagickBooleanType DrawBoundingRectangles(Image *image,
 
 1344  const DrawInfo *draw_info,
const PolygonInfo *polygon_info,
 
 1345  ExceptionInfo *exception)
 
 1373  (void) memset(primitive_info,0,
sizeof(primitive_info));
 
 1374  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 1375  status=QueryColorCompliance(
"#000F",AllCompliance,&clone_info->fill,
 
 1377  if (status == MagickFalse)
 
 1379      clone_info=DestroyDrawInfo(clone_info);
 
 1380      return(MagickFalse);
 
 1384  if (clone_info->density != (
char *) NULL)
 
 1392      flags=ParseGeometry(clone_info->density,&geometry_info);
 
 1393      if ((flags & RhoValue) != 0)
 
 1394        resolution.x=geometry_info.rho;
 
 1395      resolution.y=resolution.x;
 
 1396      if ((flags & SigmaValue) != 0)
 
 1397        resolution.y=geometry_info.sigma;
 
 1399  mid=(resolution.x/96.0)*ExpandAffine(&clone_info->affine)*
 
 1400    clone_info->stroke_width/2.0;
 
 1405  if (polygon_info != (PolygonInfo *) NULL)
 
 1407      bounds=polygon_info->edges[0].bounds;
 
 1408      for (i=1; i < (ssize_t) polygon_info->number_edges; i++)
 
 1410        if (polygon_info->edges[i].bounds.x1 < (
double) bounds.x1)
 
 1411          bounds.x1=polygon_info->edges[i].bounds.x1;
 
 1412        if (polygon_info->edges[i].bounds.y1 < (
double) bounds.y1)
 
 1413          bounds.y1=polygon_info->edges[i].bounds.y1;
 
 1414        if (polygon_info->edges[i].bounds.x2 > (
double) bounds.x2)
 
 1415          bounds.x2=polygon_info->edges[i].bounds.x2;
 
 1416        if (polygon_info->edges[i].bounds.y2 > (
double) bounds.y2)
 
 1417          bounds.y2=polygon_info->edges[i].bounds.y2;
 
 1420      bounds.x1=bounds.x1 < 0.0 ? 0.0 : bounds.x1 >= (double)
 
 1421        image->columns ? (
double) image->columns-1 : bounds.x1;
 
 1423      bounds.y1=bounds.y1 < 0.0 ? 0.0 : bounds.y1 >= (double)
 
 1424        image->rows ? (
double) image->rows-1 : bounds.y1;
 
 1426      bounds.x2=bounds.x2 < 0.0 ? 0.0 : bounds.x2 >= (double)
 
 1427        image->columns ? (
double) image->columns-1 : bounds.x2;
 
 1429      bounds.y2=bounds.y2 < 0.0 ? 0.0 : bounds.y2 >= (double)
 
 1430        image->rows ? (
double) image->rows-1 : bounds.y2;
 
 1431      for (i=0; i < (ssize_t) polygon_info->number_edges; i++)
 
 1433        if (polygon_info->edges[i].direction != 0)
 
 1434          status=QueryColorCompliance(
"#f00",AllCompliance,&clone_info->stroke,
 
 1437          status=QueryColorCompliance(
"#0f0",AllCompliance,&clone_info->stroke,
 
 1439        if (status == MagickFalse)
 
 1441        start.x=(double) (polygon_info->edges[i].bounds.x1-mid);
 
 1442        start.y=(double) (polygon_info->edges[i].bounds.y1-mid);
 
 1443        end.x=(double) (polygon_info->edges[i].bounds.x2+mid);
 
 1444        end.y=(double) (polygon_info->edges[i].bounds.y2+mid);
 
 1445        primitive_info[0].primitive=RectanglePrimitive;
 
 1446        status&=(MagickStatusType) TraceRectangle(primitive_info,start,end);
 
 1447        primitive_info[0].method=ReplaceMethod;
 
 1448        coordinates=(ssize_t) primitive_info[0].coordinates;
 
 1449        primitive_info[coordinates].primitive=UndefinedPrimitive;
 
 1450        status=DrawPrimitive(image,clone_info,primitive_info,exception);
 
 1451        if (status == MagickFalse)
 
 1454      if (i < (ssize_t) polygon_info->number_edges)
 
 1456          clone_info=DestroyDrawInfo(clone_info);
 
 1457          return(status == 0 ? MagickFalse : MagickTrue);
 
 1460  status=QueryColorCompliance(
"#00f",AllCompliance,&clone_info->stroke,
 
 1462  if (status == MagickFalse)
 
 1464      clone_info=DestroyDrawInfo(clone_info);
 
 1465      return(MagickFalse);
 
 1467  start.x=(double) (bounds.x1-mid);
 
 1468  start.y=(double) (bounds.y1-mid);
 
 1469  end.x=(double) (bounds.x2+mid);
 
 1470  end.y=(double) (bounds.y2+mid);
 
 1471  primitive_info[0].primitive=RectanglePrimitive;
 
 1472  status&=(MagickStatusType) TraceRectangle(primitive_info,start,end);
 
 1473  primitive_info[0].method=ReplaceMethod;
 
 1474  coordinates=(ssize_t) primitive_info[0].coordinates;
 
 1475  primitive_info[coordinates].primitive=UndefinedPrimitive;
 
 1476  status=DrawPrimitive(image,clone_info,primitive_info,exception);
 
 1477  clone_info=DestroyDrawInfo(clone_info);
 
 1478  return(status == 0 ? MagickFalse : MagickTrue);
 
 1510MagickExport MagickBooleanType DrawClipPath(Image *image,
 
 1511  const DrawInfo *draw_info,
const char *
id,ExceptionInfo *exception)
 
 1522  clip_path=GetImageArtifact(image,
id);
 
 1523  if (clip_path == (
const char *) NULL)
 
 1524    return(MagickFalse);
 
 1525  clipping_mask=DrawClippingMask(image,draw_info,draw_info->clip_mask,clip_path,
 
 1527  if (clipping_mask == (Image *) NULL)
 
 1528    return(MagickFalse);
 
 1529  status=SetImageMask(image,WritePixelMask,clipping_mask,exception);
 
 1530  clipping_mask=DestroyImage(clipping_mask);
 
 1566static Image *DrawClippingMask(Image *image,
const DrawInfo *draw_info,
 
 1567  const char *
id,
const char *clip_path,ExceptionInfo *exception)
 
 1582  assert(image != (Image *) NULL);
 
 1583  assert(image->signature == MagickCoreSignature);
 
 1584  assert(draw_info != (
const DrawInfo *) NULL);
 
 1585  if (IsEventLogging() != MagickFalse)
 
 1586    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 1587  clip_mask=AcquireImage((
const ImageInfo *) NULL,exception);
 
 1588  status=SetImageExtent(clip_mask,image->columns,image->rows,exception);
 
 1589  if (status == MagickFalse)
 
 1590    return(DestroyImage(clip_mask));
 
 1591  status=SetImageMask(clip_mask,WritePixelMask,(Image *) NULL,exception);
 
 1592  status=QueryColorCompliance(
"#0000",AllCompliance,
 
 1593    &clip_mask->background_color,exception);
 
 1594  clip_mask->background_color.alpha=(MagickRealType) TransparentAlpha;
 
 1595  clip_mask->background_color.alpha_trait=BlendPixelTrait;
 
 1596  status=SetImageBackgroundColor(clip_mask,exception);
 
 1597  if (draw_info->debug != MagickFalse)
 
 1598    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"\nbegin clip-path %s",
 
 1600  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 1601  (void) CloneString(&clone_info->primitive,clip_path);
 
 1602  status=QueryColorCompliance(
"#ffffff",AllCompliance,&clone_info->fill,
 
 1604  if (clone_info->clip_mask != (
char *) NULL)
 
 1605    clone_info->clip_mask=DestroyString(clone_info->clip_mask);
 
 1606  status=QueryColorCompliance(
"#00000000",AllCompliance,&clone_info->stroke,
 
 1608  clone_info->stroke_width=0.0;
 
 1609  clone_info->alpha=OpaqueAlpha;
 
 1610  clone_info->clip_path=MagickTrue;
 
 1611  status=RenderMVGContent(clip_mask,clone_info,0,exception);
 
 1612  clone_info=DestroyDrawInfo(clone_info);
 
 1613  separate_mask=SeparateImage(clip_mask,AlphaChannel,exception);
 
 1614  if (separate_mask == (Image *) NULL)
 
 1618      clip_mask=DestroyImage(clip_mask);
 
 1619      clip_mask=separate_mask;
 
 1620      status&=(MagickStatusType) NegateImage(clip_mask,MagickFalse,exception);
 
 1622  if (status == MagickFalse)
 
 1623    clip_mask=DestroyImage(clip_mask);
 
 1624  if (draw_info->debug != MagickFalse)
 
 1625    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"end clip-path");
 
 1660static Image *DrawCompositeMask(Image *image,
const DrawInfo *draw_info,
 
 1661  const char *
id,
const char *mask_path,ExceptionInfo *exception)
 
 1676  assert(image != (Image *) NULL);
 
 1677  assert(image->signature == MagickCoreSignature);
 
 1678  assert(draw_info != (
const DrawInfo *) NULL);
 
 1679  if (IsEventLogging() != MagickFalse)
 
 1680    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 1681  composite_mask=AcquireImage((
const ImageInfo *) NULL,exception);
 
 1682  status=SetImageExtent(composite_mask,image->columns,image->rows,exception);
 
 1683  if (status == MagickFalse)
 
 1684    return(DestroyImage(composite_mask));
 
 1685  status=SetImageMask(composite_mask,CompositePixelMask,(Image *) NULL,
 
 1687  status=QueryColorCompliance(
"#0000",AllCompliance,
 
 1688    &composite_mask->background_color,exception);
 
 1689  composite_mask->background_color.alpha=(MagickRealType) TransparentAlpha;
 
 1690  composite_mask->background_color.alpha_trait=BlendPixelTrait;
 
 1691  (void) SetImageBackgroundColor(composite_mask,exception);
 
 1692  if (draw_info->debug != MagickFalse)
 
 1693    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"\nbegin mask-path %s",
 
 1695  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 1696  (void) CloneString(&clone_info->primitive,mask_path);
 
 1697  status=QueryColorCompliance(
"#ffffff",AllCompliance,&clone_info->fill,
 
 1699  status=QueryColorCompliance(
"#00000000",AllCompliance,&clone_info->stroke,
 
 1701  clone_info->stroke_width=0.0;
 
 1702  clone_info->alpha=OpaqueAlpha;
 
 1703  status=RenderMVGContent(composite_mask,clone_info,0,exception);
 
 1704  clone_info=DestroyDrawInfo(clone_info);
 
 1705  separate_mask=SeparateImage(composite_mask,AlphaChannel,exception);
 
 1706  if (separate_mask != (Image *) NULL)
 
 1708      composite_mask=DestroyImage(composite_mask);
 
 1709      composite_mask=separate_mask;
 
 1710      status=NegateImage(composite_mask,MagickFalse,exception);
 
 1711      if (status == MagickFalse)
 
 1712        composite_mask=DestroyImage(composite_mask);
 
 1714  if (status == MagickFalse)
 
 1715    composite_mask=DestroyImage(composite_mask);
 
 1716  if (draw_info->debug != MagickFalse)
 
 1717    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"end mask-path");
 
 1718  return(composite_mask);
 
 1752static MagickBooleanType DrawDashPolygon(
const DrawInfo *draw_info,
 
 1753  const PrimitiveInfo *primitive_info,Image *image,ExceptionInfo *exception)
 
 1783  assert(draw_info != (
const DrawInfo *) NULL);
 
 1784  if (draw_info->debug != MagickFalse)
 
 1785    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    begin draw-dash");
 
 1786  for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++) ;
 
 1787  number_vertices=(size_t) i;
 
 1788  dash_polygon=(PrimitiveInfo *) AcquireQuantumMemory((
size_t)
 
 1789    (2UL*number_vertices+32UL),
sizeof(*dash_polygon));
 
 1790  if (dash_polygon == (PrimitiveInfo *) NULL)
 
 1792      (void) ThrowMagickException(exception,GetMagickModule(),
 
 1793        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 1794      return(MagickFalse);
 
 1796  (void) memset(dash_polygon,0,(2UL*number_vertices+32UL)*
 
 1797    sizeof(*dash_polygon));
 
 1798  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 1799  clone_info->miterlimit=0;
 
 1800  dash_polygon[0]=primitive_info[0];
 
 1801  dash_polygon[0].closed_subpath=MagickFalse;
 
 1802  scale=ExpandAffine(&draw_info->affine);
 
 1803  length=scale*draw_info->dash_pattern[0];
 
 1804  offset=fabs(draw_info->dash_offset) >= MagickEpsilon ?
 
 1805    scale*draw_info->dash_offset : 0.0;
 
 1807  for (n=0; offset > 0.0; j=0)
 
 1809    if (draw_info->dash_pattern[n] <= 0.0)
 
 1811    length=scale*(draw_info->dash_pattern[n]+(n == 0 ? -0.5 : 0.5));
 
 1812    if (offset > length)
 
 1816        length=scale*draw_info->dash_pattern[n];
 
 1819    if (offset < length)
 
 1831  for (i=1; (i < (ssize_t) number_vertices) && (length >= 0.0); i++)
 
 1833    dx=primitive_info[i].point.x-primitive_info[i-1].point.x;
 
 1834    dy=primitive_info[i].point.y-primitive_info[i-1].point.y;
 
 1835    maximum_length=hypot(dx,dy);
 
 1836    if (maximum_length > (
double) (MaxBezierCoordinates >> 2))
 
 1838    if (fabs(length) < MagickEpsilon)
 
 1840        if (fabs(draw_info->dash_pattern[n]) >= MagickEpsilon)
 
 1842        if (fabs(draw_info->dash_pattern[n]) < MagickEpsilon)
 
 1844        length=scale*draw_info->dash_pattern[n];
 
 1846    for (total_length=0.0; (length >= 0.0) && (maximum_length >= (total_length+length)); )
 
 1848      total_length+=length;
 
 1849      if ((n & 0x01) != 0)
 
 1851          dash_polygon[0]=primitive_info[0];
 
 1852          dash_polygon[0].closed_subpath=MagickFalse;
 
 1853          dash_polygon[0].point.x=(double) (primitive_info[i-1].point.x+dx*
 
 1854            total_length*MagickSafeReciprocal(maximum_length));
 
 1855          dash_polygon[0].point.y=(double) (primitive_info[i-1].point.y+dy*
 
 1856            total_length*MagickSafeReciprocal(maximum_length));
 
 1861          if ((j+1) > (ssize_t) number_vertices)
 
 1863          dash_polygon[j]=primitive_info[i-1];
 
 1864          dash_polygon[j].closed_subpath=MagickFalse;
 
 1865          dash_polygon[j].point.x=(double) (primitive_info[i-1].point.x+dx*
 
 1866            total_length*MagickSafeReciprocal(maximum_length));
 
 1867          dash_polygon[j].point.y=(double) (primitive_info[i-1].point.y+dy*
 
 1868            total_length*MagickSafeReciprocal(maximum_length));
 
 1869          dash_polygon[j].coordinates=1;
 
 1871          dash_polygon[0].coordinates=(size_t) j;
 
 1872          dash_polygon[j].primitive=UndefinedPrimitive;
 
 1873          status&=(MagickStatusType) DrawStrokePolygon(image,clone_info,
 
 1874            dash_polygon,exception);
 
 1875          if (status == MagickFalse)
 
 1878      if (fabs(draw_info->dash_pattern[n]) >= MagickEpsilon)
 
 1880      if (fabs(draw_info->dash_pattern[n]) < MagickEpsilon)
 
 1882      length=scale*draw_info->dash_pattern[n];
 
 1884    length-=(maximum_length-total_length);
 
 1885    if ((n & 0x01) != 0)
 
 1887    dash_polygon[j]=primitive_info[i];
 
 1888    dash_polygon[j].coordinates=1;
 
 1891  if ((status != MagickFalse) && (total_length < maximum_length) &&
 
 1892      ((n & 0x01) == 0) && (j > 1))
 
 1894      dash_polygon[j]=primitive_info[i-1];
 
 1895      dash_polygon[j].closed_subpath=MagickFalse;
 
 1896      dash_polygon[j].point.x+=MagickEpsilon;
 
 1897      dash_polygon[j].point.y+=MagickEpsilon;
 
 1898      dash_polygon[j].coordinates=1;
 
 1900      dash_polygon[0].coordinates=(size_t) j;
 
 1901      dash_polygon[j].primitive=UndefinedPrimitive;
 
 1902      status&=(MagickStatusType) DrawStrokePolygon(image,clone_info,
 
 1903        dash_polygon,exception);
 
 1905  dash_polygon=(PrimitiveInfo *) RelinquishMagickMemory(dash_polygon);
 
 1906  clone_info=DestroyDrawInfo(clone_info);
 
 1907  if (draw_info->debug != MagickFalse)
 
 1908    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    end draw-dash");
 
 1909  return(status != 0 ? MagickTrue : MagickFalse);
 
 1940static inline double GetStopColorOffset(
const GradientInfo *gradient,
 
 1941  const ssize_t x,
const ssize_t y)
 
 1943  switch (gradient->type)
 
 1945    case UndefinedGradient:
 
 1946    case LinearGradient:
 
 1961      gradient_vector=(&gradient->gradient_vector);
 
 1962      p.x=gradient_vector->x2-gradient_vector->x1;
 
 1963      p.y=gradient_vector->y2-gradient_vector->y1;
 
 1964      q.x=(double) x-gradient_vector->x1;
 
 1965      q.y=(double) y-gradient_vector->y1;
 
 1966      length=sqrt(q.x*q.x+q.y*q.y);
 
 1967      gamma=sqrt(p.x*p.x+p.y*p.y)*length;
 
 1968      gamma=MagickSafeReciprocal(gamma);
 
 1969      scale=p.x*q.x+p.y*q.y;
 
 1970      offset=gamma*scale*length;
 
 1973    case RadialGradient:
 
 1978      if (gradient->spread == RepeatSpread)
 
 1980          v.x=(double) x-gradient->center.x;
 
 1981          v.y=(double) y-gradient->center.y;
 
 1982          return(sqrt(v.x*v.x+v.y*v.y));
 
 1984      v.x=(double) (((x-gradient->center.x)*cos(DegreesToRadians(
 
 1985        gradient->angle)))+((y-gradient->center.y)*sin(DegreesToRadians(
 
 1986        gradient->angle))))*MagickSafeReciprocal(gradient->radii.x);
 
 1987      v.y=(double) (((x-gradient->center.x)*sin(DegreesToRadians(
 
 1988        gradient->angle)))-((y-gradient->center.y)*cos(DegreesToRadians(
 
 1989        gradient->angle))))*MagickSafeReciprocal(gradient->radii.y);
 
 1990      return(sqrt(v.x*v.x+v.y*v.y));
 
 1996static int StopInfoCompare(
const void *x,
const void *y)
 
 2002  stop_1=(StopInfo *) x;
 
 2003  stop_2=(StopInfo *) y;
 
 2004  if (stop_1->offset > stop_2->offset)
 
 2006  if (fabs(stop_1->offset-stop_2->offset) <= MagickEpsilon)
 
 2011MagickExport MagickBooleanType DrawGradientImage(Image *image,
 
 2012  const DrawInfo *draw_info,ExceptionInfo *exception)
 
 2047  assert(image != (Image *) NULL);
 
 2048  assert(image->signature == MagickCoreSignature);
 
 2049  assert(draw_info != (
const DrawInfo *) NULL);
 
 2050  if (IsEventLogging() != MagickFalse)
 
 2051    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 2052  gradient=(&draw_info->gradient);
 
 2053  qsort(gradient->stops,gradient->number_stops,
sizeof(StopInfo),
 
 2055  gradient_vector=(&gradient->gradient_vector);
 
 2056  point.x=gradient_vector->x2-gradient_vector->x1;
 
 2057  point.y=gradient_vector->y2-gradient_vector->y1;
 
 2058  length=sqrt(point.x*point.x+point.y*point.y);
 
 2059  bounding_box=gradient->bounding_box;
 
 2061  GetPixelInfo(image,&zero);
 
 2062  image_view=AcquireAuthenticCacheView(image,exception);
 
 2063  height=(size_t) (bounding_box.y+(ssize_t) bounding_box.height);
 
 2064#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 2065  #pragma omp parallel for schedule(static) shared(status) \ 
 2066    magick_number_threads(image,image,height,1) 
 2068  for (y=bounding_box.y; y < (ssize_t) height; y++)
 
 2089    if (status == MagickFalse)
 
 2091    q=GetCacheViewAuthenticPixels(image_view,bounding_box.x,y,(
size_t)
 
 2092      bounding_box.width,1,exception);
 
 2093    if (q == (Quantum *) NULL)
 
 2100    offset=GetStopColorOffset(gradient,0,y);
 
 2101    if (gradient->type != RadialGradient)
 
 2102      offset*=MagickSafeReciprocal(length);
 
 2103    width=(size_t) (bounding_box.x+(ssize_t) bounding_box.width);
 
 2104    for (x=bounding_box.x; x < (ssize_t) width; x++)
 
 2106      GetPixelInfoPixel(image,q,&pixel);
 
 2107      switch (gradient->spread)
 
 2109        case UndefinedSpread:
 
 2112          if ((x != CastDoubleToSsizeT(ceil(gradient_vector->x1-0.5))) ||
 
 2113              (y != CastDoubleToSsizeT(ceil(gradient_vector->y1-0.5))))
 
 2115              offset=GetStopColorOffset(gradient,x,y);
 
 2116              if (gradient->type != RadialGradient)
 
 2117                offset*=MagickSafeReciprocal(length);
 
 2119          for (i=0; i < (ssize_t) gradient->number_stops; i++)
 
 2120            if (offset < gradient->stops[i].offset)
 
 2122          if ((offset < 0.0) || (i == 0))
 
 2123            composite=gradient->stops[0].color;
 
 2125            if ((offset > 1.0) || (i == (ssize_t) gradient->number_stops))
 
 2126              composite=gradient->stops[gradient->number_stops-1].color;
 
 2131                alpha=(offset-gradient->stops[i].offset)/
 
 2132                  (gradient->stops[j].offset-gradient->stops[i].offset);
 
 2133                CompositePixelInfoBlend(&gradient->stops[i].color,1.0-alpha,
 
 2134                  &gradient->stops[j].color,alpha,&composite);
 
 2140          if ((x != CastDoubleToSsizeT(ceil(gradient_vector->x1-0.5))) ||
 
 2141              (y != CastDoubleToSsizeT(ceil(gradient_vector->y1-0.5))))
 
 2143              offset=GetStopColorOffset(gradient,x,y);
 
 2144              if (gradient->type != RadialGradient)
 
 2145                offset*=MagickSafeReciprocal(length);
 
 2149          if ((ssize_t) fmod(offset,2.0) == 0)
 
 2150            offset=fmod(offset,1.0);
 
 2152            offset=1.0-fmod(offset,1.0);
 
 2153          for (i=0; i < (ssize_t) gradient->number_stops; i++)
 
 2154            if (offset < gradient->stops[i].offset)
 
 2157            composite=gradient->stops[0].color;
 
 2159            if (i == (ssize_t) gradient->number_stops)
 
 2160              composite=gradient->stops[gradient->number_stops-1].color;
 
 2165                alpha=(offset-gradient->stops[i].offset)/
 
 2166                  (gradient->stops[j].offset-gradient->stops[i].offset);
 
 2167                CompositePixelInfoBlend(&gradient->stops[i].color,1.0-alpha,
 
 2168                  &gradient->stops[j].color,alpha,&composite);
 
 2180          antialias=MagickFalse;
 
 2182          if ((x != CastDoubleToSsizeT(ceil(gradient_vector->x1-0.5))) ||
 
 2183              (y != CastDoubleToSsizeT(ceil(gradient_vector->y1-0.5))))
 
 2185              offset=GetStopColorOffset(gradient,x,y);
 
 2186              if (gradient->type == LinearGradient)
 
 2188                  repeat=fmod(offset,length);
 
 2190                    repeat=length-fmod(-repeat,length);
 
 2192                    repeat=fmod(offset,length);
 
 2193                  antialias=(repeat < length) && ((repeat+1.0) > length) ?
 
 2194                    MagickTrue : MagickFalse;
 
 2195                  offset=MagickSafeReciprocal(length)*repeat;
 
 2199                  repeat=fmod(offset,gradient->radius);
 
 2201                    repeat=gradient->radius-fmod(-repeat,gradient->radius);
 
 2203                    repeat=fmod(offset,gradient->radius);
 
 2204                  antialias=repeat+1.0 > gradient->radius ? MagickTrue :
 
 2206                  offset=repeat*MagickSafeReciprocal(gradient->radius);
 
 2209          for (i=0; i < (ssize_t) gradient->number_stops; i++)
 
 2210            if (offset < gradient->stops[i].offset)
 
 2213            composite=gradient->stops[0].color;
 
 2215            if (i == (ssize_t) gradient->number_stops)
 
 2216              composite=gradient->stops[gradient->number_stops-1].color;
 
 2221                alpha=(offset-gradient->stops[i].offset)/
 
 2222                  (gradient->stops[j].offset-gradient->stops[i].offset);
 
 2223                if (antialias != MagickFalse)
 
 2225                    if (gradient->type == LinearGradient)
 
 2226                      alpha=length-repeat;
 
 2228                      alpha=gradient->radius-repeat;
 
 2230                    j=(ssize_t) gradient->number_stops-1L;
 
 2232                CompositePixelInfoBlend(&gradient->stops[i].color,1.0-alpha,
 
 2233                  &gradient->stops[j].color,alpha,&composite);
 
 2238      CompositePixelInfoOver(&composite,composite.alpha,&pixel,pixel.alpha,
 
 2240      SetPixelViaPixelInfo(image,&pixel,q);
 
 2241      q+=(ptrdiff_t) GetPixelChannels(image);
 
 2243    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
 
 2246  image_view=DestroyCacheView(image_view);
 
 2282static MagickBooleanType CheckPrimitiveExtent(MVGInfo *mvg_info,
 
 2286    **text = (
char **) NULL;
 
 2300  quantum=
sizeof(**mvg_info->primitive_info);
 
 2301  extent=(double) mvg_info->offset+pad+(PrimitiveExtentPad+1)*(double) quantum;
 
 2302  if (extent <= (
double) *mvg_info->extent)
 
 2304  if ((extent >= (
double) MAGICK_SSIZE_MAX) || (IsNaN(extent) != 0))
 
 2305    return(MagickFalse);
 
 2306  if (mvg_info->offset > 0)
 
 2308      text=(
char **) AcquireQuantumMemory((
size_t) mvg_info->offset,
 
 2310      if (text == (
char **) NULL)
 
 2311        return(MagickFalse);
 
 2312      for (i=0; i < mvg_info->offset; i++)
 
 2313        text[i]=(*mvg_info->primitive_info)[i].text;
 
 2315  *mvg_info->primitive_info=(PrimitiveInfo *) ResizeQuantumMemory(
 
 2316    *mvg_info->primitive_info,(
size_t) (extent+1),quantum);
 
 2317  if (*mvg_info->primitive_info != (PrimitiveInfo *) NULL)
 
 2319      if (text != (
char **) NULL)
 
 2320        text=(
char **) RelinquishMagickMemory(text);
 
 2321      *mvg_info->extent=(size_t) extent;
 
 2322      for (i=mvg_info->offset+1; i <= (ssize_t) extent; i++)
 
 2324        (*mvg_info->primitive_info)[i].primitive=UndefinedPrimitive;
 
 2325        (*mvg_info->primitive_info)[i].text=(
char *) NULL;
 
 2332  if (text != (
char **) NULL)
 
 2334      for (i=0; i < mvg_info->offset; i++)
 
 2335        if (text[i] != (
char *) NULL)
 
 2336          text[i]=DestroyString(text[i]);
 
 2337      text=(
char **) RelinquishMagickMemory(text);
 
 2339  (void) ThrowMagickException(mvg_info->exception,GetMagickModule(),
 
 2340    ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 2341  *mvg_info->primitive_info=(PrimitiveInfo *) AcquireCriticalMemory((
size_t)
 
 2342    (PrimitiveExtentPad+1)*quantum);
 
 2343  (void) memset(*mvg_info->primitive_info,0,(
size_t) ((PrimitiveExtentPad+1)*
 
 2345  *mvg_info->extent=1;
 
 2347  return(MagickFalse);
 
 2350static inline double GetDrawValue(
const char *magick_restrict 
string,
 
 2351  char **magick_restrict sentinel)
 
 2354    **magick_restrict q;
 
 2360  value=InterpretLocaleValue(
string,q);
 
 2365static int MVGMacroCompare(
const void *target,
const void *source)
 
 2371  p=(
const char *) target;
 
 2372  q=(
const char *) source;
 
 2373  return(strcmp(p,q));
 
 2376static SplayTreeInfo *GetMVGMacros(
const char *primitive)
 
 2394  if (primitive == (
const char *) NULL)
 
 2395    return((SplayTreeInfo *) NULL);
 
 2396  macros=NewSplayTree(MVGMacroCompare,RelinquishMagickMemory,
 
 2397    RelinquishMagickMemory);
 
 2398  macro=AcquireString(primitive);
 
 2399  token=AcquireString(primitive);
 
 2400  extent=strlen(token)+MagickPathExtent;
 
 2401  for (q=primitive; *q != 
'\0'; )
 
 2403    if (GetNextToken(q,&q,extent,token) < 1)
 
 2407    if (LocaleCompare(
"push",token) == 0)
 
 2413        (void) GetNextToken(q,&q,extent,token);
 
 2417              name[MagickPathExtent];
 
 2428            (void) GetNextToken(q,&q,extent,token);
 
 2431            (void) CopyMagickString(name,token,MagickPathExtent);
 
 2433            for (p=q; *p != 
'\0'; )
 
 2435              if (GetNextToken(p,&p,extent,token) < 1)
 
 2439              if (LocaleCompare(token,
"pop") == 0)
 
 2441                  end=p-strlen(token)-1;
 
 2444              if (LocaleCompare(token,
"push") == 0)
 
 2446              if ((n == 0) && (end >= start))
 
 2449                    length=(size_t) (end-start);
 
 2454                  (void) GetNextToken(p,&p,extent,token);
 
 2457                      (void) CopyMagickString(macro,start,length);
 
 2458                      (void) AddValueToSplayTree(macros,ConstantString(name),
 
 2459                        ConstantString(macro));
 
 2467  token=DestroyString(token);
 
 2468  macro=DestroyString(macro);
 
 2472static inline MagickBooleanType IsPoint(
const char *point)
 
 2480  value=GetDrawValue(point,&p);
 
 2481  return((fabs(value) < MagickEpsilon) && (p == point) ? MagickFalse :
 
 2485static inline MagickBooleanType TracePoint(PrimitiveInfo *primitive_info,
 
 2486  const PointInfo point)
 
 2488  primitive_info->coordinates=1;
 
 2489  primitive_info->closed_subpath=MagickFalse;
 
 2490  primitive_info->point=point;
 
 2494static MagickBooleanType RenderMVGContent(Image *image,
 
 2495  const DrawInfo *draw_info,
const size_t depth,ExceptionInfo *exception)
 
 2497#define RenderImageTag  "Render/Image" 
 2504    keyword[MagickPathExtent],
 
 2505    geometry[MagickPathExtent],
 
 2507    pattern[MagickPathExtent],
 
 2570  assert(image != (Image *) NULL);
 
 2571  assert(image->signature == MagickCoreSignature);
 
 2572  assert(draw_info != (DrawInfo *) NULL);
 
 2573  assert(draw_info->signature == MagickCoreSignature);
 
 2574  if (IsEventLogging() != MagickFalse)
 
 2575    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 2576  if (depth > MagickMaxRecursionDepth)
 
 2577    ThrowBinaryException(DrawError,
"VectorGraphicsNestedTooDeeply",
 
 2579  if ((draw_info->primitive == (
char *) NULL) ||
 
 2580      (*draw_info->primitive == 
'\0'))
 
 2581    return(MagickFalse);
 
 2582  if (draw_info->debug != MagickFalse)
 
 2583    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"begin draw-image");
 
 2584  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
 
 2585    return(MagickFalse);
 
 2586  if ((image->alpha_trait & BlendPixelTrait) == 0)
 
 2588      status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
 
 2589      if (status == MagickFalse)
 
 2590        return(MagickFalse);
 
 2592  if ((*draw_info->primitive == 
'@') && (strlen(draw_info->primitive) > 1) &&
 
 2593      (*(draw_info->primitive+1) != 
'-') && (depth == 0))
 
 2594    primitive=FileToString(draw_info->primitive,~0UL,exception);
 
 2596    primitive=AcquireString(draw_info->primitive);
 
 2597  if (primitive == (
char *) NULL)
 
 2598    return(MagickFalse);
 
 2599  primitive_extent=(double) strlen(primitive);
 
 2600  (void) SetImageArtifact(image,
"mvg:vector-graphics",primitive);
 
 2603  stops=(StopInfo *) NULL;
 
 2607  graphic_context=(DrawInfo **) AcquireMagickMemory(
sizeof(*graphic_context));
 
 2608  if (graphic_context == (DrawInfo **) NULL)
 
 2610      primitive=DestroyString(primitive);
 
 2611      ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
 
 2614  number_points=(size_t) PrimitiveExtentPad;
 
 2615  primitive_info=(PrimitiveInfo *) AcquireQuantumMemory((
size_t)
 
 2616    (number_points+1),
sizeof(*primitive_info));
 
 2617  if (primitive_info == (PrimitiveInfo *) NULL)
 
 2619      primitive=DestroyString(primitive);
 
 2620      for ( ; n >= 0; n--)
 
 2621        graphic_context[n]=DestroyDrawInfo(graphic_context[n]);
 
 2622      graphic_context=(DrawInfo **) RelinquishMagickMemory(graphic_context);
 
 2623      ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
 
 2626  (void) memset(primitive_info,0,(
size_t) (number_points+1)*
 
 2627    sizeof(*primitive_info));
 
 2628  (void) memset(&mvg_info,0,
sizeof(mvg_info));
 
 2629  mvg_info.primitive_info=(&primitive_info);
 
 2630  mvg_info.extent=(&number_points);
 
 2631  mvg_info.exception=exception;
 
 2632  graphic_context[n]=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 2633  graphic_context[n]->viewbox=image->page;
 
 2634  if ((image->page.width == 0) || (image->page.height == 0))
 
 2636      graphic_context[n]->viewbox.width=image->columns;
 
 2637      graphic_context[n]->viewbox.height=image->rows;
 
 2639  token=AcquireString(primitive);
 
 2640  extent=strlen(token)+MagickPathExtent;
 
 2644  macros=GetMVGMacros(primitive);
 
 2646  for (q=primitive; *q != 
'\0'; )
 
 2651    if (GetNextToken(q,&q,MagickPathExtent,keyword) < 1)
 
 2653    if (*keyword == 
'\0')
 
 2655    if (*keyword == 
'#')
 
 2660        while ((*q != 
'\n') && (*q != 
'\0'))
 
 2664    p=q-strlen(keyword)-1;
 
 2665    primitive_type=UndefinedPrimitive;
 
 2666    current=graphic_context[n]->affine;
 
 2667    GetAffineMatrix(&affine);
 
 2676        if (LocaleCompare(
"affine",keyword) == 0)
 
 2678            (void) GetNextToken(q,&q,extent,token);
 
 2679            affine.sx=GetDrawValue(token,&next_token);
 
 2680            if (token == next_token)
 
 2681              ThrowPointExpectedException(token,exception);
 
 2682            (void) GetNextToken(q,&q,extent,token);
 
 2684              (void) GetNextToken(q,&q,extent,token);
 
 2685            affine.ry=GetDrawValue(token,&next_token);
 
 2686            if (token == next_token)
 
 2687              ThrowPointExpectedException(token,exception);
 
 2688            (void) GetNextToken(q,&q,extent,token);
 
 2690              (void) GetNextToken(q,&q,extent,token);
 
 2691            affine.rx=GetDrawValue(token,&next_token);
 
 2692            if (token == next_token)
 
 2693              ThrowPointExpectedException(token,exception);
 
 2694            (void) GetNextToken(q,&q,extent,token);
 
 2696              (void) GetNextToken(q,&q,extent,token);
 
 2697            affine.sy=GetDrawValue(token,&next_token);
 
 2698            if (token == next_token)
 
 2699              ThrowPointExpectedException(token,exception);
 
 2700            (void) GetNextToken(q,&q,extent,token);
 
 2702              (void) GetNextToken(q,&q,extent,token);
 
 2703            affine.tx=GetDrawValue(token,&next_token);
 
 2704            if (token == next_token)
 
 2705              ThrowPointExpectedException(token,exception);
 
 2706            (void) GetNextToken(q,&q,extent,token);
 
 2708              (void) GetNextToken(q,&q,extent,token);
 
 2709            affine.ty=GetDrawValue(token,&next_token);
 
 2710            if (token == next_token)
 
 2711              ThrowPointExpectedException(token,exception);
 
 2714        if (LocaleCompare(
"alpha",keyword) == 0)
 
 2716            primitive_type=AlphaPrimitive;
 
 2719        if (LocaleCompare(
"arc",keyword) == 0)
 
 2721            primitive_type=ArcPrimitive;
 
 2730        if (LocaleCompare(
"bezier",keyword) == 0)
 
 2732            primitive_type=BezierPrimitive;
 
 2735        if (LocaleCompare(
"border-color",keyword) == 0)
 
 2737            (void) GetNextToken(q,&q,extent,token);
 
 2738            status&=(MagickStatusType) QueryColorCompliance(token,AllCompliance,
 
 2739              &graphic_context[n]->border_color,exception);
 
 2748        if (LocaleCompare(
"class",keyword) == 0)
 
 2753            (void) GetNextToken(q,&q,extent,token);
 
 2754            if ((*token == 
'\0') || (*token == 
';'))
 
 2762            for (i=0; i <= n; i++)
 
 2763              if (LocaleCompare(token,graphic_context[i]->
id) == 0)
 
 2767            mvg_class=(
const char *) GetValueFromSplayTree(macros,token);
 
 2768            if ((graphic_context[n]->render != MagickFalse) &&
 
 2769                (mvg_class != (
const char *) NULL) && (p > primitive))
 
 2780                (void) CloneString(&graphic_context[n]->
id,token);
 
 2781                offset=(ssize_t) (p-primitive);
 
 2782                elements=AcquireString(primitive);
 
 2783                elements[offset]=
'\0';
 
 2784                (void) ConcatenateString(&elements,mvg_class);
 
 2785                (void) ConcatenateString(&elements,
"\n");
 
 2786                (void) ConcatenateString(&elements,q);
 
 2787                primitive=DestroyString(primitive);
 
 2793        if (LocaleCompare(
"clip-path",keyword) == 0)
 
 2801            (void) GetNextToken(q,&q,extent,token);
 
 2807            (void) CloneString(&graphic_context[n]->clip_mask,token);
 
 2808            clip_path=(
const char *) GetValueFromSplayTree(macros,token);
 
 2809            if (clip_path != (
const char *) NULL)
 
 2811                if (graphic_context[n]->clipping_mask != (Image *) NULL)
 
 2812                  graphic_context[n]->clipping_mask=
 
 2813                    DestroyImage(graphic_context[n]->clipping_mask);
 
 2814                graphic_context[n]->clipping_mask=DrawClippingMask(image,
 
 2815                  graphic_context[n],token,clip_path,exception);
 
 2816                if (graphic_context[n]->compliance != SVGCompliance)
 
 2818                    clip_path=(
const char *) GetValueFromSplayTree(macros,
 
 2819                      graphic_context[n]->clip_mask);
 
 2820                    if (clip_path != (
const char *) NULL)
 
 2821                      (void) SetImageArtifact(image,
 
 2822                        graphic_context[n]->clip_mask,clip_path);
 
 2823                    status&=(MagickStatusType) DrawClipPath(image,
 
 2824                      graphic_context[n],graphic_context[n]->clip_mask,
 
 2830        if (LocaleCompare(
"clip-rule",keyword) == 0)
 
 2835            (void) GetNextToken(q,&q,extent,token);
 
 2836            fill_rule=ParseCommandOption(MagickFillRuleOptions,MagickFalse,
 
 2838            if (fill_rule == -1)
 
 2843            graphic_context[n]->fill_rule=(FillRule) fill_rule;
 
 2846        if (LocaleCompare(
"clip-units",keyword) == 0)
 
 2851            (void) GetNextToken(q,&q,extent,token);
 
 2852            clip_units=ParseCommandOption(MagickClipPathOptions,MagickFalse,
 
 2854            if (clip_units == -1)
 
 2859            graphic_context[n]->clip_units=(ClipPathUnits) clip_units;
 
 2860            if (clip_units == ObjectBoundingBox)
 
 2862                GetAffineMatrix(¤t);
 
 2863                affine.sx=draw_info->bounds.x2;
 
 2864                affine.sy=draw_info->bounds.y2;
 
 2865                affine.tx=draw_info->bounds.x1;
 
 2866                affine.ty=draw_info->bounds.y1;
 
 2871        if (LocaleCompare(
"circle",keyword) == 0)
 
 2873            primitive_type=CirclePrimitive;
 
 2876        if (LocaleCompare(
"color",keyword) == 0)
 
 2878            primitive_type=ColorPrimitive;
 
 2881        if (LocaleCompare(
"compliance",keyword) == 0)
 
 2887            (void) GetNextToken(q,&q,extent,token);
 
 2888            graphic_context[n]->compliance=(ComplianceType) ParseCommandOption(
 
 2889              MagickComplianceOptions,MagickFalse,token);
 
 2892        if (LocaleCompare(
"currentColor",keyword) == 0)
 
 2894            (void) GetNextToken(q,&q,extent,token);
 
 2903        if (LocaleCompare(
"decorate",keyword) == 0)
 
 2908            (void) GetNextToken(q,&q,extent,token);
 
 2909            decorate=ParseCommandOption(MagickDecorateOptions,MagickFalse,
 
 2916            graphic_context[n]->decorate=(DecorationType) decorate;
 
 2919        if (LocaleCompare(
"density",keyword) == 0)
 
 2921            (void) GetNextToken(q,&q,extent,token);
 
 2922            (void) CloneString(&graphic_context[n]->density,token);
 
 2925        if (LocaleCompare(
"direction",keyword) == 0)
 
 2930            (void) GetNextToken(q,&q,extent,token);
 
 2931            direction=ParseCommandOption(MagickDirectionOptions,MagickFalse,
 
 2933            if (direction == -1)
 
 2936              graphic_context[n]->direction=(DirectionType) direction;
 
 2945        if (LocaleCompare(
"ellipse",keyword) == 0)
 
 2947            primitive_type=EllipsePrimitive;
 
 2950        if (LocaleCompare(
"encoding",keyword) == 0)
 
 2952            (void) GetNextToken(q,&q,extent,token);
 
 2953            (void) CloneString(&graphic_context[n]->encoding,token);
 
 2962        if (LocaleCompare(
"fill",keyword) == 0)
 
 2967            (void) GetNextToken(q,&q,extent,token);
 
 2968            if (graphic_context[n]->clip_path != MagickFalse)
 
 2970            mvg_class=(
const char *) GetValueFromSplayTree(macros,token);
 
 2971            if (mvg_class != (
const char *) NULL)
 
 2973                (void) DrawPatternPath(image,draw_info,mvg_class,
 
 2974                  &graphic_context[n]->fill_pattern,exception);
 
 2977            (void) FormatLocaleString(pattern,MagickPathExtent,
"%s",token);
 
 2978            if (GetImageArtifact(image,pattern) != (
const char *) NULL)
 
 2980                (void) DrawPatternPath(image,draw_info,token,
 
 2981                  &graphic_context[n]->fill_pattern,exception);
 
 2984            status&=(MagickStatusType) QueryColorCompliance(token,AllCompliance,
 
 2985              &graphic_context[n]->fill,exception);
 
 2986            if (graphic_context[n]->fill_alpha != (
double) OpaqueAlpha)
 
 2987              graphic_context[n]->fill.alpha=graphic_context[n]->fill_alpha;
 
 2990        if (LocaleCompare(
"fill-opacity",keyword) == 0)
 
 2995            (void) GetNextToken(q,&q,extent,token);
 
 2996            if (graphic_context[n]->clip_path != MagickFalse)
 
 2998            factor=strchr(token,
'%') != (
char *) NULL ? 0.01 : 1.0;
 
 2999            opacity=MagickMin(MagickMax(factor*
 
 3000              GetDrawValue(token,&next_token),0.0),1.0);
 
 3001            if (token == next_token)
 
 3002              ThrowPointExpectedException(token,exception);
 
 3003            if (graphic_context[n]->compliance == SVGCompliance)
 
 3004              graphic_context[n]->fill_alpha*=opacity;
 
 3006              graphic_context[n]->fill_alpha=(double) QuantumRange*opacity;
 
 3007            if (graphic_context[n]->fill.alpha != (
double) TransparentAlpha)
 
 3008              graphic_context[n]->fill.alpha=graphic_context[n]->fill_alpha;
 
 3010              graphic_context[n]->fill.alpha=(MagickRealType)
 
 3011                ClampToQuantum((
double) QuantumRange*opacity);
 
 3012            graphic_context[n]->fill.alpha_trait=BlendPixelTrait;
 
 3015        if (LocaleCompare(
"fill-rule",keyword) == 0)
 
 3020            (void) GetNextToken(q,&q,extent,token);
 
 3021            fill_rule=ParseCommandOption(MagickFillRuleOptions,MagickFalse,
 
 3023            if (fill_rule == -1)
 
 3028            graphic_context[n]->fill_rule=(FillRule) fill_rule;
 
 3031        if (LocaleCompare(
"font",keyword) == 0)
 
 3033            (void) GetNextToken(q,&q,extent,token);
 
 3034            (void) CloneString(&graphic_context[n]->font,token);
 
 3035            if (LocaleCompare(
"none",token) == 0)
 
 3036              graphic_context[n]->font=(
char *) RelinquishMagickMemory(
 
 3037                graphic_context[n]->font);
 
 3040        if (LocaleCompare(
"font-family",keyword) == 0)
 
 3042            (void) GetNextToken(q,&q,extent,token);
 
 3043            (void) CloneString(&graphic_context[n]->family,token);
 
 3046        if (LocaleCompare(
"font-size",keyword) == 0)
 
 3048            (void) GetNextToken(q,&q,extent,token);
 
 3049            graphic_context[n]->pointsize=GetDrawValue(token,&next_token);
 
 3050            if (token == next_token)
 
 3051              ThrowPointExpectedException(token,exception);
 
 3054        if (LocaleCompare(
"font-stretch",keyword) == 0)
 
 3059            (void) GetNextToken(q,&q,extent,token);
 
 3060            stretch=ParseCommandOption(MagickStretchOptions,MagickFalse,token);
 
 3066            graphic_context[n]->stretch=(StretchType) stretch;
 
 3069        if (LocaleCompare(
"font-style",keyword) == 0)
 
 3074            (void) GetNextToken(q,&q,extent,token);
 
 3075            style=ParseCommandOption(MagickStyleOptions,MagickFalse,token);
 
 3081            graphic_context[n]->style=(StyleType) style;
 
 3084        if (LocaleCompare(
"font-weight",keyword) == 0)
 
 3089            (void) GetNextToken(q,&q,extent,token);
 
 3090            weight=ParseCommandOption(MagickWeightOptions,MagickFalse,token);
 
 3092              weight=(ssize_t) StringToUnsignedLong(token);
 
 3093            graphic_context[n]->weight=(size_t) weight;
 
 3102        if (LocaleCompare(
"gradient-units",keyword) == 0)
 
 3104            (void) GetNextToken(q,&q,extent,token);
 
 3107        if (LocaleCompare(
"gravity",keyword) == 0)
 
 3112            (void) GetNextToken(q,&q,extent,token);
 
 3113            gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,token);
 
 3119            graphic_context[n]->gravity=(GravityType) gravity;
 
 3128        if (LocaleCompare(
"image",keyword) == 0)
 
 3133            primitive_type=ImagePrimitive;
 
 3134            (void) GetNextToken(q,&q,extent,token);
 
 3135            compose=ParseCommandOption(MagickComposeOptions,MagickFalse,token);
 
 3141            graphic_context[n]->compose=(CompositeOperator) compose;
 
 3144        if (LocaleCompare(
"interline-spacing",keyword) == 0)
 
 3146            (void) GetNextToken(q,&q,extent,token);
 
 3147            graphic_context[n]->interline_spacing=GetDrawValue(token,
 
 3149            if (token == next_token)
 
 3150              ThrowPointExpectedException(token,exception);
 
 3153        if (LocaleCompare(
"interword-spacing",keyword) == 0)
 
 3155            (void) GetNextToken(q,&q,extent,token);
 
 3156            graphic_context[n]->interword_spacing=GetDrawValue(token,
 
 3158            if (token == next_token)
 
 3159              ThrowPointExpectedException(token,exception);
 
 3168        if (LocaleCompare(
"kerning",keyword) == 0)
 
 3170            (void) GetNextToken(q,&q,extent,token);
 
 3171            graphic_context[n]->kerning=GetDrawValue(token,&next_token);
 
 3172            if (token == next_token)
 
 3173              ThrowPointExpectedException(token,exception);
 
 3182        if (LocaleCompare(
"letter-spacing",keyword) == 0)
 
 3184            (void) GetNextToken(q,&q,extent,token);
 
 3185            if (IsPoint(token) == MagickFalse)
 
 3187            clone_info=CloneDrawInfo((ImageInfo *) NULL,graphic_context[n]);
 
 3188            clone_info->text=AcquireString(
" ");
 
 3189            status&=(MagickStatusType) GetTypeMetrics(image,clone_info,&metrics,
 
 3191            graphic_context[n]->kerning=metrics.width*
 
 3192              GetDrawValue(token,&next_token);
 
 3193            clone_info=DestroyDrawInfo(clone_info);
 
 3194            if (token == next_token)
 
 3195              ThrowPointExpectedException(token,exception);
 
 3198        if (LocaleCompare(
"line",keyword) == 0)
 
 3200            primitive_type=LinePrimitive;
 
 3209        if (LocaleCompare(
"mask",keyword) == 0)
 
 3217            (void) GetNextToken(q,&q,extent,token);
 
 3218            mask_path=(
const char *) GetValueFromSplayTree(macros,token);
 
 3219            if (mask_path != (
const char *) NULL)
 
 3221                if (graphic_context[n]->composite_mask != (Image *) NULL)
 
 3222                  graphic_context[n]->composite_mask=
 
 3223                    DestroyImage(graphic_context[n]->composite_mask);
 
 3224                graphic_context[n]->composite_mask=DrawCompositeMask(image,
 
 3225                  graphic_context[n],token,mask_path,exception);
 
 3226                if (graphic_context[n]->compliance != SVGCompliance)
 
 3227                  status=SetImageMask(image,CompositePixelMask,
 
 3228                    graphic_context[n]->composite_mask,exception);
 
 3238        if (LocaleCompare(
"offset",keyword) == 0)
 
 3240            (void) GetNextToken(q,&q,extent,token);
 
 3243        if (LocaleCompare(
"opacity",keyword) == 0)
 
 3248            (void) GetNextToken(q,&q,extent,token);
 
 3249            if (graphic_context[n]->clip_path != MagickFalse)
 
 3251            factor=strchr(token,
'%') != (
char *) NULL ? 0.01 : 1.0;
 
 3252            opacity=MagickMin(MagickMax(factor*
 
 3253              GetDrawValue(token,&next_token),0.0),1.0);
 
 3254            if (token == next_token)
 
 3255              ThrowPointExpectedException(token,exception);
 
 3256            if (graphic_context[n]->compliance == SVGCompliance)
 
 3258                graphic_context[n]->fill_alpha*=opacity;
 
 3259                graphic_context[n]->stroke_alpha*=opacity;
 
 3263                graphic_context[n]->fill_alpha=(double) QuantumRange*opacity;
 
 3264                graphic_context[n]->stroke_alpha=(double) QuantumRange*opacity;
 
 3266            if (graphic_context[n]->fill.alpha != (
double) TransparentAlpha)
 
 3268                graphic_context[n]->fill.alpha=graphic_context[n]->fill_alpha;
 
 3269                graphic_context[n]->stroke.alpha=graphic_context[n]->stroke_alpha;
 
 3273                graphic_context[n]->fill.alpha=(MagickRealType)
 
 3274                  ClampToQuantum((
double) QuantumRange*opacity);
 
 3275                graphic_context[n]->stroke.alpha=(MagickRealType)
 
 3276                  ClampToQuantum((
double) QuantumRange*opacity);
 
 3278            graphic_context[n]->fill.alpha_trait=BlendPixelTrait;
 
 3279            graphic_context[n]->stroke.alpha_trait=BlendPixelTrait;
 
 3288        if (LocaleCompare(
"path",keyword) == 0)
 
 3290            primitive_type=PathPrimitive;
 
 3293        if (LocaleCompare(
"point",keyword) == 0)
 
 3295            primitive_type=PointPrimitive;
 
 3298        if (LocaleCompare(
"polyline",keyword) == 0)
 
 3300            primitive_type=PolylinePrimitive;
 
 3303        if (LocaleCompare(
"polygon",keyword) == 0)
 
 3305            primitive_type=PolygonPrimitive;
 
 3308        if (LocaleCompare(
"pop",keyword) == 0)
 
 3310            if (GetNextToken(q,&q,extent,token) < 1)
 
 3312            if (LocaleCompare(
"class",token) == 0)
 
 3314            if (LocaleCompare(
"clip-path",token) == 0)
 
 3316            if (LocaleCompare(
"defs",token) == 0)
 
 3319                graphic_context[n]->render=defsDepth > 0 ? MagickFalse :
 
 3323            if (LocaleCompare(
"gradient",token) == 0)
 
 3325            if (LocaleCompare(
"graphic-context",token) == 0)
 
 3329                    (void) ThrowMagickException(exception,GetMagickModule(),
 
 3330                      DrawError,
"UnbalancedGraphicContextPushPop",
"`%s'",token);
 
 3335                if ((graphic_context[n]->clip_mask != (
char *) NULL) &&
 
 3336                    (graphic_context[n]->compliance != SVGCompliance))
 
 3337                  if (LocaleCompare(graphic_context[n]->clip_mask,
 
 3338                      graphic_context[n-1]->clip_mask) != 0)
 
 3339                    status=SetImageMask(image,WritePixelMask,(Image *) NULL,
 
 3341                graphic_context[n]=DestroyDrawInfo(graphic_context[n]);
 
 3345            if (LocaleCompare(
"mask",token) == 0)
 
 3347            if (LocaleCompare(
"pattern",token) == 0)
 
 3349            if (LocaleCompare(
"symbol",token) == 0)
 
 3352                graphic_context[n]->render=symbolDepth > 0 ? MagickFalse :
 
 3359        if (LocaleCompare(
"push",keyword) == 0)
 
 3361            if (GetNextToken(q,&q,extent,token) < 1)
 
 3363            if (LocaleCompare(
"class",token) == 0)
 
 3368                for (p=q; *q != 
'\0'; )
 
 3370                  if (GetNextToken(q,&q,extent,token) < 1)
 
 3372                  if (LocaleCompare(token,
"pop") != 0)
 
 3374                  (void) GetNextToken(q,(
const char **) NULL,extent,token);
 
 3375                  if (LocaleCompare(token,
"class") != 0)
 
 3379                (void) GetNextToken(q,&q,extent,token);
 
 3382            if (LocaleCompare(
"clip-path",token) == 0)
 
 3384                (void) GetNextToken(q,&q,extent,token);
 
 3385                for (p=q; *q != 
'\0'; )
 
 3387                  if (GetNextToken(q,&q,extent,token) < 1)
 
 3389                  if (LocaleCompare(token,
"pop") != 0)
 
 3391                  (void) GetNextToken(q,(
const char **) NULL,extent,token);
 
 3392                  if (LocaleCompare(token,
"clip-path") != 0)
 
 3396                if ((q == (
char *) NULL) || (p == (
char *) NULL) || ((q-4) < p))
 
 3401                (void) GetNextToken(q,&q,extent,token);
 
 3404            if (LocaleCompare(
"defs",token) == 0)
 
 3407                graphic_context[n]->render=defsDepth > 0 ? MagickFalse :
 
 3411            if (LocaleCompare(
"gradient",token) == 0)
 
 3414                  key[2*MagickPathExtent],
 
 3415                  name[MagickPathExtent],
 
 3416                  type[MagickPathExtent];
 
 3421                (void) GetNextToken(q,&q,extent,token);
 
 3422                (void) CopyMagickString(name,token,MagickPathExtent);
 
 3423                (void) GetNextToken(q,&q,extent,token);
 
 3424                (void) CopyMagickString(type,token,MagickPathExtent);
 
 3425                (void) GetNextToken(q,&q,extent,token);
 
 3426                segment.x1=GetDrawValue(token,&next_token);
 
 3427                if (token == next_token)
 
 3428                  ThrowPointExpectedException(token,exception);
 
 3429                (void) GetNextToken(q,&q,extent,token);
 
 3431                  (void) GetNextToken(q,&q,extent,token);
 
 3432                segment.y1=GetDrawValue(token,&next_token);
 
 3433                if (token == next_token)
 
 3434                  ThrowPointExpectedException(token,exception);
 
 3435                (void) GetNextToken(q,&q,extent,token);
 
 3437                  (void) GetNextToken(q,&q,extent,token);
 
 3438                segment.x2=GetDrawValue(token,&next_token);
 
 3439                if (token == next_token)
 
 3440                  ThrowPointExpectedException(token,exception);
 
 3441                (void) GetNextToken(q,&q,extent,token);
 
 3443                  (void) GetNextToken(q,&q,extent,token);
 
 3444                segment.y2=GetDrawValue(token,&next_token);
 
 3445                if (token == next_token)
 
 3446                  ThrowPointExpectedException(token,exception);
 
 3447                if (LocaleCompare(type,
"radial") == 0)
 
 3449                    (void) GetNextToken(q,&q,extent,token);
 
 3451                      (void) GetNextToken(q,&q,extent,token);
 
 3453                for (p=q; *q != 
'\0'; )
 
 3455                  if (GetNextToken(q,&q,extent,token) < 1)
 
 3457                  if (LocaleCompare(token,
"pop") != 0)
 
 3459                  (void) GetNextToken(q,(
const char **) NULL,extent,token);
 
 3460                  if (LocaleCompare(token,
"gradient") != 0)
 
 3464                if ((q == (
char *) NULL) || (*q == 
'\0') || 
 
 3465                    (p == (
char *) NULL) || ((q-4) < p))
 
 3470                (void) CopyMagickString(token,p,(
size_t) (q-p-4+1));
 
 3471                bounds.x1=graphic_context[n]->affine.sx*segment.x1+
 
 3472                  graphic_context[n]->affine.ry*segment.y1+
 
 3473                  graphic_context[n]->affine.tx;
 
 3474                bounds.y1=graphic_context[n]->affine.rx*segment.x1+
 
 3475                  graphic_context[n]->affine.sy*segment.y1+
 
 3476                  graphic_context[n]->affine.ty;
 
 3477                bounds.x2=graphic_context[n]->affine.sx*segment.x2+
 
 3478                  graphic_context[n]->affine.ry*segment.y2+
 
 3479                  graphic_context[n]->affine.tx;
 
 3480                bounds.y2=graphic_context[n]->affine.rx*segment.x2+
 
 3481                  graphic_context[n]->affine.sy*segment.y2+
 
 3482                  graphic_context[n]->affine.ty;
 
 3483                (void) FormatLocaleString(key,MagickPathExtent,
"%s",name);
 
 3484                (void) SetImageArtifact(image,key,token);
 
 3485                (void) FormatLocaleString(key,MagickPathExtent,
"%s-type",name);
 
 3486                (void) SetImageArtifact(image,key,type);
 
 3487                (void) FormatLocaleString(key,MagickPathExtent,
"%s-geometry",
 
 3489                (void) FormatLocaleString(geometry,MagickPathExtent,
 
 3490                  "%gx%g%+.15g%+.15g",
 
 3491                  MagickMax(fabs(bounds.x2-bounds.x1+1.0),1.0),
 
 3492                  MagickMax(fabs(bounds.y2-bounds.y1+1.0),1.0),
 
 3493                  bounds.x1,bounds.y1);
 
 3494                (void) SetImageArtifact(image,key,geometry);
 
 3495                (void) GetNextToken(q,&q,extent,token);
 
 3498            if (LocaleCompare(
"graphic-context",token) == 0)
 
 3501                graphic_context=(DrawInfo **) ResizeQuantumMemory(
 
 3502                  graphic_context,(
size_t) (n+1),
sizeof(*graphic_context));
 
 3503                if (graphic_context == (DrawInfo **) NULL)
 
 3505                    (void) ThrowMagickException(exception,GetMagickModule(),
 
 3506                      ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
 
 3510                graphic_context[n]=CloneDrawInfo((ImageInfo *) NULL,
 
 3511                  graphic_context[n-1]);
 
 3514                    (void) GetNextToken(q,&q,extent,token);
 
 3515                    (void) CloneString(&graphic_context[n]->
id,token);
 
 3519            if (LocaleCompare(
"mask",token) == 0)
 
 3521                (void) GetNextToken(q,&q,extent,token);
 
 3524            if (LocaleCompare(
"pattern",token) == 0)
 
 3527                  key[2*MagickPathExtent],
 
 3528                  name[MagickPathExtent];
 
 3533                (void) GetNextToken(q,&q,extent,token);
 
 3534                (void) CopyMagickString(name,token,MagickPathExtent);
 
 3535                (void) GetNextToken(q,&q,extent,token);
 
 3536                region.x=CastDoubleToSsizeT(ceil(GetDrawValue(token,
 
 3538                if (token == next_token)
 
 3539                  ThrowPointExpectedException(token,exception);
 
 3540                (void) GetNextToken(q,&q,extent,token);
 
 3542                  (void) GetNextToken(q,&q,extent,token);
 
 3543                region.y=CastDoubleToSsizeT(ceil(GetDrawValue(token,
 
 3545                if (token == next_token)
 
 3546                  ThrowPointExpectedException(token,exception);
 
 3547                (void) GetNextToken(q,&q,extent,token);
 
 3549                  (void) GetNextToken(q,&q,extent,token);
 
 3550                region.width=CastDoubleToSizeT(floor(GetDrawValue(token,
 
 3552                if (token == next_token)
 
 3553                  ThrowPointExpectedException(token,exception);
 
 3554                (void) GetNextToken(q,&q,extent,token);
 
 3556                  (void) GetNextToken(q,&q,extent,token);
 
 3557                region.height=CastDoubleToSizeT(GetDrawValue(token,
 
 3559                if (token == next_token)
 
 3560                  ThrowPointExpectedException(token,exception);
 
 3561                for (p=q; *q != 
'\0'; )
 
 3563                  if (GetNextToken(q,&q,extent,token) < 1)
 
 3565                  if (LocaleCompare(token,
"pop") != 0)
 
 3567                  (void) GetNextToken(q,(
const char **) NULL,extent,token);
 
 3568                  if (LocaleCompare(token,
"pattern") != 0)
 
 3572                if ((q == (
char *) NULL) || (p == (
char *) NULL) || ((q-4) < p))
 
 3577                (void) CopyMagickString(token,p,(
size_t) (q-p-4+1));
 
 3578                (void) FormatLocaleString(key,MagickPathExtent,
"%s",name);
 
 3579                (void) SetImageArtifact(image,key,token);
 
 3580                (void) FormatLocaleString(key,MagickPathExtent,
"%s-geometry",
 
 3582                (void) FormatLocaleString(geometry,MagickPathExtent,
 
 3583                  "%.20gx%.20g%+.20g%+.20g",(
double) region.width,(
double)
 
 3584                  region.height,(
double) region.x,(
double) region.y);
 
 3585                (void) SetImageArtifact(image,key,geometry);
 
 3586                (void) GetNextToken(q,&q,extent,token);
 
 3589            if (LocaleCompare(
"symbol",token) == 0)
 
 3592                graphic_context[n]->render=symbolDepth > 0 ? MagickFalse :
 
 3605        if (LocaleCompare(
"rectangle",keyword) == 0)
 
 3607            primitive_type=RectanglePrimitive;
 
 3610        if (LocaleCompare(
"rotate",keyword) == 0)
 
 3612            (void) GetNextToken(q,&q,extent,token);
 
 3613            angle=GetDrawValue(token,&next_token);
 
 3614            if (token == next_token)
 
 3615              ThrowPointExpectedException(token,exception);
 
 3616            affine.sx=cos(DegreesToRadians(fmod((
double) angle,360.0)));
 
 3617            affine.rx=sin(DegreesToRadians(fmod((
double) angle,360.0)));
 
 3618            affine.ry=(-sin(DegreesToRadians(fmod((
double) angle,360.0))));
 
 3619            affine.sy=cos(DegreesToRadians(fmod((
double) angle,360.0)));
 
 3622        if (LocaleCompare(
"roundRectangle",keyword) == 0)
 
 3624            primitive_type=RoundRectanglePrimitive;
 
 3633        if (LocaleCompare(
"scale",keyword) == 0)
 
 3635            (void) GetNextToken(q,&q,extent,token);
 
 3636            affine.sx=GetDrawValue(token,&next_token);
 
 3637            if (token == next_token)
 
 3638              ThrowPointExpectedException(token,exception);
 
 3639            (void) GetNextToken(q,&q,extent,token);
 
 3641              (void) GetNextToken(q,&q,extent,token);
 
 3642            affine.sy=GetDrawValue(token,&next_token);
 
 3643            if (token == next_token)
 
 3644              ThrowPointExpectedException(token,exception);
 
 3647        if (LocaleCompare(
"skewX",keyword) == 0)
 
 3649            (void) GetNextToken(q,&q,extent,token);
 
 3650            angle=GetDrawValue(token,&next_token);
 
 3651            if (token == next_token)
 
 3652              ThrowPointExpectedException(token,exception);
 
 3653            affine.ry=sin(DegreesToRadians(angle));
 
 3656        if (LocaleCompare(
"skewY",keyword) == 0)
 
 3658            (void) GetNextToken(q,&q,extent,token);
 
 3659            angle=GetDrawValue(token,&next_token);
 
 3660            if (token == next_token)
 
 3661              ThrowPointExpectedException(token,exception);
 
 3662            affine.rx=(-tan(DegreesToRadians(angle)/2.0));
 
 3665        if (LocaleCompare(
"stop-color",keyword) == 0)
 
 3671            if (number_stops == 1)
 
 3672              stops=(StopInfo *) AcquireQuantumMemory(2,
sizeof(*stops));
 
 3674              if (number_stops > 2)
 
 3675                stops=(StopInfo *) ResizeQuantumMemory(stops,number_stops,
 
 3677            if (stops == (StopInfo *) NULL)
 
 3679                (void) ThrowMagickException(exception,GetMagickModule(),
 
 3680                  ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
 
 3684            (void) GetNextToken(q,&q,extent,token);
 
 3685            status&=(MagickStatusType) QueryColorCompliance(token,AllCompliance,
 
 3686              &stop_color,exception);
 
 3687            stops[number_stops-1].color=stop_color;
 
 3688            (void) GetNextToken(q,&q,extent,token);
 
 3689            factor=strchr(token,
'%') != (
char *) NULL ? 0.01 : 1.0;
 
 3690            stops[number_stops-1].offset=factor*GetDrawValue(token,
 
 3692            if (token == next_token)
 
 3693              ThrowPointExpectedException(token,exception);
 
 3696        if (LocaleCompare(
"stroke",keyword) == 0)
 
 3701            (void) GetNextToken(q,&q,extent,token);
 
 3702            if (graphic_context[n]->clip_path != MagickFalse)
 
 3704            mvg_class=(
const char *) GetValueFromSplayTree(macros,token);
 
 3705            if (mvg_class != (
const char *) NULL)
 
 3707                (void) DrawPatternPath(image,draw_info,mvg_class,
 
 3708                  &graphic_context[n]->stroke_pattern,exception);
 
 3711            (void) FormatLocaleString(pattern,MagickPathExtent,
"%s",token);
 
 3712            if (GetImageArtifact(image,pattern) != (
const char *) NULL)
 
 3714                (void) DrawPatternPath(image,draw_info,token,
 
 3715                  &graphic_context[n]->stroke_pattern,exception);
 
 3718            status&=(MagickStatusType) QueryColorCompliance(token,AllCompliance,
 
 3719              &graphic_context[n]->stroke,exception);
 
 3720            if (graphic_context[n]->stroke_alpha != (
double) OpaqueAlpha)
 
 3721              graphic_context[n]->stroke.alpha=
 
 3722                graphic_context[n]->stroke_alpha;
 
 3725        if (LocaleCompare(
"stroke-antialias",keyword) == 0)
 
 3727            (void) GetNextToken(q,&q,extent,token);
 
 3728            graphic_context[n]->stroke_antialias=StringToLong(token) != 0 ?
 
 3729              MagickTrue : MagickFalse;
 
 3732        if (LocaleCompare(
"stroke-dasharray",keyword) == 0)
 
 3734            if (graphic_context[n]->dash_pattern != (
double *) NULL)
 
 3735              graphic_context[n]->dash_pattern=(
double *)
 
 3736                RelinquishMagickMemory(graphic_context[n]->dash_pattern);
 
 3737            if (IsPoint(q) != MagickFalse)
 
 3743                (void) GetNextToken(r,&r,extent,token);
 
 3745                  (void) GetNextToken(r,&r,extent,token);
 
 3746                for (x=0; IsPoint(token) != MagickFalse; x++)
 
 3748                  (void) GetNextToken(r,&r,extent,token);
 
 3750                    (void) GetNextToken(r,&r,extent,token);
 
 3752                graphic_context[n]->dash_pattern=(
double *)
 
 3753                  AcquireQuantumMemory((
size_t) (2*x+2),
 
 3754                  sizeof(*graphic_context[n]->dash_pattern));
 
 3755                if (graphic_context[n]->dash_pattern == (
double *) NULL)
 
 3757                    (void) ThrowMagickException(exception,GetMagickModule(),
 
 3758                      ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
 
 3763                (void) memset(graphic_context[n]->dash_pattern,0,(
size_t)
 
 3764                  (2*x+2)*
sizeof(*graphic_context[n]->dash_pattern));
 
 3765                for (j=0; j < x; j++)
 
 3767                  (void) GetNextToken(q,&q,extent,token);
 
 3769                    (void) GetNextToken(q,&q,extent,token);
 
 3770                  graphic_context[n]->dash_pattern[j]=GetDrawValue(token,
 
 3772                  if (token == next_token)
 
 3773                    ThrowPointExpectedException(token,exception);
 
 3774                  if (graphic_context[n]->dash_pattern[j] <= 0.0)
 
 3777                if ((x & 0x01) != 0)
 
 3778                  for ( ; j < (2*x); j++)
 
 3779                    graphic_context[n]->dash_pattern[j]=
 
 3780                      graphic_context[n]->dash_pattern[j-x];
 
 3781                graphic_context[n]->dash_pattern[j]=0.0;
 
 3784            (void) GetNextToken(q,&q,extent,token);
 
 3787        if (LocaleCompare(
"stroke-dashoffset",keyword) == 0)
 
 3789            (void) GetNextToken(q,&q,extent,token);
 
 3790            graphic_context[n]->dash_offset=GetDrawValue(token,&next_token);
 
 3791            if (token == next_token)
 
 3792              ThrowPointExpectedException(token,exception);
 
 3795        if (LocaleCompare(
"stroke-linecap",keyword) == 0)
 
 3800            (void) GetNextToken(q,&q,extent,token);
 
 3801            linecap=ParseCommandOption(MagickLineCapOptions,MagickFalse,token);
 
 3807            graphic_context[n]->linecap=(LineCap) linecap;
 
 3810        if (LocaleCompare(
"stroke-linejoin",keyword) == 0)
 
 3815            (void) GetNextToken(q,&q,extent,token);
 
 3816            linejoin=ParseCommandOption(MagickLineJoinOptions,MagickFalse,
 
 3823            graphic_context[n]->linejoin=(LineJoin) linejoin;
 
 3826        if (LocaleCompare(
"stroke-miterlimit",keyword) == 0)
 
 3828            (void) GetNextToken(q,&q,extent,token);
 
 3829            graphic_context[n]->miterlimit=StringToUnsignedLong(token);
 
 3832        if (LocaleCompare(
"stroke-opacity",keyword) == 0)
 
 3837            (void) GetNextToken(q,&q,extent,token);
 
 3838            if (graphic_context[n]->clip_path != MagickFalse)
 
 3840            factor=strchr(token,
'%') != (
char *) NULL ? 0.01 : 1.0;
 
 3841            opacity=MagickMin(MagickMax(factor*GetDrawValue(token,&next_token),
 
 3843            if (token == next_token)
 
 3844              ThrowPointExpectedException(token,exception);
 
 3845            if (graphic_context[n]->compliance == SVGCompliance)
 
 3846              graphic_context[n]->stroke_alpha*=opacity;
 
 3848              graphic_context[n]->stroke_alpha=(double) QuantumRange*opacity;
 
 3849            if (graphic_context[n]->stroke.alpha != (
double) TransparentAlpha)
 
 3850              graphic_context[n]->stroke.alpha=graphic_context[n]->stroke_alpha;
 
 3852              graphic_context[n]->stroke.alpha=(MagickRealType)
 
 3853                ClampToQuantum((
double) QuantumRange*opacity);
 
 3854            graphic_context[n]->stroke.alpha_trait=BlendPixelTrait;
 
 3857        if (LocaleCompare(
"stroke-width",keyword) == 0)
 
 3859            (void) GetNextToken(q,&q,extent,token);
 
 3860            if (graphic_context[n]->clip_path != MagickFalse)
 
 3862            graphic_context[n]->stroke_width=GetDrawValue(token,&next_token);
 
 3863            if ((token == next_token) ||
 
 3864                (graphic_context[n]->stroke_width < 0.0))
 
 3865              ThrowPointExpectedException(token,exception);
 
 3874        if (LocaleCompare(
"text",keyword) == 0)
 
 3876            primitive_type=TextPrimitive;
 
 3880        if (LocaleCompare(
"text-align",keyword) == 0)
 
 3885            (void) GetNextToken(q,&q,extent,token);
 
 3886            align=ParseCommandOption(MagickAlignOptions,MagickFalse,token);
 
 3892            graphic_context[n]->align=(AlignType) align;
 
 3895        if (LocaleCompare(
"text-anchor",keyword) == 0)
 
 3900            (void) GetNextToken(q,&q,extent,token);
 
 3901            align=ParseCommandOption(MagickAlignOptions,MagickFalse,token);
 
 3907            graphic_context[n]->align=(AlignType) align;
 
 3910        if (LocaleCompare(
"text-antialias",keyword) == 0)
 
 3912            (void) GetNextToken(q,&q,extent,token);
 
 3913            graphic_context[n]->text_antialias=StringToLong(token) != 0 ?
 
 3914              MagickTrue : MagickFalse;
 
 3917        if (LocaleCompare(
"text-undercolor",keyword) == 0)
 
 3919            (void) GetNextToken(q,&q,extent,token);
 
 3920            status&=(MagickStatusType) QueryColorCompliance(token,AllCompliance,
 
 3921              &graphic_context[n]->undercolor,exception);
 
 3924        if (LocaleCompare(
"translate",keyword) == 0)
 
 3926            (void) GetNextToken(q,&q,extent,token);
 
 3927            affine.tx=GetDrawValue(token,&next_token);
 
 3928            if (token == next_token)
 
 3929              ThrowPointExpectedException(token,exception);
 
 3930            (void) GetNextToken(q,&q,extent,token);
 
 3932              (void) GetNextToken(q,&q,extent,token);
 
 3933            affine.ty=GetDrawValue(token,&next_token);
 
 3934            if (token == next_token)
 
 3935              ThrowPointExpectedException(token,exception);
 
 3945        if (LocaleCompare(
"use",keyword) == 0)
 
 3953            (void) GetNextToken(q,&q,extent,token);
 
 3954            use=(
const char *) GetValueFromSplayTree(macros,token);
 
 3955            if (use != (
const char *) NULL)
 
 3957                clone_info=CloneDrawInfo((ImageInfo *) NULL,graphic_context[n]);
 
 3958                (void) CloneString(&clone_info->primitive,use);
 
 3959                status=RenderMVGContent(image,clone_info,depth+1,exception);
 
 3960                clone_info=DestroyDrawInfo(clone_info);
 
 3970        if (LocaleCompare(
"viewbox",keyword) == 0)
 
 3972            (void) GetNextToken(q,&q,extent,token);
 
 3973            graphic_context[n]->viewbox.x=CastDoubleToSsizeT(ceil(
 
 3974              GetDrawValue(token,&next_token)-0.5));
 
 3975            if (token == next_token)
 
 3976              ThrowPointExpectedException(token,exception);
 
 3977            (void) GetNextToken(q,&q,extent,token);
 
 3979              (void) GetNextToken(q,&q,extent,token);
 
 3980            graphic_context[n]->viewbox.y=CastDoubleToSsizeT(
 
 3981              ceil(GetDrawValue(token,&next_token)-0.5));
 
 3982            if (token == next_token)
 
 3983              ThrowPointExpectedException(token,exception);
 
 3984            (void) GetNextToken(q,&q,extent,token);
 
 3986              (void) GetNextToken(q,&q,extent,token);
 
 3987            graphic_context[n]->viewbox.width=CastDoubleToSizeT(floor(
 
 3988              GetDrawValue(token,&next_token)+0.5));
 
 3989            if (token == next_token)
 
 3990              ThrowPointExpectedException(token,exception);
 
 3991            (void) GetNextToken(q,&q,extent,token);
 
 3993              (void) GetNextToken(q,&q,extent,token);
 
 3994            graphic_context[n]->viewbox.height=CastDoubleToSizeT(floor(
 
 3995              GetDrawValue(token,&next_token)+0.5));
 
 3996            if (token == next_token)
 
 3997              ThrowPointExpectedException(token,exception);
 
 4006        if (LocaleCompare(
"word-spacing",keyword) == 0)
 
 4008            (void) GetNextToken(q,&q,extent,token);
 
 4009            graphic_context[n]->interword_spacing=GetDrawValue(token,
 
 4011            if (token == next_token)
 
 4012              ThrowPointExpectedException(token,exception);
 
 4024    if (status == MagickFalse)
 
 4026    if ((fabs(affine.sx-1.0) >= MagickEpsilon) ||
 
 4027        (fabs(affine.rx) >= MagickEpsilon) || (fabs(affine.ry) >= MagickEpsilon) ||
 
 4028        (fabs(affine.sy-1.0) >= MagickEpsilon) ||
 
 4029        (fabs(affine.tx) >= MagickEpsilon) || (fabs(affine.ty) >= MagickEpsilon))
 
 4031        graphic_context[n]->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
 
 4032        graphic_context[n]->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
 
 4033        graphic_context[n]->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
 
 4034        graphic_context[n]->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
 
 4035        graphic_context[n]->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
 
 4037        graphic_context[n]->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
 
 4040    if (primitive_type == UndefinedPrimitive)
 
 4044            if (number_stops > 1)
 
 4049                type=LinearGradient;
 
 4050                if (draw_info->gradient.type == RadialGradient)
 
 4051                  type=RadialGradient;
 
 4052                (void) GradientImage(image,type,PadSpread,stops,number_stops,
 
 4055           if (number_stops > 0)
 
 4056             stops=(StopInfo *) RelinquishMagickMemory(stops);
 
 4058        if ((draw_info->debug != MagickFalse) && (q > p))
 
 4059          (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"  %.*s",(
int)
 
 4066    for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++)
 
 4067      if (primitive_info[i].text != (
char *) NULL)
 
 4068        primitive_info[i].text=DestroyString(primitive_info[i].text);
 
 4072    primitive_info[0].point.x=0.0;
 
 4073    primitive_info[0].point.y=0.0;
 
 4074    primitive_info[0].coordinates=0;
 
 4075    primitive_info[0].method=FloodfillMethod;
 
 4076    primitive_info[0].closed_subpath=MagickFalse;
 
 4077    for (x=0; *q != 
'\0'; x++)
 
 4082      if (IsPoint(q) == MagickFalse)
 
 4084      (void) GetNextToken(q,&q,extent,token);
 
 4085      point.x=GetDrawValue(token,&next_token);
 
 4086      if (token == next_token)
 
 4087        ThrowPointExpectedException(token,exception);
 
 4088      (void) GetNextToken(q,&q,extent,token);
 
 4090        (void) GetNextToken(q,&q,extent,token);
 
 4091      point.y=GetDrawValue(token,&next_token);
 
 4092      if (token == next_token)
 
 4093        ThrowPointExpectedException(token,exception);
 
 4094      (void) GetNextToken(q,(
const char **) NULL,extent,token);
 
 4096        (void) GetNextToken(q,&q,extent,token);
 
 4097      primitive_info[i].primitive=primitive_type;
 
 4098      primitive_info[i].point=point;
 
 4099      primitive_info[i].coordinates=0;
 
 4100      primitive_info[i].method=FloodfillMethod;
 
 4101      primitive_info[i].closed_subpath=MagickFalse;
 
 4104      if (i < (ssize_t) number_points)
 
 4106      status&=(MagickStatusType) CheckPrimitiveExtent(&mvg_info,(
double)
 
 4108      primitive_info=(*mvg_info.primitive_info);
 
 4110    if (status == MagickFalse)
 
 4112    if (primitive_info[j].text != (
char *) NULL)
 
 4113      primitive_info[j].text=DestroyString(primitive_info[j].text);
 
 4114    primitive_info[j].primitive=primitive_type;
 
 4115    primitive_info[j].coordinates=(size_t) x;
 
 4116    primitive_info[j].method=FloodfillMethod;
 
 4117    primitive_info[j].closed_subpath=MagickFalse;
 
 4121    bounds.x1=primitive_info[j].point.x;
 
 4122    bounds.y1=primitive_info[j].point.y;
 
 4123    bounds.x2=primitive_info[j].point.x;
 
 4124    bounds.y2=primitive_info[j].point.y;
 
 4125    for (k=1; k < (ssize_t) primitive_info[j].coordinates; k++)
 
 4127      point=primitive_info[j+k].point;
 
 4128      if (point.x < bounds.x1)
 
 4130      if (point.y < bounds.y1)
 
 4132      if (point.x > bounds.x2)
 
 4134      if (point.y > bounds.y2)
 
 4140    coordinates=(double) primitive_info[j].coordinates;
 
 4141    switch (primitive_type)
 
 4143      case RectanglePrimitive:
 
 4148      case RoundRectanglePrimitive:
 
 4155        alpha=bounds.x2-bounds.x1;
 
 4156        beta=bounds.y2-bounds.y1;
 
 4157        radius=hypot(alpha,beta);
 
 4159        coordinates+=2.0*((size_t) ceil((
double) MagickPI*radius))+6.0*
 
 4160          BezierQuantum+360.0;
 
 4163      case BezierPrimitive:
 
 4165        coordinates=(BezierQuantum*(double) primitive_info[j].coordinates);
 
 4174        (void) GetNextToken(q,&q,extent,token);
 
 4177        for (s=token; *s != 
'\0'; s=t)
 
 4182          value=GetDrawValue(s,&t);
 
 4191        for (s=token; *s != 
'\0'; s++)
 
 4192          if (strspn(s,
"AaCcQqSsTt") != 0)
 
 4193            coordinates+=(20.0*BezierQuantum)+360.0;
 
 4199    if (status == MagickFalse)
 
 4201    if (((
size_t) (i+coordinates)) >= number_points)
 
 4206        number_points+=(size_t) coordinates+1;
 
 4207        if (number_points < (
size_t) coordinates)
 
 4209            (void) ThrowMagickException(exception,GetMagickModule(),
 
 4210              ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
 
 4215        status&=(MagickStatusType) CheckPrimitiveExtent(&mvg_info,(
double)
 
 4217        primitive_info=(*mvg_info.primitive_info);
 
 4219    status&=(MagickStatusType) CheckPrimitiveExtent(&mvg_info,
 
 4220      PrimitiveExtentPad);
 
 4221    primitive_info=(*mvg_info.primitive_info);
 
 4222    if (status == MagickFalse)
 
 4225    switch (primitive_type)
 
 4227      case PointPrimitive:
 
 4230        if (primitive_info[j].coordinates != 1)
 
 4235        status&=(MagickStatusType) TracePoint(primitive_info+j,
 
 4236          primitive_info[j].point);
 
 4237        primitive_info=(*mvg_info.primitive_info);
 
 4238        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4243        if (primitive_info[j].coordinates != 2)
 
 4248        status&=(MagickStatusType) TraceLine(primitive_info+j,
 
 4249          primitive_info[j].point,primitive_info[j+1].point);
 
 4250        primitive_info=(*mvg_info.primitive_info);
 
 4251        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4254      case RectanglePrimitive:
 
 4256        if (primitive_info[j].coordinates != 2)
 
 4261        status&=(MagickStatusType) TraceRectangle(primitive_info+j,
 
 4262          primitive_info[j].point,primitive_info[j+1].point);
 
 4263        primitive_info=(*mvg_info.primitive_info);
 
 4264        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4267      case RoundRectanglePrimitive:
 
 4269        if (primitive_info[j].coordinates != 3)
 
 4274        if ((primitive_info[j+2].point.x < 0.0) ||
 
 4275            (primitive_info[j+2].point.y < 0.0))
 
 4280        if ((primitive_info[j+1].point.x-primitive_info[j].point.x) < 0.0)
 
 4285        if ((primitive_info[j+1].point.y-primitive_info[j].point.y) < 0.0)
 
 4290        status&=(MagickStatusType) TraceRoundRectangle(&mvg_info,
 
 4291          primitive_info[j].point,primitive_info[j+1].point,
 
 4292          primitive_info[j+2].point);
 
 4293        primitive_info=(*mvg_info.primitive_info);
 
 4294        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4299        if (primitive_info[j].coordinates != 3)
 
 4304        status&=(MagickStatusType) TraceArc(&mvg_info,primitive_info[j].point,
 
 4305          primitive_info[j+1].point,primitive_info[j+2].point);
 
 4306        primitive_info=(*mvg_info.primitive_info);
 
 4307        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4310      case EllipsePrimitive:
 
 4312        if (primitive_info[j].coordinates != 3)
 
 4317        if ((primitive_info[j+1].point.x < 0.0) ||
 
 4318            (primitive_info[j+1].point.y < 0.0))
 
 4323        status&=(MagickStatusType) TraceEllipse(&mvg_info,
 
 4324          primitive_info[j].point,primitive_info[j+1].point,
 
 4325          primitive_info[j+2].point);
 
 4326        primitive_info=(*mvg_info.primitive_info);
 
 4327        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4330      case CirclePrimitive:
 
 4332        if (primitive_info[j].coordinates != 2)
 
 4337        status&=(MagickStatusType) TraceCircle(&mvg_info,
 
 4338          primitive_info[j].point,primitive_info[j+1].point);
 
 4339        primitive_info=(*mvg_info.primitive_info);
 
 4340        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4343      case PolylinePrimitive:
 
 4345        if (primitive_info[j].coordinates < 1)
 
 4352      case PolygonPrimitive:
 
 4354        if (primitive_info[j].coordinates < 3)
 
 4359        primitive_info[i]=primitive_info[j];
 
 4360        primitive_info[i].coordinates=0;
 
 4361        primitive_info[j].coordinates++;
 
 4362        primitive_info[j].closed_subpath=MagickTrue;
 
 4366      case BezierPrimitive:
 
 4368        if (primitive_info[j].coordinates < 3)
 
 4373        status&=(MagickStatusType) TraceBezier(&mvg_info,
 
 4374          primitive_info[j].coordinates);
 
 4375        primitive_info=(*mvg_info.primitive_info);
 
 4376        i=j+(ssize_t) primitive_info[j].coordinates;
 
 4381        coordinates=(double) TracePath(&mvg_info,token,exception);
 
 4382        primitive_info=(*mvg_info.primitive_info); 
 
 4383        if (coordinates < 0.0)
 
 4388        i=(ssize_t) (j+coordinates);
 
 4391      case AlphaPrimitive:
 
 4392      case ColorPrimitive:
 
 4397        if (primitive_info[j].coordinates != 1)
 
 4402        (void) GetNextToken(q,&q,extent,token);
 
 4403        method=ParseCommandOption(MagickMethodOptions,MagickFalse,token);
 
 4409        primitive_info[j].method=(PaintMethod) method;
 
 4414        if (primitive_info[j].coordinates != 1)
 
 4420          (void) GetNextToken(q,&q,extent,token);
 
 4421        (void) CloneString(&primitive_info[j].text,token);
 
 4425        clone_info=CloneDrawInfo((ImageInfo *) NULL,graphic_context[n]);
 
 4426        if ((fabs(mvg_info.point.x-primitive_info->point.x) < MagickEpsilon) &&
 
 4427            (fabs(mvg_info.point.y-primitive_info->point.y) < MagickEpsilon))
 
 4429            mvg_info.point=primitive_info->point;
 
 4430            primitive_info->point.x+=cursor;
 
 4434            mvg_info.point=primitive_info->point;
 
 4437        clone_info->render=MagickFalse;
 
 4438        clone_info->text=AcquireString(token);
 
 4439        status&=(MagickStatusType) GetTypeMetrics(image,clone_info,
 
 4440          &metrics,exception);
 
 4441        clone_info=DestroyDrawInfo(clone_info);
 
 4442        cursor+=metrics.width;
 
 4443        if (graphic_context[n]->compliance != SVGCompliance)
 
 4447      case ImagePrimitive:
 
 4449        if (primitive_info[j].coordinates != 2)
 
 4454        (void) GetNextToken(q,&q,extent,token);
 
 4455        (void) CloneString(&primitive_info[j].text,token);
 
 4462    primitive_info[i].primitive=UndefinedPrimitive;
 
 4463    if ((draw_info->debug != MagickFalse) && (q > p))
 
 4464      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"  %.*s",(
int) (q-p),p);
 
 4468    status&=(MagickStatusType) CheckPrimitiveExtent(&mvg_info,ExpandAffine(
 
 4469      &graphic_context[n]->affine));
 
 4470    primitive_info=(*mvg_info.primitive_info);
 
 4473    status&=(MagickStatusType) CheckPrimitiveExtent(&mvg_info,(
double)
 
 4474      graphic_context[n]->stroke_width);
 
 4475    primitive_info=(*mvg_info.primitive_info);
 
 4483    for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++)
 
 4485      point=primitive_info[i].point;
 
 4486      primitive_info[i].point.x=graphic_context[n]->affine.sx*point.x+
 
 4487        graphic_context[n]->affine.ry*point.y+graphic_context[n]->affine.tx;
 
 4488      primitive_info[i].point.y=graphic_context[n]->affine.rx*point.x+
 
 4489        graphic_context[n]->affine.sy*point.y+graphic_context[n]->affine.ty;
 
 4490      point=primitive_info[i].point;
 
 4491      if (point.x < graphic_context[n]->bounds.x1)
 
 4492        graphic_context[n]->bounds.x1=point.x;
 
 4493      if (point.y < graphic_context[n]->bounds.y1)
 
 4494        graphic_context[n]->bounds.y1=point.y;
 
 4495      if (point.x > graphic_context[n]->bounds.x2)
 
 4496        graphic_context[n]->bounds.x2=point.x;
 
 4497      if (point.y > graphic_context[n]->bounds.y2)
 
 4498        graphic_context[n]->bounds.y2=point.y;
 
 4499      if (primitive_info[i].primitive == ImagePrimitive)
 
 4501      if (i >= (ssize_t) number_points)
 
 4502        ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
 
 4504    if (graphic_context[n]->render != MagickFalse)
 
 4506        if ((n != 0) && (graphic_context[n]->compliance != SVGCompliance) &&
 
 4507            (graphic_context[n]->clip_mask != (
char *) NULL) &&
 
 4508            (LocaleCompare(graphic_context[n]->clip_mask,
 
 4509             graphic_context[n-1]->clip_mask) != 0))
 
 4514            clip_path=(
const char *) GetValueFromSplayTree(macros,
 
 4515              graphic_context[n]->clip_mask);
 
 4516            if (clip_path != (
const char *) NULL)
 
 4517              (void) SetImageArtifact(image,graphic_context[n]->clip_mask,
 
 4519            status&=(MagickStatusType) DrawClipPath(image,graphic_context[n],
 
 4520              graphic_context[n]->clip_mask,exception);
 
 4522        status&=(MagickStatusType) DrawPrimitive(image,graphic_context[n],
 
 4523          primitive_info,exception);
 
 4525    proceed=SetImageProgress(image,RenderImageTag,q-primitive,(MagickSizeType)
 
 4527    if (proceed == MagickFalse)
 
 4532  if (draw_info->debug != MagickFalse)
 
 4533    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"end draw-image");
 
 4537  macros=DestroySplayTree(macros);
 
 4538  token=DestroyString(token);
 
 4539  if (primitive_info != (PrimitiveInfo *) NULL)
 
 4541      for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++)
 
 4542        if (primitive_info[i].text != (
char *) NULL)
 
 4543          primitive_info[i].text=DestroyString(primitive_info[i].text);
 
 4544      primitive_info=(PrimitiveInfo *) RelinquishMagickMemory(primitive_info);
 
 4546  primitive=DestroyString(primitive);
 
 4547  if (stops != (StopInfo *) NULL)
 
 4548    stops=(StopInfo *) RelinquishMagickMemory(stops);
 
 4549  for ( ; n >= 0; n--)
 
 4550    graphic_context[n]=DestroyDrawInfo(graphic_context[n]);
 
 4551  graphic_context=(DrawInfo **) RelinquishMagickMemory(graphic_context);
 
 4552  if ((status == MagickFalse) && (exception->severity < ErrorException))
 
 4553    ThrowBinaryException(DrawError,
"NonconformingDrawingPrimitiveDefinition",
 
 4555  return(status != 0 ? MagickTrue : MagickFalse);
 
 4558MagickExport MagickBooleanType DrawImage(Image *image,
const DrawInfo *draw_info,
 
 4559  ExceptionInfo *exception)
 
 4561  return(RenderMVGContent(image,draw_info,0,exception));
 
 4595MagickExport MagickBooleanType DrawPatternPath(Image *image,
 
 4596  const DrawInfo *draw_info,
const char *name,Image **pattern,
 
 4597  ExceptionInfo *exception)
 
 4600    property[MagickPathExtent];
 
 4616  assert(image != (Image *) NULL);
 
 4617  assert(image->signature == MagickCoreSignature);
 
 4618  assert(draw_info != (
const DrawInfo *) NULL);
 
 4619  assert(name != (
const char *) NULL);
 
 4620  if (IsEventLogging() != MagickFalse)
 
 4621    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 4622  (void) FormatLocaleString(property,MagickPathExtent,
"%s",name);
 
 4623  path=GetImageArtifact(image,property);
 
 4624  if (path == (
const char *) NULL)
 
 4625    return(MagickFalse);
 
 4626  (void) FormatLocaleString(property,MagickPathExtent,
"%s-geometry",name);
 
 4627  geometry=GetImageArtifact(image,property);
 
 4628  if (geometry == (
const char *) NULL)
 
 4629    return(MagickFalse);
 
 4630  if ((*pattern) != (Image *) NULL)
 
 4631    *pattern=DestroyImage(*pattern);
 
 4632  image_info=AcquireImageInfo();
 
 4633  image_info->size=AcquireString(geometry);
 
 4634  *pattern=AcquireImage(image_info,exception);
 
 4635  image_info=DestroyImageInfo(image_info);
 
 4636  (void) QueryColorCompliance(
"#00000000",AllCompliance,
 
 4637    &(*pattern)->background_color,exception);
 
 4638  (void) SetImageBackgroundColor(*pattern,exception);
 
 4639  if (draw_info->debug != MagickFalse)
 
 4640    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 4641      "begin pattern-path %s %s",name,geometry);
 
 4642  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 4643  if (clone_info->fill_pattern != (Image *) NULL)
 
 4644    clone_info->fill_pattern=DestroyImage(clone_info->fill_pattern);
 
 4645  if (clone_info->stroke_pattern != (Image *) NULL)
 
 4646    clone_info->stroke_pattern=DestroyImage(clone_info->stroke_pattern);
 
 4647  (void) FormatLocaleString(property,MagickPathExtent,
"%s-type",name);
 
 4648  type=GetImageArtifact(image,property);
 
 4649  if (type != (
const char *) NULL)
 
 4650    clone_info->gradient.type=(GradientType) ParseCommandOption(
 
 4651      MagickGradientOptions,MagickFalse,type);
 
 4652  (void) CloneString(&clone_info->primitive,path);
 
 4653  status=RenderMVGContent(*pattern,clone_info,0,exception);
 
 4654  clone_info=DestroyDrawInfo(clone_info);
 
 4655  if (draw_info->debug != MagickFalse)
 
 4656    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"end pattern-path");
 
 4691static PolygonInfo **DestroyPolygonTLS(PolygonInfo **polygon_info)
 
 4696  assert(polygon_info != (PolygonInfo **) NULL);
 
 4697  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
 
 4698    if (polygon_info[i] != (PolygonInfo *) NULL)
 
 4699      polygon_info[i]=DestroyPolygonInfo(polygon_info[i]);
 
 4700  polygon_info=(PolygonInfo **) RelinquishMagickMemory(polygon_info);
 
 4701  return(polygon_info);
 
 4704static PolygonInfo **AcquirePolygonTLS(
const PrimitiveInfo *primitive_info,
 
 4705  ExceptionInfo *exception)
 
 4708    *magick_restrict path_info;
 
 4716  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
 
 4717  polygon_info=(PolygonInfo **) AcquireQuantumMemory(number_threads,
 
 4718    sizeof(*polygon_info));
 
 4719  if (polygon_info == (PolygonInfo **) NULL)
 
 4721      (void) ThrowMagickException(exception,GetMagickModule(),
 
 4722        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 4723      return((PolygonInfo **) NULL);
 
 4725  (void) memset(polygon_info,0,number_threads*
sizeof(*polygon_info));
 
 4726  path_info=ConvertPrimitiveToPath(primitive_info,exception);
 
 4727  if (path_info == (PathInfo *) NULL)
 
 4728    return(DestroyPolygonTLS(polygon_info));
 
 4729  polygon_info[0]=ConvertPathToPolygon(path_info,exception);
 
 4730  if (polygon_info[0] == (PolygonInfo *) NULL)
 
 4732      (void) ThrowMagickException(exception,GetMagickModule(),
 
 4733        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 4734      return(DestroyPolygonTLS(polygon_info));
 
 4736  path_info=(PathInfo *) RelinquishMagickMemory(path_info);
 
 4737  return(polygon_info);
 
 4740static MagickBooleanType ClonePolygonEdgesTLS(PolygonInfo **polygon_info,
 
 4741  const size_t number_threads,ExceptionInfo *exception)
 
 4746  for (i=1; i < (ssize_t) number_threads; i++)
 
 4754    polygon_info[i]=(PolygonInfo *) AcquireMagickMemory(
 
 4755      sizeof(*polygon_info[i]));
 
 4756    if (polygon_info[i] == (PolygonInfo *) NULL)
 
 4758        (void) ThrowMagickException(exception,GetMagickModule(),
 
 4759          ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 4760        return(MagickFalse);
 
 4762    polygon_info[i]->number_edges=0;
 
 4763    edge_info=polygon_info[0]->edges;
 
 4764    polygon_info[i]->edges=(EdgeInfo *) AcquireQuantumMemory(
 
 4765      polygon_info[0]->number_edges,
sizeof(*edge_info));
 
 4766    if (polygon_info[i]->edges == (EdgeInfo *) NULL)
 
 4768        (void) ThrowMagickException(exception,GetMagickModule(),
 
 4769          ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 4770        return(MagickFalse);
 
 4772    (void) memcpy(polygon_info[i]->edges,edge_info,
 
 4773      polygon_info[0]->number_edges*
sizeof(*edge_info));
 
 4774    for (j=0; j < (ssize_t) polygon_info[i]->number_edges; j++)
 
 4775      polygon_info[i]->edges[j].points=(PointInfo *) NULL;
 
 4776    polygon_info[i]->number_edges=polygon_info[0]->number_edges;
 
 4777    for (j=0; j < (ssize_t) polygon_info[i]->number_edges; j++)
 
 4779      edge_info=polygon_info[0]->edges+j;
 
 4780      polygon_info[i]->edges[j].points=(PointInfo *) AcquireQuantumMemory(
 
 4781        edge_info->number_points,
sizeof(*edge_info));
 
 4782      if (polygon_info[i]->edges[j].points == (PointInfo *) NULL)
 
 4784          (void) ThrowMagickException(exception,GetMagickModule(),
 
 4785            ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 4786          return(MagickFalse);
 
 4788      (void) memcpy(polygon_info[i]->edges[j].points,edge_info->points,
 
 4789        edge_info->number_points*
sizeof(*edge_info->points));
 
 4795static size_t DestroyEdge(PolygonInfo *polygon_info,
const ssize_t edge)
 
 4797  assert(edge < (ssize_t) polygon_info->number_edges);
 
 4798  polygon_info->edges[edge].points=(PointInfo *) RelinquishMagickMemory(
 
 4799    polygon_info->edges[edge].points);
 
 4800  polygon_info->number_edges--;
 
 4801  if (edge < (ssize_t) polygon_info->number_edges)
 
 4802    (void) memmove(polygon_info->edges+edge,polygon_info->edges+edge+1,
 
 4803      (polygon_info->number_edges-(
size_t) edge)*
sizeof(*polygon_info->edges));
 
 4804  return(polygon_info->number_edges);
 
 4807static double GetFillAlpha(PolygonInfo *polygon_info,
const double mid,
 
 4808  const MagickBooleanType fill,
const FillRule fill_rule,
const ssize_t x,
 
 4809  const ssize_t y,
double *stroke_alpha)
 
 4836  p=polygon_info->edges;
 
 4837  for (j=0; j < (ssize_t) polygon_info->number_edges; j++, p++)
 
 4839    if ((
double) y <= (p->bounds.y1-mid-0.5))
 
 4841    if ((
double) y > (p->bounds.y2+mid+0.5))
 
 4844        (void) DestroyEdge(polygon_info,j--);
 
 4847    if (((
double) x <= (p->bounds.x1-mid-0.5)) ||
 
 4848        ((
double) x > (p->bounds.x2+mid+0.5)))
 
 4850    i=(ssize_t) MagickMax((
double) p->highwater,1.0);
 
 4851    for ( ; i < (ssize_t) p->number_points; i++)
 
 4853      if ((
double) y <= (p->points[i-1].y-mid-0.5))
 
 4855      if ((
double) y > (p->points[i].y+mid+0.5))
 
 4857      if (p->scanline != (
double) y)
 
 4859          p->scanline=(double) y;
 
 4860          p->highwater=(size_t) i;
 
 4866      delta.x=(q+1)->x-q->x;
 
 4867      delta.y=(q+1)->y-q->y;
 
 4868      beta=delta.x*(x-q->x)+delta.y*(y-q->y);  
 
 4874          delta.x=(double) x-q->x;
 
 4875          delta.y=(double) y-q->y;
 
 4876          distance=delta.x*delta.x+delta.y*delta.y;
 
 4880          alpha=delta.x*delta.x+delta.y*delta.y;  
 
 4886              delta.x=(double) x-(q+1)->x;
 
 4887              delta.y=(double) y-(q+1)->y;
 
 4888              distance=delta.x*delta.x+delta.y*delta.y;
 
 4895              alpha=MagickSafeReciprocal(alpha);
 
 4896              beta=delta.x*(y-q->y)-delta.y*(x-q->x);
 
 4897              distance=alpha*beta*beta;
 
 4904      if (p->ghostline == MagickFalse)
 
 4907          if ((*stroke_alpha < 1.0) &&
 
 4908              (distance <= ((alpha+0.25)*(alpha+0.25))))
 
 4911              if (distance <= ((alpha+0.25)*(alpha+0.25)))
 
 4916                  if (fabs(distance-1.0) >= MagickEpsilon)
 
 4917                    beta=sqrt((
double) distance);
 
 4919                  if (*stroke_alpha < ((alpha-0.25)*(alpha-0.25)))
 
 4920                    *stroke_alpha=(alpha-0.25)*(alpha-0.25);
 
 4924      if ((fill == MagickFalse) || (distance > 1.0) || (subpath_alpha >= 1.0))
 
 4926      if (distance <= 0.0)
 
 4933      if (fabs(beta) < MagickEpsilon)
 
 4936          if (fabs(distance-1.0) >= MagickEpsilon)
 
 4937            beta=sqrt(distance);
 
 4940      if (subpath_alpha < (alpha*alpha))
 
 4941        subpath_alpha=alpha*alpha;
 
 4947  if (fill == MagickFalse)
 
 4949  if (subpath_alpha >= 1.0)
 
 4955  p=polygon_info->edges;
 
 4956  for (j=0; j < (ssize_t) polygon_info->number_edges; j++, p++)
 
 4958    if ((
double) y <= p->bounds.y1)
 
 4960    if (((
double) y > p->bounds.y2) || ((
double) x <= p->bounds.x1))
 
 4962    if ((
double) x > p->bounds.x2)
 
 4964        winding_number+=p->direction != 0 ? 1 : -1;
 
 4967    i=(ssize_t) MagickMax((
double) p->highwater,1.0);
 
 4968    for ( ; i < (ssize_t) (p->number_points-1); i++)
 
 4969      if ((
double) y <= p->points[i].y)
 
 4972    if ((((q+1)->x-q->x)*(y-q->y)) <= (((q+1)->y-q->y)*(x-q->x)))
 
 4973      winding_number+=p->direction != 0 ? 1 : -1;
 
 4975  if (fill_rule != NonZeroRule)
 
 4977      if ((MagickAbsoluteValue(winding_number) & 0x01) != 0)
 
 4981    if (MagickAbsoluteValue(winding_number) != 0)
 
 4983  return(subpath_alpha);
 
 4986static MagickBooleanType DrawPolygonPrimitive(Image *image,
 
 4987  const DrawInfo *draw_info,
const PrimitiveInfo *primitive_info,
 
 4988  ExceptionInfo *exception)
 
 4990  typedef struct _ExtentInfo
 
 5019    **magick_restrict polygon_info;
 
 5031  assert(image != (Image *) NULL);
 
 5032  assert(image->signature == MagickCoreSignature);
 
 5033  assert(draw_info != (DrawInfo *) NULL);
 
 5034  assert(draw_info->signature == MagickCoreSignature);
 
 5035  assert(primitive_info != (PrimitiveInfo *) NULL);
 
 5036  if (IsEventLogging() != MagickFalse)
 
 5037    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
 
 5038  if (primitive_info->coordinates <= 1)
 
 5043  polygon_info=AcquirePolygonTLS(primitive_info,exception);
 
 5044  if (polygon_info == (PolygonInfo **) NULL)
 
 5045    return(MagickFalse);
 
 5046  if (draw_info->debug != MagickFalse)
 
 5047    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    begin draw-polygon");
 
 5048  fill=(primitive_info->method == FillToBorderMethod) ||
 
 5049    (primitive_info->method == FloodfillMethod) ? MagickTrue : MagickFalse;
 
 5050  mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0;
 
 5051  bounds=polygon_info[0]->edges[0].bounds;
 
 5052  artifact=GetImageArtifact(image,
"draw:render-bounding-rectangles");
 
 5053  if (IsStringTrue(artifact) != MagickFalse)
 
 5054    (void) DrawBoundingRectangles(image,draw_info,polygon_info[0],exception);
 
 5055  for (i=1; i < (ssize_t) polygon_info[0]->number_edges; i++)
 
 5057    p=polygon_info[0]->edges+i;
 
 5058    if (p->bounds.x1 < bounds.x1)
 
 5059      bounds.x1=p->bounds.x1;
 
 5060    if (p->bounds.y1 < bounds.y1)
 
 5061      bounds.y1=p->bounds.y1;
 
 5062    if (p->bounds.x2 > bounds.x2)
 
 5063      bounds.x2=p->bounds.x2;
 
 5064    if (p->bounds.y2 > bounds.y2)
 
 5065      bounds.y2=p->bounds.y2;
 
 5067  bounds.x1-=(mid+1.0);
 
 5068  bounds.y1-=(mid+1.0);
 
 5069  bounds.x2+=(mid+1.0);
 
 5070  bounds.y2+=(mid+1.0);
 
 5071  if ((bounds.x1 >= (
double) image->columns) ||
 
 5072      (bounds.y1 >= (
double) image->rows) ||
 
 5073      (bounds.x2 <= 0.0) || (bounds.y2 <= 0.0))
 
 5075      polygon_info=DestroyPolygonTLS(polygon_info);
 
 5078  bounds.x1=bounds.x1 < 0.0 ? 0.0 : bounds.x1 >= (double) image->columns-1.0 ?
 
 5079    (
double) image->columns-1.0 : bounds.x1;
 
 5080  bounds.y1=bounds.y1 < 0.0 ? 0.0 : bounds.y1 >= (double) image->rows-1.0 ?
 
 5081    (
double) image->rows-1.0 : bounds.y1;
 
 5082  bounds.x2=bounds.x2 < 0.0 ? 0.0 : bounds.x2 >= (double) image->columns-1.0 ?
 
 5083    (
double) image->columns-1.0 : bounds.x2;
 
 5084  bounds.y2=bounds.y2 < 0.0 ? 0.0 : bounds.y2 >= (double) image->rows-1.0 ?
 
 5085    (
double) image->rows-1.0 : bounds.y2;
 
 5086  poly_extent.x1=CastDoubleToSsizeT(ceil(bounds.x1-0.5));
 
 5087  poly_extent.y1=CastDoubleToSsizeT(ceil(bounds.y1-0.5));
 
 5088  poly_extent.x2=CastDoubleToSsizeT(floor(bounds.x2+0.5));
 
 5089  poly_extent.y2=CastDoubleToSsizeT(floor(bounds.y2+0.5));
 
 5090  number_threads=(size_t) GetMagickNumberThreads(image,image,(
size_t)
 
 5091    (poly_extent.y2-poly_extent.y1+1),1);
 
 5092  status=ClonePolygonEdgesTLS(polygon_info,number_threads,exception);
 
 5093  if (status == MagickFalse)
 
 5095      polygon_info=DestroyPolygonTLS(polygon_info);
 
 5098  image_view=AcquireAuthenticCacheView(image,exception);
 
 5099  if ((primitive_info->coordinates == 1) ||
 
 5100      (polygon_info[0]->number_edges == 0))
 
 5105#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 5106      #pragma omp parallel for schedule(static) shared(status) \ 
 5107        num_threads((int) number_threads) 
 5109      for (y=poly_extent.y1; y <= poly_extent.y2; y++)
 
 5120        if (status == MagickFalse)
 
 5123        q=GetCacheViewAuthenticPixels(image_view,x,y,(
size_t) (poly_extent.x2-
 
 5125        if (q == (Quantum *) NULL)
 
 5130        GetPixelInfo(image,&pixel);
 
 5131        for ( ; x <= poly_extent.x2; x++)
 
 5133          if ((x == CastDoubleToSsizeT(ceil(primitive_info->point.x-0.5))) &&
 
 5134              (y == CastDoubleToSsizeT(ceil(primitive_info->point.y-0.5))))
 
 5136              GetFillColor(draw_info,x-poly_extent.x1,y-poly_extent.y1,&pixel,
 
 5138              SetPixelViaPixelInfo(image,&pixel,q);
 
 5140          q+=(ptrdiff_t) GetPixelChannels(image);
 
 5142        if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
 
 5145      image_view=DestroyCacheView(image_view);
 
 5146      polygon_info=DestroyPolygonTLS(polygon_info);
 
 5147      if (draw_info->debug != MagickFalse)
 
 5148        (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5149          "    end draw-polygon");
 
 5155#if defined(MAGICKCORE_OPENMP_SUPPORT) 
 5156  #pragma omp parallel for schedule(static) shared(status) \ 
 5157    num_threads((int) number_threads) 
 5159  for (y=poly_extent.y1; y <= poly_extent.y2; y++)
 
 5162      id = GetOpenMPThreadId();
 
 5170    if (status == MagickFalse)
 
 5172    q=GetCacheViewAuthenticPixels(image_view,poly_extent.x1,y,(
size_t)
 
 5173      (poly_extent.x2-poly_extent.x1+1),1,exception);
 
 5174    if (q == (Quantum *) NULL)
 
 5179    for (x=poly_extent.x1; x <= poly_extent.x2; x++)
 
 5192      fill_alpha=GetFillAlpha(polygon_info[
id],mid,fill,draw_info->fill_rule,
 
 5194      if (draw_info->stroke_antialias == MagickFalse)
 
 5196          fill_alpha=fill_alpha >= AntialiasThreshold ? 1.0 : 0.0;
 
 5197          stroke_alpha=stroke_alpha >= AntialiasThreshold ? 1.0 : 0.0;
 
 5199      GetFillColor(draw_info,x-poly_extent.x1,y-poly_extent.y1,&fill_color,
 
 5201      CompositePixelOver(image,&fill_color,fill_alpha*fill_color.alpha,q,
 
 5202        (
double) GetPixelAlpha(image,q),q);
 
 5203      GetStrokeColor(draw_info,x-poly_extent.x1,y-poly_extent.y1,&stroke_color,
 
 5205      CompositePixelOver(image,&stroke_color,stroke_alpha*stroke_color.alpha,q,
 
 5206        (
double) GetPixelAlpha(image,q),q);
 
 5207      q+=(ptrdiff_t) GetPixelChannels(image);
 
 5209    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
 
 5212  image_view=DestroyCacheView(image_view);
 
 5213  polygon_info=DestroyPolygonTLS(polygon_info);
 
 5214  if (draw_info->debug != MagickFalse)
 
 5215    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    end draw-polygon");
 
 5248static void LogPrimitiveInfo(
const PrimitiveInfo *primitive_info)
 
 5274  x=CastDoubleToSsizeT(ceil(primitive_info->point.x-0.5));
 
 5275  y=CastDoubleToSsizeT(ceil(primitive_info->point.y-0.5));
 
 5276  switch (primitive_info->primitive)
 
 5278    case AlphaPrimitive:
 
 5280      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5281        "AlphaPrimitive %.20g,%.20g %s",(
double) x,(
double) y,
 
 5282        methods[primitive_info->method]);
 
 5285    case ColorPrimitive:
 
 5287      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5288        "ColorPrimitive %.20g,%.20g %s",(
double) x,(
double) y,
 
 5289        methods[primitive_info->method]);
 
 5292    case ImagePrimitive:
 
 5294      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5295        "ImagePrimitive %.20g,%.20g",(
double) x,(
double) y);
 
 5298    case PointPrimitive:
 
 5300      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5301        "PointPrimitive %.20g,%.20g %s",(
double) x,(
double) y,
 
 5302        methods[primitive_info->method]);
 
 5307      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5308        "TextPrimitive %.20g,%.20g",(
double) x,(
double) y);
 
 5315  p=primitive_info[0].point;
 
 5318  for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++)
 
 5320    point=primitive_info[i].point;
 
 5321    if (coordinates <= 0)
 
 5323        coordinates=(ssize_t) primitive_info[i].coordinates;
 
 5324        (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5325          "    begin open (%.20g)",(
double) coordinates);
 
 5328    point=primitive_info[i].point;
 
 5329    if ((fabs(q.x-point.x) >= MagickEpsilon) ||
 
 5330        (fabs(q.y-point.y) >= MagickEpsilon))
 
 5331      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5332        "      %.20g: %.18g,%.18g",(
double) coordinates,point.x,point.y);
 
 5334      (
void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5335        "      %.20g: %g %g (duplicate)",(
double) coordinates,point.x,point.y);
 
 5338    if (coordinates > 0)
 
 5340    if ((fabs(p.x-point.x) >= MagickEpsilon) ||
 
 5341        (fabs(p.y-point.y) >= MagickEpsilon))
 
 5342      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    end last (%.20g)",
 
 5343        (
double) coordinates);
 
 5345      (
void) LogMagickEvent(DrawEvent,GetMagickModule(),
"    end open (%.20g)",
 
 5346        (
double) coordinates);
 
 5350MagickExport MagickBooleanType DrawPrimitive(Image *image,
 
 5351  const DrawInfo *draw_info,
const PrimitiveInfo *primitive_info,
 
 5352  ExceptionInfo *exception)
 
 5367  if (draw_info->debug != MagickFalse)
 
 5369      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5370        "  begin draw-primitive");
 
 5371      (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5372        "    affine: %g,%g,%g,%g,%g,%g",draw_info->affine.sx,
 
 5373        draw_info->affine.rx,draw_info->affine.ry,draw_info->affine.sy,
 
 5374        draw_info->affine.tx,draw_info->affine.ty);
 
 5377  if ((IsGrayColorspace(image->colorspace) != MagickFalse) &&
 
 5378      ((IsPixelInfoGray(&draw_info->fill) == MagickFalse) ||
 
 5379       (IsPixelInfoGray(&draw_info->stroke) == MagickFalse)))
 
 5380    status&=(MagickStatusType) SetImageColorspace(image,sRGBColorspace,
 
 5382  if (draw_info->compliance == SVGCompliance)
 
 5384      status&=(MagickStatusType) SetImageMask(image,WritePixelMask,
 
 5385        draw_info->clipping_mask,exception);
 
 5386      status&=(MagickStatusType) SetImageMask(image,CompositePixelMask,
 
 5387        draw_info->composite_mask,exception);
 
 5389  x=CastDoubleToSsizeT(ceil(primitive_info->point.x-0.5));
 
 5390  y=CastDoubleToSsizeT(ceil(primitive_info->point.y-0.5));
 
 5391  image_view=AcquireAuthenticCacheView(image,exception);
 
 5392  switch (primitive_info->primitive)
 
 5394    case AlphaPrimitive:
 
 5396      if ((image->alpha_trait & BlendPixelTrait) == 0)
 
 5397        status&=(MagickStatusType) SetImageAlphaChannel(image,
 
 5398          OpaqueAlphaChannel,exception);
 
 5399      switch (primitive_info->method)
 
 5410          q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
 
 5411          if (q == (Quantum *) NULL)
 
 5413          GetFillColor(draw_info,x,y,&pixel,exception);
 
 5414          SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
 
 5415          status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5425          status&=(MagickStatusType) GetOneCacheViewVirtualPixelInfo(image_view,
 
 5426            x,y,&target,exception);
 
 5427          GetPixelInfo(image,&pixel);
 
 5428          for (y=0; y < (ssize_t) image->rows; y++)
 
 5433            q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
 
 5435            if (q == (Quantum *) NULL)
 
 5437            for (x=0; x < (ssize_t) image->columns; x++)
 
 5439              GetPixelInfoPixel(image,q,&pixel);
 
 5440              if (IsFuzzyEquivalencePixelInfo(&pixel,&target) == MagickFalse)
 
 5442                  q+=(ptrdiff_t) GetPixelChannels(image);
 
 5445              GetFillColor(draw_info,x,y,&pixel,exception);
 
 5446              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
 
 5447              q+=(ptrdiff_t) GetPixelChannels(image);
 
 5449            status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5451            if (status == MagickFalse)
 
 5456        case FloodfillMethod:
 
 5457        case FillToBorderMethod:
 
 5465          status&=(MagickStatusType) GetOneVirtualPixelInfo(image,
 
 5466            TileVirtualPixelMethod,x,y,&target,exception);
 
 5467          if (primitive_info->method == FillToBorderMethod)
 
 5469              target.red=(double) draw_info->border_color.red;
 
 5470              target.green=(double) draw_info->border_color.green;
 
 5471              target.blue=(double) draw_info->border_color.blue;
 
 5473          channel_mask=SetImageChannelMask(image,AlphaChannel);
 
 5474          status&=(MagickStatusType) FloodfillPaintImage(image,draw_info,
 
 5475            &target,x,y,primitive_info->method == FloodfillMethod ?
 
 5476            MagickFalse : MagickTrue,exception);
 
 5477          (void) SetImageChannelMask(image,channel_mask);
 
 5485          for (y=0; y < (ssize_t) image->rows; y++)
 
 5490            q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
 
 5492            if (q == (Quantum *) NULL)
 
 5494            for (x=0; x < (ssize_t) image->columns; x++)
 
 5496              GetFillColor(draw_info,x,y,&pixel,exception);
 
 5497              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
 
 5498              q+=(ptrdiff_t) GetPixelChannels(image);
 
 5500            status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5502            if (status == MagickFalse)
 
 5510    case ColorPrimitive:
 
 5512      switch (primitive_info->method)
 
 5523          q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
 
 5524          if (q == (Quantum *) NULL)
 
 5526          GetPixelInfo(image,&pixel);
 
 5527          GetFillColor(draw_info,x,y,&pixel,exception);
 
 5528          SetPixelViaPixelInfo(image,&pixel,q);
 
 5529          status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5539          status&=(MagickStatusType) GetOneCacheViewVirtualPixelInfo(image_view,
 
 5540            x,y,&target,exception);
 
 5541          for (y=0; y < (ssize_t) image->rows; y++)
 
 5546            q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
 
 5548            if (q == (Quantum *) NULL)
 
 5550            for (x=0; x < (ssize_t) image->columns; x++)
 
 5552              GetPixelInfoPixel(image,q,&pixel);
 
 5553              if (IsFuzzyEquivalencePixelInfo(&pixel,&target) == MagickFalse)
 
 5555                  q+=(ptrdiff_t) GetPixelChannels(image);
 
 5558              GetFillColor(draw_info,x,y,&pixel,exception);
 
 5559              SetPixelViaPixelInfo(image,&pixel,q);
 
 5560              q+=(ptrdiff_t) GetPixelChannels(image);
 
 5562            status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5564            if (status == MagickFalse)
 
 5569        case FloodfillMethod:
 
 5570        case FillToBorderMethod:
 
 5575          status&=(MagickStatusType) GetOneVirtualPixelInfo(image,
 
 5576            TileVirtualPixelMethod,x,y,&target,exception);
 
 5577          if (primitive_info->method == FillToBorderMethod)
 
 5579              target.red=(double) draw_info->border_color.red;
 
 5580              target.green=(double) draw_info->border_color.green;
 
 5581              target.blue=(double) draw_info->border_color.blue;
 
 5583          status&=(MagickStatusType) FloodfillPaintImage(image,draw_info,
 
 5584            &target,x,y,primitive_info->method == FloodfillMethod ?
 
 5585            MagickFalse : MagickTrue,exception);
 
 5593          GetPixelInfo(image,&pixel);
 
 5594          for (y=0; y < (ssize_t) image->rows; y++)
 
 5599            q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
 
 5601            if (q == (Quantum *) NULL)
 
 5603            for (x=0; x < (ssize_t) image->columns; x++)
 
 5605              GetFillColor(draw_info,x,y,&pixel,exception);
 
 5606              SetPixelViaPixelInfo(image,&pixel,q);
 
 5607              q+=(ptrdiff_t) GetPixelChannels(image);
 
 5609            status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5611            if (status == MagickFalse)
 
 5619    case ImagePrimitive:
 
 5625        composite_geometry[MagickPathExtent];
 
 5641      if (primitive_info->text == (
char *) NULL)
 
 5643      clone_info=AcquireImageInfo();
 
 5644      composite_images=(Image *) NULL;
 
 5645      if (LocaleNCompare(primitive_info->text,
"data:",5) == 0)
 
 5646        composite_images=ReadInlineImage(clone_info,primitive_info->text,
 
 5649        if (*primitive_info->text != 
'\0')
 
 5663            (void) CopyMagickString(clone_info->filename,primitive_info->text,
 
 5665            (void) SetImageInfo(clone_info,1,exception);
 
 5666            option=GetImageOption(clone_info,
"svg:embedding");
 
 5667            if ((option == (
char *) NULL) &&
 
 5668                (IsStringTrue(option) == MagickFalse))
 
 5673                magick_info=GetMagickInfo(clone_info->magick,exception);
 
 5674                if ((magick_info != (
const MagickInfo*) NULL) &&
 
 5675                    (LocaleCompare(magick_info->magick_module,
"SVG") == 0))
 
 5677                    (void) ThrowMagickException(exception,GetMagickModule(),
 
 5678                      CorruptImageError,
"ImageTypeNotSupported",
"`%s'",
 
 5679                      clone_info->filename);
 
 5680                    clone_info=DestroyImageInfo(clone_info);
 
 5684            (void) CopyMagickString(clone_info->filename,primitive_info->text,
 
 5686            if (clone_info->size != (
char *) NULL)
 
 5687              clone_info->size=DestroyString(clone_info->size);
 
 5688            if (clone_info->extract != (
char *) NULL)
 
 5689              clone_info->extract=DestroyString(clone_info->extract);
 
 5690            path_status=GetPathAttributes(clone_info->filename,&attributes);
 
 5691            if (path_status != MagickFalse)
 
 5693                if (S_ISCHR(attributes.st_mode) == 0)
 
 5694                  composite_images=ReadImage(clone_info,exception);
 
 5696                  (
void) ThrowMagickException(exception,GetMagickModule(),
 
 5697                    FileOpenError,
"UnableToOpenFile",
"`%s'",
 
 5698                      clone_info->filename);
 
 5701              if ((LocaleCompare(clone_info->magick,
"ftp") != 0) &&
 
 5702                  (LocaleCompare(clone_info->magick,
"http") != 0) &&
 
 5703                  (LocaleCompare(clone_info->magick,
"https") != 0) &&
 
 5704                  (LocaleCompare(clone_info->magick,
"vid") != 0))
 
 5705                composite_images=ReadImage(clone_info,exception);
 
 5707                (
void) ThrowMagickException(exception,GetMagickModule(),
 
 5708                  FileOpenError,
"UnableToOpenFile",
"`%s'",clone_info->filename);
 
 5710      clone_info=DestroyImageInfo(clone_info);
 
 5711      if (composite_images == (Image *) NULL)
 
 5716      composite_image=RemoveFirstImageFromList(&composite_images);
 
 5717      composite_images=DestroyImageList(composite_images);
 
 5718      (void) SetImageProgressMonitor(composite_image,(MagickProgressMonitor)
 
 5719        NULL,(
void *) NULL);
 
 5720      x1=CastDoubleToSsizeT(ceil(primitive_info[1].point.x-0.5));
 
 5721      y1=CastDoubleToSsizeT(ceil(primitive_info[1].point.y-0.5));
 
 5722      if (((x1 != 0L) && (x1 != (ssize_t) composite_image->columns)) ||
 
 5723          ((y1 != 0L) && (y1 != (ssize_t) composite_image->rows)))
 
 5728          (void) FormatLocaleString(composite_geometry,MagickPathExtent,
 
 5729            "%gx%g!",primitive_info[1].point.x,primitive_info[1].point.y);
 
 5730          composite_image->filter=image->filter;
 
 5731          status&=(MagickStatusType) TransformImage(&composite_image,
 
 5732            (
char *) NULL,composite_geometry,exception);
 
 5734      if (composite_image->alpha_trait == UndefinedPixelTrait)
 
 5735        status&=(MagickStatusType) SetImageAlphaChannel(composite_image,
 
 5736          OpaqueAlphaChannel,exception);
 
 5737      if (draw_info->alpha != OpaqueAlpha)
 
 5738        status&=(MagickStatusType) SetImageAlpha(composite_image,
 
 5739          draw_info->alpha,exception);
 
 5740      SetGeometry(image,&geometry);
 
 5741      image->gravity=draw_info->gravity;
 
 5744      (void) FormatLocaleString(composite_geometry,MagickPathExtent,
 
 5745        "%.20gx%.20g%+.20g%+.20g",(
double) composite_image->columns,(
double)
 
 5746        composite_image->rows,(
double) geometry.x,(
double) geometry.y);
 
 5747      (void) ParseGravityGeometry(image,composite_geometry,&geometry,exception);
 
 5748      affine=draw_info->affine;
 
 5749      affine.tx=(double) geometry.x;
 
 5750      affine.ty=(double) geometry.y;
 
 5751      composite_image->interpolate=image->interpolate;
 
 5752      if ((draw_info->compose == OverCompositeOp) ||
 
 5753          (draw_info->compose == SrcOverCompositeOp))
 
 5754        status&=(MagickStatusType) DrawAffineImage(image,composite_image,
 
 5757        status&=(MagickStatusType) CompositeImage(image,composite_image,
 
 5758          draw_info->compose,MagickTrue,geometry.x,geometry.y,exception);
 
 5759      composite_image=DestroyImage(composite_image);
 
 5762    case PointPrimitive:
 
 5770      if ((y < 0) || (y >= (ssize_t) image->rows))
 
 5772      if ((x < 0) || (x >= (ssize_t) image->columns))
 
 5774      q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
 
 5775      if (q == (Quantum *) NULL)
 
 5777      GetFillColor(draw_info,x,y,&fill_color,exception);
 
 5778      CompositePixelOver(image,&fill_color,(
double) fill_color.alpha,q,(
double)
 
 5779        GetPixelAlpha(image,q),q);
 
 5780      status&=(MagickStatusType) SyncCacheViewAuthenticPixels(image_view,
 
 5787        geometry[MagickPathExtent];
 
 5792      if (primitive_info->text == (
char *) NULL)
 
 5794      clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 5795      (void) CloneString(&clone_info->text,primitive_info->text);
 
 5796      (void) FormatLocaleString(geometry,MagickPathExtent,
"%+f%+f",
 
 5797        primitive_info->point.x,primitive_info->point.y);
 
 5798      (void) CloneString(&clone_info->geometry,geometry);
 
 5799      status&=(MagickStatusType) AnnotateImage(image,clone_info,exception);
 
 5800      clone_info=DestroyDrawInfo(clone_info);
 
 5812      if (IsEventLogging() != MagickFalse)
 
 5813        LogPrimitiveInfo(primitive_info);
 
 5814      scale=ExpandAffine(&draw_info->affine);
 
 5815      if ((draw_info->dash_pattern != (
double *) NULL) &&
 
 5816          (fabs(draw_info->dash_pattern[0]) >= MagickEpsilon) &&
 
 5817          (fabs(scale*draw_info->stroke_width) >= MagickEpsilon) &&
 
 5818          (draw_info->stroke.alpha != (
double) TransparentAlpha))
 
 5823          clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 5824          clone_info->stroke_width=0.0;
 
 5825          clone_info->stroke.alpha=(MagickRealType) TransparentAlpha;
 
 5826          status&=(MagickStatusType) DrawPolygonPrimitive(image,clone_info,
 
 5827            primitive_info,exception);
 
 5828          clone_info=DestroyDrawInfo(clone_info);
 
 5829          if (status != MagickFalse)
 
 5830            status&=(MagickStatusType) DrawDashPolygon(draw_info,primitive_info,
 
 5834      mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0;
 
 5836          ((draw_info->stroke.alpha != (
double) TransparentAlpha) ||
 
 5837           (draw_info->stroke_pattern != (Image *) NULL)))
 
 5849          closed_path=primitive_info[0].closed_subpath;
 
 5850          i=(ssize_t) primitive_info[0].coordinates;
 
 5851          point_x=fabs(primitive_info[i-1].point.x-primitive_info[0].point.x);
 
 5852          point_y=fabs(primitive_info[i-1].point.y-primitive_info[0].point.y);
 
 5853          if ((point_x < MagickEpsilon) && (point_y < MagickEpsilon))
 
 5854            closed_path=MagickTrue;
 
 5855          if ((((draw_info->linecap == RoundCap) ||
 
 5856                (closed_path != MagickFalse)) &&
 
 5857               (draw_info->linejoin == RoundJoin)) ||
 
 5858               (primitive_info[i].primitive != UndefinedPrimitive))
 
 5860              status&=(MagickStatusType) DrawPolygonPrimitive(image,draw_info,
 
 5861                primitive_info,exception);
 
 5864          clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 5865          clone_info->stroke_width=0.0;
 
 5866          clone_info->stroke.alpha=(MagickRealType) TransparentAlpha;
 
 5867          status&=(MagickStatusType) DrawPolygonPrimitive(image,clone_info,
 
 5868            primitive_info,exception);
 
 5869          clone_info=DestroyDrawInfo(clone_info);
 
 5870          if (status != MagickFalse)
 
 5871            status&=(MagickStatusType) DrawStrokePolygon(image,draw_info,
 
 5872              primitive_info,exception);
 
 5875      status&=(MagickStatusType) DrawPolygonPrimitive(image,draw_info,
 
 5876        primitive_info,exception);
 
 5880  image_view=DestroyCacheView(image_view);
 
 5881  if (draw_info->compliance == SVGCompliance)
 
 5883      status&=(MagickStatusType) SetImageMask(image,WritePixelMask,
 
 5884        (Image *) NULL,exception);
 
 5885      status&=(MagickStatusType) SetImageMask(image,CompositePixelMask,
 
 5886        (Image *) NULL,exception);
 
 5888  if (draw_info->debug != MagickFalse)
 
 5889    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
"  end draw-primitive");
 
 5890  return(status != 0 ? MagickTrue : MagickFalse);
 
 5923static MagickBooleanType DrawRoundLinecap(Image *image,
 
 5924  const DrawInfo *draw_info,
const PrimitiveInfo *primitive_info,
 
 5925  ExceptionInfo *exception)
 
 5933  for (i=0; i < 4; i++)
 
 5934    linecap[i]=(*primitive_info);
 
 5935  linecap[0].coordinates=4;
 
 5936  linecap[1].point.x+=2.0*MagickEpsilon;
 
 5937  linecap[2].point.x+=2.0*MagickEpsilon;
 
 5938  linecap[2].point.y+=2.0*MagickEpsilon;
 
 5939  linecap[3].point.y+=2.0*MagickEpsilon;
 
 5940  linecap[4].primitive=UndefinedPrimitive;
 
 5941  return(DrawPolygonPrimitive(image,draw_info,linecap,exception));
 
 5944static MagickBooleanType DrawStrokePolygon(Image *image,
 
 5945  const DrawInfo *draw_info,
const PrimitiveInfo *primitive_info,
 
 5946  ExceptionInfo *exception)
 
 5967  if (draw_info->debug != MagickFalse)
 
 5968    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 5969      "    begin draw-stroke-polygon");
 
 5970  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
 
 5971  clone_info->fill=draw_info->stroke;
 
 5972  if (clone_info->fill_pattern != (Image *) NULL)
 
 5973    clone_info->fill_pattern=DestroyImage(clone_info->fill_pattern);
 
 5974  if (clone_info->stroke_pattern != (Image *) NULL)
 
 5975    clone_info->fill_pattern=CloneImage(clone_info->stroke_pattern,0,0,
 
 5976      MagickTrue,exception);
 
 5977  clone_info->stroke.alpha=(MagickRealType) TransparentAlpha;
 
 5978  clone_info->stroke_width=0.0;
 
 5979  clone_info->fill_rule=NonZeroRule;
 
 5981  for (p=primitive_info; p->primitive != UndefinedPrimitive; p+=(ptrdiff_t) p->coordinates)
 
 5983    if (p->coordinates == 1)
 
 5985    stroke_polygon=TraceStrokePolygon(draw_info,p,exception);
 
 5986    if (stroke_polygon == (PrimitiveInfo *) NULL)
 
 5991    status&=(MagickStatusType) DrawPolygonPrimitive(image,clone_info,
 
 5992      stroke_polygon,exception);
 
 5993    stroke_polygon=(PrimitiveInfo *) RelinquishMagickMemory(stroke_polygon);
 
 5996    q=p+p->coordinates-1;
 
 5997    closed_path=p->closed_subpath;
 
 5998    if ((draw_info->linecap == RoundCap) && (closed_path == MagickFalse))
 
 6000        status&=(MagickStatusType) DrawRoundLinecap(image,draw_info,p,
 
 6002        status&=(MagickStatusType) DrawRoundLinecap(image,draw_info,q,
 
 6006  clone_info=DestroyDrawInfo(clone_info);
 
 6007  if (draw_info->debug != MagickFalse)
 
 6008    (void) LogMagickEvent(DrawEvent,GetMagickModule(),
 
 6009      "    end draw-stroke-polygon");
 
 6010  return(status != 0 ? MagickTrue : MagickFalse);
 
 6036MagickExport 
void GetAffineMatrix(AffineMatrix *affine_matrix)
 
 6038  if (IsEventLogging() != MagickFalse)
 
 6039    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
 
 6040  assert(affine_matrix != (AffineMatrix *) NULL);
 
 6041  (void) memset(affine_matrix,0,
sizeof(*affine_matrix));
 
 6042  affine_matrix->sx=1.0;
 
 6043  affine_matrix->sy=1.0;
 
 6070MagickExport 
void GetDrawInfo(
const ImageInfo *image_info,DrawInfo *draw_info)
 
 6084  assert(draw_info != (DrawInfo *) NULL);
 
 6085  if (IsEventLogging() != MagickFalse)
 
 6086    (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
 
 6087  (void) memset(draw_info,0,
sizeof(*draw_info));
 
 6088  draw_info->image_info=CloneImageInfo(image_info);
 
 6089  GetAffineMatrix(&draw_info->affine);
 
 6090  exception=AcquireExceptionInfo();
 
 6091  (void) QueryColorCompliance(
"#000F",AllCompliance,&draw_info->fill,
 
 6093  (void) QueryColorCompliance(
"#FFF0",AllCompliance,&draw_info->stroke,
 
 6095  draw_info->stroke_antialias=draw_info->image_info->antialias;
 
 6096  draw_info->stroke_width=1.0;
 
 6097  draw_info->fill_rule=EvenOddRule;
 
 6098  draw_info->alpha=OpaqueAlpha;
 
 6099  draw_info->fill_alpha=OpaqueAlpha;
 
 6100  draw_info->stroke_alpha=OpaqueAlpha;
 
 6101  draw_info->linecap=ButtCap;
 
 6102  draw_info->linejoin=MiterJoin;
 
 6103  draw_info->miterlimit=10;
 
 6104  draw_info->decorate=NoDecoration;
 
 6105  draw_info->pointsize=12.0;
 
 6106  draw_info->undercolor.alpha=(MagickRealType) TransparentAlpha;
 
 6107  draw_info->compose=OverCompositeOp;
 
 6108  draw_info->render=MagickTrue;
 
 6109  draw_info->clip_path=MagickFalse;
 
 6110  draw_info->debug=(GetLogEventMask() & (DrawEvent | AnnotateEvent)) != 0 ?
 
 6111    MagickTrue : MagickFalse;
 
 6112  if (draw_info->image_info->font != (
char *) NULL)
 
 6113    draw_info->font=AcquireString(draw_info->image_info->font);
 
 6114  if (draw_info->image_info->density != (
char *) NULL)
 
 6115    draw_info->density=AcquireString(draw_info->image_info->density);
 
 6116  draw_info->text_antialias=draw_info->image_info->antialias;
 
 6117  if (fabs(draw_info->image_info->pointsize) >= MagickEpsilon)
 
 6118    draw_info->pointsize=draw_info->image_info->pointsize;
 
 6119  draw_info->border_color=draw_info->image_info->border_color;
 
 6120  if (draw_info->image_info->server_name != (
char *) NULL)
 
 6121    draw_info->server_name=AcquireString(draw_info->image_info->server_name);
 
 6122  option=GetImageOption(draw_info->image_info,
"direction");
 
 6123  if (option != (
const char *) NULL)
 
 6124    draw_info->direction=(DirectionType) ParseCommandOption(
 
 6125      MagickDirectionOptions,MagickFalse,option);
 
 6127    draw_info->direction=UndefinedDirection;
 
 6128  option=GetImageOption(draw_info->image_info,
"encoding");
 
 6129  if (option != (
const char *) NULL)
 
 6130    (void) CloneString(&draw_info->encoding,option);
 
 6131  option=GetImageOption(draw_info->image_info,
"family");
 
 6132  if (option != (
const char *) NULL)
 
 6133    (void) CloneString(&draw_info->family,option);
 
 6134  option=GetImageOption(draw_info->image_info,
"fill");
 
 6135  if (option != (
const char *) NULL)
 
 6136    (void) QueryColorCompliance(option,AllCompliance,&draw_info->fill,
 
 6138  option=GetImageOption(draw_info->image_info,
"gravity");
 
 6139  if (option != (
const char *) NULL)
 
 6140    draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
 
 6141      MagickFalse,option);
 
 6142  option=GetImageOption(draw_info->image_info,
"interline-spacing");
 
 6143  if (option != (
const char *) NULL)
 
 6144    draw_info->interline_spacing=GetDrawValue(option,&next_token);
 
 6145  option=GetImageOption(draw_info->image_info,
"interword-spacing");
 
 6146  if (option != (
const char *) NULL)
 
 6147    draw_info->interword_spacing=GetDrawValue(option,&next_token);
 
 6148  option=GetImageOption(draw_info->image_info,
"kerning");
 
 6149  if (option != (
const char *) NULL)
 
 6150    draw_info->kerning=GetDrawValue(option,&next_token);
 
 6151  option=GetImageOption(draw_info->image_info,
"stroke");
 
 6152  if (option != (
const char *) NULL)
 
 6153    (void) QueryColorCompliance(option,AllCompliance,&draw_info->stroke,
 
 6155  option=GetImageOption(draw_info->image_info,
"strokewidth");
 
 6156  if (option != (
const char *) NULL)
 
 6157    draw_info->stroke_width=GetDrawValue(option,&next_token);
 
 6158  option=GetImageOption(draw_info->image_info,
"style");
 
 6159  if (option != (
const char *) NULL)
 
 6160    draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
 
 6161      MagickFalse,option);
 
 6162  option=GetImageOption(draw_info->image_info,
"undercolor");
 
 6163  if (option != (
const char *) NULL)
 
 6164    (void) QueryColorCompliance(option,AllCompliance,&draw_info->undercolor,
 
 6166  option=GetImageOption(draw_info->image_info,
"weight");
 
 6167  if (option != (
const char *) NULL)
 
 6172      weight=ParseCommandOption(MagickWeightOptions,MagickFalse,option);
 
 6174        weight=(ssize_t) StringToUnsignedLong(option);
 
 6175      draw_info->weight=(size_t) weight;
 
 6177  option=GetImageOption(draw_info->image_info,
"word-break");
 
 6178  if (option != (
const char *) NULL)
 
 6179    draw_info->word_break=(WordBreakType) ParseCommandOption(
 
 6180      MagickWordBreakOptions,MagickFalse,option);
 
 6181  exception=DestroyExceptionInfo(exception);
 
 6182  draw_info->signature=MagickCoreSignature;
 
 6210static inline double Permutate(
const ssize_t n,
const ssize_t k)
 
 6219  for (i=k+1; i <= n; i++)
 
 6221  for (i=1; i <= (n-k); i++)
 
 6242static MagickBooleanType TraceArc(MVGInfo *mvg_info,
const PointInfo start,
 
 6243  const PointInfo end,
const PointInfo degrees)
 
 6249  center.x=0.5*(end.x+start.x);
 
 6250  center.y=0.5*(end.y+start.y);
 
 6251  radius.x=fabs(center.x-start.x);
 
 6252  radius.y=fabs(center.y-start.y);
 
 6253  return(TraceEllipse(mvg_info,center,radius,degrees));
 
 6256static MagickBooleanType TraceArcPath(MVGInfo *mvg_info,
const PointInfo start,
 
 6257  const PointInfo end,
const PointInfo arc,
const double angle,
 
 6258  const MagickBooleanType large_arc,
const MagickBooleanType sweep)
 
 6295  offset=mvg_info->offset;
 
 6296  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6297  primitive_info->coordinates=0;
 
 6298  if ((fabs(start.x-end.x) < MagickEpsilon) &&
 
 6299      (fabs(start.y-end.y) < MagickEpsilon))
 
 6300    return(TracePoint(primitive_info,end));
 
 6301  radii.x=fabs(arc.x);
 
 6302  radii.y=fabs(arc.y);
 
 6303  if ((radii.x < MagickEpsilon) || (radii.y < MagickEpsilon))
 
 6304    return(TraceLine(primitive_info,start,end));
 
 6305  cosine=cos(DegreesToRadians(fmod((
double) angle,360.0)));
 
 6306  sine=sin(DegreesToRadians(fmod((
double) angle,360.0)));
 
 6307  center.x=(double) (cosine*(end.x-start.x)/2+sine*(end.y-start.y)/2);
 
 6308  center.y=(double) (cosine*(end.y-start.y)/2-sine*(end.x-start.x)/2);
 
 6309  delta=(center.x*center.x)/(radii.x*radii.x)+(center.y*center.y)/
 
 6311  if (delta < MagickEpsilon)
 
 6312    return(TraceLine(primitive_info,start,end));
 
 6315      radii.x*=sqrt((
double) delta);
 
 6316      radii.y*=sqrt((
double) delta);
 
 6318  points[0].x=(double) (cosine*start.x/radii.x+sine*start.y/radii.x);
 
 6319  points[0].y=(double) (cosine*start.y/radii.y-sine*start.x/radii.y);
 
 6320  points[1].x=(double) (cosine*end.x/radii.x+sine*end.y/radii.x);
 
 6321  points[1].y=(double) (cosine*end.y/radii.y-sine*end.x/radii.y);
 
 6322  alpha=points[1].x-points[0].x;
 
 6323  beta=points[1].y-points[0].y;
 
 6324  if (fabs(alpha*alpha+beta*beta) < MagickEpsilon)
 
 6325    return(TraceLine(primitive_info,start,end));
 
 6326  factor=MagickSafeReciprocal(alpha*alpha+beta*beta)-0.25;
 
 6331      factor=sqrt((
double) factor);
 
 6332      if (sweep == large_arc)
 
 6335  center.x=(double) ((points[0].x+points[1].x)/2-factor*beta);
 
 6336  center.y=(double) ((points[0].y+points[1].y)/2+factor*alpha);
 
 6337  alpha=atan2(points[0].y-center.y,points[0].x-center.x);
 
 6338  theta=atan2(points[1].y-center.y,points[1].x-center.x)-alpha;
 
 6339  if ((theta < 0.0) && (sweep != MagickFalse))
 
 6340    theta+=2.0*MagickPI;
 
 6342    if ((theta > 0.0) && (sweep == MagickFalse))
 
 6343      theta-=2.0*MagickPI;
 
 6344  arc_segments=(size_t) CastDoubleToSsizeT(ceil(fabs((
double) (theta/(0.5*
 
 6345    MagickPI+MagickEpsilon)))));
 
 6348  for (i=0; i < (ssize_t) arc_segments; i++)
 
 6350    beta=0.5*((alpha+(i+1)*theta/arc_segments)-(alpha+i*theta/arc_segments));
 
 6351    gamma=(8.0/3.0)*sin(fmod((
double) (0.5*beta),DegreesToRadians(360.0)))*
 
 6352      sin(fmod((
double) (0.5*beta),DegreesToRadians(360.0)))/
 
 6353      sin(fmod((
double) beta,DegreesToRadians(360.0)));
 
 6354    points[0].x=(double) (center.x+cos(fmod((
double) (alpha+(
double) i*theta/
 
 6355      arc_segments),DegreesToRadians(360.0)))-gamma*sin(fmod((
double) (alpha+
 
 6356      (
double) i*theta/arc_segments),DegreesToRadians(360.0))));
 
 6357    points[0].y=(double) (center.y+sin(fmod((
double) (alpha+(
double) i*theta/
 
 6358      arc_segments),DegreesToRadians(360.0)))+gamma*cos(fmod((
double) (alpha+
 
 6359      (
double) i*theta/arc_segments),DegreesToRadians(360.0))));
 
 6360    points[2].x=(double) (center.x+cos(fmod((
double) (alpha+(
double) (i+1)*
 
 6361      theta/arc_segments),DegreesToRadians(360.0))));
 
 6362    points[2].y=(double) (center.y+sin(fmod((
double) (alpha+(
double) (i+1)*
 
 6363      theta/arc_segments),DegreesToRadians(360.0))));
 
 6364    points[1].x=(double) (points[2].x+gamma*sin(fmod((
double) (alpha+(
double)
 
 6365      (i+1)*theta/arc_segments),DegreesToRadians(360.0))));
 
 6366    points[1].y=(double) (points[2].y-gamma*cos(fmod((
double) (alpha+(
double)
 
 6367      (i+1)*theta/arc_segments),DegreesToRadians(360.0))));
 
 6368    p->point.x=(p == primitive_info) ? start.x : (p-1)->point.x;
 
 6369    p->point.y=(p == primitive_info) ? start.y : (p-1)->point.y;
 
 6370    (p+1)->point.x=(double) (cosine*radii.x*points[0].x-sine*radii.y*
 
 6372    (p+1)->point.y=(double) (sine*radii.x*points[0].x+cosine*radii.y*
 
 6374    (p+2)->point.x=(double) (cosine*radii.x*points[1].x-sine*radii.y*
 
 6376    (p+2)->point.y=(double) (sine*radii.x*points[1].x+cosine*radii.y*
 
 6378    (p+3)->point.x=(double) (cosine*radii.x*points[2].x-sine*radii.y*
 
 6380    (p+3)->point.y=(double) (sine*radii.x*points[2].x+cosine*radii.y*
 
 6382    if (i == (ssize_t) (arc_segments-1))
 
 6384    status&=(MagickStatusType) TraceBezier(mvg_info,4);
 
 6387    p=(*mvg_info->primitive_info)+(ptrdiff_t) mvg_info->offset;
 
 6388    mvg_info->offset+=(ssize_t) p->coordinates;
 
 6389    p+=(ptrdiff_t) p->coordinates;
 
 6392    return(MagickFalse);
 
 6393  mvg_info->offset=offset;
 
 6394  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6395  primitive_info->coordinates=(size_t) (p-primitive_info);
 
 6396  primitive_info->closed_subpath=MagickFalse;
 
 6397  for (i=0; i < (ssize_t) primitive_info->coordinates; i++)
 
 6399    p->primitive=primitive_info->primitive;
 
 6405static MagickBooleanType TraceBezier(MVGInfo *mvg_info,
 
 6406  const size_t number_coordinates)
 
 6435  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6436  quantum=number_coordinates;
 
 6437  for (i=0; i < (ssize_t) number_coordinates; i++)
 
 6439    for (j=i+1; j < (ssize_t) number_coordinates; j++)
 
 6441      alpha=fabs(primitive_info[j].point.x-primitive_info[i].point.x);
 
 6442      if (alpha > (
double) MAGICK_SSIZE_MAX)
 
 6444          (void) ThrowMagickException(mvg_info->exception,GetMagickModule(),
 
 6445            ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 6446          return(MagickFalse);
 
 6448      if (alpha > (
double) quantum)
 
 6449        quantum=(size_t) alpha;
 
 6450      alpha=fabs(primitive_info[j].point.y-primitive_info[i].point.y);
 
 6451      if (alpha > (
double) MAGICK_SSIZE_MAX)
 
 6453          (void) ThrowMagickException(mvg_info->exception,GetMagickModule(),
 
 6454            ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 6455          return(MagickFalse);
 
 6457      if (alpha > (
double) quantum)
 
 6458        quantum=(size_t) alpha;
 
 6461  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6462  quantum=MagickMin(quantum/number_coordinates,BezierQuantum);
 
 6463  coefficients=(
double *) AcquireQuantumMemory(number_coordinates,
 
 6464    sizeof(*coefficients));
 
 6465  points=(PointInfo *) AcquireQuantumMemory(quantum,number_coordinates*
 
 6467  if ((coefficients == (
double *) NULL) || (points == (PointInfo *) NULL))
 
 6469      if (points != (PointInfo *) NULL)
 
 6470        points=(PointInfo *) RelinquishMagickMemory(points);
 
 6471      if (coefficients != (
double *) NULL)
 
 6472        coefficients=(
double *) RelinquishMagickMemory(coefficients);
 
 6473      (void) ThrowMagickException(mvg_info->exception,GetMagickModule(),
 
 6474        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 6475      return(MagickFalse);
 
 6477  control_points=quantum*number_coordinates;
 
 6478  if (CheckPrimitiveExtent(mvg_info,(
double) control_points+1) == MagickFalse)
 
 6480      points=(PointInfo *) RelinquishMagickMemory(points);
 
 6481      coefficients=(
double *) RelinquishMagickMemory(coefficients);
 
 6482      return(MagickFalse);
 
 6484  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6488  end=primitive_info[number_coordinates-1].point;
 
 6489  for (i=0; i < (ssize_t) number_coordinates; i++)
 
 6490    coefficients[i]=Permutate((ssize_t) number_coordinates-1,i);
 
 6492  for (i=0; i < (ssize_t) control_points; i++)
 
 6497    alpha=pow((
double) (1.0-weight),(
double) number_coordinates-1.0);
 
 6498    for (j=0; j < (ssize_t) number_coordinates; j++)
 
 6500      point.x+=alpha*coefficients[j]*p->point.x;
 
 6501      point.y+=alpha*coefficients[j]*p->point.y;
 
 6502      alpha*=weight/(1.0-weight);
 
 6506    weight+=1.0/control_points;
 
 6512  for (i=0; i < (ssize_t) control_points; i++)
 
 6514    if (TracePoint(p,points[i]) == MagickFalse)
 
 6516        points=(PointInfo *) RelinquishMagickMemory(points);
 
 6517        coefficients=(
double *) RelinquishMagickMemory(coefficients);
 
 6518        return(MagickFalse);
 
 6520    p+=(ptrdiff_t) p->coordinates;
 
 6522  if (TracePoint(p,end) == MagickFalse)
 
 6524      points=(PointInfo *) RelinquishMagickMemory(points);
 
 6525      coefficients=(
double *) RelinquishMagickMemory(coefficients);
 
 6526      return(MagickFalse);
 
 6528  p+=(ptrdiff_t) p->coordinates;
 
 6529  primitive_info->coordinates=(size_t) (p-primitive_info);
 
 6530  primitive_info->closed_subpath=MagickFalse;
 
 6531  for (i=0; i < (ssize_t) primitive_info->coordinates; i++)
 
 6533    p->primitive=primitive_info->primitive;
 
 6536  points=(PointInfo *) RelinquishMagickMemory(points);
 
 6537  coefficients=(
double *) RelinquishMagickMemory(coefficients);
 
 6541static MagickBooleanType TraceCircle(MVGInfo *mvg_info,
const PointInfo start,
 
 6542  const PointInfo end)
 
 6553  alpha=end.x-start.x;
 
 6555  radius=hypot((
double) alpha,(
double) beta);
 
 6556  offset.x=(double) radius;
 
 6557  offset.y=(double) radius;
 
 6560  return(TraceEllipse(mvg_info,start,offset,degrees));
 
 6563static MagickBooleanType TraceEllipse(MVGInfo *mvg_info,
const PointInfo center,
 
 6564  const PointInfo radii,
const PointInfo arc)
 
 6589  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6590  primitive_info->coordinates=0;
 
 6591  if ((fabs(radii.x) < MagickEpsilon) || (fabs(radii.y) < MagickEpsilon))
 
 6593  delta=MagickSafeReciprocal(MagickMax(radii.x,radii.y));
 
 6594  step=MagickPI/(MagickPI*MagickSafeReciprocal(delta))/8.0;
 
 6595  angle.x=DegreesToRadians(arc.x);
 
 6599  angle.y=DegreesToRadians(y);
 
 6600  coordinates=ceil((angle.y-angle.x)/step+1.0);
 
 6601  if (CheckPrimitiveExtent(mvg_info,coordinates+1) == MagickFalse)
 
 6602    return(MagickFalse);
 
 6604  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6605  for (p=primitive_info; angle.x < angle.y; angle.x+=step)
 
 6607    point.x=cos(fmod(angle.x,DegreesToRadians(360.0)))*radii.x+center.x;
 
 6608    point.y=sin(fmod(angle.x,DegreesToRadians(360.0)))*radii.y+center.y;
 
 6609    if (i++ >= (ssize_t) coordinates)
 
 6611    if (TracePoint(p,point) == MagickFalse)
 
 6612      return(MagickFalse);
 
 6613    p+=(ptrdiff_t) p->coordinates;
 
 6615  point.x=cos(fmod(angle.y,DegreesToRadians(360.0)))*radii.x+center.x;
 
 6616  point.y=sin(fmod(angle.y,DegreesToRadians(360.0)))*radii.y+center.y;
 
 6617  if (TracePoint(p,point) == MagickFalse)
 
 6618    return(MagickFalse);
 
 6619  p+=(ptrdiff_t) p->coordinates;
 
 6620  primitive_info->coordinates=(size_t) (p-primitive_info);
 
 6621  primitive_info->closed_subpath=MagickFalse;
 
 6622  x=fabs(primitive_info[0].point.x-
 
 6623    primitive_info[primitive_info->coordinates-1].point.x);
 
 6624  y=fabs(primitive_info[0].point.y-
 
 6625    primitive_info[primitive_info->coordinates-1].point.y);
 
 6626  if ((x < MagickEpsilon) && (y < MagickEpsilon))
 
 6627    primitive_info->closed_subpath=MagickTrue;
 
 6628  for (i=0; i < (ssize_t) primitive_info->coordinates; i++)
 
 6630    p->primitive=primitive_info->primitive;
 
 6636static MagickBooleanType TraceLine(PrimitiveInfo *primitive_info,
 
 6637  const PointInfo start,
const PointInfo end)
 
 6639  if (TracePoint(primitive_info,start) == MagickFalse)
 
 6640    return(MagickFalse);
 
 6641  if (TracePoint(primitive_info+1,end) == MagickFalse)
 
 6642    return(MagickFalse);
 
 6643  (primitive_info+1)->primitive=primitive_info->primitive;
 
 6644  primitive_info->coordinates=2;
 
 6645  primitive_info->closed_subpath=MagickFalse;
 
 6649static ssize_t TracePath(MVGInfo *mvg_info,
const char *path,
 
 6650  ExceptionInfo *exception)
 
 6654    token[MagickPathExtent] = 
"";
 
 6672    points[4] = { {0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0} },
 
 6695  subpath_offset=mvg_info->offset;
 
 6696  primitive_info=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6699  number_coordinates=0;
 
 6701  primitive_type=primitive_info->primitive;
 
 6703  for (p=path; *p != 
'\0'; )
 
 6705    if (status == MagickFalse)
 
 6707    while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6711    last_attribute=attribute;
 
 6712    attribute=(int) (*p++);
 
 6722          large_arc = MagickFalse,
 
 6723          sweep = MagickFalse;
 
 6733          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6735            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6736          arc.x=GetDrawValue(token,&next_token);
 
 6737          if (token == next_token)
 
 6738            ThrowPointExpectedException(token,exception);
 
 6739          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6741            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6742          arc.y=GetDrawValue(token,&next_token);
 
 6743          if (token == next_token)
 
 6744            ThrowPointExpectedException(token,exception);
 
 6745          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6747            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6748          angle=GetDrawValue(token,&next_token);
 
 6749          if (token == next_token)
 
 6750            ThrowPointExpectedException(token,exception);
 
 6751          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6753            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6754          large_arc=StringToLong(token) != 0 ? MagickTrue : MagickFalse;
 
 6755          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6757            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6758          sweep=StringToLong(token) != 0 ? MagickTrue : MagickFalse;
 
 6760            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6761          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6763            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6764          x=GetDrawValue(token,&next_token);
 
 6765          if (token == next_token)
 
 6766            ThrowPointExpectedException(token,exception);
 
 6767          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6769            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6770          y=GetDrawValue(token,&next_token);
 
 6771          if (token == next_token)
 
 6772            ThrowPointExpectedException(token,exception);
 
 6773          end.x=(double) (attribute == (
int) 
'A' ? x : point.x+x);
 
 6774          end.y=(double) (attribute == (
int) 
'A' ? y : point.y+y);
 
 6775          if (TraceArcPath(mvg_info,point,end,arc,angle,large_arc,sweep) == MagickFalse)
 
 6777          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6778          mvg_info->offset+=(ssize_t) q->coordinates;
 
 6779          q+=(ptrdiff_t) q->coordinates;
 
 6781          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6785        } 
while (IsPoint(p) != MagickFalse);
 
 6797          for (i=1; i < 4; i++)
 
 6799            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6801              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6802            x=GetDrawValue(token,&next_token);
 
 6803            if (token == next_token)
 
 6804              ThrowPointExpectedException(token,exception);
 
 6805            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6807              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6808            y=GetDrawValue(token,&next_token);
 
 6809            if (token == next_token)
 
 6810              ThrowPointExpectedException(token,exception);
 
 6811            end.x=(double) (attribute == (
int) 
'C' ? x : point.x+x);
 
 6812            end.y=(double) (attribute == (
int) 
'C' ? y : point.y+y);
 
 6815          for (i=0; i < 4; i++)
 
 6816            (q+i)->point=points[i];
 
 6817          if (TraceBezier(mvg_info,4) == MagickFalse)
 
 6819          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6820          mvg_info->offset+=(ssize_t) q->coordinates;
 
 6821          q+=(ptrdiff_t) q->coordinates;
 
 6823          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6827        } 
while (IsPoint(p) != MagickFalse);
 
 6835          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6837            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6838          x=GetDrawValue(token,&next_token);
 
 6839          if (token == next_token)
 
 6840            ThrowPointExpectedException(token,exception);
 
 6841          point.x=(double) (attribute == (
int) 
'H' ? x: point.x+x);
 
 6842          if (CheckPrimitiveExtent(mvg_info,PrimitiveExtentPad) == MagickFalse)
 
 6844          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6845          if (TracePoint(q,point) == MagickFalse)
 
 6847          mvg_info->offset+=(ssize_t) q->coordinates;
 
 6848          q+=(ptrdiff_t) q->coordinates;
 
 6849          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6853        } 
while (IsPoint(p) != MagickFalse);
 
 6864          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6866            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6867          x=GetDrawValue(token,&next_token);
 
 6868          if (token == next_token)
 
 6869            ThrowPointExpectedException(token,exception);
 
 6870          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6872            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6873          y=GetDrawValue(token,&next_token);
 
 6874          if (token == next_token)
 
 6875            ThrowPointExpectedException(token,exception);
 
 6876          point.x=(double) (attribute == (
int) 
'L' ? x : point.x+x);
 
 6877          point.y=(double) (attribute == (
int) 
'L' ? y : point.y+y);
 
 6878          if (CheckPrimitiveExtent(mvg_info,PrimitiveExtentPad) == MagickFalse)
 
 6880          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6881          if (TracePoint(q,point) == MagickFalse)
 
 6883          mvg_info->offset+=(ssize_t) q->coordinates;
 
 6884          q+=(ptrdiff_t) q->coordinates;
 
 6885          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6889        } 
while (IsPoint(p) != MagickFalse);
 
 6898        if (mvg_info->offset != subpath_offset)
 
 6900            primitive_info=(*mvg_info->primitive_info)+subpath_offset;
 
 6901            primitive_info->coordinates=(size_t) (q-primitive_info);
 
 6902            number_coordinates+=primitive_info->coordinates;
 
 6904            subpath_offset=mvg_info->offset;
 
 6909          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6911            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6912          x=GetDrawValue(token,&next_token);
 
 6913          if (token == next_token)
 
 6914            ThrowPointExpectedException(token,exception);
 
 6915          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6917            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6918          y=GetDrawValue(token,&next_token);
 
 6919          if (token == next_token)
 
 6920            ThrowPointExpectedException(token,exception);
 
 6921          point.x=(double) (attribute == (
int) 
'M' ? x : point.x+x);
 
 6922          point.y=(double) (attribute == (
int) 
'M' ? y : point.y+y);
 
 6926          if (CheckPrimitiveExtent(mvg_info,PrimitiveExtentPad) == MagickFalse)
 
 6928          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6929          if (TracePoint(q,point) == MagickFalse)
 
 6931          mvg_info->offset+=(ssize_t) q->coordinates;
 
 6932          q+=(ptrdiff_t) q->coordinates;
 
 6933          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6937        } 
while (IsPoint(p) != MagickFalse);
 
 6949          for (i=1; i < 3; i++)
 
 6951            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6953              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6954            x=GetDrawValue(token,&next_token);
 
 6955            if (token == next_token)
 
 6956              ThrowPointExpectedException(token,exception);
 
 6957            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6959              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6960            y=GetDrawValue(token,&next_token);
 
 6961            if (token == next_token)
 
 6962              ThrowPointExpectedException(token,exception);
 
 6965            end.x=(double) (attribute == (
int) 
'Q' ? x : point.x+x);
 
 6966            end.y=(double) (attribute == (
int) 
'Q' ? y : point.y+y);
 
 6969          for (i=0; i < 3; i++)
 
 6970            (q+i)->point=points[i];
 
 6971          if (TraceBezier(mvg_info,3) == MagickFalse)
 
 6973          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 6974          mvg_info->offset+=(ssize_t) q->coordinates;
 
 6975          q+=(ptrdiff_t) q->coordinates;
 
 6977          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 6981        } 
while (IsPoint(p) != MagickFalse);
 
 6992          points[0]=points[3];
 
 6993          points[1].x=2.0*points[3].x-points[2].x;
 
 6994          points[1].y=2.0*points[3].y-points[2].y;
 
 6995          for (i=2; i < 4; i++)
 
 6997            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 6999              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7000            x=GetDrawValue(token,&next_token);
 
 7001            if (token == next_token)
 
 7002              ThrowPointExpectedException(token,exception);
 
 7003            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7005              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7006            y=GetDrawValue(token,&next_token);
 
 7007            if (token == next_token)
 
 7008              ThrowPointExpectedException(token,exception);
 
 7011            end.x=(double) (attribute == (
int) 
'S' ? x : point.x+x);
 
 7012            end.y=(double) (attribute == (
int) 
'S' ? y : point.y+y);
 
 7015          if (strchr(
"CcSs",last_attribute) == (
char *) NULL)
 
 7020          for (i=0; i < 4; i++)
 
 7021            (q+i)->point=points[i];
 
 7022          if (TraceBezier(mvg_info,4) == MagickFalse)
 
 7024          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 7025          mvg_info->offset+=(ssize_t) q->coordinates;
 
 7026          q+=(ptrdiff_t) q->coordinates;
 
 7028          last_attribute=attribute;
 
 7029          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 7033        } 
while (IsPoint(p) != MagickFalse);
 
 7044          points[0]=points[2];
 
 7045          points[1].x=2.0*points[2].x-points[1].x;
 
 7046          points[1].y=2.0*points[2].y-points[1].y;
 
 7047          for (i=2; i < 3; i++)
 
 7049            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7051              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7052            x=GetDrawValue(token,&next_token);
 
 7053            if (token == next_token)
 
 7054              ThrowPointExpectedException(token,exception);
 
 7055            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7057              (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7058            y=GetDrawValue(token,&next_token);
 
 7059            if (token == next_token)
 
 7060              ThrowPointExpectedException(token,exception);
 
 7061            end.x=(double) (attribute == (
int) 
'T' ? x : point.x+x);
 
 7062            end.y=(double) (attribute == (
int) 
'T' ? y : point.y+y);
 
 7065          if (status == MagickFalse)
 
 7067          if (strchr(
"QqTt",last_attribute) == (
char *) NULL)
 
 7072          for (i=0; i < 3; i++)
 
 7073            (q+i)->point=points[i];
 
 7074          if (TraceBezier(mvg_info,3) == MagickFalse)
 
 7076          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 7077          mvg_info->offset+=(ssize_t) q->coordinates;
 
 7078          q+=(ptrdiff_t) q->coordinates;
 
 7080          last_attribute=attribute;
 
 7081          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 7085        } 
while (IsPoint(p) != MagickFalse);
 
 7096          (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7098            (void) GetNextToken(p,&p,MagickPathExtent,token);
 
 7099          y=GetDrawValue(token,&next_token);
 
 7100          if (token == next_token)
 
 7101            ThrowPointExpectedException(token,exception);
 
 7102          point.y=(double) (attribute == (
int) 
'V' ? y : point.y+y);
 
 7103          if (CheckPrimitiveExtent(mvg_info,PrimitiveExtentPad) == MagickFalse)
 
 7105          q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 7106          if (TracePoint(q,point) == MagickFalse)
 
 7108          mvg_info->offset+=(ssize_t) q->coordinates;
 
 7109          q+=(ptrdiff_t) q->coordinates;
 
 7110          while (isspace((
int) ((
unsigned char) *p)) != 0)
 
 7114        } 
while (IsPoint(p) != MagickFalse);
 
 7124        if (CheckPrimitiveExtent(mvg_info,PrimitiveExtentPad) == MagickFalse)
 
 7126        q=(*mvg_info->primitive_info)+mvg_info->offset;
 
 7127        if (TracePoint(q,point) == MagickFalse)
 
 7129        mvg_info->offset+=(ssize_t) q->coordinates;
 
 7130        q+=(ptrdiff_t) q->coordinates;
 
 7131        primitive_info=(*mvg_info->primitive_info)+subpath_offset;
 
 7132        primitive_info->coordinates=(size_t) (q-primitive_info);
 
 7133        primitive_info->closed_subpath=MagickTrue;
 
 7134        number_coordinates+=primitive_info->coordinates;
 
 7136        subpath_offset=mvg_info->offset;
 
 7142        ThrowPointExpectedException(token,exception);
 
 7147  if (status == MagickFalse)
 
 7149  primitive_info=(*mvg_info->primitive_info)+subpath_offset;
 
 7150  primitive_info->coordinates=(size_t) (q-primitive_info);
 
 7151  number_coordinates+=primitive_info->coordinates;
 
 7152  for (i=0; i < (ssize_t) number_coordinates; i++)
 
 7155    q->primitive=primitive_type;
 
 7157      q->method=FillToBorderMethod;
 
 7160  return((ssize_t) number_coordinates);
 
 7163static MagickBooleanType TraceRectangle(PrimitiveInfo *primitive_info,
 
 7164  const PointInfo start,
const PointInfo end)
 
 7175  if ((fabs(start.x-end.x) < MagickEpsilon) ||
 
 7176      (fabs(start.y-end.y) < MagickEpsilon))
 
 7178      primitive_info->coordinates=0;
 
 7182  if (TracePoint(p,start) == MagickFalse)
 
 7183    return(MagickFalse);
 
 7184  p+=(ptrdiff_t) p->coordinates;
 
 7187  if (TracePoint(p,point) == MagickFalse)
 
 7188    return(MagickFalse);
 
 7189  p+=(ptrdiff_t) p->coordinates;
 
 7190  if (TracePoint(p,end) == MagickFalse)
 
 7191    return(MagickFalse);
 
 7192  p+=(ptrdiff_t) p->coordinates;
 
 7195  if (TracePoint(p,point) == MagickFalse)
 
 7196    return(MagickFalse);
 
 7197  p+=(ptrdiff_t) p->coordinates;
 
 7198  if (TracePoint(p,start) == MagickFalse)
 
 7199    return(MagickFalse);
 
 7200  p+=(ptrdiff_t) p->coordinates;
 
 7201  primitive_info->coordinates=(size_t) (p-primitive_info);
 
 7202  primitive_info->closed_subpath=MagickTrue;
 
 7203  for (i=0; i < (ssize_t) primitive_info->coordinates; i++)
 
 7205    p->primitive=primitive_info->primitive;
 
 7211static MagickBooleanType TraceRoundRectangle(MVGInfo *mvg_info,
 
 7212  const PointInfo start,
const PointInfo end,PointInfo arc)
 
 7231  offset=mvg_info->offset;
 
 7232  segment.x=fabs(end.x-start.x);
 
 7233  segment.y=fabs(end.y-start.y);
 
 7234  if ((segment.x < MagickEpsilon) || (segment.y < MagickEpsilon))
 
 7236      (*mvg_info->primitive_info+mvg_info->offset)->coordinates=0;
 
 7239  if (arc.x > (0.5*segment.x))
 
 7240    arc.x=0.5*segment.x;
 
 7241  if (arc.y > (0.5*segment.y))
 
 7242    arc.y=0.5*segment.y;
 
 7243  point.x=start.x+segment.x-arc.x;
 
 7244  point.y=start.y+arc.y;
 
 7247  if (TraceEllipse(mvg_info,point,arc,degrees) == MagickFalse)
 
 7248    return(MagickFalse);
 
 7249  p=(*mvg_info->primitive_info)+(ptrdiff_t) mvg_info->offset;
 
 7250  mvg_info->offset+=(ssize_t) p->coordinates;
 
 7251  point.x=start.x+segment.x-arc.x;
 
 7252  point.y=start.y+segment.y-arc.y;
 
 7255  if (TraceEllipse(mvg_info,point,arc,degrees) == MagickFalse)
 
 7256    return(MagickFalse);
 
 7257  p=(*mvg_info->primitive_info)+(ptrdiff_t) mvg_info->offset;
 
 7258  mvg_info->offset+=(ssize_t) p->coordinates;
 
 7259  point.x=start.x+arc.x;
 
 7260  point.y=start.y+segment.y-arc.y;
 
 7263  if (TraceEllipse(mvg_info,point,arc,degrees) == MagickFalse)
 
 7264    return(MagickFalse);
 
 7265  p=(*mvg_info->primitive_info)+(ptrdiff_t) mvg_info->offset;
 
 7266  mvg_info->offset+=(ssize_t) p->coordinates;
 
 7267  point.x=start.x+arc.x;
 
 7268  point.y=start.y+arc.y;
 
 7271  if (TraceEllipse(mvg_info,point,arc,degrees) == MagickFalse)
 
 7272    return(MagickFalse);
 
 7273  p=(*mvg_info->primitive_info)+(ptrdiff_t) mvg_info->offset;
 
 7274  mvg_info->offset+=(ssize_t) p->coordinates;
 
 7275  if (CheckPrimitiveExtent(mvg_info,PrimitiveExtentPad) == MagickFalse)
 
 7276    return(MagickFalse);
 
 7277  p=(*mvg_info->primitive_info)+(ptrdiff_t) mvg_info->offset;
 
 7278  if (TracePoint(p,(*mvg_info->primitive_info+offset)->point) == MagickFalse)
 
 7279    return(MagickFalse);
 
 7280  p+=(ptrdiff_t) p->coordinates;
 
 7281  mvg_info->offset=offset;
 
 7282  primitive_info=(*mvg_info->primitive_info)+offset;
 
 7283  primitive_info->coordinates=(size_t) (p-primitive_info);
 
 7284  primitive_info->closed_subpath=MagickTrue;
 
 7285  for (i=0; i < (ssize_t) primitive_info->coordinates; i++)
 
 7287    p->primitive=primitive_info->primitive;
 
 7293static MagickBooleanType TraceSquareLinecap(PrimitiveInfo *primitive_info,
 
 7294  const size_t number_vertices,
const double offset)
 
 7311  for (i=1; i < (ssize_t) number_vertices; i++)
 
 7313    dx=primitive_info[0].point.x-primitive_info[i].point.x;
 
 7314    dy=primitive_info[0].point.y-primitive_info[i].point.y;
 
 7315    if ((fabs((
double) dx) >= MagickEpsilon) ||
 
 7316        (fabs((
double) dy) >= MagickEpsilon))
 
 7319  if (i == (ssize_t) number_vertices)
 
 7320    i=(ssize_t) number_vertices-1L;
 
 7321  distance=hypot((
double) dx,(
double) dy);
 
 7322  primitive_info[0].point.x=(double) (primitive_info[i].point.x+
 
 7323    dx*(distance+offset)/distance);
 
 7324  primitive_info[0].point.y=(double) (primitive_info[i].point.y+
 
 7325    dy*(distance+offset)/distance);
 
 7326  for (j=(ssize_t) number_vertices-2; j >= 0;  j--)
 
 7328    dx=primitive_info[number_vertices-1].point.x-primitive_info[j].point.x;
 
 7329    dy=primitive_info[number_vertices-1].point.y-primitive_info[j].point.y;
 
 7330    if ((fabs((
double) dx) >= MagickEpsilon) ||
 
 7331        (fabs((
double) dy) >= MagickEpsilon))
 
 7334  distance=hypot((
double) dx,(
double) dy);
 
 7335  primitive_info[number_vertices-1].point.x=(double) (primitive_info[j].point.x+
 
 7336    dx*(distance+offset)/distance);
 
 7337  primitive_info[number_vertices-1].point.y=(double) (primitive_info[j].point.y+
 
 7338    dy*(distance+offset)/distance);
 
 7342static PrimitiveInfo *TraceStrokePolygon(
const DrawInfo *draw_info,
 
 7343  const PrimitiveInfo *primitive_info,ExceptionInfo *exception)
 
 7345#define MaxStrokePad  (6*BezierQuantum+360) 
 7346#define CheckPathExtent(pad_p,pad_q) \ 
 7348  if ((pad_p) > MaxBezierCoordinates) \ 
 7349    stroke_p=(PointInfo *) RelinquishMagickMemory(stroke_p); \ 
 7351    if ((p+(ptrdiff_t) (pad_p)) >= (ssize_t) extent_p) \ 
 7353        if (~extent_p < (pad_p)) \ 
 7354          stroke_p=(PointInfo *) RelinquishMagickMemory(stroke_p); \ 
 7357            extent_p+=(pad_p); \ 
 7358            stroke_p=(PointInfo *) ResizeQuantumMemory(stroke_p,extent_p+ \ 
 7359              MaxStrokePad,sizeof(*stroke_p)); \ 
 7362  if ((pad_q) > MaxBezierCoordinates) \ 
 7363    stroke_q=(PointInfo *) RelinquishMagickMemory(stroke_q); \ 
 7365    if ((q+(ptrdiff_t) (pad_q)) >= (ssize_t) extent_q) \ 
 7367        if (~extent_q < (pad_q)) \ 
 7368          stroke_q=(PointInfo *) RelinquishMagickMemory(stroke_q); \ 
 7371            extent_q+=(pad_q); \ 
 7372            stroke_q=(PointInfo *) ResizeQuantumMemory(stroke_q,extent_q+ \ 
 7373              MaxStrokePad,sizeof(*stroke_q)); \ 
 7376  if ((stroke_p == (PointInfo *) NULL) || (stroke_q == (PointInfo *) NULL)) \ 
 7378      if (stroke_p != (PointInfo *) NULL) \ 
 7379        stroke_p=(PointInfo *) RelinquishMagickMemory(stroke_p); \ 
 7380      if (stroke_q != (PointInfo *) NULL) \ 
 7381        stroke_q=(PointInfo *) RelinquishMagickMemory(stroke_q); \ 
 7382      polygon_primitive=(PrimitiveInfo *) \ 
 7383        RelinquishMagickMemory(polygon_primitive); \ 
 7384      (void) ThrowMagickException(exception,GetMagickModule(), \ 
 7385        ResourceLimitError,"MemoryAllocationFailed","`%s'",""); \ 
 7386      return((PrimitiveInfo *) NULL); \ 
 7390  typedef struct _StrokeSegment
 
 7436    inverse_slope = {0.0, 0.0},
 
 7443  number_vertices=primitive_info->coordinates;
 
 7444  polygon_primitive=(PrimitiveInfo *) AcquireQuantumMemory((
size_t)
 
 7445    number_vertices+2UL,
sizeof(*polygon_primitive));
 
 7446  if (polygon_primitive == (PrimitiveInfo *) NULL)
 
 7448      (void) ThrowMagickException(exception,GetMagickModule(),
 
 7449        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 7450      return((PrimitiveInfo *) NULL);
 
 7452  (void) memcpy(polygon_primitive,primitive_info,(
size_t) number_vertices*
 
 7453    sizeof(*polygon_primitive));
 
 7454  offset.x=primitive_info[number_vertices-1].point.x-primitive_info[0].point.x;
 
 7455  offset.y=primitive_info[number_vertices-1].point.y-primitive_info[0].point.y;
 
 7456  closed_path=(fabs(offset.x) < MagickEpsilon) &&
 
 7457    (fabs(offset.y) < MagickEpsilon) ? MagickTrue : MagickFalse;
 
 7458  if ((draw_info->linejoin == RoundJoin) ||
 
 7459      ((draw_info->linejoin == MiterJoin) && (closed_path != MagickFalse)))
 
 7461      polygon_primitive[number_vertices]=primitive_info[1];
 
 7464  polygon_primitive[number_vertices].primitive=UndefinedPrimitive;
 
 7468  closed_path=primitive_info[0].closed_subpath;
 
 7471  for (n=1; n < (ssize_t) number_vertices; n++)
 
 7473    dx.p=polygon_primitive[n].point.x-polygon_primitive[0].point.x;
 
 7474    dy.p=polygon_primitive[n].point.y-polygon_primitive[0].point.y;
 
 7475    if ((fabs(dx.p) >= MagickEpsilon) || (fabs(dy.p) >= MagickEpsilon))
 
 7478  if (n == (ssize_t) number_vertices)
 
 7480      if ((draw_info->linecap != RoundCap) || (closed_path != MagickFalse))
 
 7485          stroke_polygon=(PrimitiveInfo *) AcquireCriticalMemory(
 
 7486            sizeof(*stroke_polygon));
 
 7487          stroke_polygon[0]=polygon_primitive[0];
 
 7488          stroke_polygon[0].coordinates=0;
 
 7489          polygon_primitive=(PrimitiveInfo *) RelinquishMagickMemory(
 
 7491          return(stroke_polygon);
 
 7493      n=(ssize_t) number_vertices-1L;
 
 7495  extent_p=2*number_vertices;
 
 7496  extent_q=2*number_vertices;
 
 7497  stroke_p=(PointInfo *) AcquireQuantumMemory((
size_t) extent_p+MaxStrokePad,
 
 7499  stroke_q=(PointInfo *) AcquireQuantumMemory((
size_t) extent_q+MaxStrokePad,
 
 7501  if ((stroke_p == (PointInfo *) NULL) || (stroke_q == (PointInfo *) NULL))
 
 7503      if (stroke_p != (PointInfo *) NULL)
 
 7504        stroke_p=(PointInfo *) RelinquishMagickMemory(stroke_p);
 
 7505      if (stroke_q != (PointInfo *) NULL)
 
 7506        stroke_q=(PointInfo *) RelinquishMagickMemory(stroke_q);
 
 7507      polygon_primitive=(PrimitiveInfo *)
 
 7508        RelinquishMagickMemory(polygon_primitive);
 
 7509      (void) ThrowMagickException(exception,GetMagickModule(),
 
 7510        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 7511      return((PrimitiveInfo *) NULL);
 
 7514  inverse_slope.p=0.0;
 
 7515  if (fabs(dx.p) < MagickEpsilon)
 
 7518        slope.p=dy.p < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon;
 
 7520        slope.p=dy.p < 0.0 ? 1.0/MagickEpsilon : -1.0/MagickEpsilon;
 
 7523    if (fabs(dy.p) < MagickEpsilon)
 
 7526          inverse_slope.p=dx.p < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon;
 
 7528          inverse_slope.p=dx.p < 0.0 ? 1.0/MagickEpsilon : -1.0/MagickEpsilon;
 
 7533        inverse_slope.p=(-1.0*MagickSafeReciprocal(slope.p));
 
 7535  mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0;
 
 7536  miterlimit=(double) (draw_info->miterlimit*draw_info->miterlimit*mid*mid);
 
 7537  if ((draw_info->linecap == SquareCap) && (closed_path == MagickFalse))
 
 7538    (void) TraceSquareLinecap(polygon_primitive,number_vertices,mid);
 
 7539  offset.x=sqrt((
double) (mid*mid/(inverse_slope.p*inverse_slope.p+1.0)));
 
 7540  offset.y=(double) (offset.x*inverse_slope.p);
 
 7541  if ((dy.p*offset.x-dx.p*offset.y) > 0.0)
 
 7543      box_p[0].x=polygon_primitive[0].point.x-offset.x;
 
 7544      box_p[0].y=polygon_primitive[0].point.y-offset.x*inverse_slope.p;
 
 7545      box_p[1].x=polygon_primitive[n].point.x-offset.x;
 
 7546      box_p[1].y=polygon_primitive[n].point.y-offset.x*inverse_slope.p;
 
 7547      box_q[0].x=polygon_primitive[0].point.x+offset.x;
 
 7548      box_q[0].y=polygon_primitive[0].point.y+offset.x*inverse_slope.p;
 
 7549      box_q[1].x=polygon_primitive[n].point.x+offset.x;
 
 7550      box_q[1].y=polygon_primitive[n].point.y+offset.x*inverse_slope.p;
 
 7554      box_p[0].x=polygon_primitive[0].point.x+offset.x;
 
 7555      box_p[0].y=polygon_primitive[0].point.y+offset.y;
 
 7556      box_p[1].x=polygon_primitive[n].point.x+offset.x;
 
 7557      box_p[1].y=polygon_primitive[n].point.y+offset.y;
 
 7558      box_q[0].x=polygon_primitive[0].point.x-offset.x;
 
 7559      box_q[0].y=polygon_primitive[0].point.y-offset.y;
 
 7560      box_q[1].x=polygon_primitive[n].point.x-offset.x;
 
 7561      box_q[1].y=polygon_primitive[n].point.y-offset.y;
 
 7568  stroke_q[p++]=box_q[0];
 
 7569  stroke_p[q++]=box_p[0];
 
 7570  for (i=(ssize_t) n+1; i < (ssize_t) number_vertices; i++)
 
 7575    dx.q=polygon_primitive[i].point.x-polygon_primitive[n].point.x;
 
 7576    dy.q=polygon_primitive[i].point.y-polygon_primitive[n].point.y;
 
 7577    dot_product=dx.q*dx.q+dy.q*dy.q;
 
 7578    if (dot_product < 0.25)
 
 7581    inverse_slope.q=0.0;
 
 7582    if (fabs(dx.q) < MagickEpsilon)
 
 7585          slope.q=dy.q < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon;
 
 7587          slope.q=dy.q < 0.0 ? 1.0/MagickEpsilon : -1.0/MagickEpsilon;
 
 7590      if (fabs(dy.q) < MagickEpsilon)
 
 7593            inverse_slope.q=dx.q < 0.0 ? -1.0/MagickEpsilon : 1.0/MagickEpsilon;
 
 7595            inverse_slope.q=dx.q < 0.0 ? 1.0/MagickEpsilon : -1.0/MagickEpsilon;
 
 7600          inverse_slope.q=(-1.0*MagickSafeReciprocal(slope.q));
 
 7602    offset.x=sqrt((
double) (mid*mid/(inverse_slope.q*inverse_slope.q+1.0)));
 
 7603    offset.y=(double) (offset.x*inverse_slope.q);
 
 7604    dot_product=dy.q*offset.x-dx.q*offset.y;
 
 7605    if (dot_product > 0.0)
 
 7607        box_p[2].x=polygon_primitive[n].point.x-offset.x;
 
 7608        box_p[2].y=polygon_primitive[n].point.y-offset.y;
 
 7609        box_p[3].x=polygon_primitive[i].point.x-offset.x;
 
 7610        box_p[3].y=polygon_primitive[i].point.y-offset.y;
 
 7611        box_q[2].x=polygon_primitive[n].point.x+offset.x;
 
 7612        box_q[2].y=polygon_primitive[n].point.y+offset.y;
 
 7613        box_q[3].x=polygon_primitive[i].point.x+offset.x;
 
 7614        box_q[3].y=polygon_primitive[i].point.y+offset.y;
 
 7618        box_p[2].x=polygon_primitive[n].point.x+offset.x;
 
 7619        box_p[2].y=polygon_primitive[n].point.y+offset.y;
 
 7620        box_p[3].x=polygon_primitive[i].point.x+offset.x;
 
 7621        box_p[3].y=polygon_primitive[i].point.y+offset.y;
 
 7622        box_q[2].x=polygon_primitive[n].point.x-offset.x;
 
 7623        box_q[2].y=polygon_primitive[n].point.y-offset.y;
 
 7624        box_q[3].x=polygon_primitive[i].point.x-offset.x;
 
 7625        box_q[3].y=polygon_primitive[i].point.y-offset.y;
 
 7627    if (fabs((
double) (slope.p-slope.q)) < MagickEpsilon)
 
 7634        box_p[4].x=(double) ((slope.p*box_p[0].x-box_p[0].y-slope.q*box_p[3].x+
 
 7635          box_p[3].y)/(slope.p-slope.q));
 
 7636        box_p[4].y=(double) (slope.p*(box_p[4].x-box_p[0].x)+box_p[0].y);
 
 7637        box_q[4].x=(double) ((slope.p*box_q[0].x-box_q[0].y-slope.q*box_q[3].x+
 
 7638          box_q[3].y)/(slope.p-slope.q));
 
 7639        box_q[4].y=(double) (slope.p*(box_q[4].x-box_q[0].x)+box_q[0].y);
 
 7641    DisableMSCWarning(4127)
 
 7642    CheckPathExtent(MaxStrokePad,MaxStrokePad);
 
 7644    dot_product=dx.q*dy.p-dx.p*dy.q;
 
 7645    if (dot_product <= 0.0)
 
 7646      switch (draw_info->linejoin)
 
 7650          stroke_q[q++]=box_q[1];
 
 7651          stroke_q[q++]=box_q[2];
 
 7652          dot_product=(box_q[4].x-box_p[4].x)*(box_q[4].x-box_p[4].x)+
 
 7653            (box_q[4].y-box_p[4].y)*(box_q[4].y-box_p[4].y);
 
 7654          if (dot_product <= miterlimit)
 
 7655            stroke_p[p++]=box_p[4];
 
 7658              stroke_p[p++]=box_p[1];
 
 7659              stroke_p[p++]=box_p[2];
 
 7665          dot_product=(box_q[4].x-box_p[4].x)*(box_q[4].x-box_p[4].x)+
 
 7666            (box_q[4].y-box_p[4].y)*(box_q[4].y-box_p[4].y);
 
 7667          if (dot_product <= miterlimit)
 
 7669              stroke_q[q++]=box_q[4];
 
 7670              stroke_p[p++]=box_p[4];
 
 7674              stroke_q[q++]=box_q[1];
 
 7675              stroke_q[q++]=box_q[2];
 
 7676              stroke_p[p++]=box_p[1];
 
 7677              stroke_p[p++]=box_p[2];
 
 7683          dot_product=(box_q[4].x-box_p[4].x)*(box_q[4].x-box_p[4].x)+
 
 7684            (box_q[4].y-box_p[4].y)*(box_q[4].y-box_p[4].y);
 
 7685          if (dot_product <= miterlimit)
 
 7686            stroke_p[p++]=box_p[4];
 
 7689              stroke_p[p++]=box_p[1];
 
 7690              stroke_p[p++]=box_p[2];
 
 7692          center=polygon_primitive[n].point;
 
 7693          theta.p=atan2(box_q[1].y-center.y,box_q[1].x-center.x);
 
 7694          theta.q=atan2(box_q[2].y-center.y,box_q[2].x-center.x);
 
 7695          if (theta.q < theta.p)
 
 7696            theta.q+=2.0*MagickPI;
 
 7697          arc_segments=(size_t) CastDoubleToSsizeT(ceil((
double) ((theta.q-
 
 7698            theta.p)/(2.0*sqrt(MagickSafeReciprocal(mid))))));
 
 7699          DisableMSCWarning(4127)
 
 7700          CheckPathExtent(MaxStrokePad,arc_segments+MaxStrokePad);
 
 7702          stroke_q[q].x=box_q[1].x;
 
 7703          stroke_q[q].y=box_q[1].y;
 
 7705          for (j=1; j < (ssize_t) arc_segments; j++)
 
 7707            delta_theta=(double) (j*(theta.q-theta.p)/arc_segments);
 
 7708            stroke_q[q].x=(double) (center.x+mid*cos(fmod((
double)
 
 7709              (theta.p+delta_theta),DegreesToRadians(360.0))));
 
 7710            stroke_q[q].y=(double) (center.y+mid*sin(fmod((
double)
 
 7711              (theta.p+delta_theta),DegreesToRadians(360.0))));
 
 7714          stroke_q[q++]=box_q[2];
 
 7721      switch (draw_info->linejoin)
 
 7725          stroke_p[p++]=box_p[1];
 
 7726          stroke_p[p++]=box_p[2];
 
 7727          dot_product=(box_q[4].x-box_p[4].x)*(box_q[4].x-box_p[4].x)+
 
 7728            (box_q[4].y-box_p[4].y)*(box_q[4].y-box_p[4].y);
 
 7729          if (dot_product <= miterlimit)
 
 7730            stroke_q[q++]=box_q[4];
 
 7733              stroke_q[q++]=box_q[1];
 
 7734              stroke_q[q++]=box_q[2];
 
 7740          dot_product=(box_q[4].x-box_p[4].x)*(box_q[4].x-box_p[4].x)+
 
 7741            (box_q[4].y-box_p[4].y)*(box_q[4].y-box_p[4].y);
 
 7742          if (dot_product <= miterlimit)
 
 7744              stroke_q[q++]=box_q[4];
 
 7745              stroke_p[p++]=box_p[4];
 
 7749              stroke_q[q++]=box_q[1];
 
 7750              stroke_q[q++]=box_q[2];
 
 7751              stroke_p[p++]=box_p[1];
 
 7752              stroke_p[p++]=box_p[2];
 
 7758          dot_product=(box_q[4].x-box_p[4].x)*(box_q[4].x-box_p[4].x)+
 
 7759            (box_q[4].y-box_p[4].y)*(box_q[4].y-box_p[4].y);
 
 7760          if (dot_product <= miterlimit)
 
 7761            stroke_q[q++]=box_q[4];
 
 7764              stroke_q[q++]=box_q[1];
 
 7765              stroke_q[q++]=box_q[2];
 
 7767          center=polygon_primitive[n].point;
 
 7768          theta.p=atan2(box_p[1].y-center.y,box_p[1].x-center.x);
 
 7769          theta.q=atan2(box_p[2].y-center.y,box_p[2].x-center.x);
 
 7770          if (theta.p < theta.q)
 
 7771            theta.p+=2.0*MagickPI;
 
 7772          arc_segments=(size_t) CastDoubleToSsizeT(ceil((
double) ((theta.p-
 
 7773            theta.q)/(2.0*sqrt((
double) (MagickSafeReciprocal(mid)))))));
 
 7774          DisableMSCWarning(4127)
 
 7775          CheckPathExtent(arc_segments+MaxStrokePad,MaxStrokePad);
 
 7777          stroke_p[p++]=box_p[1];
 
 7778          for (j=1; j < (ssize_t) arc_segments; j++)
 
 7780            delta_theta=(double) (j*(theta.q-theta.p)/arc_segments);
 
 7781            stroke_p[p].x=(double) (center.x+mid*cos(fmod((
double)
 
 7782              (theta.p+delta_theta),DegreesToRadians(360.0))));
 
 7783            stroke_p[p].y=(double) (center.y+mid*sin(fmod((
double)
 
 7784              (theta.p+delta_theta),DegreesToRadians(360.0))));
 
 7787          stroke_p[p++]=box_p[2];
 
 7794    inverse_slope.p=inverse_slope.q;
 
 7803  stroke_p[p++]=box_p[1];
 
 7804  stroke_q[q++]=box_q[1];
 
 7808  stroke_polygon=(PrimitiveInfo *) AcquireQuantumMemory((
size_t)
 
 7809    (p+q+2L),(
size_t) (closed_path+2L)*
sizeof(*stroke_polygon));
 
 7810  if (stroke_polygon == (PrimitiveInfo *) NULL)
 
 7812      (void) ThrowMagickException(exception,GetMagickModule(),
 
 7813        ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
"");
 
 7814      stroke_p=(PointInfo *) RelinquishMagickMemory(stroke_p);
 
 7815      stroke_q=(PointInfo *) RelinquishMagickMemory(stroke_q);
 
 7816      polygon_primitive=(PrimitiveInfo *) RelinquishMagickMemory(
 
 7818      return(stroke_polygon);
 
 7820  for (i=0; i < (ssize_t) p; i++)
 
 7822    stroke_polygon[i]=polygon_primitive[0];
 
 7823    stroke_polygon[i].point=stroke_p[i];
 
 7825  if (closed_path != MagickFalse)
 
 7827      stroke_polygon[i]=polygon_primitive[0];
 
 7828      stroke_polygon[i].point=stroke_polygon[0].point;
 
 7831  for ( ; i < (ssize_t) (p+q+closed_path); i++)
 
 7833    stroke_polygon[i]=polygon_primitive[0];
 
 7834    stroke_polygon[i].point=stroke_q[p+q+closed_path-(i+1)];
 
 7836  if (closed_path != MagickFalse)
 
 7838      stroke_polygon[i]=polygon_primitive[0];
 
 7839      stroke_polygon[i].point=stroke_polygon[p+closed_path].point;
 
 7842  stroke_polygon[i]=polygon_primitive[0];
 
 7843  stroke_polygon[i].point=stroke_polygon[0].point;
 
 7845  stroke_polygon[i].primitive=UndefinedPrimitive;
 
 7846  stroke_polygon[0].coordinates=(size_t) (p+q+2*closed_path+1);
 
 7847  stroke_p=(PointInfo *) RelinquishMagickMemory(stroke_p);
 
 7848  stroke_q=(PointInfo *) RelinquishMagickMemory(stroke_q);
 
 7849  polygon_primitive=(PrimitiveInfo *) RelinquishMagickMemory(polygon_primitive);
 
 7850  return(stroke_polygon);