@shopify/react-native-skia 2.0.6 → 2.1.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 (287) hide show
  1. package/android/CMakeLists.txt +20 -1
  2. package/cpp/api/JsiSkApi.h +3 -0
  3. package/cpp/api/JsiSkImageFilterFactory.h +478 -39
  4. package/cpp/api/JsiSkPath.h +2 -1
  5. package/cpp/api/JsiSkPathFactory.h +1 -1
  6. package/cpp/api/JsiSkSkottie.h +590 -0
  7. package/cpp/api/JsiSkottieFactory.h +65 -0
  8. package/cpp/api/recorder/Command.h +1 -0
  9. package/cpp/api/recorder/Convertor.h +16 -0
  10. package/cpp/api/recorder/Drawings.h +23 -0
  11. package/cpp/api/recorder/JsiRecorder.h +6 -0
  12. package/cpp/api/recorder/RNRecorder.h +9 -0
  13. package/cpp/api/third_party/SkottieUtils.cpp +333 -0
  14. package/cpp/api/third_party/SkottieUtils.h +172 -0
  15. package/cpp/skia/modules/jsonreader/SkJSONReader.cpp +980 -0
  16. package/cpp/skia/modules/jsonreader/SkJSONReader.h +389 -0
  17. package/cpp/skia/modules/skottie/include/ExternalLayer.h +56 -0
  18. package/cpp/skia/modules/skottie/include/Skottie.h +313 -0
  19. package/cpp/skia/modules/skottie/include/SkottieProperty.h +190 -0
  20. package/cpp/skia/modules/skottie/include/SlotManager.h +113 -0
  21. package/cpp/skia/modules/skottie/include/TextShaper.h +200 -0
  22. package/cpp/skia/modules/skottie/src/SkottieValue.h +56 -0
  23. package/cpp/skia/modules/skottie/src/animator/Animator.h +89 -0
  24. package/cpp/skia/modules/skottie/src/text/Font.h +82 -0
  25. package/cpp/skia/modules/skottie/src/text/TextAdapter.h +155 -0
  26. package/cpp/skia/modules/skottie/src/text/TextAnimator.h +121 -0
  27. package/cpp/skia/modules/skottie/src/text/TextValue.h +28 -0
  28. package/cpp/skia/modules/sksg/include/SkSGClipEffect.h +61 -0
  29. package/cpp/skia/modules/sksg/include/SkSGColorFilter.h +135 -0
  30. package/cpp/skia/modules/sksg/include/SkSGDraw.h +57 -0
  31. package/cpp/skia/modules/sksg/include/SkSGEffectNode.h +50 -0
  32. package/cpp/skia/modules/sksg/include/SkSGGeometryEffect.h +181 -0
  33. package/cpp/skia/modules/sksg/include/SkSGGeometryNode.h +54 -0
  34. package/cpp/skia/modules/sksg/include/SkSGGradient.h +108 -0
  35. package/cpp/skia/modules/sksg/include/SkSGGroup.h +65 -0
  36. package/cpp/skia/modules/sksg/include/SkSGImage.h +59 -0
  37. package/cpp/skia/modules/sksg/include/SkSGInvalidationController.h +46 -0
  38. package/cpp/skia/modules/sksg/include/SkSGMaskEffect.h +65 -0
  39. package/cpp/skia/modules/sksg/include/SkSGMerge.h +74 -0
  40. package/cpp/skia/modules/sksg/include/SkSGNode.h +128 -0
  41. package/cpp/skia/modules/sksg/include/SkSGOpacityEffect.h +54 -0
  42. package/cpp/skia/modules/sksg/include/SkSGPaint.h +112 -0
  43. package/cpp/skia/modules/sksg/include/SkSGPath.h +68 -0
  44. package/cpp/skia/modules/sksg/include/SkSGPlane.h +47 -0
  45. package/cpp/skia/modules/sksg/include/SkSGRect.h +122 -0
  46. package/cpp/skia/modules/sksg/include/SkSGRenderEffect.h +283 -0
  47. package/cpp/skia/modules/sksg/include/SkSGRenderNode.h +157 -0
  48. package/cpp/skia/modules/sksg/include/SkSGScene.h +47 -0
  49. package/cpp/skia/modules/sksg/include/SkSGText.h +82 -0
  50. package/cpp/skia/modules/sksg/include/SkSGTransform.h +127 -0
  51. package/cpp/skia/src/base/SkArenaAlloc.h +371 -0
  52. package/lib/commonjs/dom/nodes/datatypes/Gradient.d.ts +15 -15
  53. package/lib/commonjs/dom/types/Drawings.d.ts +5 -1
  54. package/lib/commonjs/dom/types/Drawings.js.map +1 -1
  55. package/lib/commonjs/dom/types/NodeType.d.ts +2 -1
  56. package/lib/commonjs/dom/types/NodeType.js +2 -0
  57. package/lib/commonjs/dom/types/NodeType.js.map +1 -1
  58. package/lib/commonjs/renderer/__tests__/e2e/AdvancedImageFilters.spec.d.ts +1 -0
  59. package/lib/commonjs/renderer/__tests__/e2e/Camera.spec.d.ts +21 -0
  60. package/lib/commonjs/renderer/__tests__/e2e/LightingImageFilters.spec.d.ts +1 -0
  61. package/lib/commonjs/renderer/__tests__/e2e/Skottie.spec.d.ts +1 -0
  62. package/lib/commonjs/renderer/__tests__/setup.d.ts +5 -0
  63. package/lib/commonjs/renderer/components/Skottie.d.ts +4 -0
  64. package/lib/commonjs/renderer/components/Skottie.js +13 -0
  65. package/lib/commonjs/renderer/components/Skottie.js.map +1 -0
  66. package/lib/commonjs/renderer/components/index.d.ts +1 -0
  67. package/lib/commonjs/renderer/components/index.js +11 -0
  68. package/lib/commonjs/renderer/components/index.js.map +1 -1
  69. package/lib/commonjs/skia/types/ImageFilter/ImageFilterFactory.d.ts +252 -15
  70. package/lib/commonjs/skia/types/ImageFilter/ImageFilterFactory.js.map +1 -1
  71. package/lib/commonjs/skia/types/Matrix4.d.ts +11 -2
  72. package/lib/commonjs/skia/types/Matrix4.js +42 -1
  73. package/lib/commonjs/skia/types/Matrix4.js.map +1 -1
  74. package/lib/commonjs/skia/types/Recorder.d.ts +2 -1
  75. package/lib/commonjs/skia/types/Recorder.js.map +1 -1
  76. package/lib/commonjs/skia/types/Skia.d.ts +2 -0
  77. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  78. package/lib/commonjs/skia/types/Skottie.d.ts +223 -0
  79. package/lib/commonjs/skia/types/Skottie.js +73 -0
  80. package/lib/commonjs/skia/types/Skottie.js.map +1 -0
  81. package/lib/commonjs/skia/types/index.d.ts +1 -0
  82. package/lib/commonjs/skia/types/index.js +11 -0
  83. package/lib/commonjs/skia/types/index.js.map +1 -1
  84. package/lib/commonjs/skia/web/JsiSkImageFilterFactory.d.ts +29 -12
  85. package/lib/commonjs/skia/web/JsiSkImageFilterFactory.js +88 -19
  86. package/lib/commonjs/skia/web/JsiSkImageFilterFactory.js.map +1 -1
  87. package/lib/commonjs/skia/web/JsiSkia.js +2 -0
  88. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  89. package/lib/commonjs/skia/web/JsiSkottieAnimation.d.ts +59 -0
  90. package/lib/commonjs/skia/web/JsiSkottieAnimation.js +243 -0
  91. package/lib/commonjs/skia/web/JsiSkottieAnimation.js.map +1 -0
  92. package/lib/commonjs/skia/web/JsiSkottieFactory.d.ts +9 -0
  93. package/lib/commonjs/skia/web/JsiSkottieFactory.js +26 -0
  94. package/lib/commonjs/skia/web/JsiSkottieFactory.js.map +1 -0
  95. package/lib/commonjs/sksg/Elements.d.ts +2 -1
  96. package/lib/commonjs/sksg/Elements.js.map +1 -1
  97. package/lib/commonjs/sksg/Recorder/Core.d.ts +4 -2
  98. package/lib/commonjs/sksg/Recorder/Core.js +1 -0
  99. package/lib/commonjs/sksg/Recorder/Core.js.map +1 -1
  100. package/lib/commonjs/sksg/Recorder/Player.js +2 -0
  101. package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
  102. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +2 -1
  103. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js +4 -0
  104. package/lib/commonjs/sksg/Recorder/ReanimatedRecorder.js.map +1 -1
  105. package/lib/commonjs/sksg/Recorder/Recorder.d.ts +2 -1
  106. package/lib/commonjs/sksg/Recorder/Recorder.js +6 -0
  107. package/lib/commonjs/sksg/Recorder/Recorder.js.map +1 -1
  108. package/lib/commonjs/sksg/Recorder/Visitor.js +3 -0
  109. package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
  110. package/lib/commonjs/sksg/Recorder/commands/Drawing.d.ts +2 -2
  111. package/lib/commonjs/sksg/Recorder/commands/Drawing.js +11 -4
  112. package/lib/commonjs/sksg/Recorder/commands/Drawing.js.map +1 -1
  113. package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js +1 -1
  114. package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js.map +1 -1
  115. package/lib/module/dom/nodes/datatypes/Gradient.d.ts +15 -15
  116. package/lib/module/dom/types/Drawings.d.ts +5 -1
  117. package/lib/module/dom/types/Drawings.js.map +1 -1
  118. package/lib/module/dom/types/NodeType.d.ts +2 -1
  119. package/lib/module/dom/types/NodeType.js +2 -0
  120. package/lib/module/dom/types/NodeType.js.map +1 -1
  121. package/lib/module/renderer/__tests__/e2e/AdvancedImageFilters.spec.d.ts +1 -0
  122. package/lib/module/renderer/__tests__/e2e/Camera.spec.d.ts +21 -0
  123. package/lib/module/renderer/__tests__/e2e/LightingImageFilters.spec.d.ts +1 -0
  124. package/lib/module/renderer/__tests__/e2e/Skottie.spec.d.ts +1 -0
  125. package/lib/module/renderer/__tests__/setup.d.ts +5 -0
  126. package/lib/module/renderer/components/Skottie.d.ts +4 -0
  127. package/lib/module/renderer/components/Skottie.js +5 -0
  128. package/lib/module/renderer/components/Skottie.js.map +1 -0
  129. package/lib/module/renderer/components/index.d.ts +1 -0
  130. package/lib/module/renderer/components/index.js +1 -0
  131. package/lib/module/renderer/components/index.js.map +1 -1
  132. package/lib/module/skia/types/ImageFilter/ImageFilterFactory.d.ts +252 -15
  133. package/lib/module/skia/types/ImageFilter/ImageFilterFactory.js.map +1 -1
  134. package/lib/module/skia/types/Matrix4.d.ts +11 -2
  135. package/lib/module/skia/types/Matrix4.js +40 -0
  136. package/lib/module/skia/types/Matrix4.js.map +1 -1
  137. package/lib/module/skia/types/Recorder.d.ts +2 -1
  138. package/lib/module/skia/types/Recorder.js.map +1 -1
  139. package/lib/module/skia/types/Skia.d.ts +2 -0
  140. package/lib/module/skia/types/Skia.js.map +1 -1
  141. package/lib/module/skia/types/Skottie.d.ts +223 -0
  142. package/lib/module/skia/types/Skottie.js +74 -0
  143. package/lib/module/skia/types/Skottie.js.map +1 -0
  144. package/lib/module/skia/types/index.d.ts +1 -0
  145. package/lib/module/skia/types/index.js +1 -0
  146. package/lib/module/skia/types/index.js.map +1 -1
  147. package/lib/module/skia/web/JsiSkImageFilterFactory.d.ts +29 -12
  148. package/lib/module/skia/web/JsiSkImageFilterFactory.js +88 -19
  149. package/lib/module/skia/web/JsiSkImageFilterFactory.js.map +1 -1
  150. package/lib/module/skia/web/JsiSkia.js +2 -0
  151. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  152. package/lib/module/skia/web/JsiSkottieAnimation.d.ts +59 -0
  153. package/lib/module/skia/web/JsiSkottieAnimation.js +236 -0
  154. package/lib/module/skia/web/JsiSkottieAnimation.js.map +1 -0
  155. package/lib/module/skia/web/JsiSkottieFactory.d.ts +9 -0
  156. package/lib/module/skia/web/JsiSkottieFactory.js +19 -0
  157. package/lib/module/skia/web/JsiSkottieFactory.js.map +1 -0
  158. package/lib/module/sksg/Elements.d.ts +2 -1
  159. package/lib/module/sksg/Elements.js.map +1 -1
  160. package/lib/module/sksg/Recorder/Core.d.ts +4 -2
  161. package/lib/module/sksg/Recorder/Core.js +1 -0
  162. package/lib/module/sksg/Recorder/Core.js.map +1 -1
  163. package/lib/module/sksg/Recorder/Player.js +3 -1
  164. package/lib/module/sksg/Recorder/Player.js.map +1 -1
  165. package/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +2 -1
  166. package/lib/module/sksg/Recorder/ReanimatedRecorder.js +4 -0
  167. package/lib/module/sksg/Recorder/ReanimatedRecorder.js.map +1 -1
  168. package/lib/module/sksg/Recorder/Recorder.d.ts +2 -1
  169. package/lib/module/sksg/Recorder/Recorder.js +6 -0
  170. package/lib/module/sksg/Recorder/Recorder.js.map +1 -1
  171. package/lib/module/sksg/Recorder/Visitor.js +3 -0
  172. package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
  173. package/lib/module/sksg/Recorder/commands/Drawing.d.ts +2 -2
  174. package/lib/module/sksg/Recorder/commands/Drawing.js +9 -2
  175. package/lib/module/sksg/Recorder/commands/Drawing.js.map +1 -1
  176. package/lib/module/sksg/Recorder/commands/ImageFilters.js +1 -1
  177. package/lib/module/sksg/Recorder/commands/ImageFilters.js.map +1 -1
  178. package/lib/typescript/lib/commonjs/renderer/components/Skottie.d.ts +2 -0
  179. package/lib/typescript/lib/commonjs/skia/types/Matrix4.d.ts +1 -0
  180. package/lib/typescript/lib/commonjs/skia/types/Skottie.d.ts +6 -0
  181. package/lib/typescript/lib/commonjs/skia/web/JsiSkImageFilterFactory.d.ts +22 -5
  182. package/lib/typescript/lib/commonjs/skia/web/JsiSkia.d.ts +2 -0
  183. package/lib/typescript/lib/commonjs/skia/web/JsiSkottieAnimation.d.ts +48 -0
  184. package/lib/typescript/lib/commonjs/skia/web/JsiSkottieFactory.d.ts +6 -0
  185. package/lib/typescript/lib/commonjs/sksg/Recorder/ReanimatedRecorder.d.ts +1 -0
  186. package/lib/typescript/lib/commonjs/sksg/Recorder/Recorder.d.ts +1 -0
  187. package/lib/typescript/lib/commonjs/sksg/Recorder/commands/Drawing.d.ts +1 -1
  188. package/lib/typescript/lib/module/mock/index.d.ts +7 -0
  189. package/lib/typescript/lib/module/renderer/components/Skottie.d.ts +2 -0
  190. package/lib/typescript/lib/module/renderer/components/index.d.ts +1 -0
  191. package/lib/typescript/lib/module/skia/Skia.web.d.ts +1 -0
  192. package/lib/typescript/lib/module/skia/types/Matrix4.d.ts +1 -0
  193. package/lib/typescript/lib/module/skia/types/Skottie.d.ts +5 -0
  194. package/lib/typescript/lib/module/skia/types/index.d.ts +1 -0
  195. package/lib/typescript/lib/module/skia/web/JsiSkImageFilterFactory.d.ts +22 -5
  196. package/lib/typescript/lib/module/skia/web/JsiSkia.d.ts +2 -0
  197. package/lib/typescript/lib/module/skia/web/JsiSkottieAnimation.d.ts +47 -0
  198. package/lib/typescript/lib/module/skia/web/JsiSkottieFactory.d.ts +5 -0
  199. package/lib/typescript/lib/module/sksg/Recorder/ReanimatedRecorder.d.ts +1 -0
  200. package/lib/typescript/lib/module/sksg/Recorder/Recorder.d.ts +1 -0
  201. package/lib/typescript/lib/module/sksg/Recorder/commands/Drawing.d.ts +1 -1
  202. package/lib/typescript/src/dom/nodes/datatypes/Gradient.d.ts +15 -15
  203. package/lib/typescript/src/dom/types/Drawings.d.ts +5 -1
  204. package/lib/typescript/src/dom/types/NodeType.d.ts +2 -1
  205. package/lib/typescript/src/renderer/__tests__/e2e/AdvancedImageFilters.spec.d.ts +1 -0
  206. package/lib/typescript/src/renderer/__tests__/e2e/Camera.spec.d.ts +21 -0
  207. package/lib/typescript/src/renderer/__tests__/e2e/LightingImageFilters.spec.d.ts +1 -0
  208. package/lib/typescript/src/renderer/__tests__/e2e/Skottie.spec.d.ts +1 -0
  209. package/lib/typescript/src/renderer/__tests__/setup.d.ts +5 -0
  210. package/lib/typescript/src/renderer/components/Skottie.d.ts +4 -0
  211. package/lib/typescript/src/renderer/components/index.d.ts +1 -0
  212. package/lib/typescript/src/skia/types/ImageFilter/ImageFilterFactory.d.ts +252 -15
  213. package/lib/typescript/src/skia/types/Matrix4.d.ts +11 -2
  214. package/lib/typescript/src/skia/types/Recorder.d.ts +2 -1
  215. package/lib/typescript/src/skia/types/Skia.d.ts +2 -0
  216. package/lib/typescript/src/skia/types/Skottie.d.ts +223 -0
  217. package/lib/typescript/src/skia/types/index.d.ts +1 -0
  218. package/lib/typescript/src/skia/web/JsiSkImageFilterFactory.d.ts +29 -12
  219. package/lib/typescript/src/skia/web/JsiSkottieAnimation.d.ts +59 -0
  220. package/lib/typescript/src/skia/web/JsiSkottieFactory.d.ts +9 -0
  221. package/lib/typescript/src/sksg/Elements.d.ts +2 -1
  222. package/lib/typescript/src/sksg/Recorder/Core.d.ts +4 -2
  223. package/lib/typescript/src/sksg/Recorder/ReanimatedRecorder.d.ts +2 -1
  224. package/lib/typescript/src/sksg/Recorder/Recorder.d.ts +2 -1
  225. package/lib/typescript/src/sksg/Recorder/commands/Drawing.d.ts +2 -2
  226. package/libs/android/arm64-v8a/libjsonreader.a +0 -0
  227. package/libs/android/armeabi-v7a/libjsonreader.a +0 -0
  228. package/libs/android/x86/libjsonreader.a +0 -0
  229. package/libs/android/x86_64/libjsonreader.a +0 -0
  230. package/libs/apple/libpathops.xcframework/Info.plist +9 -9
  231. package/libs/apple/libskia.xcframework/Info.plist +14 -14
  232. package/libs/apple/libskottie.xcframework/Info.plist +13 -13
  233. package/libs/apple/libskparagraph.xcframework/Info.plist +15 -15
  234. package/libs/apple/libsksg.xcframework/Info.plist +13 -13
  235. package/libs/apple/libskshaper.xcframework/Info.plist +15 -15
  236. package/libs/apple/libskunicode_core.xcframework/Info.plist +9 -9
  237. package/libs/apple/libskunicode_libgrapheme.xcframework/Info.plist +13 -13
  238. package/libs/apple/libsvg.xcframework/Info.plist +15 -15
  239. package/package.json +1 -1
  240. package/react-native-skia.podspec +4 -2
  241. package/src/__tests__/snapshots/matrix4/camera-corner.png +0 -0
  242. package/src/__tests__/snapshots/matrix4/camera-offset.png +0 -0
  243. package/src/__tests__/snapshots/matrix4/camera-top-left-center.png +0 -0
  244. package/src/__tests__/snapshots/matrix4/camera-zoom-out.png +0 -0
  245. package/src/__tests__/snapshots/matrix4/full-rect.png +0 -0
  246. package/src/__tests__/snapshots/matrix4/rect.png +0 -0
  247. package/src/__tests__/snapshots/matrix4/scaled-rect.png +0 -0
  248. package/src/__tests__/snapshots/matrix4/test-perspective.png +0 -0
  249. package/src/__tests__/snapshots/matrix4/test-perspective2.png +0 -0
  250. package/src/dom/types/Drawings.ts +6 -0
  251. package/src/dom/types/NodeType.ts +2 -0
  252. package/src/renderer/__tests__/e2e/AdvancedImageFilters.spec.tsx +492 -0
  253. package/src/renderer/__tests__/e2e/Camera.spec.tsx +475 -0
  254. package/src/renderer/__tests__/e2e/LightingImageFilters.spec.tsx +1478 -0
  255. package/src/renderer/__tests__/e2e/Skottie.spec.tsx +440 -0
  256. package/src/renderer/__tests__/e2e/setup/skottie/basic_slots.json +1118 -0
  257. package/src/renderer/__tests__/e2e/setup/skottie/color-props.json +1 -0
  258. package/src/renderer/__tests__/e2e/setup/skottie/confetti.json +5899 -0
  259. package/src/renderer/__tests__/e2e/setup/skottie/drinks.json +43857 -0
  260. package/src/renderer/__tests__/e2e/setup/skottie/fingerprint.json +1 -0
  261. package/src/renderer/__tests__/e2e/setup/skottie/lego_loader.json +29540 -0
  262. package/src/renderer/__tests__/e2e/setup/skottie/new-drop.json +1 -0
  263. package/src/renderer/__tests__/e2e/setup/skottie/onboarding.json +1 -0
  264. package/src/renderer/__tests__/e2e/setup/skottie/text-layer.json +1 -0
  265. package/src/renderer/__tests__/setup.tsx +23 -0
  266. package/src/renderer/components/Skottie.tsx +8 -0
  267. package/src/renderer/components/index.ts +1 -0
  268. package/src/skia/__tests__/assets/Avenir-Heavy.ttf +0 -0
  269. package/src/skia/types/ImageFilter/ImageFilterFactory.ts +391 -21
  270. package/src/skia/types/Matrix4.ts +108 -2
  271. package/src/skia/types/Recorder.ts +2 -0
  272. package/src/skia/types/Skia.ts +2 -0
  273. package/src/skia/types/Skottie.ts +266 -0
  274. package/src/skia/types/index.ts +1 -0
  275. package/src/skia/web/JsiSkImageFilterFactory.ts +266 -31
  276. package/src/skia/web/JsiSkia.ts +2 -0
  277. package/src/skia/web/JsiSkottieAnimation.ts +259 -0
  278. package/src/skia/web/JsiSkottieFactory.ts +25 -0
  279. package/src/sksg/Elements.tsx +2 -0
  280. package/src/sksg/Recorder/Core.ts +3 -0
  281. package/src/sksg/Recorder/Player.ts +3 -0
  282. package/src/sksg/Recorder/ReanimatedRecorder.ts +6 -0
  283. package/src/sksg/Recorder/Recorder.ts +5 -0
  284. package/src/sksg/Recorder/Visitor.ts +3 -0
  285. package/src/sksg/Recorder/commands/Drawing.ts +7 -3
  286. package/src/sksg/Recorder/commands/ImageFilters.ts +1 -1
  287. package/cpp/skia/include/pathops/SkPathOps.h +0 -17
@@ -0,0 +1,475 @@
1
+ import React from "react";
2
+
3
+ import { checkImage } from "../../../__tests__/setup";
4
+ import type { SkPath, SkRect, Vec3, Vec4 } from "../../../skia/types";
5
+ import {
6
+ mapPoint3d,
7
+ processTransform3d,
8
+ Matrix4,
9
+ setupCamera,
10
+ } from "../../../skia/types";
11
+ import { Group, Path, Rect } from "../../components";
12
+ import { importSkia, surface } from "../setup";
13
+
14
+ const pickPoint = (p: number[], index = 0, offset = 3) =>
15
+ [
16
+ p[0 + index * offset],
17
+ p[1 + index * offset],
18
+ p[2 + index * offset],
19
+ ] as const;
20
+
21
+ enum Path3Command {
22
+ Move,
23
+ Line,
24
+ Quad,
25
+ Cubic,
26
+ Close,
27
+ }
28
+
29
+ export class Path3 {
30
+ commands: [Path3Command, ...number[]][] = [];
31
+
32
+ constructor() {}
33
+
34
+ moveTo(to: Vec3) {
35
+ this.commands.push([Path3Command.Move, ...to]);
36
+ return this;
37
+ }
38
+
39
+ lineTo(to: Vec3) {
40
+ this.commands.push([Path3Command.Line, ...to]);
41
+ return this;
42
+ }
43
+
44
+ quadTo(control: Vec3, to: Vec3) {
45
+ this.commands.push([Path3Command.Quad, ...control, ...to]);
46
+ return this;
47
+ }
48
+
49
+ cubicTo(control1: Vec3, control2: Vec3, to: Vec3) {
50
+ this.commands.push([Path3Command.Cubic, ...control1, ...control2, ...to]);
51
+ return this;
52
+ }
53
+
54
+ close() {
55
+ this.commands.push([Path3Command.Close]);
56
+ return this;
57
+ }
58
+
59
+ addHRect(rect: SkRect, z: number) {
60
+ const { x, y, width, height } = rect;
61
+ const p0: Vec3 = [x, y, z];
62
+ const p1: Vec3 = [x + width, y, z];
63
+ const p2: Vec3 = [x + width, y + height, z];
64
+ const p3: Vec3 = [x, y + height, z];
65
+ this.moveTo(p0);
66
+ this.lineTo(p1);
67
+ this.lineTo(p2);
68
+ this.lineTo(p3);
69
+ this.close();
70
+ return this;
71
+ }
72
+
73
+ project(output: SkPath, tr?: Matrix4) {
74
+ const transform = tr ?? Matrix4();
75
+ this.commands.forEach(([cmd, ...args]) => {
76
+ switch (cmd) {
77
+ case Path3Command.Move: {
78
+ const to = mapPoint3d(transform, pickPoint(args));
79
+ output.moveTo(to[0], to[1]);
80
+ break;
81
+ }
82
+ case Path3Command.Line: {
83
+ const to = mapPoint3d(transform, pickPoint(args));
84
+ output.lineTo(to[0], to[1]);
85
+ break;
86
+ }
87
+ case Path3Command.Quad: {
88
+ const control = mapPoint3d(transform, pickPoint(args));
89
+ const to = mapPoint3d(transform, pickPoint(args, 1));
90
+ output.quadTo(control[0], control[1], to[0], to[1]);
91
+ break;
92
+ }
93
+ case Path3Command.Cubic: {
94
+ const control1 = mapPoint3d(transform, pickPoint(args));
95
+ const control2 = mapPoint3d(transform, pickPoint(args, 1));
96
+ const to = mapPoint3d(transform, pickPoint(args, 2));
97
+ output.cubicTo(
98
+ control1[0],
99
+ control1[1],
100
+ control2[0],
101
+ control2[1],
102
+ to[0],
103
+ to[1]
104
+ );
105
+ break;
106
+ }
107
+ case Path3Command.Close: {
108
+ output.close();
109
+ break;
110
+ }
111
+ default:
112
+ throw new Error(`Unknown command: ${cmd}`);
113
+ }
114
+ });
115
+ return this;
116
+ }
117
+ }
118
+
119
+ describe("Camera", () => {
120
+ it("Should do a perspective transformation", async () => {
121
+ const { Skia } = importSkia();
122
+ const { width, height } = surface;
123
+ const pad = 32;
124
+ const rct = {
125
+ x: pad,
126
+ y: pad,
127
+ width: width - pad * 2,
128
+ height: height - pad * 2,
129
+ };
130
+ const path = Skia.Path.Make();
131
+ const path3 = new Path3();
132
+ path3.addHRect(rct, 0);
133
+ path3.project(
134
+ path,
135
+ processTransform3d([
136
+ { translate: [width / 2, height / 2] },
137
+ { perspective: 300 },
138
+ { rotateX: 1 },
139
+ { translate: [-width / 2, -height / 2] },
140
+ ])
141
+ );
142
+ const image = await surface.draw(
143
+ <Group>
144
+ <Rect rect={rct} color="magenta" />
145
+ <Path path={path} color="cyan" opacity={0.5} />
146
+ </Group>
147
+ );
148
+ checkImage(image, "snapshots/matrix4/perspective.png");
149
+ });
150
+ it("Camera movement", async () => {
151
+ const { Skia } = importSkia();
152
+ const { width, height } = surface;
153
+ const pad = 32;
154
+ const rct = {
155
+ x: pad,
156
+ y: pad,
157
+ width: width - pad * 2,
158
+ height: height - pad * 2,
159
+ };
160
+ const path = Skia.Path.Make();
161
+ const path3 = new Path3();
162
+ path3.addHRect(rct, 0);
163
+ path3.project(path);
164
+ const image = await surface.draw(
165
+ <Group>
166
+ <Rect rect={rct} color="magenta" />
167
+ <Path path={path} color="cyan" opacity={0.5} />
168
+ </Group>
169
+ );
170
+ checkImage(image, "snapshots/matrix4/rect.png");
171
+ });
172
+ it("Camera movement (2)", async () => {
173
+ const { Skia } = importSkia();
174
+ const { width, height } = surface;
175
+ const pad = 0;
176
+ const rct = {
177
+ x: pad,
178
+ y: pad,
179
+ width: width - pad * 2,
180
+ height: height - pad * 2,
181
+ };
182
+ const path = Skia.Path.Make();
183
+ const path3 = new Path3();
184
+ path3.addHRect(rct, 0);
185
+
186
+ // Sensible camera defaults based on surface dimensions
187
+ const camAngle = Math.PI / 4; // 45 degrees for dramatic perspective
188
+
189
+ const cam = {
190
+ eye: [0, 0, 1] as const,
191
+ coa: [0, 0, 0] as const, // Look at origin (setupCamera handles viewport translation)
192
+ up: [0, 1, 0] as const,
193
+ near: 0.02,
194
+ far: 4,
195
+ angle: camAngle,
196
+ };
197
+
198
+ // Setup camera with surface-based viewport
199
+ const area: Vec4 = [0, 0, width, height];
200
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
201
+ path3.project(path, mat);
202
+ const image = await surface.draw(
203
+ <Group>
204
+ <Path path={path} color="cyan" opacity={0.5} />
205
+ </Group>
206
+ );
207
+ checkImage(image, "snapshots/matrix4/full-rect.png");
208
+ });
209
+ it("Camera movement (3)", async () => {
210
+ const { Skia } = importSkia();
211
+ const { width, height } = surface;
212
+ const pad = 0;
213
+ const rct = {
214
+ x: pad,
215
+ y: pad,
216
+ width: width - pad * 2,
217
+ height: height - pad * 2,
218
+ };
219
+ const path = Skia.Path.Make();
220
+ const path3 = new Path3();
221
+ path3.addHRect(rct, 0);
222
+
223
+ // Sensible camera defaults based on surface dimensions
224
+ const camAngle = Math.PI / 4; // 45 degrees for dramatic perspective
225
+
226
+ const cam = {
227
+ eye: [0, 0, 4] as const,
228
+ coa: [0, 0, 0] as const, // Look at origin (setupCamera handles viewport translation)
229
+ up: [0, 1, 0] as const,
230
+ near: 0.02,
231
+ far: 4,
232
+ angle: camAngle,
233
+ };
234
+
235
+ // Setup camera with surface-based viewport
236
+ const area: Vec4 = [0, 0, width, height];
237
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
238
+ path3.project(path, mat);
239
+ const image = await surface.draw(
240
+ <Group>
241
+ <Path path={path} color="cyan" opacity={0.5} />
242
+ </Group>
243
+ );
244
+ checkImage(image, "snapshots/matrix4/scaled-rect.png");
245
+ });
246
+ it("Camera coordinate system visualization", async () => {
247
+ const { Skia } = importSkia();
248
+ const { width, height } = surface;
249
+ const pad = 0;
250
+ const rct = {
251
+ x: pad,
252
+ y: pad,
253
+ width: width - pad * 2,
254
+ height: height - pad * 2,
255
+ };
256
+ const path = Skia.Path.Make();
257
+ const path3 = new Path3();
258
+ path3.addHRect(rct, 0);
259
+
260
+ const camAngle = Math.PI / 4;
261
+
262
+ const cam = {
263
+ eye: [0.5, 0.5, 1] as const, // Offset right and up in 3D space
264
+ coa: [0, 0, 0] as const, // Still look at center
265
+ up: [0, 1, 0] as const,
266
+ near: 0.02,
267
+ far: 4,
268
+ angle: camAngle,
269
+ };
270
+
271
+ const area: Vec4 = [0, 0, width, height];
272
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
273
+ path3.project(path, mat);
274
+ const image = await surface.draw(
275
+ <Group>
276
+ <Path path={path} color="cyan" opacity={0.5} />
277
+ </Group>
278
+ );
279
+ checkImage(image, "snapshots/matrix4/camera-offset.png");
280
+ });
281
+
282
+ it("Camera zoom out - rectangle appears half size", async () => {
283
+ const { Skia } = importSkia();
284
+ const { width, height } = surface;
285
+ const pad = 0;
286
+ const rct = {
287
+ x: pad,
288
+ y: pad,
289
+ width: width - pad * 2,
290
+ height: height - pad * 2,
291
+ };
292
+ const path = Skia.Path.Make();
293
+ const path3 = new Path3();
294
+ path3.addHRect(rct, 0);
295
+
296
+ const camAngle = Math.PI / 4;
297
+
298
+ const cam = {
299
+ eye: [0, 0, 2] as const, // Move camera twice as far away
300
+ coa: [0, 0, 0] as const, // Look at center
301
+ up: [0, 1, 0] as const,
302
+ near: 0.02,
303
+ far: 8, // Increase far plane since camera is further
304
+ angle: camAngle,
305
+ };
306
+
307
+ const area: Vec4 = [0, 0, width, height];
308
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
309
+ path3.project(path, mat);
310
+ const image = await surface.draw(
311
+ <Group>
312
+ <Path path={path} color="cyan" opacity={0.5} />
313
+ </Group>
314
+ );
315
+ checkImage(image, "snapshots/matrix4/camera-zoom-out.png");
316
+ });
317
+
318
+ it("Camera positioned at corner - look at corner", async () => {
319
+ const { Skia } = importSkia();
320
+ const { width, height } = surface;
321
+ const pad = 0;
322
+ const rct = {
323
+ x: pad,
324
+ y: pad,
325
+ width: width - pad * 2,
326
+ height: height - pad * 2,
327
+ };
328
+ const path = Skia.Path.Make();
329
+ const path3 = new Path3();
330
+ path3.addHRect(rct, 0);
331
+
332
+ const camAngle = Math.PI / 4;
333
+
334
+ const cam = {
335
+ eye: [-0.5, -0.5, 1] as const, // Position at corner in normalized coords
336
+ coa: [-0.5, -0.5, 0] as const, // Look at same corner
337
+ up: [0, 1, 0] as const,
338
+ near: 0.02,
339
+ far: 4,
340
+ angle: camAngle,
341
+ };
342
+
343
+ const area: Vec4 = [0, 0, width, height];
344
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
345
+ path3.project(path, mat);
346
+ const image = await surface.draw(
347
+ <Group>
348
+ <Path path={path} color="cyan" opacity={0.5} />
349
+ </Group>
350
+ );
351
+ checkImage(image, "snapshots/matrix4/camera-corner.png");
352
+ });
353
+
354
+ it("Camera centered - top-left corner at center", async () => {
355
+ const { Skia } = importSkia();
356
+ const { width, height } = surface;
357
+ const pad = 0;
358
+ const rct = {
359
+ x: pad,
360
+ y: pad,
361
+ width: width - pad * 2,
362
+ height: height - pad * 2,
363
+ };
364
+ const path = Skia.Path.Make();
365
+ const path3 = new Path3();
366
+ path3.addHRect(rct, 0);
367
+
368
+ const camAngle = Math.PI / 4;
369
+
370
+ const cam = {
371
+ eye: [-1, -1, 1] as const, // Camera centered
372
+ coa: [-1, -1, 0] as const, // Look at top-left corner of rectangle
373
+ up: [0, 1, 0] as const,
374
+ near: 0.02,
375
+ far: 4,
376
+ angle: camAngle,
377
+ };
378
+
379
+ const area: Vec4 = [0, 0, width, height];
380
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
381
+ path3.project(path, mat);
382
+ const image = await surface.draw(
383
+ <Group>
384
+ <Path path={path} color="cyan" opacity={0.5} />
385
+ </Group>
386
+ );
387
+ checkImage(image, "snapshots/matrix4/camera-top-left-center.png");
388
+ });
389
+ it("test perspective (1)", async () => {
390
+ const { Skia } = importSkia();
391
+ const { width, height } = surface;
392
+ const pad = 0;
393
+ const rct = {
394
+ x: pad,
395
+ y: pad,
396
+ width: width - pad * 2,
397
+ height: height - pad * 2,
398
+ };
399
+ const path = Skia.Path.Make();
400
+ const path3 = new Path3();
401
+ path3.addHRect(rct, 0);
402
+
403
+ const camAngle = Math.PI / 4;
404
+
405
+ const cam = {
406
+ eye: [-1.5, 0, 0.25] as const, // Camera centered
407
+ coa: [-1, 0, 0] as const, // Look at top-left corner of rectangle
408
+ up: [0, 1, 0] as const,
409
+ near: 0.02,
410
+ far: 10,
411
+ angle: camAngle,
412
+ };
413
+
414
+ const area: Vec4 = [0, 0, width, height];
415
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
416
+ path3.project(path, mat);
417
+ const image = await surface.draw(
418
+ <Group>
419
+ <Path path={path} color="cyan" opacity={0.5} />
420
+ </Group>
421
+ );
422
+ checkImage(image, "snapshots/matrix4/test-perspective.png");
423
+ });
424
+ it("test perspective (2)", async () => {
425
+ const { Skia } = importSkia();
426
+ const { width, height } = surface;
427
+ let pad = 0;
428
+ const rct = {
429
+ x: pad,
430
+ y: pad,
431
+ width: width - pad * 2,
432
+ height: height - pad * 2,
433
+ };
434
+ const path = Skia.Path.Make();
435
+ const path3 = new Path3();
436
+ path3.addHRect(rct, 0);
437
+
438
+ const path3a = new Path3();
439
+ pad = 20;
440
+ path3a.addHRect(
441
+ {
442
+ x: pad,
443
+ y: pad,
444
+ width: width - pad * 2,
445
+ height: height - pad * 2,
446
+ },
447
+ 0.5
448
+ );
449
+
450
+ const camAngle = Math.PI / 4;
451
+
452
+ const cam = {
453
+ eye: [-1.5, 0, 0.5] as const, // Camera centered
454
+ coa: [-1, 0, 0] as const, // Look at top-left corner of rectangle
455
+ up: [0, 1, 0] as const,
456
+ near: 0.02,
457
+ far: 10,
458
+ angle: camAngle,
459
+ };
460
+
461
+ const area: Vec4 = [0, 0, width, height];
462
+ const mat = setupCamera(area, Math.min(width, height) / 2, cam);
463
+ path3.project(path, mat);
464
+ const path1 = Skia.Path.Make();
465
+
466
+ path3a.project(path1, mat);
467
+ const image = await surface.draw(
468
+ <Group>
469
+ <Path path={path} color="cyan" opacity={0.5} />
470
+ <Path path={path1} color="red" opacity={0.5} />
471
+ </Group>
472
+ );
473
+ checkImage(image, "snapshots/matrix4/test-perspective2.png");
474
+ });
475
+ });