PageRenderTime 73ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 1ms

/plugins/ImageMagick-6.3.2/coders/svg.c

https://bitbucket.org/sisko/operation-caribou
C | 4256 lines | 3759 code | 192 blank | 305 comment | 954 complexity | 52537d1ad8c6371a664884897946fa37 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. % %
  4. % %
  5. % %
  6. % SSSSS V V GGGG %
  7. % SS V V G %
  8. % SSS V V G GG %
  9. % SS V V G G %
  10. % SSSSS V GGG %
  11. % %
  12. % %
  13. % Read/Write Scalable Vector Graphics Format. %
  14. % %
  15. % Software Design %
  16. % John Cristy %
  17. % William Radcliffe %
  18. % March 2000 %
  19. % %
  20. % %
  21. % Copyright 1999-2006 ImageMagick Studio LLC, a non-profit organization %
  22. % dedicated to making software imaging solutions freely available. %
  23. % %
  24. % You may not use this file except in compliance with the License. You may %
  25. % obtain a copy of the License at %
  26. % %
  27. % http://www.imagemagick.org/script/license.php %
  28. % %
  29. % Unless required by applicable law or agreed to in writing, software %
  30. % distributed under the License is distributed on an "AS IS" BASIS, %
  31. % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
  32. % See the License for the specific language governing permissions and %
  33. % limitations under the License. %
  34. % %
  35. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  36. %
  37. %
  38. */
  39. /*
  40. Include declarations.
  41. */
  42. #include "magick/studio.h"
  43. #include "magick/annotate.h"
  44. #include "magick/blob.h"
  45. #include "magick/blob-private.h"
  46. #include "magick/constitute.h"
  47. #include "magick/composite-private.h"
  48. #include "magick/draw.h"
  49. #include "magick/exception.h"
  50. #include "magick/exception-private.h"
  51. #include "magick/gem.h"
  52. #include "magick/image.h"
  53. #include "magick/image-private.h"
  54. #include "magick/list.h"
  55. #include "magick/log.h"
  56. #include "magick/magick.h"
  57. #include "magick/memory_.h"
  58. #include "magick/quantum.h"
  59. #include "magick/property.h"
  60. #include "magick/resource_.h"
  61. #include "magick/static.h"
  62. #include "magick/string_.h"
  63. #include "magick/token.h"
  64. #include "magick/utility.h"
  65. #if defined(HasXML)
  66. # if defined(__WINDOWS__)
  67. # if defined(__MINGW32__)
  68. # define _MSC_VER
  69. # endif
  70. # include <win32config.h>
  71. # endif
  72. # include <libxml/parser.h>
  73. # include <libxml/xmlmemory.h>
  74. # include <libxml/parserInternals.h>
  75. # include <libxml/xmlerror.h>
  76. #endif
  77. #if defined(HasAUTOTRACE)
  78. #include "types.h"
  79. #include "image-header.h"
  80. #include "fit.h"
  81. #include "output.h"
  82. #include "pxl-outline.h"
  83. #include "atquantize.h"
  84. #include "thin-image.h"
  85. char
  86. *version_string = "AutoTrace version 0.24a";
  87. #endif
  88. #if defined(HasRSVG)
  89. #include "librsvg/rsvg.h"
  90. #endif
  91. /*
  92. Define declarations.
  93. */
  94. #define MVGPrintf (void) fprintf
  95. /*
  96. Typedef declarations.
  97. */
  98. typedef struct _BoundingBox
  99. {
  100. double
  101. x,
  102. y,
  103. width,
  104. height;
  105. } BoundingBox;
  106. typedef struct _ElementInfo
  107. {
  108. double
  109. cx,
  110. cy,
  111. major,
  112. minor,
  113. angle;
  114. } ElementInfo;
  115. typedef struct _SVGInfo
  116. {
  117. FILE
  118. *file;
  119. ExceptionInfo
  120. *exception;
  121. Image
  122. *image;
  123. const ImageInfo
  124. *image_info;
  125. AffineMatrix
  126. affine;
  127. unsigned long
  128. width,
  129. height;
  130. char
  131. *size,
  132. *title,
  133. *comment;
  134. int
  135. n;
  136. double
  137. *scale,
  138. pointsize;
  139. ElementInfo
  140. element;
  141. SegmentInfo
  142. segment;
  143. BoundingBox
  144. bounds,
  145. view_box;
  146. PointInfo
  147. radius;
  148. char
  149. *stop_color,
  150. *offset,
  151. *text,
  152. *vertices,
  153. *url;
  154. #if defined(HasXML)
  155. xmlParserCtxtPtr
  156. parser;
  157. xmlDocPtr
  158. document;
  159. #endif
  160. } SVGInfo;
  161. /*
  162. Forward declarations.
  163. */
  164. static MagickBooleanType
  165. WriteSVGImage(const ImageInfo *,Image *);
  166. /*
  167. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  168. % %
  169. % %
  170. % %
  171. % I s S V G %
  172. % %
  173. % %
  174. % %
  175. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  176. %
  177. % IsSVG()() returns MagickTrue if the image format type, identified by the
  178. % magick string, is SVG.
  179. %
  180. % The format of the ReadSVGImage method is:
  181. %
  182. % MagickBooleanType IsSVG(const unsigned char *magick,const size_t length)
  183. %
  184. % A description of each parameter follows:
  185. %
  186. % o magick: This string is generally the first few bytes of an image file
  187. % or blob.
  188. %
  189. % o length: Specifies the length of the magick string.
  190. %
  191. %
  192. */
  193. static MagickBooleanType IsSVG(const unsigned char *magick,const size_t length)
  194. {
  195. if (length < 4)
  196. return(MagickFalse);
  197. if (LocaleNCompare((char *) magick,"?xml",4) == 0)
  198. return(MagickTrue);
  199. return(MagickFalse);
  200. }
  201. #if defined(HasXML)
  202. /*
  203. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  204. % %
  205. % %
  206. % %
  207. % R e a d S V G I m a g e %
  208. % %
  209. % %
  210. % %
  211. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  212. %
  213. % ReadSVGImage() reads a Scalable Vector Gaphics file and returns it. It
  214. % allocates the memory necessary for the new Image structure and returns a
  215. % pointer to the new image.
  216. %
  217. % The format of the ReadSVGImage method is:
  218. %
  219. % Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
  220. %
  221. % A description of each parameter follows:
  222. %
  223. % o image_info: The image info.
  224. %
  225. % o exception: return any errors or warnings in this structure.
  226. %
  227. */
  228. static double GetUserSpaceCoordinateValue(const SVGInfo *svg_info,int type,
  229. const char *string)
  230. {
  231. char
  232. *p,
  233. token[MaxTextExtent];
  234. double
  235. value;
  236. (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",string);
  237. assert(string != (const char *) NULL);
  238. p=(char *) string;
  239. GetMagickToken(p,&p,token);
  240. value=atof(token);
  241. if (strchr(token,'%') != (char *) NULL)
  242. {
  243. double
  244. alpha,
  245. beta;
  246. if (type > 0)
  247. return(svg_info->view_box.width*value/100.0);
  248. if (type < 0)
  249. return(svg_info->view_box.height*value/100.0);
  250. alpha=value-svg_info->view_box.width;
  251. beta=value-svg_info->view_box.height;
  252. return(hypot(alpha,beta)/sqrt(2.0)/100.0);
  253. }
  254. GetMagickToken(p,&p,token);
  255. if (LocaleNCompare(token,"cm",2) == 0)
  256. return(DefaultResolution*svg_info->scale[0]/2.54*value);
  257. if (LocaleNCompare(token,"em",2) == 0)
  258. return(svg_info->pointsize*value);
  259. if (LocaleNCompare(token,"ex",2) == 0)
  260. return(svg_info->pointsize*value/2.0);
  261. if (LocaleNCompare(token,"in",2) == 0)
  262. return(DefaultResolution*svg_info->scale[0]*value);
  263. if (LocaleNCompare(token,"mm",2) == 0)
  264. return(DefaultResolution*svg_info->scale[0]/25.4*value);
  265. if (LocaleNCompare(token,"pc",2) == 0)
  266. return(DefaultResolution*svg_info->scale[0]/6.0*value);
  267. if (LocaleNCompare(token,"pt",2) == 0)
  268. return(svg_info->scale[0]*value);
  269. if (LocaleNCompare(token,"px",2) == 0)
  270. return(value);
  271. return(value);
  272. }
  273. static char **GetStyleTokens(void *context,const char *text,int *number_tokens)
  274. {
  275. char
  276. **tokens;
  277. register const char
  278. *p,
  279. *q;
  280. register long
  281. i;
  282. SVGInfo
  283. *svg_info;
  284. svg_info=(SVGInfo *) context;
  285. *number_tokens=0;
  286. if (text == (const char *) NULL)
  287. return((char **) NULL);
  288. /*
  289. Determine the number of arguments.
  290. */
  291. for (p=text; *p != '\0'; p++)
  292. if ((*p == ':') || (*p == ';'))
  293. (*number_tokens)++;
  294. tokens=(char **) AcquireMagickMemory((*number_tokens+2)*sizeof(*tokens));
  295. if (tokens == (char **) NULL)
  296. {
  297. (void) ThrowMagickException(svg_info->exception,GetMagickModule(),
  298. ResourceLimitError,"MemoryAllocationFailed","`%s'",text);
  299. return((char **) NULL);
  300. }
  301. /*
  302. Convert string to an ASCII list.
  303. */
  304. i=0;
  305. p=text;
  306. for (q=p; *q != '\0'; q++)
  307. {
  308. if ((*q != ':') && (*q != ';') && (*q != '\0'))
  309. continue;
  310. tokens[i]=AcquireString(p);
  311. (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1));
  312. StripString(tokens[i++]);
  313. p=q+1;
  314. }
  315. tokens[i]=AcquireString(p);
  316. (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1));
  317. StripString(tokens[i++]);
  318. tokens[i]=(char *) NULL;
  319. return(tokens);
  320. }
  321. static char **GetTransformTokens(void *context,const char *text,
  322. int *number_tokens)
  323. {
  324. char
  325. **tokens;
  326. register const char
  327. *p,
  328. *q;
  329. register long
  330. i;
  331. SVGInfo
  332. *svg_info;
  333. svg_info=(SVGInfo *) context;
  334. *number_tokens=0;
  335. if (text == (const char *) NULL)
  336. return((char **) NULL);
  337. /*
  338. Determine the number of arguments.
  339. */
  340. for (p=text; *p != '\0'; p++)
  341. {
  342. if (*p == '(')
  343. (*number_tokens)+=2;
  344. }
  345. tokens=(char **) AcquireMagickMemory((*number_tokens+2)*sizeof(*tokens));
  346. if (tokens == (char **) NULL)
  347. {
  348. (void) ThrowMagickException(svg_info->exception,GetMagickModule(),
  349. ResourceLimitError,"MemoryAllocationFailed","`%s'",text);
  350. return((char **) NULL);
  351. }
  352. /*
  353. Convert string to an ASCII list.
  354. */
  355. i=0;
  356. p=text;
  357. for (q=p; *q != '\0'; q++)
  358. {
  359. if ((*q != '(') && (*q != ')') && (*q != '\0'))
  360. continue;
  361. tokens[i]=AcquireString(p);
  362. (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1));
  363. StripString(tokens[i++]);
  364. p=q+1;
  365. }
  366. tokens[i]=AcquireString(p);
  367. (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1));
  368. StripString(tokens[i++]);
  369. tokens[i]=(char *) NULL;
  370. return(tokens);
  371. }
  372. #if defined(__cplusplus) || defined(c_plusplus)
  373. extern "C" {
  374. #endif
  375. static int SVGIsStandalone(void *context)
  376. {
  377. SVGInfo
  378. *svg_info;
  379. /*
  380. Is this document tagged standalone?
  381. */
  382. (void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.SVGIsStandalone()");
  383. svg_info=(SVGInfo *) context;
  384. return(svg_info->document->standalone == 1);
  385. }
  386. static int SVGHasInternalSubset(void *context)
  387. {
  388. SVGInfo
  389. *svg_info;
  390. /*
  391. Does this document has an internal subset?
  392. */
  393. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  394. " SAX.SVGHasInternalSubset()");
  395. svg_info=(SVGInfo *) context;
  396. return(svg_info->document->intSubset != NULL);
  397. }
  398. static int SVGHasExternalSubset(void *context)
  399. {
  400. SVGInfo
  401. *svg_info;
  402. /*
  403. Does this document has an external subset?
  404. */
  405. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  406. " SAX.SVGHasExternalSubset()");
  407. svg_info=(SVGInfo *) context;
  408. return(svg_info->document->extSubset != NULL);
  409. }
  410. static void SVGInternalSubset(void *context,const xmlChar *name,
  411. const xmlChar *external_id,const xmlChar *system_id)
  412. {
  413. SVGInfo
  414. *svg_info;
  415. /*
  416. Does this document has an internal subset?
  417. */
  418. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  419. " SAX.internalSubset(%s, %s, %s)",(char *) name,
  420. (external_id != (const xmlChar *) NULL ? (char *) external_id : "none"),
  421. (system_id != (const xmlChar *) NULL ? (char *) system_id : "none"));
  422. svg_info=(SVGInfo *) context;
  423. (void) xmlCreateIntSubset(svg_info->document,name,external_id,system_id);
  424. }
  425. static xmlParserInputPtr SVGResolveEntity(void *context,
  426. const xmlChar *public_id,const xmlChar *system_id)
  427. {
  428. SVGInfo
  429. *svg_info;
  430. xmlParserInputPtr
  431. stream;
  432. /*
  433. Special entity resolver, better left to the parser, it has more
  434. context than the application layer. The default behaviour is to
  435. not resolve the entities, in that case the ENTITY_REF nodes are
  436. built in the structure (and the parameter values).
  437. */
  438. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  439. " SAX.resolveEntity(%s, %s)",
  440. (public_id != (const xmlChar *) NULL ? (char *) public_id : "none"),
  441. (system_id != (const xmlChar *) NULL ? (char *) system_id : "none"));
  442. svg_info=(SVGInfo *) context;
  443. stream=xmlLoadExternalEntity((const char *) system_id,(const char *)
  444. public_id,svg_info->parser);
  445. return(stream);
  446. }
  447. static xmlEntityPtr SVGGetEntity(void *context,const xmlChar *name)
  448. {
  449. SVGInfo
  450. *svg_info;
  451. /*
  452. Get an entity by name.
  453. */
  454. (void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.SVGGetEntity(%s)",
  455. name);
  456. svg_info=(SVGInfo *) context;
  457. return(xmlGetDocEntity(svg_info->document,name));
  458. }
  459. static xmlEntityPtr SVGGetParameterEntity(void *context,const xmlChar *name)
  460. {
  461. SVGInfo
  462. *svg_info;
  463. /*
  464. Get a parameter entity by name.
  465. */
  466. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  467. " SAX.getParameterEntity(%s)",name);
  468. svg_info=(SVGInfo *) context;
  469. return(xmlGetParameterEntity(svg_info->document,name));
  470. }
  471. static void SVGEntityDeclaration(void *context,const xmlChar *name,int type,
  472. const xmlChar *public_id,const xmlChar *system_id,xmlChar *content)
  473. {
  474. SVGInfo
  475. *svg_info;
  476. /*
  477. An entity definition has been parsed.
  478. */
  479. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  480. " SAX.entityDecl(%s, %d, %s, %s, %s)",name,type,
  481. public_id != (xmlChar *) NULL ? (char *) public_id : "none",
  482. system_id != (xmlChar *) NULL ? (char *) system_id : "none",content);
  483. svg_info=(SVGInfo *) context;
  484. if (svg_info->parser->inSubset == 1)
  485. (void) xmlAddDocEntity(svg_info->document,name,type,public_id,system_id,
  486. content);
  487. else
  488. if (svg_info->parser->inSubset == 2)
  489. (void) xmlAddDtdEntity(svg_info->document,name,type,public_id,system_id,
  490. content);
  491. }
  492. static void SVGAttributeDeclaration(void *context,const xmlChar *element,
  493. const xmlChar *name,int type,int value,const xmlChar *default_value,
  494. xmlEnumerationPtr tree)
  495. {
  496. SVGInfo
  497. *svg_info;
  498. xmlChar
  499. *fullname,
  500. *prefix;
  501. xmlParserCtxtPtr
  502. parser;
  503. /*
  504. An attribute definition has been parsed.
  505. */
  506. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  507. " SAX.attributeDecl(%s, %s, %d, %d, %s, ...)",element,name,type,value,
  508. default_value);
  509. svg_info=(SVGInfo *) context;
  510. fullname=(xmlChar *) NULL;
  511. prefix=(xmlChar *) NULL;
  512. parser=svg_info->parser;
  513. fullname=(xmlChar *) xmlSplitQName(parser,name,&prefix);
  514. if (parser->inSubset == 1)
  515. (void) xmlAddAttributeDecl(&parser->vctxt,svg_info->document->intSubset,
  516. element,fullname,prefix,(xmlAttributeType) type,
  517. (xmlAttributeDefault) value,default_value,tree);
  518. else
  519. if (parser->inSubset == 2)
  520. (void) xmlAddAttributeDecl(&parser->vctxt,svg_info->document->extSubset,
  521. element,fullname,prefix,(xmlAttributeType) type,
  522. (xmlAttributeDefault) value,default_value,tree);
  523. if (prefix != (xmlChar *) NULL)
  524. xmlFree(prefix);
  525. if (fullname != (xmlChar *) NULL)
  526. xmlFree(fullname);
  527. }
  528. static void SVGElementDeclaration(void *context,const xmlChar *name,int type,
  529. xmlElementContentPtr content)
  530. {
  531. SVGInfo
  532. *svg_info;
  533. xmlParserCtxtPtr
  534. parser;
  535. /*
  536. An element definition has been parsed.
  537. */
  538. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  539. " SAX.elementDecl(%s, %d, ...)",name,type);
  540. svg_info=(SVGInfo *) context;
  541. parser=svg_info->parser;
  542. if (parser->inSubset == 1)
  543. (void) xmlAddElementDecl(&parser->vctxt,svg_info->document->intSubset,
  544. name,(xmlElementTypeVal) type,content);
  545. else
  546. if (parser->inSubset == 2)
  547. (void) xmlAddElementDecl(&parser->vctxt,svg_info->document->extSubset,
  548. name,(xmlElementTypeVal) type,content);
  549. }
  550. static void SVGNotationDeclaration(void *context,const xmlChar *name,
  551. const xmlChar *public_id,const xmlChar *system_id)
  552. {
  553. SVGInfo
  554. *svg_info;
  555. xmlParserCtxtPtr
  556. parser;
  557. /*
  558. What to do when a notation declaration has been parsed.
  559. */
  560. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  561. " SAX.notationDecl(%s, %s, %s)",name,
  562. public_id != (const xmlChar *) NULL ? (char *) public_id : "none",
  563. system_id != (const xmlChar *) NULL ? (char *) system_id : "none");
  564. svg_info=(SVGInfo *) context;
  565. parser=svg_info->parser;
  566. if (parser->inSubset == 1)
  567. (void) xmlAddNotationDecl(&parser->vctxt,svg_info->document->intSubset,
  568. name,public_id,system_id);
  569. else
  570. if (parser->inSubset == 2)
  571. (void) xmlAddNotationDecl(&parser->vctxt,svg_info->document->intSubset,
  572. name,public_id,system_id);
  573. }
  574. static void SVGUnparsedEntityDeclaration(void *context,const xmlChar *name,
  575. const xmlChar *public_id,const xmlChar *system_id,const xmlChar *notation)
  576. {
  577. SVGInfo
  578. *svg_info;
  579. /*
  580. What to do when an unparsed entity declaration is parsed.
  581. */
  582. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  583. " SAX.unparsedEntityDecl(%s, %s, %s, %s)",name,
  584. public_id != (xmlChar *) NULL ? (char *) public_id : "none",
  585. system_id != (xmlChar *) NULL ? (char *) system_id : "none",notation);
  586. svg_info=(SVGInfo *) context;
  587. (void) xmlAddDocEntity(svg_info->document,name,
  588. XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,public_id,system_id,notation);
  589. }
  590. static void SVGSetDocumentLocator(void *context,xmlSAXLocatorPtr location)
  591. {
  592. SVGInfo
  593. *svg_info;
  594. /*
  595. Receive the document locator at startup, actually xmlDefaultSAXLocator.
  596. */
  597. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  598. " SAX.setDocumentLocator()");
  599. svg_info=(SVGInfo *) context;
  600. }
  601. static void SVGStartDocument(void *context)
  602. {
  603. SVGInfo
  604. *svg_info;
  605. xmlParserCtxtPtr
  606. parser;
  607. /*
  608. Called when the document start being processed.
  609. */
  610. (void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.startDocument()");
  611. svg_info=(SVGInfo *) context;
  612. GetExceptionInfo(svg_info->exception);
  613. parser=svg_info->parser;
  614. svg_info->document=xmlNewDoc(parser->version);
  615. if (svg_info->document == (xmlDocPtr) NULL)
  616. return;
  617. if (parser->encoding == NULL)
  618. svg_info->document->encoding=(const xmlChar *) NULL;
  619. else
  620. svg_info->document->encoding=xmlStrdup(parser->encoding);
  621. svg_info->document->standalone=parser->standalone;
  622. }
  623. static void SVGEndDocument(void *context)
  624. {
  625. SVGInfo
  626. *svg_info;
  627. /*
  628. Called when the document end has been detected.
  629. */
  630. (void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.endDocument()");
  631. svg_info=(SVGInfo *) context;
  632. if (svg_info->offset != (char *) NULL)
  633. svg_info->offset=(char *) RelinquishMagickMemory(svg_info->offset);
  634. if (svg_info->stop_color != (char *) NULL)
  635. svg_info->stop_color=(char *) RelinquishMagickMemory(svg_info->stop_color);
  636. if (svg_info->scale != (double *) NULL)
  637. svg_info->scale=(double *) RelinquishMagickMemory(svg_info->scale);
  638. if (svg_info->text != (char *) NULL)
  639. svg_info->text=(char *) RelinquishMagickMemory(svg_info->text);
  640. if (svg_info->vertices != (char *) NULL)
  641. svg_info->vertices=(char *) RelinquishMagickMemory(svg_info->vertices);
  642. if (svg_info->url != (char *) NULL)
  643. svg_info->url=(char *) RelinquishMagickMemory(svg_info->url);
  644. #if defined(HasXML)
  645. if (svg_info->document != (xmlDocPtr) NULL)
  646. {
  647. xmlFreeDoc(svg_info->document);
  648. svg_info->document=(xmlDocPtr) NULL;
  649. }
  650. #endif
  651. }
  652. static void SVGStartElement(void *context,const xmlChar *name,
  653. const xmlChar **attributes)
  654. {
  655. char
  656. *color,
  657. id[MaxTextExtent],
  658. *p,
  659. token[MaxTextExtent],
  660. **tokens,
  661. *units;
  662. const char
  663. *keyword,
  664. *value;
  665. int
  666. number_tokens;
  667. SVGInfo
  668. *svg_info;
  669. register long
  670. i,
  671. j;
  672. /*
  673. Called when an opening tag has been processed.
  674. */
  675. (void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.startElement(%s",
  676. name);
  677. svg_info=(SVGInfo *) context;
  678. svg_info->n++;
  679. svg_info->scale=(double *) ResizeMagickMemory(svg_info->scale,
  680. (svg_info->n+1)*sizeof(*svg_info->scale));
  681. if (svg_info->scale == (double *) NULL)
  682. {
  683. (void) ThrowMagickException(svg_info->exception,GetMagickModule(),
  684. ResourceLimitError,"MemoryAllocationFailed","`%s'",name);
  685. return;
  686. }
  687. svg_info->scale[svg_info->n]=svg_info->scale[svg_info->n-1];
  688. color=AcquireString("none");
  689. units=AcquireString("userSpaceOnUse");
  690. value=(const char *) NULL;
  691. if (attributes != (const xmlChar **) NULL)
  692. for (i=0; (attributes[i] != (const xmlChar *) NULL); i+=2)
  693. {
  694. keyword=(const char *) attributes[i];
  695. value=(const char *) attributes[i+1];
  696. switch (*keyword)
  697. {
  698. case 'C':
  699. case 'c':
  700. {
  701. if (LocaleCompare(keyword,"cx") == 0)
  702. {
  703. svg_info->element.cx=
  704. GetUserSpaceCoordinateValue(svg_info,1,value);
  705. break;
  706. }
  707. if (LocaleCompare(keyword,"cy") == 0)
  708. {
  709. svg_info->element.cy=
  710. GetUserSpaceCoordinateValue(svg_info,-1,value);
  711. break;
  712. }
  713. break;
  714. }
  715. case 'F':
  716. case 'f':
  717. {
  718. if (LocaleCompare(keyword,"fx") == 0)
  719. {
  720. svg_info->element.major=
  721. GetUserSpaceCoordinateValue(svg_info,1,value);
  722. break;
  723. }
  724. if (LocaleCompare(keyword,"fy") == 0)
  725. {
  726. svg_info->element.minor=
  727. GetUserSpaceCoordinateValue(svg_info,-1,value);
  728. break;
  729. }
  730. break;
  731. }
  732. case 'H':
  733. case 'h':
  734. {
  735. if (LocaleCompare(keyword,"height") == 0)
  736. {
  737. svg_info->bounds.height=
  738. GetUserSpaceCoordinateValue(svg_info,-1,value);
  739. break;
  740. }
  741. break;
  742. }
  743. case 'I':
  744. case 'i':
  745. {
  746. if (LocaleCompare(keyword,"id") == 0)
  747. {
  748. (void) CopyMagickString(id,value,MaxTextExtent);
  749. break;
  750. }
  751. break;
  752. }
  753. case 'R':
  754. case 'r':
  755. {
  756. if (LocaleCompare(keyword,"r") == 0)
  757. {
  758. svg_info->element.angle=
  759. GetUserSpaceCoordinateValue(svg_info,0,value);
  760. break;
  761. }
  762. break;
  763. }
  764. case 'W':
  765. case 'w':
  766. {
  767. if (LocaleCompare(keyword,"width") == 0)
  768. {
  769. svg_info->bounds.width=
  770. GetUserSpaceCoordinateValue(svg_info,1,value);
  771. break;
  772. }
  773. break;
  774. }
  775. case 'X':
  776. case 'x':
  777. {
  778. if (LocaleCompare(keyword,"x") == 0)
  779. {
  780. svg_info->bounds.x=GetUserSpaceCoordinateValue(svg_info,1,value);
  781. break;
  782. }
  783. if (LocaleCompare(keyword,"x1") == 0)
  784. {
  785. svg_info->segment.x1=
  786. GetUserSpaceCoordinateValue(svg_info,1,value);
  787. break;
  788. }
  789. if (LocaleCompare(keyword,"x2") == 0)
  790. {
  791. svg_info->segment.x2=
  792. GetUserSpaceCoordinateValue(svg_info,1,value);
  793. break;
  794. }
  795. break;
  796. }
  797. case 'Y':
  798. case 'y':
  799. {
  800. if (LocaleCompare(keyword,"y") == 0)
  801. {
  802. svg_info->bounds.y=GetUserSpaceCoordinateValue(svg_info,-1,value);
  803. break;
  804. }
  805. if (LocaleCompare(keyword,"y1") == 0)
  806. {
  807. svg_info->segment.y1=
  808. GetUserSpaceCoordinateValue(svg_info,-1,value);
  809. break;
  810. }
  811. if (LocaleCompare(keyword,"y2") == 0)
  812. {
  813. svg_info->segment.y2=
  814. GetUserSpaceCoordinateValue(svg_info,-1,value);
  815. break;
  816. }
  817. break;
  818. }
  819. default:
  820. break;
  821. }
  822. }
  823. switch (*name)
  824. {
  825. case 'C':
  826. case 'c':
  827. {
  828. if (LocaleCompare((char *) name,"circle") == 0)
  829. {
  830. MVGPrintf(svg_info->file,"push graphic-context\n");
  831. break;
  832. }
  833. if (LocaleCompare((char *) name,"clipPath") == 0)
  834. {
  835. MVGPrintf(svg_info->file,"push clip-path '%s'\n",id);
  836. break;
  837. }
  838. break;
  839. }
  840. case 'D':
  841. case 'd':
  842. {
  843. if (LocaleCompare((char *) name,"defs") == 0)
  844. {
  845. MVGPrintf(svg_info->file,"push defs\n");
  846. break;
  847. }
  848. break;
  849. }
  850. case 'E':
  851. case 'e':
  852. {
  853. if (LocaleCompare((char *) name,"ellipse") == 0)
  854. {
  855. MVGPrintf(svg_info->file,"push graphic-context\n");
  856. break;
  857. }
  858. break;
  859. }
  860. case 'G':
  861. case 'g':
  862. {
  863. if (LocaleCompare((char *) name,"g") == 0)
  864. {
  865. MVGPrintf(svg_info->file,"push graphic-context\n");
  866. break;
  867. }
  868. break;
  869. }
  870. case 'I':
  871. case 'i':
  872. {
  873. if (LocaleCompare((char *) name,"image") == 0)
  874. {
  875. MVGPrintf(svg_info->file,"push graphic-context\n");
  876. break;
  877. }
  878. break;
  879. }
  880. case 'L':
  881. case 'l':
  882. {
  883. if (LocaleCompare((char *) name,"line") == 0)
  884. {
  885. MVGPrintf(svg_info->file,"push graphic-context\n");
  886. break;
  887. }
  888. if (LocaleCompare((char *) name,"linearGradient") == 0)
  889. {
  890. MVGPrintf(svg_info->file,"push gradient '%s' linear %g,%g %g,%g\n",id,
  891. svg_info->segment.x1,svg_info->segment.y1,svg_info->segment.x2,
  892. svg_info->segment.y2);
  893. break;
  894. }
  895. break;
  896. }
  897. case 'P':
  898. case 'p':
  899. {
  900. if (LocaleCompare((char *) name,"path") == 0)
  901. {
  902. MVGPrintf(svg_info->file,"push graphic-context\n");
  903. break;
  904. }
  905. if (LocaleCompare((char *) name,"pattern") == 0)
  906. {
  907. MVGPrintf(svg_info->file,"push pattern '%s' %g,%g %g,%g\n",id,
  908. svg_info->bounds.x,svg_info->bounds.y,svg_info->bounds.width,
  909. svg_info->bounds.height);
  910. break;
  911. }
  912. if (LocaleCompare((char *) name,"polygon") == 0)
  913. {
  914. MVGPrintf(svg_info->file,"push graphic-context\n");
  915. break;
  916. }
  917. if (LocaleCompare((char *) name,"polyline") == 0)
  918. {
  919. MVGPrintf(svg_info->file,"push graphic-context\n");
  920. break;
  921. }
  922. break;
  923. }
  924. case 'R':
  925. case 'r':
  926. {
  927. if (LocaleCompare((char *) name,"radialGradient") == 0)
  928. {
  929. MVGPrintf(svg_info->file,"push gradient '%s' radial %g,%g %g,%g %g\n",
  930. id,svg_info->element.cx,svg_info->element.cy,
  931. svg_info->element.major,svg_info->element.minor,
  932. svg_info->element.angle);
  933. break;
  934. }
  935. if (LocaleCompare((char *) name,"rect") == 0)
  936. {
  937. MVGPrintf(svg_info->file,"push graphic-context\n");
  938. break;
  939. }
  940. break;
  941. }
  942. case 'S':
  943. case 's':
  944. {
  945. if (LocaleCompare((char *) name,"svg") == 0)
  946. {
  947. MVGPrintf(svg_info->file,"push graphic-context\n");
  948. break;
  949. }
  950. break;
  951. }
  952. case 'T':
  953. case 't':
  954. {
  955. if (LocaleCompare((char *) name,"text") == 0)
  956. {
  957. MVGPrintf(svg_info->file,"push graphic-context\n");
  958. break;
  959. }
  960. if (LocaleCompare((char *) name,"tspan") == 0)
  961. {
  962. if (*svg_info->text != '\0')
  963. {
  964. DrawInfo
  965. *draw_info;
  966. TypeMetric
  967. metrics;
  968. char
  969. *text;
  970. text=EscapeString(svg_info->text,'\'');
  971. MVGPrintf(svg_info->file,"text %g,%g '%s'\n",svg_info->bounds.x,
  972. svg_info->bounds.y,text);
  973. text=(char *) RelinquishMagickMemory(text);
  974. draw_info=CloneDrawInfo(svg_info->image_info,(DrawInfo *) NULL);
  975. draw_info->pointsize=svg_info->pointsize;
  976. draw_info->text=AcquireString(svg_info->text);
  977. (void) ConcatenateString(&draw_info->text," ");
  978. GetTypeMetrics(svg_info->image,draw_info,&metrics);
  979. svg_info->bounds.x+=metrics.width;
  980. draw_info=DestroyDrawInfo(draw_info);
  981. *svg_info->text='\0';
  982. }
  983. MVGPrintf(svg_info->file,"push graphic-context\n");
  984. break;
  985. }
  986. break;
  987. }
  988. default:
  989. break;
  990. }
  991. if (attributes != (const xmlChar **) NULL)
  992. for (i=0; (attributes[i] != (const xmlChar *) NULL); i+=2)
  993. {
  994. keyword=(const char *) attributes[i];
  995. value=(const char *) attributes[i+1];
  996. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  997. " %s = %s",keyword,value);
  998. switch (*keyword)
  999. {
  1000. case 'A':
  1001. case 'a':
  1002. {
  1003. if (LocaleCompare(keyword,"angle") == 0)
  1004. {
  1005. MVGPrintf(svg_info->file,"angle %g\n",
  1006. GetUserSpaceCoordinateValue(svg_info,0,value));
  1007. break;
  1008. }
  1009. break;
  1010. }
  1011. case 'C':
  1012. case 'c':
  1013. {
  1014. if (LocaleCompare(keyword,"clip-path") == 0)
  1015. {
  1016. MVGPrintf(svg_info->file,"clip-path '%s'\n",value);
  1017. break;
  1018. }
  1019. if (LocaleCompare(keyword,"clip-rule") == 0)
  1020. {
  1021. MVGPrintf(svg_info->file,"clip-rule '%s'\n",value);
  1022. break;
  1023. }
  1024. if (LocaleCompare(keyword,"clipPathUnits") == 0)
  1025. {
  1026. (void) CloneString(&units,value);
  1027. MVGPrintf(svg_info->file,"clip-units '%s'\n",value);
  1028. break;
  1029. }
  1030. if (LocaleCompare(keyword,"color") == 0)
  1031. {
  1032. (void) CloneString(&color,value);
  1033. break;
  1034. }
  1035. if (LocaleCompare(keyword,"cx") == 0)
  1036. {
  1037. svg_info->element.cx=
  1038. GetUserSpaceCoordinateValue(svg_info,1,value);
  1039. break;
  1040. }
  1041. if (LocaleCompare(keyword,"cy") == 0)
  1042. {
  1043. svg_info->element.cy=
  1044. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1045. break;
  1046. }
  1047. break;
  1048. }
  1049. case 'D':
  1050. case 'd':
  1051. {
  1052. if (LocaleCompare(keyword,"d") == 0)
  1053. {
  1054. (void) CloneString(&svg_info->vertices,value);
  1055. break;
  1056. }
  1057. if (LocaleCompare(keyword,"dx") == 0)
  1058. {
  1059. svg_info->bounds.x+=
  1060. GetUserSpaceCoordinateValue(svg_info,1,value);
  1061. break;
  1062. }
  1063. if (LocaleCompare(keyword,"dy") == 0)
  1064. {
  1065. svg_info->bounds.y+=
  1066. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1067. break;
  1068. }
  1069. break;
  1070. }
  1071. case 'F':
  1072. case 'f':
  1073. {
  1074. if (LocaleCompare(keyword,"fill") == 0)
  1075. {
  1076. if (LocaleCompare(value,"currentColor") == 0)
  1077. {
  1078. MVGPrintf(svg_info->file,"fill '%s'\n",color);
  1079. break;
  1080. }
  1081. MVGPrintf(svg_info->file,"fill '%s'\n",value);
  1082. break;
  1083. }
  1084. if (LocaleCompare(keyword,"fillcolor") == 0)
  1085. {
  1086. MVGPrintf(svg_info->file,"fill '%s'\n",value);
  1087. break;
  1088. }
  1089. if (LocaleCompare(keyword,"fill-rule") == 0)
  1090. {
  1091. MVGPrintf(svg_info->file,"fill-rule '%s'\n",value);
  1092. break;
  1093. }
  1094. if (LocaleCompare(keyword,"fill-opacity") == 0)
  1095. {
  1096. MVGPrintf(svg_info->file,"fill-opacity '%s'\n",value);
  1097. break;
  1098. }
  1099. if (LocaleCompare(keyword,"font-family") == 0)
  1100. {
  1101. MVGPrintf(svg_info->file,"font-family '%s'\n",value);
  1102. break;
  1103. }
  1104. if (LocaleCompare(keyword,"font-stretch") == 0)
  1105. {
  1106. MVGPrintf(svg_info->file,"font-stretch '%s'\n",value);
  1107. break;
  1108. }
  1109. if (LocaleCompare(keyword,"font-style") == 0)
  1110. {
  1111. MVGPrintf(svg_info->file,"font-style '%s'\n",value);
  1112. break;
  1113. }
  1114. if (LocaleCompare(keyword,"font-size") == 0)
  1115. {
  1116. svg_info->pointsize=GetUserSpaceCoordinateValue(svg_info,0,value);
  1117. MVGPrintf(svg_info->file,"font-size %g\n",svg_info->pointsize);
  1118. break;
  1119. }
  1120. if (LocaleCompare(keyword,"font-weight") == 0)
  1121. {
  1122. MVGPrintf(svg_info->file,"font-weight '%s'\n",value);
  1123. break;
  1124. }
  1125. break;
  1126. }
  1127. case 'G':
  1128. case 'g':
  1129. {
  1130. if (LocaleCompare(keyword,"gradientTransform") == 0)
  1131. {
  1132. AffineMatrix
  1133. affine,
  1134. current,
  1135. transform;
  1136. GetAffineMatrix(&transform);
  1137. (void) LogMagickEvent(CoderEvent,GetMagickModule()," ");
  1138. tokens=GetTransformTokens(context,value,&number_tokens);
  1139. for (j=0; j < (number_tokens-1); j+=2)
  1140. {
  1141. keyword=(char *) tokens[j];
  1142. if (keyword == (char *) NULL)
  1143. continue;
  1144. value=(char *) tokens[j+1];
  1145. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  1146. " %s: %s",keyword,value);
  1147. current=transform;
  1148. GetAffineMatrix(&affine);
  1149. switch (*keyword)
  1150. {
  1151. case 'M':
  1152. case 'm':
  1153. {
  1154. if (LocaleCompare(keyword,"matrix") == 0)
  1155. {
  1156. p=(char *) value;
  1157. GetMagickToken(p,&p,token);
  1158. affine.sx=atof(value);
  1159. GetMagickToken(p,&p,token);
  1160. if (*token == ',')
  1161. GetMagickToken(p,&p,token);
  1162. affine.rx=atof(token);
  1163. GetMagickToken(p,&p,token);
  1164. if (*token == ',')
  1165. GetMagickToken(p,&p,token);
  1166. affine.ry=atof(token);
  1167. GetMagickToken(p,&p,token);
  1168. if (*token == ',')
  1169. GetMagickToken(p,&p,token);
  1170. affine.sy=atof(token);
  1171. GetMagickToken(p,&p,token);
  1172. if (*token == ',')
  1173. GetMagickToken(p,&p,token);
  1174. affine.tx=atof(token);
  1175. GetMagickToken(p,&p,token);
  1176. if (*token == ',')
  1177. GetMagickToken(p,&p,token);
  1178. affine.ty=atof(token);
  1179. break;
  1180. }
  1181. break;
  1182. }
  1183. case 'R':
  1184. case 'r':
  1185. {
  1186. if (LocaleCompare(keyword,"rotate") == 0)
  1187. {
  1188. double
  1189. angle;
  1190. angle=GetUserSpaceCoordinateValue(svg_info,0,value);
  1191. affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
  1192. affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
  1193. affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
  1194. affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
  1195. break;
  1196. }
  1197. break;
  1198. }
  1199. case 'S':
  1200. case 's':
  1201. {
  1202. if (LocaleCompare(keyword,"scale") == 0)
  1203. {
  1204. for (p=(char *) value; *p != '\0'; p++)
  1205. if ((isspace((int) ((unsigned char) *p)) != 0) ||
  1206. (*p == ','))
  1207. break;
  1208. affine.sx=GetUserSpaceCoordinateValue(svg_info,1,value);
  1209. affine.sy=affine.sx;
  1210. if (*p != '\0')
  1211. affine.sy=
  1212. GetUserSpaceCoordinateValue(svg_info,-1,p+1);
  1213. svg_info->scale[svg_info->n]=ExpandAffine(&affine);
  1214. break;
  1215. }
  1216. if (LocaleCompare(keyword,"skewX") == 0)
  1217. {
  1218. affine.sx=svg_info->affine.sx;
  1219. affine.ry=tan(DegreesToRadians(fmod(
  1220. GetUserSpaceCoordinateValue(svg_info,1,value),
  1221. 360.0)));
  1222. affine.sy=svg_info->affine.sy;
  1223. break;
  1224. }
  1225. if (LocaleCompare(keyword,"skewY") == 0)
  1226. {
  1227. affine.sx=svg_info->affine.sx;
  1228. affine.rx=tan(DegreesToRadians(fmod(
  1229. GetUserSpaceCoordinateValue(svg_info,-1,value),
  1230. 360.0)));
  1231. affine.sy=svg_info->affine.sy;
  1232. break;
  1233. }
  1234. break;
  1235. }
  1236. case 'T':
  1237. case 't':
  1238. {
  1239. if (LocaleCompare(keyword,"translate") == 0)
  1240. {
  1241. for (p=(char *) value; *p != '\0'; p++)
  1242. if ((isspace((int) ((unsigned char) *p)) != 0) ||
  1243. (*p == ','))
  1244. break;
  1245. affine.tx=GetUserSpaceCoordinateValue(svg_info,1,value);
  1246. affine.ty=affine.tx;
  1247. if (*p != '\0')
  1248. affine.ty=
  1249. GetUserSpaceCoordinateValue(svg_info,-1,p+1);
  1250. break;
  1251. }
  1252. break;
  1253. }
  1254. default:
  1255. break;
  1256. }
  1257. transform.sx=current.sx*affine.sx+current.ry*affine.rx;
  1258. transform.rx=current.rx*affine.sx+current.sy*affine.rx;
  1259. transform.ry=current.sx*affine.ry+current.ry*affine.sy;
  1260. transform.sy=current.rx*affine.ry+current.sy*affine.sy;
  1261. transform.tx=current.sx*affine.tx+current.ry*affine.ty+
  1262. current.tx;
  1263. transform.ty=current.rx*affine.tx+current.sy*affine.ty+
  1264. current.ty;
  1265. }
  1266. MVGPrintf(svg_info->file,"affine %g %g %g %g %g %g\n",
  1267. transform.sx,transform.rx,transform.ry,transform.sy,
  1268. transform.tx,transform.ty);
  1269. for (j=0; tokens[j] != (char *) NULL; j++)
  1270. tokens[j]=(char *) RelinquishMagickMemory(tokens[j]);
  1271. tokens=(char **) RelinquishMagickMemory(tokens);
  1272. break;
  1273. }
  1274. if (LocaleCompare(keyword,"gradientUnits") == 0)
  1275. {
  1276. (void) CloneString(&units,value);
  1277. MVGPrintf(svg_info->file,"gradient-units '%s'\n",value);
  1278. break;
  1279. }
  1280. break;
  1281. }
  1282. case 'H':
  1283. case 'h':
  1284. {
  1285. if (LocaleCompare(keyword,"height") == 0)
  1286. {
  1287. svg_info->bounds.height=
  1288. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1289. break;
  1290. }
  1291. if (LocaleCompare(keyword,"href") == 0)
  1292. {
  1293. (void) CloneString(&svg_info->url,value);
  1294. break;
  1295. }
  1296. break;
  1297. }
  1298. case 'M':
  1299. case 'm':
  1300. {
  1301. if (LocaleCompare(keyword,"major") == 0)
  1302. {
  1303. svg_info->element.major=
  1304. GetUserSpaceCoordinateValue(svg_info,1,value);
  1305. break;
  1306. }
  1307. if (LocaleCompare(keyword,"minor") == 0)
  1308. {
  1309. svg_info->element.minor=
  1310. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1311. break;
  1312. }
  1313. break;
  1314. }
  1315. case 'O':
  1316. case 'o':
  1317. {
  1318. if (LocaleCompare(keyword,"offset") == 0)
  1319. {
  1320. (void) CloneString(&svg_info->offset,value);
  1321. break;
  1322. }
  1323. if (LocaleCompare(keyword,"opacity") == 0)
  1324. {
  1325. MVGPrintf(svg_info->file,"opacity '%s'\n",value);
  1326. break;
  1327. }
  1328. break;
  1329. }
  1330. case 'P':
  1331. case 'p':
  1332. {
  1333. if (LocaleCompare(keyword,"path") == 0)
  1334. {
  1335. (void) CloneString(&svg_info->url,value);
  1336. break;
  1337. }
  1338. if (LocaleCompare(keyword,"points") == 0)
  1339. {
  1340. (void) CloneString(&svg_info->vertices,value);
  1341. break;
  1342. }
  1343. break;
  1344. }
  1345. case 'R':
  1346. case 'r':
  1347. {
  1348. if (LocaleCompare(keyword,"r") == 0)
  1349. {
  1350. svg_info->element.major=
  1351. GetUserSpaceCoordinateValue(svg_info,1,value);
  1352. svg_info->element.minor=
  1353. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1354. break;
  1355. }
  1356. if (LocaleCompare(keyword,"rotate") == 0)
  1357. {
  1358. double
  1359. angle;
  1360. angle=GetUserSpaceCoordinateValue(svg_info,0,value);
  1361. MVGPrintf(svg_info->file,"translate %g,%g\n",svg_info->bounds.x,
  1362. svg_info->bounds.y);
  1363. svg_info->bounds.x=0;
  1364. svg_info->bounds.y=0;
  1365. MVGPrintf(svg_info->file,"rotate %g\n",angle);
  1366. break;
  1367. }
  1368. if (LocaleCompare(keyword,"rx") == 0)
  1369. {
  1370. if (LocaleCompare((char *) name,"ellipse") == 0)
  1371. svg_info->element.major=
  1372. GetUserSpaceCoordinateValue(svg_info,1,value);
  1373. else
  1374. svg_info->radius.x=
  1375. GetUserSpaceCoordinateValue(svg_info,1,value);
  1376. break;
  1377. }
  1378. if (LocaleCompare(keyword,"ry") == 0)
  1379. {
  1380. if (LocaleCompare((char *) name,"ellipse") == 0)
  1381. svg_info->element.minor=
  1382. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1383. else
  1384. svg_info->radius.y=
  1385. GetUserSpaceCoordinateValue(svg_info,-1,value);
  1386. break;
  1387. }
  1388. break;
  1389. }
  1390. case 'S':
  1391. case 's':
  1392. {
  1393. if (LocaleCompare(keyword,"stop-color") == 0)
  1394. {
  1395. (void) CloneString(&svg_info->stop_color,value);
  1396. break;
  1397. }
  1398. if (LocaleCompare(keyword,"stroke") == 0)
  1399. {
  1400. if (LocaleCompare(value,"currentColor") == 0)
  1401. {
  1402. MVGPrintf(svg_info->file,"stroke '%s'\n",color);
  1403. break;
  1404. }
  1405. MVGPrintf(svg_info->file,"stroke '%s'\n",value);
  1406. break;
  1407. }
  1408. if (LocaleCompare(keyword,"stroke-antialiasing") == 0)
  1409. {
  1410. MVGPrintf(svg_info->file,"stroke-antialias %d\n",
  1411. LocaleCompare(value,"true") == 0);
  1412. break;
  1413. }
  1414. if (LocaleCompare(keyword,"stroke-dasharray") == 0)
  1415. {
  1416. MVGPrintf(svg_info->file,"stroke-dasharray %s\n",value);
  1417. break;
  1418. }
  1419. if (LocaleCompare(keyword,"stroke-dashoffset") == 0)
  1420. {
  1421. MVGPrintf(svg_info->file,"stroke-dashoffset %s\n",value);
  1422. break;
  1423. }
  1424. if (LocaleCompare(keyword,"stroke-linecap") == 0)
  1425. {
  1426. MVGPrintf(svg_info->file,"stroke-linecap '%s'\n",value);
  1427. break;
  1428. }
  1429. if (LocaleCompare(keyword,"stroke-linejoin") == 0)
  1430. {
  1431. MVGPrintf(svg_info->file,"stroke-linejoin '%s'\n",value);
  1432. break;
  1433. }
  1434. if (LocaleCompare(keyword,"stroke-miterlimit") == 0)
  1435. {
  1436. MVGPrintf(svg_info->file,"stroke-miterlimit '%s'\n",value);
  1437. break;
  1438. }
  1439. if (LocaleCompare(keyword,"stroke-opacity") == 0)
  1440. {
  1441. MVGPrintf(svg_info->file,"stroke-opacity '%s'\n",value);
  1442. break;
  1443. }
  1444. if (LocaleCompare(keyword,"stroke-width") == 0)
  1445. {
  1446. MVGPrintf(svg_info->file,"stroke-width %g\n",
  1447. GetUserSpaceCoordinateValue(svg_info,1,value));
  1448. break;
  1449. }
  1450. if (LocaleCompare(keyword,"style") == 0)
  1451. {
  1452. (void) LogMagickEvent(CoderEvent,GetMagickModule()," ");
  1453. tokens=GetStyleTokens(context,value,&number_tokens);
  1454. for (j=0; j < (number_tokens-1); j+=2)
  1455. {
  1456. keyword=(char *) tokens[j];
  1457. value=(char *) tokens[j+1];
  1458. (void) LogMagickEvent(CoderEvent,GetMagickModule(),
  1459. " %s: %s",keyword,value);
  1460. switch (*keyword)
  1461. {
  1462. case 'C':
  1463. case 'c':
  1464. {
  1465. if (LocaleCompare(keyword,"clip-path") == 0)
  1466. {
  1467. MVGPrintf(svg_info->file,"clip-path '%s'\n",value);
  1468. break;
  1469. }
  1470. if (LocaleCompare(keyword,"clip-rule") == 0)
  1471. {
  1472. MVGPrintf(svg_info->file,"clip-rule '%s'\n",value);
  1473. break;
  1474. }
  1475. if (LocaleCompare(keyword,"clipPathUnits") == 0)
  1476. {
  1477. (void) CloneString(&units,value);
  1478. MVGPrintf(svg_info->file,"clip-units '%s'\n",value);
  1479. break;
  1480. }
  1481. if (LocaleCompare(keyword,"color") == 0)
  1482. {
  1483. (void) CloneString(&color,value);
  1484. break;
  1485. }
  1486. break;
  1487. }
  1488. case 'F':
  1489. case 'f':
  1490. {
  1491. if (LocaleCompare(keyword,"fill") == 0)
  1492. {
  1493. if (LocaleCompare(value,"currentColor") == 0)
  1494. {
  1495. MVGPrintf(svg_info->file,"fill '%s'\n",color);
  1496. break;
  1497. }
  1498. MVGPrintf(svg_info->file,"fill '%s'\n",value);
  1499. break;
  1500. }
  1501. if (LocaleCompare(keyword,"fillcolor") == 0)
  1502. {
  1503. MVGPrintf(svg_info->file,"fill '%s'\n",value);
  1504. break;
  1505. }
  1506. if (LocaleCompare(keyword,"fill-rule") == 0)
  1507. {
  1508. MVGPrintf(svg_info->file,"fill-rule '%s'\n",value);
  1509. break;
  1510. }
  1511. if (LocaleCompare(keyword,"fill-opacity") == 0)
  1512. {
  1513. MVGPrintf(svg_info->file,"fill-opacity '%s'\n",value);
  1514. break;
  1515. }
  1516. if (LocaleCompare(keyword,"font-family") == 0)
  1517. {
  1518. MVGPrintf(svg_info->file,"font-family '%s'\n",value);
  1519. break;
  1520. }
  1521. if (LocaleCompare(keyword,"font-stretch") == 0)
  1522. {
  1523. MVGPrintf(svg_info->file,"font-stretch '%s'\n",value);
  1524. break;
  1525. }
  1526. if (LocaleCompare(keyword,"font-style") == 0)
  1527. {
  1528. MVGPrintf(svg_info->file,"font-style '%s'\n",value);
  1529. break;
  1530. }
  1531. if (LocaleCompare(keyword,"font-size") == 0)
  1532. {
  1533. svg_info->pointsize=GetUserSpaceCoordinateValue(
  1534. svg_info,0,value);
  1535. MVGPrintf(svg_info->file,"font-size %g\n",

Large files files are truncated, but you can click here to view the full file