From c9dcad1f6e21412b36ead0997b913afc9bf9efd5 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 1 Oct 2026 09:36:32 -0400 Subject: [PATCH] continued work --- Cargo.lock | 1051 +++++++++++++++++++++ Cargo.toml | 4 +- assets/fonts/SourceSerif4-Bold.ttf | Bin 0 -> 271568 bytes assets/fonts/SourceSerif4-BoldIt.ttf | Bin 0 -> 191832 bytes assets/fonts/SourceSerif4-It.ttf | Bin 0 -> 187808 bytes assets/fonts/SourceSerif4-Semibold.ttf | Bin 0 -> 272088 bytes crates/compose/Cargo.toml | 19 + crates/compose/src/breaker.rs | 390 ++++++++ crates/compose/src/cache.rs | 93 ++ crates/compose/src/hyphen.rs | 120 +++ crates/compose/src/lib.rs | 913 ++++++++++++++++++ crates/compose/src/shape.rs | 334 +++++++ crates/compose/src/tests.rs | 172 ++++ crates/doc/proptest-regressions/story.txt | 7 + crates/doc/src/build.rs | 498 ++++++++++ crates/doc/src/edit.rs | 371 ++++++++ crates/doc/src/item.rs | 599 ++++++++++++ crates/doc/src/lib.rs | 387 ++++++++ crates/doc/src/page.rs | 262 +++++ crates/doc/src/selection.rs | 65 ++ crates/doc/src/story.rs | 3 +- crates/doc/src/tests.rs | 85 ++ crates/fonts/Cargo.toml | 15 + crates/fonts/src/fontdb.rs | 558 +++++++++++ crates/fonts/src/lib.rs | 139 +++ crates/render/Cargo.toml | 23 + crates/render/src/lib.rs | 674 +++++++++++++ crates/tools/Cargo.toml | 17 + crates/tools/src/catalog.rs | 71 ++ crates/tools/src/layout.rs | 101 ++ crates/tools/src/lib.rs | 249 +++++ 31 files changed, 7217 insertions(+), 3 deletions(-) create mode 100644 Cargo.lock create mode 100644 assets/fonts/SourceSerif4-Bold.ttf create mode 100644 assets/fonts/SourceSerif4-BoldIt.ttf create mode 100644 assets/fonts/SourceSerif4-It.ttf create mode 100644 assets/fonts/SourceSerif4-Semibold.ttf create mode 100644 crates/compose/Cargo.toml create mode 100644 crates/compose/src/breaker.rs create mode 100644 crates/compose/src/cache.rs create mode 100644 crates/compose/src/hyphen.rs create mode 100644 crates/compose/src/lib.rs create mode 100644 crates/compose/src/shape.rs create mode 100644 crates/compose/src/tests.rs create mode 100644 crates/doc/proptest-regressions/story.txt create mode 100644 crates/doc/src/build.rs create mode 100644 crates/doc/src/edit.rs create mode 100644 crates/doc/src/item.rs create mode 100644 crates/doc/src/lib.rs create mode 100644 crates/doc/src/page.rs create mode 100644 crates/doc/src/selection.rs create mode 100644 crates/doc/src/tests.rs create mode 100644 crates/fonts/Cargo.toml create mode 100644 crates/fonts/src/fontdb.rs create mode 100644 crates/fonts/src/lib.rs create mode 100644 crates/render/Cargo.toml create mode 100644 crates/render/src/lib.rs create mode 100644 crates/tools/Cargo.toml create mode 100644 crates/tools/src/catalog.rs create mode 100644 crates/tools/src/layout.rs create mode 100644 crates/tools/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..6c42baa6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1051 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "color" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec7c5eb7a16992b1904d76c517d170ab353b0e0b3d5a0c81a8a0cd1037893cf" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "designcraft-color" +version = "0.1.0" +dependencies = [ + "kurbo", + "moxcms", + "proptest", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "designcraft-compose" +version = "0.1.0" +dependencies = [ + "designcraft-color", + "designcraft-doc", + "designcraft-fonts", + "designcraft-geom", + "log", + "proptest", +] + +[[package]] +name = "designcraft-doc" +version = "0.1.0" +dependencies = [ + "designcraft-color", + "designcraft-geom", + "proptest", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "designcraft-fonts" +version = "0.1.0" +dependencies = [ + "harfrust", + "kurbo", + "log", + "skrifa 0.47.0", +] + +[[package]] +name = "designcraft-geom" +version = "0.1.0" +dependencies = [ + "kurbo", + "proptest", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "designcraft-render" +version = "0.1.0" +dependencies = [ + "designcraft-color", + "designcraft-compose", + "designcraft-doc", + "designcraft-fonts", + "designcraft-geom", + "image", + "log", + "vello_common", + "vello_cpu", +] + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fearless_simd" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97b65636e5b9ef369943878ac74335ba1c55c1cb6adbf1e2c293c624248d693" + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide 0.9.1", + "zlib-rs", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "font-types" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8eb065f3251655b3c90e22e5e363f310fc5332fb3402e37bbc94752283248f6" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "glifo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a26c1e23de04bdab3e34a21b6f877a479b96737792516b9b8b8f69b6661be" +dependencies = [ + "bytemuck", + "foldhash", + "hashbrown", + "log", + "peniko", + "png", + "skrifa 0.44.0", + "smallvec", + "vello_common", +] + +[[package]] +name = "guillotiere" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b17e70c989c36bad147b27a58d148c0741c51448aa5653436547323e524d0ab" +dependencies = [ + "euclid", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "harfrust" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "948d0741125ba89cd3e1c23e5642415b6ade7e1d29d67ba25fb925b533e989d6" +dependencies = [ + "bitflags", + "bytemuck", + "once_cell", + "read-fonts 0.43.3", + "smallvec", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error 2.0.1", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "kurbo" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2" +dependencies = [ + "arrayvec", + "euclid", + "polycool", + "serde", + "smallvec", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "ordered-channel" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95be4d57809897b5a7539fc15a7dfe0e84141bc3dfaa2e9b1b27caa90acf61ab" +dependencies = [ + "crossbeam-channel", +] + +[[package]] +name = "peniko" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "839c8299360d2e998bdb106dc0a6cd71dcc5f4df51df1b620361bf50e283cca6" +dependencies = [ + "bytemuck", + "color", + "kurbo", + "linebender_resource_handle", + "smallvec", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "polycool" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "read-fonts" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709" +dependencies = [ + "bytemuck", + "font-types", + "once_cell", +] + +[[package]] +name = "read-fonts" +version = "0.43.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005c8acf251756c478b0bf402885bfd88a1476020c4c7e6060edc1aa68da38ea" +dependencies = [ + "bytemuck", + "font-types", + "once_cell", +] + +[[package]] +name = "read-fonts" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a0cf4bb6cbce4c29756270d189a5e400ac05e91192161d83a0bcb6e68492e8" +dependencies = [ + "bytemuck", + "font-types", + "once_cell", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustix" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "skrifa" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819ab7d62b1d3e72d9d9dea5650bac30424f9111364bb94928dbf5ecad1baa68" +dependencies = [ + "bytemuck", + "read-fonts 0.41.0", +] + +[[package]] +name = "skrifa" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "526e654b303ff4ad73a5a40b25de2b3ce3d039c5e3b6da5f89ae6e57004cb40f" +dependencies = [ + "bytemuck", + "read-fonts 0.44.0", +] + +[[package]] +name = "smallvec" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" +dependencies = [ + "serde", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error 2.0.1", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "vello_common" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb2141a2bca6e6d598e471fd4d1d7eed8e020aad6a28187edda07f091a325dd" +dependencies = [ + "bytemuck", + "fearless_simd", + "guillotiere", + "log", + "peniko", + "png", + "smallvec", + "thiserror", +] + +[[package]] +name = "vello_cpu" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace506ca414548966fcf3c283be94eb1cad8254de488791ee698bf438b0890a9" +dependencies = [ + "bytemuck", + "crossbeam-channel", + "glifo", + "hashbrown", + "ordered-channel", + "png", + "rayon", + "thread_local", + "vello_common", +] + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "serde_json", +] + +[[package]] +name = "zerocopy" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zune-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index cd893757..b3a041bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "3" -members = ["crates/*", "apps/*", "xtask"] -default-members = ["crates/*", "apps/designcraft", "apps/designcraft-cli", "xtask"] +members = ["crates/*", "xtask"] +default-members = ["crates/*", "xtask"] [workspace.package] version = "0.1.0" diff --git a/assets/fonts/SourceSerif4-Bold.ttf b/assets/fonts/SourceSerif4-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c4159ff2a409d9224dfa97af4e5167817e91e833 GIT binary patch literal 271568 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

K5o$9TYBLRLGZ|{r2(_6EwP}Rf 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

S8pQe`G{B^~LQ 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 GSN{clp+vX< literal 0 HcmV?d00001 diff --git a/assets/fonts/SourceSerif4-It.ttf b/assets/fonts/SourceSerif4-It.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e818087d0c75997a38189f6cf578c468df175062 GIT binary patch literal 187808 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 literal 0 HcmV?d00001 diff --git a/assets/fonts/SourceSerif4-Semibold.ttf b/assets/fonts/SourceSerif4-Semibold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..151e9a9d5c08dfd4751650ab4bff92771a132888 GIT binary patch literal 272088 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
    HeQ2P4Kf|)7O+~{H=QGX+4Gp};lOa?H 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 literal 0 HcmV?d00001 diff --git a/crates/compose/Cargo.toml b/crates/compose/Cargo.toml new file mode 100644 index 00000000..e507559a --- /dev/null +++ b/crates/compose/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "designcraft-compose" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "DesignCraft text composition: paragraph composer (Knuth–Plass), hyphenation, justification, columns, threading, wrap" + +[lints] +workspace = true + +[dependencies] +designcraft-geom = { workspace = true } +designcraft-color = { workspace = true } +designcraft-doc = { workspace = true } +designcraft-fonts = { workspace = true } +log = { workspace = true } + +[dev-dependencies] +proptest = { workspace = true } diff --git a/crates/compose/src/breaker.rs b/crates/compose/src/breaker.rs new file mode 100644 index 00000000..87074862 --- /dev/null +++ b/crates/compose/src/breaker.rs @@ -0,0 +1,390 @@ +//! Line breaking: the paragraph composer (Knuth–Plass total fit) and the single-line composer +//! (greedy first fit). Both work on a paragraph's glyphs and a per-line measure function. + +use crate::shape::{Glyph, SOFT_HYPHEN}; + +/// One line chosen by a breaker: glyphs `start..end` are visible; `next` is where the next line starts. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Break { + pub start: usize, + pub end: usize, + pub next: usize, + /// Broken at a hyphenation point (a hyphen glyph must be added). + pub hyphen: bool, + /// Ended by a forced break (paragraph end, forced line break, column/frame/page break). + pub forced: bool, +} + +/// Spacing parameters (from the paragraph's Justification settings), as fractions. +#[derive(Clone, Copy, Debug)] +pub struct Spacing { + pub justify: bool, + pub word_min: f64, + pub word_desired: f64, + pub word_max: f64, + /// Penalty for a hyphenated break (0 = free, larger = fewer hyphens). + pub hyphen_penalty: f64, + /// Maximum consecutive hyphenated lines (0 = unlimited). + pub hyphen_limit: u32, + /// Ragged-right stretchability (points) for unjustified paragraphs. + pub ragged_stretch: f64, +} + +#[derive(Clone, Copy, Debug)] +enum Item { + /// Unbreakable width (a glyph). + Box { w: f64 }, + /// Space glyph `g`. + Glue { w: f64, st: f64, sh: f64 }, + Penalty { w: f64, p: f64, flagged: bool }, +} + +const INF: f64 = 10000.0; + +/// Does the glyph force a line end after it? +pub fn is_forced(c: char) -> bool { + use designcraft_doc::story::*; + matches!(c, FORCED_LINE_BREAK | COLUMN_BREAK | FRAME_BREAK | PAGE_BREAK) +} + +/// Build Knuth items. `item_glyph[k]` = glyph index of item k (penalties: the glyph *before* which the break happens). +fn items(glyphs: &[Glyph], hyph_after: &[bool], sp: &Spacing) -> (Vec, Vec) { + let mut it = Vec::with_capacity(glyphs.len() * 2 + 2); + let mut ig = Vec::with_capacity(glyphs.len() * 2 + 2); + let n = glyphs.len(); + for (i, g) in glyphs.iter().enumerate() { + if is_forced(g.ch) { + if !sp.justify || true { + it.push(Item::Glue { w: 0.0, st: INF, sh: 0.0 }); + ig.push(i); + } + it.push(Item::Penalty { w: 0.0, p: -INF, flagged: false }); + ig.push(i + 1); + continue; + } + if g.is_space() && !g.no_break { + let w = g.adv; + if sp.justify { + let base = w / sp.word_desired.max(1e-6); + it.push(Item::Glue { w, st: base * (sp.word_max - sp.word_desired).max(0.0), sh: base * (sp.word_desired - sp.word_min).max(0.0) }); + ig.push(i); + } else { + // Ragged right (Knuth): glue(0, s, 0) penalty(0) glue(w, -s, 0). + it.push(Item::Glue { w: 0.0, st: sp.ragged_stretch, sh: 0.0 }); + ig.push(i); + it.push(Item::Penalty { w: 0.0, p: 0.0, flagged: false }); + ig.push(i); + it.push(Item::Glue { w, st: -sp.ragged_stretch, sh: 0.0 }); + ig.push(i); + } + continue; + } + if g.ch == SOFT_HYPHEN { + let hw = g.size * 0.33; + it.push(Item::Penalty { w: hw, p: sp.hyphen_penalty, flagged: true }); + ig.push(i + 1); + continue; + } + it.push(Item::Box { w: g.adv }); + ig.push(i); + let next_is_space = glyphs.get(i + 1).is_none_or(|n| n.is_space()); + if i + 1 < n && !next_is_space && !g.no_break { + if matches!(g.ch, '-' | '\u{2010}') { + it.push(Item::Penalty { w: 0.0, p: 50.0, flagged: true }); + ig.push(i + 1); + } else if matches!(g.ch, '\u{2013}' | '\u{2014}' | '/') { + it.push(Item::Penalty { w: 0.0, p: 0.0, flagged: false }); + ig.push(i + 1); + } else if hyph_after[i] { + let hw = g.size * 0.33; + it.push(Item::Penalty { w: hw, p: sp.hyphen_penalty, flagged: true }); + ig.push(i + 1); + } + } + } + // Paragraph end: fill glue + forced break. + it.push(Item::Glue { w: 0.0, st: INF, sh: 0.0 }); + ig.push(n); + it.push(Item::Penalty { w: 0.0, p: -INF, flagged: false }); + ig.push(n); + (it, ig) +} + +#[derive(Clone, Copy, Debug)] +struct Node { + pos: usize, + line: usize, + fitness: u8, + tw: f64, + ty: f64, + tz: f64, + demerits: f64, + prev: Option, + hyphens: u32, + flagged: bool, +} + +/// Knuth–Plass total-fit line breaking. `width(line)` gives each line's measure. +pub fn knuth_plass(glyphs: &[Glyph], hyph_after: &[bool], sp: &Spacing, width: &dyn Fn(usize) -> f64) -> Vec { + if glyphs.is_empty() { + return vec![Break { start: 0, end: 0, next: 0, hyphen: false, forced: true }]; + } + let (items, ig) = items(glyphs, hyph_after, sp); + for tolerance in [3.0, 30.0, f64::INFINITY] { + if let Some(b) = kp_pass(&items, &ig, glyphs, sp, width, tolerance, tolerance.is_infinite()) { + return b; + } + } + greedy(glyphs, hyph_after, sp, width) +} + +#[allow(clippy::too_many_arguments)] +fn kp_pass(items: &[Item], ig: &[usize], glyphs: &[Glyph], sp: &Spacing, width: &dyn Fn(usize) -> f64, tol: f64, emergency: bool) -> Option> { + let m = items.len(); + // Prefix sums (before item i). + let mut sw = vec![0.0; m + 1]; + let mut sy = vec![0.0; m + 1]; + let mut sz = vec![0.0; m + 1]; + for (i, it) in items.iter().enumerate() { + let (w, y, z) = match *it { + Item::Box { w } => (w, 0.0, 0.0), + Item::Glue { w, st, sh } => (w, st, sh), + Item::Penalty { .. } => (0.0, 0.0, 0.0), + }; + sw[i + 1] = sw[i] + w; + sy[i + 1] = sy[i] + y; + sz[i + 1] = sz[i] + z; + } + let mut arena: Vec = vec![Node { pos: 0, line: 0, fitness: 1, tw: 0.0, ty: 0.0, tz: 0.0, demerits: 0.0, prev: None, hyphens: 0, flagged: false }]; + let mut active: Vec = vec![0]; + for b in 0..m { + let (is_break, pw, pp, flagged) = match items[b] { + Item::Penalty { w, p, flagged } if p < INF => (true, w, p, flagged), + Item::Glue { .. } if b > 0 && matches!(items[b - 1], Item::Box { .. }) => (true, 0.0, 0.0, false), + _ => (false, 0.0, 0.0, false), + }; + if !is_break { + continue; + } + let forced = pp <= -INF; + let mut best: [Option<(f64, usize, f64)>; 4] = [None; 4]; // (demerits, active node, ratio) + let mut keep = Vec::with_capacity(active.len()); + let mut last_removed: Option<(usize, f64)> = None; + for &a in &active { + let n = arena[a]; + let l = sw[b] - n.tw + pw; + let target = width(n.line).max(1.0); + let (y, z) = (sy[b] - n.ty, sz[b] - n.tz); + let r = if l < target { + if y > 1e-9 { (target - l) / y } else { INF } + } else if l > target { + if z > 1e-9 { (target - l) / z } else { -INF } + } else { + 0.0 + }; + let deactivate = r < -1.0 || forced; + if !deactivate { + keep.push(a); + } else { + last_removed = Some((a, r)); + } + if r >= -1.0 && r <= tol || (forced && r >= -1.0) { + let bad = (100.0 * r.abs().powi(3)).min(INF); + let lp = 10.0 + bad; + let mut d = if pp >= 0.0 { lp * lp + pp * pp } else if pp > -INF { lp * lp - pp * pp } else { lp * lp }; + if flagged && n.flagged { + d += 3000.0; + } + if flagged && sp.hyphen_limit > 0 && n.hyphens >= sp.hyphen_limit { + d += 1e7; + } + let fit = if r < -0.5 { + 0 + } else if r <= 0.5 { + 1 + } else if r <= 1.0 { + 2 + } else { + 3 + }; + if (fit as i32 - n.fitness as i32).abs() > 1 { + d += 3000.0; + } + let total = n.demerits + d; + if best[fit as usize].is_none_or(|(bd, _, _)| total < bd) { + best[fit as usize] = Some((total, a, r)); + } + } + } + // Emergency: nothing can reach this break and nothing remains active → accept an overfull line. + if emergency + && keep.is_empty() + && best.iter().all(Option::is_none) + && let Some((a, _)) = last_removed + { + best[0] = Some((arena[a].demerits + 1e8, a, -1.0)); + } + active = keep; + // Totals after the break: skip glue and penalties up to the next box. + let (mut tw, mut ty, mut tz) = (sw[b], sy[b], sz[b]); + let mut i = b; + while i < m { + match items[i] { + Item::Box { .. } => break, + Item::Glue { w, st, sh } => { + tw += w; + ty += st; + tz += sh; + } + Item::Penalty { p, .. } if p <= -INF && i > b => break, + Item::Penalty { .. } => {} + } + i += 1; + } + for (fit, c) in best.iter().enumerate() { + if let Some((d, a, _)) = *c { + let prev = arena[a]; + arena.push(Node { + pos: b, + line: prev.line + 1, + fitness: fit as u8, + tw, + ty, + tz, + demerits: d, + prev: Some(a), + hyphens: if flagged { prev.hyphens + 1 } else { 0 }, + flagged, + }); + active.push(arena.len() - 1); + } + } + if active.is_empty() { + return None; + } + } + // The final forced break: best node at position m-1. + let end = active.iter().copied().filter(|&a| arena[a].pos == m - 1).min_by(|&a, &b| arena[a].demerits.total_cmp(&arena[b].demerits))?; + let mut chain = Vec::new(); + let mut cur = Some(end); + while let Some(c) = cur { + if arena[c].prev.is_some() { + chain.push(arena[c].pos); + } + cur = arena[c].prev; + } + chain.reverse(); + Some(breaks_from_positions(items, ig, glyphs, &chain)) +} + +fn breaks_from_positions(items: &[Item], ig: &[usize], glyphs: &[Glyph], chain: &[usize]) -> Vec { + let n = glyphs.len(); + let mut out = Vec::with_capacity(chain.len()); + let mut start = 0; + for &b in chain { + let (end, hyphen, forced) = match items[b] { + Item::Penalty { p, flagged, w } => { + let e = ig[b].min(n); + // A flagged penalty with width = an inserted hyphen (not an explicit '-'). + let explicit = e > 0 && matches!(glyphs[e - 1].ch, '-' | '\u{2010}'); + (e, flagged && w > 0.0 && !explicit || (flagged && e > 0 && glyphs[e - 1].ch == SOFT_HYPHEN), p <= -INF) + } + Item::Glue { .. } => (ig[b], false, false), + Item::Box { .. } => (ig[b], false, false), + }; + // Trim trailing spaces from the visible range; skip leading spaces of the next line. + let mut vis_end = end; + while vis_end > start && glyphs[vis_end - 1].is_space() { + vis_end -= 1; + } + let mut next = end; + while next < n && glyphs[next].is_space() { + next += 1; + } + let forced_glyph = end > 0 && end <= n && is_forced(glyphs[end - 1].ch); + out.push(Break { start, end: vis_end, next, hyphen, forced: forced || forced_glyph }); + start = next; + } + if out.is_empty() { + out.push(Break { start: 0, end: n, next: n, hyphen: false, forced: true }); + } + // Lines produced past the paragraph end (e.g. a trailing forced break) are dropped. + out.retain(|b| b.start <= n); + out +} + +/// Greedy first-fit breaking (single-line composer; also used for paragraphs with tabs). +pub fn greedy(glyphs: &[Glyph], hyph_after: &[bool], sp: &Spacing, width: &dyn Fn(usize) -> f64) -> Vec { + let n = glyphs.len(); + let mut out = Vec::new(); + let mut start = 0; + let mut line = 0; + if n == 0 { + return vec![Break { start: 0, end: 0, next: 0, hyphen: false, forced: true }]; + } + while start < n { + let w = width(line).max(1.0); + let mut x = 0.0; + let mut spaces_shrink = 0.0; + let mut last_ok: Option<(usize, bool)> = None; // (break position = end glyph, hyphen) + let mut i = start; + let mut brk: Option<(usize, bool, bool)> = None; + while i < n { + let g = &glyphs[i]; + if is_forced(g.ch) { + brk = Some((i + 1, false, true)); + break; + } + if g.is_space() && !g.no_break { + if sp.justify { + spaces_shrink += g.adv * (sp.word_desired - sp.word_min).max(0.0) / sp.word_desired.max(1e-6); + } + last_ok = Some((i, false)); + x += g.adv; + i += 1; + continue; + } + let hy = if hyph_after[i] { g.size * 0.33 } else { 0.0 }; + if x + g.adv > w + spaces_shrink && i > start { + // Overflow: break at the last opportunity, else before this glyph. + brk = Some(match last_ok { + Some((p, h)) => (p, h, false), + None => (i, false, false), + }); + break; + } + x += g.adv; + if i + 1 < n && !glyphs[i + 1].is_space() && !g.no_break { + if matches!(g.ch, '-' | '\u{2010}' | '\u{2013}' | '\u{2014}' | '/') { + last_ok = Some((i + 1, false)); + } else if hyph_after[i] && x + hy <= w + spaces_shrink { + last_ok = Some((i + 1, true)); + } + } + i += 1; + } + let (end, hyphen, forced) = brk.unwrap_or((n, false, true)); + let mut vis_end = end; + while vis_end > start && glyphs[vis_end - 1].is_space() { + vis_end -= 1; + } + let mut next = end; + while next < n && glyphs[next].is_space() { + next += 1; + } + let next = next.max(start + 1).min(n.max(start + 1)); + out.push(Break { start, end: vis_end, next: next.min(n), hyphen, forced: forced || end == n }); + if next >= n { + break; + } + start = next; + line += 1; + } + // A forced break as the very last glyph leaves an empty final line (InDesign shows it). + if let Some(last) = glyphs.last() + && is_forced(last.ch) + { + out.push(Break { start: n, end: n, next: n, hyphen: false, forced: true }); + } + out +} diff --git a/crates/compose/src/cache.rs b/crates/compose/src/cache.rs new file mode 100644 index 00000000..60629d5d --- /dev/null +++ b/crates/compose/src/cache.rs @@ -0,0 +1,93 @@ +//! Composition cache shared by the engine, the renderer and exporters. +//! +//! An entry is valid while the inputs it was composed from are the *same allocations*: the story +//! `Arc` (and its revision), the styles `Arc`, the frame items' `Arc`s and the `Arc`s of every +//! wrapping item on the frames' spreads. Entries hold clones of those `Arc`s, so the pointers can't +//! be reused by other allocations while the entry lives. + +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; + +use designcraft_doc::{Document, Item, Story, StoryId, Styles, WrapMode}; + +use crate::{ComposeOptions, ComposedStory}; + +type Key = (StoryId, Option); + +struct Entry { + sig: Vec, + _keep: (Arc, Arc, Vec>), + out: Arc, + stamp: u64, +} + +#[derive(Default)] +pub struct Cache { + map: Mutex<(HashMap, u64)>, +} + +impl Cache { + pub fn new() -> Self { + Self::default() + } + + /// The composed story, from cache or freshly composed. + pub fn get(&self, doc: &Document, sid: StoryId, page_name: Option<&str>) -> Arc { + let Some(story) = doc.stories.get(&sid) else { return Arc::new(ComposedStory { story: sid, ..Default::default() }) }; + let (sig, keep_items) = signature(doc, story); + let key = (sid, page_name.map(str::to_string)); + { + let mut g = self.map.lock().unwrap_or_else(|e| e.into_inner()); + g.1 += 1; + let stamp = g.1; + if let Some(e) = g.0.get_mut(&key) + && e.sig == sig + { + e.stamp = stamp; + return e.out.clone(); + } + } + let out = Arc::new(crate::compose_story(doc, sid, &ComposeOptions { page_name: page_name.map(str::to_string) })); + let mut g = self.map.lock().unwrap_or_else(|e| e.into_inner()); + let stamp = g.1; + if g.0.len() > 4096 { + g.0.retain(|_, e| stamp - e.stamp < 64); + } + g.0.insert(key, Entry { sig, _keep: (story.clone(), doc.styles.clone(), keep_items), out: out.clone(), stamp }); + out + } + + pub fn clear(&self) { + self.map.lock().unwrap_or_else(|e| e.into_inner()).0.clear(); + } +} + +fn signature(doc: &Document, story: &Arc) -> (Vec, Vec>) { + let mut sig = vec![Arc::as_ptr(story) as usize, story.rev as usize, Arc::as_ptr(&doc.styles) as usize, doc.sections.len()]; + let mut keep = Vec::new(); + let mut spreads = Vec::new(); + for f in &story.frames { + let Some(loc) = doc.find(*f) else { + sig.push(0); + continue; + }; + if let Some(sp) = doc.spread(loc.spread) { + let top = &sp.items[loc.top()]; + sig.push(Arc::as_ptr(top) as usize); + keep.push(top.clone()); + // Page position matters for page-number markers. + sig.push(loc.top()); + if !spreads.contains(&loc.spread) { + spreads.push(loc.spread); + for it in &sp.items { + if it.wrap.mode != WrapMode::None { + sig.push(Arc::as_ptr(it) as usize); + keep.push(it.clone()); + } + } + sig.push(usize::MAX); + } + } + } + (sig, keep) +} diff --git a/crates/compose/src/hyphen.rs b/crates/compose/src/hyphen.rs new file mode 100644 index 00000000..ddb6e0ca --- /dev/null +++ b/crates/compose/src/hyphen.rs @@ -0,0 +1,120 @@ +//! Dictionary-free English hyphenation (ours): breaks between syllables at vowel–consonant +//! boundaries (V-CV "ty-po", VC-CV "hap-pen"), respecting onset clusters ("gra-phy"). +//! +//! A Liang pattern engine with loadable pattern sets is planned (see plan/adr); patterns are only +//! bundled once their licence is confirmed to fit the asset policy. + +/// Hyphenation limits from the paragraph's Hyphenation settings. +#[derive(Clone, Copy, Debug)] +pub struct Limits { + pub min_word: usize, + pub after_first: usize, + pub before_last: usize, + pub capitalized: bool, +} + +impl Default for Limits { + fn default() -> Self { + Limits { min_word: 5, after_first: 2, before_last: 2, capitalized: true } + } +} + +fn is_vowel(c: char) -> bool { + matches!(c.to_ascii_lowercase(), 'a' | 'e' | 'i' | 'o' | 'u' | 'y') || (c.is_alphabetic() && !c.is_ascii()) +} + +fn onset_pair(a: char, b: char) -> bool { + let (a, b) = (a.to_ascii_lowercase(), b.to_ascii_lowercase()); + matches!( + (a, b), + ('c' | 's' | 't' | 'p' | 'w' | 'g', 'h') + | ('b' | 'c' | 'd' | 'f' | 'g' | 'k' | 'p' | 't', 'r') + | ('b' | 'c' | 'f' | 'g' | 'k' | 'p' | 's', 'l') + | ('q', 'u') + | ('s', 't' | 'p' | 'c' | 'k') + ) +} + +/// Common English suffixes that form their own syllable (break before them). +const SUFFIXES: &[&str] = &["tion", "sion", "ment", "ness", "less", "ful", "able", "ible", "ing", "ly"]; + +/// Allowed hyphenation points in `word` as char indices (a hyphen goes before that char). +pub fn hyphen_points(word: &str, lim: &Limits) -> Vec { + let c: Vec = word.chars().collect(); + let n = c.len(); + let min_before = lim.after_first.max(1); + let min_after = lim.before_last.max(1); + if n < lim.min_word.max(2) || n < min_before + min_after || !c.iter().all(|c| c.is_alphabetic() || matches!(c, '\'' | '’')) { + return vec![]; + } + if c.iter().all(|c| c.is_uppercase()) || (!lim.capitalized && c[0].is_uppercase()) { + return vec![]; + } + let v: Vec = c.iter().map(|&x| is_vowel(x)).collect(); + let lower: String = word.to_lowercase(); + let mut out = vec![]; + for i in min_before..=n - min_after { + if !c[i].is_alphabetic() || !c[i - 1].is_alphabetic() { + continue; + } + let suffix_at = SUFFIXES.iter().any(|s| { + let sl = s.chars().count(); + n - i == sl && lower.ends_with(s) && v[..i].iter().any(|x| *x) + }); + let ok = suffix_at + || if v[i - 1] && !v[i] { + (i + 1 < n && v[i + 1]) || (i + 2 < n && onset_pair(c[i], c[i + 1]) && v[i + 2]) + } else if !v[i - 1] && !v[i] { + i >= 2 && v[i - 2] && i + 1 < n && v[i + 1] && !onset_pair(c[i - 1], c[i]) && c[i - 1] != c[i] || (c[i - 1] == c[i] && i >= 2 && v[i - 2]) + } else { + false + }; + if ok && !out.contains(&i) { + out.push(i); + } + } + out.sort(); + out +} + +/// `word` with `-` at every hyphenation point (tests and diagnostics). +pub fn hyphenate_word(word: &str, lim: &Limits) -> String { + let pts = hyphen_points(word, lim); + let mut s = String::with_capacity(word.len() + pts.len()); + for (i, ch) in word.chars().enumerate() { + if pts.contains(&i) { + s.push('-'); + } + s.push(ch); + } + s +} + +#[cfg(test)] +mod tests { + use super::*; + + fn h(w: &str) -> String { + hyphenate_word(w, &Limits::default()) + } + + #[test] + fn common_words() { + assert_eq!(h("happen"), "hap-pen"); + assert_eq!(h("typography"), "ty-po-gra-phy"); + assert!(h("composition").contains("com-")); + assert_eq!(h("cat"), "cat"); + assert_eq!(h("NASA"), "NASA"); + } + + #[test] + fn limits_are_respected() { + let lim = Limits { min_word: 5, after_first: 3, before_last: 3, capitalized: false }; + for w in ["typography", "hyphenation", "justification", "Paragraph", "beautiful"] { + for p in hyphen_points(w, &lim) { + assert!(p >= 3 && p <= w.chars().count() - 3, "{w} {p}"); + } + } + assert!(hyphen_points("Paragraph", &lim).is_empty()); + } +} diff --git a/crates/compose/src/lib.rs b/crates/compose/src/lib.rs new file mode 100644 index 00000000..ac6224e8 --- /dev/null +++ b/crates/compose/src/lib.rs @@ -0,0 +1,913 @@ +//! DesignCraft text composition. +//! +//! [`compose_story`] lays a story out through its chain of threaded frames: +//! style resolution → shaping ([`shape`]) → line breaking ([`breaker`]: the paragraph composer is +//! Knuth–Plass total fit, the single-line composer is greedy) → placement in columns and frames +//! (first-baseline offset, leading, space before/after, baseline grid, text wrap, column/frame +//! breaks, vertical justification) → overset detection. +//! +//! Output coordinates are each frame's *inner* space (apply the frame item's `xf` for spread space). +#![forbid(unsafe_code)] + +pub mod breaker; +mod cache; +pub mod hyphen; +pub mod shape; + +use std::ops::Range; +use std::sync::Arc; + +use designcraft_doc::{ + Align, Composer, Document, FirstBaseline, GridAlign, ItemId, ParaProps, SpanColumns, StartParagraph, Story, StoryId, TabAlign, TextFrameOptions, + VerticalJustification, WrapMode, story, +}; +use designcraft_fonts::{FontDb, FontFace}; +use designcraft_geom::{Point, Rect}; + +use crate::breaker::{Break, Spacing}; +pub use crate::cache::Cache; +use crate::shape::{Glyph, StyleTable, SubstCtx}; + +/// Character appearance shared by many glyphs (indexed from [`PlacedGlyph::style`]). +#[derive(Clone, Debug, PartialEq)] +pub struct RunStyle { + pub fill: String, + pub fill_tint: f32, + pub stroke: String, + pub stroke_tint: f32, + pub stroke_weight: f64, + pub underline: bool, + pub strikethrough: bool, + pub skew: f64, + pub size: f64, +} + +/// A positioned glyph. `x` is absolute in frame inner space; `y` is relative to the line baseline. +#[derive(Clone, Debug)] +pub struct PlacedGlyph { + pub face: Arc, + pub gid: u32, + pub x: f64, + pub y: f64, + pub adv: f64, + pub sx: f64, + pub sy: f64, + pub style: u32, + pub byte: usize, + pub len: usize, + /// Control characters (tabs, breaks, markers' carriers) are not drawn. + pub visible: bool, +} + +#[derive(Clone, Debug)] +pub struct Line { + pub column: u32, + /// Baseline y in frame inner space. + pub baseline: f64, + /// Line slot (column minus wrap) horizontal extent. + pub x0: f64, + pub x1: f64, + pub ascent: f64, + pub descent: f64, + pub leading: f64, + /// Story byte range (excluding the paragraph separator). + pub range: Range, + pub para: usize, + pub glyphs: Vec, + pub hyphenated: bool, + pub first_in_para: bool, + pub last_in_para: bool, + /// x after the last glyph (caret at line end). + pub end_x: f64, + /// Word-space ratio actually used vs desired (H&J violation highlighting), 1.0 = desired. + pub spacing: f64, +} + +/// A paragraph rule or shading rectangle in frame inner space. +#[derive(Clone, Debug, PartialEq)] +pub struct Deco { + pub rect: Rect, + pub color: String, + pub tint: f32, +} + +#[derive(Clone, Debug, Default)] +pub struct FrameText { + pub frame: ItemId, + pub lines: Vec, + pub decos: Vec, + /// Byte range of the story shown in this frame. + pub range: Range, + /// Column rectangles (inner space) for drawing column guides / hit testing. + pub columns: Vec, + /// Height the text needs (for auto-sizing), from the text area top. + pub content_height: f64, +} + +#[derive(Clone, Debug, Default)] +pub struct ComposedStory { + pub story: StoryId, + pub rev: u64, + pub frames: Vec, + /// First byte that didn't fit (overset text), if any. + pub overset_at: Option, + pub styles: Vec, + pub text_len: usize, +} + +impl ComposedStory { + pub fn is_overset(&self) -> bool { + self.overset_at.is_some() + } + pub fn frame(&self, id: ItemId) -> Option<&FrameText> { + self.frames.iter().find(|f| f.frame == id) + } + /// Number of lines in all frames. + pub fn line_count(&self) -> usize { + self.frames.iter().map(|f| f.lines.len()).sum() + } +} + +/// A text-wrap exclusion in a frame's inner space. +#[derive(Clone, Debug, PartialEq)] +pub struct Exclusion { + pub rect: Rect, + pub mode: WrapMode, +} + +/// One frame of the thread, ready for composition. +#[derive(Clone, Debug)] +pub struct FrameSpec { + pub id: ItemId, + /// Text area (inner space, after inset). + pub area: Rect, + pub opts: TextFrameOptions, + pub exclusions: Vec, + pub page_name: Option, + /// Baseline grid in inner space: (first grid line y, increment). + pub grid: Option<(f64, f64)>, + /// The frame is on a left page (for towards/away-from-spine alignment). + pub left_page: bool, +} + +impl FrameSpec { + pub fn columns(&self) -> Vec { + let a = self.area; + let n = self.opts.columns.max(1); + match self.opts.columns_kind { + designcraft_doc::ColumnsKind::FixedWidth if self.opts.column_width > 0.0 => (0..n) + .map(|i| { + let x = a.x0 + i as f64 * (self.opts.column_width + self.opts.gutter); + Rect::new(x, a.y0, x + self.opts.column_width, a.y1) + }) + .collect(), + _ => designcraft_doc::page::column_rects(a, n, self.opts.gutter), + } + } +} + +/// Composition inputs that are not in the story itself. +#[derive(Clone, Debug, Default)] +pub struct ComposeOptions { + /// Page name for page-number markers when the story is composed for a specific page (parent items). + pub page_name: Option, +} + +/// Build the frame specs of a story from the document (geometry, wrap, page names, grid). +pub fn frame_specs(doc: &Document, sid: StoryId) -> Vec { + let Some(st) = doc.story(sid) else { return vec![] }; + let mut out = Vec::with_capacity(st.frames.len()); + for &fid in &st.frames { + let Some(loc) = doc.find(fid) else { continue }; + let Some(item) = doc.item_at(&loc) else { continue }; + let Some(tf) = item.text_frame() else { continue }; + let xf = doc.parent_xf(&loc) * item.xf; + let inv = xf.inverse(); + let mut exclusions = Vec::new(); + let spread = doc.spread(loc.spread); + if !tf.options.ignore_wrap + && let Some(sp) = spread + { + for other in &sp.items { + if other.id == item.id || other.wrap.mode == WrapMode::None || other.hidden { + continue; + } + if doc.layer(other.layer).is_some_and(|l| !l.visible) { + continue; + } + let o = other.wrap.offsets; + let b = other.bounds(); + let r = Rect::new(b.x0 - o[1], b.y0 - o[0], b.x1 + o[3], b.y1 + o[2]); + let inner = inv.transform_rect_bbox(r); + exclusions.push(Exclusion { rect: inner, mode: other.wrap.mode }); + } + } + let (page_name, left_page) = match (loc.spread, spread) { + (designcraft_doc::SpreadRef::Doc(si), Some(sp)) => { + let c = item.bounds().center(); + let pi = sp.page_at_x(c.x).unwrap_or(0); + let abs = doc.first_page_of_spread(si) + pi; + (Some(doc.page_name(abs)), sp.pages.get(pi).is_some_and(|p| p.side == designcraft_doc::PageSide::Left)) + } + (designcraft_doc::SpreadRef::Parent(pi), Some(sp)) => { + let prefix = sp.parent.as_ref().map(|p| p.prefix.clone()).unwrap_or_else(|| "A".into()); + let _ = pi; + (Some(prefix), false) + } + _ => (None, false), + }; + let g = &doc.settings.baseline_grid; + let (inc, start) = tf.options.baseline_grid.unwrap_or((g.increment, g.start)); + // Grid lines are at spread y = start + n·inc (page tops are y = 0); map into inner space (translation only). + let ty = xf.translation().y; + let grid = (inc > 0.0).then_some((start - ty, inc)); + out.push(FrameSpec { id: fid, area: item.text_area(), opts: tf.options.clone(), exclusions, page_name, grid, left_page }); + } + out +} + +/// Compose a story of `doc` through its frames. +pub fn compose_story(doc: &Document, sid: StoryId, opts: &ComposeOptions) -> ComposedStory { + let specs = frame_specs(doc, sid); + match doc.story(sid) { + Some(st) => compose(doc, st, &specs, opts), + None => ComposedStory { story: sid, ..Default::default() }, + } +} + +const DEFAULT_TAB: f64 = 36.0; + +/// Compose `story` into `frames`. +pub fn compose(doc: &Document, story: &Story, frames: &[FrameSpec], opts: &ComposeOptions) -> ComposedStory { + let db = FontDb::global(); + let mut out = ComposedStory { story: story.id, rev: story.rev, text_len: story.text.len(), ..Default::default() }; + let mut styles_tab: Vec = Vec::new(); + out.frames = frames.iter().map(|f| FrameText { frame: f.id, columns: f.columns(), ..Default::default() }).collect(); + let cols: Vec> = frames.iter().map(FrameSpec::columns).collect(); + let mut cur = Cursor { fi: 0, col: 0, last_baseline: None, last_descent: 0.0, pending: 0.0 }; + let para_ranges = story.para_ranges(); + let mut list_counter: u32 = 0; + 'paras: for (pi, prange) in para_ranges.iter().enumerate() { + let pf = &story.paras[pi]; + let (pp, base_chars) = doc.styles.resolve_para(pf); + // Bullets & numbering: generated prefix (shaped as its own glyphs, mapped to the paragraph start). + let sub = SubstCtx { + page_name: opts.page_name.clone().or_else(|| frames.get(cur.fi.min(frames.len().saturating_sub(1))).and_then(|f| f.page_name.clone())), + section_marker: None, + }; + let mut table = StyleTable { styles: &mut styles_tab }; + let mut sp = shape::shape_para(db, &doc.styles, story, pi, prange.clone(), &base_chars, pp.auto_leading, &sub, &mut table); + match pp.list_type { + designcraft_doc::ListType::Numbers => { + list_counter += 1; + let label = format!("{}.{}", pp.number_style.format(list_counter), pp.list_separator); + prepend_label(db, &mut sp.glyphs, &label, prange.start, &base_chars, &pp, &mut table); + } + designcraft_doc::ListType::Bullets => { + let label = format!("{}{}", pp.bullet_char, pp.list_separator); + prepend_label(db, &mut sp.glyphs, &label, prange.start, &base_chars, &pp, &mut table); + } + designcraft_doc::ListType::None => list_counter = 0, + } + let glyphs = sp.glyphs; + let hyph_after = hyphenation_points(&story.text, &glyphs, &pp); + let base_size = base_chars.size; + let base_leading = match base_chars.leading { + designcraft_doc::Leading::Auto => base_size * pp.auto_leading, + designcraft_doc::Leading::Points(v) => v, + }; + let spacing = Spacing { + justify: pp.align.is_justified(), + word_min: pp.word_space_min, + word_desired: pp.word_space_desired, + word_max: pp.word_space_max, + hyphen_penalty: 50.0 + 450.0 * pp.hyph_weight, + hyphen_limit: pp.hyph_limit, + ragged_stretch: base_size * 2.0, + }; + // Paragraph start options. + if cur.last_baseline.is_some() { + match pp.start_paragraph { + StartParagraph::NextColumn => cur.next_column(&cols), + StartParagraph::NextFrame | StartParagraph::NextPage | StartParagraph::NextOddPage | StartParagraph::NextEvenPage => cur.next_frame(), + StartParagraph::Anywhere => {} + } + } + if cur.last_baseline.is_some() { + cur.pending += pp.space_before; + } + // Rule above / shading track the paragraph's first line. + let mut g0 = 0usize; + let mut line_no = 0usize; + let has_tabs = glyphs.iter().any(|g| g.ch == '\t'); + let mut first_line_rect: Option<(usize, f64, f64, f64)> = None; // frame, baseline, ascent, x-span + loop { + if cur.fi >= frames.len() { + out.overset_at = Some(glyphs.get(g0).map(|g| g.byte).unwrap_or(prange.start)); + break 'paras; + } + let f = &frames[cur.fi]; + let col = cols[cur.fi][cur.col.min(cols[cur.fi].len() - 1)]; + let col = match pp.span_columns { + SpanColumns::Span(n) if cur.col == 0 => { + let n = if n == 0 { cols[cur.fi].len() } else { (n as usize).min(cols[cur.fi].len()) }; + Rect::new(col.x0, col.y0, cols[cur.fi][n - 1].x1, col.y1) + } + _ => col, + }; + // Estimate slots for the breaker with the paragraph's base leading. + let est_first = cur.next_baseline(f, col, base_leading, base_chars.size * 0.75, &pp); + let slots = estimate_slots(f, col, est_first, base_leading, base_chars.size, &glyphs[g0..], &pp, line_no); + let width = |j: usize| -> f64 { + let (x0, x1) = slots.get(j).copied().unwrap_or((col.x0, col.x1)); + let ind = pp.left_indent + pp.right_indent + if line_no + j == 0 { pp.first_line_indent } else { 0.0 }; + (x1 - x0 - ind).max(1.0) + }; + let rest = &glyphs[g0..]; + let rest_h = &hyph_after[g0..]; + let breaks: Vec = if pp.composer == Composer::SingleLine || has_tabs || rest.len() > 4000 { + breaker::greedy(rest, rest_h, &spacing, &width) + } else { + breaker::knuth_plass(rest, rest_h, &spacing, &width) + }; + let mut moved = false; + for (k, b) in breaks.iter().enumerate() { + let (s, e) = (g0 + b.start, g0 + b.end); + let line_glyphs = &glyphs[s..e.max(s)]; + let (asc, desc, lead) = line_metrics(line_glyphs, &glyphs, s, base_leading, base_chars.size, db, &base_chars); + let mut baseline = cur.next_baseline(f, col, lead, asc, &pp); + // Baseline grid. + if let Some((g_start, inc)) = f.grid + && (pp.grid_align == GridAlign::AllLines || (pp.grid_align == GridAlign::FirstLineOnly && line_no == 0)) + && inc > 0.0 + { + let n = ((baseline - g_start) / inc - 1e-6).ceil(); + baseline = g_start + n * inc; + } + // Wrap: push the line down until a slot exists. + let (mut x0, mut x1) = (col.x0, col.x1); + if !f.exclusions.is_empty() { + let mut tries = 0; + loop { + match free_slot(f, col, baseline - asc, baseline + desc, base_size) { + Some((a, b)) => { + x0 = a; + x1 = b; + break; + } + None => { + baseline += 1.0; + tries += 1; + if baseline > col.y1 || tries > 4000 { + break; + } + } + } + } + } + let fits = baseline + desc <= col.y1 + 0.01 || (cur.last_baseline.is_none() && baseline <= col.y1 && false); + if !fits { + // Next column / frame; re-break the rest of the paragraph there. + g0 = s; + cur.next_column(&cols); + moved = true; + let _ = k; + break; + } + let ind_l = pp.left_indent + if line_no == 0 { pp.first_line_indent } else { 0.0 }; + let lx0 = x0 + ind_l; + let lx1 = x1 - pp.right_indent; + let last = k + 1 == breaks.len(); + let (placed, end_x, ratio) = layout_line(&glyphs, s, e, b.hyphen, lx0, lx1, col.x0, &pp, last, b.forced && !last, f.left_page); + let range_end = if last { prange.end } else { glyphs.get(g0 + b.next).map(|g| g.byte).unwrap_or(prange.end) }; + let range_start = glyphs.get(s).map(|g| g.byte).unwrap_or(prange.start).min(range_end); + let range_start = if line_no == 0 { prange.start } else { range_start }; + let ft = &mut out.frames[cur.fi]; + if line_no == 0 { + first_line_rect = Some((cur.fi, baseline, asc, x0)); + } + ft.lines.push(Line { + column: cur.col as u32, + baseline, + x0, + x1, + ascent: asc, + descent: desc, + leading: lead, + range: range_start..range_end, + para: pi, + glyphs: placed, + hyphenated: b.hyphen, + first_in_para: line_no == 0, + last_in_para: last, + end_x, + spacing: ratio, + }); + cur.last_baseline = Some(baseline); + cur.last_descent = desc; + cur.pending = 0.0; + line_no += 1; + // Column / frame / page break characters. + if b.forced && e < glyphs.len() + 1 { + let brk = glyphs.get(g0 + b.next.saturating_sub(1)).map(|g| g.ch); + match brk { + Some(story::COLUMN_BREAK) => cur.next_column(&cols), + Some(story::FRAME_BREAK) | Some(story::PAGE_BREAK) => cur.next_frame(), + _ => {} + } + } + } + if !moved { + break; + } + } + // Rules and shading for the paragraph. + if let Some((fi, bl, asc, _)) = first_line_rect { + let ft = &mut out.frames[fi]; + if pp.rule_above.on { + let r = &pp.rule_above; + let y = bl - asc - r.offset; + let col = ft.lines.iter().rev().find(|l| l.para == pi).map(|l| (l.x0, l.x1)).unwrap_or((0.0, 0.0)); + ft.decos.push(Deco { rect: Rect::new(col.0 + r.left_indent, y - r.weight, col.1 - r.right_indent, y), color: r.color.clone(), tint: r.tint }); + } + if pp.shading_on { + let lines: Vec<&Line> = ft.lines.iter().filter(|l| l.para == pi).collect(); + if let (Some(a), Some(z)) = (lines.first(), lines.last()) { + ft.decos.insert(0, Deco { rect: Rect::new(a.x0, a.baseline - a.ascent, a.x1, z.baseline + z.descent), color: pp.shading_color.clone(), tint: pp.shading_tint }); + } + } + } + if pp.rule_below.on + && let Some(ft) = out.frames.get_mut(cur.fi.min(frames.len().saturating_sub(1))) + && let Some(l) = ft.lines.iter().rev().find(|l| l.para == pi) + { + let r = &pp.rule_below; + let y = l.baseline + r.offset; + let (x0, x1) = if r.column_width { (l.x0, l.x1) } else { (l.x0, l.end_x) }; + ft.decos.push(Deco { rect: Rect::new(x0 + r.left_indent, y, x1 - r.right_indent, y + r.weight), color: r.color.clone(), tint: r.tint }); + } + cur.pending += pp.space_after; + } + // Ranges, content heights and vertical justification. + for (fi, ft) in out.frames.iter_mut().enumerate() { + let f = &frames[fi]; + if let (Some(a), Some(z)) = (ft.lines.first(), ft.lines.last()) { + ft.range = a.range.start..z.range.end; + ft.content_height = z.baseline + z.descent - f.area.y0; + } else { + let p = ft_prev_end(&out.overset_at, story.text.len()); + ft.range = p..p; + } + vertical_justify(ft, f); + } + // Frame ranges for empty frames after the text: start at the end of the text shown. + let mut last_end = 0; + for ft in &mut out.frames { + if ft.lines.is_empty() { + let p = out.overset_at.unwrap_or(last_end).max(last_end); + ft.range = p..p; + } else { + last_end = ft.range.end; + } + } + out.styles = styles_tab; + out +} + +fn ft_prev_end(overset: &Option, len: usize) -> usize { + overset.unwrap_or(len) +} + +struct Cursor { + fi: usize, + col: usize, + last_baseline: Option, + last_descent: f64, + /// Space before/after waiting to be added to the next line. + pending: f64, +} + +impl Cursor { + fn next_column(&mut self, cols: &[Vec]) { + self.col += 1; + if self.fi < cols.len() && self.col >= cols[self.fi].len() { + self.col = 0; + self.fi += 1; + } + self.last_baseline = None; + self.pending = 0.0; + } + fn next_frame(&mut self) { + self.fi += 1; + self.col = 0; + self.last_baseline = None; + self.pending = 0.0; + } + /// Baseline for the next line with leading `lead` and ascent `asc`. + fn next_baseline(&self, f: &FrameSpec, col: Rect, lead: f64, asc: f64, _pp: &ParaProps) -> f64 { + match self.last_baseline { + Some(b) => b + lead + self.pending, + None => { + let off = match f.opts.first_baseline { + FirstBaseline::Ascent => asc, + FirstBaseline::CapHeight => asc * 0.72, + FirstBaseline::XHeight => asc * 0.5, + FirstBaseline::Leading => lead, + FirstBaseline::Fixed => 0.0, + }; + col.y0 + off.max(f.opts.first_baseline_min) + } + } + } +} + +fn line_metrics(line: &[Glyph], all: &[Glyph], s: usize, base_leading: f64, base_size: f64, db: &FontDb, base: &designcraft_doc::CharProps) -> (f64, f64, f64) { + let _ = db; + let src: &[Glyph] = if line.is_empty() { all.get(s..(s + 1).min(all.len())).unwrap_or(&[]) } else { line }; + if src.is_empty() { + let face = FontDb::global().face(&base.font_family, &base.font_style); + let k = base_size / face.upem; + return (face.ascent * k, face.descent * k, base_leading); + } + let mut asc: f64 = 0.0; + let mut desc: f64 = 0.0; + let mut lead: f64 = 0.0; + for g in src { + asc = asc.max(g.ascent + g.shift.max(0.0)); + desc = desc.max(g.descent - g.shift.min(0.0)); + lead = lead.max(g.leading); + } + (asc, desc, lead) +} + +/// Widest free horizontal interval of `col` in the band, or None if blocked. +fn free_slot(f: &FrameSpec, col: Rect, y0: f64, y1: f64, size: f64) -> Option<(f64, f64)> { + let mut free = vec![(col.x0, col.x1)]; + for ex in &f.exclusions { + let r = ex.rect; + let overlaps_band = r.y0 < y1 && r.y1 > y0; + match ex.mode { + WrapMode::JumpToNextColumn if y1 > r.y0 && r.x0 < col.x1 && r.x1 > col.x0 => return None, + WrapMode::JumpObject if overlaps_band && r.x0 < col.x1 && r.x1 > col.x0 => return None, + WrapMode::BoundingBox | WrapMode::Contour if overlaps_band => { + let mut next = Vec::new(); + for (a, b) in free { + if r.x1 <= a || r.x0 >= b { + next.push((a, b)); + continue; + } + if r.x0 > a { + next.push((a, r.x0)); + } + if r.x1 < b { + next.push((r.x1, b)); + } + } + free = next; + } + _ => {} + } + } + free.into_iter().filter(|(a, b)| b - a >= size * 1.5).max_by(|x, y| (x.1 - x.0).total_cmp(&(y.1 - y.0))) +} + +#[allow(clippy::too_many_arguments)] +fn estimate_slots(f: &FrameSpec, col: Rect, first: f64, lead: f64, size: f64, glyphs: &[Glyph], pp: &ParaProps, line_no: usize) -> Vec<(f64, f64)> { + let _ = (pp, line_no); + if f.exclusions.is_empty() { + return vec![]; + } + // Rough upper bound on lines: total advance / column width × 2. + let total: f64 = glyphs.iter().map(|g| g.adv).sum(); + let n = ((total / (col.width().max(10.0) * 0.5)).ceil() as usize + 2).min(2000); + let mut v = Vec::with_capacity(n); + let mut b = first; + for _ in 0..n { + let mut tries = 0; + let slot = loop { + if let Some(s) = free_slot(f, col, b - size * 0.8, b + size * 0.25, size) { + break s; + } + b += 1.0; + tries += 1; + if b > col.y1 || tries > 4000 { + break (col.x0, col.x1); + } + }; + v.push(slot); + b += lead; + } + v +} + +/// Position glyphs `s..e` within `[x0, x1]`; returns (glyphs, end x, word-space ratio). +#[allow(clippy::too_many_arguments)] +fn layout_line( + glyphs: &[Glyph], + s: usize, + e: usize, + hyphen: bool, + x0: f64, + x1: f64, + tab_origin: f64, + pp: &ParaProps, + last: bool, + forced_mid: bool, + left_page: bool, +) -> (Vec, f64, f64) { + let mut line: Vec = glyphs[s..e.max(s)].to_vec(); + if hyphen && let Some(g) = line.last() { + let h = shape::hyphen_after(g); + line.push(h); + } + // Tabs: compute widths left to right. + let measure = x1 - x0; + let mut x = 0.0; + let mut i = 0; + while i < line.len() { + if line[i].ch == '\t' { + let abs = x0 + x - tab_origin; + let stop = pp.tabs.iter().find(|t| t.position > abs + 0.01).cloned(); + let (pos, align) = match &stop { + Some(t) => (t.position, t.align), + None => (((abs / DEFAULT_TAB).floor() + 1.0) * DEFAULT_TAB, TabAlign::Left), + }; + // Width of the text after this tab up to the next tab / line end. + let seg_end = line[i + 1..].iter().position(|g| g.ch == '\t').map_or(line.len(), |p| i + 1 + p); + let seg_w: f64 = line[i + 1..seg_end].iter().map(|g| g.adv).sum(); + let target = pos + tab_origin - x0; + let w = match align { + TabAlign::Left => target - x, + TabAlign::Right => target - x - seg_w, + TabAlign::Center => target - x - seg_w / 2.0, + TabAlign::Char => { + let ch = stop.as_ref().and_then(|t| t.align_on.chars().next()).unwrap_or('.'); + let before: f64 = line[i + 1..seg_end].iter().take_while(|g| g.ch != ch).map(|g| g.adv).sum(); + target - x - before + } + }; + line[i].adv = w.max(0.0); + } else if line[i].ch == story::RIGHT_INDENT_TAB { + let rest: f64 = line[i + 1..].iter().map(|g| g.adv).sum(); + line[i].adv = (measure - x - rest).max(0.0); + } + x += line[i].adv; + i += 1; + } + let natural: f64 = line.iter().map(|g| g.adv).sum(); + let extra = measure - natural; + let spaces: Vec = line.iter().enumerate().filter(|(_, g)| g.is_space() && !g.no_break).map(|(i, _)| i).collect(); + let has_tab = line.iter().any(|g| g.ch == '\t' || g.ch == story::RIGHT_INDENT_TAB); + let align = match pp.align { + Align::TowardsSpine => { + if left_page { + Align::Right + } else { + Align::Left + } + } + Align::AwayFromSpine => { + if left_page { + Align::Left + } else { + Align::Right + } + } + a => a, + }; + let justify_this = align.is_justified() && (!last || align == Align::FullyJustified || forced_mid) && !has_tab; + let mut per_space = 0.0; + let mut offset = 0.0; + let mut ratio = 1.0; + if justify_this && !spaces.is_empty() { + per_space = extra / spaces.len() as f64; + let space_w: f64 = spaces.iter().map(|&i| line[i].adv).sum::() / spaces.len() as f64; + ratio = if space_w > 0.0 { (space_w + per_space) / space_w * pp.word_space_desired } else { 1.0 }; + } else if justify_this && spaces.is_empty() && line.len() > 1 && !last { + // Single word: Single Word Justification. + match pp.single_word_justify { + Align::FullyJustified => { + let gaps = (line.len() - 1) as f64; + let per = extra / gaps; + let mut x = x0; + let mut out = Vec::with_capacity(line.len()); + for (i, g) in line.iter().enumerate() { + out.push(place(g, x)); + x += g.adv + if i + 1 < line.len() { per } else { 0.0 }; + } + return (out, x, 1.0); + } + Align::Center => offset = extra / 2.0, + Align::Right => offset = extra, + _ => {} + } + } else { + let last_align = match align { + Align::LeftJustified => Align::Left, + Align::CenterJustified => Align::Center, + Align::RightJustified => Align::Right, + Align::FullyJustified => Align::Left, + a => a, + }; + offset = match last_align { + Align::Center => extra / 2.0, + Align::Right => extra, + _ => 0.0, + }; + // Overfull ragged lines are not shifted left of the slot. + if offset < 0.0 { + offset = 0.0; + } + } + let mut out = Vec::with_capacity(line.len()); + let mut x = x0 + offset; + for (i, g) in line.iter().enumerate() { + out.push(place(g, x)); + x += g.adv; + if per_space != 0.0 && spaces.binary_search(&i).is_ok() { + x += per_space; + if let Some(p) = out.last_mut() { + p.adv += per_space; + } + } + } + (out, x, ratio) +} + +fn place(g: &Glyph, x: f64) -> PlacedGlyph { + let visible = !(g.ch == '\t' || g.ch == '\n' || breaker::is_forced(g.ch) || g.ch == story::INDENT_HERE || g.ch == story::RIGHT_INDENT_TAB || g.ch == shape::SOFT_HYPHEN); + PlacedGlyph { face: g.face.clone(), gid: g.gid, x: x + g.dx, y: -g.shift + g.dy, adv: g.adv, sx: g.sx, sy: g.sy, style: g.style, byte: g.byte, len: g.len, visible } +} + +fn prepend_label(db: &FontDb, glyphs: &mut Vec, label: &str, at: usize, base: &designcraft_doc::CharProps, pp: &ParaProps, table: &mut StyleTable<'_>) { + // Shape the label as a tiny standalone story so it uses the paragraph's base character style. + let mut tmp = Story::new(StoryId(0)); + tmp.insert(0, label); + let styles = designcraft_doc::Styles::default(); + let shaped = shape::shape_para(db, &styles, &tmp, 0, 0..label.len(), base, pp.auto_leading, &SubstCtx::default(), table); + let mut pre: Vec = shaped + .glyphs + .into_iter() + .map(|mut g| { + g.byte = at; + g.len = 0; + g + }) + .collect(); + pre.append(glyphs); + *glyphs = pre; +} + +/// Mark glyphs after which a hyphen may be inserted. +fn hyphenation_points(text: &str, glyphs: &[Glyph], pp: &ParaProps) -> Vec { + let mut out = vec![false; glyphs.len()]; + if !pp.hyphenate { + return out; + } + let lim = hyphen::Limits { + min_word: pp.hyph_min_word as usize, + after_first: pp.hyph_after_first as usize, + before_last: pp.hyph_before_last as usize, + capitalized: pp.hyph_capitalized, + }; + let mut i = 0; + while i < glyphs.len() { + if !glyphs[i].is_letter() || glyphs[i].len == 0 { + i += 1; + continue; + } + let mut j = i; + while j < glyphs.len() && (glyphs[j].is_letter() || glyphs[j].len == 0) && !glyphs[j].no_break { + j += 1; + } + let (a, b) = (glyphs[i].byte, glyphs[j - 1].byte + glyphs[j - 1].len); + if b > a && b <= text.len() && text.is_char_boundary(a) && text.is_char_boundary(b) { + let word = &text[a..b]; + // Do not hyphenate the paragraph's last word unless allowed. + let is_last_word = !pp.hyph_last_word && glyphs[j..].iter().all(|g| !g.is_letter()); + if !is_last_word { + let pts = hyphen::hyphen_points(word, &lim); + for p in pts { + // char index p → byte → glyph whose cluster ends at that byte. + let byte = a + word.char_indices().nth(p).map(|(bi, _)| bi).unwrap_or(word.len()); + if let Some(k) = (i..j).find(|&k| glyphs[k].byte + glyphs[k].len == byte && glyphs[k].len > 0) { + out[k] = true; + } + } + } + } + i = j.max(i + 1); + } + out +} + +fn vertical_justify(ft: &mut FrameText, f: &FrameSpec) { + if ft.lines.is_empty() || f.opts.vertical_justification == VerticalJustification::Top { + return; + } + // Per column. + let ncols = ft.columns.len().max(1) as u32; + for c in 0..ncols { + let idx: Vec = ft.lines.iter().enumerate().filter(|(_, l)| l.column == c).map(|(i, _)| i).collect(); + let (Some(&a), Some(&z)) = (idx.first(), idx.last()) else { continue }; + let bottom = ft.lines[z].baseline + ft.lines[z].descent; + let space = f.area.y1 - bottom; + if space <= 0.0 { + continue; + } + let _ = a; + match f.opts.vertical_justification { + VerticalJustification::Center => idx.iter().for_each(|&i| ft.lines[i].baseline += space / 2.0), + VerticalJustification::Bottom => idx.iter().for_each(|&i| ft.lines[i].baseline += space), + VerticalJustification::Justify if idx.len() > 1 => { + let per = space / (idx.len() - 1) as f64; + for (k, &i) in idx.iter().enumerate() { + ft.lines[i].baseline += per * k as f64; + } + } + _ => {} + } + } +} + +// ---------- caret and hit testing (Type tool) ---------- + +/// Caret geometry for story byte `pos`: (frame index, x, baseline, ascent, descent). +pub fn caret(cs: &ComposedStory, pos: usize) -> Option<(usize, f64, f64, f64, f64)> { + let mut best: Option<(usize, &Line)> = None; + for (fi, ft) in cs.frames.iter().enumerate() { + for l in &ft.lines { + if pos >= l.range.start && pos <= l.range.end { + // Prefer the line where pos is not at its end (except the last line of a paragraph). + let at_end = pos == l.range.end && !l.last_in_para; + if best.is_none() || !at_end { + best = Some((fi, l)); + if !at_end { + break; + } + } + } + } + if best.is_some_and(|(_, l)| pos < l.range.end || l.last_in_para) { + break; + } + } + let (fi, l) = best?; + Some((fi, caret_x(l, pos), l.baseline, l.ascent, l.descent)) +} + +fn caret_x(l: &Line, pos: usize) -> f64 { + for g in &l.glyphs { + if g.len > 0 && pos >= g.byte && pos < g.byte + g.len { + // Inside a multi-char cluster (ligature): interpolate. + let t = (pos - g.byte) as f64 / g.len as f64; + return g.x + g.adv * t; + } + if g.len > 0 && g.byte >= pos { + return g.x; + } + } + l.end_x +} + +/// Story byte nearest to point `p` (frame inner space) in frame `fi`. +pub fn hit(cs: &ComposedStory, fi: usize, p: Point) -> Option { + let ft = cs.frames.get(fi)?; + if ft.lines.is_empty() { + return Some(ft.range.start); + } + // Closest line vertically (within its column). + let l = ft + .lines + .iter() + .filter(|l| p.x >= l.x0 - 20.0 && p.x <= l.x1 + 20.0 || ft.columns.len() <= 1) + .min_by(|a, b| line_dist(a, p.y).total_cmp(&line_dist(b, p.y))) + .or_else(|| ft.lines.first())?; + let mut best = l.range.start; + let mut prev_mid = f64::NEG_INFINITY; + for g in l.glyphs.iter().filter(|g| g.len > 0) { + let mid = g.x + g.adv / 2.0; + if p.x < mid && p.x >= prev_mid { + return Some(g.byte); + } + prev_mid = mid; + best = g.byte + g.len; + } + // After the last glyph: line end (before the paragraph separator / break). + Some(if l.last_in_para { l.range.end } else { best.min(l.range.end) }) +} + +fn line_dist(l: &Line, y: f64) -> f64 { + let top = l.baseline - l.ascent; + let bot = l.baseline + l.descent; + if y < top { + top - y + } else if y > bot { + y - bot + } else { + 0.0 + } +} + +#[cfg(test)] +mod tests; diff --git a/crates/compose/src/shape.rs b/crates/compose/src/shape.rs new file mode 100644 index 00000000..9f36ad02 --- /dev/null +++ b/crates/compose/src/shape.rs @@ -0,0 +1,334 @@ +//! Paragraph → styled, positioned glyphs (before line breaking). + +use std::sync::Arc; + +use designcraft_doc::{Capitalization, CharProps, Kerning, Leading, Position, Story, Styles, story}; +use designcraft_fonts::{Feature, FontDb, FontFace, ShapedGlyph, feature}; + +use crate::RunStyle; + +/// One glyph with every character attribute applied, in points. +#[derive(Clone, Debug)] +pub struct Glyph { + pub face: Arc, + pub gid: u32, + /// Story byte offset of the cluster and its byte length (0 for generated glyphs). + pub byte: usize, + pub len: usize, + /// First source character of the cluster (special characters keep their code). + pub ch: char, + /// Advance in points (tracking and horizontal scale applied). + pub adv: f64, + pub dx: f64, + pub dy: f64, + /// Font units → points (incl. horizontal / vertical scale). + pub sx: f64, + pub sy: f64, + /// Baseline shift (positive = up), including super/subscript. + pub shift: f64, + pub ascent: f64, + pub descent: f64, + /// The leading this character asks for (absolute, or auto = size × auto %). + pub leading: f64, + pub cap: f64, + pub xh: f64, + pub size: f64, + /// Index into the composed story's [`RunStyle`] table. + pub style: u32, + /// Unbreakable (No Break). + pub no_break: bool, +} + +impl Glyph { + pub fn is_space(&self) -> bool { + matches!(self.ch, ' ' | '\u{2002}'..='\u{200A}' | '\u{3000}') + } + pub fn is_letter(&self) -> bool { + self.ch.is_alphabetic() || matches!(self.ch, '\'' | '’') + } +} + +pub const SOFT_HYPHEN: char = '\u{AD}'; + +/// Shaped paragraph. +pub struct ShapedPara { + pub glyphs: Vec, + /// Byte range of the paragraph text (without its `\n`). + pub range: std::ops::Range, +} + +/// Context for substitutions (page number markers). +#[derive(Clone, Debug, Default)] +pub struct SubstCtx { + pub page_name: Option, + pub section_marker: Option, +} + +pub(crate) struct StyleTable<'a> { + pub styles: &'a mut Vec, +} + +impl StyleTable<'_> { + fn intern(&mut self, p: &CharProps) -> u32 { + let rs = RunStyle { + fill: p.fill.clone(), + fill_tint: p.fill_tint, + stroke: p.stroke.clone(), + stroke_tint: p.stroke_tint, + stroke_weight: p.stroke_weight, + underline: p.underline, + strikethrough: p.strikethrough, + skew: p.skew, + size: p.size, + }; + if let Some(i) = self.styles.iter().rposition(|s| *s == rs) { + return i as u32; + } + self.styles.push(rs); + (self.styles.len() - 1) as u32 + } +} + +/// Resolve and shape one paragraph. +pub(crate) fn shape_para( + db: &FontDb, + styles: &Styles, + story: &Story, + pi: usize, + range: std::ops::Range, + para_chars: &CharProps, + auto_leading: f64, + sub: &SubstCtx, + table: &mut StyleTable<'_>, +) -> ShapedPara { + let _ = pi; + let mut glyphs = Vec::with_capacity(range.len()); + for (rr, fmt) in story.runs() { + let a = rr.start.max(range.start); + let b = rr.end.min(range.end); + if a >= b { + continue; + } + let props = styles.resolve_char(para_chars, fmt); + let style = table.intern(&props); + shape_run(db, &story.text, a..b, &props, auto_leading, style, sub, &mut glyphs); + } + ShapedPara { glyphs, range } +} + +fn features_for(p: &CharProps) -> Vec { + let mut v = Vec::new(); + if !matches!(p.kerning, Kerning::Metrics | Kerning::Optical) { + v.extend(feature("-kern")); + } + if !p.ligatures || p.tracking.abs() > 1e-9 { + v.extend(feature("-liga")); + v.extend(feature("-clig")); + } + if p.capitalization == Capitalization::AllCaps { + v.extend(feature("case")); + } + if matches!(p.capitalization, Capitalization::SmallCaps | Capitalization::OpenTypeAllSmallCaps) { + v.extend(feature("smcp")); + } + if p.capitalization == Capitalization::OpenTypeAllSmallCaps { + v.extend(feature("c2sc")); + } + match p.position { + Position::OtSuperscript => v.extend(feature("sups")), + Position::OtSubscript => v.extend(feature("subs")), + Position::OtNumerator => v.extend(feature("numr")), + Position::OtDenominator => v.extend(feature("dnom")), + _ => {} + } + for f in &p.otf_features { + v.extend(feature(f)); + } + v +} + +fn is_mark(c: char) -> bool { + matches!(c as u32, 0x0300..=0x036F | 0x1AB0..=0x1AFF | 0x1DC0..=0x1DFF | 0x20D0..=0x20FF | 0xFE20..=0xFE2F | 0x200D | 0xFE00..=0xFE0F) +} + +#[allow(clippy::too_many_arguments)] +fn shape_run(db: &FontDb, text: &str, range: std::ops::Range, p: &CharProps, auto_leading: f64, style: u32, sub: &SubstCtx, out: &mut Vec) { + let primary = db.face(&p.font_family, &p.font_style); + // Split into segments: font coverage changes and special characters (markers, tabs, breaks). + let mut seg_start = range.start; + let mut seg_face = primary.clone(); + let flush = |a: usize, b: usize, face: &Arc, out: &mut Vec| { + if a < b { + shape_segment(db, text, a..b, None, p, face, auto_leading, style, out); + } + }; + for (i, c) in text[range.clone()].char_indices() { + let i = range.start + i; + let special = matches!( + c, + '\t' | story::FORCED_LINE_BREAK + | story::PAGE_NUMBER + | story::NEXT_PAGE_NUMBER + | story::PREV_PAGE_NUMBER + | story::SECTION_MARKER + | story::COLUMN_BREAK + | story::FRAME_BREAK + | story::PAGE_BREAK + | story::INDENT_HERE + | story::RIGHT_INDENT_TAB + ); + if special { + flush(seg_start, i, &seg_face, out); + seg_start = i + c.len_utf8(); + match c { + story::PAGE_NUMBER | story::NEXT_PAGE_NUMBER | story::PREV_PAGE_NUMBER | story::SECTION_MARKER => { + let s = if c == story::SECTION_MARKER { + sub.section_marker.clone().unwrap_or_else(|| "Section".into()) + } else { + sub.page_name.clone().unwrap_or_else(|| "#".into()) + }; + shape_segment(db, text, i..i + c.len_utf8(), Some(&s), p, &primary, auto_leading, style, out); + } + _ => { + // Zero-width control glyph carrying metrics (tabs get their width at line layout). + let mut g = control_glyph(&primary, p, auto_leading, style, i, c); + if c == '\t' || c == story::RIGHT_INDENT_TAB { + g.adv = 0.0; + } + out.push(g); + } + } + continue; + } + let covered = c.is_whitespace() || c.is_control() || c == SOFT_HYPHEN || primary.covers(c); + let face = if covered || is_mark(c) { if is_mark(c) { seg_face.clone() } else { primary.clone() } } else { db.fallback_for(c, primary.id()).unwrap_or_else(|| primary.clone()) }; + if face.id() != seg_face.id() { + flush(seg_start, i, &seg_face, out); + seg_start = i; + seg_face = face; + } + } + flush(seg_start, range.end, &seg_face, out); +} + +fn metrics(face: &FontFace, p: &CharProps, auto_leading: f64) -> (f64, f64, f64, f64, f64, f64, f64, f64) { + let (size, shift) = effective_size(p); + let k = size / face.upem; + let vs = p.v_scale; + let leading = match p.leading { + Leading::Auto => p.size * auto_leading, + Leading::Points(v) => v, + }; + (size, k, face.ascent * k * vs, face.descent * k * vs, leading, face.cap_height * k * vs, face.x_height * k * vs, shift) +} + +/// Super/subscript use 58.3% size and ±33.3% / −10% shift (InDesign's defaults). +fn effective_size(p: &CharProps) -> (f64, f64) { + match p.position { + Position::Superscript => (p.size * 0.583, p.baseline_shift + p.size * 0.333), + Position::Subscript => (p.size * 0.583, p.baseline_shift - p.size * 0.333 * 0.3), + _ => (p.size, p.baseline_shift), + } +} + +fn control_glyph(face: &Arc, p: &CharProps, auto_leading: f64, style: u32, byte: usize, ch: char) -> Glyph { + let (size, k, ascent, descent, leading, cap, xh, shift) = metrics(face, p, auto_leading); + Glyph { + face: face.clone(), + gid: face.glyph_for(' '), + byte, + len: ch.len_utf8(), + ch, + adv: 0.0, + dx: 0.0, + dy: 0.0, + sx: k * p.h_scale, + sy: k * p.v_scale, + shift, + ascent, + descent, + leading, + cap, + xh, + size, + style, + no_break: p.no_break, + } +} + +#[allow(clippy::too_many_arguments)] +fn shape_segment( + db: &FontDb, + text: &str, + range: std::ops::Range, + replacement: Option<&str>, + p: &CharProps, + face: &Arc, + auto_leading: f64, + style: u32, + out: &mut Vec, +) { + let _ = db; + let (size, k, ascent, descent, leading, cap, xh, shift) = metrics(face, p, auto_leading); + let hs = p.h_scale; + let tracking = p.tracking / 1000.0 * p.size; + let manual = if let Kerning::Manual(v) = p.kerning { v / 1000.0 * p.size } else { 0.0 }; + let src = replacement.unwrap_or(&text[range.clone()]); + let caps = p.capitalization == Capitalization::AllCaps; + let feats = features_for(p); + let shaped: Vec = designcraft_fonts::shape(face, src, &feats, |c| if caps { c.to_uppercase().next().unwrap_or(c) } else { c }); + let n = shaped.len(); + for (gi, sg) in shaped.iter().enumerate() { + let (byte, len, ch) = if replacement.is_some() { + (range.start, if gi == 0 { range.len() } else { 0 }, text[range.start..].chars().next().unwrap_or(' ')) + } else { + let cl = range.start + sg.cluster; + let end = shaped[gi + 1..].iter().map(|r| range.start + r.cluster).find(|&c| c > cl).unwrap_or(range.end); + (cl, end.saturating_sub(cl), text[cl..].chars().next().unwrap_or(' ')) + }; + let last_in_cluster = gi + 1 == n || shaped[gi + 1].cluster != sg.cluster; + let mut adv = sg.x_advance as f64 * k * hs; + if ch == SOFT_HYPHEN { + adv = 0.0; + } else if last_in_cluster { + adv += tracking + manual; + } + // Only the first glyph of a cluster owns the bytes (so ranges partition the text). + let first_in_cluster = gi == 0 || shaped[gi - 1].cluster != sg.cluster; + out.push(Glyph { + face: face.clone(), + gid: sg.gid, + byte, + len: if first_in_cluster || replacement.is_some() { len } else { 0 }, + ch, + adv, + dx: sg.x_offset as f64 * k * hs, + dy: -(sg.y_offset as f64) * k * p.v_scale, + sx: k * hs, + sy: k * p.v_scale, + shift, + ascent, + descent, + leading, + cap, + xh, + size, + style, + no_break: p.no_break, + }); + } +} + +/// A hyphen glyph in the face/size of `g`, placed after it (zero source length). +pub(crate) fn hyphen_after(g: &Glyph) -> Glyph { + let gid = designcraft_fonts::first_glyph(&g.face, &['-', '\u{2010}']); + let mut h = g.clone(); + h.gid = gid; + h.adv = g.face.advance(gid) * g.sx; + h.dx = 0.0; + h.dy = 0.0; + h.byte = g.byte + g.len; + h.len = 0; + h.ch = '-'; + h +} diff --git a/crates/compose/src/tests.rs b/crates/compose/src/tests.rs new file mode 100644 index 00000000..05d7dc06 --- /dev/null +++ b/crates/compose/src/tests.rs @@ -0,0 +1,172 @@ +use designcraft_doc::build::NewDocument; +use designcraft_doc::{Align, Document, ParaAttrs, ParaFormat, SpreadRef}; +use designcraft_geom::Rect; + +use super::*; + +const LOREM: &str = "Typography is the art and technique of arranging type to make written language legible, readable and appealing when displayed. \ +The arrangement of type involves selecting typefaces, point sizes, line lengths, line spacing, and letter spacing, and adjusting the space between pairs of letters."; + +fn doc_with(text: &str, rect: Rect, para: ParaAttrs) -> (Document, StoryId, ItemId) { + let mut d = Document::new(&NewDocument::default()); + let lid = d.default_layer(); + let (fid, sid) = d.add_text_frame(SpreadRef::Doc(0), rect, lid, text, ParaFormat { para, ..Default::default() }).unwrap(); + (d, sid, fid) +} + +fn all_lines(cs: &ComposedStory) -> Vec<&Line> { + cs.frames.iter().flat_map(|f| f.lines.iter()).collect() +} + +#[test] +fn composes_simple_paragraph() { + let (d, sid, _) = doc_with(LOREM, Rect::new(36.0, 36.0, 300.0, 700.0), ParaAttrs::default()); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + assert!(!cs.is_overset()); + let lines = all_lines(&cs); + assert!(lines.len() >= 5, "{}", lines.len()); + // Baselines increase by the auto leading (12 × 120% = 14.4). + for w in lines.windows(2) { + assert!((w[1].baseline - w[0].baseline - 14.4).abs() < 1e-6); + } + // Lines fit their measure. + for l in &lines { + assert!(l.end_x <= l.x1 + 0.5, "line overflows: {} > {}", l.end_x, l.x1); + } +} + +#[test] +fn line_ranges_partition_the_story() { + let text = format!("{LOREM}\n\nSecond paragraph here.\n{LOREM}"); + let (d, sid, _) = doc_with(&text, Rect::new(0.0, 0.0, 200.0, 2000.0), ParaAttrs::default()); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let lines = all_lines(&cs); + let mut pos = 0; + for l in &lines { + // Each line starts where the previous ended (or after a paragraph separator). + assert!(l.range.start == pos || l.range.start == pos + 1, "gap at {pos}: {:?}", l.range); + pos = l.range.end; + } + assert_eq!(pos, text.len()); + assert_eq!(lines.iter().filter(|l| l.first_in_para).count(), 4); +} + +#[test] +fn justified_lines_fill_the_measure() { + let (d, sid, _) = doc_with(LOREM, Rect::new(0.0, 0.0, 220.0, 2000.0), ParaAttrs { align: Some(Align::LeftJustified), ..Default::default() }); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let lines = all_lines(&cs); + for l in &lines[..lines.len() - 1] { + assert!((l.end_x - l.x1).abs() < 0.6, "justified line ends at {} not {}", l.end_x, l.x1); + } + let last = lines.last().unwrap(); + assert!(last.end_x < last.x1 - 1.0, "last line is ragged"); +} + +#[test] +fn small_frame_oversets() { + let (d, sid, _) = doc_with(LOREM, Rect::new(0.0, 0.0, 200.0, 40.0), ParaAttrs::default()); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + assert!(cs.is_overset()); + let shown = cs.frames[0].range.clone(); + assert_eq!(cs.overset_at.unwrap(), shown.end.max(cs.overset_at.unwrap()).min(cs.overset_at.unwrap())); + assert!(cs.frames[0].lines.len() <= 3); +} + +#[test] +fn text_flows_through_threaded_frames() { + let mut d = Document::new(&NewDocument::default()); + let lid = d.default_layer(); + let long = [LOREM; 4].join("\n"); + let (a, sid) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(0.0, 0.0, 200.0, 120.0), lid, &long, ParaFormat::default()).unwrap(); + let (b, _) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(250.0, 0.0, 450.0, 2000.0), lid, "", ParaFormat::default()).unwrap(); + d.thread(a, b).unwrap(); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + assert!(!cs.is_overset()); + assert!(!cs.frames[0].lines.is_empty() && !cs.frames[1].lines.is_empty()); + assert_eq!(cs.frames[0].range.end, cs.frames[1].range.start.min(cs.frames[0].range.end).max(cs.frames[0].range.end)); + // The second frame's lines start at its top. + assert!(cs.frames[1].lines[0].baseline < 20.0); +} + +#[test] +fn columns_fill_left_to_right() { + let (mut d, sid, fid) = doc_with(&[LOREM; 3].join(" "), Rect::new(0.0, 0.0, 400.0, 150.0), ParaAttrs::default()); + d.item_mut(fid).unwrap().text_frame_mut().unwrap().options.columns = 2; + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let lines = all_lines(&cs); + assert!(lines.iter().any(|l| l.column == 1)); + let c1 = lines.iter().find(|l| l.column == 1).unwrap(); + assert!(c1.x0 > 200.0); +} + +#[test] +fn centered_text_is_centered() { + let (d, sid, _) = doc_with("Hello", Rect::new(0.0, 0.0, 300.0, 100.0), ParaAttrs { align: Some(Align::Center), ..Default::default() }); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let l = &cs.frames[0].lines[0]; + let left = l.glyphs[0].x - l.x0; + let right = l.x1 - l.end_x; + assert!((left - right).abs() < 0.5, "{left} vs {right}"); +} + +#[test] +fn caret_and_hit_roundtrip() { + let (d, sid, _) = doc_with(LOREM, Rect::new(0.0, 0.0, 200.0, 1000.0), ParaAttrs::default()); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + for pos in [0, 5, 40, 100, LOREM.len()] { + let (fi, x, b, _, _) = caret(&cs, pos).unwrap(); + let back = hit(&cs, fi, Point::new(x + 0.1, b - 2.0)).unwrap(); + assert!((back as i64 - pos as i64).abs() <= 1, "{pos} -> {back}"); + } +} + +#[test] +fn empty_story_has_one_line() { + let (d, sid, _) = doc_with("", Rect::new(0.0, 0.0, 200.0, 100.0), ParaAttrs::default()); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + assert_eq!(cs.line_count(), 1); + assert!(caret(&cs, 0).is_some()); +} + +#[test] +fn wrap_pushes_text_aside() { + let (mut d, sid, _) = doc_with(&[LOREM; 2].join(" "), Rect::new(0.0, 0.0, 300.0, 800.0), ParaAttrs::default()); + let lid = d.default_layer(); + let id = ItemId(d.alloc()); + let mut it = designcraft_doc::Item::new(id, lid, designcraft_doc::Shape::Rectangle, designcraft_geom::shapes::rectangle(Rect::new(0.0, 0.0, 120.0, 60.0))); + it.wrap.mode = WrapMode::BoundingBox; + it.wrap.offsets = [0.0, 0.0, 6.0, 6.0]; + d.insert_item(SpreadRef::Doc(0), it, None).unwrap(); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let first = &cs.frames[0].lines[0]; + assert!(first.x0 >= 126.0 - 1e-6, "{}", first.x0); + let below = cs.frames[0].lines.iter().find(|l| l.baseline - l.ascent > 66.0).unwrap(); + assert!(below.x0 < 1.0); +} + +#[test] +fn paragraph_composer_is_no_worse_than_greedy() { + // Sum of squared slack over lines (excluding last) should not exceed the greedy result. + let measure = 180.0; + let mk = |c: designcraft_doc::Composer| { + let (d, sid, _) = doc_with(&[LOREM; 2].join(" "), Rect::new(0.0, 0.0, measure, 4000.0), ParaAttrs { composer: Some(c), hyphenate: Some(false), ..Default::default() }); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let lines = all_lines(&cs); + let n = lines.len(); + lines[..n - 1].iter().map(|l| (l.x1 - l.end_x).powi(2)).sum::() + }; + let kp = mk(designcraft_doc::Composer::Paragraph); + let gr = mk(designcraft_doc::Composer::SingleLine); + assert!(kp <= gr * 1.05 + 1.0, "kp {kp} greedy {gr}"); +} + +#[test] +fn tabs_align_to_stops() { + let mut pa = ParaAttrs::default(); + pa.tabs = Some(vec![designcraft_doc::TabStop { position: 100.0, align: TabAlign::Right, leader: String::new(), align_on: String::new() }]); + let (d, sid, _) = doc_with("Name\t42", Rect::new(0.0, 0.0, 300.0, 100.0), pa); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let l = &cs.frames[0].lines[0]; + assert!((l.end_x - 100.0).abs() < 0.5, "{}", l.end_x); +} diff --git a/crates/doc/proptest-regressions/story.txt b/crates/doc/proptest-regressions/story.txt new file mode 100644 index 00000000..c922cc41 --- /dev/null +++ b/crates/doc/proptest-regressions/story.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 3e642ee9cd6b3dfe88454002147ccd4c5d072f080b54f02b3e28f85dccbdf9cb # shrinks to ops = [Ins(0, ""), Ins(0, "éé"), Ins(21, "é"), Fmt(21, 1, 0)] diff --git a/crates/doc/src/build.rs b/crates/doc/src/build.rs new file mode 100644 index 00000000..846ea25e --- /dev/null +++ b/crates/doc/src/build.rs @@ -0,0 +1,498 @@ +//! Creating documents (File → New → Document), presets, and page/spread structure edits +//! (insert/delete/move pages, repagination into spreads, parents). + +use std::collections::BTreeMap; +use std::sync::Arc; + +use designcraft_geom::{Affine, Unit, units}; +use serde::{Deserialize, Serialize}; + +use crate::ids::{ItemId, LayerId, PageId, SpreadId}; +use crate::item::Item; +use crate::page::{Columns, Margins, Page, PageSide, ParentInfo, Section, Spread}; +use crate::styles::Styles; +use crate::{DocError, DocSettings, Document, Intent, LAYER_COLORS, Layer, Result}; + +/// A New Document preset. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Preset { + pub name: &'static str, + pub intent: Intent, + pub width: f64, + pub height: f64, + pub units: Unit, +} + +const MM: f64 = units::PT_PER_MM; + +pub const PRESETS: &[Preset] = &[ + Preset { name: "Letter", intent: Intent::Print, width: 612.0, height: 792.0, units: Unit::Picas }, + Preset { name: "Legal", intent: Intent::Print, width: 612.0, height: 1008.0, units: Unit::Picas }, + Preset { name: "Tabloid", intent: Intent::Print, width: 792.0, height: 1224.0, units: Unit::Picas }, + Preset { name: "Letter - Half", intent: Intent::Print, width: 396.0, height: 612.0, units: Unit::Picas }, + Preset { name: "A3", intent: Intent::Print, width: 297.0 * MM, height: 420.0 * MM, units: Unit::Millimeters }, + Preset { name: "A4", intent: Intent::Print, width: 210.0 * MM, height: 297.0 * MM, units: Unit::Millimeters }, + Preset { name: "A5", intent: Intent::Print, width: 148.0 * MM, height: 210.0 * MM, units: Unit::Millimeters }, + Preset { name: "B5", intent: Intent::Print, width: 176.0 * MM, height: 250.0 * MM, units: Unit::Millimeters }, + Preset { name: "Business Card", intent: Intent::Print, width: 252.0, height: 144.0, units: Unit::Picas }, + Preset { name: "Postcard", intent: Intent::Print, width: 432.0, height: 288.0, units: Unit::Picas }, + Preset { name: "Web 1920 × 1080", intent: Intent::Web, width: 1920.0, height: 1080.0, units: Unit::Pixels }, + Preset { name: "Web 1366 × 768", intent: Intent::Web, width: 1366.0, height: 768.0, units: Unit::Pixels }, + Preset { name: "Web 1024 × 768", intent: Intent::Web, width: 1024.0, height: 768.0, units: Unit::Pixels }, + Preset { name: "Mobile 1080 × 1920", intent: Intent::Mobile, width: 1080.0, height: 1920.0, units: Unit::Pixels }, + Preset { name: "Mobile 390 × 844", intent: Intent::Mobile, width: 390.0, height: 844.0, units: Unit::Pixels }, + Preset { name: "Tablet 1024 × 1366", intent: Intent::Mobile, width: 1024.0, height: 1366.0, units: Unit::Pixels }, +]; + +/// File → New → Document parameters. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct NewDocument { + pub title: String, + pub intent: Intent, + pub width: f64, + pub height: f64, + pub pages: usize, + pub start_page: u32, + pub facing_pages: bool, + pub primary_text_frame: bool, + pub columns: u32, + pub gutter: f64, + pub margins: Margins, + pub bleed: [f64; 4], + pub slug: [f64; 4], + pub units: Unit, +} + +impl Default for NewDocument { + fn default() -> Self { + NewDocument { + title: "Untitled-1".into(), + intent: Intent::Print, + width: 612.0, + height: 792.0, + pages: 1, + start_page: 1, + facing_pages: true, + primary_text_frame: false, + columns: 1, + gutter: 12.0, + margins: Margins::uniform(36.0), + bleed: [0.0; 4], + slug: [0.0; 4], + units: Unit::Picas, + } + } +} + +impl NewDocument { + pub fn from_preset(name: &str) -> Option { + let p = PRESETS.iter().find(|p| p.name.eq_ignore_ascii_case(name))?; + let web = p.intent != Intent::Print; + Some(NewDocument { + intent: p.intent, + width: p.width, + height: p.height, + units: p.units, + facing_pages: !web, + margins: if p.units == Unit::Millimeters { Margins::uniform(12.7 * MM) } else { Margins::uniform(36.0) }, + ..Default::default() + }) + } +} + +impl Document { + /// Build a new document. + pub fn new(nd: &NewDocument) -> Document { + let settings = DocSettings { + intent: nd.intent, + page_width: nd.width, + page_height: nd.height, + facing_pages: nd.facing_pages, + primary_text_frame: nd.primary_text_frame, + bleed: nd.bleed, + slug: nd.slug, + horizontal_units: nd.units, + vertical_units: nd.units, + ..Default::default() + }; + let mut d = Document { + title: nd.title.clone(), + settings, + spreads: vec![], + parents: vec![], + layers: vec![], + stories: BTreeMap::new(), + styles: Arc::new(Styles::default()), + swatches: designcraft_color::default_swatches(), + sections: vec![Section { + start: 0, + start_number: Some(nd.start_page.max(1)), + style: Default::default(), + prefix: String::new(), + marker: String::new(), + include_prefix: false, + }], + assets: BTreeMap::new(), + next_id: 0, + }; + let lid = LayerId(d.alloc()); + d.layers.push(Layer { + id: lid, + name: "Layer 1".into(), + color: LAYER_COLORS[0].1, + visible: true, + locked: false, + printable: true, + show_guides: true, + suppress_wrap_when_hidden: false, + }); + // A-Parent. + let parent_id = d.add_parent("A", "Parent", nd.columns, nd.gutter, nd.margins); + // Document pages. + let pages: Vec = (0..nd.pages.max(1)).map(|_| d.make_page(Some(parent_id), nd.columns, nd.gutter, nd.margins)).collect(); + d.spreads = vec![Arc::new(Spread { id: SpreadId(d.alloc()), pages, items: vec![], parent: None, allow_shuffle: true })]; + d.repaginate(); + d + } + + fn make_page(&mut self, parent: Option, columns: u32, gutter: f64, margins: Margins) -> Page { + Page { + id: PageId(self.alloc()), + width: self.settings.page_width, + height: self.settings.page_height, + x: 0.0, + margins, + columns: Columns { count: columns.max(1), gutter, positions: None }, + parent, + side: PageSide::Single, + overridden: vec![], + guides: vec![], + show_parent_items: true, + } + } + + /// Add a parent spread (`prefix`-`name`) and return its id. + pub fn add_parent(&mut self, prefix: &str, name: &str, columns: u32, gutter: f64, margins: Margins) -> SpreadId { + let n = if self.settings.facing_pages { 2 } else { 1 }; + let mut pages: Vec = (0..n).map(|_| self.make_page(None, columns, gutter, margins)).collect(); + if n == 2 { + pages[0].side = PageSide::Left; + pages[1].side = PageSide::Right; + } + let id = SpreadId(self.alloc()); + let mut sp = Spread { id, pages, items: vec![], parent: Some(ParentInfo { prefix: prefix.into(), name: name.into(), based_on: None }), allow_shuffle: true }; + sp.relayout(); + self.parents.push(Arc::new(sp)); + id + } + + pub fn parent_index(&self, id: SpreadId) -> Option { + self.parents.iter().position(|p| p.id == id) + } + + /// The next free parent prefix (A, B, C…). + pub fn next_parent_prefix(&self) -> String { + for c in 'A'..='Z' { + let s = c.to_string(); + if !self.parents.iter().any(|p| p.parent.as_ref().is_some_and(|i| i.prefix == s)) { + return s; + } + } + format!("P{}", self.parents.len() + 1) + } + + /// Redistribute document pages into spreads (facing: page 1 alone on the right, then pairs). + /// Items move with the page their centre is on. Spreads with `allow_shuffle == false` are kept. + pub fn repaginate(&mut self) { + // Collect pages with their items (items in page-relative coordinates). + let mut pages: Vec<(Page, Vec>)> = Vec::new(); + let mut kept: Vec<(usize, Arc)> = Vec::new(); + for sp in self.spreads.drain(..) { + if !sp.allow_shuffle && sp.pages.len() > 1 { + kept.push((pages.len(), sp)); + continue; + } + let mut sp = Arc::unwrap_or_clone(sp); + let mut per: Vec>> = vec![Vec::new(); sp.pages.len()]; + for it in std::mem::take(&mut sp.items) { + let cx = it.bounds().center().x; + let pi = sp.page_at_x(cx).unwrap_or(0); + let dx = sp.pages[pi].x; + let mut it = Arc::unwrap_or_clone(it); + it.xf = Affine::translate((-dx, 0.0)) * it.xf; + per[pi].push(Arc::new(it)); + } + for (p, items) in sp.pages.into_iter().zip(per) { + pages.push((p, items)); + } + } + let facing = self.settings.facing_pages; + let mut spreads: Vec = Vec::new(); + let mut cur: Vec<(Page, Vec>)> = Vec::new(); + let total = pages.len(); + let flush = |cur: &mut Vec<(Page, Vec>)>, spreads: &mut Vec, id: SpreadId| { + if cur.is_empty() { + return; + } + let mut sp = Spread { id, pages: vec![], items: vec![], parent: None, allow_shuffle: true }; + let mut x = 0.0; + let n = cur.len(); + for (i, (mut p, items)) in cur.drain(..).enumerate() { + p.side = if !facing { + PageSide::Single + } else if n == 1 { + // Lone page: right if odd page number position, decided by caller via side preset. + p.side + } else if i == 0 { + PageSide::Left + } else { + PageSide::Right + }; + p.x = x; + for it in items { + let mut it = Arc::unwrap_or_clone(it); + it.xf = Affine::translate((x, 0.0)) * it.xf; + sp.items.push(Arc::new(it)); + } + x += p.width; + sp.pages.push(p); + } + spreads.push(sp); + }; + for (i, (mut p, items)) in pages.into_iter().enumerate() { + if facing { + // Page i (0-based) is a right page when i is even (page 1, 3, 5 …). + p.side = if i % 2 == 0 { PageSide::Right } else { PageSide::Left }; + if p.side == PageSide::Left && !cur.is_empty() { + let id = SpreadId(self.alloc()); + flush(&mut cur, &mut spreads, id); + } + cur.push((p, items)); + if cur.len() == 2 || i + 1 == total { + let id = SpreadId(self.alloc()); + flush(&mut cur, &mut spreads, id); + } + } else { + cur.push((p, items)); + let id = SpreadId(self.alloc()); + flush(&mut cur, &mut spreads, id); + } + } + let mut out: Vec> = spreads.into_iter().map(Arc::new).collect(); + // Re-insert kept (non-shuffling) spreads at roughly their old page positions. + for (page_pos, sp) in kept.into_iter().rev() { + let mut n = 0; + let mut at = out.len(); + for (i, s) in out.iter().enumerate() { + if n >= page_pos { + at = i; + break; + } + n += s.pages.len(); + } + out.insert(at, sp); + } + self.spreads = out; + } + + /// Insert `count` pages after absolute page `after` (None = at the start), using `parent`. + pub fn insert_pages(&mut self, after: Option, count: usize, parent: Option) -> Result> { + if count == 0 { + return Ok(vec![]); + } + let n = self.page_count(); + let at = after.map_or(0, |a| (a + 1).min(n)); + let template = self.page(at.saturating_sub(1).min(n.saturating_sub(1))).cloned(); + let (cols, gutter, margins) = + template.as_ref().map(|t| (t.columns.count, t.columns.gutter, t.margins)).unwrap_or((1, 12.0, Margins::uniform(36.0))); + let mut ids = Vec::new(); + let new_pages: Vec = (0..count) + .map(|_| { + let mut p = self.make_page(parent, cols, gutter, margins); + if let Some(t) = &template { + p.width = t.width; + p.height = t.height; + } + ids.push(p.id); + p + }) + .collect(); + // Splice into the spread holding page `at` (or append a new spread), then repaginate. + match self.page_loc(at) { + Some((si, pi)) => { + let sp = Arc::make_mut(&mut self.spreads[si]); + let x = sp.pages[pi].x; + let w: f64 = new_pages.iter().map(|p| p.width).sum(); + // Shift items right of the insertion point. + for it in &mut sp.items { + if it.bounds().center().x >= x { + let it = Arc::make_mut(it); + it.xf = Affine::translate((w, 0.0)) * it.xf; + } + } + for (k, p) in new_pages.into_iter().enumerate() { + sp.pages.insert(pi + k, p); + } + sp.relayout(); + } + None => { + let id = SpreadId(self.alloc()); + let mut sp = Spread { id, pages: new_pages, items: vec![], parent: None, allow_shuffle: true }; + sp.relayout(); + self.spreads.push(Arc::new(sp)); + } + } + self.repaginate(); + Ok(ids) + } + + /// Delete absolute pages (items whose centre is on a deleted page are deleted too). + pub fn delete_pages(&mut self, pages: &[usize]) -> Result<()> { + if pages.len() >= self.page_count() { + return Err(DocError::Invalid("a document needs at least one page".into())); + } + let mut doomed: Vec<(usize, usize)> = pages.iter().filter_map(|p| self.page_loc(*p)).collect(); + doomed.sort(); + doomed.dedup(); + let mut remove_items: Vec = Vec::new(); + for &(si, pi) in &doomed { + let sp = &self.spreads[si]; + for it in &sp.items { + if sp.page_at_x(it.bounds().center().x) == Some(pi) { + remove_items.push(it.id); + } + } + } + for id in remove_items { + let _ = self.remove_item(id); + } + for &(si, pi) in doomed.iter().rev() { + let sp = Arc::make_mut(&mut self.spreads[si]); + let w = sp.pages[pi].width; + let x = sp.pages[pi].x; + sp.pages.remove(pi); + for it in &mut sp.items { + if it.bounds().center().x >= x + w { + let it = Arc::make_mut(it); + it.xf = Affine::translate((-w, 0.0)) * it.xf; + } + } + sp.relayout(); + } + self.spreads.retain(|s| !s.pages.is_empty()); + self.repaginate(); + Ok(()) + } + + /// Move absolute page `from` so it ends up at index `to` (items travel with it). + pub fn move_page(&mut self, from: usize, to: usize) -> Result<()> { + let n = self.page_count(); + if from >= n || to >= n { + return Err(DocError::NoPage(from.max(to))); + } + if from == to { + return Ok(()); + } + // Flatten to single-page spreads, reorder, repaginate. + let facing = self.settings.facing_pages; + self.settings.facing_pages = false; + self.repaginate(); + let sp = self.spreads.remove(from); + self.spreads.insert(to, sp); + self.settings.facing_pages = facing; + self.repaginate(); + Ok(()) + } + + /// Apply a parent (None = [None]) to absolute pages. + pub fn apply_parent(&mut self, pages: &[usize], parent: Option) -> Result<()> { + if let Some(p) = parent + && self.parent_index(p).is_none() + { + return Err(DocError::Invalid(format!("no parent {p}"))); + } + for &abs in pages { + let (si, pi) = self.page_loc(abs).ok_or(DocError::NoPage(abs))?; + Arc::make_mut(&mut self.spreads[si]).pages[pi].parent = parent; + } + Ok(()) + } + + /// Parent page (spread index, page index) to show behind document page `abs`. + pub fn parent_page_for(&self, abs: usize) -> Option<(usize, usize)> { + let page = self.page(abs)?; + let pi = self.parent_index(page.parent?)?; + let ps = &self.parents[pi]; + let idx = if ps.pages.len() >= 2 && page.side == PageSide::Left { 0 } else { ps.pages.len() - 1 }; + Some((pi, idx)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_facing_document_layout() { + let d = Document::new(&NewDocument { pages: 4, ..Default::default() }); + assert_eq!(d.page_count(), 4); + // [1] [2 3] [4] + assert_eq!(d.spreads.iter().map(|s| s.pages.len()).collect::>(), vec![1, 2, 1]); + assert_eq!(d.spreads[0].pages[0].side, PageSide::Right); + assert_eq!(d.spreads[1].pages[0].side, PageSide::Left); + assert_eq!(d.spreads[1].pages[1].x, 612.0); + assert_eq!(d.parents.len(), 1); + assert_eq!(d.parents[0].pages.len(), 2); + d.check().unwrap(); + } + + #[test] + fn non_facing_one_page_per_spread() { + let d = Document::new(&NewDocument { pages: 3, facing_pages: false, ..Default::default() }); + assert_eq!(d.spreads.len(), 3); + assert!(d.spreads.iter().all(|s| s.pages.len() == 1 && s.pages[0].side == PageSide::Single)); + } + + #[test] + fn insert_and_delete_pages_reshuffle() { + let mut d = Document::new(&NewDocument { pages: 1, ..Default::default() }); + d.insert_pages(Some(0), 3, d.parents.first().map(|p| p.id)).unwrap(); + assert_eq!(d.page_count(), 4); + assert_eq!(d.spreads.len(), 3); + d.delete_pages(&[1, 2]).unwrap(); + assert_eq!(d.page_count(), 2); + assert_eq!(d.spreads.iter().map(|s| s.pages.len()).collect::>(), vec![1, 1]); + assert!(d.delete_pages(&[0, 1]).is_err()); + } + + #[test] + fn items_travel_with_pages() { + let mut d = Document::new(&NewDocument { pages: 3, ..Default::default() }); + // Put a frame on page 3 (spread 1, page index 1). + let lid = d.default_layer(); + let r = designcraft_geom::Rect::new(612.0 + 100.0, 100.0, 612.0 + 200.0, 200.0); + let (id, _) = d.add_text_frame(crate::SpreadRef::Doc(1), r, lid, "hello", Default::default()).unwrap(); + d.move_page(2, 0).unwrap(); + // The frame's page is now page 1 (spread 0, single right page at x=0). + let loc = d.find(id).unwrap(); + assert_eq!(loc.spread, crate::SpreadRef::Doc(0)); + let b = d.item(id).unwrap().bounds(); + assert!((b.x0 - 100.0).abs() < 1e-9, "{b:?}"); + d.check().unwrap(); + } + + #[test] + fn presets_and_parents() { + let nd = NewDocument::from_preset("A4").unwrap(); + assert!((nd.width - 595.2756).abs() < 1e-3); + let mut d = Document::new(&nd); + assert_eq!(d.next_parent_prefix(), "B"); + let b = d.add_parent("B", "Parent", 2, 12.0, Margins::uniform(36.0)); + d.apply_parent(&[0], Some(b)).unwrap(); + assert_eq!(d.parent_page_for(0), Some((1, 1))); + d.apply_parent(&[0], None).unwrap(); + assert_eq!(d.parent_page_for(0), None); + } +} diff --git a/crates/doc/src/edit.rs b/crates/doc/src/edit.rs new file mode 100644 index 00000000..95f685ee --- /dev/null +++ b/crates/doc/src/edit.rs @@ -0,0 +1,371 @@ +//! Locating and editing items, threading, and story management. + +use std::sync::Arc; + +use designcraft_geom::{Point, Rect, shapes}; +use serde::{Deserialize, Serialize}; + +use crate::ids::{ItemId, LayerId, StoryId}; +use crate::item::{Content, Item, Shape, TextFrame, TextFrameOptions}; +use crate::page::Spread; +use crate::story::{CharRun, ParaFormat, Story}; +use crate::{DocError, Document, Result}; + +/// Which spread list an item lives in. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", tag = "kind", content = "index")] +pub enum SpreadRef { + Doc(usize), + Parent(usize), +} + +/// Indices from `spread.items` down through nested groups. +pub type ItemPath = Vec; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ItemLoc { + pub spread: SpreadRef, + pub path: ItemPath, +} + +impl ItemLoc { + /// Top-level index in the spread. + pub fn top(&self) -> usize { + self.path[0] + } +} + +fn find_in(items: &[Arc], id: ItemId, path: &mut ItemPath) -> bool { + for (i, it) in items.iter().enumerate() { + path.push(i); + if it.id == id || find_in(it.children(), id, path) { + return true; + } + path.pop(); + } + false +} + +impl Document { + pub fn spread(&self, r: SpreadRef) -> Option<&Spread> { + match r { + SpreadRef::Doc(i) => self.spreads.get(i).map(|s| &**s), + SpreadRef::Parent(i) => self.parents.get(i).map(|s| &**s), + } + } + + pub fn spread_mut(&mut self, r: SpreadRef) -> Option<&mut Spread> { + match r { + SpreadRef::Doc(i) => self.spreads.get_mut(i).map(Arc::make_mut), + SpreadRef::Parent(i) => self.parents.get_mut(i).map(Arc::make_mut), + } + } + + /// All spread refs: document spreads then parents. + pub fn spread_refs(&self) -> impl Iterator { + (0..self.spreads.len()).map(SpreadRef::Doc).chain((0..self.parents.len()).map(SpreadRef::Parent)) + } + + pub fn find(&self, id: ItemId) -> Option { + for r in self.spread_refs() { + let mut path = Vec::new(); + if find_in(&self.spread(r)?.items, id, &mut path) { + return Some(ItemLoc { spread: r, path }); + } + } + None + } + + pub fn item_at(&self, loc: &ItemLoc) -> Option<&Item> { + let sp = self.spread(loc.spread)?; + let mut it: &Item = sp.items.get(*loc.path.first()?)?; + for &i in &loc.path[1..] { + it = it.children().get(i)?; + } + Some(it) + } + + pub fn item(&self, id: ItemId) -> Option<&Item> { + self.item_at(&self.find(id)?) + } + + pub fn item_mut_at(&mut self, loc: &ItemLoc) -> Option<&mut Item> { + let sp = self.spread_mut(loc.spread)?; + let mut it: &mut Item = Arc::make_mut(sp.items.get_mut(*loc.path.first()?)?); + for &i in &loc.path[1..] { + it = Arc::make_mut(it.children_mut()?.get_mut(i)?); + } + Some(it) + } + + pub fn item_mut(&mut self, id: ItemId) -> Option<&mut Item> { + let loc = self.find(id)?; + self.item_mut_at(&loc) + } + + /// The top-level item (group root) containing `id`. + pub fn top_level_of(&self, id: ItemId) -> Option { + let loc = self.find(id)?; + Some(self.spread(loc.spread)?.items[loc.top()].id) + } + + /// Spread-space transform of the parent group chain of the item at `loc` (identity at top level). + pub fn parent_xf(&self, loc: &ItemLoc) -> designcraft_geom::Affine { + let mut xf = designcraft_geom::Affine::IDENTITY; + if let Some(sp) = self.spread(loc.spread) { + let mut items = &sp.items; + for &i in &loc.path[..loc.path.len().saturating_sub(1)] { + let it = &items[i]; + xf *= it.xf; + items = match &it.content { + Content::Group { items } => items, + _ => break, + }; + } + } + xf + } + + /// Insert an item into a spread at `index` (None = front). + pub fn insert_item(&mut self, r: SpreadRef, item: Item, index: Option) -> Result { + let id = item.id; + let sp = self.spread_mut(r).ok_or_else(|| DocError::Invalid(format!("no spread {r:?}")))?; + let i = index.unwrap_or(sp.items.len()).min(sp.items.len()); + sp.items.insert(i, Arc::new(item)); + Ok(id) + } + + /// Remove an item (and its descendants) from the document. Text frames leave their threads; + /// stories that lose their last frame are deleted. + pub fn remove_item(&mut self, id: ItemId) -> Result> { + let loc = self.find(id).ok_or(DocError::NoItem(id))?; + let removed = { + let sp = self.spread_mut(loc.spread).ok_or(DocError::NoItem(id))?; + if loc.path.len() == 1 { + sp.items.remove(loc.path[0]) + } else { + let mut it: &mut Item = Arc::make_mut(&mut sp.items[loc.path[0]]); + for &i in &loc.path[1..loc.path.len() - 1] { + it = Arc::make_mut(&mut it.children_mut().ok_or(DocError::NoItem(id))?[i]); + } + it.children_mut().ok_or(DocError::NoItem(id))?.remove(*loc.path.last().expect("non-empty")) + } + }; + let mut frames = Vec::new(); + removed.walk(&mut |i| { + if let Some(t) = i.text_frame() { + frames.push((i.id, t.story)); + } + }); + for (fid, sid) in frames { + let empty = { + let st = self.story_mut(sid).ok_or(DocError::NoStory(sid))?; + st.frames.retain(|f| *f != fid); + st.frames.is_empty() + }; + if empty { + self.stories.remove(&sid); + } + } + Ok(removed) + } + + /// Create a text frame with a new (or given) story at `rect` on spread `r`. + pub fn add_text_frame(&mut self, r: SpreadRef, rect: Rect, layer: LayerId, text: &str, para: ParaFormat) -> Result<(ItemId, StoryId)> { + let id = ItemId(self.alloc()); + let sid = StoryId(self.alloc()); + let mut story = Story::with_text(sid, text, para); + story.frames.push(id); + self.stories.insert(sid, Arc::new(story)); + let mut item = Item::new(id, layer, Shape::Rectangle, shapes::rectangle(rect)); + item.object_style = self.styles.default_text_frame.clone(); + if let Some(os) = self.styles.object_style(&self.styles.default_text_frame).cloned() { + if let Some(f) = os.fill { + item.fill = f; + } + if let Some(s) = os.stroke { + item.stroke = s; + } + } + item.content = Content::Text(TextFrame { story: sid, options: TextFrameOptions::default() }); + self.insert_item(r, item, None)?; + Ok((id, sid)) + } + + /// Thread `from` → `to`: `to` joins `from`'s story right after `from`. If `to` held its own text, + /// that text is appended to the story (as a new paragraph) and its old story is removed. + pub fn thread(&mut self, from: ItemId, to: ItemId) -> Result<()> { + if from == to { + return Err(DocError::Invalid("cannot thread a frame to itself".into())); + } + let fs = self.item(from).and_then(|i| i.text_frame()).map(|t| t.story).ok_or(DocError::NoItem(from))?; + // Convert unassigned/graphic-less frames into text frames. + let ts = match self.item(to).ok_or(DocError::NoItem(to))?.content.clone() { + Content::Text(t) => Some(t.story), + Content::Unassigned => None, + _ => return Err(DocError::Invalid("can only thread to text or empty frames".into())), + }; + if ts == Some(fs) { + return Err(DocError::Invalid("frames are already in the same story".into())); + } + if let Some(ts) = ts { + let other = self.stories.remove(&ts).ok_or(DocError::NoStory(ts))?; + let other = Arc::unwrap_or_clone(other); + // Frames of the other story after `to` follow along; frames before it are left as empty new stories. + let pos_to = other.frames.iter().position(|f| *f == to).unwrap_or(0); + let before: Vec = other.frames[..pos_to].to_vec(); + let after: Vec = other.frames[pos_to..].to_vec(); + { + let st = self.story_mut(fs).ok_or(DocError::NoStory(fs))?; + if !other.text.is_empty() { + st.text.push('\n'); + st.text.push_str(&other.text); + st.paras.extend(other.paras.iter().cloned()); + // Char runs: '\n' takes the last run's format, then the other story's runs. + if let Some(last) = st.chars.last_mut() { + last.len += 1; + } + st.chars.extend(other.chars.iter().filter(|r| r.len > 0).cloned()); + st.rev += 1; + } + let at = st.frames.iter().position(|f| *f == from).map_or(st.frames.len(), |p| p + 1); + for (k, f) in after.iter().enumerate() { + st.frames.insert(at + k, *f); + } + } + for f in &after { + if let Some(t) = self.item_mut(*f).and_then(Item::text_frame_mut) { + t.story = fs; + } + } + if !before.is_empty() { + let nid = StoryId(self.alloc()); + let mut ns = Story::new(nid); + ns.frames = before.clone(); + for f in &before { + if let Some(t) = self.item_mut(*f).and_then(Item::text_frame_mut) { + t.story = nid; + } + } + self.stories.insert(nid, Arc::new(ns)); + } + } else { + let st = self.story_mut(fs).ok_or(DocError::NoStory(fs))?; + let at = st.frames.iter().position(|f| *f == from).map_or(st.frames.len(), |p| p + 1); + st.frames.insert(at, to); + let it = self.item_mut(to).ok_or(DocError::NoItem(to))?; + it.content = Content::Text(TextFrame { story: fs, options: TextFrameOptions::default() }); + } + if let Some(st) = self.story_mut(fs) { + st.rev += 1; + } + Ok(()) + } + + /// Break the thread after `frame`: the following frames become a new empty story (the text + /// stays with the first part and may become overset). + pub fn unthread_after(&mut self, frame: ItemId) -> Result<()> { + let sid = self.item(frame).and_then(|i| i.text_frame()).map(|t| t.story).ok_or(DocError::NoItem(frame))?; + let tail = { + let st = self.story_mut(sid).ok_or(DocError::NoStory(sid))?; + let p = st.frames.iter().position(|f| *f == frame).ok_or(DocError::NoItem(frame))?; + let tail = st.frames.split_off(p + 1); + st.rev += 1; + tail + }; + if tail.is_empty() { + return Ok(()); + } + let nid = StoryId(self.alloc()); + let mut ns = Story::new(nid); + ns.frames = tail.clone(); + self.stories.insert(nid, Arc::new(ns)); + for f in tail { + if let Some(t) = self.item_mut(f).and_then(Item::text_frame_mut) { + t.story = nid; + } + } + Ok(()) + } + + /// Next / previous frame in a thread. + pub fn next_frame(&self, frame: ItemId) -> Option { + let st = self.story(self.item(frame)?.text_frame()?.story)?; + let p = st.frames.iter().position(|f| *f == frame)?; + st.frames.get(p + 1).copied() + } + pub fn prev_frame(&self, frame: ItemId) -> Option { + let st = self.story(self.item(frame)?.text_frame()?.story)?; + let p = st.frames.iter().position(|f| *f == frame)?; + p.checked_sub(1).map(|i| st.frames[i]) + } + + /// Hit test: the frontmost visible, unlocked-layer item on spread `si` containing `p` (spread space). + /// Frames hit by area if they have a fill or are text/graphic frames; otherwise near the outline. + pub fn hit_item(&self, si: usize, p: Point, tol: f64) -> Option { + let sp = self.spreads.get(si)?; + let mut items: Vec<&Arc> = sp.items.iter().collect(); + items.sort_by_key(|i| self.layer_rank(i.layer)); + for it in items.into_iter().rev() { + let layer = self.layer(it.layer); + if it.hidden || layer.is_some_and(|l| !l.visible || l.locked) { + continue; + } + if item_hit(it, p, tol) { + return Some(it.id); + } + } + None + } + + /// Every item id (pre-order) on document spreads. + pub fn all_items(&self) -> Vec { + let mut v = Vec::new(); + for sp in &self.spreads { + for it in &sp.items { + it.walk(&mut |i| v.push(i.id)); + } + } + v + } + + /// Plain story text with frame/story stats (for agents). + pub fn story_summary(&self, sid: StoryId) -> Option { + let st = self.story(sid)?; + Some(serde_json::json!({ + "id": sid.0, + "length": st.text.len(), + "paragraphs": st.paras.len(), + "frames": st.frames.iter().map(|f| f.0).collect::>(), + "text": st.text, + })) + } + + /// Replace a story's text and formatting wholesale (agents / import). + pub fn set_story_text(&mut self, sid: StoryId, text: &str) -> Result<()> { + let st = self.story_mut(sid).ok_or(DocError::NoStory(sid))?; + let para = st.paras.first().cloned().unwrap_or_default(); + let fmt = st.chars.first().map(|r| r.format.clone()).unwrap_or_default(); + let n = text.matches('\n').count() + 1; + st.text = text.to_string(); + st.paras = vec![para; n]; + st.chars = vec![CharRun { len: text.len(), format: fmt }]; + st.rev += 1; + Ok(()) + } +} + +/// Does `p` (in the item's parent space) hit `it`? +pub fn item_hit(it: &Item, p: Point, tol: f64) -> bool { + if let Content::Group { items } = &it.content { + let inner = it.xf.inverse() * p; + return items.iter().any(|c| item_hit(c, inner, tol)); + } + let inner = it.xf.inverse() * p; + let bp = it.path.to_bezpath(); + let area = !it.fill.is_none() || matches!(it.content, Content::Text(_) | Content::Graphic(_)) || it.path.is_closed() && it.shape != Shape::Path; + if area && it.path.is_closed() && designcraft_geom::hit::fill_contains(&bp, designcraft_geom::FillRule::NonZero, inner) { + return true; + } + designcraft_geom::hit::stroke_contains(&bp, it.stroke.weight.max(1.0), tol, inner) +} diff --git a/crates/doc/src/item.rs b/crates/doc/src/item.rs new file mode 100644 index 00000000..749cc8e3 --- /dev/null +++ b/crates/doc/src/item.rs @@ -0,0 +1,599 @@ +//! Page items: frames (text / graphic / unassigned), paths, lines and groups. + +use std::sync::Arc; + +use designcraft_color::BlendMode; +use designcraft_geom::corners::CornerOptions; +use designcraft_geom::{Affine, PathData, Point, Rect}; +use serde::{Deserialize, Serialize}; + +use crate::ids::{AssetId, ItemId, LayerId, StoryId}; + +/// Fill: a swatch reference and tint (InDesign fills always go through swatches or unnamed colours). +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct Fill { + pub swatch: String, + pub tint: f32, + /// Gradient angle (degrees) and length override for gradient swatches (`None` = fit to bounds). + #[serde(skip_serializing_if = "Option::is_none")] + pub gradient_angle: Option, + pub overprint: bool, +} + +impl Default for Fill { + fn default() -> Self { + Fill::none() + } +} + +impl Fill { + pub fn none() -> Self { + Fill { swatch: designcraft_color::swatch::NONE.into(), tint: 1.0, gradient_angle: None, overprint: false } + } + pub fn swatch(name: &str) -> Self { + Fill { swatch: name.into(), ..Fill::none() } + } + pub fn is_none(&self) -> bool { + self.swatch == designcraft_color::swatch::NONE + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum StrokeAlign { + #[default] + Center, + Inside, + Outside, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Cap { + #[default] + Butt, + Round, + Projecting, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Join { + #[default] + Miter, + Round, + Bevel, +} + +/// Stroke types (Stroke panel → Type). Dash/gap arrays are in points. +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", tag = "kind")] +pub enum StrokeType { + #[default] + Solid, + Dashed { + pattern: Vec, + }, + Dotted, + ThickThin, + ThinThick, + ThinThin, + ThickThick, + ThinThickThin, + ThickThinThick, + Wavy, + Hashed, +} + +impl StrokeType { + pub fn label(&self) -> &'static str { + match self { + StrokeType::Solid => "Solid", + StrokeType::Dashed { .. } => "Dashed", + StrokeType::Dotted => "Dotted", + StrokeType::ThickThin => "Thick - Thin", + StrokeType::ThinThick => "Thin - Thick", + StrokeType::ThinThin => "Thin - Thin", + StrokeType::ThickThick => "Thick - Thick", + StrokeType::ThinThickThin => "Thin - Thick - Thin", + StrokeType::ThickThinThick => "Thick - Thin - Thick", + StrokeType::Wavy => "Wavy", + StrokeType::Hashed => "Straight Hash", + } + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Arrowhead { + #[default] + None, + SimpleWide, + Simple, + Triangle, + TriangleWide, + Barbed, + Curved, + Circle, + CircleSolid, + Square, + SquareSolid, + Bar, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct Stroke { + pub swatch: String, + pub tint: f32, + pub weight: f64, + #[serde(rename = "type")] + pub kind: StrokeType, + pub align: StrokeAlign, + pub cap: Cap, + pub join: Join, + pub miter_limit: f64, + pub start: Arrowhead, + pub end: Arrowhead, + /// Gap colour for dashed/striped strokes. + pub gap_swatch: String, + pub gap_tint: f32, + pub overprint: bool, +} + +impl Default for Stroke { + /// InDesign's default for drawn shapes: 1 pt black. + fn default() -> Self { + Stroke { + swatch: designcraft_color::swatch::BLACK.into(), + tint: 1.0, + weight: 1.0, + kind: StrokeType::Solid, + align: StrokeAlign::Center, + cap: Cap::Butt, + join: Join::Miter, + miter_limit: 4.0, + start: Arrowhead::None, + end: Arrowhead::None, + gap_swatch: designcraft_color::swatch::NONE.into(), + gap_tint: 1.0, + overprint: false, + } + } +} + +impl Stroke { + pub fn none() -> Self { + Stroke { swatch: designcraft_color::swatch::NONE.into(), ..Stroke::default() } + } + pub fn is_none(&self) -> bool { + self.swatch == designcraft_color::swatch::NONE || self.weight <= 0.0 + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum VerticalJustification { + #[default] + Top, + Center, + Bottom, + Justify, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum FirstBaseline { + #[default] + Ascent, + CapHeight, + Leading, + XHeight, + Fixed, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum AutoSize { + #[default] + Off, + HeightOnly, + WidthOnly, + HeightAndWidth, + HeightAndWidthProportionally, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum ColumnsKind { + #[default] + FixedNumber, + FixedWidth, + FlexibleWidth, +} + +/// Text Frame Options. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct TextFrameOptions { + pub columns: u32, + pub columns_kind: ColumnsKind, + pub gutter: f64, + /// Column width for fixed/flexible width columns. + pub column_width: f64, + pub balance_columns: bool, + /// Inset spacing: top, left, bottom, right. + pub inset: [f64; 4], + pub vertical_justification: VerticalJustification, + pub vj_paragraph_spacing_limit: f64, + pub first_baseline: FirstBaseline, + pub first_baseline_min: f64, + pub ignore_wrap: bool, + pub auto_size: AutoSize, + /// Reference point (0..9) that stays fixed when auto-sizing. + pub auto_size_ref: u8, + pub column_rule: bool, + pub column_rule_weight: f64, + pub column_rule_color: String, + /// Use a custom baseline grid for this frame. + #[serde(skip_serializing_if = "Option::is_none")] + pub baseline_grid: Option<(f64, f64)>, +} + +impl Default for TextFrameOptions { + fn default() -> Self { + TextFrameOptions { + columns: 1, + columns_kind: ColumnsKind::FixedNumber, + gutter: 12.0, + column_width: 0.0, + balance_columns: false, + inset: [0.0; 4], + vertical_justification: VerticalJustification::Top, + vj_paragraph_spacing_limit: 0.0, + first_baseline: FirstBaseline::Ascent, + first_baseline_min: 0.0, + ignore_wrap: false, + auto_size: AutoSize::Off, + auto_size_ref: 1, + column_rule: false, + column_rule_weight: 1.0, + column_rule_color: designcraft_color::swatch::BLACK.into(), + baseline_grid: None, + } + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum WrapMode { + #[default] + None, + BoundingBox, + Contour, + JumpObject, + JumpToNextColumn, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum WrapSide { + #[default] + BothSides, + RightSide, + LeftSide, + TowardsSpine, + AwayFromSpine, + LargestArea, +} + +/// Text Wrap panel settings. +#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct TextWrap { + pub mode: WrapMode, + /// Top, left, bottom, right offsets. + pub offsets: [f64; 4], + pub invert: bool, + pub side: WrapSide, +} + +/// Frame fitting options (Object → Fitting → Frame Fitting Options). +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Fitting { + #[default] + None, + FillProportionally, + FitProportionally, + FitContentToFrame, + CenterContent, +} + +/// A placed graphic inside a frame. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Graphic { + pub asset: AssetId, + /// Natural size of the graphic in points (pixels at its resolution, or PDF page size). + pub size: (f64, f64), + /// Graphic space (0,0)-(w,h) → frame inner space. + pub xf: Affine, + #[serde(default)] + pub auto_fit: Fitting, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TextFrame { + pub story: StoryId, + #[serde(default)] + pub options: TextFrameOptions, +} + +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", tag = "type")] +pub enum Content { + #[default] + Unassigned, + Text(TextFrame), + Graphic(Graphic), + Group { + items: Vec>, + }, +} + +/// What kind of spline the item was drawn as (labels in the Layers panel, tool behaviours). +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Shape { + #[default] + Rectangle, + Oval, + Polygon, + GraphicLine, + Path, + Group, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct DropShadow { + pub on: bool, + pub color: String, + pub opacity: f32, + pub angle: f64, + pub distance: f64, + pub size: f64, + pub spread: f64, +} + +impl Default for DropShadow { + fn default() -> Self { + DropShadow { on: false, color: designcraft_color::swatch::BLACK.into(), opacity: 0.75, angle: 135.0, distance: 7.0, size: 5.0, spread: 0.0 } + } +} + +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct Effects { + pub drop_shadow: DropShadow, + /// Basic feather width (0 = off). + pub feather: f64, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Item { + pub id: ItemId, + #[serde(default, skip_serializing_if = "String::is_empty")] + pub name: String, + pub layer: LayerId, + #[serde(default)] + pub shape: Shape, + /// Geometry in the item's inner coordinate space. + pub path: PathData, + /// Inner space → spread space. + #[serde(default = "identity")] + pub xf: Affine, + #[serde(default)] + pub fill: Fill, + #[serde(default = "Stroke::none")] + pub stroke: Stroke, + #[serde(default)] + pub corners: CornerOptions, + #[serde(default = "one")] + pub opacity: f32, + #[serde(default)] + pub blend: BlendMode, + #[serde(default)] + pub effects: Effects, + #[serde(default)] + pub wrap: TextWrap, + #[serde(default)] + pub locked: bool, + #[serde(default)] + pub hidden: bool, + #[serde(default)] + pub nonprinting: bool, + #[serde(default)] + pub object_style: String, + #[serde(default)] + pub content: Content, + /// For items on a document page that override a parent-page item. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub overrides: Option, +} + +fn identity() -> Affine { + Affine::IDENTITY +} +fn one() -> f32 { + 1.0 +} + +impl Item { + pub fn new(id: ItemId, layer: LayerId, shape: Shape, path: PathData) -> Self { + Item { + id, + name: String::new(), + layer, + shape, + path, + xf: Affine::IDENTITY, + fill: Fill::none(), + stroke: Stroke::none(), + corners: CornerOptions::default(), + opacity: 1.0, + blend: BlendMode::default(), + effects: Effects::default(), + wrap: TextWrap::default(), + locked: false, + hidden: false, + nonprinting: false, + object_style: crate::styles::NO_OBJECT_STYLE.into(), + content: Content::Unassigned, + overrides: None, + } + } + + pub fn is_text_frame(&self) -> bool { + matches!(self.content, Content::Text(_)) + } + pub fn text_frame(&self) -> Option<&TextFrame> { + match &self.content { + Content::Text(t) => Some(t), + _ => None, + } + } + pub fn text_frame_mut(&mut self) -> Option<&mut TextFrame> { + match &mut self.content { + Content::Text(t) => Some(t), + _ => None, + } + } + pub fn graphic(&self) -> Option<&Graphic> { + match &self.content { + Content::Graphic(g) => Some(g), + _ => None, + } + } + pub fn children(&self) -> &[Arc] { + match &self.content { + Content::Group { items } => items, + _ => &[], + } + } + pub fn children_mut(&mut self) -> Option<&mut Vec>> { + match &mut self.content { + Content::Group { items } => Some(items), + _ => None, + } + } + + /// Inner-space bounds of the path (the frame's "geometric bounds" before transform). + pub fn inner_bounds(&self) -> Rect { + self.path.bounds().unwrap_or(Rect::ZERO) + } + + /// Spread-space geometric bounds (axis-aligned box of the transformed path; groups: union). + pub fn bounds(&self) -> Rect { + if let Content::Group { items } = &self.content { + let mut r: Option = None; + for c in items { + let b = self.xf.transform_rect_bbox(c.bounds()); + r = Some(r.map_or(b, |r| r.union(b))); + } + return r.unwrap_or(Rect::ZERO); + } + self.path.transformed(self.xf).bounds().unwrap_or(Rect::ZERO) + } + + /// Visible bounds including stroke weight (approximate for inside/outside alignment). + pub fn visible_bounds(&self) -> Rect { + let b = self.bounds(); + if self.stroke.is_none() { + return b; + } + let w = match self.stroke.align { + StrokeAlign::Center => self.stroke.weight / 2.0, + StrokeAlign::Inside => 0.0, + StrokeAlign::Outside => self.stroke.weight, + }; + b.inflate(w, w) + } + + /// The frame's text area (inner space) after inset. + pub fn text_area(&self) -> Rect { + let r = self.inner_bounds(); + let inset = self.text_frame().map(|t| t.options.inset).unwrap_or([0.0; 4]); + Rect::new(r.x0 + inset[1], r.y0 + inset[0], (r.x1 - inset[3]).max(r.x0 + inset[1]), (r.y1 - inset[2]).max(r.y0 + inset[0])) + } + + /// Spread-space centre. + pub fn center(&self) -> Point { + self.bounds().center() + } + + /// The Layers-panel label: ``, the first words of a text frame, the placed file name… + pub fn default_label(&self) -> &'static str { + match (&self.content, self.shape) { + (Content::Group { .. }, _) => "", + (Content::Text(_), _) => "", + (Content::Graphic(_), _) => "", + (_, Shape::Rectangle) => "", + (_, Shape::Oval) => "", + (_, Shape::Polygon) => "", + (_, Shape::GraphicLine) => "", + (_, Shape::Path) | (_, Shape::Group) => "", + } + } + + /// Visit this item and descendants (pre-order). + pub fn walk<'a>(&'a self, f: &mut impl FnMut(&'a Item)) { + f(self); + for c in self.children() { + c.walk(f); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use designcraft_geom::shapes; + + #[test] + fn bounds_and_text_area() { + let mut it = Item::new(ItemId(1), LayerId(1), Shape::Rectangle, shapes::rectangle(Rect::new(0.0, 0.0, 100.0, 50.0))); + it.xf = Affine::translate((10.0, 20.0)); + assert_eq!(it.bounds(), Rect::new(10.0, 20.0, 110.0, 70.0)); + it.content = Content::Text(TextFrame { story: StoryId(2), options: TextFrameOptions { inset: [5.0, 6.0, 7.0, 8.0], ..Default::default() } }); + assert_eq!(it.text_area(), Rect::new(6.0, 5.0, 92.0, 43.0)); + it.stroke = Stroke { weight: 4.0, ..Stroke::default() }; + assert_eq!(it.visible_bounds(), Rect::new(8.0, 18.0, 112.0, 72.0)); + } + + #[test] + fn group_bounds_union_children() { + let a = Item::new(ItemId(1), LayerId(1), Shape::Rectangle, shapes::rectangle(Rect::new(0.0, 0.0, 10.0, 10.0))); + let b = Item::new(ItemId(2), LayerId(1), Shape::Rectangle, shapes::rectangle(Rect::new(20.0, 20.0, 30.0, 40.0))); + let mut g = Item::new(ItemId(3), LayerId(1), Shape::Group, PathData::default()); + g.content = Content::Group { items: vec![Arc::new(a), Arc::new(b)] }; + assert_eq!(g.bounds(), Rect::new(0.0, 0.0, 30.0, 40.0)); + let mut n = 0; + g.walk(&mut |_| n += 1); + assert_eq!(n, 3); + } + + #[test] + fn serde_roundtrip() { + let mut it = Item::new(ItemId(1), LayerId(1), Shape::Oval, shapes::ellipse(Rect::new(0.0, 0.0, 10.0, 10.0))); + it.fill = Fill::swatch("[Black]"); + it.content = Content::Text(TextFrame { story: StoryId(9), options: TextFrameOptions::default() }); + let s = serde_json::to_string(&it).unwrap(); + let back: Item = serde_json::from_str(&s).unwrap(); + assert_eq!(it, back); + } +} diff --git a/crates/doc/src/lib.rs b/crates/doc/src/lib.rs new file mode 100644 index 00000000..def4d380 --- /dev/null +++ b/crates/doc/src/lib.rs @@ -0,0 +1,387 @@ +//! The DesignCraft document model (pure data + serde). +//! +//! A [`Document`] holds spreads of pages, parent ("master") spreads, layers, stories, styles, +//! swatches, sections and embedded assets. Spreads, items and stories are `Arc`-shared so an +//! edit clones only what it touches and undo snapshots are O(1). +//! +//! Coordinates are points, y down. Each spread has its own space: pages sit side by side from +//! x = 0 with their tops at y = 0. Items live in spread space via `Item::xf`. +#![forbid(unsafe_code)] + +pub mod attrs; +pub mod build; +mod edit; +pub mod ids; +pub mod item; +pub mod page; +pub mod selection; +pub mod story; +pub mod styles; + +use std::collections::BTreeMap; +use std::sync::Arc; + +pub use attrs::*; +pub use designcraft_color as color; +pub use designcraft_geom as geom; +pub use edit::{ItemLoc, ItemPath, SpreadRef}; +pub use ids::*; +pub use item::*; +pub use page::*; +pub use selection::*; +pub use story::*; +pub use styles::*; + +use designcraft_color::Swatch; +use designcraft_geom::Unit; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, thiserror::Error, PartialEq)] +pub enum DocError { + #[error("no such item {0}")] + NoItem(ItemId), + #[error("no such story {0}")] + NoStory(StoryId), + #[error("no such page {0}")] + NoPage(usize), + #[error("no such layer {0}")] + NoLayer(LayerId), + #[error("{0}")] + Invalid(String), +} + +pub type Result = std::result::Result; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Intent { + #[default] + Print, + Web, + Mobile, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum GridRelative { + #[default] + TopOfPage, + TopMargin, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct BaselineGrid { + pub start: f64, + pub increment: f64, + pub relative_to: GridRelative, + pub color: [u8; 3], + /// Hidden below this zoom (1.0 = 100%). + pub view_threshold: f64, +} + +impl Default for BaselineGrid { + fn default() -> Self { + BaselineGrid { start: 36.0, increment: 12.0, relative_to: GridRelative::TopOfPage, color: [140, 205, 230], view_threshold: 0.75 } + } +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct DocumentGrid { + pub horizontal: f64, + pub vertical: f64, + pub subdivisions: u32, + pub color: [u8; 3], + pub in_back: bool, +} + +impl Default for DocumentGrid { + fn default() -> Self { + DocumentGrid { horizontal: 72.0, vertical: 72.0, subdivisions: 8, color: [200, 200, 200], in_back: true } + } +} + +/// File → Document Setup + the guide/grid/unit preferences stored with the document. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", default)] +pub struct DocSettings { + pub intent: Intent, + pub page_width: f64, + pub page_height: f64, + pub facing_pages: bool, + pub primary_text_frame: bool, + /// Bleed: top, bottom, inside, outside. + pub bleed: [f64; 4], + pub slug: [f64; 4], + pub horizontal_units: Unit, + pub vertical_units: Unit, + pub baseline_grid: BaselineGrid, + pub grid: DocumentGrid, + /// Pasteboard extent around spreads (horizontal, vertical). + pub pasteboard: (f64, f64), + pub margin_color: [u8; 3], + pub column_color: [u8; 3], + pub bleed_color: [u8; 3], + pub slug_color: [u8; 3], + pub keyboard_increment: f64, +} + +impl Default for DocSettings { + fn default() -> Self { + DocSettings { + intent: Intent::Print, + page_width: 612.0, + page_height: 792.0, + facing_pages: true, + primary_text_frame: false, + bleed: [0.0; 4], + slug: [0.0; 4], + horizontal_units: Unit::Picas, + vertical_units: Unit::Picas, + baseline_grid: BaselineGrid::default(), + grid: DocumentGrid::default(), + pasteboard: (72.0, 72.0), + margin_color: [255, 0, 255], + column_color: [148, 112, 255], + bleed_color: [255, 0, 0], + slug_color: [60, 120, 255], + keyboard_increment: 1.0, + } + } +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Layer { + pub id: LayerId, + pub name: String, + /// Selection / frame-edge colour. + pub color: [u8; 3], + #[serde(default = "yes")] + pub visible: bool, + #[serde(default)] + pub locked: bool, + #[serde(default = "yes")] + pub printable: bool, + #[serde(default = "yes")] + pub show_guides: bool, + #[serde(default)] + pub suppress_wrap_when_hidden: bool, +} + +fn yes() -> bool { + true +} + +/// InDesign's layer colour sequence (names are the conventional colour names). +pub const LAYER_COLORS: &[(&str, [u8; 3])] = &[ + ("Light Blue", [79, 153, 255]), + ("Red", [255, 0, 0]), + ("Green", [79, 255, 79]), + ("Blue", [0, 0, 255]), + ("Yellow", [255, 255, 79]), + ("Magenta", [255, 79, 255]), + ("Cyan", [0, 255, 255]), + ("Gray", [128, 128, 128]), + ("Black", [0, 0, 0]), + ("Orange", [255, 102, 0]), + ("Dark Green", [0, 84, 0]), + ("Teal", [0, 153, 153]), + ("Tan", [204, 153, 102]), + ("Brown", [153, 51, 0]), + ("Violet", [153, 51, 255]), + ("Gold", [255, 153, 0]), +]; + +/// An embedded file (placed image / PDF). Bytes are stored next to the JSON in the native format. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Asset { + pub id: AssetId, + pub name: String, + pub mime: String, + /// Original location on disk (Links panel), if linked. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub link: Option, + #[serde(skip)] + pub data: Arc>, + /// Pixel size for raster images. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub pixels: Option<(u32, u32)>, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Document { + pub title: String, + pub settings: DocSettings, + pub spreads: Vec>, + pub parents: Vec>, + /// Top of the list = frontmost layer (Layers panel order). + pub layers: Vec, + pub stories: BTreeMap>, + pub styles: Arc, + pub swatches: Vec, + pub sections: Vec
    , + #[serde(default)] + pub assets: BTreeMap>, + pub next_id: u64, +} + +impl Document { + /// Allocate a fresh id. + pub fn alloc(&mut self) -> u64 { + self.next_id += 1; + self.next_id + } + + pub fn page_count(&self) -> usize { + self.spreads.iter().map(|s| s.pages.len()).sum() + } + + /// (spread index, page index within spread) for an absolute page index. + pub fn page_loc(&self, abs: usize) -> Option<(usize, usize)> { + let mut n = 0; + for (si, s) in self.spreads.iter().enumerate() { + if abs < n + s.pages.len() { + return Some((si, abs - n)); + } + n += s.pages.len(); + } + None + } + + /// Absolute index of the first page of spread `si`. + pub fn first_page_of_spread(&self, si: usize) -> usize { + self.spreads[..si.min(self.spreads.len())].iter().map(|s| s.pages.len()).sum() + } + + pub fn page(&self, abs: usize) -> Option<&Page> { + let (s, p) = self.page_loc(abs)?; + self.spreads[s].pages.get(p) + } + + /// Iterate all pages with their absolute index and spread index. + pub fn pages(&self) -> impl Iterator { + self.spreads.iter().enumerate().flat_map(|(si, s)| s.pages.iter().map(move |p| (si, p))).enumerate().map(|(i, (si, p))| (i, si, p)) + } + + /// The displayed page name ("1", "iv", "A-3"…) for an absolute page index, per sections. + pub fn page_name(&self, abs: usize) -> String { + let mut sec: Option<&Section> = None; + for s in &self.sections { + if s.start <= abs && sec.is_none_or(|c| s.start >= c.start) { + sec = Some(s); + } + } + let Some(sec) = sec else { return (abs + 1).to_string() }; + // Numbers continue from the previous section when start_number is None. + let start_number = match sec.start_number { + Some(n) => n, + None => { + let prev: Vec<&Section> = self.sections.iter().filter(|s| s.start < sec.start).collect(); + if prev.is_empty() { + sec.start as u32 + 1 + } else { + // Approximate continuation: absolute position + 1. + sec.start as u32 + 1 + } + } + }; + let n = start_number + (abs - sec.start) as u32; + let num = sec.style.format(n); + if sec.include_prefix { format!("{}{}", sec.prefix, num) } else { num } + } + + pub fn layer(&self, id: LayerId) -> Option<&Layer> { + self.layers.iter().find(|l| l.id == id) + } + pub fn layer_mut(&mut self, id: LayerId) -> Option<&mut Layer> { + self.layers.iter_mut().find(|l| l.id == id) + } + /// Stacking rank of a layer: 0 = backmost. + pub fn layer_rank(&self, id: LayerId) -> usize { + self.layers.iter().position(|l| l.id == id).map(|i| self.layers.len() - 1 - i).unwrap_or(0) + } + pub fn default_layer(&self) -> LayerId { + self.layers.first().map(|l| l.id).unwrap_or_default() + } + + pub fn story(&self, id: StoryId) -> Option<&Story> { + self.stories.get(&id).map(|s| &**s) + } + pub fn story_mut(&mut self, id: StoryId) -> Option<&mut Story> { + self.stories.get_mut(&id).map(Arc::make_mut) + } + + pub fn swatch(&self, name: &str) -> Option<&Swatch> { + self.swatches.iter().find(|s| s.name == name) + } + + /// Resolve a swatch reference to a display colour. + pub fn resolve_color(&self, swatch: &str, tint: f32) -> Option { + designcraft_color::swatch::resolve(&self.swatches, swatch, tint) + } + + /// Validate structural invariants (ids unique, threads consistent, stories well-formed). + pub fn check(&self) -> Result<()> { + let mut ids = std::collections::HashSet::new(); + for sp in self.spreads.iter().chain(self.parents.iter()) { + for it in &sp.items { + let mut dup = None; + it.walk(&mut |i| { + if !ids.insert(i.id.0) { + dup = Some(i.id); + } + }); + if let Some(d) = dup { + return Err(DocError::Invalid(format!("duplicate item id {d}"))); + } + } + } + for (sid, st) in &self.stories { + st.check().map_err(DocError::Invalid)?; + if st.id != *sid { + return Err(DocError::Invalid(format!("story key {sid} != id {}", st.id))); + } + for f in &st.frames { + let item = self.find(*f).ok_or(DocError::NoItem(*f))?; + match self.item_at(&item).and_then(|i| i.text_frame().map(|t| t.story)) { + Some(s) if s == *sid => {} + other => return Err(DocError::Invalid(format!("frame {f} in story {sid} points at {other:?}"))), + } + } + } + // Every text frame is in its story's thread. + for sp in self.spreads.iter().chain(self.parents.iter()) { + for it in &sp.items { + let mut bad = None; + it.walk(&mut |i| { + if let Some(t) = i.text_frame() + && !self.stories.get(&t.story).is_some_and(|s| s.frames.contains(&i.id)) + { + bad = Some(i.id); + } + }); + if let Some(b) = bad { + return Err(DocError::Invalid(format!("text frame {b} not in its story's thread"))); + } + } + } + if self.next_id < ids.iter().copied().max().unwrap_or(0) { + return Err(DocError::Invalid("next_id behind existing ids".into())); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests; + +impl Document { + /// Mutable styles (copy-on-write). + pub fn styles_mut(&mut self) -> &mut Styles { + Arc::make_mut(&mut self.styles) + } +} diff --git a/crates/doc/src/page.rs b/crates/doc/src/page.rs new file mode 100644 index 00000000..3855104c --- /dev/null +++ b/crates/doc/src/page.rs @@ -0,0 +1,262 @@ +//! Spreads, pages, margins, columns, guides; parent ("master") spreads; sections. + +use std::sync::Arc; + +use designcraft_geom::Rect; +use serde::{Deserialize, Serialize}; + +use crate::attrs::NumberStyle; +use crate::ids::{ItemId, PageId, SpreadId}; +use crate::item::Item; + +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Margins { + pub top: f64, + pub bottom: f64, + /// Inside (facing pages) / left. + pub inside: f64, + /// Outside (facing pages) / right. + pub outside: f64, +} + +impl Margins { + pub fn uniform(v: f64) -> Self { + Margins { top: v, bottom: v, inside: v, outside: v } + } +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Columns { + pub count: u32, + pub gutter: f64, + /// Custom column positions (after dragging column guides); `None` = evenly spaced. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub positions: Option>, +} + +impl Default for Columns { + fn default() -> Self { + Columns { count: 1, gutter: 12.0, positions: None } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Orientation { + Horizontal, + Vertical, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Guide { + pub orientation: Orientation, + /// Spread coordinate (x for vertical guides, y for horizontal). + pub position: f64, + /// Spread guides cross the whole pasteboard; page guides only their page. + #[serde(default)] + pub spread: bool, + #[serde(default)] + pub locked: bool, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum PageSide { + #[default] + Single, + Left, + Right, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Page { + pub id: PageId, + pub width: f64, + pub height: f64, + /// Position of the page's left edge in spread coordinates (top is y = 0). + pub x: f64, + pub margins: Margins, + pub columns: Columns, + /// Applied parent spread (`None` = [None]). + #[serde(default, skip_serializing_if = "Option::is_none")] + pub parent: Option, + #[serde(default)] + pub side: PageSide, + /// Parent items overridden on this page (hidden from the parent rendering). + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub overridden: Vec, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub guides: Vec, + /// Show parent items on this page. + #[serde(default = "yes")] + pub show_parent_items: bool, +} + +fn yes() -> bool { + true +} + +impl Page { + pub fn bounds(&self) -> Rect { + Rect::new(self.x, 0.0, self.x + self.width, self.height) + } + /// Left and right margins resolved for the page side (inside is at the spine). + pub fn left_right_margins(&self) -> (f64, f64) { + match self.side { + PageSide::Left => (self.margins.outside, self.margins.inside), + _ => (self.margins.inside, self.margins.outside), + } + } + /// The live area inside the margins. + pub fn margin_rect(&self) -> Rect { + let (l, r) = self.left_right_margins(); + let b = self.bounds(); + Rect::new(b.x0 + l, b.y0 + self.margins.top, (b.x1 - r).max(b.x0 + l), (b.y1 - self.margins.bottom).max(b.y0 + self.margins.top)) + } + /// Column rects within the margins. + pub fn column_rects(&self) -> Vec { + let m = self.margin_rect(); + column_rects(m, self.columns.count.max(1), self.columns.gutter) + } +} + +/// Split `area` into `n` equal columns separated by `gutter`. +pub fn column_rects(area: Rect, n: u32, gutter: f64) -> Vec { + let n = n.max(1) as usize; + let w = ((area.width() - gutter * (n as f64 - 1.0)) / n as f64).max(0.0); + (0..n).map(|i| Rect::new(area.x0 + i as f64 * (w + gutter), area.y0, area.x0 + i as f64 * (w + gutter) + w, area.y1)).collect() +} + +/// Parent spread metadata. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ParentInfo { + /// `A`, `B`… + pub prefix: String, + /// `Parent`. + pub name: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub based_on: Option, +} + +impl ParentInfo { + pub fn label(&self) -> String { + format!("{}-{}", self.prefix, self.name) + } +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Spread { + pub id: SpreadId, + pub pages: Vec, + /// Items in z-order (last = front). Coordinates are spread space. + pub items: Vec>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub parent: Option, + #[serde(default = "yes")] + pub allow_shuffle: bool, +} + +impl Spread { + /// Union of the page rects. + pub fn bounds(&self) -> Rect { + self.pages.iter().map(Page::bounds).reduce(|a, b| a.union(b)).unwrap_or(Rect::ZERO) + } + /// x of the spine (between left and right pages) or the page centre for single pages. + pub fn spine_x(&self) -> f64 { + match self.pages.iter().position(|p| p.side == PageSide::Right) { + Some(i) => self.pages[i].x, + None => self.bounds().center().x, + } + } + /// Index of the page under spread x (nearest page for the pasteboard). + pub fn page_at_x(&self, x: f64) -> Option { + if self.pages.is_empty() { + return None; + } + self.pages + .iter() + .position(|p| x >= p.x && x < p.x + p.width) + .or_else(|| if x < self.pages[0].x { Some(0) } else { Some(self.pages.len() - 1) }) + } + /// Lay the pages out left to right with no gaps, starting at x = 0. + pub fn relayout(&mut self) { + let mut x = 0.0; + for p in &mut self.pages { + p.x = x; + x += p.width; + } + } +} + +/// A numbering section starting at a document page. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Section { + /// Absolute index of the first page of the section. + pub start: usize, + /// Start numbering at (None = continue from the previous section). + #[serde(default, skip_serializing_if = "Option::is_none")] + pub start_number: Option, + #[serde(default)] + pub style: NumberStyle, + #[serde(default, skip_serializing_if = "String::is_empty")] + pub prefix: String, + #[serde(default, skip_serializing_if = "String::is_empty")] + pub marker: String, + #[serde(default)] + pub include_prefix: bool, +} + +#[cfg(test)] +mod tests { + use super::*; + + fn page(side: PageSide, x: f64) -> Page { + Page { + id: PageId(1), + width: 612.0, + height: 792.0, + x, + margins: Margins { top: 36.0, bottom: 36.0, inside: 54.0, outside: 36.0 }, + columns: Columns { count: 2, gutter: 12.0, positions: None }, + parent: None, + side, + overridden: vec![], + guides: vec![], + show_parent_items: true, + } + } + + #[test] + fn margins_mirror_on_left_pages() { + let l = page(PageSide::Left, 0.0); + let r = page(PageSide::Right, 612.0); + assert_eq!(l.margin_rect(), Rect::new(36.0, 36.0, 558.0, 756.0)); + assert_eq!(r.margin_rect(), Rect::new(666.0, 36.0, 1188.0, 756.0)); + } + + #[test] + fn columns_divide_live_area() { + let p = page(PageSide::Single, 0.0); + let cols = p.column_rects(); + assert_eq!(cols.len(), 2); + let total: f64 = cols.iter().map(|c| c.width()).sum::() + 12.0; + assert!((total - p.margin_rect().width()).abs() < 1e-9); + assert!((cols[1].x0 - cols[0].x1 - 12.0).abs() < 1e-9); + } + + #[test] + fn spread_spine_and_hit() { + let s = Spread { id: SpreadId(1), pages: vec![page(PageSide::Left, 0.0), page(PageSide::Right, 612.0)], items: vec![], parent: None, allow_shuffle: true }; + assert_eq!(s.spine_x(), 612.0); + assert_eq!(s.page_at_x(700.0), Some(1)); + assert_eq!(s.page_at_x(-50.0), Some(0)); + assert_eq!(s.page_at_x(5000.0), Some(1)); + } +} diff --git a/crates/doc/src/selection.rs b/crates/doc/src/selection.rs new file mode 100644 index 00000000..1f31dfe7 --- /dev/null +++ b/crates/doc/src/selection.rs @@ -0,0 +1,65 @@ +//! What is selected: page items (containers or their content) or a text range in a story. + +use serde::{Deserialize, Serialize}; + +use crate::ids::{ItemId, StoryId}; + +/// A caret or text range in a story. `anchor` stays put while `focus` moves (Shift-arrows). +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TextSel { + pub story: StoryId, + pub anchor: usize, + pub focus: usize, + /// The frame the caret is shown in (for carets at frame boundaries). + #[serde(default, skip_serializing_if = "Option::is_none")] + pub frame: Option, +} + +impl TextSel { + pub fn caret(story: StoryId, pos: usize) -> Self { + TextSel { story, anchor: pos, focus: pos, frame: None } + } + pub fn range(&self) -> std::ops::Range { + self.anchor.min(self.focus)..self.anchor.max(self.focus) + } + pub fn is_caret(&self) -> bool { + self.anchor == self.focus + } +} + +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Selection { + /// Selected items (top-level or, with the Direct Selection tool, nested items). + pub items: Vec, + /// Content selection (graphic inside its frame) instead of the container. + #[serde(default)] + pub content: bool, + /// Direct selection: selected anchors as (item, subpath, anchor). + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub anchors: Vec<(ItemId, usize, usize)>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub text: Option, + /// Key object for Align. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub key: Option, +} + +impl Selection { + pub fn is_empty(&self) -> bool { + self.items.is_empty() && self.text.is_none() + } + pub fn len(&self) -> usize { + self.items.len() + } + pub fn items(ids: Vec) -> Self { + Selection { items: ids, ..Default::default() } + } + pub fn text(t: TextSel) -> Self { + Selection { text: Some(t), ..Default::default() } + } + pub fn contains(&self, id: ItemId) -> bool { + self.items.contains(&id) + } +} diff --git a/crates/doc/src/story.rs b/crates/doc/src/story.rs index 4b2a0297..de79ad82 100644 --- a/crates/doc/src/story.rs +++ b/crates/doc/src/story.rs @@ -211,7 +211,8 @@ impl Story { /// Apply `f` to the character format of every run intersecting `range` (splitting runs at the /// range boundaries). With an empty range nothing changes (callers set typing formats instead). pub fn format_chars(&mut self, range: std::ops::Range, mut f: impl FnMut(&mut CharFormat)) { - let (a, b) = (range.start.min(self.text.len()), range.end.min(self.text.len())); + let a = floor_char_boundary(&self.text, range.start); + let b = floor_char_boundary(&self.text, range.end); if a >= b { return; } diff --git a/crates/doc/src/tests.rs b/crates/doc/src/tests.rs new file mode 100644 index 00000000..d07804d9 --- /dev/null +++ b/crates/doc/src/tests.rs @@ -0,0 +1,85 @@ +use designcraft_geom::Rect; + +use super::*; +use crate::build::NewDocument; + +fn doc() -> Document { + Document::new(&NewDocument { pages: 2, ..Default::default() }) +} + +#[test] +fn threading_moves_frames_and_text() { + let mut d = doc(); + let lid = d.default_layer(); + let (a, sa) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "first", ParaFormat::default()).unwrap(); + let (b, sb) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(110.0, 10.0, 200.0, 100.0), lid, "second", ParaFormat::default()).unwrap(); + d.thread(a, b).unwrap(); + d.check().unwrap(); + assert!(d.story(sb).is_none()); + let st = d.story(sa).unwrap(); + assert_eq!(st.text, "first\nsecond"); + assert_eq!(st.frames, vec![a, b]); + assert_eq!(d.next_frame(a), Some(b)); + assert_eq!(d.prev_frame(b), Some(a)); + d.unthread_after(a).unwrap(); + d.check().unwrap(); + assert_eq!(d.story(sa).unwrap().frames, vec![a]); + assert_ne!(d.item(b).unwrap().text_frame().unwrap().story, sa); +} + +#[test] +fn thread_to_empty_frame_converts_it() { + let mut d = doc(); + let lid = d.default_layer(); + let (a, sa) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "x", ParaFormat::default()).unwrap(); + let id = ItemId(d.alloc()); + let it = Item::new(id, lid, Shape::Rectangle, designcraft_geom::shapes::rectangle(Rect::new(0.0, 200.0, 50.0, 300.0))); + d.insert_item(SpreadRef::Doc(0), it, None).unwrap(); + d.thread(a, id).unwrap(); + assert!(d.item(id).unwrap().is_text_frame()); + assert_eq!(d.story(sa).unwrap().frames, vec![a, id]); + d.check().unwrap(); + assert!(d.thread(a, a).is_err()); +} + +#[test] +fn removing_last_frame_deletes_story() { + let mut d = doc(); + let lid = d.default_layer(); + let (a, sa) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "x", ParaFormat::default()).unwrap(); + d.remove_item(a).unwrap(); + assert!(d.story(sa).is_none()); + d.check().unwrap(); +} + +#[test] +fn hit_testing_respects_layers() { + let mut d = doc(); + let lid = d.default_layer(); + let (a, _) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "x", ParaFormat::default()).unwrap(); + assert_eq!(d.hit_item(0, designcraft_geom::Point::new(50.0, 50.0), 2.0), Some(a)); + assert_eq!(d.hit_item(0, designcraft_geom::Point::new(300.0, 300.0), 2.0), None); + d.layer_mut(lid).unwrap().locked = true; + assert_eq!(d.hit_item(0, designcraft_geom::Point::new(50.0, 50.0), 2.0), None); +} + +#[test] +fn page_names_follow_sections() { + let mut d = Document::new(&NewDocument { pages: 6, ..Default::default() }); + assert_eq!(d.page_name(0), "1"); + d.sections.push(Section { start: 2, start_number: Some(1), style: NumberStyle::LowerRoman, prefix: "A-".into(), marker: String::new(), include_prefix: true }); + assert_eq!(d.page_name(1), "2"); + assert_eq!(d.page_name(2), "A-i"); + assert_eq!(d.page_name(4), "A-iii"); +} + +#[test] +fn document_serde_roundtrip() { + let mut d = doc(); + let lid = d.default_layer(); + d.add_text_frame(SpreadRef::Doc(0), Rect::new(10.0, 10.0, 100.0, 100.0), lid, "héllo\nworld", ParaFormat::default()).unwrap(); + let s = serde_json::to_string(&d).unwrap(); + let back: Document = serde_json::from_str(&s).unwrap(); + assert_eq!(d, back); + back.check().unwrap(); +} diff --git a/crates/fonts/Cargo.toml b/crates/fonts/Cargo.toml new file mode 100644 index 00000000..664ea1df --- /dev/null +++ b/crates/fonts/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "designcraft-fonts" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "DesignCraft fonts: font database (bundled OFL + system), metrics, glyph outlines, shaping" + +[lints] +workspace = true + +[dependencies] +kurbo = { workspace = true } +skrifa = { workspace = true } +harfrust = { workspace = true } +log = { workspace = true } diff --git a/crates/fonts/src/fontdb.rs b/crates/fonts/src/fontdb.rs new file mode 100644 index 00000000..28c1167d --- /dev/null +++ b/crates/fonts/src/fontdb.rs @@ -0,0 +1,558 @@ +//! Font database: bundled OFL fonts, user fonts, optional system font catalog, outline cache. + +use std::collections::HashMap; +use std::sync::atomic::{AtomicU32, Ordering}; +use std::sync::{Arc, Mutex, RwLock}; + +use kurbo::BezPath; +use skrifa::instance::{LocationRef, Size}; +use skrifa::outline::{DrawSettings, OutlinePen}; +use skrifa::raw::FileRef; +use skrifa::string::StringId; +use skrifa::{GlyphId, MetadataProvider}; + +/// The family used when a requested family is unknown (the UI sans). +pub const FALLBACK_FAMILY: &str = "Source Sans 3"; + +static BUNDLED: &[&[u8]] = &[ + include_bytes!("../../../assets/fonts/SourceSans3-Regular.ttf"), + include_bytes!("../../../assets/fonts/SourceSans3-Semibold.ttf"), + include_bytes!("../../../assets/fonts/SourceSans3-Bold.ttf"), + include_bytes!("../../../assets/fonts/SourceSans3-It.ttf"), + include_bytes!("../../../assets/fonts/SourceSerif4-Regular.ttf"), + include_bytes!("../../../assets/fonts/SourceSerif4-It.ttf"), + include_bytes!("../../../assets/fonts/SourceSerif4-Semibold.ttf"), + include_bytes!("../../../assets/fonts/SourceSerif4-Bold.ttf"), + include_bytes!("../../../assets/fonts/SourceSerif4-BoldIt.ttf"), + include_bytes!("../../../assets/fonts/Inter-Regular.ttf"), + include_bytes!("../../../assets/fonts/Inter-Medium.ttf"), + include_bytes!("../../../assets/fonts/Inter-SemiBold.ttf"), + include_bytes!("../../../assets/fonts/JetBrainsMono-Regular.ttf"), +]; + +enum FontBytes { + Static(&'static [u8]), + Owned(Arc>), +} + +/// One loaded font face. +pub struct FontFace { + id: u32, + /// Typographic family name (e.g. "Source Sans 3"). + pub family: String, + /// Typographic style name (e.g. "Semibold", "Italic"). + pub style: String, + /// usWeightClass-style weight (400 = regular). + pub weight: f32, + pub italic: bool, + bytes: FontBytes, + index: u32, + pub upem: f64, + /// Ascender in font units (positive = up). + pub ascent: f64, + /// Descender in font units (positive = down). + pub descent: f64, + /// Cap height and x height in font units (estimated from the ascent when the font has no OS/2 + /// values). + pub cap_height: f64, + pub x_height: f64, + pub shaper: harfrust::ShaperData, +} + +impl std::fmt::Debug for FontFace { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "FontFace({} {})", self.family, self.style) + } +} + +impl FontFace { + pub fn data(&self) -> &[u8] { + match &self.bytes { + FontBytes::Static(b) => b, + FontBytes::Owned(v) => v.as_slice(), + } + } + pub fn skrifa(&self) -> Option> { + skrifa::FontRef::from_index(self.data(), self.index).ok() + } + pub fn hb(&self) -> Option> { + harfrust::FontRef::from_index(self.data(), self.index).ok() + } + /// Unique id of this face within the process. + pub fn id(&self) -> u32 { + self.id + } + /// Does the face map `c` to a glyph? + pub fn covers(&self, c: char) -> bool { + self.skrifa().is_some_and(|f| f.charmap().map(c).is_some()) + } + /// Units per em. + pub fn units_per_em(&self) -> f64 { + self.upem + } + /// (ascent, descent) in font units, both positive. + pub fn vertical_metrics(&self) -> (f64, f64) { + (self.ascent, self.descent) + } + /// Every mapped character and its glyph id, sorted by code point (the Glyphs panel). + pub fn chars(&self) -> Vec<(char, u32)> { + let Some(f) = self.skrifa() else { return vec![] }; + let mut v: Vec<(char, u32)> = f.charmap().mappings().filter_map(|(cp, g)| char::from_u32(cp).map(|c| (c, g.to_u32()))).collect(); + v.sort_unstable_by_key(|x| x.0); + v.dedup_by_key(|x| x.0); + v + } + /// Advance width of glyph `gid` in font units. + pub fn advance(&self, gid: u32) -> f64 { + self.skrifa() + .and_then(|f| f.glyph_metrics(Size::unscaled(), LocationRef::default()).advance_width(GlyphId::new(gid))) + .map(|a| a as f64) + .unwrap_or(self.upem * 0.5) + } + /// Glyph id for `c` (0 = .notdef). + pub fn glyph_for(&self, c: char) -> u32 { + self.skrifa().and_then(|f| f.charmap().map(c)).map(|g| g.to_u32()).unwrap_or(0) + } +} + +#[cfg(not(target_arch = "wasm32"))] +#[derive(Clone, Debug)] +struct CatalogEntry { + family: String, + style: String, + path: std::path::PathBuf, +} + +/// Process-wide font database. +pub struct FontDb { + faces: RwLock>>, + outlines: Mutex>>, + #[cfg(not(target_arch = "wasm32"))] + catalog: RwLock>, + /// System fallback state: scanned yet, and characters no system font covers. + #[cfg(not(target_arch = "wasm32"))] + sys: Mutex, +} + +#[cfg(not(target_arch = "wasm32"))] +#[derive(Default)] +struct SysFallback { + enabled: bool, + scanned: bool, + misses: std::collections::HashSet, +} + +/// Families tried (when installed) for characters the loaded fonts lack: CJK, symbols, emoji. +#[cfg(not(target_arch = "wasm32"))] +const SYSTEM_FALLBACKS: &[&str] = &[ + "Helvetica Neue", + "Arial", + "Segoe UI", + "Noto Sans", + "DejaVu Sans", + "PingFang SC", + "Hiragino Sans", + "Hiragino Kaku Gothic ProN", + "Apple SD Gothic Neo", + "Heiti SC", + "STHeiti", + "Microsoft YaHei", + "Yu Gothic", + "Malgun Gothic", + "Noto Sans CJK SC", + "Noto Sans CJK JP", + "Arial Unicode MS", + "Apple Symbols", + "Segoe UI Symbol", + "Noto Sans Symbols", + "Noto Sans Symbols2", + "Noto Emoji", + "Segoe UI Emoji", + "Apple Color Emoji", + "Noto Color Emoji", +]; + +static NEXT_ID: AtomicU32 = AtomicU32::new(1); +const OUTLINE_CACHE_MAX: usize = 50_000; + +fn name(font: &skrifa::FontRef<'_>, ids: &[StringId]) -> Option { + ids.iter().find_map(|id| font.localized_strings(*id).english_or_first().map(|s| s.to_string()).filter(|s| !s.is_empty())) +} + +/// Parse every face in `data` (a font file or collection). Returns `(index, family, style)`. +fn enumerate_faces(data: &[u8]) -> Vec<(u32, String, String)> { + let count = match FileRef::new(data) { + Ok(FileRef::Font(_)) => 1, + Ok(FileRef::Collection(c)) => c.len(), + Err(_) => 0, + }; + (0..count) + .filter_map(|i| { + let f = skrifa::FontRef::from_index(data, i).ok()?; + let family = name(&f, &[StringId::TYPOGRAPHIC_FAMILY_NAME, StringId::FAMILY_NAME])?; + let style = name(&f, &[StringId::TYPOGRAPHIC_SUBFAMILY_NAME, StringId::SUBFAMILY_NAME]).unwrap_or_else(|| "Regular".into()); + Some((i, family, style)) + }) + .collect() +} + +fn make_face(bytes: FontBytes, index: u32, family: String, style: String) -> Option { + let data: &[u8] = match &bytes { + FontBytes::Static(b) => b, + FontBytes::Owned(v) => v.as_slice(), + }; + let f = skrifa::FontRef::from_index(data, index).ok()?; + let m = f.metrics(Size::unscaled(), LocationRef::default()); + let a = f.attributes(); + let shaper = harfrust::ShaperData::new(&harfrust::FontRef::from_index(data, index).ok()?); + Some(FontFace { + id: NEXT_ID.fetch_add(1, Ordering::Relaxed), + family, + style, + weight: a.weight.value(), + italic: !matches!(a.style, skrifa::attribute::Style::Normal), + upem: m.units_per_em.max(1) as f64, + ascent: m.ascent as f64, + descent: -(m.descent as f64), + cap_height: m.cap_height.map(|v| v as f64).filter(|v| *v > 0.0).unwrap_or(m.ascent as f64 * 0.72), + x_height: m.x_height.map(|v| v as f64).filter(|v| *v > 0.0).unwrap_or(m.ascent as f64 * 0.5), + shaper, + bytes, + index, + }) +} + +fn norm(s: &str) -> String { + s.chars().filter(|c| c.is_alphanumeric()).flat_map(|c| c.to_lowercase()).collect() +} + +/// Weight implied by a style name. +fn style_weight(style: &str) -> f32 { + let s = norm(style); + const TABLE: &[(&str, f32)] = &[ + ("extralight", 200.0), + ("ultralight", 200.0), + ("semibold", 600.0), + ("demibold", 600.0), + ("extrabold", 800.0), + ("ultrabold", 800.0), + ("hairline", 100.0), + ("thin", 100.0), + ("light", 300.0), + ("medium", 500.0), + ("bold", 700.0), + ("black", 900.0), + ("heavy", 900.0), + ]; + TABLE.iter().find(|(k, _)| s.contains(k)).map(|(_, w)| *w).unwrap_or(400.0) +} + +fn style_italic(style: &str) -> bool { + let s = norm(style); + s.contains("italic") || s.contains("oblique") || s == "it" +} + +impl FontDb { + fn new_bundled() -> Self { + let mut faces = Vec::new(); + for data in BUNDLED { + for (i, family, style) in enumerate_faces(data) { + if let Some(f) = make_face(FontBytes::Static(data), i, family, style) { + faces.push(Arc::new(f)); + } + } + } + Self { + faces: RwLock::new(faces), + outlines: Mutex::new(HashMap::new()), + #[cfg(not(target_arch = "wasm32"))] + catalog: RwLock::new(Vec::new()), + #[cfg(not(target_arch = "wasm32"))] + sys: Mutex::new(SysFallback { enabled: true, ..Default::default() }), + } + } + + /// Enable or disable the lazy system-font fallback for characters the loaded fonts lack + /// (native only; on by default). + pub fn set_system_fallback(&self, on: bool) { + #[cfg(not(target_arch = "wasm32"))] + { + self.sys.lock().unwrap_or_else(|e| e.into_inner()).enabled = on; + } + #[cfg(target_arch = "wasm32")] + let _ = on; + } + + /// Process-wide database preloaded with the bundled fonts. + pub fn global() -> &'static FontDb { + static DB: std::sync::OnceLock = std::sync::OnceLock::new(); + DB.get_or_init(FontDb::new_bundled) + } + + fn read_faces(&self) -> std::sync::RwLockReadGuard<'_, Vec>> { + self.faces.read().unwrap_or_else(|e| e.into_inner()) + } + + /// Family names available (loaded plus cataloged system fonts), sorted and deduplicated. + pub fn families(&self) -> Vec { + let mut v: Vec = self.read_faces().iter().map(|f| f.family.clone()).collect(); + #[cfg(not(target_arch = "wasm32"))] + v.extend(self.catalog.read().unwrap_or_else(|e| e.into_inner()).iter().map(|c| c.family.clone())); + v.sort_by_key(|a| a.to_lowercase()); + v.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + v + } + + /// Style names available for `family` (Regular first, then by weight). + pub fn styles(&self, family: &str) -> Vec { + let mut v: Vec<(bool, f32, String)> = + self.read_faces().iter().filter(|f| f.family.eq_ignore_ascii_case(family)).map(|f| (f.italic, f.weight, f.style.clone())).collect(); + #[cfg(not(target_arch = "wasm32"))] + for c in self.catalog.read().unwrap_or_else(|e| e.into_inner()).iter() { + if c.family.eq_ignore_ascii_case(family) && !v.iter().any(|(_, _, s)| s.eq_ignore_ascii_case(&c.style)) { + v.push((style_italic(&c.style), style_weight(&c.style), c.style.clone())); + } + } + v.sort_by(|a, b| a.0.cmp(&b.0).then(a.1.total_cmp(&b.1)).then(a.2.cmp(&b.2))); + v.dedup_by(|a, b| a.2 == b.2); + v.into_iter().map(|t| t.2).collect() + } + + /// Add a user font (TTF/OTF/TTC bytes). Returns the number of faces added (0 if unparseable or + /// every face was already present). + pub fn add_font(&self, bytes: Vec) -> usize { + let data = Arc::new(bytes); + let mut added = 0; + for (i, family, style) in enumerate_faces(&data) { + if self.read_faces().iter().any(|f| f.family.eq_ignore_ascii_case(&family) && f.style.eq_ignore_ascii_case(&style)) { + continue; + } + if let Some(f) = make_face(FontBytes::Owned(data.clone()), i, family, style) { + self.faces.write().unwrap_or_else(|e| e.into_inner()).push(Arc::new(f)); + added += 1; + } + } + added + } + + /// Scan the platform's font directories and catalog the faces found (native only; not called by + /// default). Font data is loaded lazily when a cataloged family is first resolved. Returns the + /// number of faces cataloged. + #[cfg(not(target_arch = "wasm32"))] + pub fn load_system_fonts(&self) -> usize { + let mut dirs: Vec = Vec::new(); + let home = std::env::var_os("HOME").map(std::path::PathBuf::from); + if cfg!(target_os = "macos") { + dirs.extend(["/System/Library/Fonts", "/Library/Fonts"].map(Into::into)); + if let Some(h) = &home { + dirs.push(h.join("Library/Fonts")); + } + } else if cfg!(windows) { + let root = std::env::var_os("WINDIR").map(std::path::PathBuf::from).unwrap_or_else(|| "C:\\Windows".into()); + dirs.push(root.join("Fonts")); + if let Some(l) = std::env::var_os("LOCALAPPDATA") { + dirs.push(std::path::PathBuf::from(l).join("Microsoft\\Windows\\Fonts")); + } + } else { + dirs.extend(["/usr/share/fonts", "/usr/local/share/fonts"].map(Into::into)); + if let Some(h) = &home { + dirs.push(h.join(".fonts")); + dirs.push(h.join(".local/share/fonts")); + } + } + let mut found = Vec::new(); + let mut stack = dirs; + while let Some(d) = stack.pop() { + let Ok(rd) = std::fs::read_dir(&d) else { continue }; + for e in rd.flatten() { + let p = e.path(); + if p.is_dir() { + stack.push(p); + continue; + } + let ext = p.extension().and_then(|e| e.to_str()).map(|e| e.to_ascii_lowercase()); + if !matches!(ext.as_deref(), Some("ttf" | "otf" | "ttc" | "otc")) { + continue; + } + let Ok(data) = std::fs::read(&p) else { continue }; + for (_, family, style) in enumerate_faces(&data) { + found.push(CatalogEntry { family, style, path: p.clone() }); + } + } + } + let n = found.len(); + log::debug!("cataloged {n} system font faces"); + *self.catalog.write().unwrap_or_else(|e| e.into_inner()) = found; + n + } + + #[cfg(not(target_arch = "wasm32"))] + fn load_cataloged(&self, family: &str) -> bool { + let paths: Vec = { + let cat = self.catalog.read().unwrap_or_else(|e| e.into_inner()); + let mut p: Vec<_> = cat.iter().filter(|c| c.family.eq_ignore_ascii_case(family)).map(|c| c.path.clone()).collect(); + p.dedup(); + p + }; + let mut any = false; + for p in paths { + if let Ok(data) = std::fs::read(&p) { + any |= self.add_font(data) > 0; + } + } + any + } + + /// Resolve a family + style to a face, falling back to the closest style of the family, then to + /// Source Sans 3 Regular. + pub fn face(&self, family: &str, style: &str) -> Arc { + if let Some(f) = self.find(family, style) { + return f; + } + #[cfg(not(target_arch = "wasm32"))] + if self.load_cataloged(family) + && let Some(f) = self.find(family, style) + { + return f; + } + self.find(FALLBACK_FAMILY, style) + .or_else(|| self.find(FALLBACK_FAMILY, "Regular")) + .or_else(|| self.read_faces().first().cloned()) + .expect("bundled fonts are always present") + } + + /// Is `family` available (loaded)? + pub fn has_family(&self, family: &str) -> bool { + self.read_faces().iter().any(|f| f.family.eq_ignore_ascii_case(family)) + } + + fn find(&self, family: &str, style: &str) -> Option> { + let faces = self.read_faces(); + let cands: Vec<&Arc> = faces.iter().filter(|f| f.family.eq_ignore_ascii_case(family)).collect(); + if cands.is_empty() { + return None; + } + let ns = norm(style); + if let Some(f) = cands.iter().find(|f| norm(&f.style) == ns) { + return Some((*f).clone()); + } + let (tw, ti) = (style_weight(style), style_italic(style)); + cands + .iter() + .min_by(|a, b| { + let sa = (a.weight - tw).abs() + if a.italic != ti { 1000.0 } else { 0.0 }; + let sb = (b.weight - tw).abs() + if b.italic != ti { 1000.0 } else { 0.0 }; + sa.total_cmp(&sb) + }) + .map(|f| (*f).clone()) + } + + /// First face (fallback family first, then load order) that covers `c`; on native, system + /// fonts are cataloged and loaded lazily the first time no loaded face covers a character. + pub fn fallback_for(&self, c: char, exclude: u32) -> Option> { + if let Some(f) = self.loaded_fallback(c, exclude) { + return Some(f); + } + #[cfg(not(target_arch = "wasm32"))] + if self.system_fallback(c) { + return self.loaded_fallback(c, exclude); + } + None + } + + fn loaded_fallback(&self, c: char, exclude: u32) -> Option> { + let faces = self.read_faces(); + let mut order: Vec<&Arc> = faces.iter().filter(|f| f.id != exclude).collect(); + order.sort_by_key(|f| (!f.family.eq_ignore_ascii_case(FALLBACK_FAMILY), f.italic, (f.weight - 400.0).abs() as i32)); + order.into_iter().find(|f| f.covers(c)).cloned() + } + + /// Load a system font covering `c` (preferred fallback families first, then any cataloged + /// file under 40 MB). Returns true if one was loaded. Misses are remembered. + #[cfg(not(target_arch = "wasm32"))] + fn system_fallback(&self, c: char) -> bool { + if c.is_control() || c.is_whitespace() { + return false; + } + { + let mut sys = self.sys.lock().unwrap_or_else(|e| e.into_inner()); + if !sys.enabled || sys.misses.contains(&c) { + return false; + } + if !sys.scanned { + sys.scanned = true; + if self.catalog.read().unwrap_or_else(|e| e.into_inner()).is_empty() { + drop(sys); + self.load_system_fonts(); + } + } + } + let covered = |db: &FontDb| db.read_faces().iter().any(|f| f.covers(c)); + let cataloged: Vec = self.catalog.read().unwrap_or_else(|e| e.into_inner()).iter().map(|e| e.family.clone()).collect(); + for fam in SYSTEM_FALLBACKS { + if !self.has_family(fam) && cataloged.iter().any(|f| f.eq_ignore_ascii_case(fam)) { + self.load_cataloged(fam); + if covered(self) { + return true; + } + } + } + let mut paths: Vec = self.catalog.read().unwrap_or_else(|e| e.into_inner()).iter().map(|e| e.path.clone()).collect(); + paths.sort(); + paths.dedup(); + for p in paths { + if std::fs::metadata(&p).map(|m| m.len() > 40 << 20).unwrap_or(true) { + continue; + } + let Ok(data) = std::fs::read(&p) else { continue }; + let hit = + enumerate_faces(&data).iter().any(|(i, _, _)| skrifa::FontRef::from_index(&data, *i).is_ok_and(|f| f.charmap().map(c).is_some())); + if hit && self.add_font(data) > 0 && covered(self) { + return true; + } + } + self.sys.lock().unwrap_or_else(|e| e.into_inner()).misses.insert(c); + false + } + + /// Glyph outline in font units, y-down (flipped), cached per (face, glyph). + pub fn outline(&self, face: &FontFace, gid: u32) -> Arc { + let key = (face.id, gid); + if let Some(p) = self.outlines.lock().unwrap_or_else(|e| e.into_inner()).get(&key) { + return p.clone(); + } + let mut pen = FlipPen(BezPath::new()); + if let Some(f) = face.skrifa() + && let Some(g) = f.outline_glyphs().get(GlyphId::new(gid)) + { + let _ = g.draw(DrawSettings::unhinted(Size::unscaled(), LocationRef::default()), &mut pen); + } + let p = Arc::new(pen.0); + let mut cache = self.outlines.lock().unwrap_or_else(|e| e.into_inner()); + if cache.len() >= OUTLINE_CACHE_MAX { + cache.clear(); + } + cache.insert(key, p.clone()); + p + } +} + +struct FlipPen(BezPath); + +impl OutlinePen for FlipPen { + fn move_to(&mut self, x: f32, y: f32) { + self.0.move_to((x as f64, -y as f64)); + } + fn line_to(&mut self, x: f32, y: f32) { + self.0.line_to((x as f64, -y as f64)); + } + fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) { + self.0.quad_to((cx0 as f64, -cy0 as f64), (x as f64, -y as f64)); + } + fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) { + self.0.curve_to((cx0 as f64, -cy0 as f64), (cx1 as f64, -cy1 as f64), (x as f64, -y as f64)); + } + fn close(&mut self) { + self.0.close_path(); + } +} diff --git a/crates/fonts/src/lib.rs b/crates/fonts/src/lib.rs new file mode 100644 index 00000000..ee29ed21 --- /dev/null +++ b/crates/fonts/src/lib.rs @@ -0,0 +1,139 @@ +//! DesignCraft fonts: the font database (bundled OFL families + user/system fonts), vertical +//! metrics, glyph outlines and OpenType shaping. +//! +//! Shaping here is style-agnostic: [`shape`] turns a string in one face into glyph ids, clusters +//! and advances in font units. `designcraft-compose` applies sizes, tracking, scaling and +//! justification on top. +#![forbid(unsafe_code)] + +mod fontdb; + +pub use fontdb::{FALLBACK_FAMILY, FontDb, FontFace}; +pub use harfrust::Feature; +use harfrust::{Direction, ShapeOptions, Tag, UnicodeBuffer}; +pub use kurbo::BezPath; +use skrifa::MetadataProvider; +use skrifa::instance::{LocationRef, Size}; + +/// InDesign's default text font is a serif; ours is Source Serif 4. +pub const DEFAULT_FAMILY: &str = "Source Serif 4"; + +/// One shaped glyph, in font units. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct ShapedGlyph { + pub gid: u32, + /// Byte offset (in the shaped string) of the cluster this glyph belongs to. + pub cluster: usize, + pub x_advance: i32, + pub x_offset: i32, + pub y_offset: i32, +} + +/// An OpenType feature setting: `"liga"`, `"-kern"`, `"ss01"`. +pub fn feature(tag: &str) -> Option { + let (on, t) = match tag.strip_prefix('-') { + Some(r) => (false, r), + None => (true, tag.strip_prefix('+').unwrap_or(tag)), + }; + let b = t.as_bytes(); + if b.len() != 4 { + return None; + } + Some(Feature::new(Tag::new(&[b[0], b[1], b[2], b[3]]), on as u32, ..)) +} + +/// Shape `text` with `face`. `chars` lets callers substitute characters (e.g. uppercase for All +/// Caps) while keeping clusters pointing into the original string. +pub fn shape(face: &FontFace, text: &str, features: &[Feature], map: impl Fn(char) -> char) -> Vec { + let mut out = Vec::with_capacity(text.len()); + let shaped = face.hb().map(|hb| { + let shaper = face.shaper.shaper(&hb).build(); + let mut buf = UnicodeBuffer::new(); + for (i, c) in text.char_indices() { + buf.add(map(c), i as u32); + } + buf.set_direction(Direction::LeftToRight); + buf.guess_segment_properties(); + let gb = shaper.shape(buf, ShapeOptions::new().features(features)); + for (info, pos) in gb.glyph_infos().iter().zip(gb.glyph_positions()) { + out.push(ShapedGlyph { + gid: info.glyph_id, + cluster: info.cluster as usize, + x_advance: pos.x_advance, + x_offset: pos.x_offset, + y_offset: pos.y_offset, + }); + } + }); + if shaped.is_none() + && let Some(f) = face.skrifa() + { + let cmap = f.charmap(); + let gm = f.glyph_metrics(Size::unscaled(), LocationRef::default()); + for (i, c) in text.char_indices() { + let g = cmap.map(map(c)).unwrap_or_default(); + let adv = gm.advance_width(g).unwrap_or(face.upem as f32 * 0.5); + out.push(ShapedGlyph { gid: g.to_u32(), cluster: i, x_advance: adv.round() as i32, x_offset: 0, y_offset: 0 }); + } + } + out +} + +/// Glyph id of the first of `chars` the face has (0 = .notdef). +pub fn first_glyph(face: &FontFace, chars: &[char]) -> u32 { + chars.iter().map(|c| face.glyph_for(*c)).find(|g| *g != 0).unwrap_or(0) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bundled_families_load() { + let db = FontDb::global(); + let fams = db.families(); + assert!(fams.iter().any(|f| f == DEFAULT_FAMILY), "{fams:?}"); + assert!(fams.iter().any(|f| f == "Source Sans 3")); + let styles = db.styles(DEFAULT_FAMILY); + for s in ["Regular", "Italic", "Bold", "Semibold"] { + assert!(styles.iter().any(|x| x == s), "{s} in {styles:?}"); + } + } + + #[test] + fn shaping_produces_clusters_and_advances() { + let face = FontDb::global().face(DEFAULT_FAMILY, "Regular"); + let g = shape(&face, "Hello", &[], |c| c); + assert_eq!(g.len(), 5); + assert_eq!(g.iter().map(|g| g.cluster).collect::>(), vec![0, 1, 2, 3, 4]); + assert!(g.iter().all(|g| g.x_advance > 0 && g.gid != 0)); + } + + #[test] + fn ligatures_can_be_disabled() { + let face = FontDb::global().face(DEFAULT_FAMILY, "Regular"); + let on = shape(&face, "office", &[], |c| c); + let off = shape(&face, "office", &[feature("-liga").unwrap()], |c| c); + assert!(on.len() <= off.len()); + assert_eq!(off.len(), 6); + } + + #[test] + fn mapping_keeps_clusters() { + let face = FontDb::global().face(DEFAULT_FAMILY, "Regular"); + let g = shape(&face, "ab", &[], |c| c.to_ascii_uppercase()); + assert_eq!(g[0].gid, face.glyph_for('A')); + assert_eq!(g[1].cluster, 1); + } + + #[test] + fn outlines_and_metrics() { + let db = FontDb::global(); + let face = db.face(DEFAULT_FAMILY, "Bold"); + assert_eq!(face.style, "Bold"); + let o = db.outline(&face, face.glyph_for('O')); + assert!(!o.elements().is_empty()); + assert!(face.ascent > 0.0 && face.descent > 0.0 && face.cap_height > face.x_height); + assert!(feature("abc").is_none()); + } +} diff --git a/crates/render/Cargo.toml b/crates/render/Cargo.toml new file mode 100644 index 00000000..b3e52cfd --- /dev/null +++ b/crates/render/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "designcraft-render" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "DesignCraft renderer: spreads, pages, frames, composed text and images to pixels (vello_cpu)" + +[lints] +workspace = true + +[dependencies] +designcraft-geom = { workspace = true } +designcraft-color = { workspace = true } +designcraft-doc = { workspace = true } +designcraft-fonts = { workspace = true } +designcraft-compose = { workspace = true } +vello_cpu = { workspace = true } +vello_common = { workspace = true } +image = { workspace = true } +log = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +vello_cpu = { workspace = true, features = ["multithreading"] } diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs new file mode 100644 index 00000000..d4b6f364 --- /dev/null +++ b/crates/render/src/lib.rs @@ -0,0 +1,674 @@ +//! DesignCraft renderer: spreads → premultiplied RGBA pixels with `vello_cpu`. +//! +//! The renderer draws *document content only* (paper, page items, parent items, composed text, +//! placed images). Non-printing chrome — guides, frame edges, ports, selection — is drawn by the +//! UI as vector overlays so it stays crisp at any zoom. +//! +//! Callers pass a list of spreads with their placement on a shared canvas and a canvas → pixel +//! view transform, so the UI can render exactly its viewport with every visible spread. +#![forbid(unsafe_code)] + +use std::collections::HashMap; +use std::sync::Arc; + +use designcraft_color::BlendMode as DcBlend; +use designcraft_compose::{Cache, ComposedStory, FrameText}; +use designcraft_doc::{AssetId, Content, Document, Item, PageSide, SpreadRef, StrokeAlign, StrokeType}; +use designcraft_fonts::FontDb; +use designcraft_geom::corners; +use designcraft_geom::{Affine, BezPath, Rect, Shape, Vec2}; +use vello_cpu::kurbo; +use vello_cpu::peniko::{self, BlendMode, Compose, Mix}; +use vello_cpu::{Pixmap, RenderContext, Resources}; + +pub use vello_cpu; + +/// A rendered image (premultiplied RGBA8, row-major). +#[derive(Clone)] +pub struct Rendered { + pub width: u32, + pub height: u32, + pub pixels: Vec, +} + +impl Rendered { + pub fn to_straight(&self) -> Vec { + let mut out = self.pixels.clone(); + for px in out.chunks_exact_mut(4) { + let a = px[3] as u32; + if a != 0 && a != 255 { + for c in &mut px[..3] { + *c = ((*c as u32 * 255 + a / 2) / a).min(255) as u8; + } + } + } + out + } + pub fn to_png(&self) -> Vec { + let mut buf = Vec::new(); + let img = image::RgbaImage::from_raw(self.width, self.height, self.to_straight()).expect("size"); + img.write_to(&mut std::io::Cursor::new(&mut buf), image::ImageFormat::Png).expect("png encode"); + buf + } + pub fn to_jpeg(&self, quality: u8) -> Vec { + let rgba = self.to_straight(); + let rgb: Vec = rgba + .chunks_exact(4) + .flat_map(|p| { + let a = p[3] as u32; + let mix = |c: u8| ((c as u32 * a + 255 * (255 - a)) / 255) as u8; + [mix(p[0]), mix(p[1]), mix(p[2])] + }) + .collect(); + let mut buf = Vec::new(); + let enc = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, quality.clamp(1, 100)); + let _ = image::ImageEncoder::write_image(enc, &rgb, self.width, self.height, image::ExtendedColorType::Rgb8); + buf + } + /// Straight-alpha RGBA at (x, y). + pub fn pixel(&self, x: u32, y: u32) -> [u8; 4] { + let i = ((y * self.width + x) * 4) as usize; + let p = &self.pixels[i..i + 4]; + let a = p[3] as u32; + if a == 0 { + return [0, 0, 0, 0]; + } + let un = |c: u8| ((c as u32 * 255 + a / 2) / a).min(255) as u8; + [un(p[0]), un(p[1]), un(p[2]), p[3]] + } +} + +/// What to draw. +#[derive(Clone, Debug)] +pub struct RenderOptions { + /// Canvas background (premultiplied RGBA8); `None` = transparent. + pub background: Option<[u8; 4]>, + /// Fill pages with paper colour. + pub paper: bool, + /// Skip non-printing items and layers (Preview mode, export). + pub printing_only: bool, + /// Items not to draw (live drag previews). + pub hidden: Vec, + /// Draw text smaller than this many pixels as grey bars ("greeking"); 0 = never. + pub greek_below_px: f64, + /// Drop shadow on pages (screen view). + pub page_shadow: bool, +} + +impl Default for RenderOptions { + fn default() -> Self { + Self { background: None, paper: true, printing_only: false, hidden: vec![], greek_below_px: 0.0, page_shadow: false } + } +} + +/// A spread placed on the canvas: canvas = spread + offset. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Placed { + pub spread: SpreadRef, + pub offset: Vec2, +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct FrameStats { + pub items: usize, + pub glyphs: usize, + pub micros: u64, +} + +/// Reusable renderer (keeps the render context and decoded images). +pub struct Renderer { + ctx: Option, + resources: Resources, + images: HashMap<(AssetId, usize), Arc>, + pub threads: u16, + pub stats: FrameStats, +} + +impl Default for Renderer { + fn default() -> Self { + Self::new() + } +} + +struct Frame<'a> { + doc: &'a Document, + cache: &'a Cache, + view: Affine, + visible: Rect, + px: f64, + opts: &'a RenderOptions, +} + +pub fn default_threads() -> u16 { + #[cfg(target_arch = "wasm32")] + { + 0 + } + #[cfg(not(target_arch = "wasm32"))] + { + if let Some(n) = std::env::var("DESIGNCRAFT_RENDER_THREADS").ok().and_then(|v| v.parse().ok()) { + return n; + } + std::thread::available_parallelism().map(|n| (n.get().saturating_sub(1)).clamp(0, 8) as u16).unwrap_or(0) + } +} + +impl Renderer { + pub fn new() -> Self { + Self { ctx: None, resources: Resources::new(), images: HashMap::new(), threads: default_threads(), stats: FrameStats::default() } + } + + /// Render the given spreads into a `width`×`height` image with `view` (canvas → pixels). + pub fn render(&mut self, doc: &Document, cache: &Cache, spreads: &[Placed], width: u32, height: u32, view: Affine, opts: &RenderOptions) -> Rendered { + let start = now(); + let w = width.clamp(1, u16::MAX as u32) as u16; + let h = height.clamp(1, u16::MAX as u32) as u16; + let mut ctx = match self.ctx.take() { + Some(mut c) if c.width() == w && c.height() == h => { + c.reset(); + c + } + _ => RenderContext::new_with(w, h, vello_cpu::RenderSettings { num_threads: self.threads, ..Default::default() }), + }; + self.stats = FrameStats::default(); + if let Some(bg) = opts.background { + ctx.set_transform(Affine::IDENTITY); + ctx.set_paint(peniko::Color::from_rgba8(bg[0], bg[1], bg[2], bg[3])); + ctx.fill_rect(&kurbo::Rect::new(0.0, 0.0, w as f64, h as f64)); + } + let px = 1.0 / view.determinant().abs().sqrt().max(1e-12); + let canvas_visible = view.inverse().transform_rect_bbox(Rect::new(0.0, 0.0, w as f64, h as f64)); + for pl in spreads { + let Some(sp) = doc.spread(pl.spread) else { continue }; + let sview = view * Affine::translate(pl.offset); + let visible = canvas_visible - pl.offset; + let bounds = sp.bounds(); + // Cull spreads far outside the viewport (pasteboard items may extend; allow a margin). + if !rect_overlaps(bounds.inflate(2000.0, 2000.0), visible) { + continue; + } + let f = Frame { doc, cache, view: sview, visible, px, opts }; + self.draw_spread(&mut ctx, &f, pl.spread); + } + ctx.flush(); + let mut pm = Pixmap::new(w, h); + ctx.render(&mut pm, &mut self.resources); + self.ctx = Some(ctx); + self.stats.micros = now().saturating_sub(start); + Rendered { width: w as u32, height: h as u32, pixels: pm.data_as_u8_slice().to_vec() } + } + + /// Render one document page (absolute index) at `scale` px/pt, optionally including bleed. + pub fn render_page(&mut self, doc: &Document, cache: &Cache, abs: usize, scale: f64, bleed: bool, opts: &RenderOptions) -> Option { + let (si, pi) = doc.page_loc(abs)?; + let page = &doc.spreads[si].pages[pi]; + let mut r = page.bounds(); + if bleed { + let b = doc.settings.bleed; + let (l, rr) = if page.side == PageSide::Left { (b[3], b[2]) } else { (b[2], b[3]) }; + r = Rect::new(r.x0 - l, r.y0 - b[0], r.x1 + rr, r.y1 + b[1]); + } + let w = (r.width() * scale).round().max(1.0) as u32; + let h = (r.height() * scale).round().max(1.0) as u32; + let view = Affine::scale(scale) * Affine::translate(-r.origin().to_vec2()); + let mut o = opts.clone(); + o.background = Some([255, 255, 255, 255]); + Some(self.render(doc, cache, &[Placed { spread: SpreadRef::Doc(si), offset: Vec2::ZERO }], w, h, view, &o)) + } + + fn draw_spread(&mut self, ctx: &mut RenderContext, f: &Frame, sr: SpreadRef) { + let doc = f.doc; + let Some(sp) = doc.spread(sr) else { return }; + // Paper. + if f.opts.paper { + let paper = doc.resolve_color(designcraft_color::swatch::PAPER, 1.0).unwrap_or(designcraft_color::Color::WHITE); + if f.opts.page_shadow { + ctx.set_transform(f.view); + ctx.set_paint(peniko::Color::from_rgba8(0, 0, 0, 90)); + for p in &sp.pages { + let s = 3.0 * f.px; + ctx.fill_rect(&(p.bounds() + Vec2::new(s, s))); + } + } + ctx.set_transform(f.view); + ctx.set_paint(color_of(&paper, 1.0)); + for p in &sp.pages { + ctx.fill_rect(&p.bounds()); + } + } + // Layers back to front; within each layer parent items first (document spreads only). + for layer in doc.layers.iter().rev() { + if !layer.visible || f.opts.printing_only && !layer.printable { + continue; + } + if let SpreadRef::Doc(si) = sr { + let first = doc.first_page_of_spread(si); + for (pi, page) in sp.pages.iter().enumerate() { + if !page.show_parent_items { + continue; + } + let Some((ppi, ppage)) = doc.parent_page_for(first + pi) else { continue }; + let parent = &doc.parents[ppi]; + let dx = page.x - parent.pages[ppage].x; + let page_name = doc.page_name(first + pi); + let pr = parent.pages[ppage].bounds(); + for it in &parent.items { + if it.layer != layer.id || page.overridden.contains(&it.id) { + continue; + } + // Parent items belong to the parent page they sit on. + if parent.page_at_x(it.bounds().center().x) != Some(ppage) && parent.pages.len() > 1 { + continue; + } + let _ = pr; + self.draw_item(ctx, f, it, Affine::translate((dx, 0.0)), Some(&page_name)); + } + } + } + for it in &sp.items { + if it.layer == layer.id { + self.draw_item(ctx, f, it, Affine::IDENTITY, None); + } + } + } + } + + fn draw_item(&mut self, ctx: &mut RenderContext, f: &Frame, it: &Item, parent: Affine, page_name: Option<&str>) { + if it.hidden || f.opts.hidden.contains(&it.id) || f.opts.printing_only && it.nonprinting { + return; + } + let xf = parent * it.xf; + let vb = xf.transform_rect_bbox(it.inner_bounds()).inflate(it.stroke.weight + 2.0, it.stroke.weight + 2.0); + if !it.children().is_empty() { + // Groups: children carry their own transforms relative to the group. + let layered = it.opacity < 0.999 || it.blend != DcBlend::Normal; + if layered { + ctx.set_transform(Affine::IDENTITY); + ctx.push_layer(None, Some(blend_mode(it.blend)), Some(it.opacity), None, None); + } + for c in it.children() { + self.draw_item(ctx, f, c, xf, page_name); + } + if layered { + ctx.pop_layer(); + } + return; + } + if !rect_overlaps(vb, f.visible) && !matches!(it.content, Content::Text(_)) { + return; + } + self.stats.items += 1; + let doc = f.doc; + let bp = if it.corners.is_none() { it.path.to_bezpath() } else { corners::apply(&it.path, &it.corners) }; + let layered = it.opacity < 0.999 || it.blend != DcBlend::Normal; + if layered { + ctx.set_transform(Affine::IDENTITY); + ctx.push_layer(None, Some(blend_mode(it.blend)), Some(it.opacity), None, None); + } + // Drop shadow (simple offset silhouette). + if it.effects.drop_shadow.on { + let ds = &it.effects.drop_shadow; + let a = ds.angle.to_radians(); + let off = Vec2::new(-a.cos() * ds.distance, a.sin() * ds.distance); + if let Some(c) = doc.resolve_color(&ds.color, 1.0) { + ctx.set_transform(f.view * Affine::translate(off) * xf); + ctx.set_paint(color_of(&c, ds.opacity)); + ctx.fill_path(&bp); + } + } + // Fill. + if !it.fill.is_none() { + ctx.set_transform(f.view * xf); + if set_fill_paint(ctx, doc, &it.fill.swatch, it.fill.tint, bp.bounding_box(), it.fill.gradient_angle) && it.path.is_closed() { + ctx.fill_path(&bp); + } + ctx.reset_paint_transform(); + } + // Content. + match &it.content { + Content::Graphic(g) => { + ctx.set_transform(f.view * xf); + ctx.push_clip_layer(&bp); + self.draw_graphic(ctx, f, g, xf); + ctx.pop_layer(); + } + Content::Text(tf) => { + let cs = f.cache.get(doc, tf.story, page_name); + if let Some(ft) = cs.frame(it.id) { + self.draw_text(ctx, f, &cs, ft, xf); + } + } + _ => {} + } + // Stroke. + if !it.stroke.is_none() { + self.draw_stroke(ctx, f, it, &bp, xf); + } + if layered { + ctx.pop_layer(); + } + } + + fn draw_stroke(&mut self, ctx: &mut RenderContext, f: &Frame, it: &Item, bp: &BezPath, xf: Affine) { + let st = &it.stroke; + let Some(c) = f.doc.resolve_color(&st.swatch, st.tint) else { return }; + let mut stroke = kurbo::Stroke::new(st.weight) + .with_caps(match st.cap { + designcraft_doc::Cap::Butt => kurbo::Cap::Butt, + designcraft_doc::Cap::Round => kurbo::Cap::Round, + designcraft_doc::Cap::Projecting => kurbo::Cap::Square, + }) + .with_join(match st.join { + designcraft_doc::Join::Miter => kurbo::Join::Miter, + designcraft_doc::Join::Round => kurbo::Join::Round, + designcraft_doc::Join::Bevel => kurbo::Join::Bevel, + }) + .with_miter_limit(st.miter_limit); + match &st.kind { + StrokeType::Dashed { pattern } if !pattern.is_empty() => stroke = stroke.with_dashes(0.0, pattern.iter().copied()), + StrokeType::Dotted => stroke = stroke.with_dashes(0.0, [0.0, st.weight * 2.0]).with_caps(kurbo::Cap::Round), + _ => {} + } + ctx.set_transform(f.view * xf); + ctx.set_paint(color_of(&c, 1.0)); + let closed = it.path.is_closed(); + match st.align { + StrokeAlign::Inside if closed => { + // Clip a double-width stroke to the path. + ctx.push_clip_layer(bp); + ctx.set_stroke(kurbo::Stroke { width: st.weight * 2.0, ..stroke }); + ctx.stroke_path(bp); + ctx.pop_layer(); + } + StrokeAlign::Outside if closed => { + let outline = kurbo::stroke(bp.iter(), &kurbo::Stroke { width: st.weight * 2.0, ..stroke }, &kurbo::StrokeOpts::default(), 0.05 * f.px); + let mut p = outline; + // Remove the interior: even-odd with the path itself. + for el in bp.elements() { + p.push(*el); + } + ctx.set_fill_rule(peniko::Fill::EvenOdd); + ctx.fill_path(&p); + ctx.set_fill_rule(peniko::Fill::NonZero); + } + _ => { + ctx.set_stroke(stroke); + ctx.stroke_path(bp); + } + } + } + + fn draw_graphic(&mut self, ctx: &mut RenderContext, f: &Frame, g: &designcraft_doc::Graphic, xf: Affine) { + let Some(asset) = f.doc.assets.get(&g.asset) else { return }; + // Pick a mip level close to the on-screen size. + let on_screen = (f.view * xf * g.xf).determinant().abs().sqrt(); + let full = match self.images.get(&(g.asset, 0)) { + Some(p) => p.clone(), + None => { + let Some(pm) = decode_pixmap(&asset.data) else { return }; + let pm = Arc::new(pm); + self.images.insert((g.asset, 0), pm.clone()); + pm + } + }; + let ppt = full.width() as f64 / g.size.0.max(1e-6); // pixels per point + let need = on_screen * 1.0; // pixels per point on screen + let mut level = 0usize; + let mut pm = full.clone(); + while ppt / (1 << (level + 1)) as f64 >= need * 1.2 && pm.width() > 64 && pm.height() > 64 && level < 8 { + level += 1; + pm = match self.images.get(&(g.asset, level)) { + Some(p) => p.clone(), + None => { + let half = Arc::new(halve(&pm)); + self.images.insert((g.asset, level), half.clone()); + half + } + }; + } + let rect = Rect::new(0.0, 0.0, g.size.0, g.size.1); + ctx.set_transform(f.view * xf * g.xf); + let sx = g.size.0 / pm.width().max(1) as f64; + let sy = g.size.1 / pm.height().max(1) as f64; + ctx.set_paint(vello_cpu::Image { image: vello_cpu::ImageSource::Pixmap(pm), sampler: peniko::ImageSampler::default().with_quality(peniko::ImageQuality::Medium) }); + ctx.set_paint_transform(Affine::scale_non_uniform(sx, sy)); + ctx.fill_rect(&rect); + ctx.reset_paint_transform(); + } + + fn draw_text(&mut self, ctx: &mut RenderContext, f: &Frame, cs: &ComposedStory, ft: &FrameText, xf: Affine) { + let db = FontDb::global(); + let doc = f.doc; + // Decorations under text (shading) and rules. + for d in &ft.decos { + if let Some(c) = doc.resolve_color(&d.color, d.tint) { + ctx.set_transform(f.view * xf); + ctx.set_paint(color_of(&c, 1.0)); + ctx.fill_rect(&d.rect); + } + } + let scale = (f.view * xf).determinant().abs().sqrt(); + // Batch glyph outlines per run style into one path (in frame inner space). + let mut batches: HashMap = HashMap::new(); + let mut lines_deco: Vec<(u32, kurbo::Rect)> = Vec::new(); + for l in &ft.lines { + let greek = f.opts.greek_below_px > 0.0 && l.ascent * scale < f.opts.greek_below_px; + if greek { + if let (Some(a), Some(_)) = (l.glyphs.first(), l.glyphs.last()) { + let r = kurbo::Rect::new(a.x, l.baseline - l.ascent * 0.5, l.end_x, l.baseline); + lines_deco.push((u32::MAX, r)); + } + continue; + } + for g in &l.glyphs { + if !g.visible { + continue; + } + let style = &cs.styles[g.style as usize]; + if style.underline || style.strikethrough { + let w = style.size / 14.0; + if style.underline { + lines_deco.push((g.style, kurbo::Rect::new(g.x, l.baseline + style.size * 0.12, g.x + g.adv, l.baseline + style.size * 0.12 + w))); + } + if style.strikethrough { + lines_deco.push((g.style, kurbo::Rect::new(g.x, l.baseline - style.size * 0.3, g.x + g.adv, l.baseline - style.size * 0.3 + w))); + } + } + let outline = db.outline(&g.face, g.gid); + if outline.elements().is_empty() { + continue; + } + let skew = if style.skew != 0.0 { Affine::new([1.0, 0.0, -style.skew.to_radians().tan(), 1.0, 0.0, 0.0]) } else { Affine::IDENTITY }; + let a = Affine::translate((g.x, l.baseline + g.y)) * skew * Affine::scale_non_uniform(g.sx, g.sy); + let b = batches.entry(g.style).or_default(); + for el in outline.elements() { + b.push(transform_el(a, *el)); + } + self.stats.glyphs += 1; + } + } + ctx.set_transform(f.view * xf); + for (si, bp) in &batches { + let st = &cs.styles[*si as usize]; + if let Some(c) = doc.resolve_color(&st.fill, st.fill_tint) { + ctx.set_paint(color_of(&c, 1.0)); + ctx.fill_path(bp); + } + if st.stroke != designcraft_color::swatch::NONE + && let Some(c) = doc.resolve_color(&st.stroke, st.stroke_tint) + { + ctx.set_paint(color_of(&c, 1.0)); + ctx.set_stroke(kurbo::Stroke::new(st.stroke_weight)); + ctx.stroke_path(bp); + } + } + for (si, r) in lines_deco { + let c = if si == u32::MAX { + designcraft_color::Color::gray(0.35) + } else { + let st = &cs.styles[si as usize]; + doc.resolve_color(&st.fill, st.fill_tint).unwrap_or(designcraft_color::Color::BLACK) + }; + ctx.set_paint(color_of(&c, if si == u32::MAX { 0.5 } else { 1.0 })); + ctx.fill_rect(&r); + } + } +} + +fn transform_el(a: Affine, el: kurbo::PathEl) -> kurbo::PathEl { + use kurbo::PathEl::*; + match el { + MoveTo(p) => MoveTo(a * p), + LineTo(p) => LineTo(a * p), + QuadTo(p1, p2) => QuadTo(a * p1, a * p2), + CurveTo(p1, p2, p3) => CurveTo(a * p1, a * p2, a * p3), + ClosePath => ClosePath, + } +} + +fn rect_overlaps(a: Rect, b: Rect) -> bool { + a.x0 < b.x1 && a.x1 > b.x0 && a.y0 < b.y1 && a.y1 > b.y0 +} + +pub fn color_of(c: &designcraft_color::Color, alpha: f32) -> peniko::Color { + let [r, g, b, a] = c.to_rgba8(alpha); + peniko::Color::from_rgba8(r, g, b, a) +} + +/// Set a swatch fill (solid or gradient) as the paint. Returns false for [None]/unknown. +fn set_fill_paint(ctx: &mut RenderContext, doc: &Document, swatch: &str, tint: f32, bounds: Rect, angle: Option) -> bool { + if let Some(g) = designcraft_color::swatch::resolve_gradient(&doc.swatches, swatch) { + let stops: Vec = g.expanded_stops().iter().map(|(o, c, a)| peniko::ColorStop::from((*o, color_of(c, *a)))).collect(); + if stops.is_empty() { + return false; + } + let c = bounds.center(); + let grad = match g.kind { + designcraft_color::GradientKind::Radial => { + let r = bounds.width().max(bounds.height()) / 2.0; + peniko::Gradient::new_radial(c, r as f32).with_stops(stops.as_slice()) + } + _ => { + let a = angle.unwrap_or(0.0).to_radians(); + let half = (bounds.width() * a.cos().abs() + bounds.height() * a.sin().abs()) / 2.0; + let d = Vec2::new(a.cos(), -a.sin()) * half; + peniko::Gradient::new_linear(c - d, c + d).with_stops(stops.as_slice()) + } + }; + ctx.set_paint(grad); + return true; + } + match doc.resolve_color(swatch, tint) { + Some(c) => { + ctx.set_paint(color_of(&c, 1.0)); + true + } + None => false, + } +} + +pub fn blend_mode(b: DcBlend) -> BlendMode { + use DcBlend as B; + let mix = match b { + B::Normal => Mix::Normal, + B::Darken => Mix::Darken, + B::Multiply => Mix::Multiply, + B::ColorBurn => Mix::ColorBurn, + B::Lighten => Mix::Lighten, + B::Screen => Mix::Screen, + B::ColorDodge => Mix::ColorDodge, + B::Overlay => Mix::Overlay, + B::SoftLight => Mix::SoftLight, + B::HardLight => Mix::HardLight, + B::Difference => Mix::Difference, + B::Exclusion => Mix::Exclusion, + B::Hue => Mix::Hue, + B::Saturation => Mix::Saturation, + B::Color => Mix::Color, + B::Luminosity => Mix::Luminosity, + }; + BlendMode::new(mix, Compose::SrcOver) +} + +/// Decode encoded image bytes into a premultiplied pixmap. +pub fn decode_pixmap(bytes: &[u8]) -> Option { + let img = image::load_from_memory(bytes).ok()?.to_rgba8(); + let (w, h) = img.dimensions(); + if w == 0 || h == 0 || w > u16::MAX as u32 || h > u16::MAX as u32 { + return None; + } + let data: Vec = img + .pixels() + .map(|p| { + let a = p[3] as u16; + let m = |c: u8| ((c as u16 * a + 127) / 255) as u8; + vello_cpu::color::PremulRgba8 { r: m(p[0]), g: m(p[1]), b: m(p[2]), a: p[3] } + }) + .collect(); + Some(Pixmap::from_parts(data, w as u16, h as u16)) +} + +/// Box-filter downsample by 2. +fn halve(pm: &Pixmap) -> Pixmap { + let (w, h) = (pm.width() as usize, pm.height() as usize); + let (nw, nh) = ((w / 2).max(1), (h / 2).max(1)); + let src = pm.data(); + let mut out = Vec::with_capacity(nw * nh); + for y in 0..nh { + for x in 0..nw { + let mut acc = [0u32; 4]; + for (dx, dy) in [(0, 0), (1, 0), (0, 1), (1, 1)] { + let sx = (2 * x + dx).min(w - 1); + let sy = (2 * y + dy).min(h - 1); + let p = src[sy * w + sx]; + acc[0] += p.r as u32; + acc[1] += p.g as u32; + acc[2] += p.b as u32; + acc[3] += p.a as u32; + } + out.push(vello_cpu::color::PremulRgba8 { r: (acc[0] / 4) as u8, g: (acc[1] / 4) as u8, b: (acc[2] / 4) as u8, a: (acc[3] / 4) as u8 }); + } + } + Pixmap::from_parts(out, nw as u16, nh as u16) +} + +#[cfg(not(target_arch = "wasm32"))] +fn now() -> u64 { + use std::time::{SystemTime, UNIX_EPOCH}; + SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_micros() as u64).unwrap_or(0) +} +#[cfg(target_arch = "wasm32")] +fn now() -> u64 { + 0 +} + +#[cfg(test)] +mod tests { + use super::*; + use designcraft_doc::build::NewDocument; + use designcraft_doc::{Fill, ParaFormat}; + + #[test] + fn renders_page_with_text_and_fill() { + let mut d = Document::new(&NewDocument::default()); + let lid = d.default_layer(); + let (fid, _) = d.add_text_frame(SpreadRef::Doc(0), Rect::new(36.0, 36.0, 576.0, 300.0), lid, "Hello DesignCraft", ParaFormat::default()).unwrap(); + let id = designcraft_doc::ItemId(d.alloc()); + let mut box_ = Item::new(id, lid, designcraft_doc::Shape::Rectangle, designcraft_geom::shapes::rectangle(Rect::new(36.0, 400.0, 136.0, 500.0))); + box_.fill = Fill::swatch("C=100 M=0 Y=0 K=0"); + d.insert_item(SpreadRef::Doc(0), box_, None).unwrap(); + let cache = Cache::new(); + let mut r = Renderer::new(); + r.threads = 0; + let img = r.render_page(&d, &cache, 0, 1.0, false, &RenderOptions::default()).unwrap(); + assert_eq!((img.width, img.height), (612, 792)); + // Paper is white, the box is cyan-ish, text drew some dark pixels. + assert_eq!(img.pixel(300, 700), [255, 255, 255, 255]); + let c = img.pixel(80, 450); + assert!(c[0] < 80 && c[2] > 150, "{c:?}"); + let dark = (36..300).flat_map(|x| (36..60).map(move |y| (x, y))).filter(|&(x, y)| img.pixel(x, y)[0] < 100).count(); + assert!(dark > 50, "text pixels: {dark}"); + let _ = fid; + assert!(r.stats.glyphs >= 15); + } +} diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml new file mode 100644 index 00000000..747a74e2 --- /dev/null +++ b/crates/tools/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "designcraft-tools" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "DesignCraft tools: pointer events in, commands and overlays out (Selection, Direct Selection, frames, Type, Hand, Zoom…)" + +[lints] +workspace = true + +[dependencies] +designcraft-geom = { workspace = true } +designcraft-color = { workspace = true } +designcraft-doc = { workspace = true } +designcraft-compose = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } diff --git a/crates/tools/src/catalog.rs b/crates/tools/src/catalog.rs new file mode 100644 index 00000000..7d145244 --- /dev/null +++ b/crates/tools/src/catalog.rs @@ -0,0 +1,71 @@ +//! The tool catalogue: ids, labels, shortcuts and Tools-panel groups (InDesign's order). + +use serde::Serialize; + +#[derive(Clone, Copy, Debug, Serialize)] +pub struct ToolInfo { + pub id: &'static str, + pub label: &'static str, + pub shortcut: Option<&'static str>, + pub icon: &'static str, +} + +const fn t(id: &'static str, label: &'static str, shortcut: Option<&'static str>, icon: &'static str) -> ToolInfo { + ToolInfo { id, label, shortcut, icon } +} + +/// Tools-panel groups in order (the first tool of each group shows by default). A `None` group +/// marks a separator. +pub const TOOL_GROUPS: &[&[ToolInfo]] = &[ + &[t("selection", "Selection Tool", Some("V"), "tool-selection")], + &[t("directSelection", "Direct Selection Tool", Some("A"), "tool-direct")], + &[t("page", "Page Tool", Some("Shift+P"), "tool-page")], + &[t("gap", "Gap Tool", Some("U"), "tool-gap")], + &[t("contentCollector", "Content Collector Tool", Some("B"), "tool-collector"), t("contentPlacer", "Content Placer Tool", Some("B"), "tool-placer")], + &[], + &[ + t("type", "Type Tool", Some("T"), "tool-type"), + t("typeOnPath", "Type on a Path Tool", Some("Shift+T"), "tool-type-path"), + t("verticalType", "Vertical Type Tool", None, "tool-type-vertical"), + t("verticalTypeOnPath", "Vertical Type on a Path Tool", None, "tool-type-path"), + ], + &[t("line", "Line Tool", Some("\\"), "tool-line")], + &[ + t("pen", "Pen Tool", Some("P"), "tool-pen"), + t("addAnchor", "Add Anchor Point Tool", Some("="), "tool-pen-add"), + t("deleteAnchor", "Delete Anchor Point Tool", Some("-"), "tool-pen-delete"), + t("convertDirection", "Convert Direction Point Tool", Some("Shift+C"), "tool-anchor"), + ], + &[t("pencil", "Pencil Tool", Some("N"), "tool-pencil"), t("smooth", "Smooth Tool", None, "tool-smooth"), t("erase", "Erase Tool", None, "tool-erase")], + &[ + t("rectangleFrame", "Rectangle Frame Tool", Some("F"), "tool-rect-frame"), + t("ellipseFrame", "Ellipse Frame Tool", None, "tool-ellipse-frame"), + t("polygonFrame", "Polygon Frame Tool", None, "tool-polygon-frame"), + ], + &[t("rectangle", "Rectangle Tool", Some("M"), "tool-rect"), t("ellipse", "Ellipse Tool", Some("L"), "tool-ellipse"), t("polygon", "Polygon Tool", None, "tool-polygon")], + &[t("scissors", "Scissors Tool", Some("C"), "tool-scissors")], + &[ + t("freeTransform", "Free Transform Tool", Some("E"), "tool-free-transform"), + t("rotate", "Rotate Tool", Some("R"), "tool-rotate"), + t("scale", "Scale Tool", Some("S"), "tool-scale"), + t("shear", "Shear Tool", Some("O"), "tool-shear"), + ], + &[t("gradientSwatch", "Gradient Swatch Tool", Some("G"), "tool-gradient"), t("gradientFeather", "Gradient Feather Tool", Some("Shift+G"), "tool-gradient-feather")], + &[t("note", "Note Tool", None, "tool-note")], + &[ + t("colorTheme", "Color Theme Tool", Some("Shift+I"), "tool-color-theme"), + t("eyedropper", "Eyedropper Tool", Some("I"), "tool-eyedropper"), + t("measure", "Measure Tool", Some("K"), "tool-measure"), + ], + &[t("hand", "Hand Tool", Some("H"), "tool-hand")], + &[t("zoom", "Zoom Tool", Some("Z"), "tool-zoom")], +]; + +pub fn tool_info(id: &str) -> Option { + TOOL_GROUPS.iter().flat_map(|g| g.iter()).find(|t| t.id == id).copied() +} + +/// Tool for a single-key shortcut (`"T"`, `"Shift+P"`). +pub fn tool_for_shortcut(key: &str) -> Option<&'static str> { + TOOL_GROUPS.iter().flat_map(|g| g.iter()).find(|t| t.shortcut == Some(key)).map(|t| t.id) +} diff --git a/crates/tools/src/layout.rs b/crates/tools/src/layout.rs new file mode 100644 index 00000000..3d433c8f --- /dev/null +++ b/crates/tools/src/layout.rs @@ -0,0 +1,101 @@ +//! Where spreads sit on the canvas (the pasteboard): stacked vertically, spines aligned at x = 0, +//! parents shown on their own canvas when a parent spread is being edited. + +use designcraft_doc::{Document, SpreadRef}; +use designcraft_geom::{Point, Rect, Vec2}; +use serde::Serialize; + +#[derive(Clone, Copy, Debug, PartialEq, Serialize)] +pub struct SpreadSlot { + pub spread: SpreadRef, + /// canvas = spread + offset + pub offset: Vec2, + /// Spread page bounds in canvas coordinates. + pub bounds: Rect, +} + +#[derive(Clone, Debug, Default, PartialEq, Serialize)] +pub struct CanvasLayout { + pub slots: Vec, + /// Pasteboard extent (canvas coordinates). + pub pasteboard: Rect, +} + +/// Vertical gap between spreads (points). +pub const SPREAD_GAP: f64 = 72.0; + +impl CanvasLayout { + /// Layout of the document spreads (or the parent spreads when `parents` is true). + pub fn new(doc: &Document, parents: bool) -> Self { + let list: Vec = if parents { (0..doc.parents.len()).map(SpreadRef::Parent).collect() } else { (0..doc.spreads.len()).map(SpreadRef::Doc).collect() }; + let mut slots = Vec::with_capacity(list.len()); + let mut y = 0.0; + let mut pb: Option = None; + let (px, py) = doc.settings.pasteboard; + for r in list { + let Some(sp) = doc.spread(r) else { continue }; + let b = sp.bounds(); + let offset = Vec2::new(-sp.spine_x(), y - b.y0); + let cb = b + offset; + let pr = Rect::new(cb.x0 - px.max(b.width()), cb.y0 - py * 0.5, cb.x1 + px.max(b.width()), cb.y1 + py * 0.5); + pb = Some(pb.map_or(pr, |p| p.union(pr))); + slots.push(SpreadSlot { spread: r, offset, bounds: cb }); + y += b.height() + SPREAD_GAP; + } + let pasteboard = pb.unwrap_or(Rect::new(-500.0, -500.0, 500.0, 500.0)).inflate(0.0, py * 0.5); + CanvasLayout { slots, pasteboard } + } + + /// The spread under (or nearest to) a canvas point, and the point in spread coordinates. + pub fn spread_at(&self, p: Point) -> Option<(SpreadRef, Point)> { + let s = self.slots.iter().min_by(|a, b| dist_y(a.bounds, p.y).total_cmp(&dist_y(b.bounds, p.y)))?; + Some((s.spread, p - s.offset)) + } + + pub fn slot(&self, r: SpreadRef) -> Option<&SpreadSlot> { + self.slots.iter().find(|s| s.spread == r) + } + + pub fn offset(&self, r: SpreadRef) -> Vec2 { + self.slot(r).map(|s| s.offset).unwrap_or(Vec2::ZERO) + } + + /// Canvas rect of a document page. + pub fn page_rect(&self, doc: &Document, abs: usize) -> Option { + let (si, pi) = doc.page_loc(abs)?; + let off = self.offset(SpreadRef::Doc(si)); + Some(doc.spreads[si].pages[pi].bounds() + off) + } +} + +fn dist_y(r: Rect, y: f64) -> f64 { + if y < r.y0 - SPREAD_GAP / 2.0 { + r.y0 - y + } else if y > r.y1 + SPREAD_GAP / 2.0 { + y - r.y1 + } else { + 0.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use designcraft_doc::build::NewDocument; + + #[test] + fn spreads_stack_on_the_spine() { + let d = Document::new(&NewDocument { pages: 3, ..Default::default() }); + let l = CanvasLayout::new(&d, false); + assert_eq!(l.slots.len(), 2); + // Page 1 is a right page: it starts at the spine (x = 0). + assert_eq!(l.slots[0].bounds.x0, 0.0); + // Spread 2 (pages 2–3) straddles the spine. + assert_eq!(l.slots[1].bounds.x0, -612.0); + assert_eq!(l.slots[1].bounds.y0, 792.0 + SPREAD_GAP); + let (r, p) = l.spread_at(Point::new(-100.0, 900.0)).unwrap(); + assert_eq!(r, SpreadRef::Doc(1)); + assert_eq!(p, Point::new(512.0, 900.0 - 792.0 - SPREAD_GAP)); + assert_eq!(l.page_rect(&d, 2).unwrap().x0, 0.0); + } +} diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs new file mode 100644 index 00000000..af8c0b1d --- /dev/null +++ b/crates/tools/src/lib.rs @@ -0,0 +1,249 @@ +//! DesignCraft tools: pointer events in → commands and overlays out. +//! +//! Tools never mutate the document. They emit [`Action`]s the engine executes: `Begin` snapshots +//! the document, each `Preview` re-applies one command on top of the snapshot, `Commit` records +//! the last preview as one undo step. `Exec` runs a command immediately. Every gesture is therefore +//! replayable by the control channel and MCP, and tools are testable without a UI. +//! +//! Pointer positions are **canvas** coordinates (see [`layout::CanvasLayout`]). +#![forbid(unsafe_code)] + +pub mod catalog; +mod frame; +pub mod layout; +mod nav; +mod select; +mod text; + +use designcraft_compose::Cache; +use designcraft_doc::{Document, Item, ItemId, Selection, SpreadRef}; +use designcraft_geom::{Affine, BezPath, Point, Rect}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +pub use catalog::{TOOL_GROUPS, ToolInfo, tool_for_shortcut, tool_info}; +pub use layout::CanvasLayout; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct Mods { + #[serde(default)] + pub shift: bool, + #[serde(default)] + pub alt: bool, + /// Command on macOS, Ctrl elsewhere. + #[serde(default)] + pub cmd: bool, + #[serde(default)] + pub ctrl: bool, + #[serde(default)] + pub space: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum PointerKind { + Down, + Drag, + Up, + Move, + DoubleClick, +} + +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +pub struct PointerEvent { + pub kind: PointerKind, + /// Canvas coordinates. + pub pos: Point, + #[serde(default)] + pub mods: Mods, +} + +impl PointerEvent { + pub fn new(kind: PointerKind, x: f64, y: f64) -> Self { + Self { kind, pos: Point::new(x, y), mods: Mods::default() } + } + pub fn with_mods(mut self, m: Mods) -> Self { + self.mods = m; + self + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum ToolKey { + Enter, + Escape, + Backspace, + Delete, + Up, + Down, + Left, + Right, + Home, + End, + Tab, + PageUp, + PageDown, +} + +/// What a tool asks the engine to do. +#[derive(Clone, Debug, PartialEq)] +pub enum Action { + Begin(String), + Preview(String, Value), + Commit, + Cancel, + Exec(String, Value), + /// Ask the UI to open a dialog. + Dialog(String, Value), + SwitchTool(String), + /// Ask the UI to pan/zoom: `{"pan":[dx,dy]}` (screen px) or `{"zoomAt":[x,y], "factor":f}` (canvas). + View(Value), +} + +/// Read-only context a tool sees. +pub struct ToolContext<'a> { + pub doc: &'a Document, + pub selection: &'a Selection, + pub cache: &'a Cache, + pub layout: &'a CanvasLayout, + /// Screen pixels per point. + pub zoom: f64, + /// Layer new items go on. + pub layer: designcraft_doc::LayerId, + pub snap: bool, +} + +impl ToolContext<'_> { + pub fn tol(&self, px: f64) -> f64 { + px / self.zoom.max(1e-9) + } + + /// Frontmost unlocked item under a canvas point. + pub fn hit(&self, p: Point) -> Option<(SpreadRef, ItemId)> { + let (sr, sp) = self.layout.spread_at(p)?; + let SpreadRef::Doc(si) = sr else { + return self.hit_parent(sr, sp); + }; + self.doc.hit_item(si, sp, self.tol(4.0)).map(|id| (sr, id)) + } + + fn hit_parent(&self, sr: SpreadRef, sp: Point) -> Option<(SpreadRef, ItemId)> { + let s = self.doc.spread(sr)?; + s.items.iter().rev().find(|it| !it.locked && designcraft_doc::edit_hit(it, sp, self.tol(4.0))).map(|it| (sr, it.id)) + } + + /// Spread-space → canvas transform of the spread holding item `id`. + pub fn item_canvas_xf(&self, id: ItemId) -> Option { + let loc = self.doc.find(id)?; + let off = self.layout.offset(loc.spread); + Some(Affine::translate(off) * self.doc.parent_xf(&loc)) + } + + pub fn item(&self, id: ItemId) -> Option<&Item> { + self.doc.item(id) + } + + /// Canvas bounds of the selected items. + pub fn selection_bounds(&self) -> Option { + let mut r: Option = None; + for id in &self.selection.items { + let (Some(it), Some(xf)) = (self.doc.item(*id), self.item_canvas_xf(*id)) else { continue }; + let b = xf.transform_rect_bbox(it.bounds()); + r = Some(r.map_or(b, |r| r.union(b))); + } + r + } +} + +/// Visual feedback (canvas coordinates) drawn by the UI. +#[derive(Clone, Debug, PartialEq)] +pub enum Overlay { + Marquee(Rect), + /// Preview outline of a frame being drawn. + Path { path: BezPath, color: [u8; 3], dashed: bool }, + Line { a: Point, b: Point, color: [u8; 3], dashed: bool }, + /// Measurement pill near the cursor. + Measure { p: Point, text: String }, + /// Smart guide line in the smart-guide colour. + Guide { a: Point, b: Point }, +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum Cursor { + #[default] + Arrow, + ArrowHollow, + Move, + Crosshair, + ResizeH, + ResizeV, + ResizeNwSe, + ResizeNeSw, + Rotate, + Pen, + Text, + Hand, + HandGrab, + ZoomIn, + ZoomOut, + Eyedropper, + LoadedText, + LoadedGraphic, + NotAllowed, +} + +pub trait Tool: Send { + fn id(&self) -> &'static str; + fn pointer(&mut self, cx: &ToolContext, ev: &PointerEvent) -> Vec; + fn key(&mut self, _cx: &ToolContext, _key: ToolKey, _mods: Mods) -> Vec { + vec![] + } + fn overlays(&self, _cx: &ToolContext) -> Vec { + vec![] + } + fn cursor(&self, _cx: &ToolContext, _p: Point, _mods: Mods) -> Cursor { + Cursor::Arrow + } + fn busy(&self) -> bool { + false + } + /// The tool takes typed text (Type tool with a caret): single-key shortcuts are suppressed. + fn wants_text(&self, _cx: &ToolContext) -> bool { + false + } +} + +pub fn create(id: &str) -> Box { + match id { + "selection" => Box::new(select::SelectionTool::new(false)), + "directSelection" => Box::new(select::SelectionTool::new(true)), + "rectangleFrame" | "ellipseFrame" | "polygonFrame" | "rectangle" | "ellipse" | "polygon" | "line" => Box::new(frame::FrameTool::new(id)), + "type" => Box::new(text::TypeTool::default()), + "hand" => Box::new(nav::HandTool::default()), + "zoom" => Box::new(nav::ZoomTool::default()), + other => Box::new(NoopTool(tool_info(other).map(|t| t.id).unwrap_or("selection"))), + } +} + +/// Placeholder for tools whose behaviour hasn't landed yet. +pub struct NoopTool(&'static str); + +impl Tool for NoopTool { + fn id(&self) -> &'static str { + self.0 + } + fn pointer(&mut self, _cx: &ToolContext, _ev: &PointerEvent) -> Vec { + vec![] + } +} + +pub(crate) fn rect_json(r: Rect) -> Value { + serde_json::json!([r.x0, r.y0, r.x1, r.y1]) +} + +pub(crate) fn spread_json(r: SpreadRef) -> Value { + serde_json::to_value(r).unwrap_or(Value::Null) +} + +#[cfg(test)] +mod tests;