@simonklee/opentui-tex-native-source 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. package/LICENSE +674 -0
  2. package/LICENSE-PROJECT +21 -0
  3. package/README.md +7 -0
  4. package/build.zig +112 -0
  5. package/build.zig.zon +12 -0
  6. package/native/lib.zig +280 -0
  7. package/native/nanosvg.c +4 -0
  8. package/native/vendor/.bootstrap-v5 +1 -0
  9. package/native/vendor/LICENSE-NANOSVG +18 -0
  10. package/native/vendor/microtex/.clang-format +26 -0
  11. package/native/vendor/microtex/.github/workflows/ubuntu.yml +92 -0
  12. package/native/vendor/microtex/.github/workflows/windows-gdi.yml +34 -0
  13. package/native/vendor/microtex/.github/workflows/windows-qt.yml +52 -0
  14. package/native/vendor/microtex/CMakeLists.txt +110 -0
  15. package/native/vendor/microtex/LICENSE +21 -0
  16. package/native/vendor/microtex/MicroTeXInstall.cmake +42 -0
  17. package/native/vendor/microtex/README.md +600 -0
  18. package/native/vendor/microtex/build.zig +209 -0
  19. package/native/vendor/microtex/clatexmath.wrap +6 -0
  20. package/native/vendor/microtex/doc/meson.build +38 -0
  21. package/native/vendor/microtex/doc/microtex-doc.toml.in +47 -0
  22. package/native/vendor/microtex/doc/microtex.svg +39 -0
  23. package/native/vendor/microtex/doc/urlmap.js +6 -0
  24. package/native/vendor/microtex/example/gtk/CMakeLists.txt +68 -0
  25. package/native/vendor/microtex/example/gtk/gtk_main.c +170 -0
  26. package/native/vendor/microtex/example/gtk/isamples.cpp +21 -0
  27. package/native/vendor/microtex/example/gtk/isamples.h +15 -0
  28. package/native/vendor/microtex/example/gtk/meson.build +27 -0
  29. package/native/vendor/microtex/example/gtk/microtex-gtk.gresource.xml +6 -0
  30. package/native/vendor/microtex/example/gtk/microtex-gtk.ui +117 -0
  31. package/native/vendor/microtex/example/gtkmm/CMakeLists.txt +19 -0
  32. package/native/vendor/microtex/example/gtkmm/gtkmm_main.cpp +531 -0
  33. package/native/vendor/microtex/example/gtkmm/meson.build +19 -0
  34. package/native/vendor/microtex/example/memcheck/CMakeLists.txt +12 -0
  35. package/native/vendor/microtex/example/memcheck/mem_check_main.cpp +154 -0
  36. package/native/vendor/microtex/example/qt/CMakeLists.txt +37 -0
  37. package/native/vendor/microtex/example/qt/meson.build +25 -0
  38. package/native/vendor/microtex/example/qt/qt_main.cpp +70 -0
  39. package/native/vendor/microtex/example/qt/qt_mainwindow.cpp +107 -0
  40. package/native/vendor/microtex/example/qt/qt_mainwindow.h +40 -0
  41. package/native/vendor/microtex/example/qt/qt_skiatexwidget.cpp +149 -0
  42. package/native/vendor/microtex/example/qt/qt_skiatexwidget.h +48 -0
  43. package/native/vendor/microtex/example/qt/qt_tex_render.h +15 -0
  44. package/native/vendor/microtex/example/qt/qt_texqmlitem.cpp +56 -0
  45. package/native/vendor/microtex/example/qt/qt_texqmlitem.h +31 -0
  46. package/native/vendor/microtex/example/qt/qt_texwidget.cpp +62 -0
  47. package/native/vendor/microtex/example/qt/qt_texwidget.h +31 -0
  48. package/native/vendor/microtex/example/qtpng/CMakeLists.txt +11 -0
  49. package/native/vendor/microtex/example/qtpng/latex2png.cpp +115 -0
  50. package/native/vendor/microtex/example/samples/samples.cpp +52 -0
  51. package/native/vendor/microtex/example/samples/samples.h +32 -0
  52. package/native/vendor/microtex/example/win32/CMakeLists.txt +15 -0
  53. package/native/vendor/microtex/example/win32/meson.build +18 -0
  54. package/native/vendor/microtex/example/win32/win32_main.cpp +375 -0
  55. package/native/vendor/microtex/githooks/pre-commit +19 -0
  56. package/native/vendor/microtex/githooks/pre-push +103 -0
  57. package/native/vendor/microtex/lib/CMakeLists.txt +234 -0
  58. package/native/vendor/microtex/lib/atom/atom.cpp +14 -0
  59. package/native/vendor/microtex/lib/atom/atom.h +96 -0
  60. package/native/vendor/microtex/lib/atom/atom_accent.cpp +115 -0
  61. package/native/vendor/microtex/lib/atom/atom_accent.h +53 -0
  62. package/native/vendor/microtex/lib/atom/atom_basic.cpp +146 -0
  63. package/native/vendor/microtex/lib/atom/atom_basic.h +273 -0
  64. package/native/vendor/microtex/lib/atom/atom_box.cpp +41 -0
  65. package/native/vendor/microtex/lib/atom/atom_box.h +70 -0
  66. package/native/vendor/microtex/lib/atom/atom_char.cpp +99 -0
  67. package/native/vendor/microtex/lib/atom/atom_char.h +147 -0
  68. package/native/vendor/microtex/lib/atom/atom_delim.cpp +65 -0
  69. package/native/vendor/microtex/lib/atom/atom_delim.h +58 -0
  70. package/native/vendor/microtex/lib/atom/atom_fence.cpp +65 -0
  71. package/native/vendor/microtex/lib/atom/atom_fence.h +56 -0
  72. package/native/vendor/microtex/lib/atom/atom_font.cpp +20 -0
  73. package/native/vendor/microtex/lib/atom/atom_font.h +49 -0
  74. package/native/vendor/microtex/lib/atom/atom_frac.cpp +101 -0
  75. package/native/vendor/microtex/lib/atom/atom_frac.h +42 -0
  76. package/native/vendor/microtex/lib/atom/atom_matrix.cpp +756 -0
  77. package/native/vendor/microtex/lib/atom/atom_matrix.h +268 -0
  78. package/native/vendor/microtex/lib/atom/atom_misc.cpp +230 -0
  79. package/native/vendor/microtex/lib/atom/atom_misc.h +200 -0
  80. package/native/vendor/microtex/lib/atom/atom_operator.cpp +51 -0
  81. package/native/vendor/microtex/lib/atom/atom_operator.h +41 -0
  82. package/native/vendor/microtex/lib/atom/atom_root.cpp +61 -0
  83. package/native/vendor/microtex/lib/atom/atom_root.h +27 -0
  84. package/native/vendor/microtex/lib/atom/atom_row.cpp +334 -0
  85. package/native/vendor/microtex/lib/atom/atom_row.h +176 -0
  86. package/native/vendor/microtex/lib/atom/atom_scripts.cpp +182 -0
  87. package/native/vendor/microtex/lib/atom/atom_scripts.h +52 -0
  88. package/native/vendor/microtex/lib/atom/atom_sideset.cpp +92 -0
  89. package/native/vendor/microtex/lib/atom/atom_sideset.h +24 -0
  90. package/native/vendor/microtex/lib/atom/atom_space.cpp +22 -0
  91. package/native/vendor/microtex/lib/atom/atom_space.h +38 -0
  92. package/native/vendor/microtex/lib/atom/atom_stack.cpp +117 -0
  93. package/native/vendor/microtex/lib/atom/atom_stack.h +103 -0
  94. package/native/vendor/microtex/lib/atom/atom_text.cpp +17 -0
  95. package/native/vendor/microtex/lib/atom/atom_text.h +33 -0
  96. package/native/vendor/microtex/lib/atom/atom_vrow.cpp +96 -0
  97. package/native/vendor/microtex/lib/atom/atom_vrow.h +47 -0
  98. package/native/vendor/microtex/lib/atom/atom_zstack.cpp +66 -0
  99. package/native/vendor/microtex/lib/atom/atom_zstack.h +37 -0
  100. package/native/vendor/microtex/lib/atom/colors_def.cpp +157 -0
  101. package/native/vendor/microtex/lib/atom/meson.build +50 -0
  102. package/native/vendor/microtex/lib/box/box.cpp +49 -0
  103. package/native/vendor/microtex/lib/box/box.h +184 -0
  104. package/native/vendor/microtex/lib/box/box_factory.cpp +162 -0
  105. package/native/vendor/microtex/lib/box/box_factory.h +24 -0
  106. package/native/vendor/microtex/lib/box/box_group.cpp +503 -0
  107. package/native/vendor/microtex/lib/box/box_group.h +285 -0
  108. package/native/vendor/microtex/lib/box/box_single.cpp +179 -0
  109. package/native/vendor/microtex/lib/box/box_single.h +157 -0
  110. package/native/vendor/microtex/lib/box/meson.build +15 -0
  111. package/native/vendor/microtex/lib/core/debug_config.cpp +3 -0
  112. package/native/vendor/microtex/lib/core/debug_config.h +24 -0
  113. package/native/vendor/microtex/lib/core/formula.cpp +180 -0
  114. package/native/vendor/microtex/lib/core/formula.h +137 -0
  115. package/native/vendor/microtex/lib/core/formula_def.cpp +167 -0
  116. package/native/vendor/microtex/lib/core/glue.cpp +108 -0
  117. package/native/vendor/microtex/lib/core/glue.h +55 -0
  118. package/native/vendor/microtex/lib/core/localized_num.cpp +51 -0
  119. package/native/vendor/microtex/lib/core/meson.build +19 -0
  120. package/native/vendor/microtex/lib/core/parser.cpp +874 -0
  121. package/native/vendor/microtex/lib/core/parser.h +306 -0
  122. package/native/vendor/microtex/lib/core/split.cpp +185 -0
  123. package/native/vendor/microtex/lib/core/split.h +40 -0
  124. package/native/vendor/microtex/lib/env/env.cpp +141 -0
  125. package/native/vendor/microtex/lib/env/env.h +221 -0
  126. package/native/vendor/microtex/lib/env/meson.build +11 -0
  127. package/native/vendor/microtex/lib/env/units.cpp +109 -0
  128. package/native/vendor/microtex/lib/env/units.h +61 -0
  129. package/native/vendor/microtex/lib/graphic/font_style.cpp +63 -0
  130. package/native/vendor/microtex/lib/graphic/font_style.h +61 -0
  131. package/native/vendor/microtex/lib/graphic/graphic.cpp +38 -0
  132. package/native/vendor/microtex/lib/graphic/graphic.h +314 -0
  133. package/native/vendor/microtex/lib/graphic/graphic_basic.cpp +44 -0
  134. package/native/vendor/microtex/lib/graphic/graphic_basic.h +131 -0
  135. package/native/vendor/microtex/lib/graphic/meson.build +13 -0
  136. package/native/vendor/microtex/lib/macro/macro.cpp +143 -0
  137. package/native/vendor/microtex/lib/macro/macro.h +155 -0
  138. package/native/vendor/microtex/lib/macro/macro_accent.cpp +50 -0
  139. package/native/vendor/microtex/lib/macro/macro_accent.h +61 -0
  140. package/native/vendor/microtex/lib/macro/macro_boxes.h +68 -0
  141. package/native/vendor/microtex/lib/macro/macro_colors.cpp +42 -0
  142. package/native/vendor/microtex/lib/macro/macro_colors.h +42 -0
  143. package/native/vendor/microtex/lib/macro/macro_decl.h +16 -0
  144. package/native/vendor/microtex/lib/macro/macro_def.cpp +418 -0
  145. package/native/vendor/microtex/lib/macro/macro_delims.cpp +56 -0
  146. package/native/vendor/microtex/lib/macro/macro_delims.h +73 -0
  147. package/native/vendor/microtex/lib/macro/macro_env.h +212 -0
  148. package/native/vendor/microtex/lib/macro/macro_fonts.cpp +53 -0
  149. package/native/vendor/microtex/lib/macro/macro_fonts.h +78 -0
  150. package/native/vendor/microtex/lib/macro/macro_frac.cpp +138 -0
  151. package/native/vendor/microtex/lib/macro/macro_frac.h +50 -0
  152. package/native/vendor/microtex/lib/macro/macro_misc.cpp +211 -0
  153. package/native/vendor/microtex/lib/macro/macro_misc.h +217 -0
  154. package/native/vendor/microtex/lib/macro/macro_scripts.cpp +32 -0
  155. package/native/vendor/microtex/lib/macro/macro_scripts.h +17 -0
  156. package/native/vendor/microtex/lib/macro/macro_sizes.h +110 -0
  157. package/native/vendor/microtex/lib/macro/macro_space.cpp +31 -0
  158. package/native/vendor/microtex/lib/macro/macro_space.h +17 -0
  159. package/native/vendor/microtex/lib/macro/macro_styles.cpp +45 -0
  160. package/native/vendor/microtex/lib/macro/macro_styles.h +22 -0
  161. package/native/vendor/microtex/lib/macro/macro_types.h +48 -0
  162. package/native/vendor/microtex/lib/macro/meson.build +33 -0
  163. package/native/vendor/microtex/lib/meson.build +102 -0
  164. package/native/vendor/microtex/lib/microtex.cpp +208 -0
  165. package/native/vendor/microtex/lib/microtex.h +225 -0
  166. package/native/vendor/microtex/lib/microtexConfig.cmake.in +2 -0
  167. package/native/vendor/microtex/lib/microtexapi.h +22 -0
  168. package/native/vendor/microtex/lib/microtexconfig.h.in +7 -0
  169. package/native/vendor/microtex/lib/microtexexport.h +31 -0
  170. package/native/vendor/microtex/lib/otf/clm.cpp +405 -0
  171. package/native/vendor/microtex/lib/otf/clm.h +61 -0
  172. package/native/vendor/microtex/lib/otf/fontsense.cpp +191 -0
  173. package/native/vendor/microtex/lib/otf/fontsense.h +20 -0
  174. package/native/vendor/microtex/lib/otf/glyph.cpp +53 -0
  175. package/native/vendor/microtex/lib/otf/glyph.h +384 -0
  176. package/native/vendor/microtex/lib/otf/math_consts.h +154 -0
  177. package/native/vendor/microtex/lib/otf/meson.build +18 -0
  178. package/native/vendor/microtex/lib/otf/otf.cpp +84 -0
  179. package/native/vendor/microtex/lib/otf/otf.h +177 -0
  180. package/native/vendor/microtex/lib/otf/otfconfig.h +32 -0
  181. package/native/vendor/microtex/lib/otf/path.cpp +187 -0
  182. package/native/vendor/microtex/lib/otf/path.h +120 -0
  183. package/native/vendor/microtex/lib/render/builder.cpp +68 -0
  184. package/native/vendor/microtex/lib/render/builder.h +73 -0
  185. package/native/vendor/microtex/lib/render/meson.build +11 -0
  186. package/native/vendor/microtex/lib/render/render.cpp +136 -0
  187. package/native/vendor/microtex/lib/render/render.h +59 -0
  188. package/native/vendor/microtex/lib/unimath/font_meta.h +22 -0
  189. package/native/vendor/microtex/lib/unimath/font_src.cpp +21 -0
  190. package/native/vendor/microtex/lib/unimath/font_src.h +61 -0
  191. package/native/vendor/microtex/lib/unimath/math_type.cpp +318 -0
  192. package/native/vendor/microtex/lib/unimath/math_type.h +105 -0
  193. package/native/vendor/microtex/lib/unimath/meson.build +18 -0
  194. package/native/vendor/microtex/lib/unimath/uni_char.cpp +121 -0
  195. package/native/vendor/microtex/lib/unimath/uni_char.h +109 -0
  196. package/native/vendor/microtex/lib/unimath/uni_font.cpp +248 -0
  197. package/native/vendor/microtex/lib/unimath/uni_font.h +139 -0
  198. package/native/vendor/microtex/lib/unimath/uni_symbol.cpp +2929 -0
  199. package/native/vendor/microtex/lib/unimath/uni_symbol.h +31 -0
  200. package/native/vendor/microtex/lib/utils/dict_tree.h +68 -0
  201. package/native/vendor/microtex/lib/utils/exceptions.h +61 -0
  202. package/native/vendor/microtex/lib/utils/log.h +34 -0
  203. package/native/vendor/microtex/lib/utils/meson.build +18 -0
  204. package/native/vendor/microtex/lib/utils/nums.h +24 -0
  205. package/native/vendor/microtex/lib/utils/string_utils.cpp +85 -0
  206. package/native/vendor/microtex/lib/utils/string_utils.h +130 -0
  207. package/native/vendor/microtex/lib/utils/types.h +152 -0
  208. package/native/vendor/microtex/lib/utils/utf.cpp +115 -0
  209. package/native/vendor/microtex/lib/utils/utf.h +58 -0
  210. package/native/vendor/microtex/lib/utils/utils.cpp +40 -0
  211. package/native/vendor/microtex/lib/utils/utils.h +88 -0
  212. package/native/vendor/microtex/lib/wrapper/byte_seq.cpp +46 -0
  213. package/native/vendor/microtex/lib/wrapper/byte_seq.h +70 -0
  214. package/native/vendor/microtex/lib/wrapper/callback.cpp +10 -0
  215. package/native/vendor/microtex/lib/wrapper/callback.h +72 -0
  216. package/native/vendor/microtex/lib/wrapper/cwrapper.cpp +206 -0
  217. package/native/vendor/microtex/lib/wrapper/cwrapper.h +305 -0
  218. package/native/vendor/microtex/lib/wrapper/graphic_wrapper.cpp +211 -0
  219. package/native/vendor/microtex/lib/wrapper/graphic_wrapper.h +159 -0
  220. package/native/vendor/microtex/lib/wrapper/meson.build +22 -0
  221. package/native/vendor/microtex/meson.build +75 -0
  222. package/native/vendor/microtex/meson_options.txt +29 -0
  223. package/native/vendor/microtex/platform/cairo/CMakeLists.txt +36 -0
  224. package/native/vendor/microtex/platform/cairo/graphic_cairo.cpp +384 -0
  225. package/native/vendor/microtex/platform/cairo/graphic_cairo.h +119 -0
  226. package/native/vendor/microtex/platform/cairo/meson.build +47 -0
  227. package/native/vendor/microtex/platform/cairo/microtex-cairoConfig.cmake.in +11 -0
  228. package/native/vendor/microtex/platform/flutter/microtex/.metadata +10 -0
  229. package/native/vendor/microtex/platform/flutter/microtex/CHANGELOG.md +3 -0
  230. package/native/vendor/microtex/platform/flutter/microtex/LICENSE +1 -0
  231. package/native/vendor/microtex/platform/flutter/microtex/README.md +15 -0
  232. package/native/vendor/microtex/platform/flutter/microtex/analysis_options.yaml +4 -0
  233. package/native/vendor/microtex/platform/flutter/microtex/android/build.gradle +56 -0
  234. package/native/vendor/microtex/platform/flutter/microtex/android/settings.gradle +1 -0
  235. package/native/vendor/microtex/platform/flutter/microtex/android/src/main/AndroidManifest.xml +3 -0
  236. package/native/vendor/microtex/platform/flutter/microtex/android/src/main/kotlin/io/nano/microtex/microtex/MicrotexPlugin.kt +35 -0
  237. package/native/vendor/microtex/platform/flutter/microtex/example/.metadata +10 -0
  238. package/native/vendor/microtex/platform/flutter/microtex/example/README.md +16 -0
  239. package/native/vendor/microtex/platform/flutter/microtex/example/analysis_options.yaml +31 -0
  240. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/build.gradle +68 -0
  241. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/debug/AndroidManifest.xml +7 -0
  242. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/AndroidManifest.xml +34 -0
  243. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/kotlin/io/nano/microtex/microtex_example/MainActivity.kt +6 -0
  244. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/drawable/launch_background.xml +12 -0
  245. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
  246. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  247. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  248. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  249. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  250. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  251. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/values/styles.xml +18 -0
  252. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/main/res/values-night/styles.xml +18 -0
  253. package/native/vendor/microtex/platform/flutter/microtex/example/android/app/src/profile/AndroidManifest.xml +7 -0
  254. package/native/vendor/microtex/platform/flutter/microtex/example/android/build.gradle +31 -0
  255. package/native/vendor/microtex/platform/flutter/microtex/example/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  256. package/native/vendor/microtex/platform/flutter/microtex/example/android/gradle.properties +3 -0
  257. package/native/vendor/microtex/platform/flutter/microtex/example/android/settings.gradle +11 -0
  258. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Flutter/AppFrameworkInfo.plist +26 -0
  259. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Flutter/Debug.xcconfig +2 -0
  260. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Flutter/Release.xcconfig +2 -0
  261. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Podfile +41 -0
  262. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Podfile.lock +22 -0
  263. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/AppDelegate.swift +13 -0
  264. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +122 -0
  265. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png +0 -0
  266. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png +0 -0
  267. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png +0 -0
  268. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png +0 -0
  269. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png +0 -0
  270. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png +0 -0
  271. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png +0 -0
  272. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png +0 -0
  273. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png +0 -0
  274. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png +0 -0
  275. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png +0 -0
  276. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png +0 -0
  277. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png +0 -0
  278. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png +0 -0
  279. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png +0 -0
  280. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +23 -0
  281. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  282. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  283. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  284. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +5 -0
  285. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +37 -0
  286. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Base.lproj/Main.storyboard +26 -0
  287. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Info.plist +49 -0
  288. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner/Runner-Bridging-Header.h +1 -0
  289. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcodeproj/project.pbxproj +549 -0
  290. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  291. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  292. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  293. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +87 -0
  294. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcworkspace/contents.xcworkspacedata +10 -0
  295. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  296. package/native/vendor/microtex/platform/flutter/microtex/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  297. package/native/vendor/microtex/platform/flutter/microtex/example/lib/main.dart +23 -0
  298. package/native/vendor/microtex/platform/flutter/microtex/example/lib/screen/edit_in_one.dart +0 -0
  299. package/native/vendor/microtex/platform/flutter/microtex/example/lib/screen/edit_screen.dart +208 -0
  300. package/native/vendor/microtex/platform/flutter/microtex/example/lib/utils/convert_spans.dart +63 -0
  301. package/native/vendor/microtex/platform/flutter/microtex/example/lib/utils/string_ext.dart +10 -0
  302. package/native/vendor/microtex/platform/flutter/microtex/example/lib/widget/cmp.dart +118 -0
  303. package/native/vendor/microtex/platform/flutter/microtex/example/lib/widget/draggable.dart +75 -0
  304. package/native/vendor/microtex/platform/flutter/microtex/example/lib/widget/rich.dart +23 -0
  305. package/native/vendor/microtex/platform/flutter/microtex/example/lib/widget/split.dart +72 -0
  306. package/native/vendor/microtex/platform/flutter/microtex/example/lib/widget/tex_highlight_controller.dart +66 -0
  307. package/native/vendor/microtex/platform/flutter/microtex/example/lib/widget/tex_input_controller.dart +19 -0
  308. package/native/vendor/microtex/platform/flutter/microtex/example/linux/CMakeLists.txt +116 -0
  309. package/native/vendor/microtex/platform/flutter/microtex/example/linux/flutter/CMakeLists.txt +87 -0
  310. package/native/vendor/microtex/platform/flutter/microtex/example/linux/flutter/generated_plugin_registrant.cc +15 -0
  311. package/native/vendor/microtex/platform/flutter/microtex/example/linux/flutter/generated_plugin_registrant.h +15 -0
  312. package/native/vendor/microtex/platform/flutter/microtex/example/linux/flutter/generated_plugins.cmake +24 -0
  313. package/native/vendor/microtex/platform/flutter/microtex/example/linux/main.cc +6 -0
  314. package/native/vendor/microtex/platform/flutter/microtex/example/linux/my_application.cc +104 -0
  315. package/native/vendor/microtex/platform/flutter/microtex/example/linux/my_application.h +18 -0
  316. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Flutter/Flutter-Debug.xcconfig +2 -0
  317. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Flutter/Flutter-Release.xcconfig +2 -0
  318. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Flutter/GeneratedPluginRegistrant.swift +12 -0
  319. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Podfile +40 -0
  320. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Podfile.lock +22 -0
  321. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/AppDelegate.swift +9 -0
  322. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  323. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  324. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  325. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  326. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  327. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  328. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  329. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  330. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Base.lproj/MainMenu.xib +343 -0
  331. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Configs/AppInfo.xcconfig +14 -0
  332. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Configs/Debug.xcconfig +2 -0
  333. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Configs/Release.xcconfig +2 -0
  334. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Configs/Warnings.xcconfig +13 -0
  335. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/DebugProfile.entitlements +12 -0
  336. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Info.plist +32 -0
  337. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/MainFlutterWindow.swift +15 -0
  338. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner/Release.entitlements +8 -0
  339. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner.xcodeproj/project.pbxproj +633 -0
  340. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  341. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +87 -0
  342. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner.xcworkspace/contents.xcworkspacedata +10 -0
  343. package/native/vendor/microtex/platform/flutter/microtex/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  344. package/native/vendor/microtex/platform/flutter/microtex/example/pubspec.lock +191 -0
  345. package/native/vendor/microtex/platform/flutter/microtex/example/pubspec.yaml +56 -0
  346. package/native/vendor/microtex/platform/flutter/microtex/example/test/widget_test.dart +26 -0
  347. package/native/vendor/microtex/platform/flutter/microtex/example/windows/CMakeLists.txt +95 -0
  348. package/native/vendor/microtex/platform/flutter/microtex/example/windows/flutter/CMakeLists.txt +103 -0
  349. package/native/vendor/microtex/platform/flutter/microtex/example/windows/flutter/generated_plugin_registrant.cc +14 -0
  350. package/native/vendor/microtex/platform/flutter/microtex/example/windows/flutter/generated_plugin_registrant.h +15 -0
  351. package/native/vendor/microtex/platform/flutter/microtex/example/windows/flutter/generated_plugins.cmake +24 -0
  352. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/CMakeLists.txt +17 -0
  353. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/Runner.rc +121 -0
  354. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/flutter_window.cpp +61 -0
  355. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/flutter_window.h +33 -0
  356. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/main.cpp +43 -0
  357. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/resource.h +16 -0
  358. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/resources/app_icon.ico +0 -0
  359. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/runner.exe.manifest +20 -0
  360. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/utils.cpp +64 -0
  361. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/utils.h +19 -0
  362. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/win32_window.cpp +245 -0
  363. package/native/vendor/microtex/platform/flutter/microtex/example/windows/runner/win32_window.h +98 -0
  364. package/native/vendor/microtex/platform/flutter/microtex/ios/Assets/.gitkeep +0 -0
  365. package/native/vendor/microtex/platform/flutter/microtex/ios/Classes/MicrotexPlugin.h +4 -0
  366. package/native/vendor/microtex/platform/flutter/microtex/ios/Classes/MicrotexPlugin.m +19 -0
  367. package/native/vendor/microtex/platform/flutter/microtex/ios/Classes/SwiftMicrotexPlugin.swift +14 -0
  368. package/native/vendor/microtex/platform/flutter/microtex/ios/Classes/dummy.h +4 -0
  369. package/native/vendor/microtex/platform/flutter/microtex/ios/microtex.podspec +27 -0
  370. package/native/vendor/microtex/platform/flutter/microtex/lib/microtex.dart +7 -0
  371. package/native/vendor/microtex/platform/flutter/microtex/lib/src/bindings.dart +218 -0
  372. package/native/vendor/microtex/platform/flutter/microtex/lib/src/bounds.dart +10 -0
  373. package/native/vendor/microtex/platform/flutter/microtex/lib/src/context.dart +205 -0
  374. package/native/vendor/microtex/platform/flutter/microtex/lib/src/fontdesc.dart +14 -0
  375. package/native/vendor/microtex/platform/flutter/microtex/lib/src/fontmeta.dart +14 -0
  376. package/native/vendor/microtex/platform/flutter/microtex/lib/src/pathcache.dart +17 -0
  377. package/native/vendor/microtex/platform/flutter/microtex/lib/src/render.dart +291 -0
  378. package/native/vendor/microtex/platform/flutter/microtex/lib/src/texstyle.dart +11 -0
  379. package/native/vendor/microtex/platform/flutter/microtex/lib/src/textlayout.dart +93 -0
  380. package/native/vendor/microtex/platform/flutter/microtex/lib/src/widget.dart +163 -0
  381. package/native/vendor/microtex/platform/flutter/microtex/linux/CMakeLists.txt +33 -0
  382. package/native/vendor/microtex/platform/flutter/microtex/linux/include/microtex/microtex_plugin.h +26 -0
  383. package/native/vendor/microtex/platform/flutter/microtex/linux/microtex_plugin.cc +70 -0
  384. package/native/vendor/microtex/platform/flutter/microtex/macos/Classes/MicrotexPlugin.swift +20 -0
  385. package/native/vendor/microtex/platform/flutter/microtex/macos/Classes/dummy.h +4 -0
  386. package/native/vendor/microtex/platform/flutter/microtex/macos/Classes/microtex-Bridging-Header.h +1 -0
  387. package/native/vendor/microtex/platform/flutter/microtex/macos/microtex.podspec +26 -0
  388. package/native/vendor/microtex/platform/flutter/microtex/nativelib/CMakeLists.txt +44 -0
  389. package/native/vendor/microtex/platform/flutter/microtex/nativelib/builddarwin.sh +108 -0
  390. package/native/vendor/microtex/platform/flutter/microtex/pubspec.yaml +37 -0
  391. package/native/vendor/microtex/platform/flutter/microtex/test/microtex_test.dart +23 -0
  392. package/native/vendor/microtex/platform/flutter/microtex/windows/CMakeLists.txt +32 -0
  393. package/native/vendor/microtex/platform/flutter/microtex/windows/include/microtex/microtex_plugin.h +23 -0
  394. package/native/vendor/microtex/platform/flutter/microtex/windows/microtex_plugin.cpp +82 -0
  395. package/native/vendor/microtex/platform/gdi_win/CMakeLists.txt +20 -0
  396. package/native/vendor/microtex/platform/gdi_win/graphic_win32.cpp +352 -0
  397. package/native/vendor/microtex/platform/gdi_win/graphic_win32.h +137 -0
  398. package/native/vendor/microtex/platform/gdi_win/meson.build +39 -0
  399. package/native/vendor/microtex/platform/gtk/CMakeLists.txt +36 -0
  400. package/native/vendor/microtex/platform/gtk/meson.build +65 -0
  401. package/native/vendor/microtex/platform/gtk/microtex-gtkConfig.cmake.in +11 -0
  402. package/native/vendor/microtex/platform/gtk/microtexequation.cpp +708 -0
  403. package/native/vendor/microtex/platform/gtk/microtexequation.h +72 -0
  404. package/native/vendor/microtex/platform/qt/CMakeLists.txt +37 -0
  405. package/native/vendor/microtex/platform/qt/graphic_qt.cpp +355 -0
  406. package/native/vendor/microtex/platform/qt/graphic_qt.h +116 -0
  407. package/native/vendor/microtex/platform/qt/meson.build +38 -0
  408. package/native/vendor/microtex/platform/qt/microtex-qtConfig.cmake.in +7 -0
  409. package/native/vendor/microtex/platform/skia/CMakeLists.txt +46 -0
  410. package/native/vendor/microtex/platform/skia/graphic_skia.cpp +306 -0
  411. package/native/vendor/microtex/platform/skia/graphic_skia.h +125 -0
  412. package/native/vendor/microtex/platform/skia/microtex-skiaConfig.cmake.in +6 -0
  413. package/native/vendor/microtex/platform/wasm/CMakeLists.txt +38 -0
  414. package/native/vendor/microtex/platform/wasm/emscripten.cross +31 -0
  415. package/native/vendor/microtex/platform/wasm/main.cpp +15 -0
  416. package/native/vendor/microtex/platform/wasm/meson.build +8 -0
  417. package/native/vendor/microtex/platform/wasm/prebuild-example-meson.sh +21 -0
  418. package/native/vendor/microtex/platform/wasm/prebuild-example.sh +21 -0
  419. package/native/vendor/microtex/platform/wasm/prebuild-lib-meson.sh +28 -0
  420. package/native/vendor/microtex/platform/wasm/prebuild-lib.sh +31 -0
  421. package/native/vendor/microtex/platform/wasm/web/.babelrc +10 -0
  422. package/native/vendor/microtex/platform/wasm/web/example/examples.js +43 -0
  423. package/native/vendor/microtex/platform/wasm/web/example/hello.js +31 -0
  424. package/native/vendor/microtex/platform/wasm/web/example/index.html +55 -0
  425. package/native/vendor/microtex/platform/wasm/web/example/index.js +243 -0
  426. package/native/vendor/microtex/platform/wasm/web/example/styles.css +86 -0
  427. package/native/vendor/microtex/platform/wasm/web/example/utils.js +47 -0
  428. package/native/vendor/microtex/platform/wasm/web/lib/context.js +271 -0
  429. package/native/vendor/microtex/platform/wasm/web/lib/index.js +10 -0
  430. package/native/vendor/microtex/platform/wasm/web/lib/render.js +293 -0
  431. package/native/vendor/microtex/platform/wasm/web/lib/runtime.js +14 -0
  432. package/native/vendor/microtex/platform/wasm/web/lib/svg.js +237 -0
  433. package/native/vendor/microtex/platform/wasm/web/lib/textlayout.js +88 -0
  434. package/native/vendor/microtex/platform/wasm/web/package-lock.json +5931 -0
  435. package/native/vendor/microtex/platform/wasm/web/package.json +45 -0
  436. package/native/vendor/microtex/platform/wasm/web/publish-example.sh +17 -0
  437. package/native/vendor/microtex/platform/wasm/web/rollup.config.example.js +24 -0
  438. package/native/vendor/microtex/platform/wasm/web/rollup.config.lib.js +16 -0
  439. package/native/vendor/microtex/prebuilt/otf2clm.py +807 -0
  440. package/native/vendor/microtex/prebuilt/otf2clm.sh +9 -0
  441. package/native/vendor/microtex/prebuilt/preclms.sh +17 -0
  442. package/native/vendor/microtex/readme/example_bw_false.svg +680 -0
  443. package/native/vendor/microtex/readme/example_bw_true.svg +680 -0
  444. package/native/vendor/microtex/readme/example_cjk_trying.svg +54 -0
  445. package/native/vendor/microtex/readme/example_custom_symbols.svg +92 -0
  446. package/native/vendor/microtex/readme/example_debug.svg +764 -0
  447. package/native/vendor/microtex/readme/example_emoji.svg +199 -0
  448. package/native/vendor/microtex/readme/example_have_log.svg +79 -0
  449. package/native/vendor/microtex/readme/example_keep_trying.svg +101 -0
  450. package/native/vendor/microtex/readme/example_logos.svg +50 -0
  451. package/native/vendor/microtex/readme/example_ubuntu.png +0 -0
  452. package/native/vendor/microtex/readme/example_windows.png +0 -0
  453. package/native/vendor/microtex/readme/samples/sample_0.svg +665 -0
  454. package/native/vendor/microtex/readme/samples/sample_1.svg +1259 -0
  455. package/native/vendor/microtex/readme/samples/sample_10.svg +333 -0
  456. package/native/vendor/microtex/readme/samples/sample_11.svg +306 -0
  457. package/native/vendor/microtex/readme/samples/sample_2.svg +2461 -0
  458. package/native/vendor/microtex/readme/samples/sample_3.svg +2653 -0
  459. package/native/vendor/microtex/readme/samples/sample_4.svg +554 -0
  460. package/native/vendor/microtex/readme/samples/sample_5.svg +247 -0
  461. package/native/vendor/microtex/readme/samples/sample_6.svg +1082 -0
  462. package/native/vendor/microtex/readme/samples/sample_7.svg +518 -0
  463. package/native/vendor/microtex/readme/samples/sample_8.svg +529 -0
  464. package/native/vendor/microtex/readme/samples/sample_9.svg +1702 -0
  465. package/native/vendor/microtex/readme/samples.md +301 -0
  466. package/native/vendor/microtex/readme/tex_logo.svg +19 -0
  467. package/native/vendor/microtex/res/EXAMPLE.txt +25 -0
  468. package/native/vendor/microtex/res/SAMPLES.tex +946 -0
  469. package/native/vendor/microtex/res/firamath/FiraMath-Regular.clm1 +0 -0
  470. package/native/vendor/microtex/res/firamath/FiraMath-Regular.clm2 +0 -0
  471. package/native/vendor/microtex/res/firamath/FiraMath-Regular.otf +0 -0
  472. package/native/vendor/microtex/res/firamath/README.md +42 -0
  473. package/native/vendor/microtex/res/lm-math/README +92 -0
  474. package/native/vendor/microtex/res/lm-math/latinmodern-math.clm1 +0 -0
  475. package/native/vendor/microtex/res/lm-math/latinmodern-math.clm2 +0 -0
  476. package/native/vendor/microtex/res/lm-math/latinmodern-math.otf +0 -0
  477. package/native/vendor/microtex/res/tex-gyre/README-TeX-Gyre-DejaVu-Math.txt +82 -0
  478. package/native/vendor/microtex/res/tex-gyre/texgyredejavu-math.clm1 +0 -0
  479. package/native/vendor/microtex/res/tex-gyre/texgyredejavu-math.clm2 +0 -0
  480. package/native/vendor/microtex/res/tex-gyre/texgyredejavu-math.otf +0 -0
  481. package/native/vendor/microtex/res/xits/FONTLOG.txt +246 -0
  482. package/native/vendor/microtex/res/xits/OFL.txt +98 -0
  483. package/native/vendor/microtex/res/xits/README.txt +15 -0
  484. package/native/vendor/microtex/res/xits/XITS-Bold.clm1 +0 -0
  485. package/native/vendor/microtex/res/xits/XITS-Bold.clm2 +0 -0
  486. package/native/vendor/microtex/res/xits/XITS-Bold.otf +0 -0
  487. package/native/vendor/microtex/res/xits/XITS-BoldItalic.clm1 +0 -0
  488. package/native/vendor/microtex/res/xits/XITS-BoldItalic.clm2 +0 -0
  489. package/native/vendor/microtex/res/xits/XITS-BoldItalic.otf +0 -0
  490. package/native/vendor/microtex/res/xits/XITS-Italic.clm1 +0 -0
  491. package/native/vendor/microtex/res/xits/XITS-Italic.clm2 +0 -0
  492. package/native/vendor/microtex/res/xits/XITS-Italic.otf +0 -0
  493. package/native/vendor/microtex/res/xits/XITS-Regular.clm1 +0 -0
  494. package/native/vendor/microtex/res/xits/XITS-Regular.clm2 +0 -0
  495. package/native/vendor/microtex/res/xits/XITS-Regular.otf +0 -0
  496. package/native/vendor/microtex/res/xits/XITSMath-Bold.clm1 +0 -0
  497. package/native/vendor/microtex/res/xits/XITSMath-Bold.clm2 +0 -0
  498. package/native/vendor/microtex/res/xits/XITSMath-Bold.otf +0 -0
  499. package/native/vendor/microtex/res/xits/XITSMath-Regular.clm1 +0 -0
  500. package/native/vendor/microtex/res/xits/XITSMath-Regular.clm2 +0 -0
  501. package/native/vendor/microtex/res/xits/XITSMath-Regular.otf +0 -0
  502. package/native/vendor/microtex/test/clm/meson.build +10 -0
  503. package/native/vendor/microtex/test/clm/test_clm.cpp +140 -0
  504. package/native/vendor/microtex/test/env/meson.build +10 -0
  505. package/native/vendor/microtex/test/env/test_env.cpp +100 -0
  506. package/native/vendor/microtex/test/fuzzer/afl.native +20 -0
  507. package/native/vendor/microtex/test/fuzzer/fuzz.sh +135 -0
  508. package/native/vendor/microtex/test/fuzzer/fuzzer.cpp +61 -0
  509. package/native/vendor/microtex/test/fuzzer/generateSeed.java +33 -0
  510. package/native/vendor/microtex/test/fuzzer/meson.build +9 -0
  511. package/native/vendor/microtex/test/fuzzer/microtex.dict +3708 -0
  512. package/native/vendor/microtex/test/fuzzer/platform_none.cpp +100 -0
  513. package/native/vendor/microtex/test/has_filesystem.cpp +8 -0
  514. package/native/vendor/microtex/test/meson.build +6 -0
  515. package/native/vendor/nanosvg.h +3278 -0
  516. package/native/vendor/nanosvgrast.h +1472 -0
  517. package/native/vendor/zigtex/.github/assets/example.svg +27 -0
  518. package/native/vendor/zigtex/LICENSE +674 -0
  519. package/native/vendor/zigtex/README.md +52 -0
  520. package/native/vendor/zigtex/build.zig +52 -0
  521. package/native/vendor/zigtex/build.zig.zon +16 -0
  522. package/native/vendor/zigtex/fonts/latinmodern-math.clm2 +0 -0
  523. package/native/vendor/zigtex/src/main.zig +22 -0
  524. package/native/vendor/zigtex/src/root.zig +124 -0
  525. package/native/vendor/zigtex/src/svg.zig +273 -0
  526. package/native/vendor/zigtex/src/tex.zig +383 -0
  527. package/native/zigtex-0.16.patch +35 -0
  528. package/package.json +27 -0
  529. package/scripts/bootstrap-native +89 -0
@@ -0,0 +1,3278 @@
1
+ /*
2
+ * Copyright (c) 2013-14 Mikko Mononen memon@inside.org
3
+ *
4
+ * This software is provided 'as-is', without any express or implied
5
+ * warranty. In no event will the authors be held liable for any damages
6
+ * arising from the use of this software.
7
+ *
8
+ * Permission is granted to anyone to use this software for any purpose,
9
+ * including commercial applications, and to alter it and redistribute it
10
+ * freely, subject to the following restrictions:
11
+ *
12
+ * 1. The origin of this software must not be misrepresented; you must not
13
+ * claim that you wrote the original software. If you use this software
14
+ * in a product, an acknowledgment in the product documentation would be
15
+ * appreciated but is not required.
16
+ * 2. Altered source versions must be plainly marked as such, and must not be
17
+ * misrepresented as being the original software.
18
+ * 3. This notice may not be removed or altered from any source distribution.
19
+ *
20
+ * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
21
+ * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
22
+ *
23
+ * Arc calculation code based on canvg (https://code.google.com/p/canvg/)
24
+ *
25
+ * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
26
+ *
27
+ */
28
+
29
+ #ifndef NANOSVG_H
30
+ #define NANOSVG_H
31
+
32
+ #ifndef NANOSVG_CPLUSPLUS
33
+ #ifdef __cplusplus
34
+ extern "C" {
35
+ #endif
36
+ #endif
37
+
38
+ // NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
39
+ //
40
+ // The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.
41
+ //
42
+ // NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!
43
+ //
44
+ // The shapes in the SVG images are transformed by the viewBox and converted to specified units.
45
+ // That is, you should get the same looking data as your designed in your favorite app.
46
+ //
47
+ // NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
48
+ // to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
49
+ //
50
+ // The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
51
+ // DPI (dots-per-inch) controls how the unit conversion is done.
52
+ //
53
+ // If you don't know or care about the units stuff, "px" and 96 should get you going.
54
+
55
+
56
+ /* Example Usage:
57
+ // Load SVG
58
+ NSVGimage* image;
59
+ image = nsvgParseFromFile("test.svg", "px", 96);
60
+ printf("size: %f x %f\n", image->width, image->height);
61
+ // Use...
62
+ for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
63
+ for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
64
+ for (int i = 0; i < path->npts-1; i += 3) {
65
+ float* p = &path->pts[i*2];
66
+ drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
67
+ }
68
+ }
69
+ }
70
+ // Delete
71
+ nsvgDelete(image);
72
+ */
73
+
74
+ enum NSVGpaintType {
75
+ NSVG_PAINT_UNDEF = -1,
76
+ NSVG_PAINT_NONE = 0,
77
+ NSVG_PAINT_COLOR = 1,
78
+ NSVG_PAINT_LINEAR_GRADIENT = 2,
79
+ NSVG_PAINT_RADIAL_GRADIENT = 3
80
+ };
81
+
82
+ enum NSVGspreadType {
83
+ NSVG_SPREAD_PAD = 0,
84
+ NSVG_SPREAD_REFLECT = 1,
85
+ NSVG_SPREAD_REPEAT = 2
86
+ };
87
+
88
+ enum NSVGlineJoin {
89
+ NSVG_JOIN_MITER = 0,
90
+ NSVG_JOIN_ROUND = 1,
91
+ NSVG_JOIN_BEVEL = 2
92
+ };
93
+
94
+ enum NSVGlineCap {
95
+ NSVG_CAP_BUTT = 0,
96
+ NSVG_CAP_ROUND = 1,
97
+ NSVG_CAP_SQUARE = 2
98
+ };
99
+
100
+ enum NSVGfillRule {
101
+ NSVG_FILLRULE_NONZERO = 0,
102
+ NSVG_FILLRULE_EVENODD = 1
103
+ };
104
+
105
+ enum NSVGflags {
106
+ NSVG_FLAGS_VISIBLE = 0x01
107
+ };
108
+
109
+ enum NSVGpaintOrder {
110
+ NSVG_PAINT_FILL = 0x00,
111
+ NSVG_PAINT_MARKERS = 0x01,
112
+ NSVG_PAINT_STROKE = 0x02,
113
+ };
114
+
115
+ typedef struct NSVGgradientStop {
116
+ unsigned int color;
117
+ float offset;
118
+ } NSVGgradientStop;
119
+
120
+ typedef struct NSVGgradient {
121
+ float xform[6];
122
+ char spread;
123
+ float fx, fy;
124
+ int nstops;
125
+ NSVGgradientStop stops[1];
126
+ } NSVGgradient;
127
+
128
+ typedef struct NSVGpaint {
129
+ signed char type;
130
+ union {
131
+ unsigned int color;
132
+ NSVGgradient* gradient;
133
+ };
134
+ } NSVGpaint;
135
+
136
+ typedef struct NSVGpath
137
+ {
138
+ float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
139
+ int npts; // Total number of bezier points.
140
+ char closed; // Flag indicating if shapes should be treated as closed.
141
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
142
+ struct NSVGpath* next; // Pointer to next path, or NULL if last element.
143
+ } NSVGpath;
144
+
145
+ typedef struct NSVGshape
146
+ {
147
+ char id[64]; // Optional 'id' attr of the shape or its group
148
+ NSVGpaint fill; // Fill paint
149
+ NSVGpaint stroke; // Stroke paint
150
+ float opacity; // Opacity of the shape.
151
+ float strokeWidth; // Stroke width (scaled).
152
+ float strokeDashOffset; // Stroke dash offset (scaled).
153
+ float strokeDashArray[8]; // Stroke dash array (scaled).
154
+ char strokeDashCount; // Number of dash values in dash array.
155
+ char strokeLineJoin; // Stroke join type.
156
+ char strokeLineCap; // Stroke cap type.
157
+ float miterLimit; // Miter limit
158
+ char fillRule; // Fill rule, see NSVGfillRule.
159
+ unsigned char paintOrder; // Encoded paint order (3×2-bit fields) see NSVGpaintOrder
160
+ unsigned char flags; // Logical or of NSVG_FLAGS_* flags
161
+ float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
162
+ char fillGradient[64]; // Optional 'id' of fill gradient
163
+ char strokeGradient[64]; // Optional 'id' of stroke gradient
164
+ float xform[6]; // Root transformation for fill/stroke gradient
165
+ NSVGpath* paths; // Linked list of paths in the image.
166
+ struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
167
+ } NSVGshape;
168
+
169
+ typedef struct NSVGimage
170
+ {
171
+ float width; // Width of the image.
172
+ float height; // Height of the image.
173
+ NSVGshape* shapes; // Linked list of shapes in the image.
174
+ } NSVGimage;
175
+
176
+ // Parses SVG file from a file, returns SVG image as paths.
177
+ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
178
+
179
+ // Parses SVG file from a null terminated string, returns SVG image as paths.
180
+ // Important note: changes the string.
181
+ NSVGimage* nsvgParse(char* input, const char* units, float dpi);
182
+
183
+ // Duplicates a path.
184
+ NSVGpath* nsvgDuplicatePath(NSVGpath* p);
185
+
186
+ // Deletes an image.
187
+ void nsvgDelete(NSVGimage* image);
188
+
189
+ #ifndef NANOSVG_CPLUSPLUS
190
+ #ifdef __cplusplus
191
+ }
192
+ #endif
193
+ #endif
194
+
195
+ #ifdef NANOSVG_IMPLEMENTATION
196
+
197
+ #include <string.h>
198
+ #include <stdlib.h>
199
+ #include <stdio.h>
200
+ #include <math.h>
201
+
202
+ #define NSVG_PI (3.14159265358979323846264338327f)
203
+ #define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
204
+
205
+ #define NSVG_ALIGN_MIN 0
206
+ #define NSVG_ALIGN_MID 1
207
+ #define NSVG_ALIGN_MAX 2
208
+ #define NSVG_ALIGN_NONE 0
209
+ #define NSVG_ALIGN_MEET 1
210
+ #define NSVG_ALIGN_SLICE 2
211
+
212
+ #define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
213
+ #define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
214
+
215
+ #ifdef _MSC_VER
216
+ #pragma warning (disable: 4996) // Switch off security warnings
217
+ #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
218
+ #ifdef __cplusplus
219
+ #define NSVG_INLINE inline
220
+ #else
221
+ #define NSVG_INLINE
222
+ #endif
223
+ #else
224
+ #define NSVG_INLINE inline
225
+ #endif
226
+
227
+
228
+ static int nsvg__isspace(char c)
229
+ {
230
+ return strchr(" \t\n\v\f\r", c) != 0;
231
+ }
232
+
233
+ static int nsvg__isdigit(char c)
234
+ {
235
+ return c >= '0' && c <= '9';
236
+ }
237
+
238
+ static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
239
+ static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
240
+
241
+
242
+ // Simple XML parser
243
+
244
+ #define NSVG_XML_TAG 1
245
+ #define NSVG_XML_CONTENT 2
246
+ #define NSVG_XML_MAX_ATTRIBS 256
247
+
248
+ static void nsvg__parseContent(char* s,
249
+ void (*contentCb)(void* ud, const char* s),
250
+ void* ud)
251
+ {
252
+ // Trim start white spaces
253
+ while (*s && nsvg__isspace(*s)) s++;
254
+ if (!*s) return;
255
+
256
+ if (contentCb)
257
+ (*contentCb)(ud, s);
258
+ }
259
+
260
+ static void nsvg__parseElement(char* s,
261
+ void (*startelCb)(void* ud, const char* el, const char** attr),
262
+ void (*endelCb)(void* ud, const char* el),
263
+ void* ud)
264
+ {
265
+ const char* attr[NSVG_XML_MAX_ATTRIBS];
266
+ int nattr = 0;
267
+ char* name;
268
+ int start = 0;
269
+ int end = 0;
270
+ char quote;
271
+
272
+ // Skip white space after the '<'
273
+ while (*s && nsvg__isspace(*s)) s++;
274
+
275
+ // Check if the tag is end tag
276
+ if (*s == '/') {
277
+ s++;
278
+ end = 1;
279
+ } else {
280
+ start = 1;
281
+ }
282
+
283
+ // Skip comments, data and preprocessor stuff.
284
+ if (!*s || *s == '?' || *s == '!')
285
+ return;
286
+
287
+ // Get tag name
288
+ name = s;
289
+ while (*s && !nsvg__isspace(*s)) s++;
290
+ if (*s) { *s++ = '\0'; }
291
+
292
+ // Get attribs
293
+ while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
294
+ char* name = NULL;
295
+ char* value = NULL;
296
+
297
+ // Skip white space before the attrib name
298
+ while (*s && nsvg__isspace(*s)) s++;
299
+ if (!*s) break;
300
+ if (*s == '/') {
301
+ end = 1;
302
+ break;
303
+ }
304
+ name = s;
305
+ // Find end of the attrib name.
306
+ while (*s && !nsvg__isspace(*s) && *s != '=') s++;
307
+ if (*s) { *s++ = '\0'; }
308
+ // Skip until the beginning of the value.
309
+ while (*s && *s != '\"' && *s != '\'') s++;
310
+ if (!*s) break;
311
+ quote = *s;
312
+ s++;
313
+ // Store value and find the end of it.
314
+ value = s;
315
+ while (*s && *s != quote) s++;
316
+ if (*s) { *s++ = '\0'; }
317
+
318
+ // Store only well formed attributes
319
+ if (name && value) {
320
+ attr[nattr++] = name;
321
+ attr[nattr++] = value;
322
+ }
323
+ }
324
+
325
+ // List terminator
326
+ attr[nattr++] = 0;
327
+ attr[nattr++] = 0;
328
+
329
+ // Call callbacks.
330
+ if (start && startelCb)
331
+ (*startelCb)(ud, name, attr);
332
+ if (end && endelCb)
333
+ (*endelCb)(ud, name);
334
+ }
335
+
336
+ int nsvg__parseXML(char* input,
337
+ void (*startelCb)(void* ud, const char* el, const char** attr),
338
+ void (*endelCb)(void* ud, const char* el),
339
+ void (*contentCb)(void* ud, const char* s),
340
+ void* ud)
341
+ {
342
+ char* s = input;
343
+ char* mark = s;
344
+ int state = NSVG_XML_CONTENT;
345
+ while (*s) {
346
+ if (*s == '<' && state == NSVG_XML_CONTENT) {
347
+ // Start of a tag
348
+ *s++ = '\0';
349
+ nsvg__parseContent(mark, contentCb, ud);
350
+ mark = s;
351
+ state = NSVG_XML_TAG;
352
+ } else if (*s == '>' && state == NSVG_XML_TAG) {
353
+ // Start of a content or new tag.
354
+ *s++ = '\0';
355
+ nsvg__parseElement(mark, startelCb, endelCb, ud);
356
+ mark = s;
357
+ state = NSVG_XML_CONTENT;
358
+ } else {
359
+ s++;
360
+ }
361
+ }
362
+
363
+ return 1;
364
+ }
365
+
366
+
367
+ /* Simple SVG parser. */
368
+
369
+ #define NSVG_MAX_ATTR 128
370
+
371
+ enum NSVGgradientUnits {
372
+ NSVG_USER_SPACE = 0,
373
+ NSVG_OBJECT_SPACE = 1
374
+ };
375
+
376
+ #define NSVG_MAX_DASHES 8
377
+ #define NSVG_MAX_CLASSES 32
378
+
379
+ enum NSVGunits {
380
+ NSVG_UNITS_USER,
381
+ NSVG_UNITS_PX,
382
+ NSVG_UNITS_PT,
383
+ NSVG_UNITS_PC,
384
+ NSVG_UNITS_MM,
385
+ NSVG_UNITS_CM,
386
+ NSVG_UNITS_IN,
387
+ NSVG_UNITS_PERCENT,
388
+ NSVG_UNITS_EM,
389
+ NSVG_UNITS_EX
390
+ };
391
+
392
+ typedef struct NSVGcoordinate {
393
+ float value;
394
+ int units;
395
+ } NSVGcoordinate;
396
+
397
+ typedef struct NSVGlinearData {
398
+ NSVGcoordinate x1, y1, x2, y2;
399
+ } NSVGlinearData;
400
+
401
+ typedef struct NSVGradialData {
402
+ NSVGcoordinate cx, cy, r, fx, fy;
403
+ } NSVGradialData;
404
+
405
+ typedef struct NSVGgradientData
406
+ {
407
+ char id[64];
408
+ char ref[64];
409
+ signed char type;
410
+ union {
411
+ NSVGlinearData linear;
412
+ NSVGradialData radial;
413
+ };
414
+ char spread;
415
+ char units;
416
+ float xform[6];
417
+ int nstops;
418
+ NSVGgradientStop* stops;
419
+ struct NSVGgradientData* next;
420
+ } NSVGgradientData;
421
+
422
+ typedef struct NSVGattrib
423
+ {
424
+ char id[64];
425
+ float xform[6];
426
+ unsigned int fillColor;
427
+ unsigned int strokeColor;
428
+ float opacity;
429
+ float fillOpacity;
430
+ float strokeOpacity;
431
+ char fillGradient[64];
432
+ char strokeGradient[64];
433
+ float strokeWidth;
434
+ float strokeDashOffset;
435
+ float strokeDashArray[NSVG_MAX_DASHES];
436
+ int strokeDashCount;
437
+ char strokeLineJoin;
438
+ char strokeLineCap;
439
+ float miterLimit;
440
+ char fillRule;
441
+ float fontSize;
442
+ unsigned int stopColor;
443
+ float stopOpacity;
444
+ float stopOffset;
445
+ char hasFill;
446
+ char hasStroke;
447
+ char visible;
448
+ unsigned char paintOrder;
449
+ } NSVGattrib;
450
+
451
+ typedef struct NSVGstyleDeclaration
452
+ {
453
+ char* className;
454
+ char* propertiesText;
455
+ struct NSVGstyleDeclaration* next;
456
+ } NSVGstyleDeclaration;
457
+
458
+ typedef struct NSVGparser
459
+ {
460
+ NSVGattrib attr[NSVG_MAX_ATTR];
461
+ int attrHead;
462
+ float* pts;
463
+ int npts;
464
+ int cpts;
465
+ NSVGpath* plist;
466
+ NSVGimage* image;
467
+ NSVGstyleDeclaration* styles;
468
+ NSVGgradientData* gradients;
469
+ NSVGshape* shapesTail;
470
+ float viewMinx, viewMiny, viewWidth, viewHeight;
471
+ int alignX, alignY, alignType;
472
+ float dpi;
473
+ char pathFlag;
474
+ char defsFlag;
475
+ char styleFlag;
476
+ } NSVGparser;
477
+
478
+ static void nsvg__xformIdentity(float* t)
479
+ {
480
+ t[0] = 1.0f; t[1] = 0.0f;
481
+ t[2] = 0.0f; t[3] = 1.0f;
482
+ t[4] = 0.0f; t[5] = 0.0f;
483
+ }
484
+
485
+ static void nsvg__xformSetTranslation(float* t, float tx, float ty)
486
+ {
487
+ t[0] = 1.0f; t[1] = 0.0f;
488
+ t[2] = 0.0f; t[3] = 1.0f;
489
+ t[4] = tx; t[5] = ty;
490
+ }
491
+
492
+ static void nsvg__xformSetScale(float* t, float sx, float sy)
493
+ {
494
+ t[0] = sx; t[1] = 0.0f;
495
+ t[2] = 0.0f; t[3] = sy;
496
+ t[4] = 0.0f; t[5] = 0.0f;
497
+ }
498
+
499
+ static void nsvg__xformSetSkewX(float* t, float a)
500
+ {
501
+ t[0] = 1.0f; t[1] = 0.0f;
502
+ t[2] = tanf(a); t[3] = 1.0f;
503
+ t[4] = 0.0f; t[5] = 0.0f;
504
+ }
505
+
506
+ static void nsvg__xformSetSkewY(float* t, float a)
507
+ {
508
+ t[0] = 1.0f; t[1] = tanf(a);
509
+ t[2] = 0.0f; t[3] = 1.0f;
510
+ t[4] = 0.0f; t[5] = 0.0f;
511
+ }
512
+
513
+ static void nsvg__xformSetRotation(float* t, float a)
514
+ {
515
+ float cs = cosf(a), sn = sinf(a);
516
+ t[0] = cs; t[1] = sn;
517
+ t[2] = -sn; t[3] = cs;
518
+ t[4] = 0.0f; t[5] = 0.0f;
519
+ }
520
+
521
+ static void nsvg__xformMultiply(float* t, float* s)
522
+ {
523
+ float t0 = t[0] * s[0] + t[1] * s[2];
524
+ float t2 = t[2] * s[0] + t[3] * s[2];
525
+ float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
526
+ t[1] = t[0] * s[1] + t[1] * s[3];
527
+ t[3] = t[2] * s[1] + t[3] * s[3];
528
+ t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
529
+ t[0] = t0;
530
+ t[2] = t2;
531
+ t[4] = t4;
532
+ }
533
+
534
+ static void nsvg__xformInverse(float* inv, float* t)
535
+ {
536
+ double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
537
+ if (det > -1e-6 && det < 1e-6) {
538
+ nsvg__xformIdentity(t);
539
+ return;
540
+ }
541
+ invdet = 1.0 / det;
542
+ inv[0] = (float)(t[3] * invdet);
543
+ inv[2] = (float)(-t[2] * invdet);
544
+ inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
545
+ inv[1] = (float)(-t[1] * invdet);
546
+ inv[3] = (float)(t[0] * invdet);
547
+ inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
548
+ }
549
+
550
+ static void nsvg__xformPremultiply(float* t, float* s)
551
+ {
552
+ float s2[6];
553
+ memcpy(s2, s, sizeof(float)*6);
554
+ nsvg__xformMultiply(s2, t);
555
+ memcpy(t, s2, sizeof(float)*6);
556
+ }
557
+
558
+ static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
559
+ {
560
+ *dx = x*t[0] + y*t[2] + t[4];
561
+ *dy = x*t[1] + y*t[3] + t[5];
562
+ }
563
+
564
+ static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
565
+ {
566
+ *dx = x*t[0] + y*t[2];
567
+ *dy = x*t[1] + y*t[3];
568
+ }
569
+
570
+ #define NSVG_EPSILON (1e-12)
571
+
572
+ static int nsvg__ptInBounds(float* pt, float* bounds)
573
+ {
574
+ return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
575
+ }
576
+
577
+
578
+ static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
579
+ {
580
+ double it = 1.0-t;
581
+ return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
582
+ }
583
+
584
+ static void nsvg__curveBounds(float* bounds, float* curve)
585
+ {
586
+ int i, j, count;
587
+ double roots[2], a, b, c, b2ac, t, v;
588
+ float* v0 = &curve[0];
589
+ float* v1 = &curve[2];
590
+ float* v2 = &curve[4];
591
+ float* v3 = &curve[6];
592
+
593
+ // Start the bounding box by end points
594
+ bounds[0] = nsvg__minf(v0[0], v3[0]);
595
+ bounds[1] = nsvg__minf(v0[1], v3[1]);
596
+ bounds[2] = nsvg__maxf(v0[0], v3[0]);
597
+ bounds[3] = nsvg__maxf(v0[1], v3[1]);
598
+
599
+ // Bezier curve fits inside the convex hull of it's control points.
600
+ // If control points are inside the bounds, we're done.
601
+ if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
602
+ return;
603
+
604
+ // Add bezier curve inflection points in X and Y.
605
+ for (i = 0; i < 2; i++) {
606
+ a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
607
+ b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
608
+ c = 3.0 * v1[i] - 3.0 * v0[i];
609
+ count = 0;
610
+ if (fabs(a) < NSVG_EPSILON) {
611
+ if (fabs(b) > NSVG_EPSILON) {
612
+ t = -c / b;
613
+ if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
614
+ roots[count++] = t;
615
+ }
616
+ } else {
617
+ b2ac = b*b - 4.0*c*a;
618
+ if (b2ac > NSVG_EPSILON) {
619
+ t = (-b + sqrt(b2ac)) / (2.0 * a);
620
+ if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
621
+ roots[count++] = t;
622
+ t = (-b - sqrt(b2ac)) / (2.0 * a);
623
+ if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
624
+ roots[count++] = t;
625
+ }
626
+ }
627
+ for (j = 0; j < count; j++) {
628
+ v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
629
+ bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
630
+ bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
631
+ }
632
+ }
633
+ }
634
+
635
+ static unsigned char nsvg__encodePaintOrder(enum NSVGpaintOrder a, enum NSVGpaintOrder b, enum NSVGpaintOrder c) {
636
+ return (a & 0x03) | ((b & 0x03) << 2) | ((c & 0x03) << 4);
637
+ }
638
+
639
+ static NSVGparser* nsvg__createParser(void)
640
+ {
641
+ NSVGparser* p;
642
+ p = (NSVGparser*)malloc(sizeof(NSVGparser));
643
+ if (p == NULL) goto error;
644
+ memset(p, 0, sizeof(NSVGparser));
645
+
646
+ p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
647
+ if (p->image == NULL) goto error;
648
+ memset(p->image, 0, sizeof(NSVGimage));
649
+
650
+ // Init style
651
+ nsvg__xformIdentity(p->attr[0].xform);
652
+ memset(p->attr[0].id, 0, sizeof p->attr[0].id);
653
+ p->attr[0].fillColor = NSVG_RGB(0,0,0);
654
+ p->attr[0].strokeColor = NSVG_RGB(0,0,0);
655
+ p->attr[0].opacity = 1;
656
+ p->attr[0].fillOpacity = 1;
657
+ p->attr[0].strokeOpacity = 1;
658
+ p->attr[0].stopOpacity = 1;
659
+ p->attr[0].strokeWidth = 1;
660
+ p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
661
+ p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
662
+ p->attr[0].miterLimit = 4;
663
+ p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
664
+ p->attr[0].hasFill = 1;
665
+ p->attr[0].visible = 1;
666
+ p->attr[0].paintOrder = nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS);
667
+
668
+ return p;
669
+
670
+ error:
671
+ if (p) {
672
+ if (p->image) free(p->image);
673
+ free(p);
674
+ }
675
+ return NULL;
676
+ }
677
+ static void nsvg__deleteStyles(NSVGstyleDeclaration* style) {
678
+ while (style) {
679
+ NSVGstyleDeclaration* next = style->next;
680
+ free(style->className);
681
+ free(style->propertiesText);
682
+ free(style);
683
+ style = next;
684
+ }
685
+ }
686
+
687
+ static void nsvg__deletePaths(NSVGpath* path)
688
+ {
689
+ while (path) {
690
+ NSVGpath *next = path->next;
691
+ if (path->pts != NULL)
692
+ free(path->pts);
693
+ free(path);
694
+ path = next;
695
+ }
696
+ }
697
+
698
+ static void nsvg__deletePaint(NSVGpaint* paint)
699
+ {
700
+ if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
701
+ free(paint->gradient);
702
+ }
703
+
704
+ static void nsvg__deleteGradientData(NSVGgradientData* grad)
705
+ {
706
+ NSVGgradientData* next;
707
+ while (grad != NULL) {
708
+ next = grad->next;
709
+ free(grad->stops);
710
+ free(grad);
711
+ grad = next;
712
+ }
713
+ }
714
+
715
+ static void nsvg__deleteParser(NSVGparser* p)
716
+ {
717
+ if (p != NULL) {
718
+ nsvg__deleteStyles(p->styles);
719
+ nsvg__deletePaths(p->plist);
720
+ nsvg__deleteGradientData(p->gradients);
721
+ nsvgDelete(p->image);
722
+ free(p->pts);
723
+ free(p);
724
+ }
725
+ }
726
+
727
+ static void nsvg__resetPath(NSVGparser* p)
728
+ {
729
+ p->npts = 0;
730
+ }
731
+
732
+ static void nsvg__addPoint(NSVGparser* p, float x, float y)
733
+ {
734
+ if (p->npts+1 > p->cpts) {
735
+ p->cpts = p->cpts ? p->cpts*2 : 8;
736
+ p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float));
737
+ if (!p->pts) return;
738
+ }
739
+ p->pts[p->npts*2+0] = x;
740
+ p->pts[p->npts*2+1] = y;
741
+ p->npts++;
742
+ }
743
+
744
+ static void nsvg__moveTo(NSVGparser* p, float x, float y)
745
+ {
746
+ if (p->npts > 0) {
747
+ p->pts[(p->npts-1)*2+0] = x;
748
+ p->pts[(p->npts-1)*2+1] = y;
749
+ } else {
750
+ nsvg__addPoint(p, x, y);
751
+ }
752
+ }
753
+
754
+ static void nsvg__lineTo(NSVGparser* p, float x, float y)
755
+ {
756
+ float px,py, dx,dy;
757
+ if (p->npts > 0) {
758
+ px = p->pts[(p->npts-1)*2+0];
759
+ py = p->pts[(p->npts-1)*2+1];
760
+ dx = x - px;
761
+ dy = y - py;
762
+ nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
763
+ nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
764
+ nsvg__addPoint(p, x, y);
765
+ }
766
+ }
767
+
768
+ static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
769
+ {
770
+ if (p->npts > 0) {
771
+ nsvg__addPoint(p, cpx1, cpy1);
772
+ nsvg__addPoint(p, cpx2, cpy2);
773
+ nsvg__addPoint(p, x, y);
774
+ }
775
+ }
776
+
777
+ static NSVGattrib* nsvg__getAttr(NSVGparser* p)
778
+ {
779
+ return &p->attr[p->attrHead];
780
+ }
781
+
782
+ static void nsvg__pushAttr(NSVGparser* p)
783
+ {
784
+ if (p->attrHead < NSVG_MAX_ATTR-1) {
785
+ p->attrHead++;
786
+ memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));
787
+ }
788
+ }
789
+
790
+ static void nsvg__popAttr(NSVGparser* p)
791
+ {
792
+ if (p->attrHead > 0)
793
+ p->attrHead--;
794
+ }
795
+
796
+ static float nsvg__actualOrigX(NSVGparser* p)
797
+ {
798
+ return p->viewMinx;
799
+ }
800
+
801
+ static float nsvg__actualOrigY(NSVGparser* p)
802
+ {
803
+ return p->viewMiny;
804
+ }
805
+
806
+ static float nsvg__actualWidth(NSVGparser* p)
807
+ {
808
+ return p->viewWidth;
809
+ }
810
+
811
+ static float nsvg__actualHeight(NSVGparser* p)
812
+ {
813
+ return p->viewHeight;
814
+ }
815
+
816
+ static float nsvg__actualLength(NSVGparser* p)
817
+ {
818
+ float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
819
+ return sqrtf(w*w + h*h) / sqrtf(2.0f);
820
+ }
821
+
822
+ static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)
823
+ {
824
+ NSVGattrib* attr = nsvg__getAttr(p);
825
+ switch (c.units) {
826
+ case NSVG_UNITS_USER: return c.value;
827
+ case NSVG_UNITS_PX: return c.value;
828
+ case NSVG_UNITS_PT: return c.value / 72.0f * p->dpi;
829
+ case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi;
830
+ case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi;
831
+ case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi;
832
+ case NSVG_UNITS_IN: return c.value * p->dpi;
833
+ case NSVG_UNITS_EM: return c.value * attr->fontSize;
834
+ case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
835
+ case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length;
836
+ default: return c.value;
837
+ }
838
+ return c.value;
839
+ }
840
+
841
+ static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
842
+ {
843
+ NSVGgradientData* grad = p->gradients;
844
+ if (id == NULL || *id == '\0')
845
+ return NULL;
846
+ while (grad != NULL) {
847
+ if (strcmp(grad->id, id) == 0)
848
+ return grad;
849
+ grad = grad->next;
850
+ }
851
+ return NULL;
852
+ }
853
+
854
+ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float *xform, signed char* paintType)
855
+ {
856
+ NSVGgradientData* data = NULL;
857
+ NSVGgradientData* ref = NULL;
858
+ NSVGgradientStop* stops = NULL;
859
+ NSVGgradient* grad;
860
+ float ox, oy, sw, sh, sl;
861
+ int nstops = 0;
862
+ int refIter;
863
+
864
+ data = nsvg__findGradientData(p, id);
865
+ if (data == NULL) return NULL;
866
+
867
+ // TODO: use ref to fill in all unset values too.
868
+ ref = data;
869
+ refIter = 0;
870
+ while (ref != NULL) {
871
+ NSVGgradientData* nextRef = NULL;
872
+ if (stops == NULL && ref->stops != NULL) {
873
+ stops = ref->stops;
874
+ nstops = ref->nstops;
875
+ break;
876
+ }
877
+ nextRef = nsvg__findGradientData(p, ref->ref);
878
+ if (nextRef == ref) break; // prevent infite loops on malformed data
879
+ ref = nextRef;
880
+ refIter++;
881
+ if (refIter > 32) break; // prevent infite loops on malformed data
882
+ }
883
+ if (stops == NULL) return NULL;
884
+
885
+ grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1));
886
+ if (grad == NULL) return NULL;
887
+
888
+ // The shape width and height.
889
+ if (data->units == NSVG_OBJECT_SPACE) {
890
+ ox = localBounds[0];
891
+ oy = localBounds[1];
892
+ sw = localBounds[2] - localBounds[0];
893
+ sh = localBounds[3] - localBounds[1];
894
+ } else {
895
+ ox = nsvg__actualOrigX(p);
896
+ oy = nsvg__actualOrigY(p);
897
+ sw = nsvg__actualWidth(p);
898
+ sh = nsvg__actualHeight(p);
899
+ }
900
+ sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);
901
+
902
+ if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
903
+ float x1, y1, x2, y2, dx, dy;
904
+ x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
905
+ y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
906
+ x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
907
+ y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
908
+ // Calculate transform aligned to the line
909
+ dx = x2 - x1;
910
+ dy = y2 - y1;
911
+ grad->xform[0] = dy; grad->xform[1] = -dx;
912
+ grad->xform[2] = dx; grad->xform[3] = dy;
913
+ grad->xform[4] = x1; grad->xform[5] = y1;
914
+ } else {
915
+ float cx, cy, fx, fy, r;
916
+ cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
917
+ cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
918
+ fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
919
+ fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
920
+ r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
921
+ // Calculate transform aligned to the circle
922
+ grad->xform[0] = r; grad->xform[1] = 0;
923
+ grad->xform[2] = 0; grad->xform[3] = r;
924
+ grad->xform[4] = cx; grad->xform[5] = cy;
925
+ grad->fx = fx / r;
926
+ grad->fy = fy / r;
927
+ }
928
+
929
+ nsvg__xformMultiply(grad->xform, data->xform);
930
+ nsvg__xformMultiply(grad->xform, xform);
931
+
932
+ grad->spread = data->spread;
933
+ memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
934
+ grad->nstops = nstops;
935
+
936
+ *paintType = data->type;
937
+
938
+ return grad;
939
+ }
940
+
941
+ static float nsvg__getAverageScale(float* t)
942
+ {
943
+ float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
944
+ float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
945
+ return (sx + sy) * 0.5f;
946
+ }
947
+
948
+ static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
949
+ {
950
+ NSVGpath* path;
951
+ float curve[4*2], curveBounds[4];
952
+ int i, first = 1;
953
+ for (path = shape->paths; path != NULL; path = path->next) {
954
+ nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
955
+ for (i = 0; i < path->npts-1; i += 3) {
956
+ nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);
957
+ nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);
958
+ nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);
959
+ nsvg__curveBounds(curveBounds, curve);
960
+ if (first) {
961
+ bounds[0] = curveBounds[0];
962
+ bounds[1] = curveBounds[1];
963
+ bounds[2] = curveBounds[2];
964
+ bounds[3] = curveBounds[3];
965
+ first = 0;
966
+ } else {
967
+ bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
968
+ bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
969
+ bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
970
+ bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
971
+ }
972
+ curve[0] = curve[6];
973
+ curve[1] = curve[7];
974
+ }
975
+ }
976
+ }
977
+
978
+ static void nsvg__addShape(NSVGparser* p)
979
+ {
980
+ NSVGattrib* attr = nsvg__getAttr(p);
981
+ float scale = 1.0f;
982
+ NSVGshape* shape;
983
+ NSVGpath* path;
984
+ int i;
985
+
986
+ if (p->plist == NULL)
987
+ return;
988
+
989
+ shape = (NSVGshape*)malloc(sizeof(NSVGshape));
990
+ if (shape == NULL) goto error;
991
+ memset(shape, 0, sizeof(NSVGshape));
992
+
993
+ memcpy(shape->id, attr->id, sizeof shape->id);
994
+ memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient);
995
+ memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient);
996
+ memcpy(shape->xform, attr->xform, sizeof shape->xform);
997
+ scale = nsvg__getAverageScale(attr->xform);
998
+ shape->strokeWidth = attr->strokeWidth * scale;
999
+ shape->strokeDashOffset = attr->strokeDashOffset * scale;
1000
+ shape->strokeDashCount = (char)attr->strokeDashCount;
1001
+ for (i = 0; i < attr->strokeDashCount; i++)
1002
+ shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
1003
+ shape->strokeLineJoin = attr->strokeLineJoin;
1004
+ shape->strokeLineCap = attr->strokeLineCap;
1005
+ shape->miterLimit = attr->miterLimit;
1006
+ shape->fillRule = attr->fillRule;
1007
+ shape->opacity = attr->opacity;
1008
+ shape->paintOrder = attr->paintOrder;
1009
+
1010
+ shape->paths = p->plist;
1011
+ p->plist = NULL;
1012
+
1013
+ // Calculate shape bounds
1014
+ shape->bounds[0] = shape->paths->bounds[0];
1015
+ shape->bounds[1] = shape->paths->bounds[1];
1016
+ shape->bounds[2] = shape->paths->bounds[2];
1017
+ shape->bounds[3] = shape->paths->bounds[3];
1018
+ for (path = shape->paths->next; path != NULL; path = path->next) {
1019
+ shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
1020
+ shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
1021
+ shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
1022
+ shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
1023
+ }
1024
+
1025
+ // Set fill
1026
+ if (attr->hasFill == 0) {
1027
+ shape->fill.type = NSVG_PAINT_NONE;
1028
+ } else if (attr->hasFill == 1) {
1029
+ shape->fill.type = NSVG_PAINT_COLOR;
1030
+ shape->fill.color = attr->fillColor;
1031
+ shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
1032
+ } else if (attr->hasFill == 2) {
1033
+ shape->fill.type = NSVG_PAINT_UNDEF;
1034
+ }
1035
+
1036
+ // Set stroke
1037
+ if (attr->hasStroke == 0) {
1038
+ shape->stroke.type = NSVG_PAINT_NONE;
1039
+ } else if (attr->hasStroke == 1) {
1040
+ shape->stroke.type = NSVG_PAINT_COLOR;
1041
+ shape->stroke.color = attr->strokeColor;
1042
+ shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
1043
+ } else if (attr->hasStroke == 2) {
1044
+ shape->stroke.type = NSVG_PAINT_UNDEF;
1045
+ }
1046
+
1047
+ // Set flags
1048
+ shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
1049
+
1050
+ // Add to tail
1051
+ if (p->image->shapes == NULL)
1052
+ p->image->shapes = shape;
1053
+ else
1054
+ p->shapesTail->next = shape;
1055
+ p->shapesTail = shape;
1056
+
1057
+ return;
1058
+
1059
+ error:
1060
+ if (shape) free(shape);
1061
+ }
1062
+
1063
+ static void nsvg__addPath(NSVGparser* p, char closed)
1064
+ {
1065
+ NSVGattrib* attr = nsvg__getAttr(p);
1066
+ NSVGpath* path = NULL;
1067
+ float bounds[4];
1068
+ float* curve;
1069
+ int i;
1070
+
1071
+ if (p->npts < 4)
1072
+ return;
1073
+
1074
+ if (closed)
1075
+ nsvg__lineTo(p, p->pts[0], p->pts[1]);
1076
+
1077
+ // Expect 1 + N*3 points (N = number of cubic bezier segments).
1078
+ if ((p->npts % 3) != 1)
1079
+ return;
1080
+
1081
+ path = (NSVGpath*)malloc(sizeof(NSVGpath));
1082
+ if (path == NULL) goto error;
1083
+ memset(path, 0, sizeof(NSVGpath));
1084
+
1085
+ path->pts = (float*)malloc(p->npts*2*sizeof(float));
1086
+ if (path->pts == NULL) goto error;
1087
+ path->closed = closed;
1088
+ path->npts = p->npts;
1089
+
1090
+ // Transform path.
1091
+ for (i = 0; i < p->npts; ++i)
1092
+ nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform);
1093
+
1094
+ // Find bounds
1095
+ for (i = 0; i < path->npts-1; i += 3) {
1096
+ curve = &path->pts[i*2];
1097
+ nsvg__curveBounds(bounds, curve);
1098
+ if (i == 0) {
1099
+ path->bounds[0] = bounds[0];
1100
+ path->bounds[1] = bounds[1];
1101
+ path->bounds[2] = bounds[2];
1102
+ path->bounds[3] = bounds[3];
1103
+ } else {
1104
+ path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
1105
+ path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
1106
+ path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
1107
+ path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
1108
+ }
1109
+ }
1110
+
1111
+ path->next = p->plist;
1112
+ p->plist = path;
1113
+
1114
+ return;
1115
+
1116
+ error:
1117
+ if (path != NULL) {
1118
+ if (path->pts != NULL) free(path->pts);
1119
+ free(path);
1120
+ }
1121
+ }
1122
+
1123
+ // We roll our own string to float because the std library one uses locale and messes things up.
1124
+ static double nsvg__atof(const char* s)
1125
+ {
1126
+ char* cur = (char*)s;
1127
+ char* end = NULL;
1128
+ double res = 0.0, sign = 1.0;
1129
+ long long intPart = 0, fracPart = 0;
1130
+ char hasIntPart = 0, hasFracPart = 0;
1131
+
1132
+ // Parse optional sign
1133
+ if (*cur == '+') {
1134
+ cur++;
1135
+ } else if (*cur == '-') {
1136
+ sign = -1;
1137
+ cur++;
1138
+ }
1139
+
1140
+ // Parse integer part
1141
+ if (nsvg__isdigit(*cur)) {
1142
+ // Parse digit sequence
1143
+ intPart = strtoll(cur, &end, 10);
1144
+ if (cur != end) {
1145
+ res = (double)intPart;
1146
+ hasIntPart = 1;
1147
+ cur = end;
1148
+ }
1149
+ }
1150
+
1151
+ // Parse fractional part.
1152
+ if (*cur == '.') {
1153
+ cur++; // Skip '.'
1154
+ if (nsvg__isdigit(*cur)) {
1155
+ // Parse digit sequence
1156
+ fracPart = strtoll(cur, &end, 10);
1157
+ if (cur != end) {
1158
+ res += (double)fracPart / pow(10.0, (double)(end - cur));
1159
+ hasFracPart = 1;
1160
+ cur = end;
1161
+ }
1162
+ }
1163
+ }
1164
+
1165
+ // A valid number should have integer or fractional part.
1166
+ if (!hasIntPart && !hasFracPart)
1167
+ return 0.0;
1168
+
1169
+ // Parse optional exponent
1170
+ if (*cur == 'e' || *cur == 'E') {
1171
+ long expPart = 0;
1172
+ cur++; // skip 'E'
1173
+ expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
1174
+ if (cur != end) {
1175
+ res *= pow(10.0, (double)expPart);
1176
+ }
1177
+ }
1178
+
1179
+ return res * sign;
1180
+ }
1181
+
1182
+
1183
+ static const char* nsvg__parseNumber(const char* s, char* it, const int size)
1184
+ {
1185
+ const int last = size-1;
1186
+ int i = 0;
1187
+
1188
+ // sign
1189
+ if (*s == '-' || *s == '+') {
1190
+ if (i < last) it[i++] = *s;
1191
+ s++;
1192
+ }
1193
+ // integer part
1194
+ while (*s && nsvg__isdigit(*s)) {
1195
+ if (i < last) it[i++] = *s;
1196
+ s++;
1197
+ }
1198
+ if (*s == '.') {
1199
+ // decimal point
1200
+ if (i < last) it[i++] = *s;
1201
+ s++;
1202
+ // fraction part
1203
+ while (*s && nsvg__isdigit(*s)) {
1204
+ if (i < last) it[i++] = *s;
1205
+ s++;
1206
+ }
1207
+ }
1208
+ // exponent
1209
+ if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) {
1210
+ if (i < last) it[i++] = *s;
1211
+ s++;
1212
+ if (*s == '-' || *s == '+') {
1213
+ if (i < last) it[i++] = *s;
1214
+ s++;
1215
+ }
1216
+ while (*s && nsvg__isdigit(*s)) {
1217
+ if (i < last) it[i++] = *s;
1218
+ s++;
1219
+ }
1220
+ }
1221
+ it[i] = '\0';
1222
+
1223
+ return s;
1224
+ }
1225
+
1226
+ static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it)
1227
+ {
1228
+ it[0] = '\0';
1229
+ while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
1230
+ if (!*s) return s;
1231
+ if (*s == '0' || *s == '1') {
1232
+ it[0] = *s++;
1233
+ it[1] = '\0';
1234
+ return s;
1235
+ }
1236
+ return s;
1237
+ }
1238
+
1239
+ static const char* nsvg__getNextPathItem(const char* s, char* it)
1240
+ {
1241
+ it[0] = '\0';
1242
+ // Skip white spaces and commas
1243
+ while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
1244
+ if (!*s) return s;
1245
+ if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
1246
+ s = nsvg__parseNumber(s, it, 64);
1247
+ } else {
1248
+ // Parse command
1249
+ it[0] = *s++;
1250
+ it[1] = '\0';
1251
+ return s;
1252
+ }
1253
+
1254
+ return s;
1255
+ }
1256
+
1257
+ static unsigned int nsvg__parseColorHex(const char* str)
1258
+ {
1259
+ unsigned int r=0, g=0, b=0;
1260
+ if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) // 2 digit hex
1261
+ return NSVG_RGB(r, g, b);
1262
+ if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) // 1 digit hex, e.g. #abc -> 0xccbbaa
1263
+ return NSVG_RGB(r*17, g*17, b*17); // same effect as (r<<4|r), (g<<4|g), ..
1264
+ return NSVG_RGB(128, 128, 128);
1265
+ }
1266
+
1267
+ // Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters).
1268
+ // This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors
1269
+ // for backwards compatibility. Note: other image viewers return black instead.
1270
+
1271
+ static unsigned int nsvg__parseColorRGB(const char* str)
1272
+ {
1273
+ int i;
1274
+ unsigned int rgbi[3];
1275
+ float rgbf[3];
1276
+ // try decimal integers first
1277
+ if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) {
1278
+ // integers failed, try percent values (float, locale independent)
1279
+ const char delimiter[3] = {',', ',', ')'};
1280
+ str += 4; // skip "rgb("
1281
+ for (i = 0; i < 3; i++) {
1282
+ while (*str && (nsvg__isspace(*str))) str++; // skip leading spaces
1283
+ if (*str == '+') str++; // skip '+' (don't allow '-')
1284
+ if (!*str) break;
1285
+ rgbf[i] = nsvg__atof(str);
1286
+
1287
+ // Note 1: it would be great if nsvg__atof() returned how many
1288
+ // bytes it consumed but it doesn't. We need to skip the number,
1289
+ // the '%' character, spaces, and the delimiter ',' or ')'.
1290
+
1291
+ // Note 2: The following code does not allow values like "33.%",
1292
+ // i.e. a decimal point w/o fractional part, but this is consistent
1293
+ // with other image viewers, e.g. firefox, chrome, eog, gimp.
1294
+
1295
+ while (*str && nsvg__isdigit(*str)) str++; // skip integer part
1296
+ if (*str == '.') {
1297
+ str++;
1298
+ if (!nsvg__isdigit(*str)) break; // error: no digit after '.'
1299
+ while (*str && nsvg__isdigit(*str)) str++; // skip fractional part
1300
+ }
1301
+ if (*str == '%') str++; else break;
1302
+ while (*str && nsvg__isspace(*str)) str++;
1303
+ if (*str == delimiter[i]) str++;
1304
+ else break;
1305
+ }
1306
+ if (i == 3) {
1307
+ rgbi[0] = roundf(rgbf[0] * 2.55f);
1308
+ rgbi[1] = roundf(rgbf[1] * 2.55f);
1309
+ rgbi[2] = roundf(rgbf[2] * 2.55f);
1310
+ } else {
1311
+ rgbi[0] = rgbi[1] = rgbi[2] = 128;
1312
+ }
1313
+ }
1314
+ // clip values as the CSS spec requires
1315
+ for (i = 0; i < 3; i++) {
1316
+ if (rgbi[i] > 255) rgbi[i] = 255;
1317
+ }
1318
+ return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]);
1319
+ }
1320
+
1321
+ typedef struct NSVGNamedColor {
1322
+ const char* name;
1323
+ unsigned int color;
1324
+ } NSVGNamedColor;
1325
+
1326
+ NSVGNamedColor nsvg__colors[] = {
1327
+
1328
+ { "red", NSVG_RGB(255, 0, 0) },
1329
+ { "green", NSVG_RGB( 0, 128, 0) },
1330
+ { "blue", NSVG_RGB( 0, 0, 255) },
1331
+ { "yellow", NSVG_RGB(255, 255, 0) },
1332
+ { "cyan", NSVG_RGB( 0, 255, 255) },
1333
+ { "magenta", NSVG_RGB(255, 0, 255) },
1334
+ { "black", NSVG_RGB( 0, 0, 0) },
1335
+ { "grey", NSVG_RGB(128, 128, 128) },
1336
+ { "gray", NSVG_RGB(128, 128, 128) },
1337
+ { "white", NSVG_RGB(255, 255, 255) },
1338
+
1339
+ #ifdef NANOSVG_ALL_COLOR_KEYWORDS
1340
+ { "aliceblue", NSVG_RGB(240, 248, 255) },
1341
+ { "antiquewhite", NSVG_RGB(250, 235, 215) },
1342
+ { "aqua", NSVG_RGB( 0, 255, 255) },
1343
+ { "aquamarine", NSVG_RGB(127, 255, 212) },
1344
+ { "azure", NSVG_RGB(240, 255, 255) },
1345
+ { "beige", NSVG_RGB(245, 245, 220) },
1346
+ { "bisque", NSVG_RGB(255, 228, 196) },
1347
+ { "blanchedalmond", NSVG_RGB(255, 235, 205) },
1348
+ { "blueviolet", NSVG_RGB(138, 43, 226) },
1349
+ { "brown", NSVG_RGB(165, 42, 42) },
1350
+ { "burlywood", NSVG_RGB(222, 184, 135) },
1351
+ { "cadetblue", NSVG_RGB( 95, 158, 160) },
1352
+ { "chartreuse", NSVG_RGB(127, 255, 0) },
1353
+ { "chocolate", NSVG_RGB(210, 105, 30) },
1354
+ { "coral", NSVG_RGB(255, 127, 80) },
1355
+ { "cornflowerblue", NSVG_RGB(100, 149, 237) },
1356
+ { "cornsilk", NSVG_RGB(255, 248, 220) },
1357
+ { "crimson", NSVG_RGB(220, 20, 60) },
1358
+ { "darkblue", NSVG_RGB( 0, 0, 139) },
1359
+ { "darkcyan", NSVG_RGB( 0, 139, 139) },
1360
+ { "darkgoldenrod", NSVG_RGB(184, 134, 11) },
1361
+ { "darkgray", NSVG_RGB(169, 169, 169) },
1362
+ { "darkgreen", NSVG_RGB( 0, 100, 0) },
1363
+ { "darkgrey", NSVG_RGB(169, 169, 169) },
1364
+ { "darkkhaki", NSVG_RGB(189, 183, 107) },
1365
+ { "darkmagenta", NSVG_RGB(139, 0, 139) },
1366
+ { "darkolivegreen", NSVG_RGB( 85, 107, 47) },
1367
+ { "darkorange", NSVG_RGB(255, 140, 0) },
1368
+ { "darkorchid", NSVG_RGB(153, 50, 204) },
1369
+ { "darkred", NSVG_RGB(139, 0, 0) },
1370
+ { "darksalmon", NSVG_RGB(233, 150, 122) },
1371
+ { "darkseagreen", NSVG_RGB(143, 188, 143) },
1372
+ { "darkslateblue", NSVG_RGB( 72, 61, 139) },
1373
+ { "darkslategray", NSVG_RGB( 47, 79, 79) },
1374
+ { "darkslategrey", NSVG_RGB( 47, 79, 79) },
1375
+ { "darkturquoise", NSVG_RGB( 0, 206, 209) },
1376
+ { "darkviolet", NSVG_RGB(148, 0, 211) },
1377
+ { "deeppink", NSVG_RGB(255, 20, 147) },
1378
+ { "deepskyblue", NSVG_RGB( 0, 191, 255) },
1379
+ { "dimgray", NSVG_RGB(105, 105, 105) },
1380
+ { "dimgrey", NSVG_RGB(105, 105, 105) },
1381
+ { "dodgerblue", NSVG_RGB( 30, 144, 255) },
1382
+ { "firebrick", NSVG_RGB(178, 34, 34) },
1383
+ { "floralwhite", NSVG_RGB(255, 250, 240) },
1384
+ { "forestgreen", NSVG_RGB( 34, 139, 34) },
1385
+ { "fuchsia", NSVG_RGB(255, 0, 255) },
1386
+ { "gainsboro", NSVG_RGB(220, 220, 220) },
1387
+ { "ghostwhite", NSVG_RGB(248, 248, 255) },
1388
+ { "gold", NSVG_RGB(255, 215, 0) },
1389
+ { "goldenrod", NSVG_RGB(218, 165, 32) },
1390
+ { "greenyellow", NSVG_RGB(173, 255, 47) },
1391
+ { "honeydew", NSVG_RGB(240, 255, 240) },
1392
+ { "hotpink", NSVG_RGB(255, 105, 180) },
1393
+ { "indianred", NSVG_RGB(205, 92, 92) },
1394
+ { "indigo", NSVG_RGB( 75, 0, 130) },
1395
+ { "ivory", NSVG_RGB(255, 255, 240) },
1396
+ { "khaki", NSVG_RGB(240, 230, 140) },
1397
+ { "lavender", NSVG_RGB(230, 230, 250) },
1398
+ { "lavenderblush", NSVG_RGB(255, 240, 245) },
1399
+ { "lawngreen", NSVG_RGB(124, 252, 0) },
1400
+ { "lemonchiffon", NSVG_RGB(255, 250, 205) },
1401
+ { "lightblue", NSVG_RGB(173, 216, 230) },
1402
+ { "lightcoral", NSVG_RGB(240, 128, 128) },
1403
+ { "lightcyan", NSVG_RGB(224, 255, 255) },
1404
+ { "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
1405
+ { "lightgray", NSVG_RGB(211, 211, 211) },
1406
+ { "lightgreen", NSVG_RGB(144, 238, 144) },
1407
+ { "lightgrey", NSVG_RGB(211, 211, 211) },
1408
+ { "lightpink", NSVG_RGB(255, 182, 193) },
1409
+ { "lightsalmon", NSVG_RGB(255, 160, 122) },
1410
+ { "lightseagreen", NSVG_RGB( 32, 178, 170) },
1411
+ { "lightskyblue", NSVG_RGB(135, 206, 250) },
1412
+ { "lightslategray", NSVG_RGB(119, 136, 153) },
1413
+ { "lightslategrey", NSVG_RGB(119, 136, 153) },
1414
+ { "lightsteelblue", NSVG_RGB(176, 196, 222) },
1415
+ { "lightyellow", NSVG_RGB(255, 255, 224) },
1416
+ { "lime", NSVG_RGB( 0, 255, 0) },
1417
+ { "limegreen", NSVG_RGB( 50, 205, 50) },
1418
+ { "linen", NSVG_RGB(250, 240, 230) },
1419
+ { "maroon", NSVG_RGB(128, 0, 0) },
1420
+ { "mediumaquamarine", NSVG_RGB(102, 205, 170) },
1421
+ { "mediumblue", NSVG_RGB( 0, 0, 205) },
1422
+ { "mediumorchid", NSVG_RGB(186, 85, 211) },
1423
+ { "mediumpurple", NSVG_RGB(147, 112, 219) },
1424
+ { "mediumseagreen", NSVG_RGB( 60, 179, 113) },
1425
+ { "mediumslateblue", NSVG_RGB(123, 104, 238) },
1426
+ { "mediumspringgreen", NSVG_RGB( 0, 250, 154) },
1427
+ { "mediumturquoise", NSVG_RGB( 72, 209, 204) },
1428
+ { "mediumvioletred", NSVG_RGB(199, 21, 133) },
1429
+ { "midnightblue", NSVG_RGB( 25, 25, 112) },
1430
+ { "mintcream", NSVG_RGB(245, 255, 250) },
1431
+ { "mistyrose", NSVG_RGB(255, 228, 225) },
1432
+ { "moccasin", NSVG_RGB(255, 228, 181) },
1433
+ { "navajowhite", NSVG_RGB(255, 222, 173) },
1434
+ { "navy", NSVG_RGB( 0, 0, 128) },
1435
+ { "oldlace", NSVG_RGB(253, 245, 230) },
1436
+ { "olive", NSVG_RGB(128, 128, 0) },
1437
+ { "olivedrab", NSVG_RGB(107, 142, 35) },
1438
+ { "orange", NSVG_RGB(255, 165, 0) },
1439
+ { "orangered", NSVG_RGB(255, 69, 0) },
1440
+ { "orchid", NSVG_RGB(218, 112, 214) },
1441
+ { "palegoldenrod", NSVG_RGB(238, 232, 170) },
1442
+ { "palegreen", NSVG_RGB(152, 251, 152) },
1443
+ { "paleturquoise", NSVG_RGB(175, 238, 238) },
1444
+ { "palevioletred", NSVG_RGB(219, 112, 147) },
1445
+ { "papayawhip", NSVG_RGB(255, 239, 213) },
1446
+ { "peachpuff", NSVG_RGB(255, 218, 185) },
1447
+ { "peru", NSVG_RGB(205, 133, 63) },
1448
+ { "pink", NSVG_RGB(255, 192, 203) },
1449
+ { "plum", NSVG_RGB(221, 160, 221) },
1450
+ { "powderblue", NSVG_RGB(176, 224, 230) },
1451
+ { "purple", NSVG_RGB(128, 0, 128) },
1452
+ { "rosybrown", NSVG_RGB(188, 143, 143) },
1453
+ { "royalblue", NSVG_RGB( 65, 105, 225) },
1454
+ { "saddlebrown", NSVG_RGB(139, 69, 19) },
1455
+ { "salmon", NSVG_RGB(250, 128, 114) },
1456
+ { "sandybrown", NSVG_RGB(244, 164, 96) },
1457
+ { "seagreen", NSVG_RGB( 46, 139, 87) },
1458
+ { "seashell", NSVG_RGB(255, 245, 238) },
1459
+ { "sienna", NSVG_RGB(160, 82, 45) },
1460
+ { "silver", NSVG_RGB(192, 192, 192) },
1461
+ { "skyblue", NSVG_RGB(135, 206, 235) },
1462
+ { "slateblue", NSVG_RGB(106, 90, 205) },
1463
+ { "slategray", NSVG_RGB(112, 128, 144) },
1464
+ { "slategrey", NSVG_RGB(112, 128, 144) },
1465
+ { "snow", NSVG_RGB(255, 250, 250) },
1466
+ { "springgreen", NSVG_RGB( 0, 255, 127) },
1467
+ { "steelblue", NSVG_RGB( 70, 130, 180) },
1468
+ { "tan", NSVG_RGB(210, 180, 140) },
1469
+ { "teal", NSVG_RGB( 0, 128, 128) },
1470
+ { "thistle", NSVG_RGB(216, 191, 216) },
1471
+ { "tomato", NSVG_RGB(255, 99, 71) },
1472
+ { "turquoise", NSVG_RGB( 64, 224, 208) },
1473
+ { "violet", NSVG_RGB(238, 130, 238) },
1474
+ { "wheat", NSVG_RGB(245, 222, 179) },
1475
+ { "whitesmoke", NSVG_RGB(245, 245, 245) },
1476
+ { "yellowgreen", NSVG_RGB(154, 205, 50) },
1477
+ #endif
1478
+ };
1479
+
1480
+ static unsigned int nsvg__parseColorName(const char* str)
1481
+ {
1482
+ int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
1483
+
1484
+ for (i = 0; i < ncolors; i++) {
1485
+ if (strcmp(nsvg__colors[i].name, str) == 0) {
1486
+ return nsvg__colors[i].color;
1487
+ }
1488
+ }
1489
+
1490
+ return NSVG_RGB(128, 128, 128);
1491
+ }
1492
+
1493
+ static unsigned int nsvg__parseColor(const char* str)
1494
+ {
1495
+ size_t len = 0;
1496
+ while(*str == ' ') ++str;
1497
+ len = strlen(str);
1498
+ if (len >= 1 && *str == '#')
1499
+ return nsvg__parseColorHex(str);
1500
+ else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
1501
+ return nsvg__parseColorRGB(str);
1502
+ return nsvg__parseColorName(str);
1503
+ }
1504
+
1505
+ static float nsvg__parseOpacity(const char* str)
1506
+ {
1507
+ float val = nsvg__atof(str);
1508
+ if (val < 0.0f) val = 0.0f;
1509
+ if (val > 1.0f) val = 1.0f;
1510
+ return val;
1511
+ }
1512
+
1513
+ static float nsvg__parseMiterLimit(const char* str)
1514
+ {
1515
+ float val = nsvg__atof(str);
1516
+ if (val < 0.0f) val = 0.0f;
1517
+ return val;
1518
+ }
1519
+
1520
+ static int nsvg__parseUnits(const char* units)
1521
+ {
1522
+ if (units[0] == 'p' && units[1] == 'x')
1523
+ return NSVG_UNITS_PX;
1524
+ else if (units[0] == 'p' && units[1] == 't')
1525
+ return NSVG_UNITS_PT;
1526
+ else if (units[0] == 'p' && units[1] == 'c')
1527
+ return NSVG_UNITS_PC;
1528
+ else if (units[0] == 'm' && units[1] == 'm')
1529
+ return NSVG_UNITS_MM;
1530
+ else if (units[0] == 'c' && units[1] == 'm')
1531
+ return NSVG_UNITS_CM;
1532
+ else if (units[0] == 'i' && units[1] == 'n')
1533
+ return NSVG_UNITS_IN;
1534
+ else if (units[0] == '%')
1535
+ return NSVG_UNITS_PERCENT;
1536
+ else if (units[0] == 'e' && units[1] == 'm')
1537
+ return NSVG_UNITS_EM;
1538
+ else if (units[0] == 'e' && units[1] == 'x')
1539
+ return NSVG_UNITS_EX;
1540
+ return NSVG_UNITS_USER;
1541
+ }
1542
+
1543
+ static int nsvg__isCoordinate(const char* s)
1544
+ {
1545
+ // optional sign
1546
+ if (*s == '-' || *s == '+')
1547
+ s++;
1548
+ // must have at least one digit, or start by a dot
1549
+ return (nsvg__isdigit(*s) || *s == '.');
1550
+ }
1551
+
1552
+ static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
1553
+ {
1554
+ NSVGcoordinate coord = {0, NSVG_UNITS_USER};
1555
+ char buf[64];
1556
+ coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
1557
+ coord.value = nsvg__atof(buf);
1558
+ return coord;
1559
+ }
1560
+
1561
+ static NSVGcoordinate nsvg__coord(float v, int units)
1562
+ {
1563
+ NSVGcoordinate coord = {v, units};
1564
+ return coord;
1565
+ }
1566
+
1567
+ static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)
1568
+ {
1569
+ NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
1570
+ return nsvg__convertToPixels(p, coord, orig, length);
1571
+ }
1572
+
1573
+ static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)
1574
+ {
1575
+ const char* end;
1576
+ const char* ptr;
1577
+ char it[64];
1578
+
1579
+ *na = 0;
1580
+ ptr = str;
1581
+ while (*ptr && *ptr != '(') ++ptr;
1582
+ if (*ptr == 0)
1583
+ return 1;
1584
+ end = ptr;
1585
+ while (*end && *end != ')') ++end;
1586
+ if (*end == 0)
1587
+ return 1;
1588
+
1589
+ while (ptr < end) {
1590
+ if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
1591
+ if (*na >= maxNa) return 0;
1592
+ ptr = nsvg__parseNumber(ptr, it, 64);
1593
+ args[(*na)++] = (float)nsvg__atof(it);
1594
+ } else {
1595
+ ++ptr;
1596
+ }
1597
+ }
1598
+ return (int)(end - str);
1599
+ }
1600
+
1601
+
1602
+ static int nsvg__parseMatrix(float* xform, const char* str)
1603
+ {
1604
+ float t[6];
1605
+ int na = 0;
1606
+ int len = nsvg__parseTransformArgs(str, t, 6, &na);
1607
+ if (na != 6) return len;
1608
+ memcpy(xform, t, sizeof(float)*6);
1609
+ return len;
1610
+ }
1611
+
1612
+ static int nsvg__parseTranslate(float* xform, const char* str)
1613
+ {
1614
+ float args[2];
1615
+ float t[6];
1616
+ int na = 0;
1617
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
1618
+ if (na == 1) args[1] = 0.0;
1619
+
1620
+ nsvg__xformSetTranslation(t, args[0], args[1]);
1621
+ memcpy(xform, t, sizeof(float)*6);
1622
+ return len;
1623
+ }
1624
+
1625
+ static int nsvg__parseScale(float* xform, const char* str)
1626
+ {
1627
+ float args[2];
1628
+ int na = 0;
1629
+ float t[6];
1630
+ int len = nsvg__parseTransformArgs(str, args, 2, &na);
1631
+ if (na == 1) args[1] = args[0];
1632
+ nsvg__xformSetScale(t, args[0], args[1]);
1633
+ memcpy(xform, t, sizeof(float)*6);
1634
+ return len;
1635
+ }
1636
+
1637
+ static int nsvg__parseSkewX(float* xform, const char* str)
1638
+ {
1639
+ float args[1];
1640
+ int na = 0;
1641
+ float t[6];
1642
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
1643
+ nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
1644
+ memcpy(xform, t, sizeof(float)*6);
1645
+ return len;
1646
+ }
1647
+
1648
+ static int nsvg__parseSkewY(float* xform, const char* str)
1649
+ {
1650
+ float args[1];
1651
+ int na = 0;
1652
+ float t[6];
1653
+ int len = nsvg__parseTransformArgs(str, args, 1, &na);
1654
+ nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
1655
+ memcpy(xform, t, sizeof(float)*6);
1656
+ return len;
1657
+ }
1658
+
1659
+ static int nsvg__parseRotate(float* xform, const char* str)
1660
+ {
1661
+ float args[3];
1662
+ int na = 0;
1663
+ float m[6];
1664
+ float t[6];
1665
+ int len = nsvg__parseTransformArgs(str, args, 3, &na);
1666
+ if (na == 1)
1667
+ args[1] = args[2] = 0.0f;
1668
+ nsvg__xformIdentity(m);
1669
+
1670
+ if (na > 1) {
1671
+ nsvg__xformSetTranslation(t, -args[1], -args[2]);
1672
+ nsvg__xformMultiply(m, t);
1673
+ }
1674
+
1675
+ nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
1676
+ nsvg__xformMultiply(m, t);
1677
+
1678
+ if (na > 1) {
1679
+ nsvg__xformSetTranslation(t, args[1], args[2]);
1680
+ nsvg__xformMultiply(m, t);
1681
+ }
1682
+
1683
+ memcpy(xform, m, sizeof(float)*6);
1684
+
1685
+ return len;
1686
+ }
1687
+
1688
+ static void nsvg__parseTransform(float* xform, const char* str)
1689
+ {
1690
+ float t[6];
1691
+ int len;
1692
+ nsvg__xformIdentity(xform);
1693
+ while (*str)
1694
+ {
1695
+ if (strncmp(str, "matrix", 6) == 0)
1696
+ len = nsvg__parseMatrix(t, str);
1697
+ else if (strncmp(str, "translate", 9) == 0)
1698
+ len = nsvg__parseTranslate(t, str);
1699
+ else if (strncmp(str, "scale", 5) == 0)
1700
+ len = nsvg__parseScale(t, str);
1701
+ else if (strncmp(str, "rotate", 6) == 0)
1702
+ len = nsvg__parseRotate(t, str);
1703
+ else if (strncmp(str, "skewX", 5) == 0)
1704
+ len = nsvg__parseSkewX(t, str);
1705
+ else if (strncmp(str, "skewY", 5) == 0)
1706
+ len = nsvg__parseSkewY(t, str);
1707
+ else{
1708
+ ++str;
1709
+ continue;
1710
+ }
1711
+ if (len != 0) {
1712
+ str += len;
1713
+ } else {
1714
+ ++str;
1715
+ continue;
1716
+ }
1717
+
1718
+ nsvg__xformPremultiply(xform, t);
1719
+ }
1720
+ }
1721
+
1722
+ static void nsvg__parseUrl(char* id, const char* str)
1723
+ {
1724
+ int i = 0;
1725
+ str += 4; // "url(";
1726
+ if (*str && *str == '#')
1727
+ str++;
1728
+ while (i < 63 && *str && *str != ')') {
1729
+ id[i] = *str++;
1730
+ i++;
1731
+ }
1732
+ id[i] = '\0';
1733
+ }
1734
+
1735
+ static char nsvg__parseLineCap(const char* str)
1736
+ {
1737
+ if (strcmp(str, "butt") == 0)
1738
+ return NSVG_CAP_BUTT;
1739
+ else if (strcmp(str, "round") == 0)
1740
+ return NSVG_CAP_ROUND;
1741
+ else if (strcmp(str, "square") == 0)
1742
+ return NSVG_CAP_SQUARE;
1743
+ // TODO: handle inherit.
1744
+ return NSVG_CAP_BUTT;
1745
+ }
1746
+
1747
+ static char nsvg__parseLineJoin(const char* str)
1748
+ {
1749
+ if (strcmp(str, "miter") == 0)
1750
+ return NSVG_JOIN_MITER;
1751
+ else if (strcmp(str, "round") == 0)
1752
+ return NSVG_JOIN_ROUND;
1753
+ else if (strcmp(str, "bevel") == 0)
1754
+ return NSVG_JOIN_BEVEL;
1755
+ // TODO: handle inherit.
1756
+ return NSVG_JOIN_MITER;
1757
+ }
1758
+
1759
+ static char nsvg__parseFillRule(const char* str)
1760
+ {
1761
+ if (strcmp(str, "nonzero") == 0)
1762
+ return NSVG_FILLRULE_NONZERO;
1763
+ else if (strcmp(str, "evenodd") == 0)
1764
+ return NSVG_FILLRULE_EVENODD;
1765
+ // TODO: handle inherit.
1766
+ return NSVG_FILLRULE_NONZERO;
1767
+ }
1768
+
1769
+ static unsigned char nsvg__parsePaintOrder(const char* str)
1770
+ {
1771
+ if (strcmp(str, "normal") == 0 || strcmp(str, "fill stroke markers") == 0)
1772
+ return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS);
1773
+ else if (strcmp(str, "fill markers stroke") == 0)
1774
+ return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE);
1775
+ else if (strcmp(str, "markers fill stroke") == 0)
1776
+ return nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_FILL, NSVG_PAINT_STROKE);
1777
+ else if (strcmp(str, "markers stroke fill") == 0)
1778
+ return nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE, NSVG_PAINT_FILL);
1779
+ else if (strcmp(str, "stroke fill markers") == 0)
1780
+ return nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_FILL, NSVG_PAINT_MARKERS);
1781
+ else if (strcmp(str, "stroke markers fill") == 0)
1782
+ return nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS, NSVG_PAINT_FILL);
1783
+ // TODO: handle inherit.
1784
+ return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS);
1785
+ }
1786
+
1787
+ static const char* nsvg__getNextDashItem(const char* s, char* it)
1788
+ {
1789
+ int n = 0;
1790
+ it[0] = '\0';
1791
+ // Skip white spaces and commas
1792
+ while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
1793
+ // Advance until whitespace, comma or end.
1794
+ while (*s && (!nsvg__isspace(*s) && *s != ',')) {
1795
+ if (n < 63)
1796
+ it[n++] = *s;
1797
+ s++;
1798
+ }
1799
+ it[n++] = '\0';
1800
+ return s;
1801
+ }
1802
+
1803
+ static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)
1804
+ {
1805
+ char item[64];
1806
+ int count = 0, i;
1807
+ float sum = 0.0f;
1808
+
1809
+ // Handle "none"
1810
+ if (str[0] == 'n')
1811
+ return 0;
1812
+
1813
+ // Parse dashes
1814
+ while (*str) {
1815
+ str = nsvg__getNextDashItem(str, item);
1816
+ if (!*item) break;
1817
+ if (count < NSVG_MAX_DASHES)
1818
+ strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
1819
+ }
1820
+
1821
+ for (i = 0; i < count; i++)
1822
+ sum += strokeDashArray[i];
1823
+ if (sum <= 1e-6f)
1824
+ count = 0;
1825
+
1826
+ return count;
1827
+ }
1828
+
1829
+ static void nsvg__parseStyle(NSVGparser* p, const char* str);
1830
+
1831
+ // Apply any matching class styles for a "class" attribute value. We support only simple class
1832
+ // selectors. The class attribute may contain multiple space-separated class names.
1833
+ static void nsvg__applyClassStyles(NSVGparser* p, const char* value)
1834
+ {
1835
+ const char* cur = value;
1836
+ while (*cur) {
1837
+ const char* classStart;
1838
+ size_t classLen;
1839
+ NSVGstyleDeclaration* style;
1840
+
1841
+ while (*cur && nsvg__isspace(*cur))
1842
+ cur++;
1843
+ if (!*cur)
1844
+ break;
1845
+
1846
+ classStart = cur;
1847
+ while (*cur && !nsvg__isspace(*cur))
1848
+ cur++;
1849
+ classLen = (size_t)(cur - classStart);
1850
+
1851
+ for (style = p->styles; style != NULL; style = style->next) {
1852
+ if (strncmp(style->className, classStart, classLen) == 0 && style->className[classLen] == '\0') {
1853
+ nsvg__parseStyle(p, style->propertiesText);
1854
+ }
1855
+ }
1856
+ }
1857
+ }
1858
+
1859
+ static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
1860
+ {
1861
+ float xform[6];
1862
+ NSVGattrib* attr = nsvg__getAttr(p);
1863
+ if (!attr) return 0;
1864
+
1865
+ if (strcmp(name, "style") == 0) {
1866
+ nsvg__parseStyle(p, value);
1867
+ } else if (strcmp(name, "display") == 0) {
1868
+ if (strcmp(value, "none") == 0)
1869
+ attr->visible = 0;
1870
+ // Don't reset ->visible on display:inline, one display:none hides the whole subtree
1871
+
1872
+ } else if (strcmp(name, "fill") == 0) {
1873
+ if (strcmp(value, "none") == 0) {
1874
+ attr->hasFill = 0;
1875
+ } else if (strncmp(value, "url(", 4) == 0) {
1876
+ attr->hasFill = 2;
1877
+ nsvg__parseUrl(attr->fillGradient, value);
1878
+ } else {
1879
+ attr->hasFill = 1;
1880
+ attr->fillColor = nsvg__parseColor(value);
1881
+ }
1882
+ } else if (strcmp(name, "opacity") == 0) {
1883
+ attr->opacity = nsvg__parseOpacity(value);
1884
+ } else if (strcmp(name, "fill-opacity") == 0) {
1885
+ attr->fillOpacity = nsvg__parseOpacity(value);
1886
+ } else if (strcmp(name, "stroke") == 0) {
1887
+ if (strcmp(value, "none") == 0) {
1888
+ attr->hasStroke = 0;
1889
+ } else if (strncmp(value, "url(", 4) == 0) {
1890
+ attr->hasStroke = 2;
1891
+ nsvg__parseUrl(attr->strokeGradient, value);
1892
+ } else {
1893
+ attr->hasStroke = 1;
1894
+ attr->strokeColor = nsvg__parseColor(value);
1895
+ }
1896
+ } else if (strcmp(name, "stroke-width") == 0) {
1897
+ attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
1898
+ } else if (strcmp(name, "stroke-dasharray") == 0) {
1899
+ attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
1900
+ } else if (strcmp(name, "stroke-dashoffset") == 0) {
1901
+ attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
1902
+ } else if (strcmp(name, "stroke-opacity") == 0) {
1903
+ attr->strokeOpacity = nsvg__parseOpacity(value);
1904
+ } else if (strcmp(name, "stroke-linecap") == 0) {
1905
+ attr->strokeLineCap = nsvg__parseLineCap(value);
1906
+ } else if (strcmp(name, "stroke-linejoin") == 0) {
1907
+ attr->strokeLineJoin = nsvg__parseLineJoin(value);
1908
+ } else if (strcmp(name, "stroke-miterlimit") == 0) {
1909
+ attr->miterLimit = nsvg__parseMiterLimit(value);
1910
+ } else if (strcmp(name, "fill-rule") == 0) {
1911
+ attr->fillRule = nsvg__parseFillRule(value);
1912
+ } else if (strcmp(name, "font-size") == 0) {
1913
+ attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
1914
+ } else if (strcmp(name, "transform") == 0) {
1915
+ nsvg__parseTransform(xform, value);
1916
+ nsvg__xformPremultiply(attr->xform, xform);
1917
+ } else if (strcmp(name, "stop-color") == 0) {
1918
+ attr->stopColor = nsvg__parseColor(value);
1919
+ } else if (strcmp(name, "stop-opacity") == 0) {
1920
+ attr->stopOpacity = nsvg__parseOpacity(value);
1921
+ } else if (strcmp(name, "offset") == 0) {
1922
+ attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
1923
+ } else if (strcmp(name, "paint-order") == 0) {
1924
+ attr->paintOrder = nsvg__parsePaintOrder(value);
1925
+ } else if (strcmp(name, "id") == 0) {
1926
+ strncpy(attr->id, value, 63);
1927
+ attr->id[63] = '\0';
1928
+ } else if (strcmp(name, "class") == 0) {
1929
+ nsvg__applyClassStyles(p, value);
1930
+ }
1931
+ else {
1932
+ return 0;
1933
+ }
1934
+ return 1;
1935
+ }
1936
+
1937
+ static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)
1938
+ {
1939
+ const char* str;
1940
+ const char* val;
1941
+ char name[512];
1942
+ char value[512];
1943
+ int n;
1944
+
1945
+ str = start;
1946
+ while (str < end && *str != ':') ++str;
1947
+
1948
+ val = str;
1949
+
1950
+ // Right Trim
1951
+ while (str > start && (*str == ':' || nsvg__isspace(*str))) --str;
1952
+ ++str;
1953
+
1954
+ n = (int)(str - start);
1955
+ if (n > 511) n = 511;
1956
+ if (n) memcpy(name, start, n);
1957
+ name[n] = 0;
1958
+
1959
+ while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;
1960
+
1961
+ n = (int)(end - val);
1962
+ if (n > 511) n = 511;
1963
+ if (n) memcpy(value, val, n);
1964
+ value[n] = 0;
1965
+
1966
+ return nsvg__parseAttr(p, name, value);
1967
+ }
1968
+
1969
+ static void nsvg__parseStyle(NSVGparser* p, const char* str)
1970
+ {
1971
+ const char* start;
1972
+ const char* end;
1973
+
1974
+ while (*str) {
1975
+ // Left Trim
1976
+ while(*str && nsvg__isspace(*str)) ++str;
1977
+ start = str;
1978
+ while(*str && *str != ';') ++str;
1979
+ end = str;
1980
+
1981
+ // Right Trim
1982
+ while (end > start && (*end == ';' || nsvg__isspace(*end))) --end;
1983
+ ++end;
1984
+
1985
+ nsvg__parseNameValue(p, start, end);
1986
+ if (*str) ++str;
1987
+ }
1988
+ }
1989
+
1990
+ static void nsvg__parseAttribs(NSVGparser* p, const char** attr)
1991
+ {
1992
+ int i;
1993
+ for (i = 0; attr[i]; i += 2)
1994
+ {
1995
+ if (strcmp(attr[i], "style") == 0)
1996
+ nsvg__parseStyle(p, attr[i + 1]);
1997
+ else
1998
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
1999
+ }
2000
+ }
2001
+
2002
+ static int nsvg__getArgsPerElement(char cmd)
2003
+ {
2004
+ switch (cmd) {
2005
+ case 'v':
2006
+ case 'V':
2007
+ case 'h':
2008
+ case 'H':
2009
+ return 1;
2010
+ case 'm':
2011
+ case 'M':
2012
+ case 'l':
2013
+ case 'L':
2014
+ case 't':
2015
+ case 'T':
2016
+ return 2;
2017
+ case 'q':
2018
+ case 'Q':
2019
+ case 's':
2020
+ case 'S':
2021
+ return 4;
2022
+ case 'c':
2023
+ case 'C':
2024
+ return 6;
2025
+ case 'a':
2026
+ case 'A':
2027
+ return 7;
2028
+ case 'z':
2029
+ case 'Z':
2030
+ return 0;
2031
+ }
2032
+ return -1;
2033
+ }
2034
+
2035
+ static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
2036
+ {
2037
+ if (rel) {
2038
+ *cpx += args[0];
2039
+ *cpy += args[1];
2040
+ } else {
2041
+ *cpx = args[0];
2042
+ *cpy = args[1];
2043
+ }
2044
+ nsvg__moveTo(p, *cpx, *cpy);
2045
+ }
2046
+
2047
+ static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
2048
+ {
2049
+ if (rel) {
2050
+ *cpx += args[0];
2051
+ *cpy += args[1];
2052
+ } else {
2053
+ *cpx = args[0];
2054
+ *cpy = args[1];
2055
+ }
2056
+ nsvg__lineTo(p, *cpx, *cpy);
2057
+ }
2058
+
2059
+ static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
2060
+ {
2061
+ if (rel)
2062
+ *cpx += args[0];
2063
+ else
2064
+ *cpx = args[0];
2065
+ nsvg__lineTo(p, *cpx, *cpy);
2066
+ }
2067
+
2068
+ static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
2069
+ {
2070
+ if (rel)
2071
+ *cpy += args[0];
2072
+ else
2073
+ *cpy = args[0];
2074
+ nsvg__lineTo(p, *cpx, *cpy);
2075
+ }
2076
+
2077
+ static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,
2078
+ float* cpx2, float* cpy2, float* args, int rel)
2079
+ {
2080
+ float x2, y2, cx1, cy1, cx2, cy2;
2081
+
2082
+ if (rel) {
2083
+ cx1 = *cpx + args[0];
2084
+ cy1 = *cpy + args[1];
2085
+ cx2 = *cpx + args[2];
2086
+ cy2 = *cpy + args[3];
2087
+ x2 = *cpx + args[4];
2088
+ y2 = *cpy + args[5];
2089
+ } else {
2090
+ cx1 = args[0];
2091
+ cy1 = args[1];
2092
+ cx2 = args[2];
2093
+ cy2 = args[3];
2094
+ x2 = args[4];
2095
+ y2 = args[5];
2096
+ }
2097
+
2098
+ nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
2099
+
2100
+ *cpx2 = cx2;
2101
+ *cpy2 = cy2;
2102
+ *cpx = x2;
2103
+ *cpy = y2;
2104
+ }
2105
+
2106
+ static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,
2107
+ float* cpx2, float* cpy2, float* args, int rel)
2108
+ {
2109
+ float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
2110
+
2111
+ x1 = *cpx;
2112
+ y1 = *cpy;
2113
+ if (rel) {
2114
+ cx2 = *cpx + args[0];
2115
+ cy2 = *cpy + args[1];
2116
+ x2 = *cpx + args[2];
2117
+ y2 = *cpy + args[3];
2118
+ } else {
2119
+ cx2 = args[0];
2120
+ cy2 = args[1];
2121
+ x2 = args[2];
2122
+ y2 = args[3];
2123
+ }
2124
+
2125
+ cx1 = 2*x1 - *cpx2;
2126
+ cy1 = 2*y1 - *cpy2;
2127
+
2128
+ nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
2129
+
2130
+ *cpx2 = cx2;
2131
+ *cpy2 = cy2;
2132
+ *cpx = x2;
2133
+ *cpy = y2;
2134
+ }
2135
+
2136
+ static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,
2137
+ float* cpx2, float* cpy2, float* args, int rel)
2138
+ {
2139
+ float x1, y1, x2, y2, cx, cy;
2140
+ float cx1, cy1, cx2, cy2;
2141
+
2142
+ x1 = *cpx;
2143
+ y1 = *cpy;
2144
+ if (rel) {
2145
+ cx = *cpx + args[0];
2146
+ cy = *cpy + args[1];
2147
+ x2 = *cpx + args[2];
2148
+ y2 = *cpy + args[3];
2149
+ } else {
2150
+ cx = args[0];
2151
+ cy = args[1];
2152
+ x2 = args[2];
2153
+ y2 = args[3];
2154
+ }
2155
+
2156
+ // Convert to cubic bezier
2157
+ cx1 = x1 + 2.0f/3.0f*(cx - x1);
2158
+ cy1 = y1 + 2.0f/3.0f*(cy - y1);
2159
+ cx2 = x2 + 2.0f/3.0f*(cx - x2);
2160
+ cy2 = y2 + 2.0f/3.0f*(cy - y2);
2161
+
2162
+ nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
2163
+
2164
+ *cpx2 = cx;
2165
+ *cpy2 = cy;
2166
+ *cpx = x2;
2167
+ *cpy = y2;
2168
+ }
2169
+
2170
+ static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,
2171
+ float* cpx2, float* cpy2, float* args, int rel)
2172
+ {
2173
+ float x1, y1, x2, y2, cx, cy;
2174
+ float cx1, cy1, cx2, cy2;
2175
+
2176
+ x1 = *cpx;
2177
+ y1 = *cpy;
2178
+ if (rel) {
2179
+ x2 = *cpx + args[0];
2180
+ y2 = *cpy + args[1];
2181
+ } else {
2182
+ x2 = args[0];
2183
+ y2 = args[1];
2184
+ }
2185
+
2186
+ cx = 2*x1 - *cpx2;
2187
+ cy = 2*y1 - *cpy2;
2188
+
2189
+ // Convert to cubix bezier
2190
+ cx1 = x1 + 2.0f/3.0f*(cx - x1);
2191
+ cy1 = y1 + 2.0f/3.0f*(cy - y1);
2192
+ cx2 = x2 + 2.0f/3.0f*(cx - x2);
2193
+ cy2 = y2 + 2.0f/3.0f*(cy - y2);
2194
+
2195
+ nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
2196
+
2197
+ *cpx2 = cx;
2198
+ *cpy2 = cy;
2199
+ *cpx = x2;
2200
+ *cpy = y2;
2201
+ }
2202
+
2203
+ static float nsvg__sqr(float x) { return x*x; }
2204
+ static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }
2205
+
2206
+ static float nsvg__vecrat(float ux, float uy, float vx, float vy)
2207
+ {
2208
+ return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
2209
+ }
2210
+
2211
+ static float nsvg__vecang(float ux, float uy, float vx, float vy)
2212
+ {
2213
+ float r = nsvg__vecrat(ux,uy, vx,vy);
2214
+ if (r < -1.0f) r = -1.0f;
2215
+ if (r > 1.0f) r = 1.0f;
2216
+ return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);
2217
+ }
2218
+
2219
+ static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
2220
+ {
2221
+ // Ported from canvg (https://code.google.com/p/canvg/)
2222
+ float rx, ry, rotx;
2223
+ float x1, y1, x2, y2, cx, cy, dx, dy, d;
2224
+ float x1p, y1p, cxp, cyp, s, sa, sb;
2225
+ float ux, uy, vx, vy, a1, da;
2226
+ float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
2227
+ float sinrx, cosrx;
2228
+ int fa, fs;
2229
+ int i, ndivs;
2230
+ float hda, kappa;
2231
+
2232
+ rx = fabsf(args[0]); // y radius
2233
+ ry = fabsf(args[1]); // x radius
2234
+ rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle
2235
+ fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
2236
+ fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
2237
+ x1 = *cpx; // start point
2238
+ y1 = *cpy;
2239
+ if (rel) { // end point
2240
+ x2 = *cpx + args[5];
2241
+ y2 = *cpy + args[6];
2242
+ } else {
2243
+ x2 = args[5];
2244
+ y2 = args[6];
2245
+ }
2246
+
2247
+ dx = x1 - x2;
2248
+ dy = y1 - y2;
2249
+ d = sqrtf(dx*dx + dy*dy);
2250
+ if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
2251
+ // The arc degenerates to a line
2252
+ nsvg__lineTo(p, x2, y2);
2253
+ *cpx = x2;
2254
+ *cpy = y2;
2255
+ return;
2256
+ }
2257
+
2258
+ sinrx = sinf(rotx);
2259
+ cosrx = cosf(rotx);
2260
+
2261
+ // Convert to center point parameterization.
2262
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
2263
+ // 1) Compute x1', y1'
2264
+ x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
2265
+ y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
2266
+ d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);
2267
+ if (d > 1) {
2268
+ d = sqrtf(d);
2269
+ rx *= d;
2270
+ ry *= d;
2271
+ }
2272
+ // 2) Compute cx', cy'
2273
+ s = 0.0f;
2274
+ sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);
2275
+ sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);
2276
+ if (sa < 0.0f) sa = 0.0f;
2277
+ if (sb > 0.0f)
2278
+ s = sqrtf(sa / sb);
2279
+ if (fa == fs)
2280
+ s = -s;
2281
+ cxp = s * rx * y1p / ry;
2282
+ cyp = s * -ry * x1p / rx;
2283
+
2284
+ // 3) Compute cx,cy from cx',cy'
2285
+ cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;
2286
+ cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;
2287
+
2288
+ // 4) Calculate theta1, and delta theta.
2289
+ ux = (x1p - cxp) / rx;
2290
+ uy = (y1p - cyp) / ry;
2291
+ vx = (-x1p - cxp) / rx;
2292
+ vy = (-y1p - cyp) / ry;
2293
+ a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle
2294
+ da = nsvg__vecang(ux,uy, vx,vy); // Delta angle
2295
+
2296
+ // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
2297
+ // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
2298
+
2299
+ if (fs == 0 && da > 0)
2300
+ da -= 2 * NSVG_PI;
2301
+ else if (fs == 1 && da < 0)
2302
+ da += 2 * NSVG_PI;
2303
+
2304
+ // Approximate the arc using cubic spline segments.
2305
+ t[0] = cosrx; t[1] = sinrx;
2306
+ t[2] = -sinrx; t[3] = cosrx;
2307
+ t[4] = cx; t[5] = cy;
2308
+
2309
+ // Split arc into max 90 degree segments.
2310
+ // The loop assumes an iteration per end point (including start and end), this +1.
2311
+ ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
2312
+ hda = (da / (float)ndivs) / 2.0f;
2313
+ // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite)
2314
+ if ((hda < 1e-3f) && (hda > -1e-3f))
2315
+ hda *= 0.5f;
2316
+ else
2317
+ hda = (1.0f - cosf(hda)) / sinf(hda);
2318
+ kappa = fabsf(4.0f / 3.0f * hda);
2319
+ if (da < 0.0f)
2320
+ kappa = -kappa;
2321
+
2322
+ for (i = 0; i <= ndivs; i++) {
2323
+ a = a1 + da * ((float)i/(float)ndivs);
2324
+ dx = cosf(a);
2325
+ dy = sinf(a);
2326
+ nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position
2327
+ nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent
2328
+ if (i > 0)
2329
+ nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
2330
+ px = x;
2331
+ py = y;
2332
+ ptanx = tanx;
2333
+ ptany = tany;
2334
+ }
2335
+
2336
+ *cpx = x2;
2337
+ *cpy = y2;
2338
+ }
2339
+
2340
+ static void nsvg__parsePath(NSVGparser* p, const char** attr)
2341
+ {
2342
+ const char* s = NULL;
2343
+ char cmd = '\0';
2344
+ float args[10];
2345
+ int nargs;
2346
+ int rargs = 0;
2347
+ char initPoint;
2348
+ float cpx, cpy, cpx2, cpy2;
2349
+ const char* tmp[4];
2350
+ char closedFlag;
2351
+ int i;
2352
+ char item[64];
2353
+
2354
+ for (i = 0; attr[i]; i += 2) {
2355
+ if (strcmp(attr[i], "d") == 0) {
2356
+ s = attr[i + 1];
2357
+ } else {
2358
+ tmp[0] = attr[i];
2359
+ tmp[1] = attr[i + 1];
2360
+ tmp[2] = 0;
2361
+ tmp[3] = 0;
2362
+ nsvg__parseAttribs(p, tmp);
2363
+ }
2364
+ }
2365
+
2366
+ if (s) {
2367
+ nsvg__resetPath(p);
2368
+ cpx = 0; cpy = 0;
2369
+ cpx2 = 0; cpy2 = 0;
2370
+ initPoint = 0;
2371
+ closedFlag = 0;
2372
+ nargs = 0;
2373
+
2374
+ while (*s) {
2375
+ item[0] = '\0';
2376
+ if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4))
2377
+ s = nsvg__getNextPathItemWhenArcFlag(s, item);
2378
+ if (!*item)
2379
+ s = nsvg__getNextPathItem(s, item);
2380
+ if (!*item) break;
2381
+ if (cmd != '\0' && nsvg__isCoordinate(item)) {
2382
+ if (nargs < 10)
2383
+ args[nargs++] = (float)nsvg__atof(item);
2384
+ if (nargs >= rargs) {
2385
+ switch (cmd) {
2386
+ case 'm':
2387
+ case 'M':
2388
+ nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
2389
+ // Moveto can be followed by multiple coordinate pairs,
2390
+ // which should be treated as linetos.
2391
+ cmd = (cmd == 'm') ? 'l' : 'L';
2392
+ rargs = nsvg__getArgsPerElement(cmd);
2393
+ cpx2 = cpx; cpy2 = cpy;
2394
+ initPoint = 1;
2395
+ break;
2396
+ case 'l':
2397
+ case 'L':
2398
+ nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
2399
+ cpx2 = cpx; cpy2 = cpy;
2400
+ break;
2401
+ case 'H':
2402
+ case 'h':
2403
+ nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
2404
+ cpx2 = cpx; cpy2 = cpy;
2405
+ break;
2406
+ case 'V':
2407
+ case 'v':
2408
+ nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
2409
+ cpx2 = cpx; cpy2 = cpy;
2410
+ break;
2411
+ case 'C':
2412
+ case 'c':
2413
+ nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
2414
+ break;
2415
+ case 'S':
2416
+ case 's':
2417
+ nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
2418
+ break;
2419
+ case 'Q':
2420
+ case 'q':
2421
+ nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
2422
+ break;
2423
+ case 'T':
2424
+ case 't':
2425
+ nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
2426
+ break;
2427
+ case 'A':
2428
+ case 'a':
2429
+ nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
2430
+ cpx2 = cpx; cpy2 = cpy;
2431
+ break;
2432
+ default:
2433
+ if (nargs >= 2) {
2434
+ cpx = args[nargs-2];
2435
+ cpy = args[nargs-1];
2436
+ cpx2 = cpx; cpy2 = cpy;
2437
+ }
2438
+ break;
2439
+ }
2440
+ nargs = 0;
2441
+ }
2442
+ } else {
2443
+ cmd = item[0];
2444
+ if (cmd == 'M' || cmd == 'm') {
2445
+ // Commit path.
2446
+ if (p->npts > 0)
2447
+ nsvg__addPath(p, closedFlag);
2448
+ // Start new subpath.
2449
+ nsvg__resetPath(p);
2450
+ closedFlag = 0;
2451
+ nargs = 0;
2452
+ } else if (initPoint == 0) {
2453
+ // Do not allow other commands until initial point has been set (moveTo called once).
2454
+ cmd = '\0';
2455
+ }
2456
+ if (cmd == 'Z' || cmd == 'z') {
2457
+ closedFlag = 1;
2458
+ // Commit path.
2459
+ if (p->npts > 0) {
2460
+ // Move current point to first point
2461
+ cpx = p->pts[0];
2462
+ cpy = p->pts[1];
2463
+ cpx2 = cpx; cpy2 = cpy;
2464
+ nsvg__addPath(p, closedFlag);
2465
+ }
2466
+ // Start new subpath.
2467
+ nsvg__resetPath(p);
2468
+ nsvg__moveTo(p, cpx, cpy);
2469
+ closedFlag = 0;
2470
+ nargs = 0;
2471
+ }
2472
+ rargs = nsvg__getArgsPerElement(cmd);
2473
+ if (rargs == -1) {
2474
+ // Command not recognized
2475
+ cmd = '\0';
2476
+ rargs = 0;
2477
+ }
2478
+ }
2479
+ }
2480
+ // Commit path.
2481
+ if (p->npts)
2482
+ nsvg__addPath(p, closedFlag);
2483
+ }
2484
+
2485
+ nsvg__addShape(p);
2486
+ }
2487
+
2488
+ static void nsvg__parseRect(NSVGparser* p, const char** attr)
2489
+ {
2490
+ float x = 0.0f;
2491
+ float y = 0.0f;
2492
+ float w = 0.0f;
2493
+ float h = 0.0f;
2494
+ float rx = -1.0f; // marks not set
2495
+ float ry = -1.0f;
2496
+ int i;
2497
+
2498
+ for (i = 0; attr[i]; i += 2) {
2499
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2500
+ if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
2501
+ if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
2502
+ if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
2503
+ if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
2504
+ if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
2505
+ if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
2506
+ }
2507
+ }
2508
+
2509
+ if (rx < 0.0f && ry > 0.0f) rx = ry;
2510
+ if (ry < 0.0f && rx > 0.0f) ry = rx;
2511
+ if (rx < 0.0f) rx = 0.0f;
2512
+ if (ry < 0.0f) ry = 0.0f;
2513
+ if (rx > w/2.0f) rx = w/2.0f;
2514
+ if (ry > h/2.0f) ry = h/2.0f;
2515
+
2516
+ if (w != 0.0f && h != 0.0f) {
2517
+ nsvg__resetPath(p);
2518
+
2519
+ if (rx < 0.00001f || ry < 0.0001f) {
2520
+ nsvg__moveTo(p, x, y);
2521
+ nsvg__lineTo(p, x+w, y);
2522
+ nsvg__lineTo(p, x+w, y+h);
2523
+ nsvg__lineTo(p, x, y+h);
2524
+ } else {
2525
+ // Rounded rectangle
2526
+ nsvg__moveTo(p, x+rx, y);
2527
+ nsvg__lineTo(p, x+w-rx, y);
2528
+ nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);
2529
+ nsvg__lineTo(p, x+w, y+h-ry);
2530
+ nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);
2531
+ nsvg__lineTo(p, x+rx, y+h);
2532
+ nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
2533
+ nsvg__lineTo(p, x, y+ry);
2534
+ nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
2535
+ }
2536
+
2537
+ nsvg__addPath(p, 1);
2538
+
2539
+ nsvg__addShape(p);
2540
+ }
2541
+ }
2542
+
2543
+ static void nsvg__parseCircle(NSVGparser* p, const char** attr)
2544
+ {
2545
+ float cx = 0.0f;
2546
+ float cy = 0.0f;
2547
+ float r = 0.0f;
2548
+ int i;
2549
+
2550
+ for (i = 0; attr[i]; i += 2) {
2551
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2552
+ if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
2553
+ if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
2554
+ if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
2555
+ }
2556
+ }
2557
+
2558
+ if (r > 0.0f) {
2559
+ nsvg__resetPath(p);
2560
+
2561
+ nsvg__moveTo(p, cx+r, cy);
2562
+ nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
2563
+ nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
2564
+ nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
2565
+ nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
2566
+
2567
+ nsvg__addPath(p, 1);
2568
+
2569
+ nsvg__addShape(p);
2570
+ }
2571
+ }
2572
+
2573
+ static void nsvg__parseEllipse(NSVGparser* p, const char** attr)
2574
+ {
2575
+ float cx = 0.0f;
2576
+ float cy = 0.0f;
2577
+ float rx = 0.0f;
2578
+ float ry = 0.0f;
2579
+ int i;
2580
+
2581
+ for (i = 0; attr[i]; i += 2) {
2582
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2583
+ if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
2584
+ if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
2585
+ if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
2586
+ if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
2587
+ }
2588
+ }
2589
+
2590
+ if (rx > 0.0f && ry > 0.0f) {
2591
+
2592
+ nsvg__resetPath(p);
2593
+
2594
+ nsvg__moveTo(p, cx+rx, cy);
2595
+ nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
2596
+ nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
2597
+ nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
2598
+ nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
2599
+
2600
+ nsvg__addPath(p, 1);
2601
+
2602
+ nsvg__addShape(p);
2603
+ }
2604
+ }
2605
+
2606
+ static void nsvg__parseLine(NSVGparser* p, const char** attr)
2607
+ {
2608
+ float x1 = 0.0;
2609
+ float y1 = 0.0;
2610
+ float x2 = 0.0;
2611
+ float y2 = 0.0;
2612
+ int i;
2613
+
2614
+ for (i = 0; attr[i]; i += 2) {
2615
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2616
+ if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
2617
+ if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
2618
+ if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
2619
+ if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
2620
+ }
2621
+ }
2622
+
2623
+ nsvg__resetPath(p);
2624
+
2625
+ nsvg__moveTo(p, x1, y1);
2626
+ nsvg__lineTo(p, x2, y2);
2627
+
2628
+ nsvg__addPath(p, 0);
2629
+
2630
+ nsvg__addShape(p);
2631
+ }
2632
+
2633
+ static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
2634
+ {
2635
+ int i;
2636
+ const char* s;
2637
+ float args[2];
2638
+ int nargs, npts = 0;
2639
+ char item[64];
2640
+
2641
+ nsvg__resetPath(p);
2642
+
2643
+ for (i = 0; attr[i]; i += 2) {
2644
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2645
+ if (strcmp(attr[i], "points") == 0) {
2646
+ s = attr[i + 1];
2647
+ nargs = 0;
2648
+ while (*s) {
2649
+ s = nsvg__getNextPathItem(s, item);
2650
+ args[nargs++] = (float)nsvg__atof(item);
2651
+ if (nargs >= 2) {
2652
+ if (npts == 0)
2653
+ nsvg__moveTo(p, args[0], args[1]);
2654
+ else
2655
+ nsvg__lineTo(p, args[0], args[1]);
2656
+ nargs = 0;
2657
+ npts++;
2658
+ }
2659
+ }
2660
+ }
2661
+ }
2662
+ }
2663
+
2664
+ nsvg__addPath(p, (char)closeFlag);
2665
+
2666
+ nsvg__addShape(p);
2667
+ }
2668
+
2669
+ static void nsvg__parseSVG(NSVGparser* p, const char** attr)
2670
+ {
2671
+ int i;
2672
+ for (i = 0; attr[i]; i += 2) {
2673
+ if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2674
+ if (strcmp(attr[i], "width") == 0) {
2675
+ p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
2676
+ } else if (strcmp(attr[i], "height") == 0) {
2677
+ p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
2678
+ } else if (strcmp(attr[i], "viewBox") == 0) {
2679
+ const char *s = attr[i + 1];
2680
+ char buf[64];
2681
+ s = nsvg__parseNumber(s, buf, 64);
2682
+ p->viewMinx = nsvg__atof(buf);
2683
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
2684
+ if (!*s) return;
2685
+ s = nsvg__parseNumber(s, buf, 64);
2686
+ p->viewMiny = nsvg__atof(buf);
2687
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
2688
+ if (!*s) return;
2689
+ s = nsvg__parseNumber(s, buf, 64);
2690
+ p->viewWidth = nsvg__atof(buf);
2691
+ while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++;
2692
+ if (!*s) return;
2693
+ s = nsvg__parseNumber(s, buf, 64);
2694
+ p->viewHeight = nsvg__atof(buf);
2695
+ } else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
2696
+ if (strstr(attr[i + 1], "none") != 0) {
2697
+ // No uniform scaling
2698
+ p->alignType = NSVG_ALIGN_NONE;
2699
+ } else {
2700
+ // Parse X align
2701
+ if (strstr(attr[i + 1], "xMin") != 0)
2702
+ p->alignX = NSVG_ALIGN_MIN;
2703
+ else if (strstr(attr[i + 1], "xMid") != 0)
2704
+ p->alignX = NSVG_ALIGN_MID;
2705
+ else if (strstr(attr[i + 1], "xMax") != 0)
2706
+ p->alignX = NSVG_ALIGN_MAX;
2707
+ // Parse X align
2708
+ if (strstr(attr[i + 1], "yMin") != 0)
2709
+ p->alignY = NSVG_ALIGN_MIN;
2710
+ else if (strstr(attr[i + 1], "yMid") != 0)
2711
+ p->alignY = NSVG_ALIGN_MID;
2712
+ else if (strstr(attr[i + 1], "yMax") != 0)
2713
+ p->alignY = NSVG_ALIGN_MAX;
2714
+ // Parse meet/slice
2715
+ p->alignType = NSVG_ALIGN_MEET;
2716
+ if (strstr(attr[i + 1], "slice") != 0)
2717
+ p->alignType = NSVG_ALIGN_SLICE;
2718
+ }
2719
+ }
2720
+ }
2721
+ }
2722
+ }
2723
+
2724
+ static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type)
2725
+ {
2726
+ int i;
2727
+ NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
2728
+ if (grad == NULL) return;
2729
+ memset(grad, 0, sizeof(NSVGgradientData));
2730
+ grad->units = NSVG_OBJECT_SPACE;
2731
+ grad->type = type;
2732
+ if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
2733
+ grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
2734
+ grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
2735
+ grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
2736
+ grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
2737
+ } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
2738
+ grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
2739
+ grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
2740
+ grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
2741
+ }
2742
+
2743
+ nsvg__xformIdentity(grad->xform);
2744
+
2745
+ for (i = 0; attr[i]; i += 2) {
2746
+ if (strcmp(attr[i], "id") == 0) {
2747
+ strncpy(grad->id, attr[i+1], 63);
2748
+ grad->id[63] = '\0';
2749
+ } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
2750
+ if (strcmp(attr[i], "gradientUnits") == 0) {
2751
+ if (strcmp(attr[i+1], "objectBoundingBox") == 0)
2752
+ grad->units = NSVG_OBJECT_SPACE;
2753
+ else
2754
+ grad->units = NSVG_USER_SPACE;
2755
+ } else if (strcmp(attr[i], "gradientTransform") == 0) {
2756
+ nsvg__parseTransform(grad->xform, attr[i + 1]);
2757
+ } else if (strcmp(attr[i], "cx") == 0) {
2758
+ grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
2759
+ } else if (strcmp(attr[i], "cy") == 0) {
2760
+ grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
2761
+ } else if (strcmp(attr[i], "r") == 0) {
2762
+ grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
2763
+ } else if (strcmp(attr[i], "fx") == 0) {
2764
+ grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
2765
+ } else if (strcmp(attr[i], "fy") == 0) {
2766
+ grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
2767
+ } else if (strcmp(attr[i], "x1") == 0) {
2768
+ grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
2769
+ } else if (strcmp(attr[i], "y1") == 0) {
2770
+ grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
2771
+ } else if (strcmp(attr[i], "x2") == 0) {
2772
+ grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
2773
+ } else if (strcmp(attr[i], "y2") == 0) {
2774
+ grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
2775
+ } else if (strcmp(attr[i], "spreadMethod") == 0) {
2776
+ if (strcmp(attr[i+1], "pad") == 0)
2777
+ grad->spread = NSVG_SPREAD_PAD;
2778
+ else if (strcmp(attr[i+1], "reflect") == 0)
2779
+ grad->spread = NSVG_SPREAD_REFLECT;
2780
+ else if (strcmp(attr[i+1], "repeat") == 0)
2781
+ grad->spread = NSVG_SPREAD_REPEAT;
2782
+ } else if (strcmp(attr[i], "xlink:href") == 0) {
2783
+ const char *href = attr[i+1];
2784
+ strncpy(grad->ref, href+1, 62);
2785
+ grad->ref[62] = '\0';
2786
+ }
2787
+ }
2788
+ }
2789
+
2790
+ grad->next = p->gradients;
2791
+ p->gradients = grad;
2792
+ }
2793
+
2794
+ static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
2795
+ {
2796
+ NSVGattrib* curAttr = nsvg__getAttr(p);
2797
+ NSVGgradientData* grad;
2798
+ NSVGgradientStop* stop;
2799
+ int i, idx;
2800
+
2801
+ curAttr->stopOffset = 0;
2802
+ curAttr->stopColor = 0;
2803
+ curAttr->stopOpacity = 1.0f;
2804
+
2805
+ for (i = 0; attr[i]; i += 2) {
2806
+ nsvg__parseAttr(p, attr[i], attr[i + 1]);
2807
+ }
2808
+
2809
+ // Add stop to the last gradient.
2810
+ grad = p->gradients;
2811
+ if (grad == NULL) return;
2812
+
2813
+ grad->nstops++;
2814
+ grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops);
2815
+ if (grad->stops == NULL) return;
2816
+
2817
+ // Insert
2818
+ idx = grad->nstops-1;
2819
+ for (i = 0; i < grad->nstops-1; i++) {
2820
+ if (curAttr->stopOffset < grad->stops[i].offset) {
2821
+ idx = i;
2822
+ break;
2823
+ }
2824
+ }
2825
+ if (idx != grad->nstops-1) {
2826
+ for (i = grad->nstops-1; i > idx; i--)
2827
+ grad->stops[i] = grad->stops[i-1];
2828
+ }
2829
+
2830
+ stop = &grad->stops[idx];
2831
+ stop->color = curAttr->stopColor;
2832
+ stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
2833
+ stop->offset = curAttr->stopOffset;
2834
+ }
2835
+
2836
+ static void nsvg__startElement(void* ud, const char* el, const char** attr)
2837
+ {
2838
+ NSVGparser* p = (NSVGparser*)ud;
2839
+
2840
+ if (p->defsFlag) {
2841
+ // Skip everything but gradients and styles in defs
2842
+ if (strcmp(el, "linearGradient") == 0) {
2843
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
2844
+ } else if (strcmp(el, "radialGradient") == 0) {
2845
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
2846
+ } else if (strcmp(el, "stop") == 0) {
2847
+ nsvg__parseGradientStop(p, attr);
2848
+ } else if (strcmp(el, "style") == 0) {
2849
+ p->styleFlag = 1;
2850
+ }
2851
+ return;
2852
+ }
2853
+
2854
+ if (strcmp(el, "g") == 0) {
2855
+ nsvg__pushAttr(p);
2856
+ nsvg__parseAttribs(p, attr);
2857
+ } else if (strcmp(el, "path") == 0) {
2858
+ if (p->pathFlag) // Do not allow nested paths.
2859
+ return;
2860
+ nsvg__pushAttr(p);
2861
+ nsvg__parsePath(p, attr);
2862
+ nsvg__popAttr(p);
2863
+ } else if (strcmp(el, "rect") == 0) {
2864
+ nsvg__pushAttr(p);
2865
+ nsvg__parseRect(p, attr);
2866
+ nsvg__popAttr(p);
2867
+ } else if (strcmp(el, "circle") == 0) {
2868
+ nsvg__pushAttr(p);
2869
+ nsvg__parseCircle(p, attr);
2870
+ nsvg__popAttr(p);
2871
+ } else if (strcmp(el, "ellipse") == 0) {
2872
+ nsvg__pushAttr(p);
2873
+ nsvg__parseEllipse(p, attr);
2874
+ nsvg__popAttr(p);
2875
+ } else if (strcmp(el, "line") == 0) {
2876
+ nsvg__pushAttr(p);
2877
+ nsvg__parseLine(p, attr);
2878
+ nsvg__popAttr(p);
2879
+ } else if (strcmp(el, "polyline") == 0) {
2880
+ nsvg__pushAttr(p);
2881
+ nsvg__parsePoly(p, attr, 0);
2882
+ nsvg__popAttr(p);
2883
+ } else if (strcmp(el, "polygon") == 0) {
2884
+ nsvg__pushAttr(p);
2885
+ nsvg__parsePoly(p, attr, 1);
2886
+ nsvg__popAttr(p);
2887
+ } else if (strcmp(el, "linearGradient") == 0) {
2888
+ nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
2889
+ } else if (strcmp(el, "radialGradient") == 0) {
2890
+ nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
2891
+ } else if (strcmp(el, "stop") == 0) {
2892
+ nsvg__parseGradientStop(p, attr);
2893
+ } else if (strcmp(el, "defs") == 0) {
2894
+ p->defsFlag = 1;
2895
+ } else if (strcmp(el, "svg") == 0) {
2896
+ nsvg__parseSVG(p, attr);
2897
+ } else if (strcmp(el, "style") == 0) {
2898
+ p->styleFlag = 1;
2899
+ }
2900
+ }
2901
+
2902
+ static void nsvg__endElement(void* ud, const char* el)
2903
+ {
2904
+ NSVGparser* p = (NSVGparser*)ud;
2905
+
2906
+ if (strcmp(el, "g") == 0) {
2907
+ nsvg__popAttr(p);
2908
+ } else if (strcmp(el, "path") == 0) {
2909
+ p->pathFlag = 0;
2910
+ } else if (strcmp(el, "defs") == 0) {
2911
+ p->defsFlag = 0;
2912
+ } else if (strcmp(el, "style") == 0) {
2913
+ p->styleFlag = 0;
2914
+ }
2915
+ }
2916
+
2917
+ static char *nsvg__strndup(const char *s, size_t n)
2918
+ {
2919
+ char *result = (char *)malloc(n + 1);
2920
+ if (result == NULL)
2921
+ return NULL;
2922
+
2923
+ memcpy(result, s, n);
2924
+ result[n] = '\0';
2925
+ return result;
2926
+ }
2927
+
2928
+ static void nsvg__content(void* ud, const char* s)
2929
+ {
2930
+ NSVGparser* p = (NSVGparser*)ud;
2931
+ if (!p->styleFlag)
2932
+ return;
2933
+
2934
+ // Parse all the styles inside the style block. Each style's content will be later processed using nsvg__parseStyle().
2935
+ // Note: We only support selector lists of simple class selectors (e.g. ".foo, .bar { ... }").
2936
+ while (*s) {
2937
+ NSVGstyleDeclaration* styles[NSVG_MAX_CLASSES];
2938
+ int nstyles = 0;
2939
+ const char* propsStart;
2940
+ const char* propsEnd;
2941
+ int i;
2942
+
2943
+ // 1) Parse the selector list up to '{'. For each simple class selector ('.name'),
2944
+ // allocate a new NSVGstyleDeclaration into the local staging array. Styles are
2945
+ // only committed to p->styles in step 3 below, once their propertiesText has
2946
+ // also been allocated successfully.
2947
+ while (*s && *s != '{') {
2948
+ const char* selStart;
2949
+ const char* selEnd;
2950
+ NSVGstyleDeclaration* style;
2951
+
2952
+ while (*s && (nsvg__isspace(*s) || *s == ','))
2953
+ s++;
2954
+ if (!*s || *s == '{')
2955
+ break;
2956
+
2957
+ selStart = s;
2958
+ while (*s && !nsvg__isspace(*s) && *s != ',' && *s != '{')
2959
+ s++;
2960
+ selEnd = s;
2961
+
2962
+ if (*selStart != '.' || nstyles >= NSVG_MAX_CLASSES)
2963
+ continue; // unsupported selector, or staging array full
2964
+ selStart++; // strip leading '.'
2965
+
2966
+ style = (NSVGstyleDeclaration*)malloc(sizeof(NSVGstyleDeclaration));
2967
+ if (style == NULL)
2968
+ continue;
2969
+ style->className = nsvg__strndup(selStart, (size_t)(selEnd - selStart));
2970
+ if (style->className == NULL) {
2971
+ free(style);
2972
+ continue;
2973
+ }
2974
+ style->propertiesText = NULL;
2975
+ style->next = NULL;
2976
+ styles[nstyles++] = style;
2977
+ }
2978
+ if (!*s) {
2979
+ // No '{' found - discard pending styles and stop.
2980
+ for (i = 0; i < nstyles; i++) {
2981
+ free(styles[i]->className);
2982
+ free(styles[i]);
2983
+ }
2984
+ break;
2985
+ }
2986
+ s++; // advance past '{'
2987
+
2988
+ // 2) Find the end of the properties block (up to '}').
2989
+ propsStart = s;
2990
+ while (*s && *s != '}')
2991
+ s++;
2992
+ propsEnd = s;
2993
+
2994
+ // 3) Allocate propertiesText for each pending style. Commit successful ones to
2995
+ // p->styles (head-insertion); free any whose allocation fails.
2996
+ for (i = 0; i < nstyles; i++) {
2997
+ styles[i]->propertiesText = nsvg__strndup(propsStart, (size_t)(propsEnd - propsStart));
2998
+ if (styles[i]->propertiesText == NULL) {
2999
+ free(styles[i]->className);
3000
+ free(styles[i]);
3001
+ } else {
3002
+ styles[i]->next = p->styles;
3003
+ p->styles = styles[i];
3004
+ }
3005
+ }
3006
+
3007
+ if (*s)
3008
+ s++; // advance past '}'
3009
+ }
3010
+ }
3011
+
3012
+ static void nsvg__imageBounds(NSVGparser* p, float* bounds)
3013
+ {
3014
+ NSVGshape* shape;
3015
+ shape = p->image->shapes;
3016
+ if (shape == NULL) {
3017
+ bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
3018
+ return;
3019
+ }
3020
+ bounds[0] = shape->bounds[0];
3021
+ bounds[1] = shape->bounds[1];
3022
+ bounds[2] = shape->bounds[2];
3023
+ bounds[3] = shape->bounds[3];
3024
+ for (shape = shape->next; shape != NULL; shape = shape->next) {
3025
+ bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
3026
+ bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
3027
+ bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
3028
+ bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
3029
+ }
3030
+ }
3031
+
3032
+ static float nsvg__viewAlign(float content, float container, int type)
3033
+ {
3034
+ if (type == NSVG_ALIGN_MIN)
3035
+ return 0;
3036
+ else if (type == NSVG_ALIGN_MAX)
3037
+ return container - content;
3038
+ // mid
3039
+ return (container - content) * 0.5f;
3040
+ }
3041
+
3042
+ static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)
3043
+ {
3044
+ float t[6];
3045
+ nsvg__xformSetTranslation(t, tx, ty);
3046
+ nsvg__xformMultiply (grad->xform, t);
3047
+
3048
+ nsvg__xformSetScale(t, sx, sy);
3049
+ nsvg__xformMultiply (grad->xform, t);
3050
+ }
3051
+
3052
+ static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
3053
+ {
3054
+ NSVGshape* shape;
3055
+ NSVGpath* path;
3056
+ float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
3057
+ int i;
3058
+ float* pt;
3059
+
3060
+ // Guess image size if not set completely.
3061
+ nsvg__imageBounds(p, bounds);
3062
+
3063
+ if (p->viewWidth == 0) {
3064
+ if (p->image->width > 0) {
3065
+ p->viewWidth = p->image->width;
3066
+ } else {
3067
+ p->viewMinx = bounds[0];
3068
+ p->viewWidth = bounds[2] - bounds[0];
3069
+ }
3070
+ }
3071
+ if (p->viewHeight == 0) {
3072
+ if (p->image->height > 0) {
3073
+ p->viewHeight = p->image->height;
3074
+ } else {
3075
+ p->viewMiny = bounds[1];
3076
+ p->viewHeight = bounds[3] - bounds[1];
3077
+ }
3078
+ }
3079
+ if (p->image->width == 0)
3080
+ p->image->width = p->viewWidth;
3081
+ if (p->image->height == 0)
3082
+ p->image->height = p->viewHeight;
3083
+
3084
+ tx = -p->viewMinx;
3085
+ ty = -p->viewMiny;
3086
+ sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
3087
+ sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
3088
+ // Unit scaling
3089
+ us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
3090
+
3091
+ // Fix aspect ratio
3092
+ if (p->alignType == NSVG_ALIGN_MEET) {
3093
+ // fit whole image into viewbox
3094
+ sx = sy = nsvg__minf(sx, sy);
3095
+ tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
3096
+ ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
3097
+ } else if (p->alignType == NSVG_ALIGN_SLICE) {
3098
+ // fill whole viewbox with image
3099
+ sx = sy = nsvg__maxf(sx, sy);
3100
+ tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
3101
+ ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
3102
+ }
3103
+
3104
+ // Transform
3105
+ sx *= us;
3106
+ sy *= us;
3107
+ avgs = (sx+sy) / 2.0f;
3108
+ for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
3109
+ shape->bounds[0] = (shape->bounds[0] + tx) * sx;
3110
+ shape->bounds[1] = (shape->bounds[1] + ty) * sy;
3111
+ shape->bounds[2] = (shape->bounds[2] + tx) * sx;
3112
+ shape->bounds[3] = (shape->bounds[3] + ty) * sy;
3113
+ for (path = shape->paths; path != NULL; path = path->next) {
3114
+ path->bounds[0] = (path->bounds[0] + tx) * sx;
3115
+ path->bounds[1] = (path->bounds[1] + ty) * sy;
3116
+ path->bounds[2] = (path->bounds[2] + tx) * sx;
3117
+ path->bounds[3] = (path->bounds[3] + ty) * sy;
3118
+ for (i =0; i < path->npts; i++) {
3119
+ pt = &path->pts[i*2];
3120
+ pt[0] = (pt[0] + tx) * sx;
3121
+ pt[1] = (pt[1] + ty) * sy;
3122
+ }
3123
+ }
3124
+
3125
+ if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
3126
+ nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);
3127
+ memcpy(t, shape->fill.gradient->xform, sizeof(float)*6);
3128
+ nsvg__xformInverse(shape->fill.gradient->xform, t);
3129
+ }
3130
+ if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
3131
+ nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);
3132
+ memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);
3133
+ nsvg__xformInverse(shape->stroke.gradient->xform, t);
3134
+ }
3135
+
3136
+ shape->strokeWidth *= avgs;
3137
+ shape->strokeDashOffset *= avgs;
3138
+ for (i = 0; i < shape->strokeDashCount; i++)
3139
+ shape->strokeDashArray[i] *= avgs;
3140
+ }
3141
+ }
3142
+
3143
+ static void nsvg__createGradients(NSVGparser* p)
3144
+ {
3145
+ NSVGshape* shape;
3146
+
3147
+ for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
3148
+ if (shape->fill.type == NSVG_PAINT_UNDEF) {
3149
+ if (shape->fillGradient[0] != '\0') {
3150
+ float inv[6], localBounds[4];
3151
+ nsvg__xformInverse(inv, shape->xform);
3152
+ nsvg__getLocalBounds(localBounds, shape, inv);
3153
+ shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type);
3154
+ }
3155
+ if (shape->fill.type == NSVG_PAINT_UNDEF) {
3156
+ shape->fill.type = NSVG_PAINT_NONE;
3157
+ }
3158
+ }
3159
+ if (shape->stroke.type == NSVG_PAINT_UNDEF) {
3160
+ if (shape->strokeGradient[0] != '\0') {
3161
+ float inv[6], localBounds[4];
3162
+ nsvg__xformInverse(inv, shape->xform);
3163
+ nsvg__getLocalBounds(localBounds, shape, inv);
3164
+ shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type);
3165
+ }
3166
+ if (shape->stroke.type == NSVG_PAINT_UNDEF) {
3167
+ shape->stroke.type = NSVG_PAINT_NONE;
3168
+ }
3169
+ }
3170
+ }
3171
+ }
3172
+
3173
+ NSVGimage* nsvgParse(char* input, const char* units, float dpi)
3174
+ {
3175
+ NSVGparser* p;
3176
+ NSVGimage* ret = 0;
3177
+
3178
+ p = nsvg__createParser();
3179
+ if (p == NULL) {
3180
+ return NULL;
3181
+ }
3182
+ p->dpi = dpi;
3183
+
3184
+ nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
3185
+
3186
+ // Create gradients after all definitions have been parsed
3187
+ nsvg__createGradients(p);
3188
+
3189
+ // Scale to viewBox
3190
+ nsvg__scaleToViewbox(p, units);
3191
+
3192
+ ret = p->image;
3193
+ p->image = NULL;
3194
+
3195
+ nsvg__deleteParser(p);
3196
+
3197
+ return ret;
3198
+ }
3199
+
3200
+ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
3201
+ {
3202
+ FILE* fp = NULL;
3203
+ size_t size;
3204
+ char* data = NULL;
3205
+ NSVGimage* image = NULL;
3206
+
3207
+ fp = fopen(filename, "rb");
3208
+ if (!fp) goto error;
3209
+ if (fseek(fp, 0, SEEK_END)) goto error;
3210
+ size = ftell(fp);
3211
+ if (size == -1l) goto error;
3212
+ if (fseek(fp, 0, SEEK_SET)) goto error;
3213
+ data = (char*)malloc(size+1);
3214
+ if (data == NULL) goto error;
3215
+ if (fread(data, 1, size, fp) != size) goto error;
3216
+ data[size] = '\0'; // Must be null terminated.
3217
+ fclose(fp);
3218
+ image = nsvgParse(data, units, dpi);
3219
+ free(data);
3220
+
3221
+ return image;
3222
+
3223
+ error:
3224
+ if (fp) fclose(fp);
3225
+ if (data) free(data);
3226
+ if (image) nsvgDelete(image);
3227
+ return NULL;
3228
+ }
3229
+
3230
+ NSVGpath* nsvgDuplicatePath(NSVGpath* p)
3231
+ {
3232
+ NSVGpath* res = NULL;
3233
+
3234
+ if (p == NULL)
3235
+ return NULL;
3236
+
3237
+ res = (NSVGpath*)malloc(sizeof(NSVGpath));
3238
+ if (res == NULL) goto error;
3239
+ memset(res, 0, sizeof(NSVGpath));
3240
+
3241
+ res->pts = (float*)malloc(p->npts*2*sizeof(float));
3242
+ if (res->pts == NULL) goto error;
3243
+ memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
3244
+ res->npts = p->npts;
3245
+
3246
+ memcpy(res->bounds, p->bounds, sizeof(p->bounds));
3247
+
3248
+ res->closed = p->closed;
3249
+
3250
+ return res;
3251
+
3252
+ error:
3253
+ if (res != NULL) {
3254
+ free(res->pts);
3255
+ free(res);
3256
+ }
3257
+ return NULL;
3258
+ }
3259
+
3260
+ void nsvgDelete(NSVGimage* image)
3261
+ {
3262
+ NSVGshape *snext, *shape;
3263
+ if (image == NULL) return;
3264
+ shape = image->shapes;
3265
+ while (shape != NULL) {
3266
+ snext = shape->next;
3267
+ nsvg__deletePaths(shape->paths);
3268
+ nsvg__deletePaint(&shape->fill);
3269
+ nsvg__deletePaint(&shape->stroke);
3270
+ free(shape);
3271
+ shape = snext;
3272
+ }
3273
+ free(image);
3274
+ }
3275
+
3276
+ #endif // NANOSVG_IMPLEMENTATION
3277
+
3278
+ #endif // NANOSVG_H