From: Cristy Date: Sat, 21 Apr 2018 18:45:52 +0000 (-0400) Subject: Support "use" element X-Git-Tag: 7.0.7-29~67 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d7e3659e6086e3abfafbf8e7efa2480d356c77a2;p=imagemagick Support "use" element --- diff --git a/MagickCore/draw.c b/MagickCore/draw.c index 13ae5509e..5d6a5220d 100644 --- a/MagickCore/draw.c +++ b/MagickCore/draw.c @@ -1691,7 +1691,7 @@ static size_t GetEllipseCoordinates(const PointInfo start,const PointInfo stop, return((size_t) floor((angle.y-angle.x)/step+0.5)+3); } -static char *GetGroupByID(const char *primitive,const char *id) +static char *GetNodeByID(const char *primitive,const char *id) { char *token; @@ -1719,8 +1719,9 @@ static char *GetGroupByID(const char *primitive,const char *id) n=0; start=(const char *) NULL; p=(const char *) NULL; - for (q=primitive; *q != '\0'; ) + for (q=primitive; (*q != '\0') && (length == 0); ) { + p=q; GetNextToken(q,&q,extent,token); if (*token == '\0') break; @@ -1742,12 +1743,12 @@ static char *GetGroupByID(const char *primitive,const char *id) /* End of group by ID. */ - length=(size_t) (q-start); + if (start != (const char *) NULL) + length=(size_t) (p-start); break; } n--; } - p=q; if (LocaleCompare("push",token) == 0) { GetNextToken(q,&q,extent,token); @@ -1763,13 +1764,13 @@ static char *GetGroupByID(const char *primitive,const char *id) Start of group by ID. */ n=0; - start=p; + start=q; } } } } } - if (length == 0) + if (start == (const char *) NULL) return((char *) NULL); (void) CopyMagickString(token,start,length); return(token); @@ -2993,6 +2994,34 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, status=MagickFalse; break; } + case 'u': + case 'U': + { + if (LocaleCompare("use",keyword) == 0) + { + char + *node; + + /* + Take a node from within the MVG document, and duplicate it here. + */ + GetNextToken(q,&q,extent,token); + node=GetNodeByID(primitive,token); + if (node != (char *) NULL) + { + DrawInfo + *clone_info; + + clone_info=CloneDrawInfo((ImageInfo *) NULL,graphic_context[n]); + (void) CloneString(&clone_info->primitive,node); + node=DestroyString(node); + status=DrawImage(image,clone_info,exception); + clone_info=DestroyDrawInfo(clone_info); + } + break; + } + break; + } case 'v': case 'V': { diff --git a/coders/svg.c b/coders/svg.c index 2546e47d3..8c2e7502b 100644 --- a/coders/svg.c +++ b/coders/svg.c @@ -786,6 +786,15 @@ static void SVGEndDocument(void *context) static void SVGStartElement(void *context,const xmlChar *name, const xmlChar **attributes) { +#define PushGraphicContext(id) \ +{ \ + if (*id == '\0') \ + (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); \ + else \ + (void) FormatLocaleFile(svg_info->file,"push graphic-context \"%s\"\n", \ + id); \ +} + char *color, background[MagickPathExtent], @@ -992,7 +1001,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"circle") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } if (LocaleCompare((const char *) name,"clipPath") == 0) @@ -1017,7 +1026,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"ellipse") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } break; @@ -1027,7 +1036,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"foreignObject") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } break; @@ -1037,7 +1046,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"g") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } break; @@ -1047,7 +1056,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"image") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } break; @@ -1057,7 +1066,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"line") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } if (LocaleCompare((const char *) name,"linearGradient") == 0) @@ -1075,7 +1084,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"path") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } if (LocaleCompare((const char *) name,"pattern") == 0) @@ -1088,12 +1097,12 @@ static void SVGStartElement(void *context,const xmlChar *name, } if (LocaleCompare((const char *) name,"polygon") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } if (LocaleCompare((const char *) name,"polyline") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } break; @@ -1112,7 +1121,7 @@ static void SVGStartElement(void *context,const xmlChar *name, } if (LocaleCompare((const char *) name,"rect") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); break; } break; @@ -1122,7 +1131,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"svg") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); (void) FormatLocaleFile(svg_info->file,"fill \"black\"\n"); (void) FormatLocaleFile(svg_info->file,"fill-opacity 1\n"); (void) FormatLocaleFile(svg_info->file,"stroke \"none\"\n"); @@ -1137,7 +1146,7 @@ static void SVGStartElement(void *context,const xmlChar *name, { if (LocaleCompare((const char *) name,"text") == 0) { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); svg_info->bounds.x=0.0; svg_info->bounds.y=0.0; svg_info->bounds.width=0.0; @@ -1172,7 +1181,17 @@ static void SVGStartElement(void *context,const xmlChar *name, draw_info=DestroyDrawInfo(draw_info); *svg_info->text='\0'; } - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); + break; + } + break; + } + case 'U': + case 'u': + { + if (LocaleCompare((char *) name,"use") == 0) + { + PushGraphicContext(id); break; } break; @@ -1513,7 +1532,10 @@ static void SVGStartElement(void *context,const xmlChar *name, } if (LocaleCompare(keyword,"href") == 0) { - (void) CloneString(&svg_info->url,value); + if (*value != '#') + (void) CloneString(&svg_info->url,value); + else + (void) CloneString(&svg_info->url,value+1); break; } break; @@ -2196,7 +2218,10 @@ static void SVGStartElement(void *context,const xmlChar *name, } if (LocaleCompare(keyword,"xlink:href") == 0) { - (void) CloneString(&svg_info->url,value); + if (*value != '#') + (void) CloneString(&svg_info->url,value); + else + (void) CloneString(&svg_info->url,value+1); break; } if (LocaleCompare(keyword,"x1") == 0) @@ -2273,7 +2298,7 @@ static void SVGStartElement(void *context,const xmlChar *name, sx,sy,tx,ty); if (*background != '\0') { - (void) FormatLocaleFile(svg_info->file,"push graphic-context\n"); + PushGraphicContext(id); (void) FormatLocaleFile(svg_info->file,"fill %s\n",background); (void) FormatLocaleFile(svg_info->file, "rectangle 0,0 %g,%g\n",svg_info->view_box.width, @@ -2566,6 +2591,20 @@ static void SVGEndElement(void *context,const xmlChar *name) } break; } + case 'U': + case 'u': + { + if (LocaleCompare((char *) name,"use") == 0) + { + if ((svg_info->bounds.x != 0.0) || (svg_info->bounds.y != 0.0)) + (void) FormatLocaleFile(svg_info->file,"translate %g,%g\n", + svg_info->bounds.x,svg_info->bounds.y); + (void) FormatLocaleFile(svg_info->file,"use \"%s\"\n",svg_info->url); + (void) FormatLocaleFile(svg_info->file,"pop graphic-context\n"); + break; + } + break; + } default: break; } @@ -3708,7 +3747,7 @@ static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) blob=(unsigned char *) RelinquishMagickMemory(blob); (void) FormatLocaleString(message,MagickPathExtent, " scene,(double) image->columns,(double) image->rows, (double) image->page.x,(double) image->page.y); (void) WriteBlobString(image,message); @@ -4817,7 +4856,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image, GetNextToken(q,&q,extent,token); (void) FormatLocaleString(message,MagickPathExtent, " \n",primitive_info[j].point.x, + "href=\"%s\"/>\n",primitive_info[j].point.x, primitive_info[j].point.y,primitive_info[j+1].point.x, primitive_info[j+1].point.y,token); (void) WriteBlobString(image,message);