Another project
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(text): intro bone-text crate, fonts, outline tessellation

Lewis: May this revision serve well! <lu5a@proton.me>

+1003 -47
+390 -2
Cargo.lock
··· 245 245 dependencies = [ 246 246 "bone-document", 247 247 "bone-kernel", 248 + "bone-text", 248 249 "bone-types", 249 250 "bytemuck", 250 251 "lyon_tessellation", ··· 272 273 ] 273 274 274 275 [[package]] 276 + name = "bone-text" 277 + version = "0.0.0" 278 + dependencies = [ 279 + "lyon_tessellation", 280 + "parley", 281 + "serde", 282 + "swash", 283 + ] 284 + 285 + [[package]] 275 286 name = "bone-types" 276 287 version = "0.0.0" 277 288 dependencies = [ ··· 289 300 name = "bone-ui" 290 301 version = "0.0.0" 291 302 dependencies = [ 303 + "bone-text", 292 304 "insta", 305 + "lyon_tessellation", 293 306 "palette", 294 307 "ron", 295 308 "serde", 309 + "swash", 296 310 "taffy", 297 311 "thiserror 2.0.18", 312 + "unicode-segmentation", 298 313 "uom", 299 314 ] 300 315 ··· 480 495 ] 481 496 482 497 [[package]] 498 + name = "core_maths" 499 + version = "0.1.1" 500 + source = "registry+https://github.com/rust-lang/crates.io-index" 501 + checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" 502 + dependencies = [ 503 + "libm", 504 + ] 505 + 506 + [[package]] 483 507 name = "cpufeatures" 484 508 version = "0.3.0" 485 509 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 538 562 ] 539 563 540 564 [[package]] 565 + name = "displaydoc" 566 + version = "0.2.5" 567 + source = "registry+https://github.com/rust-lang/crates.io-index" 568 + checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 569 + dependencies = [ 570 + "proc-macro2", 571 + "quote", 572 + "syn 2.0.117", 573 + ] 574 + 575 + [[package]] 541 576 name = "dlib" 542 577 version = "0.5.3" 543 578 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 761 796 checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" 762 797 dependencies = [ 763 798 "bytemuck", 799 + ] 800 + 801 + [[package]] 802 + name = "fontique" 803 + version = "0.9.0" 804 + source = "registry+https://github.com/rust-lang/crates.io-index" 805 + checksum = "7c20b425addb8661e97fe1d51c4d8bcec3ec29ed6ad0db983976a7521276b8f7" 806 + dependencies = [ 807 + "hashbrown 0.17.0", 808 + "linebender_resource_handle", 809 + "memmap2", 810 + "parlance", 811 + "read-fonts 0.39.2", 812 + "smallvec", 764 813 ] 765 814 766 815 [[package]] ··· 1045 1094 ] 1046 1095 1047 1096 [[package]] 1097 + name = "harfrust" 1098 + version = "0.6.0" 1099 + source = "registry+https://github.com/rust-lang/crates.io-index" 1100 + checksum = "a9ce5e848d21ba97a324266e41c70e0eb5e2577a610c1fbd546e15096f2e8e37" 1101 + dependencies = [ 1102 + "bitflags 2.11.1", 1103 + "bytemuck", 1104 + "core_maths", 1105 + "read-fonts 0.39.2", 1106 + "smallvec", 1107 + ] 1108 + 1109 + [[package]] 1048 1110 name = "hashbrown" 1049 1111 version = "0.15.5" 1050 1112 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1069 1131 version = "0.17.0" 1070 1132 source = "registry+https://github.com/rust-lang/crates.io-index" 1071 1133 checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" 1134 + dependencies = [ 1135 + "foldhash 0.2.0", 1136 + ] 1072 1137 1073 1138 [[package]] 1074 1139 name = "heck" ··· 1089 1154 checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" 1090 1155 1091 1156 [[package]] 1157 + name = "icu_collections" 1158 + version = "2.2.0" 1159 + source = "registry+https://github.com/rust-lang/crates.io-index" 1160 + checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" 1161 + dependencies = [ 1162 + "displaydoc", 1163 + "potential_utf", 1164 + "utf8_iter", 1165 + "yoke", 1166 + "zerofrom", 1167 + "zerovec", 1168 + ] 1169 + 1170 + [[package]] 1171 + name = "icu_locale" 1172 + version = "2.2.0" 1173 + source = "registry+https://github.com/rust-lang/crates.io-index" 1174 + checksum = "d5a396343c7208121dc86e35623d3dfe19814a7613cfd14964994cdc9c9a2e26" 1175 + dependencies = [ 1176 + "icu_collections", 1177 + "icu_locale_core", 1178 + "icu_locale_data", 1179 + "icu_provider", 1180 + "potential_utf", 1181 + "tinystr", 1182 + "zerovec", 1183 + ] 1184 + 1185 + [[package]] 1186 + name = "icu_locale_core" 1187 + version = "2.2.0" 1188 + source = "registry+https://github.com/rust-lang/crates.io-index" 1189 + checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" 1190 + dependencies = [ 1191 + "displaydoc", 1192 + "litemap", 1193 + "serde", 1194 + "tinystr", 1195 + "writeable", 1196 + "zerovec", 1197 + ] 1198 + 1199 + [[package]] 1200 + name = "icu_locale_data" 1201 + version = "2.2.0" 1202 + source = "registry+https://github.com/rust-lang/crates.io-index" 1203 + checksum = "d5fdcc9ac77c6d74ff5cf6e65ef3181d6af32003b16fce3a77fb451d2f695993" 1204 + 1205 + [[package]] 1206 + name = "icu_normalizer" 1207 + version = "2.2.0" 1208 + source = "registry+https://github.com/rust-lang/crates.io-index" 1209 + checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" 1210 + dependencies = [ 1211 + "icu_collections", 1212 + "icu_normalizer_data", 1213 + "icu_properties", 1214 + "icu_provider", 1215 + "smallvec", 1216 + "zerovec", 1217 + ] 1218 + 1219 + [[package]] 1220 + name = "icu_normalizer_data" 1221 + version = "2.2.0" 1222 + source = "registry+https://github.com/rust-lang/crates.io-index" 1223 + checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" 1224 + 1225 + [[package]] 1226 + name = "icu_properties" 1227 + version = "2.2.0" 1228 + source = "registry+https://github.com/rust-lang/crates.io-index" 1229 + checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" 1230 + dependencies = [ 1231 + "icu_collections", 1232 + "icu_locale_core", 1233 + "icu_properties_data", 1234 + "icu_provider", 1235 + "zerotrie", 1236 + "zerovec", 1237 + ] 1238 + 1239 + [[package]] 1240 + name = "icu_properties_data" 1241 + version = "2.2.0" 1242 + source = "registry+https://github.com/rust-lang/crates.io-index" 1243 + checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" 1244 + 1245 + [[package]] 1246 + name = "icu_provider" 1247 + version = "2.2.0" 1248 + source = "registry+https://github.com/rust-lang/crates.io-index" 1249 + checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" 1250 + dependencies = [ 1251 + "displaydoc", 1252 + "icu_locale_core", 1253 + "serde", 1254 + "stable_deref_trait", 1255 + "writeable", 1256 + "yoke", 1257 + "zerofrom", 1258 + "zerotrie", 1259 + "zerovec", 1260 + ] 1261 + 1262 + [[package]] 1263 + name = "icu_segmenter" 1264 + version = "2.2.0" 1265 + source = "registry+https://github.com/rust-lang/crates.io-index" 1266 + checksum = "5c0794db0b1a86193ac9c48768d0e6c52c54448e0870ad87907d456ee0dac964" 1267 + dependencies = [ 1268 + "icu_collections", 1269 + "icu_locale", 1270 + "icu_provider", 1271 + "icu_segmenter_data", 1272 + "potential_utf", 1273 + "utf8_iter", 1274 + "zerovec", 1275 + ] 1276 + 1277 + [[package]] 1278 + name = "icu_segmenter_data" 1279 + version = "2.2.0" 1280 + source = "registry+https://github.com/rust-lang/crates.io-index" 1281 + checksum = "e4a2c462a4d927d512f5f882a033ddd62f33a05bb9f230d98f736ac3dc85938f" 1282 + 1283 + [[package]] 1092 1284 name = "indexmap" 1093 1285 version = "2.14.0" 1094 1286 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1261 1453 ] 1262 1454 1263 1455 [[package]] 1456 + name = "linebender_resource_handle" 1457 + version = "0.1.1" 1458 + source = "registry+https://github.com/rust-lang/crates.io-index" 1459 + checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" 1460 + 1461 + [[package]] 1264 1462 name = "linux-raw-sys" 1265 1463 version = "0.4.15" 1266 1464 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1271 1469 version = "0.12.1" 1272 1470 source = "registry+https://github.com/rust-lang/crates.io-index" 1273 1471 checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" 1472 + 1473 + [[package]] 1474 + name = "litemap" 1475 + version = "0.8.2" 1476 + source = "registry+https://github.com/rust-lang/crates.io-index" 1477 + checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" 1274 1478 1275 1479 [[package]] 1276 1480 name = "litrs" ··· 1941 2145 ] 1942 2146 1943 2147 [[package]] 2148 + name = "parlance" 2149 + version = "0.1.0" 2150 + source = "registry+https://github.com/rust-lang/crates.io-index" 2151 + checksum = "4b6937eda350acc1a5d05872c3cbf99fe78619c269096e2be3d4a350058639d5" 2152 + 2153 + [[package]] 2154 + name = "parley" 2155 + version = "0.9.0" 2156 + source = "registry+https://github.com/rust-lang/crates.io-index" 2157 + checksum = "8fad031076f48f0d4d85ce1aea9b94b4e715a4d636a030a123038f8f5b5e4343" 2158 + dependencies = [ 2159 + "fontique", 2160 + "harfrust", 2161 + "hashbrown 0.17.0", 2162 + "icu_normalizer", 2163 + "icu_properties", 2164 + "icu_segmenter", 2165 + "linebender_resource_handle", 2166 + "parlance", 2167 + "parley_data", 2168 + "skrifa 0.42.1", 2169 + ] 2170 + 2171 + [[package]] 2172 + name = "parley_data" 2173 + version = "0.9.0" 2174 + source = "registry+https://github.com/rust-lang/crates.io-index" 2175 + checksum = "19ab9ace3fad1b9ed603ddac5b595e69931fc50263d7e04e4055015b77b02da5" 2176 + dependencies = [ 2177 + "icu_properties", 2178 + ] 2179 + 2180 + [[package]] 1944 2181 name = "paste" 1945 2182 version = "1.0.15" 1946 2183 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2039 2276 ] 2040 2277 2041 2278 [[package]] 2279 + name = "potential_utf" 2280 + version = "0.1.5" 2281 + source = "registry+https://github.com/rust-lang/crates.io-index" 2282 + checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" 2283 + dependencies = [ 2284 + "serde_core", 2285 + "writeable", 2286 + "zerovec", 2287 + ] 2288 + 2289 + [[package]] 2042 2290 name = "ppv-lite86" 2043 2291 version = "0.2.21" 2044 2292 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2247 2495 checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" 2248 2496 dependencies = [ 2249 2497 "bytemuck", 2498 + "font-types", 2499 + ] 2500 + 2501 + [[package]] 2502 + name = "read-fonts" 2503 + version = "0.39.2" 2504 + source = "registry+https://github.com/rust-lang/crates.io-index" 2505 + checksum = "c4ed38b89c2c77ff968c524145ad65fb010f38af5c7a224b53b81d47ac2daa81" 2506 + dependencies = [ 2507 + "bytemuck", 2508 + "core_maths", 2250 2509 "font-types", 2251 2510 ] 2252 2511 ··· 2515 2774 checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" 2516 2775 dependencies = [ 2517 2776 "bytemuck", 2518 - "read-fonts", 2777 + "read-fonts 0.37.0", 2778 + ] 2779 + 2780 + [[package]] 2781 + name = "skrifa" 2782 + version = "0.42.1" 2783 + source = "registry+https://github.com/rust-lang/crates.io-index" 2784 + checksum = "0c34617370ae968efb7161bb2beb517d9084659aae19e24b89e3db25b46e4564" 2785 + dependencies = [ 2786 + "bytemuck", 2787 + "read-fonts 0.39.2", 2519 2788 ] 2520 2789 2521 2790 [[package]] ··· 2584 2853 ] 2585 2854 2586 2855 [[package]] 2856 + name = "stable_deref_trait" 2857 + version = "1.2.1" 2858 + source = "registry+https://github.com/rust-lang/crates.io-index" 2859 + checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 2860 + 2861 + [[package]] 2587 2862 name = "static_assertions" 2588 2863 version = "1.1.0" 2589 2864 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2601 2876 source = "registry+https://github.com/rust-lang/crates.io-index" 2602 2877 checksum = "842f3cd369c2ba38966204f983eaa5e54a8e84a7d7159ed36ade2b6c335aae64" 2603 2878 dependencies = [ 2604 - "skrifa", 2879 + "skrifa 0.40.0", 2605 2880 "yazi", 2606 2881 "zeno", 2607 2882 ] ··· 2629 2904 ] 2630 2905 2631 2906 [[package]] 2907 + name = "synstructure" 2908 + version = "0.13.2" 2909 + source = "registry+https://github.com/rust-lang/crates.io-index" 2910 + checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 2911 + dependencies = [ 2912 + "proc-macro2", 2913 + "quote", 2914 + "syn 2.0.117", 2915 + ] 2916 + 2917 + [[package]] 2632 2918 name = "sysctl" 2633 2919 version = "0.6.0" 2634 2920 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2751 3037 ] 2752 3038 2753 3039 [[package]] 3040 + name = "tinystr" 3041 + version = "0.8.3" 3042 + source = "registry+https://github.com/rust-lang/crates.io-index" 3043 + checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" 3044 + dependencies = [ 3045 + "displaydoc", 3046 + "serde_core", 3047 + "zerovec", 3048 + ] 3049 + 3050 + [[package]] 2754 3051 name = "toml_datetime" 2755 3052 version = "1.1.1+spec-1.1.0" 2756 3053 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2892 3189 "num-traits", 2893 3190 "typenum", 2894 3191 ] 3192 + 3193 + [[package]] 3194 + name = "utf8_iter" 3195 + version = "1.0.4" 3196 + source = "registry+https://github.com/rust-lang/crates.io-index" 3197 + checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2895 3198 2896 3199 [[package]] 2897 3200 name = "valuable" ··· 3563 3866 checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" 3564 3867 3565 3868 [[package]] 3869 + name = "writeable" 3870 + version = "0.6.3" 3871 + source = "registry+https://github.com/rust-lang/crates.io-index" 3872 + checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" 3873 + 3874 + [[package]] 3566 3875 name = "x11-dl" 3567 3876 version = "2.21.0" 3568 3877 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3632 3941 checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" 3633 3942 3634 3943 [[package]] 3944 + name = "yoke" 3945 + version = "0.8.2" 3946 + source = "registry+https://github.com/rust-lang/crates.io-index" 3947 + checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" 3948 + dependencies = [ 3949 + "stable_deref_trait", 3950 + "yoke-derive", 3951 + "zerofrom", 3952 + ] 3953 + 3954 + [[package]] 3955 + name = "yoke-derive" 3956 + version = "0.8.2" 3957 + source = "registry+https://github.com/rust-lang/crates.io-index" 3958 + checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" 3959 + dependencies = [ 3960 + "proc-macro2", 3961 + "quote", 3962 + "syn 2.0.117", 3963 + "synstructure", 3964 + ] 3965 + 3966 + [[package]] 3635 3967 name = "zeno" 3636 3968 version = "0.3.3" 3637 3969 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3656 3988 "quote", 3657 3989 "syn 2.0.117", 3658 3990 ] 3991 + 3992 + [[package]] 3993 + name = "zerofrom" 3994 + version = "0.1.7" 3995 + source = "registry+https://github.com/rust-lang/crates.io-index" 3996 + checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" 3997 + dependencies = [ 3998 + "zerofrom-derive", 3999 + ] 4000 + 4001 + [[package]] 4002 + name = "zerofrom-derive" 4003 + version = "0.1.7" 4004 + source = "registry+https://github.com/rust-lang/crates.io-index" 4005 + checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" 4006 + dependencies = [ 4007 + "proc-macro2", 4008 + "quote", 4009 + "syn 2.0.117", 4010 + "synstructure", 4011 + ] 4012 + 4013 + [[package]] 4014 + name = "zerotrie" 4015 + version = "0.2.4" 4016 + source = "registry+https://github.com/rust-lang/crates.io-index" 4017 + checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" 4018 + dependencies = [ 4019 + "displaydoc", 4020 + "yoke", 4021 + "zerofrom", 4022 + "zerovec", 4023 + ] 4024 + 4025 + [[package]] 4026 + name = "zerovec" 4027 + version = "0.11.6" 4028 + source = "registry+https://github.com/rust-lang/crates.io-index" 4029 + checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" 4030 + dependencies = [ 4031 + "serde", 4032 + "yoke", 4033 + "zerofrom", 4034 + "zerovec-derive", 4035 + ] 4036 + 4037 + [[package]] 4038 + name = "zerovec-derive" 4039 + version = "0.11.3" 4040 + source = "registry+https://github.com/rust-lang/crates.io-index" 4041 + checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" 4042 + dependencies = [ 4043 + "proc-macro2", 4044 + "quote", 4045 + "syn 2.0.117", 4046 + ]
+5 -1
Cargo.toml
··· 5 5 "crates/bone-kernel", 6 6 "crates/bone-solver", 7 7 "crates/bone-document", 8 + "crates/bone-text", 8 9 "crates/bone-render", 9 10 "crates/bone-ui", 10 11 "crates/bone-app", ··· 33 34 bone-solver = { path = "crates/bone-solver" } 34 35 bone-document = { path = "crates/bone-document" } 35 36 bone-render = { path = "crates/bone-render" } 37 + bone-text = { path = "crates/bone-text" } 36 38 bone-ui = { path = "crates/bone-ui" } 37 39 38 40 blake3 = { version = "1", default-features = false, features = ["std"] } ··· 42 44 lyon_tessellation = "1" 43 45 nalgebra = { version = "0.33", default-features = false, features = ["std"] } 44 46 palette = { version = "0.7", default-features = false, features = ["std"] } 47 + parley = { version = "0.9", default-features = false, features = ["std"] } 45 48 png = { version = "0.17", default-features = false } 46 49 pollster = "0.4" 47 50 proptest = { version = "1", default-features = false, features = ["std"] } 48 51 ron = "0.12" 49 52 serde = { version = "1", default-features = false, features = ["std", "derive", "rc"] } 50 53 slotmap = { version = "1", default-features = false, features = ["std", "serde"] } 51 - swash = { version = "0.2", default-features = false, features = ["std", "scale"] } 54 + swash = { version = "0.2", default-features = false, features = ["std", "scale", "render"] } 52 55 taffy = { version = "0.10", default-features = false, features = ["std", "flexbox", "grid", "content_size", "serde", "taffy_tree"] } 53 56 tempfile = "3" 54 57 thiserror = "2" 55 58 tracing = "0.1" 56 59 tracing-subscriber = { version = "0.3", features = ["env-filter"] } 60 + unicode-segmentation = "1" 57 61 uom = { version = "0.38", default-features = false, features = ["f64", "si", "std", "autoconvert"] } 58 62 wgpu = "29" 59 63 winit = "0.30"
+187
assets/DejaVu-LICENSE
··· 1 + Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. 2 + Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) 3 + 4 + 5 + Bitstream Vera Fonts Copyright 6 + ------------------------------ 7 + 8 + Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is 9 + a trademark of Bitstream, Inc. 10 + 11 + Permission is hereby granted, free of charge, to any person obtaining a copy 12 + of the fonts accompanying this license ("Fonts") and associated 13 + documentation files (the "Font Software"), to reproduce and distribute the 14 + Font Software, including without limitation the rights to use, copy, merge, 15 + publish, distribute, and/or sell copies of the Font Software, and to permit 16 + persons to whom the Font Software is furnished to do so, subject to the 17 + following conditions: 18 + 19 + The above copyright and trademark notices and this permission notice shall 20 + be included in all copies of one or more of the Font Software typefaces. 21 + 22 + The Font Software may be modified, altered, or added to, and in particular 23 + the designs of glyphs or characters in the Fonts may be modified and 24 + additional glyphs or characters may be added to the Fonts, only if the fonts 25 + are renamed to names not containing either the words "Bitstream" or the word 26 + "Vera". 27 + 28 + This License becomes null and void to the extent applicable to Fonts or Font 29 + Software that has been modified and is distributed under the "Bitstream 30 + Vera" names. 31 + 32 + The Font Software may be sold as part of a larger software package but no 33 + copy of one or more of the Font Software typefaces may be sold by itself. 34 + 35 + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 36 + OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, 37 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, 38 + TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME 39 + FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING 40 + ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 41 + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 42 + THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE 43 + FONT SOFTWARE. 44 + 45 + Except as contained in this notice, the names of Gnome, the Gnome 46 + Foundation, and Bitstream Inc., shall not be used in advertising or 47 + otherwise to promote the sale, use or other dealings in this Font Software 48 + without prior written authorization from the Gnome Foundation or Bitstream 49 + Inc., respectively. For further information, contact: fonts at gnome dot 50 + org. 51 + 52 + Arev Fonts Copyright 53 + ------------------------------ 54 + 55 + Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. 56 + 57 + Permission is hereby granted, free of charge, to any person obtaining 58 + a copy of the fonts accompanying this license ("Fonts") and 59 + associated documentation files (the "Font Software"), to reproduce 60 + and distribute the modifications to the Bitstream Vera Font Software, 61 + including without limitation the rights to use, copy, merge, publish, 62 + distribute, and/or sell copies of the Font Software, and to permit 63 + persons to whom the Font Software is furnished to do so, subject to 64 + the following conditions: 65 + 66 + The above copyright and trademark notices and this permission notice 67 + shall be included in all copies of one or more of the Font Software 68 + typefaces. 69 + 70 + The Font Software may be modified, altered, or added to, and in 71 + particular the designs of glyphs or characters in the Fonts may be 72 + modified and additional glyphs or characters may be added to the 73 + Fonts, only if the fonts are renamed to names not containing either 74 + the words "Tavmjong Bah" or the word "Arev". 75 + 76 + This License becomes null and void to the extent applicable to Fonts 77 + or Font Software that has been modified and is distributed under the 78 + "Tavmjong Bah Arev" names. 79 + 80 + The Font Software may be sold as part of a larger software package but 81 + no copy of one or more of the Font Software typefaces may be sold by 82 + itself. 83 + 84 + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 85 + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 86 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 87 + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL 88 + TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 89 + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 90 + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 91 + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 92 + OTHER DEALINGS IN THE FONT SOFTWARE. 93 + 94 + Except as contained in this notice, the name of Tavmjong Bah shall not 95 + be used in advertising or otherwise to promote the sale, use or other 96 + dealings in this Font Software without prior written authorization 97 + from Tavmjong Bah. For further information, contact: tavmjong @ free 98 + . fr. 99 + 100 + TeX Gyre DJV Math 101 + ----------------- 102 + Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. 103 + 104 + Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski 105 + (on behalf of TeX users groups) are in public domain. 106 + 107 + Letters imported from Euler Fraktur from AMSfonts are (c) American 108 + Mathematical Society (see below). 109 + Bitstream Vera Fonts Copyright 110 + Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera 111 + is a trademark of Bitstream, Inc. 112 + 113 + Permission is hereby granted, free of charge, to any person obtaining a copy 114 + of the fonts accompanying this license (“Fonts”) and associated 115 + documentation 116 + files (the “Font Software”), to reproduce and distribute the Font Software, 117 + including without limitation the rights to use, copy, merge, publish, 118 + distribute, 119 + and/or sell copies of the Font Software, and to permit persons to whom 120 + the Font Software is furnished to do so, subject to the following 121 + conditions: 122 + 123 + The above copyright and trademark notices and this permission notice 124 + shall be 125 + included in all copies of one or more of the Font Software typefaces. 126 + 127 + The Font Software may be modified, altered, or added to, and in particular 128 + the designs of glyphs or characters in the Fonts may be modified and 129 + additional 130 + glyphs or characters may be added to the Fonts, only if the fonts are 131 + renamed 132 + to names not containing either the words “Bitstream” or the word “Vera”. 133 + 134 + This License becomes null and void to the extent applicable to Fonts or 135 + Font Software 136 + that has been modified and is distributed under the “Bitstream Vera” 137 + names. 138 + 139 + The Font Software may be sold as part of a larger software package but 140 + no copy 141 + of one or more of the Font Software typefaces may be sold by itself. 142 + 143 + THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS 144 + OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, 145 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, 146 + TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME 147 + FOUNDATION 148 + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, 149 + SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN 150 + ACTION 151 + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR 152 + INABILITY TO USE 153 + THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. 154 + Except as contained in this notice, the names of GNOME, the GNOME 155 + Foundation, 156 + and Bitstream Inc., shall not be used in advertising or otherwise to promote 157 + the sale, use or other dealings in this Font Software without prior written 158 + authorization from the GNOME Foundation or Bitstream Inc., respectively. 159 + For further information, contact: fonts at gnome dot org. 160 + 161 + AMSFonts (v. 2.2) copyright 162 + 163 + The PostScript Type 1 implementation of the AMSFonts produced by and 164 + previously distributed by Blue Sky Research and Y&Y, Inc. are now freely 165 + available for general use. This has been accomplished through the 166 + cooperation 167 + of a consortium of scientific publishers with Blue Sky Research and Y&Y. 168 + Members of this consortium include: 169 + 170 + Elsevier Science IBM Corporation Society for Industrial and Applied 171 + Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) 172 + 173 + In order to assure the authenticity of these fonts, copyright will be 174 + held by 175 + the American Mathematical Society. This is not meant to restrict in any way 176 + the legitimate use of the fonts, such as (but not limited to) electronic 177 + distribution of documents containing these fonts, inclusion of these fonts 178 + into other public domain or commercial font collections or computer 179 + applications, use of the outline data to create derivative fonts and/or 180 + faces, etc. However, the AMS does require that the AMS copyright notice be 181 + removed from any derivative versions of the fonts which have been altered in 182 + any way. In addition, to ensure the fidelity of TeX documents using Computer 183 + Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, 184 + has requested that any alterations which yield different font metrics be 185 + given a different name. 186 + 187 + $Id$
assets/DejaVuSans.ttf

This is a binary file and will not be displayed.

-44
crates/bone-render/assets/DejaVuSansMono.LICENSE
··· 1 - DejaVu Sans Mono (unmodified redistribution) 2 - 3 - Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. 4 - Bitstream Vera is a trademark of Bitstream, Inc. 5 - DejaVu changes are in public domain. 6 - 7 - Permission is hereby granted, free of charge, to any person obtaining a copy 8 - of the fonts accompanying this license ("Fonts") and associated documentation 9 - files (the "Font Software"), to reproduce and distribute the Font Software, 10 - including without limitation the rights to use, copy, merge, publish, 11 - distribute, and/or sell copies of the Font Software, and to permit persons to 12 - whom the Font Software is furnished to do so, subject to the following 13 - conditions: 14 - 15 - The above copyright and trademark notices and this permission notice shall be 16 - included in all copies of one or more of the Font Software typefaces. 17 - 18 - The Font Software may be modified, altered, or added to, and in particular 19 - the designs of glyphs or characters in the Fonts may be modified and 20 - additional glyphs or characters may be added to the Fonts, only if the fonts 21 - are renamed to names not containing either the words "Bitstream" or the word 22 - "Vera". 23 - 24 - This License becomes null and void to the extent applicable to Fonts or Font 25 - Software that has been modified and is distributed under the "Bitstream Vera" 26 - names. 27 - 28 - The Font Software may be sold as part of a larger software package but no 29 - copy of one or more of the Font Software typefaces may be sold by itself. 30 - 31 - THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 32 - OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, 33 - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, 34 - TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION 35 - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, 36 - SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION 37 - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO 38 - USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. 39 - 40 - Except as contained in this notice, the names of Gnome, the Gnome Foundation, 41 - and Bitstream Inc., shall not be used in advertising or otherwise to promote 42 - the sale, use or other dealings in this Font Software without prior written 43 - authorization from the Gnome Foundation or Bitstream Inc., respectively. For 44 - further information, contact: fonts at gnome dot org.
crates/bone-render/assets/DejaVuSansMono.ttf assets/DejaVuSansMono.ttf
+15
crates/bone-text/Cargo.toml
··· 1 + [package] 2 + name = "bone-text" 3 + version.workspace = true 4 + edition.workspace = true 5 + license.workspace = true 6 + rust-version.workspace = true 7 + 8 + [dependencies] 9 + lyon_tessellation = { workspace = true } 10 + parley = { workspace = true } 11 + serde = { workspace = true } 12 + swash = { workspace = true } 13 + 14 + [lints] 15 + workspace = true
+103
crates/bone-text/src/fonts.rs
··· 1 + use parley::FontWeight as ParleyFontWeight; 2 + use serde::{Deserialize, Serialize}; 3 + use swash::FontRef; 4 + 5 + pub(crate) const SANS_DATA: &[u8] = include_bytes!("../../../assets/DejaVuSans.ttf"); 6 + pub(crate) const MONO_DATA: &[u8] = include_bytes!("../../../assets/DejaVuSansMono.ttf"); 7 + 8 + pub(crate) const SANS_FAMILY: &str = "DejaVu Sans"; 9 + pub(crate) const MONO_FAMILY: &str = "DejaVu Sans Mono"; 10 + 11 + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] 12 + pub enum FontFace { 13 + Sans, 14 + Mono, 15 + } 16 + 17 + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] 18 + pub enum FontWeight { 19 + Regular, 20 + Medium, 21 + Semibold, 22 + Bold, 23 + } 24 + 25 + #[must_use] 26 + pub fn load_font(face: FontFace) -> FontRef<'static> { 27 + let bytes = data_for(face); 28 + let label = family_for(face); 29 + let Some(font) = FontRef::from_index(bytes, 0) else { 30 + panic!("bundled font {label} failed to parse; binary asset is broken"); 31 + }; 32 + font 33 + } 34 + 35 + pub(crate) const fn data_for(face: FontFace) -> &'static [u8] { 36 + match face { 37 + FontFace::Sans => SANS_DATA, 38 + FontFace::Mono => MONO_DATA, 39 + } 40 + } 41 + 42 + pub(crate) const fn family_for(face: FontFace) -> &'static str { 43 + match face { 44 + FontFace::Sans => SANS_FAMILY, 45 + FontFace::Mono => MONO_FAMILY, 46 + } 47 + } 48 + 49 + pub(crate) const fn parley_weight(weight: FontWeight) -> ParleyFontWeight { 50 + match weight { 51 + FontWeight::Regular => ParleyFontWeight::NORMAL, 52 + FontWeight::Medium => ParleyFontWeight::MEDIUM, 53 + FontWeight::Semibold => ParleyFontWeight::SEMI_BOLD, 54 + FontWeight::Bold => ParleyFontWeight::BOLD, 55 + } 56 + } 57 + 58 + #[cfg(test)] 59 + mod tests { 60 + use super::{ 61 + FontFace, FontWeight, MONO_DATA, MONO_FAMILY, SANS_DATA, SANS_FAMILY, data_for, family_for, 62 + load_font, parley_weight, 63 + }; 64 + use parley::FontWeight as ParleyFontWeight; 65 + 66 + #[test] 67 + fn sans_and_mono_data_are_distinct_bundled_assets() { 68 + assert!(!SANS_DATA.is_empty()); 69 + assert!(!MONO_DATA.is_empty()); 70 + assert_ne!(SANS_DATA, MONO_DATA); 71 + } 72 + 73 + #[test] 74 + fn data_for_resolves_face_to_its_asset() { 75 + assert_eq!(data_for(FontFace::Sans), SANS_DATA); 76 + assert_eq!(data_for(FontFace::Mono), MONO_DATA); 77 + } 78 + 79 + #[test] 80 + fn family_for_resolves_face_to_its_family_name() { 81 + assert_eq!(family_for(FontFace::Sans), SANS_FAMILY); 82 + assert_eq!(family_for(FontFace::Mono), MONO_FAMILY); 83 + } 84 + 85 + #[test] 86 + fn load_font_returns_valid_fontref_for_each_face() { 87 + let sans = load_font(FontFace::Sans); 88 + let mono = load_font(FontFace::Mono); 89 + assert!(sans.charmap().map(u32::from('A')) > 0); 90 + assert!(mono.charmap().map(u32::from('A')) > 0); 91 + } 92 + 93 + #[test] 94 + fn parley_weight_round_trips_each_step() { 95 + assert_eq!(parley_weight(FontWeight::Regular), ParleyFontWeight::NORMAL); 96 + assert_eq!(parley_weight(FontWeight::Medium), ParleyFontWeight::MEDIUM); 97 + assert_eq!( 98 + parley_weight(FontWeight::Semibold), 99 + ParleyFontWeight::SEMI_BOLD 100 + ); 101 + assert_eq!(parley_weight(FontWeight::Bold), ParleyFontWeight::BOLD); 102 + } 103 + }
+10
crates/bone-text/src/lib.rs
··· 1 + mod fonts; 2 + mod outline; 3 + mod shape; 4 + 5 + pub use fonts::{FontFace, FontWeight, load_font}; 6 + pub use outline::{TessellatedOutline, append_outline, outline_to_path, tessellate_path}; 7 + pub use shape::{ 8 + GlyphId, MaxWidth, ShapeRequest, ShapedGlyph, ShapedLine, ShapedRun, ShapedText, Shaper, 9 + SourceByteIndex, 10 + };
+293
crates/bone-text/src/outline.rs
··· 1 + use lyon_tessellation::{ 2 + BuffersBuilder, FillOptions, FillTessellator, FillVertex, TessellationError, VertexBuffers, 3 + path::{Path as LyonPath, builder::WithSvg, math::Point as LyonPoint, path::BuilderImpl}, 4 + }; 5 + use swash::{ 6 + scale::outline::Outline, 7 + zeno::{PathBuilder, PathData as _, Point as ZenoPoint}, 8 + }; 9 + 10 + const FILL_TOLERANCE_PX: f32 = 0.2; 11 + 12 + #[derive(Clone, Debug, Default, PartialEq)] 13 + pub struct TessellatedOutline { 14 + pub vertices_px: Vec<[f32; 2]>, 15 + pub indices: Vec<u32>, 16 + } 17 + 18 + impl TessellatedOutline { 19 + #[must_use] 20 + pub fn is_empty(&self) -> bool { 21 + self.indices.is_empty() 22 + } 23 + } 24 + 25 + pub fn append_outline(builder: &mut WithSvg<BuilderImpl>, outline: &Outline, offset: ZenoPoint) { 26 + let mut adapter = ZenoToLyon::with_offset(builder, offset); 27 + outline.path().copy_to(&mut adapter); 28 + } 29 + 30 + #[must_use] 31 + pub fn outline_to_path(outline: &Outline) -> LyonPath { 32 + let mut builder = LyonPath::svg_builder(); 33 + append_outline(&mut builder, outline, ZenoPoint::new(0.0, 0.0)); 34 + builder.build() 35 + } 36 + 37 + pub fn tessellate_path( 38 + path: &LyonPath, 39 + fill: &mut FillTessellator, 40 + ) -> Result<TessellatedOutline, TessellationError> { 41 + let mut buffers: VertexBuffers<[f32; 2], u32> = VertexBuffers::new(); 42 + fill.tessellate_path( 43 + path, 44 + &FillOptions::default().with_tolerance(FILL_TOLERANCE_PX), 45 + &mut BuffersBuilder::new(&mut buffers, |v: FillVertex| { 46 + [v.position().x, v.position().y] 47 + }), 48 + )?; 49 + Ok(TessellatedOutline { 50 + vertices_px: buffers.vertices, 51 + indices: buffers.indices, 52 + }) 53 + } 54 + 55 + struct ZenoToLyon<'a> { 56 + builder: &'a mut WithSvg<BuilderImpl>, 57 + offset: ZenoPoint, 58 + current: ZenoPoint, 59 + open: bool, 60 + } 61 + 62 + impl<'a> ZenoToLyon<'a> { 63 + fn with_offset(builder: &'a mut WithSvg<BuilderImpl>, offset: ZenoPoint) -> Self { 64 + Self { 65 + builder, 66 + offset, 67 + current: ZenoPoint::new(0.0, 0.0), 68 + open: false, 69 + } 70 + } 71 + 72 + fn map(&self, p: ZenoPoint) -> LyonPoint { 73 + LyonPoint::new(p.x + self.offset.x, p.y + self.offset.y) 74 + } 75 + } 76 + 77 + impl PathBuilder for ZenoToLyon<'_> { 78 + fn current_point(&self) -> ZenoPoint { 79 + self.current 80 + } 81 + 82 + fn move_to(&mut self, to: impl Into<ZenoPoint>) -> &mut Self { 83 + let p = to.into(); 84 + self.current = p; 85 + self.builder.move_to(self.map(p)); 86 + self.open = true; 87 + self 88 + } 89 + 90 + fn line_to(&mut self, to: impl Into<ZenoPoint>) -> &mut Self { 91 + let p = to.into(); 92 + self.current = p; 93 + self.builder.line_to(self.map(p)); 94 + self 95 + } 96 + 97 + fn quad_to(&mut self, control: impl Into<ZenoPoint>, to: impl Into<ZenoPoint>) -> &mut Self { 98 + let c = control.into(); 99 + let p = to.into(); 100 + self.current = p; 101 + self.builder.quadratic_bezier_to(self.map(c), self.map(p)); 102 + self 103 + } 104 + 105 + fn curve_to( 106 + &mut self, 107 + control1: impl Into<ZenoPoint>, 108 + control2: impl Into<ZenoPoint>, 109 + to: impl Into<ZenoPoint>, 110 + ) -> &mut Self { 111 + let c1 = control1.into(); 112 + let c2 = control2.into(); 113 + let p = to.into(); 114 + self.current = p; 115 + self.builder 116 + .cubic_bezier_to(self.map(c1), self.map(c2), self.map(p)); 117 + self 118 + } 119 + 120 + fn close(&mut self) -> &mut Self { 121 + if self.open { 122 + self.builder.close(); 123 + self.open = false; 124 + } 125 + self 126 + } 127 + } 128 + 129 + #[cfg(test)] 130 + mod tests { 131 + use super::{ 132 + FILL_TOLERANCE_PX, TessellatedOutline, ZenoToLyon, append_outline, outline_to_path, 133 + tessellate_path, 134 + }; 135 + use lyon_tessellation::{ 136 + FillTessellator, 137 + path::{Event, Path as LyonPath, math::Point as LyonPoint}, 138 + }; 139 + use swash::zeno::{PathBuilder, Point as ZenoPoint}; 140 + 141 + fn zero() -> ZenoPoint { 142 + ZenoPoint::new(0.0, 0.0) 143 + } 144 + 145 + #[test] 146 + fn forwards_zero_offset_path_unchanged() { 147 + let mut builder = LyonPath::svg_builder(); 148 + { 149 + let mut adapter = ZenoToLyon::with_offset(&mut builder, zero()); 150 + adapter 151 + .move_to(ZenoPoint::new(0.0, 0.0)) 152 + .line_to(ZenoPoint::new(2.0, 0.0)) 153 + .line_to(ZenoPoint::new(2.0, 1.0)) 154 + .close(); 155 + } 156 + let path = builder.build(); 157 + assert!(path.iter().count() >= 4); 158 + } 159 + 160 + #[test] 161 + fn applies_offset_to_every_emitted_point() { 162 + let mut shifted = LyonPath::svg_builder(); 163 + { 164 + let mut adapter = ZenoToLyon::with_offset(&mut shifted, ZenoPoint::new(10.0, -5.0)); 165 + adapter 166 + .move_to(ZenoPoint::new(0.0, 0.0)) 167 + .line_to(ZenoPoint::new(1.0, 1.0)) 168 + .close(); 169 + } 170 + let path = shifted.build(); 171 + let xs_within_offset = path.iter().all(|event| { 172 + let bbox = bounding_box(event); 173 + bbox.iter().all(|(x, y)| *x >= 10.0 && *y >= -5.0) 174 + }); 175 + assert!( 176 + xs_within_offset, 177 + "every emitted point must respect the offset" 178 + ); 179 + } 180 + 181 + fn bounding_box(event: Event<LyonPoint, LyonPoint>) -> Vec<(f32, f32)> { 182 + match event { 183 + Event::Begin { at } | Event::End { last: at, .. } => vec![(at.x, at.y)], 184 + Event::Line { from, to } => vec![(from.x, from.y), (to.x, to.y)], 185 + Event::Quadratic { from, ctrl, to } => { 186 + vec![(from.x, from.y), (ctrl.x, ctrl.y), (to.x, to.y)] 187 + } 188 + Event::Cubic { 189 + from, 190 + ctrl1, 191 + ctrl2, 192 + to, 193 + } => vec![ 194 + (from.x, from.y), 195 + (ctrl1.x, ctrl1.y), 196 + (ctrl2.x, ctrl2.y), 197 + (to.x, to.y), 198 + ], 199 + } 200 + } 201 + 202 + #[test] 203 + fn current_point_tracks_last_emitted_point() { 204 + let mut builder = LyonPath::svg_builder(); 205 + let mut adapter = ZenoToLyon::with_offset(&mut builder, zero()); 206 + adapter.move_to(ZenoPoint::new(3.0, 4.0)); 207 + let cp = adapter.current_point(); 208 + assert!((cp.x - 3.0).abs() < f32::EPSILON); 209 + assert!((cp.y - 4.0).abs() < f32::EPSILON); 210 + adapter.line_to(ZenoPoint::new(7.0, 8.0)); 211 + let cp = adapter.current_point(); 212 + assert!((cp.x - 7.0).abs() < f32::EPSILON); 213 + assert!((cp.y - 8.0).abs() < f32::EPSILON); 214 + } 215 + 216 + #[test] 217 + fn close_without_open_subpath_is_noop() { 218 + let mut builder = LyonPath::svg_builder(); 219 + let mut adapter = ZenoToLyon::with_offset(&mut builder, zero()); 220 + adapter.close(); 221 + let _ = builder.build(); 222 + } 223 + 224 + #[test] 225 + fn fill_tolerance_is_subpixel_default() { 226 + const _: () = assert!(FILL_TOLERANCE_PX > 0.0); 227 + const _: () = assert!(FILL_TOLERANCE_PX < 1.0); 228 + } 229 + 230 + #[test] 231 + fn tessellate_path_emits_triangles_for_filled_quad() { 232 + let mut builder = LyonPath::svg_builder(); 233 + { 234 + let mut adapter = ZenoToLyon::with_offset(&mut builder, zero()); 235 + adapter 236 + .move_to(ZenoPoint::new(0.0, 0.0)) 237 + .line_to(ZenoPoint::new(1.0, 0.0)) 238 + .line_to(ZenoPoint::new(1.0, 1.0)) 239 + .line_to(ZenoPoint::new(0.0, 1.0)) 240 + .close(); 241 + } 242 + let path = builder.build(); 243 + let mut fill = FillTessellator::new(); 244 + let Ok(result) = tessellate_path(&path, &mut fill) else { 245 + panic!("tessellation must succeed for a filled quad"); 246 + }; 247 + assert!(!result.is_empty()); 248 + assert!(result.indices.len().is_multiple_of(3)); 249 + assert!( 250 + result 251 + .vertices_px 252 + .iter() 253 + .all(|[x, y]| { (0.0..=1.0).contains(x) && (0.0..=1.0).contains(y) }) 254 + ); 255 + } 256 + 257 + #[test] 258 + fn tessellate_empty_path_returns_empty_result() { 259 + let path = LyonPath::svg_builder().build(); 260 + let mut fill = FillTessellator::new(); 261 + let Ok(result) = tessellate_path(&path, &mut fill) else { 262 + panic!("empty path tessellation must succeed"); 263 + }; 264 + assert!(result.is_empty()); 265 + assert!(result.vertices_px.is_empty()); 266 + } 267 + 268 + #[test] 269 + fn tessellated_outline_default_is_empty() { 270 + let t = TessellatedOutline::default(); 271 + assert!(t.is_empty()); 272 + assert!(t.vertices_px.is_empty()); 273 + assert!(t.indices.is_empty()); 274 + } 275 + 276 + #[test] 277 + fn append_outline_into_lyon_uses_offset() { 278 + use swash::scale::outline::Outline; 279 + let outline = Outline::new(); 280 + let mut builder = LyonPath::svg_builder(); 281 + append_outline(&mut builder, &outline, ZenoPoint::new(5.0, 6.0)); 282 + let path = builder.build(); 283 + assert_eq!(path.iter().count(), 0, "empty outline emits no events"); 284 + } 285 + 286 + #[test] 287 + fn outline_to_path_handles_empty_outline() { 288 + use swash::scale::outline::Outline; 289 + let outline = Outline::new(); 290 + let path = outline_to_path(&outline); 291 + assert_eq!(path.iter().count(), 0); 292 + } 293 + }