PathParser.rl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. //
  2. // PathParser.rl
  3. //
  4. // Created by Marcus Rohrmoser on 11.03.10.
  5. // Copyright (c) 2010-2014, Marcus Rohrmoser mobile Software
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without modification, are permitted
  9. // provided that the following conditions are met:
  10. //
  11. // 1. Redistributions of source code must retain the above copyright notice, this list of conditions
  12. // and the following disclaimer.
  13. //
  14. // 2. The software must not be used for military or intelligence or related purposes nor
  15. // anything that's in conflict with human rights as declared in http://www.un.org/en/documents/udhr/ .
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  18. // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  19. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  20. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  23. // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  24. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. //
  26. //
  27. #import "PathParser.h"
  28. #import "PathBuilder.h"
  29. #ifdef MRLogD
  30. #undef MRLogD
  31. #undef MRLogTStart
  32. #endif
  33. // No Logging
  34. #define MRLogD(x,...)
  35. #define MRLogTStart()
  36. static inline double strltod(const char *restrict nptr, char **restrict endptr, const size_t size)
  37. {
  38. char push_number_tmp[size];
  39. // push_number_tmp[len] = '\0';
  40. strlcpy(push_number_tmp, nptr, size);
  41. assert(push_number_tmp[size-1] == '\0' && "must be NUL terminated");
  42. return strtod(push_number_tmp, endptr);
  43. }
  44. /** <a href="http://www.complang.org/ragel/">Ragel</a> parser
  45. * for <a href="http://www.w3.org/TR/SVG11/paths.html#PathDataBNF">paths</a>
  46. * This file is auto-generated
  47. * <p>
  48. * DO NOT EDIT MANUALLY!!!
  49. * </p>
  50. * See also https://lib2geom.svn.sourceforge.net/svnroot/lib2geom/lib2geom/trunk/src/2geom/svg-path-parser.rl
  51. */
  52. @implementation PathParser
  53. #pragma clang diagnostic push
  54. #pragma clang diagnostic ignored "-Wunused-const-variable"
  55. %%{
  56. machine path;
  57. #######################################################
  58. ## Define the actions
  59. #######################################################
  60. action start_number {
  61. start = p;
  62. }
  63. action push_number {
  64. assert(p >= start && "must be positive size");
  65. argv[argc++] = strltod(start, NULL, p-start);
  66. start = NULL;
  67. }
  68. action push_true {
  69. if(YES)
  70. [NSException raise:@"ragel action push_true isn't implemented yet." format:@""];
  71. }
  72. action push_false {
  73. if(YES)
  74. [NSException raise:@"ragel action push_false isn't implemented yet." format:@""];
  75. }
  76. action mode_abs {
  77. absolute = YES;
  78. }
  79. action mode_rel {
  80. absolute = NO;
  81. }
  82. action moveto {
  83. [pb moveToAbsolute:absolute x:argv[0] y:argv[1]];
  84. argc = 0;
  85. }
  86. action lineto {
  87. [pb lineToAbsolute:absolute x:argv[0] y:argv[1]];
  88. argc = 0;
  89. }
  90. action horizontal_lineto {
  91. [pb hlineToAbsolute:absolute x:argv[0]];
  92. argc = 0;
  93. }
  94. action vertical_lineto {
  95. [pb vlineToAbsolute:absolute y:argv[0]];
  96. argc = 0;
  97. }
  98. action curveto {
  99. [pb cubicToAbsolute:absolute x1:argv[0] y1:argv[1] x2:argv[2] y2:argv[3] x3:argv[4] y3:argv[5] ];
  100. argc = 0;
  101. }
  102. action smooth_curveto {
  103. [pb smoothCubicToAbsolute:absolute x2:argv[0] y2:argv[1] x3:argv[2] y3:argv[3] ];
  104. argc = 0;
  105. }
  106. action quadratic_bezier_curveto {
  107. [pb quadToAbsolute:absolute x1:argv[0] y1:argv[1] x2:argv[2] y2:argv[3] ];
  108. argc = 0;
  109. }
  110. action smooth_quadratic_bezier_curveto {
  111. [pb smoothQuadToAbsolute:absolute x2:argv[0] y2:argv[1] ];
  112. argc = 0;
  113. }
  114. action elliptical_arc {
  115. if(YES)
  116. [NSException raise:@"ragel action elliptical_arc isn't implemented yet." format:@""];
  117. argc = 0;
  118. }
  119. action closepath {
  120. [pb closePath];
  121. }
  122. #######################################################
  123. ## Define the grammar
  124. #######################################################
  125. wsp = (' ' | 9 | 10 | 13);
  126. sign = ('+' | '-');
  127. digit_sequence = digit+;
  128. exponent = ('e' | 'E') sign? digit_sequence;
  129. fractional_constant =
  130. digit_sequence? '.' digit_sequence
  131. | digit_sequence '.';
  132. floating_point_constant =
  133. fractional_constant exponent?
  134. | digit_sequence exponent;
  135. integer_constant = digit_sequence;
  136. comma = ',';
  137. comma_wsp = (wsp+ comma? wsp*) | (comma wsp*);
  138. flag = ('0' %push_false | '1' %push_true);
  139. number =
  140. ( sign? integer_constant
  141. | sign? floating_point_constant )
  142. >start_number %push_number;
  143. nonnegative_number =
  144. ( integer_constant
  145. | floating_point_constant)
  146. >start_number %push_number;
  147. coordinate = number $(number,1) %(number,0);
  148. coordinate_pair = (coordinate $(coordinate_pair_a,1) %(coordinate_pair_a,0) comma_wsp? coordinate $(coordinate_pair_b,1) %(coordinate_pair_b,0)) $(coordinate_pair,1) %(coordinate_pair,0);
  149. elliptical_arc_argument =
  150. (nonnegative_number $(elliptical_arg_a,1) %(elliptical_arg_a,0) comma_wsp?
  151. nonnegative_number $(elliptical_arg_b,1) %(elliptical_arg_b,0) comma_wsp?
  152. number comma_wsp
  153. flag comma_wsp flag comma_wsp
  154. coordinate_pair)
  155. %elliptical_arc;
  156. elliptical_arc_argument_sequence =
  157. elliptical_arc_argument $1 %0
  158. (comma_wsp? elliptical_arc_argument $1 %0)*;
  159. elliptical_arc =
  160. ('A' %mode_abs| 'a' %mode_rel) wsp*
  161. elliptical_arc_argument_sequence;
  162. smooth_quadratic_bezier_curveto_argument =
  163. coordinate_pair %smooth_quadratic_bezier_curveto;
  164. smooth_quadratic_bezier_curveto_argument_sequence =
  165. smooth_quadratic_bezier_curveto_argument $1 %0
  166. (comma_wsp?
  167. smooth_quadratic_bezier_curveto_argument $1 %0)*;
  168. smooth_quadratic_bezier_curveto =
  169. ('T' %mode_abs| 't' %mode_rel) wsp*
  170. smooth_quadratic_bezier_curveto_argument_sequence;
  171. quadratic_bezier_curveto_argument =
  172. (coordinate_pair $1 %0 comma_wsp? coordinate_pair)
  173. %quadratic_bezier_curveto;
  174. quadratic_bezier_curveto_argument_sequence =
  175. quadratic_bezier_curveto_argument $1 %0
  176. (comma_wsp? quadratic_bezier_curveto_argument $1 %0)*;
  177. quadratic_bezier_curveto =
  178. ('Q' %mode_abs| 'q' %mode_rel) wsp*
  179. quadratic_bezier_curveto_argument_sequence;
  180. smooth_curveto_argument =
  181. (coordinate_pair $1 %0 comma_wsp? coordinate_pair)
  182. %smooth_curveto;
  183. smooth_curveto_argument_sequence =
  184. smooth_curveto_argument $1 %0
  185. (comma_wsp? smooth_curveto_argument $1 %0)*;
  186. smooth_curveto =
  187. ('S' %mode_abs| 's' %mode_rel)
  188. wsp* smooth_curveto_argument_sequence;
  189. curveto_argument =
  190. (coordinate_pair $1 %0 comma_wsp?
  191. coordinate_pair $1 %0 comma_wsp?
  192. coordinate_pair)
  193. %curveto;
  194. curveto_argument_sequence =
  195. curveto_argument $1 %0
  196. (comma_wsp? curveto_argument $1 %0)*;
  197. curveto =
  198. ('C' %mode_abs| 'c' %mode_rel)
  199. wsp* curveto_argument_sequence;
  200. vertical_lineto_argument = coordinate %vertical_lineto;
  201. vertical_lineto_argument_sequence =
  202. vertical_lineto_argument $(vertical_lineto_argument_a,1) %(vertical_lineto_argument_a,0)
  203. (comma_wsp? vertical_lineto_argument $(vertical_lineto_argument_b,1) %(vertical_lineto_argument_b,0))*;
  204. vertical_lineto =
  205. ('V' %mode_abs| 'v' %mode_rel)
  206. wsp* vertical_lineto_argument_sequence;
  207. horizontal_lineto_argument = coordinate %horizontal_lineto;
  208. horizontal_lineto_argument_sequence =
  209. horizontal_lineto_argument $(horizontal_lineto_argument_a,1) %(horizontal_lineto_argument_a,0)
  210. (comma_wsp? horizontal_lineto_argument $(horizontal_lineto_argument_b,1) %(horizontal_lineto_argument_b,0))*;
  211. horizontal_lineto =
  212. ('H' %mode_abs| 'h' %mode_rel)
  213. wsp* horizontal_lineto_argument_sequence;
  214. lineto_argument = coordinate_pair %lineto;
  215. lineto_argument_sequence =
  216. lineto_argument $1 %0
  217. (comma_wsp? lineto_argument $1 %0)*;
  218. lineto =
  219. ('L' %mode_abs| 'l' %mode_rel) wsp*
  220. lineto_argument_sequence;
  221. closepath = ('Z' | 'z') %closepath;
  222. moveto_argument = coordinate_pair %moveto;
  223. moveto_argument_sequence =
  224. moveto_argument $1 %0
  225. (comma_wsp? lineto_argument $1 %0)*;
  226. moveto =
  227. ('M' %mode_abs | 'm' %mode_rel)
  228. wsp* moveto_argument_sequence;
  229. drawto_command =
  230. closepath | lineto |
  231. horizontal_lineto | vertical_lineto |
  232. curveto | smooth_curveto |
  233. quadratic_bezier_curveto |
  234. smooth_quadratic_bezier_curveto |
  235. elliptical_arc;
  236. drawto_commands = drawto_command (wsp* drawto_command)*;
  237. moveto_drawto_command_group = moveto wsp* drawto_commands?;
  238. moveto_drawto_command_groups =
  239. moveto_drawto_command_group
  240. (wsp* moveto_drawto_command_group)*;
  241. svg_path = wsp* moveto_drawto_command_groups? wsp*;
  242. main := svg_path;
  243. }%%
  244. %% write data;
  245. -(CGPathRef)newCGPathWithCString:(const char*)data length:(const size_t)length trafo:(const CGAffineTransform*)trafo error:(NSError**)errPtr
  246. {
  247. MRLogTStart();
  248. PathBuilder *pb = [[PathBuilder alloc] initWithTrafo:trafo];
  249. if(data == NULL)
  250. return CGPathRetain([pb toPath]);
  251. // high-level buffers
  252. const char *start = NULL;
  253. CGFloat argv[] = {0,1,2,3,4,5,6,7};
  254. int argc = 0;
  255. BOOL absolute = YES;
  256. // ragel variables (low level)
  257. const char *p = data;
  258. const char *pe = data + length; // pointer "end"
  259. const char *eof = pe;
  260. int cs = 0;
  261. // int top;
  262. ///////////////////////////////////////////////////////////
  263. // init ragel
  264. %% write init;
  265. ///////////////////////////////////////////////////////////
  266. // exec ragel
  267. %% write exec;
  268. if ( errPtr != nil && cs < path_first_final )
  269. *errPtr = [self parseError:data position:p];
  270. MRLogT(@"", nil);
  271. return CGPathRetain([pb toPath]);
  272. }
  273. -(CGPathRef)newCGPathWithNSString:(NSString*)data trafo:(const CGAffineTransform*)trafo error:(NSError**)errPtr
  274. {
  275. const char *c = [data UTF8String];
  276. return [self newCGPathWithCString:c length:strlen(c) trafo:trafo error:errPtr];
  277. }
  278. #pragma clang diagnostic pop
  279. @end