commit 274012f854a4d90dfe890d5d201a7b40717c9b93 Author: trandinhnamuet Date: Wed Jun 17 22:34:06 2026 +0700 Initial commit: FoFreeXit Phase 1 (Viewer) + Phase 2 (Annotate) PDF viewer (render/search/text-select/thumbnails/outline) and annotation engine (Highlight/Underline/Strikeout/Square/FreeText/Note) over PDFium + lopdf, with Unicode font embedding for Vietnamese text and undo/redo. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..082ee03 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +/target +**/*.rs.bk +Cargo.lock.bak + +# PDFium prebuilt binary (tải bằng scripts/fetch-pdfium.ps1) +/pdfium/ +/pdfium.dll +/pdfium.dll.lib + +# Tauri / node +/app/node_modules +/app/dist +/app/src-tauri/target + +# Ảnh tạm khi test render +/tmp-out/ +*.tmp.png + +# File PDF thật của user (hồ sơ/kinh doanh cá nhân) — chỉ dùng test local, +# không đẩy lên repo công khai. +/pdf-file-to-test/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..cf8dbd3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1832 @@ +# 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 = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "built" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "ecb" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" +dependencies = [ + "cipher", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[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 = "ff-cli" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "ff-engine", +] + +[[package]] +name = "ff-cos" +version = "0.1.0" +dependencies = [ + "thiserror", +] + +[[package]] +name = "ff-engine" +version = "0.1.0" +dependencies = [ + "anyhow", + "ff-cos", + "ff-pdmodel", + "image", + "lopdf", + "pdfium-render", + "thiserror", + "ttf-parser", +] + +[[package]] +name = "ff-pdmodel" +version = "0.1.0" +dependencies = [ + "ff-cos", + "thiserror", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[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", + "wasip2", +] + +[[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 = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[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", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "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", +] + +[[package]] +name = "imgref" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jiff" +version = "0.2.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102" +dependencies = [ + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link", +] + +[[package]] +name = "jiff-static" +version = "0.2.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "log" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lopdf" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fa2559e99ba0f26a12458aabc754432c805bbb8cba516c427825a997af1fb7" +dependencies = [ + "aes", + "bitflags", + "cbc", + "chrono", + "ecb", + "encoding_rs", + "flate2", + "indexmap", + "itoa", + "jiff", + "log", + "md-5", + "nom", + "nom_locate", + "rand", + "rangemap", + "rayon", + "sha2", + "stringprep", + "thiserror", + "time", + "weezl", +] + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[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 = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom_locate" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d" +dependencies = [ + "bytecount", + "memchr", + "nom", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[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 = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "pdfium-render" +version = "0.8.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6553f6604a52b3203db7b4e9d51eb4dd193cf455af9e56d40cab6575b547b679" +dependencies = [ + "bitflags", + "bytemuck", + "bytes", + "chrono", + "console_error_panic_hook", + "console_log", + "image", + "itertools", + "js-sys", + "libloading", + "log", + "maybe-owned", + "once_cell", + "utf16string", + "vecmath", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piston-float" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590" + +[[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", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[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.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[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.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +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 = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +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", +] + +[[package]] +name = "rangemap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[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 = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "time" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "utf16string" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b62a1e85e12d5d712bf47a85f426b73d303e2d00a90de5f3004df3596e9d216" +dependencies = [ + "byteorder", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "vecmath" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ae1e0d85bca567dee1dcf87fb1ca2e792792f66f87dced8381f99cd91156a" +dependencies = [ + "piston-float", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[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 = "wasm-bindgen" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[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 = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "zerocopy" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[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 new file mode 100644 index 0000000..18b8351 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[workspace] +resolver = "2" +members = [ + "crates/ff-cos", + "crates/ff-pdmodel", + "crates/ff-engine", + "crates/ff-cli", +] + +[workspace.package] +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +repository = "" +description = "FoFreeXit - open source PDF editor (Foxit alternative)" + +[workspace.dependencies] +anyhow = "1" +thiserror = "2" diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c0843f --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# FoFreeXit + +**Mục tiêu dự án:** Xây dựng một phần mềm chỉnh sửa PDF trên desktop có thể thay thế Foxit PDF Editor (và một phần Adobe Acrobat) cho các nhu cầu phổ biến — miễn phí / mã nguồn mở. + +> Dự án được thực hiện qua nhiều session Claude Code. Token và thời gian không phải là ràng buộc. Ưu tiên số 1: **tạo ra được một sản phẩm dùng được, thay thế Foxit cho các tác vụ chính**. + +## Tài liệu + +| File | Nội dung | +|------|----------| +| [docs/01-research.md](docs/01-research.md) | Khảo sát tính năng Foxit, tính năng "đáng tiền", khó khăn kỹ thuật, thuật toán Foxit/Adobe, khảo sát thư viện PDF | +| [docs/02-tech-stack.md](docs/02-tech-stack.md) | Phân tích & lựa chọn ngôn ngữ / framework / engine | +| [docs/03-roadmap.md](docs/03-roadmap.md) | Lộ trình theo phase, mục tiêu, phương pháp, định nghĩa hoàn thành (DoD) | +| [docs/04-architecture.md](docs/04-architecture.md) | Kiến trúc kỹ thuật chi tiết (sẽ chi tiết hóa dần) | + +## Trạng thái hiện tại + +- [x] Phase 0 — Nghiên cứu & lập kế hoạch +- [x] **Đã chốt stack:** **Rust + Tauri** (App/UI) trên engine **PDFium + QPDF** (xem [docs/02-tech-stack.md](docs/02-tech-stack.md)) +- [x] **Phase 1 — Engine core + Viewer** ✅ HOÀN TẤT (10/10 test xanh) + - [x] Cargo workspace + app Tauri; engine render qua PDFium + - [x] CLI `ff`: `info`/`render`/`pages`/`text`/`search`/`outline` + - [x] Engine: render, `page_dims`, `extract_text`, `search`(+toạ độ), `outline`, `page_char_boxes` + - [x] Viewer: mở file (hộp thoại), cuộn liên tục + lazy render (file 1000+ trang), zoom/Fit, thumbnails, outline, tìm kiếm + highlight, **chọn & copy text** (text-layer) + - Tổng kết: [docs/06-phase1-summary.md](docs/06-phase1-summary.md) · **Checklist test cho bạn**: [docs/07-phase1-user-tests.md](docs/07-phase1-user-tests.md) +- [x] **Phase 2 — Annotate** ✅ lõi hoàn tất (13/13 test xanh) + - [x] Engine: 6 loại annotation (Highlight/Underline/Strikeout/Square/FreeText/Note) + lưu file + đọc lại — round-trip test + - [x] UI: thanh công cụ + vẽ bằng chuột + preview + chọn màu + tab Chú thích + lưu qua hộp thoại + - [ ] Follow-up: Ink, sửa/di chuyển annotation đã lưu, XFDF — xem [docs/08-phase2-summary.md](docs/08-phase2-summary.md) + - **Checklist test cho bạn**: [docs/09-phase2-user-tests.md](docs/09-phase2-user-tests.md) +- [ ] **Phase 3 — Organize trang + lưu file vững** (kế tiếp) — xem [docs/03-roadmap.md](docs/03-roadmap.md) + +Build & chạy: xem [docs/05-dev-setup.md](docs/05-dev-setup.md). + +## Nguyên tắc làm việc qua nhiều session + +1. **Tài liệu là nguồn chân lý.** Mọi quyết định kiến trúc phải được ghi vào `docs/`. +2. Mỗi phase có **Definition of Done** rõ ràng và **test** kèm theo. +3. Không viết lại engine PDF từ con số 0 ở giai đoạn đầu — đứng trên vai người khổng lồ (PDFium/QPDF), tự xây phần "editor" và "UX". +4. Ưu tiên giấy phép **permissive** (BSD/Apache/MIT) để sản phẩm có thể tự do phân phối. diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock new file mode 100644 index 0000000..2df15c8 --- /dev/null +++ b/app/src-tauri/Cargo.lock @@ -0,0 +1,5726 @@ +# 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 = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "atk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[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 = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "brotli" +version = "8.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "built" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.13.0", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "cargo_toml" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" +dependencies = [ + "serde", + "toml 0.9.12+spec-1.1.0", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.13.0", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.13.0", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ctor" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dbus" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.0", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dlopen2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dom_query" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +dependencies = [ + "bit-set", + "cssparser", + "foldhash 0.2.0", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +dependencies = [ + "serde", +] + +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecb" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" +dependencies = [ + "cipher", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "embed-resource" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 1.1.2+spec-1.1.0", + "vswhom", + "winreg", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[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 = "ff-cos" +version = "0.1.0" +dependencies = [ + "thiserror 2.0.18", +] + +[[package]] +name = "ff-engine" +version = "0.1.0" +dependencies = [ + "anyhow", + "ff-cos", + "ff-pdmodel", + "image", + "lopdf", + "pdfium-render", + "thiserror 2.0.18", + "ttf-parser", +] + +[[package]] +name = "ff-pdmodel" +version = "0.1.0" +dependencies = [ + "ff-cos", + "thiserror 2.0.18", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fofreexit-app" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "ff-engine", + "image", + "pdfium-render", + "serde", + "serde_json", + "tauri", + "tauri-build", + "tauri-plugin-dialog", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[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 = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.13.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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 = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" +dependencies = [ + "log", + "markup5ever", +] + +[[package]] +name = "http" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" +dependencies = [ + "byteorder", + "png 0.17.16", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[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", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "rgb", + "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", +] + +[[package]] +name = "imgref" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jiff" +version = "0.2.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102" +dependencies = [ + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link 0.2.1", +] + +[[package]] +name = "jiff-static" +version = "0.2.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonptr" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.13.0", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading 0.7.4", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "libfuzzer-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libredox" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +dependencies = [ + "libc", +] + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lopdf" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fa2559e99ba0f26a12458aabc754432c805bbb8cba516c427825a997af1fb7" +dependencies = [ + "aes", + "bitflags 2.13.0", + "cbc", + "chrono", + "ecb", + "encoding_rs", + "flate2", + "indexmap 2.14.0", + "itoa", + "jiff", + "log", + "md-5", + "nom", + "nom_locate", + "rand", + "rangemap", + "rayon", + "sha2", + "stringprep", + "thiserror 2.0.18", + "time", + "weezl", +] + +[[package]] +name = "markup5ever" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[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 = "mio" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[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 = "muda" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png 0.18.1", + "serde", + "thiserror 2.0.18", + "windows-sys 0.61.2", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.0", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom_locate" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d" +dependencies = [ + "bytecount", + "memchr", + "nom", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", + "objc2-exception-helper", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.13.0", + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.0", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" +dependencies = [ + "bitflags 2.13.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "pdfium-render" +version = "0.8.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6553f6604a52b3203db7b4e9d51eb4dd193cf455af9e56d40cab6575b547b679" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "bytes", + "chrono", + "console_error_panic_hook", + "console_log", + "image", + "itertools", + "js-sys", + "libloading 0.9.0", + "log", + "maybe-owned", + "once_cell", + "utf16string", + "vecmath", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piston-float" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plist" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" +dependencies = [ + "base64 0.22.1", + "indexmap 2.14.0", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.12+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.39.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +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 = "rangemap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[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 = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.0", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reqwest" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "sync_wrapper", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672" +dependencies = [ + "block2", + "dispatch2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.60.2", +] + +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", + "url", + "uuid", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.117", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "selectors" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" +dependencies = [ + "bitflags 2.13.0", + "cssparser", + "derive_more", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_with" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" +dependencies = [ + "base64 0.22.1", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "servo_arc" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "socket2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "softbuffer" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" +dependencies = [ + "bytemuck", + "js-sys", + "ndk", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle", + "redox_syscall", + "tracing", + "wasm-bindgen", + "web-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "swift-rs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.2", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.35.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" +dependencies = [ + "bitflags 2.13.0", + "block2", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dbus", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni", + "libc", + "log", + "ndk", + "ndk-sys", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "once_cell", + "parking_lot", + "percent-encoding", + "raw-window-handle", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tauri" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437404997acf375d85f1177afa7e11bb971f274ed6a7b83a2a3e339015f4cc28" +dependencies = [ + "anyhow", + "bytes", + "cookie", + "dirs", + "dunce", + "embed_plist", + "getrandom 0.3.4", + "glob", + "gtk", + "heck 0.5.0", + "http", + "jni", + "libc", + "log", + "mime", + "muda", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "percent-encoding", + "plist", + "raw-window-handle", + "reqwest", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "swift-rs", + "tauri-build", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils", + "thiserror 2.0.18", + "tokio", + "tray-icon", + "url", + "webkit2gtk", + "webview2-com", + "window-vibrancy", + "windows", +] + +[[package]] +name = "tauri-build" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa1f9055fc23919a54e4e125052bed16ed04aef0487086e758fe01a67b451c7" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs", + "glob", + "heck 0.5.0", + "json-patch", + "schemars 0.8.22", + "semver", + "serde", + "serde_json", + "tauri-utils", + "tauri-winres", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a0319528a025a38c4078e7dae2c446f4e63620ddb0659a643ede1cb38f90e9" +dependencies = [ + "base64 0.22.1", + "brotli", + "ico", + "json-patch", + "plist", + "png 0.17.16", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "syn 2.0.117", + "tauri-utils", + "thiserror 2.0.18", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6cb4e3896c21d2f6da5b31251d2faea0153bba56ed0e970f918115dbee4924" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-plugin" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e126abc9e84e35cdfd01596140a73a1850cdb0df0a23acf0185776c30b469a6e" +dependencies = [ + "anyhow", + "glob", + "plist", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri-utils", + "walkdir", +] + +[[package]] +name = "tauri-plugin-dialog" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65981abb771e74e571a38196c3baa11c459379164791eba0e67abc1a5fac9884" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror 2.0.18", + "url", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371" +dependencies = [ + "anyhow", + "dunce", + "glob", + "log", + "objc2-foundation", + "percent-encoding", + "schemars 0.8.22", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "tauri-utils", + "thiserror 2.0.18", + "toml 1.1.2+spec-1.1.0", + "url", +] + +[[package]] +name = "tauri-runtime" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48222d7116c8807eaa6fe2f372e023fae125084e61e6eca6d70b7961cdf129ef" +dependencies = [ + "cookie", + "dpi", + "gtk", + "http", + "jni", + "objc2", + "objc2-ui-kit", + "objc2-web-kit", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror 2.0.18", + "url", + "webkit2gtk", + "webview2-com", + "windows", +] + +[[package]] +name = "tauri-runtime-wry" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b83849ee63ecb27a8e8d0fe51915ca215076914aca43f96db1179f0f415f6cd9" +dependencies = [ + "gtk", + "http", + "jni", + "log", + "objc2", + "objc2-app-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "softbuffer", + "tao", + "tauri-runtime", + "tauri-utils", + "url", + "webkit2gtk", + "webview2-com", + "windows", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092379df9a707631978e6c56b1bc2401d387f01e2d4a3c123360d167bbb9aa95" +dependencies = [ + "anyhow", + "brotli", + "cargo_metadata", + "ctor", + "dom_query", + "dunce", + "glob", + "http", + "infer", + "json-patch", + "log", + "memchr", + "phf", + "plist", + "proc-macro2", + "quote", + "regex", + "schemars 0.8.22", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror 2.0.18", + "toml 1.1.2+spec-1.1.0", + "url", + "urlpattern", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-winres" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" +dependencies = [ + "dunce", + "embed-resource", + "toml 1.1.2+spec-1.1.0", +] + +[[package]] +name = "tendril" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" +dependencies = [ + "new_debug_unreachable", + "utf-8", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "time" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.3", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.14.0", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.0", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tray-icon" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "once_cell", + "png 0.18.1", + "serde", + "thiserror 2.0.18", + "windows-sys 0.61.2", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-ucd-ident" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "urlpattern" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +dependencies = [ + "regex", + "serde", + "unic-ucd-ident", + "url", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf16string" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b62a1e85e12d5d712bf47a85f426b73d303e2d00a90de5f3004df3596e9d216" +dependencies = [ + "byteorder", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "vecmath" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ae1e0d85bca567dee1dcf87fb1ca2e792792f66f87dced8381f99cd91156a" +dependencies = [ + "piston-float", +] + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[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 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.13.0", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web_atoms" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webview2-com" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "webview2-com-sys" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" +dependencies = [ + "thiserror 2.0.18", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +dependencies = [ + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "raw-window-handle", + "windows-sys 0.59.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.13.0", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wry" +version = "0.55.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" +dependencies = [ + "base64 0.22.1", + "block2", + "cookie", + "crossbeam-channel", + "dirs", + "dom_query", + "dpi", + "dunce", + "gdkx11", + "gtk", + "http", + "javascriptcore-rs", + "jni", + "libc", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "sha2", + "soup3", + "tao-macros", + "thiserror 2.0.18", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[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/app/src-tauri/Cargo.toml b/app/src-tauri/Cargo.toml new file mode 100644 index 0000000..ae91d47 --- /dev/null +++ b/app/src-tauri/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "fofreexit-app" +version = "0.1.0" +edition = "2021" +description = "FoFreeXit desktop app (Tauri shell)" +license = "Apache-2.0" + +# Detach from the main crates/* workspace (Tauri uses its own build profiles). +[workspace] + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +tauri = { version = "2", features = [] } +tauri-plugin-dialog = "2" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +base64 = "0.22" +image = "0.25" +pdfium-render = "0.8" +ff-engine = { path = "../../crates/ff-engine" } + +[profile.release] +opt-level = "s" +lto = true +strip = true diff --git a/app/src-tauri/build.rs b/app/src-tauri/build.rs new file mode 100644 index 0000000..d860e1e --- /dev/null +++ b/app/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/app/src-tauri/capabilities/default.json b/app/src-tauri/capabilities/default.json new file mode 100644 index 0000000..772369e --- /dev/null +++ b/app/src-tauri/capabilities/default.json @@ -0,0 +1,7 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "Quyền mặc định cho cửa sổ chính.", + "windows": ["main"], + "permissions": ["core:default", "dialog:default"] +} diff --git a/app/src-tauri/gen/schemas/acl-manifests.json b/app/src-tauri/gen/schemas/acl-manifests.json new file mode 100644 index 0000000..f2f210a --- /dev/null +++ b/app/src-tauri/gen/schemas/acl-manifests.json @@ -0,0 +1 @@ +{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/app/src-tauri/gen/schemas/capabilities.json b/app/src-tauri/gen/schemas/capabilities.json new file mode 100644 index 0000000..f5dcdb4 --- /dev/null +++ b/app/src-tauri/gen/schemas/capabilities.json @@ -0,0 +1 @@ +{"default":{"identifier":"default","description":"Quyền mặc định cho cửa sổ chính.","local":true,"windows":["main"],"permissions":["core:default","dialog:default"]}} \ No newline at end of file diff --git a/app/src-tauri/gen/schemas/desktop-schema.json b/app/src-tauri/gen/schemas/desktop-schema.json new file mode 100644 index 0000000..24c9001 --- /dev/null +++ b/app/src-tauri/gen/schemas/desktop-schema.json @@ -0,0 +1,2358 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CapabilityFile", + "description": "Capability formats accepted in a capability file.", + "anyOf": [ + { + "description": "A single capability.", + "allOf": [ + { + "$ref": "#/definitions/Capability" + } + ] + }, + { + "description": "A list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + { + "description": "A list of capabilities.", + "type": "object", + "required": [ + "capabilities" + ], + "properties": { + "capabilities": { + "description": "The list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + } + } + } + ], + "definitions": { + "Capability": { + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows' and webviews' fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", + "type": "object", + "required": [ + "identifier", + "permissions" + ], + "properties": { + "identifier": { + "description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`", + "type": "string" + }, + "description": { + "description": "Description of what the capability is intended to allow on associated windows.\n\nIt should contain a description of what the grouped permissions should allow.\n\n## Example\n\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.", + "default": "", + "type": "string" + }, + "remote": { + "description": "Configure remote URLs that can use the capability permissions.\n\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\n\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\n\n## Example\n\n```json { \"urls\": [\"https://*.mydomain.dev\"] } ```", + "anyOf": [ + { + "$ref": "#/definitions/CapabilityRemote" + }, + { + "type": "null" + } + ] + }, + "local": { + "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", + "default": true, + "type": "boolean" + }, + "windows": { + "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\nIf a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [`Self::webviews`].\n\nOn multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`] for a fine grained access control.\n\n## Example\n\n`[\"main\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "webviews": { + "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\nThe capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n## Example\n\n`[\"sub-webview-one\", \"sub-webview-two\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionEntry" + }, + "uniqueItems": true + }, + "platforms": { + "description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "CapabilityRemote": { + "description": "Configuration for remote URLs that are associated with the capability.", + "type": "object", + "required": [ + "urls" + ], + "properties": { + "urls": { + "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionEntry": { + "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.", + "anyOf": [ + { + "description": "Reference a permission or permission set by identifier.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + { + "description": "Reference a permission or permission set by identifier and extends its scope.", + "type": "object", + "allOf": [ + { + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + } + } + } + ], + "required": [ + "identifier" + ] + } + ] + }, + "Identifier": { + "description": "Permission identifier", + "oneOf": [ + { + "description": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`", + "type": "string", + "const": "core:default", + "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`", + "type": "string", + "const": "core:app:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`" + }, + { + "description": "Enables the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-hide", + "markdownDescription": "Enables the app_hide command without any pre-configured scope." + }, + { + "description": "Enables the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-show", + "markdownDescription": "Enables the app_show command without any pre-configured scope." + }, + { + "description": "Enables the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-bundle-type", + "markdownDescription": "Enables the bundle_type command without any pre-configured scope." + }, + { + "description": "Enables the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-default-window-icon", + "markdownDescription": "Enables the default_window_icon command without any pre-configured scope." + }, + { + "description": "Enables the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-fetch-data-store-identifiers", + "markdownDescription": "Enables the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Enables the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-identifier", + "markdownDescription": "Enables the identifier command without any pre-configured scope." + }, + { + "description": "Enables the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-name", + "markdownDescription": "Enables the name command without any pre-configured scope." + }, + { + "description": "Enables the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-register-listener", + "markdownDescription": "Enables the register_listener command without any pre-configured scope." + }, + { + "description": "Enables the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-data-store", + "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." + }, + { + "description": "Enables the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-listener", + "markdownDescription": "Enables the remove_listener command without any pre-configured scope." + }, + { + "description": "Enables the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-app-theme", + "markdownDescription": "Enables the set_app_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-dock-visibility", + "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Enables the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-supports-multiple-windows", + "markdownDescription": "Enables the supports_multiple_windows command without any pre-configured scope." + }, + { + "description": "Enables the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-tauri-version", + "markdownDescription": "Enables the tauri_version command without any pre-configured scope." + }, + { + "description": "Enables the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-version", + "markdownDescription": "Enables the version command without any pre-configured scope." + }, + { + "description": "Denies the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-hide", + "markdownDescription": "Denies the app_hide command without any pre-configured scope." + }, + { + "description": "Denies the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-show", + "markdownDescription": "Denies the app_show command without any pre-configured scope." + }, + { + "description": "Denies the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-bundle-type", + "markdownDescription": "Denies the bundle_type command without any pre-configured scope." + }, + { + "description": "Denies the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-default-window-icon", + "markdownDescription": "Denies the default_window_icon command without any pre-configured scope." + }, + { + "description": "Denies the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-fetch-data-store-identifiers", + "markdownDescription": "Denies the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Denies the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-identifier", + "markdownDescription": "Denies the identifier command without any pre-configured scope." + }, + { + "description": "Denies the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-name", + "markdownDescription": "Denies the name command without any pre-configured scope." + }, + { + "description": "Denies the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-register-listener", + "markdownDescription": "Denies the register_listener command without any pre-configured scope." + }, + { + "description": "Denies the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-data-store", + "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." + }, + { + "description": "Denies the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-listener", + "markdownDescription": "Denies the remove_listener command without any pre-configured scope." + }, + { + "description": "Denies the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-app-theme", + "markdownDescription": "Denies the set_app_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-dock-visibility", + "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Denies the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-supports-multiple-windows", + "markdownDescription": "Denies the supports_multiple_windows command without any pre-configured scope." + }, + { + "description": "Denies the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-tauri-version", + "markdownDescription": "Denies the tauri_version command without any pre-configured scope." + }, + { + "description": "Denies the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-version", + "markdownDescription": "Denies the version command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`", + "type": "string", + "const": "core:event:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`" + }, + { + "description": "Enables the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit", + "markdownDescription": "Enables the emit command without any pre-configured scope." + }, + { + "description": "Enables the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit-to", + "markdownDescription": "Enables the emit_to command without any pre-configured scope." + }, + { + "description": "Enables the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-listen", + "markdownDescription": "Enables the listen command without any pre-configured scope." + }, + { + "description": "Enables the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-unlisten", + "markdownDescription": "Enables the unlisten command without any pre-configured scope." + }, + { + "description": "Denies the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit", + "markdownDescription": "Denies the emit command without any pre-configured scope." + }, + { + "description": "Denies the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit-to", + "markdownDescription": "Denies the emit_to command without any pre-configured scope." + }, + { + "description": "Denies the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-listen", + "markdownDescription": "Denies the listen command without any pre-configured scope." + }, + { + "description": "Denies the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-unlisten", + "markdownDescription": "Denies the unlisten command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`", + "type": "string", + "const": "core:image:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`" + }, + { + "description": "Enables the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-bytes", + "markdownDescription": "Enables the from_bytes command without any pre-configured scope." + }, + { + "description": "Enables the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-path", + "markdownDescription": "Enables the from_path command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-rgba", + "markdownDescription": "Enables the rgba command without any pre-configured scope." + }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-size", + "markdownDescription": "Enables the size command without any pre-configured scope." + }, + { + "description": "Denies the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-bytes", + "markdownDescription": "Denies the from_bytes command without any pre-configured scope." + }, + { + "description": "Denies the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-path", + "markdownDescription": "Denies the from_path command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-rgba", + "markdownDescription": "Denies the rgba command without any pre-configured scope." + }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-size", + "markdownDescription": "Denies the size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`", + "type": "string", + "const": "core:menu:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`" + }, + { + "description": "Enables the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-append", + "markdownDescription": "Enables the append command without any pre-configured scope." + }, + { + "description": "Enables the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-create-default", + "markdownDescription": "Enables the create_default command without any pre-configured scope." + }, + { + "description": "Enables the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-get", + "markdownDescription": "Enables the get command without any pre-configured scope." + }, + { + "description": "Enables the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-insert", + "markdownDescription": "Enables the insert command without any pre-configured scope." + }, + { + "description": "Enables the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-checked", + "markdownDescription": "Enables the is_checked command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-items", + "markdownDescription": "Enables the items command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-popup", + "markdownDescription": "Enables the popup command without any pre-configured scope." + }, + { + "description": "Enables the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-prepend", + "markdownDescription": "Enables the prepend command without any pre-configured scope." + }, + { + "description": "Enables the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove", + "markdownDescription": "Enables the remove command without any pre-configured scope." + }, + { + "description": "Enables the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove-at", + "markdownDescription": "Enables the remove_at command without any pre-configured scope." + }, + { + "description": "Enables the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-accelerator", + "markdownDescription": "Enables the set_accelerator command without any pre-configured scope." + }, + { + "description": "Enables the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-app-menu", + "markdownDescription": "Enables the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-help-menu-for-nsapp", + "markdownDescription": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-window-menu", + "markdownDescription": "Enables the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-windows-menu-for-nsapp", + "markdownDescription": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-checked", + "markdownDescription": "Enables the set_checked command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-text", + "markdownDescription": "Enables the set_text command without any pre-configured scope." + }, + { + "description": "Enables the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-text", + "markdownDescription": "Enables the text command without any pre-configured scope." + }, + { + "description": "Denies the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-append", + "markdownDescription": "Denies the append command without any pre-configured scope." + }, + { + "description": "Denies the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-create-default", + "markdownDescription": "Denies the create_default command without any pre-configured scope." + }, + { + "description": "Denies the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-get", + "markdownDescription": "Denies the get command without any pre-configured scope." + }, + { + "description": "Denies the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-insert", + "markdownDescription": "Denies the insert command without any pre-configured scope." + }, + { + "description": "Denies the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-checked", + "markdownDescription": "Denies the is_checked command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-items", + "markdownDescription": "Denies the items command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-popup", + "markdownDescription": "Denies the popup command without any pre-configured scope." + }, + { + "description": "Denies the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-prepend", + "markdownDescription": "Denies the prepend command without any pre-configured scope." + }, + { + "description": "Denies the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove", + "markdownDescription": "Denies the remove command without any pre-configured scope." + }, + { + "description": "Denies the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove-at", + "markdownDescription": "Denies the remove_at command without any pre-configured scope." + }, + { + "description": "Denies the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-accelerator", + "markdownDescription": "Denies the set_accelerator command without any pre-configured scope." + }, + { + "description": "Denies the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-app-menu", + "markdownDescription": "Denies the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-help-menu-for-nsapp", + "markdownDescription": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-window-menu", + "markdownDescription": "Denies the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-windows-menu-for-nsapp", + "markdownDescription": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-checked", + "markdownDescription": "Denies the set_checked command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-text", + "markdownDescription": "Denies the set_text command without any pre-configured scope." + }, + { + "description": "Denies the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-text", + "markdownDescription": "Denies the text command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`", + "type": "string", + "const": "core:path:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`" + }, + { + "description": "Enables the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-basename", + "markdownDescription": "Enables the basename command without any pre-configured scope." + }, + { + "description": "Enables the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-dirname", + "markdownDescription": "Enables the dirname command without any pre-configured scope." + }, + { + "description": "Enables the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-extname", + "markdownDescription": "Enables the extname command without any pre-configured scope." + }, + { + "description": "Enables the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-is-absolute", + "markdownDescription": "Enables the is_absolute command without any pre-configured scope." + }, + { + "description": "Enables the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-join", + "markdownDescription": "Enables the join command without any pre-configured scope." + }, + { + "description": "Enables the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-normalize", + "markdownDescription": "Enables the normalize command without any pre-configured scope." + }, + { + "description": "Enables the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve", + "markdownDescription": "Enables the resolve command without any pre-configured scope." + }, + { + "description": "Enables the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve-directory", + "markdownDescription": "Enables the resolve_directory command without any pre-configured scope." + }, + { + "description": "Denies the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-basename", + "markdownDescription": "Denies the basename command without any pre-configured scope." + }, + { + "description": "Denies the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-dirname", + "markdownDescription": "Denies the dirname command without any pre-configured scope." + }, + { + "description": "Denies the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-extname", + "markdownDescription": "Denies the extname command without any pre-configured scope." + }, + { + "description": "Denies the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-is-absolute", + "markdownDescription": "Denies the is_absolute command without any pre-configured scope." + }, + { + "description": "Denies the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-join", + "markdownDescription": "Denies the join command without any pre-configured scope." + }, + { + "description": "Denies the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-normalize", + "markdownDescription": "Denies the normalize command without any pre-configured scope." + }, + { + "description": "Denies the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve", + "markdownDescription": "Denies the resolve command without any pre-configured scope." + }, + { + "description": "Denies the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve-directory", + "markdownDescription": "Denies the resolve_directory command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`", + "type": "string", + "const": "core:resources:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`" + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`", + "type": "string", + "const": "core:tray:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`" + }, + { + "description": "Enables the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-get-by-id", + "markdownDescription": "Enables the get_by_id command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-remove-by-id", + "markdownDescription": "Enables the remove_by_id command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-as-template", + "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-with-as-template", + "markdownDescription": "Enables the set_icon_with_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-menu", + "markdownDescription": "Enables the set_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-show-menu-on-left-click", + "markdownDescription": "Enables the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Enables the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-temp-dir-path", + "markdownDescription": "Enables the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-tooltip", + "markdownDescription": "Enables the set_tooltip command without any pre-configured scope." + }, + { + "description": "Enables the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-visible", + "markdownDescription": "Enables the set_visible command without any pre-configured scope." + }, + { + "description": "Denies the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-get-by-id", + "markdownDescription": "Denies the get_by_id command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-remove-by-id", + "markdownDescription": "Denies the remove_by_id command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-as-template", + "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-with-as-template", + "markdownDescription": "Denies the set_icon_with_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-menu", + "markdownDescription": "Denies the set_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-show-menu-on-left-click", + "markdownDescription": "Denies the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Denies the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-temp-dir-path", + "markdownDescription": "Denies the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-tooltip", + "markdownDescription": "Denies the set_tooltip command without any pre-configured scope." + }, + { + "description": "Denies the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-visible", + "markdownDescription": "Denies the set_visible command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`", + "type": "string", + "const": "core:webview:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`" + }, + { + "description": "Enables the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-clear-all-browsing-data", + "markdownDescription": "Enables the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Enables the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview", + "markdownDescription": "Enables the create_webview command without any pre-configured scope." + }, + { + "description": "Enables the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview-window", + "markdownDescription": "Enables the create_webview_window command without any pre-configured scope." + }, + { + "description": "Enables the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-get-all-webviews", + "markdownDescription": "Enables the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-internal-toggle-devtools", + "markdownDescription": "Enables the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Enables the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-print", + "markdownDescription": "Enables the print command without any pre-configured scope." + }, + { + "description": "Enables the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-reparent", + "markdownDescription": "Enables the reparent command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-auto-resize", + "markdownDescription": "Enables the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-background-color", + "markdownDescription": "Enables the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-focus", + "markdownDescription": "Enables the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-position", + "markdownDescription": "Enables the set_webview_position command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-size", + "markdownDescription": "Enables the set_webview_size command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-zoom", + "markdownDescription": "Enables the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Enables the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-close", + "markdownDescription": "Enables the webview_close command without any pre-configured scope." + }, + { + "description": "Enables the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-hide", + "markdownDescription": "Enables the webview_hide command without any pre-configured scope." + }, + { + "description": "Enables the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-position", + "markdownDescription": "Enables the webview_position command without any pre-configured scope." + }, + { + "description": "Enables the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-show", + "markdownDescription": "Enables the webview_show command without any pre-configured scope." + }, + { + "description": "Enables the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-size", + "markdownDescription": "Enables the webview_size command without any pre-configured scope." + }, + { + "description": "Denies the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-clear-all-browsing-data", + "markdownDescription": "Denies the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Denies the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview", + "markdownDescription": "Denies the create_webview command without any pre-configured scope." + }, + { + "description": "Denies the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview-window", + "markdownDescription": "Denies the create_webview_window command without any pre-configured scope." + }, + { + "description": "Denies the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-get-all-webviews", + "markdownDescription": "Denies the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-internal-toggle-devtools", + "markdownDescription": "Denies the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Denies the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-print", + "markdownDescription": "Denies the print command without any pre-configured scope." + }, + { + "description": "Denies the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-reparent", + "markdownDescription": "Denies the reparent command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-auto-resize", + "markdownDescription": "Denies the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-background-color", + "markdownDescription": "Denies the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-focus", + "markdownDescription": "Denies the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-position", + "markdownDescription": "Denies the set_webview_position command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-size", + "markdownDescription": "Denies the set_webview_size command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-zoom", + "markdownDescription": "Denies the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Denies the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-close", + "markdownDescription": "Denies the webview_close command without any pre-configured scope." + }, + { + "description": "Denies the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-hide", + "markdownDescription": "Denies the webview_hide command without any pre-configured scope." + }, + { + "description": "Denies the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-position", + "markdownDescription": "Denies the webview_position command without any pre-configured scope." + }, + { + "description": "Denies the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-show", + "markdownDescription": "Denies the webview_show command without any pre-configured scope." + }, + { + "description": "Denies the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-size", + "markdownDescription": "Denies the webview_size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`", + "type": "string", + "const": "core:window:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-activity-name", + "markdownDescription": "Enables the activity_name command without any pre-configured scope." + }, + { + "description": "Enables the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-available-monitors", + "markdownDescription": "Enables the available_monitors command without any pre-configured scope." + }, + { + "description": "Enables the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-center", + "markdownDescription": "Enables the center command without any pre-configured scope." + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Enables the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-create", + "markdownDescription": "Enables the create command without any pre-configured scope." + }, + { + "description": "Enables the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-current-monitor", + "markdownDescription": "Enables the current_monitor command without any pre-configured scope." + }, + { + "description": "Enables the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-cursor-position", + "markdownDescription": "Enables the cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-destroy", + "markdownDescription": "Enables the destroy command without any pre-configured scope." + }, + { + "description": "Enables the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-get-all-windows", + "markdownDescription": "Enables the get_all_windows command without any pre-configured scope." + }, + { + "description": "Enables the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-hide", + "markdownDescription": "Enables the hide command without any pre-configured scope." + }, + { + "description": "Enables the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-position", + "markdownDescription": "Enables the inner_position command without any pre-configured scope." + }, + { + "description": "Enables the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-size", + "markdownDescription": "Enables the inner_size command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-internal-toggle-maximize", + "markdownDescription": "Enables the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-always-on-top", + "markdownDescription": "Enables the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-closable", + "markdownDescription": "Enables the is_closable command without any pre-configured scope." + }, + { + "description": "Enables the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-decorated", + "markdownDescription": "Enables the is_decorated command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-focused", + "markdownDescription": "Enables the is_focused command without any pre-configured scope." + }, + { + "description": "Enables the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-fullscreen", + "markdownDescription": "Enables the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximizable", + "markdownDescription": "Enables the is_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximized", + "markdownDescription": "Enables the is_maximized command without any pre-configured scope." + }, + { + "description": "Enables the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimizable", + "markdownDescription": "Enables the is_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimized", + "markdownDescription": "Enables the is_minimized command without any pre-configured scope." + }, + { + "description": "Enables the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-resizable", + "markdownDescription": "Enables the is_resizable command without any pre-configured scope." + }, + { + "description": "Enables the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-visible", + "markdownDescription": "Enables the is_visible command without any pre-configured scope." + }, + { + "description": "Enables the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-maximize", + "markdownDescription": "Enables the maximize command without any pre-configured scope." + }, + { + "description": "Enables the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-minimize", + "markdownDescription": "Enables the minimize command without any pre-configured scope." + }, + { + "description": "Enables the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-monitor-from-point", + "markdownDescription": "Enables the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Enables the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-position", + "markdownDescription": "Enables the outer_position command without any pre-configured scope." + }, + { + "description": "Enables the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-size", + "markdownDescription": "Enables the outer_size command without any pre-configured scope." + }, + { + "description": "Enables the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-primary-monitor", + "markdownDescription": "Enables the primary_monitor command without any pre-configured scope." + }, + { + "description": "Enables the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-request-user-attention", + "markdownDescription": "Enables the request_user_attention command without any pre-configured scope." + }, + { + "description": "Enables the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scale-factor", + "markdownDescription": "Enables the scale_factor command without any pre-configured scope." + }, + { + "description": "Enables the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scene-identifier", + "markdownDescription": "Enables the scene_identifier command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-bottom", + "markdownDescription": "Enables the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-top", + "markdownDescription": "Enables the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-background-color", + "markdownDescription": "Enables the set_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-count", + "markdownDescription": "Enables the set_badge_count command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-label", + "markdownDescription": "Enables the set_badge_label command without any pre-configured scope." + }, + { + "description": "Enables the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-closable", + "markdownDescription": "Enables the set_closable command without any pre-configured scope." + }, + { + "description": "Enables the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-content-protected", + "markdownDescription": "Enables the set_content_protected command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-grab", + "markdownDescription": "Enables the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-icon", + "markdownDescription": "Enables the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-position", + "markdownDescription": "Enables the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-visible", + "markdownDescription": "Enables the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Enables the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-decorations", + "markdownDescription": "Enables the set_decorations command without any pre-configured scope." + }, + { + "description": "Enables the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-effects", + "markdownDescription": "Enables the set_effects command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focus", + "markdownDescription": "Enables the set_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focusable", + "markdownDescription": "Enables the set_focusable command without any pre-configured scope." + }, + { + "description": "Enables the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-fullscreen", + "markdownDescription": "Enables the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-ignore-cursor-events", + "markdownDescription": "Enables the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Enables the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-max-size", + "markdownDescription": "Enables the set_max_size command without any pre-configured scope." + }, + { + "description": "Enables the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-maximizable", + "markdownDescription": "Enables the set_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-min-size", + "markdownDescription": "Enables the set_min_size command without any pre-configured scope." + }, + { + "description": "Enables the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-minimizable", + "markdownDescription": "Enables the set_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-overlay-icon", + "markdownDescription": "Enables the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-position", + "markdownDescription": "Enables the set_position command without any pre-configured scope." + }, + { + "description": "Enables the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-progress-bar", + "markdownDescription": "Enables the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Enables the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-resizable", + "markdownDescription": "Enables the set_resizable command without any pre-configured scope." + }, + { + "description": "Enables the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-shadow", + "markdownDescription": "Enables the set_shadow command without any pre-configured scope." + }, + { + "description": "Enables the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-simple-fullscreen", + "markdownDescription": "Enables the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size", + "markdownDescription": "Enables the set_size command without any pre-configured scope." + }, + { + "description": "Enables the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size-constraints", + "markdownDescription": "Enables the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Enables the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-skip-taskbar", + "markdownDescription": "Enables the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Enables the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-theme", + "markdownDescription": "Enables the set_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title-bar-style", + "markdownDescription": "Enables the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Enables the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-visible-on-all-workspaces", + "markdownDescription": "Enables the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Enables the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-show", + "markdownDescription": "Enables the show command without any pre-configured scope." + }, + { + "description": "Enables the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-dragging", + "markdownDescription": "Enables the start_dragging command without any pre-configured scope." + }, + { + "description": "Enables the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-resize-dragging", + "markdownDescription": "Enables the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Enables the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-theme", + "markdownDescription": "Enables the theme command without any pre-configured scope." + }, + { + "description": "Enables the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-title", + "markdownDescription": "Enables the title command without any pre-configured scope." + }, + { + "description": "Enables the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-toggle-maximize", + "markdownDescription": "Enables the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unmaximize", + "markdownDescription": "Enables the unmaximize command without any pre-configured scope." + }, + { + "description": "Enables the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unminimize", + "markdownDescription": "Enables the unminimize command without any pre-configured scope." + }, + { + "description": "Denies the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-activity-name", + "markdownDescription": "Denies the activity_name command without any pre-configured scope." + }, + { + "description": "Denies the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-available-monitors", + "markdownDescription": "Denies the available_monitors command without any pre-configured scope." + }, + { + "description": "Denies the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-center", + "markdownDescription": "Denies the center command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Denies the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-create", + "markdownDescription": "Denies the create command without any pre-configured scope." + }, + { + "description": "Denies the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-current-monitor", + "markdownDescription": "Denies the current_monitor command without any pre-configured scope." + }, + { + "description": "Denies the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-cursor-position", + "markdownDescription": "Denies the cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-destroy", + "markdownDescription": "Denies the destroy command without any pre-configured scope." + }, + { + "description": "Denies the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-get-all-windows", + "markdownDescription": "Denies the get_all_windows command without any pre-configured scope." + }, + { + "description": "Denies the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-hide", + "markdownDescription": "Denies the hide command without any pre-configured scope." + }, + { + "description": "Denies the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-position", + "markdownDescription": "Denies the inner_position command without any pre-configured scope." + }, + { + "description": "Denies the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-size", + "markdownDescription": "Denies the inner_size command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-internal-toggle-maximize", + "markdownDescription": "Denies the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-always-on-top", + "markdownDescription": "Denies the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-closable", + "markdownDescription": "Denies the is_closable command without any pre-configured scope." + }, + { + "description": "Denies the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-decorated", + "markdownDescription": "Denies the is_decorated command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-focused", + "markdownDescription": "Denies the is_focused command without any pre-configured scope." + }, + { + "description": "Denies the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-fullscreen", + "markdownDescription": "Denies the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximizable", + "markdownDescription": "Denies the is_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximized", + "markdownDescription": "Denies the is_maximized command without any pre-configured scope." + }, + { + "description": "Denies the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimizable", + "markdownDescription": "Denies the is_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimized", + "markdownDescription": "Denies the is_minimized command without any pre-configured scope." + }, + { + "description": "Denies the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-resizable", + "markdownDescription": "Denies the is_resizable command without any pre-configured scope." + }, + { + "description": "Denies the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-visible", + "markdownDescription": "Denies the is_visible command without any pre-configured scope." + }, + { + "description": "Denies the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-maximize", + "markdownDescription": "Denies the maximize command without any pre-configured scope." + }, + { + "description": "Denies the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-minimize", + "markdownDescription": "Denies the minimize command without any pre-configured scope." + }, + { + "description": "Denies the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-monitor-from-point", + "markdownDescription": "Denies the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Denies the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-position", + "markdownDescription": "Denies the outer_position command without any pre-configured scope." + }, + { + "description": "Denies the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-size", + "markdownDescription": "Denies the outer_size command without any pre-configured scope." + }, + { + "description": "Denies the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-primary-monitor", + "markdownDescription": "Denies the primary_monitor command without any pre-configured scope." + }, + { + "description": "Denies the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-request-user-attention", + "markdownDescription": "Denies the request_user_attention command without any pre-configured scope." + }, + { + "description": "Denies the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scale-factor", + "markdownDescription": "Denies the scale_factor command without any pre-configured scope." + }, + { + "description": "Denies the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scene-identifier", + "markdownDescription": "Denies the scene_identifier command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-bottom", + "markdownDescription": "Denies the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-top", + "markdownDescription": "Denies the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-background-color", + "markdownDescription": "Denies the set_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-count", + "markdownDescription": "Denies the set_badge_count command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-label", + "markdownDescription": "Denies the set_badge_label command without any pre-configured scope." + }, + { + "description": "Denies the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-closable", + "markdownDescription": "Denies the set_closable command without any pre-configured scope." + }, + { + "description": "Denies the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-content-protected", + "markdownDescription": "Denies the set_content_protected command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-grab", + "markdownDescription": "Denies the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-icon", + "markdownDescription": "Denies the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-position", + "markdownDescription": "Denies the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-visible", + "markdownDescription": "Denies the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Denies the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-decorations", + "markdownDescription": "Denies the set_decorations command without any pre-configured scope." + }, + { + "description": "Denies the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-effects", + "markdownDescription": "Denies the set_effects command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focus", + "markdownDescription": "Denies the set_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focusable", + "markdownDescription": "Denies the set_focusable command without any pre-configured scope." + }, + { + "description": "Denies the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-fullscreen", + "markdownDescription": "Denies the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-ignore-cursor-events", + "markdownDescription": "Denies the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Denies the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-max-size", + "markdownDescription": "Denies the set_max_size command without any pre-configured scope." + }, + { + "description": "Denies the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-maximizable", + "markdownDescription": "Denies the set_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-min-size", + "markdownDescription": "Denies the set_min_size command without any pre-configured scope." + }, + { + "description": "Denies the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-minimizable", + "markdownDescription": "Denies the set_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-overlay-icon", + "markdownDescription": "Denies the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-position", + "markdownDescription": "Denies the set_position command without any pre-configured scope." + }, + { + "description": "Denies the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-progress-bar", + "markdownDescription": "Denies the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Denies the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-resizable", + "markdownDescription": "Denies the set_resizable command without any pre-configured scope." + }, + { + "description": "Denies the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-shadow", + "markdownDescription": "Denies the set_shadow command without any pre-configured scope." + }, + { + "description": "Denies the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-simple-fullscreen", + "markdownDescription": "Denies the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size", + "markdownDescription": "Denies the set_size command without any pre-configured scope." + }, + { + "description": "Denies the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size-constraints", + "markdownDescription": "Denies the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Denies the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-skip-taskbar", + "markdownDescription": "Denies the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Denies the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-theme", + "markdownDescription": "Denies the set_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title-bar-style", + "markdownDescription": "Denies the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Denies the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-visible-on-all-workspaces", + "markdownDescription": "Denies the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Denies the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-show", + "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "Denies the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-dragging", + "markdownDescription": "Denies the start_dragging command without any pre-configured scope." + }, + { + "description": "Denies the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-resize-dragging", + "markdownDescription": "Denies the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Denies the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-theme", + "markdownDescription": "Denies the theme command without any pre-configured scope." + }, + { + "description": "Denies the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-title", + "markdownDescription": "Denies the title command without any pre-configured scope." + }, + { + "description": "Denies the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-toggle-maximize", + "markdownDescription": "Denies the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unmaximize", + "markdownDescription": "Denies the unmaximize command without any pre-configured scope." + }, + { + "description": "Denies the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unminimize", + "markdownDescription": "Denies the unminimize command without any pre-configured scope." + }, + { + "description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-message`\n- `allow-save`\n- `allow-open`", + "type": "string", + "const": "dialog:default", + "markdownDescription": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-message`\n- `allow-save`\n- `allow-open`" + }, + { + "description": "Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)", + "type": "string", + "const": "dialog:allow-ask", + "markdownDescription": "Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)" + }, + { + "description": "Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)", + "type": "string", + "const": "dialog:allow-confirm", + "markdownDescription": "Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)" + }, + { + "description": "Enables the message command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-message", + "markdownDescription": "Enables the message command without any pre-configured scope." + }, + { + "description": "Enables the open command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-open", + "markdownDescription": "Enables the open command without any pre-configured scope." + }, + { + "description": "Enables the save command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-save", + "markdownDescription": "Enables the save command without any pre-configured scope." + }, + { + "description": "Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)", + "type": "string", + "const": "dialog:deny-ask", + "markdownDescription": "Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)" + }, + { + "description": "Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)", + "type": "string", + "const": "dialog:deny-confirm", + "markdownDescription": "Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)" + }, + { + "description": "Denies the message command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-message", + "markdownDescription": "Denies the message command without any pre-configured scope." + }, + { + "description": "Denies the open command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-open", + "markdownDescription": "Denies the open command without any pre-configured scope." + }, + { + "description": "Denies the save command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-save", + "markdownDescription": "Denies the save command without any pre-configured scope." + } + ] + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": [ + "macOS" + ] + }, + { + "description": "Windows.", + "type": "string", + "enum": [ + "windows" + ] + }, + { + "description": "Linux.", + "type": "string", + "enum": [ + "linux" + ] + }, + { + "description": "Android.", + "type": "string", + "enum": [ + "android" + ] + }, + { + "description": "iOS.", + "type": "string", + "enum": [ + "iOS" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/app/src-tauri/gen/schemas/windows-schema.json b/app/src-tauri/gen/schemas/windows-schema.json new file mode 100644 index 0000000..24c9001 --- /dev/null +++ b/app/src-tauri/gen/schemas/windows-schema.json @@ -0,0 +1,2358 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CapabilityFile", + "description": "Capability formats accepted in a capability file.", + "anyOf": [ + { + "description": "A single capability.", + "allOf": [ + { + "$ref": "#/definitions/Capability" + } + ] + }, + { + "description": "A list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + { + "description": "A list of capabilities.", + "type": "object", + "required": [ + "capabilities" + ], + "properties": { + "capabilities": { + "description": "The list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + } + } + } + ], + "definitions": { + "Capability": { + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows' and webviews' fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", + "type": "object", + "required": [ + "identifier", + "permissions" + ], + "properties": { + "identifier": { + "description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`", + "type": "string" + }, + "description": { + "description": "Description of what the capability is intended to allow on associated windows.\n\nIt should contain a description of what the grouped permissions should allow.\n\n## Example\n\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.", + "default": "", + "type": "string" + }, + "remote": { + "description": "Configure remote URLs that can use the capability permissions.\n\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\n\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\n\n## Example\n\n```json { \"urls\": [\"https://*.mydomain.dev\"] } ```", + "anyOf": [ + { + "$ref": "#/definitions/CapabilityRemote" + }, + { + "type": "null" + } + ] + }, + "local": { + "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", + "default": true, + "type": "boolean" + }, + "windows": { + "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\nIf a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [`Self::webviews`].\n\nOn multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`] for a fine grained access control.\n\n## Example\n\n`[\"main\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "webviews": { + "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\nThe capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n## Example\n\n`[\"sub-webview-one\", \"sub-webview-two\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionEntry" + }, + "uniqueItems": true + }, + "platforms": { + "description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "CapabilityRemote": { + "description": "Configuration for remote URLs that are associated with the capability.", + "type": "object", + "required": [ + "urls" + ], + "properties": { + "urls": { + "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionEntry": { + "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.", + "anyOf": [ + { + "description": "Reference a permission or permission set by identifier.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + { + "description": "Reference a permission or permission set by identifier and extends its scope.", + "type": "object", + "allOf": [ + { + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + } + } + } + ], + "required": [ + "identifier" + ] + } + ] + }, + "Identifier": { + "description": "Permission identifier", + "oneOf": [ + { + "description": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`", + "type": "string", + "const": "core:default", + "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`", + "type": "string", + "const": "core:app:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`" + }, + { + "description": "Enables the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-hide", + "markdownDescription": "Enables the app_hide command without any pre-configured scope." + }, + { + "description": "Enables the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-show", + "markdownDescription": "Enables the app_show command without any pre-configured scope." + }, + { + "description": "Enables the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-bundle-type", + "markdownDescription": "Enables the bundle_type command without any pre-configured scope." + }, + { + "description": "Enables the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-default-window-icon", + "markdownDescription": "Enables the default_window_icon command without any pre-configured scope." + }, + { + "description": "Enables the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-fetch-data-store-identifiers", + "markdownDescription": "Enables the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Enables the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-identifier", + "markdownDescription": "Enables the identifier command without any pre-configured scope." + }, + { + "description": "Enables the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-name", + "markdownDescription": "Enables the name command without any pre-configured scope." + }, + { + "description": "Enables the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-register-listener", + "markdownDescription": "Enables the register_listener command without any pre-configured scope." + }, + { + "description": "Enables the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-data-store", + "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." + }, + { + "description": "Enables the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-listener", + "markdownDescription": "Enables the remove_listener command without any pre-configured scope." + }, + { + "description": "Enables the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-app-theme", + "markdownDescription": "Enables the set_app_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-dock-visibility", + "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Enables the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-supports-multiple-windows", + "markdownDescription": "Enables the supports_multiple_windows command without any pre-configured scope." + }, + { + "description": "Enables the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-tauri-version", + "markdownDescription": "Enables the tauri_version command without any pre-configured scope." + }, + { + "description": "Enables the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-version", + "markdownDescription": "Enables the version command without any pre-configured scope." + }, + { + "description": "Denies the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-hide", + "markdownDescription": "Denies the app_hide command without any pre-configured scope." + }, + { + "description": "Denies the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-show", + "markdownDescription": "Denies the app_show command without any pre-configured scope." + }, + { + "description": "Denies the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-bundle-type", + "markdownDescription": "Denies the bundle_type command without any pre-configured scope." + }, + { + "description": "Denies the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-default-window-icon", + "markdownDescription": "Denies the default_window_icon command without any pre-configured scope." + }, + { + "description": "Denies the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-fetch-data-store-identifiers", + "markdownDescription": "Denies the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Denies the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-identifier", + "markdownDescription": "Denies the identifier command without any pre-configured scope." + }, + { + "description": "Denies the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-name", + "markdownDescription": "Denies the name command without any pre-configured scope." + }, + { + "description": "Denies the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-register-listener", + "markdownDescription": "Denies the register_listener command without any pre-configured scope." + }, + { + "description": "Denies the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-data-store", + "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." + }, + { + "description": "Denies the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-listener", + "markdownDescription": "Denies the remove_listener command without any pre-configured scope." + }, + { + "description": "Denies the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-app-theme", + "markdownDescription": "Denies the set_app_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-dock-visibility", + "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Denies the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-supports-multiple-windows", + "markdownDescription": "Denies the supports_multiple_windows command without any pre-configured scope." + }, + { + "description": "Denies the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-tauri-version", + "markdownDescription": "Denies the tauri_version command without any pre-configured scope." + }, + { + "description": "Denies the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-version", + "markdownDescription": "Denies the version command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`", + "type": "string", + "const": "core:event:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`" + }, + { + "description": "Enables the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit", + "markdownDescription": "Enables the emit command without any pre-configured scope." + }, + { + "description": "Enables the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit-to", + "markdownDescription": "Enables the emit_to command without any pre-configured scope." + }, + { + "description": "Enables the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-listen", + "markdownDescription": "Enables the listen command without any pre-configured scope." + }, + { + "description": "Enables the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-unlisten", + "markdownDescription": "Enables the unlisten command without any pre-configured scope." + }, + { + "description": "Denies the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit", + "markdownDescription": "Denies the emit command without any pre-configured scope." + }, + { + "description": "Denies the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit-to", + "markdownDescription": "Denies the emit_to command without any pre-configured scope." + }, + { + "description": "Denies the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-listen", + "markdownDescription": "Denies the listen command without any pre-configured scope." + }, + { + "description": "Denies the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-unlisten", + "markdownDescription": "Denies the unlisten command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`", + "type": "string", + "const": "core:image:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`" + }, + { + "description": "Enables the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-bytes", + "markdownDescription": "Enables the from_bytes command without any pre-configured scope." + }, + { + "description": "Enables the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-path", + "markdownDescription": "Enables the from_path command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-rgba", + "markdownDescription": "Enables the rgba command without any pre-configured scope." + }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-size", + "markdownDescription": "Enables the size command without any pre-configured scope." + }, + { + "description": "Denies the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-bytes", + "markdownDescription": "Denies the from_bytes command without any pre-configured scope." + }, + { + "description": "Denies the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-path", + "markdownDescription": "Denies the from_path command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-rgba", + "markdownDescription": "Denies the rgba command without any pre-configured scope." + }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-size", + "markdownDescription": "Denies the size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`", + "type": "string", + "const": "core:menu:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`" + }, + { + "description": "Enables the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-append", + "markdownDescription": "Enables the append command without any pre-configured scope." + }, + { + "description": "Enables the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-create-default", + "markdownDescription": "Enables the create_default command without any pre-configured scope." + }, + { + "description": "Enables the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-get", + "markdownDescription": "Enables the get command without any pre-configured scope." + }, + { + "description": "Enables the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-insert", + "markdownDescription": "Enables the insert command without any pre-configured scope." + }, + { + "description": "Enables the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-checked", + "markdownDescription": "Enables the is_checked command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-items", + "markdownDescription": "Enables the items command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-popup", + "markdownDescription": "Enables the popup command without any pre-configured scope." + }, + { + "description": "Enables the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-prepend", + "markdownDescription": "Enables the prepend command without any pre-configured scope." + }, + { + "description": "Enables the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove", + "markdownDescription": "Enables the remove command without any pre-configured scope." + }, + { + "description": "Enables the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove-at", + "markdownDescription": "Enables the remove_at command without any pre-configured scope." + }, + { + "description": "Enables the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-accelerator", + "markdownDescription": "Enables the set_accelerator command without any pre-configured scope." + }, + { + "description": "Enables the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-app-menu", + "markdownDescription": "Enables the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-help-menu-for-nsapp", + "markdownDescription": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-window-menu", + "markdownDescription": "Enables the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-windows-menu-for-nsapp", + "markdownDescription": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-checked", + "markdownDescription": "Enables the set_checked command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-text", + "markdownDescription": "Enables the set_text command without any pre-configured scope." + }, + { + "description": "Enables the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-text", + "markdownDescription": "Enables the text command without any pre-configured scope." + }, + { + "description": "Denies the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-append", + "markdownDescription": "Denies the append command without any pre-configured scope." + }, + { + "description": "Denies the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-create-default", + "markdownDescription": "Denies the create_default command without any pre-configured scope." + }, + { + "description": "Denies the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-get", + "markdownDescription": "Denies the get command without any pre-configured scope." + }, + { + "description": "Denies the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-insert", + "markdownDescription": "Denies the insert command without any pre-configured scope." + }, + { + "description": "Denies the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-checked", + "markdownDescription": "Denies the is_checked command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-items", + "markdownDescription": "Denies the items command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-popup", + "markdownDescription": "Denies the popup command without any pre-configured scope." + }, + { + "description": "Denies the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-prepend", + "markdownDescription": "Denies the prepend command without any pre-configured scope." + }, + { + "description": "Denies the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove", + "markdownDescription": "Denies the remove command without any pre-configured scope." + }, + { + "description": "Denies the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove-at", + "markdownDescription": "Denies the remove_at command without any pre-configured scope." + }, + { + "description": "Denies the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-accelerator", + "markdownDescription": "Denies the set_accelerator command without any pre-configured scope." + }, + { + "description": "Denies the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-app-menu", + "markdownDescription": "Denies the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-help-menu-for-nsapp", + "markdownDescription": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-window-menu", + "markdownDescription": "Denies the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-windows-menu-for-nsapp", + "markdownDescription": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-checked", + "markdownDescription": "Denies the set_checked command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-text", + "markdownDescription": "Denies the set_text command without any pre-configured scope." + }, + { + "description": "Denies the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-text", + "markdownDescription": "Denies the text command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`", + "type": "string", + "const": "core:path:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`" + }, + { + "description": "Enables the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-basename", + "markdownDescription": "Enables the basename command without any pre-configured scope." + }, + { + "description": "Enables the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-dirname", + "markdownDescription": "Enables the dirname command without any pre-configured scope." + }, + { + "description": "Enables the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-extname", + "markdownDescription": "Enables the extname command without any pre-configured scope." + }, + { + "description": "Enables the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-is-absolute", + "markdownDescription": "Enables the is_absolute command without any pre-configured scope." + }, + { + "description": "Enables the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-join", + "markdownDescription": "Enables the join command without any pre-configured scope." + }, + { + "description": "Enables the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-normalize", + "markdownDescription": "Enables the normalize command without any pre-configured scope." + }, + { + "description": "Enables the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve", + "markdownDescription": "Enables the resolve command without any pre-configured scope." + }, + { + "description": "Enables the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve-directory", + "markdownDescription": "Enables the resolve_directory command without any pre-configured scope." + }, + { + "description": "Denies the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-basename", + "markdownDescription": "Denies the basename command without any pre-configured scope." + }, + { + "description": "Denies the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-dirname", + "markdownDescription": "Denies the dirname command without any pre-configured scope." + }, + { + "description": "Denies the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-extname", + "markdownDescription": "Denies the extname command without any pre-configured scope." + }, + { + "description": "Denies the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-is-absolute", + "markdownDescription": "Denies the is_absolute command without any pre-configured scope." + }, + { + "description": "Denies the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-join", + "markdownDescription": "Denies the join command without any pre-configured scope." + }, + { + "description": "Denies the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-normalize", + "markdownDescription": "Denies the normalize command without any pre-configured scope." + }, + { + "description": "Denies the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve", + "markdownDescription": "Denies the resolve command without any pre-configured scope." + }, + { + "description": "Denies the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve-directory", + "markdownDescription": "Denies the resolve_directory command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`", + "type": "string", + "const": "core:resources:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`" + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`", + "type": "string", + "const": "core:tray:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`" + }, + { + "description": "Enables the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-get-by-id", + "markdownDescription": "Enables the get_by_id command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-remove-by-id", + "markdownDescription": "Enables the remove_by_id command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-as-template", + "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-with-as-template", + "markdownDescription": "Enables the set_icon_with_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-menu", + "markdownDescription": "Enables the set_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-show-menu-on-left-click", + "markdownDescription": "Enables the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Enables the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-temp-dir-path", + "markdownDescription": "Enables the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-tooltip", + "markdownDescription": "Enables the set_tooltip command without any pre-configured scope." + }, + { + "description": "Enables the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-visible", + "markdownDescription": "Enables the set_visible command without any pre-configured scope." + }, + { + "description": "Denies the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-get-by-id", + "markdownDescription": "Denies the get_by_id command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-remove-by-id", + "markdownDescription": "Denies the remove_by_id command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-as-template", + "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-with-as-template", + "markdownDescription": "Denies the set_icon_with_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-menu", + "markdownDescription": "Denies the set_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-show-menu-on-left-click", + "markdownDescription": "Denies the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Denies the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-temp-dir-path", + "markdownDescription": "Denies the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-tooltip", + "markdownDescription": "Denies the set_tooltip command without any pre-configured scope." + }, + { + "description": "Denies the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-visible", + "markdownDescription": "Denies the set_visible command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`", + "type": "string", + "const": "core:webview:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`" + }, + { + "description": "Enables the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-clear-all-browsing-data", + "markdownDescription": "Enables the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Enables the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview", + "markdownDescription": "Enables the create_webview command without any pre-configured scope." + }, + { + "description": "Enables the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview-window", + "markdownDescription": "Enables the create_webview_window command without any pre-configured scope." + }, + { + "description": "Enables the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-get-all-webviews", + "markdownDescription": "Enables the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-internal-toggle-devtools", + "markdownDescription": "Enables the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Enables the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-print", + "markdownDescription": "Enables the print command without any pre-configured scope." + }, + { + "description": "Enables the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-reparent", + "markdownDescription": "Enables the reparent command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-auto-resize", + "markdownDescription": "Enables the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-background-color", + "markdownDescription": "Enables the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-focus", + "markdownDescription": "Enables the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-position", + "markdownDescription": "Enables the set_webview_position command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-size", + "markdownDescription": "Enables the set_webview_size command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-zoom", + "markdownDescription": "Enables the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Enables the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-close", + "markdownDescription": "Enables the webview_close command without any pre-configured scope." + }, + { + "description": "Enables the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-hide", + "markdownDescription": "Enables the webview_hide command without any pre-configured scope." + }, + { + "description": "Enables the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-position", + "markdownDescription": "Enables the webview_position command without any pre-configured scope." + }, + { + "description": "Enables the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-show", + "markdownDescription": "Enables the webview_show command without any pre-configured scope." + }, + { + "description": "Enables the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-size", + "markdownDescription": "Enables the webview_size command without any pre-configured scope." + }, + { + "description": "Denies the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-clear-all-browsing-data", + "markdownDescription": "Denies the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Denies the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview", + "markdownDescription": "Denies the create_webview command without any pre-configured scope." + }, + { + "description": "Denies the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview-window", + "markdownDescription": "Denies the create_webview_window command without any pre-configured scope." + }, + { + "description": "Denies the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-get-all-webviews", + "markdownDescription": "Denies the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-internal-toggle-devtools", + "markdownDescription": "Denies the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Denies the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-print", + "markdownDescription": "Denies the print command without any pre-configured scope." + }, + { + "description": "Denies the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-reparent", + "markdownDescription": "Denies the reparent command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-auto-resize", + "markdownDescription": "Denies the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-background-color", + "markdownDescription": "Denies the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-focus", + "markdownDescription": "Denies the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-position", + "markdownDescription": "Denies the set_webview_position command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-size", + "markdownDescription": "Denies the set_webview_size command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-zoom", + "markdownDescription": "Denies the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Denies the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-close", + "markdownDescription": "Denies the webview_close command without any pre-configured scope." + }, + { + "description": "Denies the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-hide", + "markdownDescription": "Denies the webview_hide command without any pre-configured scope." + }, + { + "description": "Denies the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-position", + "markdownDescription": "Denies the webview_position command without any pre-configured scope." + }, + { + "description": "Denies the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-show", + "markdownDescription": "Denies the webview_show command without any pre-configured scope." + }, + { + "description": "Denies the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-size", + "markdownDescription": "Denies the webview_size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`", + "type": "string", + "const": "core:window:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-activity-name", + "markdownDescription": "Enables the activity_name command without any pre-configured scope." + }, + { + "description": "Enables the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-available-monitors", + "markdownDescription": "Enables the available_monitors command without any pre-configured scope." + }, + { + "description": "Enables the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-center", + "markdownDescription": "Enables the center command without any pre-configured scope." + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Enables the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-create", + "markdownDescription": "Enables the create command without any pre-configured scope." + }, + { + "description": "Enables the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-current-monitor", + "markdownDescription": "Enables the current_monitor command without any pre-configured scope." + }, + { + "description": "Enables the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-cursor-position", + "markdownDescription": "Enables the cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-destroy", + "markdownDescription": "Enables the destroy command without any pre-configured scope." + }, + { + "description": "Enables the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-get-all-windows", + "markdownDescription": "Enables the get_all_windows command without any pre-configured scope." + }, + { + "description": "Enables the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-hide", + "markdownDescription": "Enables the hide command without any pre-configured scope." + }, + { + "description": "Enables the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-position", + "markdownDescription": "Enables the inner_position command without any pre-configured scope." + }, + { + "description": "Enables the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-size", + "markdownDescription": "Enables the inner_size command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-internal-toggle-maximize", + "markdownDescription": "Enables the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-always-on-top", + "markdownDescription": "Enables the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-closable", + "markdownDescription": "Enables the is_closable command without any pre-configured scope." + }, + { + "description": "Enables the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-decorated", + "markdownDescription": "Enables the is_decorated command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-focused", + "markdownDescription": "Enables the is_focused command without any pre-configured scope." + }, + { + "description": "Enables the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-fullscreen", + "markdownDescription": "Enables the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximizable", + "markdownDescription": "Enables the is_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximized", + "markdownDescription": "Enables the is_maximized command without any pre-configured scope." + }, + { + "description": "Enables the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimizable", + "markdownDescription": "Enables the is_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimized", + "markdownDescription": "Enables the is_minimized command without any pre-configured scope." + }, + { + "description": "Enables the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-resizable", + "markdownDescription": "Enables the is_resizable command without any pre-configured scope." + }, + { + "description": "Enables the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-visible", + "markdownDescription": "Enables the is_visible command without any pre-configured scope." + }, + { + "description": "Enables the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-maximize", + "markdownDescription": "Enables the maximize command without any pre-configured scope." + }, + { + "description": "Enables the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-minimize", + "markdownDescription": "Enables the minimize command without any pre-configured scope." + }, + { + "description": "Enables the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-monitor-from-point", + "markdownDescription": "Enables the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Enables the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-position", + "markdownDescription": "Enables the outer_position command without any pre-configured scope." + }, + { + "description": "Enables the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-size", + "markdownDescription": "Enables the outer_size command without any pre-configured scope." + }, + { + "description": "Enables the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-primary-monitor", + "markdownDescription": "Enables the primary_monitor command without any pre-configured scope." + }, + { + "description": "Enables the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-request-user-attention", + "markdownDescription": "Enables the request_user_attention command without any pre-configured scope." + }, + { + "description": "Enables the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scale-factor", + "markdownDescription": "Enables the scale_factor command without any pre-configured scope." + }, + { + "description": "Enables the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scene-identifier", + "markdownDescription": "Enables the scene_identifier command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-bottom", + "markdownDescription": "Enables the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-top", + "markdownDescription": "Enables the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-background-color", + "markdownDescription": "Enables the set_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-count", + "markdownDescription": "Enables the set_badge_count command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-label", + "markdownDescription": "Enables the set_badge_label command without any pre-configured scope." + }, + { + "description": "Enables the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-closable", + "markdownDescription": "Enables the set_closable command without any pre-configured scope." + }, + { + "description": "Enables the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-content-protected", + "markdownDescription": "Enables the set_content_protected command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-grab", + "markdownDescription": "Enables the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-icon", + "markdownDescription": "Enables the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-position", + "markdownDescription": "Enables the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-visible", + "markdownDescription": "Enables the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Enables the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-decorations", + "markdownDescription": "Enables the set_decorations command without any pre-configured scope." + }, + { + "description": "Enables the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-effects", + "markdownDescription": "Enables the set_effects command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focus", + "markdownDescription": "Enables the set_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focusable", + "markdownDescription": "Enables the set_focusable command without any pre-configured scope." + }, + { + "description": "Enables the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-fullscreen", + "markdownDescription": "Enables the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-ignore-cursor-events", + "markdownDescription": "Enables the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Enables the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-max-size", + "markdownDescription": "Enables the set_max_size command without any pre-configured scope." + }, + { + "description": "Enables the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-maximizable", + "markdownDescription": "Enables the set_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-min-size", + "markdownDescription": "Enables the set_min_size command without any pre-configured scope." + }, + { + "description": "Enables the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-minimizable", + "markdownDescription": "Enables the set_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-overlay-icon", + "markdownDescription": "Enables the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-position", + "markdownDescription": "Enables the set_position command without any pre-configured scope." + }, + { + "description": "Enables the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-progress-bar", + "markdownDescription": "Enables the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Enables the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-resizable", + "markdownDescription": "Enables the set_resizable command without any pre-configured scope." + }, + { + "description": "Enables the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-shadow", + "markdownDescription": "Enables the set_shadow command without any pre-configured scope." + }, + { + "description": "Enables the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-simple-fullscreen", + "markdownDescription": "Enables the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size", + "markdownDescription": "Enables the set_size command without any pre-configured scope." + }, + { + "description": "Enables the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size-constraints", + "markdownDescription": "Enables the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Enables the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-skip-taskbar", + "markdownDescription": "Enables the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Enables the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-theme", + "markdownDescription": "Enables the set_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title-bar-style", + "markdownDescription": "Enables the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Enables the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-visible-on-all-workspaces", + "markdownDescription": "Enables the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Enables the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-show", + "markdownDescription": "Enables the show command without any pre-configured scope." + }, + { + "description": "Enables the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-dragging", + "markdownDescription": "Enables the start_dragging command without any pre-configured scope." + }, + { + "description": "Enables the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-resize-dragging", + "markdownDescription": "Enables the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Enables the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-theme", + "markdownDescription": "Enables the theme command without any pre-configured scope." + }, + { + "description": "Enables the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-title", + "markdownDescription": "Enables the title command without any pre-configured scope." + }, + { + "description": "Enables the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-toggle-maximize", + "markdownDescription": "Enables the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unmaximize", + "markdownDescription": "Enables the unmaximize command without any pre-configured scope." + }, + { + "description": "Enables the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unminimize", + "markdownDescription": "Enables the unminimize command without any pre-configured scope." + }, + { + "description": "Denies the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-activity-name", + "markdownDescription": "Denies the activity_name command without any pre-configured scope." + }, + { + "description": "Denies the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-available-monitors", + "markdownDescription": "Denies the available_monitors command without any pre-configured scope." + }, + { + "description": "Denies the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-center", + "markdownDescription": "Denies the center command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Denies the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-create", + "markdownDescription": "Denies the create command without any pre-configured scope." + }, + { + "description": "Denies the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-current-monitor", + "markdownDescription": "Denies the current_monitor command without any pre-configured scope." + }, + { + "description": "Denies the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-cursor-position", + "markdownDescription": "Denies the cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-destroy", + "markdownDescription": "Denies the destroy command without any pre-configured scope." + }, + { + "description": "Denies the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-get-all-windows", + "markdownDescription": "Denies the get_all_windows command without any pre-configured scope." + }, + { + "description": "Denies the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-hide", + "markdownDescription": "Denies the hide command without any pre-configured scope." + }, + { + "description": "Denies the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-position", + "markdownDescription": "Denies the inner_position command without any pre-configured scope." + }, + { + "description": "Denies the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-size", + "markdownDescription": "Denies the inner_size command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-internal-toggle-maximize", + "markdownDescription": "Denies the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-always-on-top", + "markdownDescription": "Denies the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-closable", + "markdownDescription": "Denies the is_closable command without any pre-configured scope." + }, + { + "description": "Denies the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-decorated", + "markdownDescription": "Denies the is_decorated command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-focused", + "markdownDescription": "Denies the is_focused command without any pre-configured scope." + }, + { + "description": "Denies the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-fullscreen", + "markdownDescription": "Denies the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximizable", + "markdownDescription": "Denies the is_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximized", + "markdownDescription": "Denies the is_maximized command without any pre-configured scope." + }, + { + "description": "Denies the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimizable", + "markdownDescription": "Denies the is_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimized", + "markdownDescription": "Denies the is_minimized command without any pre-configured scope." + }, + { + "description": "Denies the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-resizable", + "markdownDescription": "Denies the is_resizable command without any pre-configured scope." + }, + { + "description": "Denies the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-visible", + "markdownDescription": "Denies the is_visible command without any pre-configured scope." + }, + { + "description": "Denies the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-maximize", + "markdownDescription": "Denies the maximize command without any pre-configured scope." + }, + { + "description": "Denies the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-minimize", + "markdownDescription": "Denies the minimize command without any pre-configured scope." + }, + { + "description": "Denies the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-monitor-from-point", + "markdownDescription": "Denies the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Denies the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-position", + "markdownDescription": "Denies the outer_position command without any pre-configured scope." + }, + { + "description": "Denies the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-size", + "markdownDescription": "Denies the outer_size command without any pre-configured scope." + }, + { + "description": "Denies the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-primary-monitor", + "markdownDescription": "Denies the primary_monitor command without any pre-configured scope." + }, + { + "description": "Denies the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-request-user-attention", + "markdownDescription": "Denies the request_user_attention command without any pre-configured scope." + }, + { + "description": "Denies the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scale-factor", + "markdownDescription": "Denies the scale_factor command without any pre-configured scope." + }, + { + "description": "Denies the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scene-identifier", + "markdownDescription": "Denies the scene_identifier command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-bottom", + "markdownDescription": "Denies the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-top", + "markdownDescription": "Denies the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-background-color", + "markdownDescription": "Denies the set_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-count", + "markdownDescription": "Denies the set_badge_count command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-label", + "markdownDescription": "Denies the set_badge_label command without any pre-configured scope." + }, + { + "description": "Denies the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-closable", + "markdownDescription": "Denies the set_closable command without any pre-configured scope." + }, + { + "description": "Denies the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-content-protected", + "markdownDescription": "Denies the set_content_protected command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-grab", + "markdownDescription": "Denies the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-icon", + "markdownDescription": "Denies the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-position", + "markdownDescription": "Denies the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-visible", + "markdownDescription": "Denies the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Denies the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-decorations", + "markdownDescription": "Denies the set_decorations command without any pre-configured scope." + }, + { + "description": "Denies the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-effects", + "markdownDescription": "Denies the set_effects command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focus", + "markdownDescription": "Denies the set_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focusable", + "markdownDescription": "Denies the set_focusable command without any pre-configured scope." + }, + { + "description": "Denies the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-fullscreen", + "markdownDescription": "Denies the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-ignore-cursor-events", + "markdownDescription": "Denies the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Denies the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-max-size", + "markdownDescription": "Denies the set_max_size command without any pre-configured scope." + }, + { + "description": "Denies the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-maximizable", + "markdownDescription": "Denies the set_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-min-size", + "markdownDescription": "Denies the set_min_size command without any pre-configured scope." + }, + { + "description": "Denies the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-minimizable", + "markdownDescription": "Denies the set_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-overlay-icon", + "markdownDescription": "Denies the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-position", + "markdownDescription": "Denies the set_position command without any pre-configured scope." + }, + { + "description": "Denies the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-progress-bar", + "markdownDescription": "Denies the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Denies the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-resizable", + "markdownDescription": "Denies the set_resizable command without any pre-configured scope." + }, + { + "description": "Denies the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-shadow", + "markdownDescription": "Denies the set_shadow command without any pre-configured scope." + }, + { + "description": "Denies the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-simple-fullscreen", + "markdownDescription": "Denies the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size", + "markdownDescription": "Denies the set_size command without any pre-configured scope." + }, + { + "description": "Denies the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size-constraints", + "markdownDescription": "Denies the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Denies the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-skip-taskbar", + "markdownDescription": "Denies the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Denies the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-theme", + "markdownDescription": "Denies the set_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title-bar-style", + "markdownDescription": "Denies the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Denies the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-visible-on-all-workspaces", + "markdownDescription": "Denies the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Denies the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-show", + "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "Denies the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-dragging", + "markdownDescription": "Denies the start_dragging command without any pre-configured scope." + }, + { + "description": "Denies the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-resize-dragging", + "markdownDescription": "Denies the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Denies the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-theme", + "markdownDescription": "Denies the theme command without any pre-configured scope." + }, + { + "description": "Denies the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-title", + "markdownDescription": "Denies the title command without any pre-configured scope." + }, + { + "description": "Denies the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-toggle-maximize", + "markdownDescription": "Denies the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unmaximize", + "markdownDescription": "Denies the unmaximize command without any pre-configured scope." + }, + { + "description": "Denies the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unminimize", + "markdownDescription": "Denies the unminimize command without any pre-configured scope." + }, + { + "description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-message`\n- `allow-save`\n- `allow-open`", + "type": "string", + "const": "dialog:default", + "markdownDescription": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-message`\n- `allow-save`\n- `allow-open`" + }, + { + "description": "Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)", + "type": "string", + "const": "dialog:allow-ask", + "markdownDescription": "Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)" + }, + { + "description": "Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)", + "type": "string", + "const": "dialog:allow-confirm", + "markdownDescription": "Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)" + }, + { + "description": "Enables the message command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-message", + "markdownDescription": "Enables the message command without any pre-configured scope." + }, + { + "description": "Enables the open command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-open", + "markdownDescription": "Enables the open command without any pre-configured scope." + }, + { + "description": "Enables the save command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-save", + "markdownDescription": "Enables the save command without any pre-configured scope." + }, + { + "description": "Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)", + "type": "string", + "const": "dialog:deny-ask", + "markdownDescription": "Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)" + }, + { + "description": "Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)", + "type": "string", + "const": "dialog:deny-confirm", + "markdownDescription": "Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)" + }, + { + "description": "Denies the message command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-message", + "markdownDescription": "Denies the message command without any pre-configured scope." + }, + { + "description": "Denies the open command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-open", + "markdownDescription": "Denies the open command without any pre-configured scope." + }, + { + "description": "Denies the save command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-save", + "markdownDescription": "Denies the save command without any pre-configured scope." + } + ] + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": [ + "macOS" + ] + }, + { + "description": "Windows.", + "type": "string", + "enum": [ + "windows" + ] + }, + { + "description": "Linux.", + "type": "string", + "enum": [ + "linux" + ] + }, + { + "description": "Android.", + "type": "string", + "enum": [ + "android" + ] + }, + { + "description": "iOS.", + "type": "string", + "enum": [ + "iOS" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/app/src-tauri/icons/128x128.png b/app/src-tauri/icons/128x128.png new file mode 100644 index 0000000..5693079 Binary files /dev/null and b/app/src-tauri/icons/128x128.png differ diff --git a/app/src-tauri/icons/32x32.png b/app/src-tauri/icons/32x32.png new file mode 100644 index 0000000..ed91143 Binary files /dev/null and b/app/src-tauri/icons/32x32.png differ diff --git a/app/src-tauri/icons/icon.ico b/app/src-tauri/icons/icon.ico new file mode 100644 index 0000000..7defc7b Binary files /dev/null and b/app/src-tauri/icons/icon.ico differ diff --git a/app/src-tauri/icons/icon.png b/app/src-tauri/icons/icon.png new file mode 100644 index 0000000..5f04dda Binary files /dev/null and b/app/src-tauri/icons/icon.png differ diff --git a/app/src-tauri/src/main.rs b/app/src-tauri/src/main.rs new file mode 100644 index 0000000..30fd5fc --- /dev/null +++ b/app/src-tauri/src/main.rs @@ -0,0 +1,342 @@ +// Ẩn cửa sổ console trên Windows ở bản release. +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +use std::io::Cursor; +use std::path::PathBuf; + +use base64::Engine as _; +use serde::Serialize; +use tauri_plugin_dialog::DialogExt; + +/// Thư mục gốc workspace (app/src-tauri -> ../../). +fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") +} + +/// Đảm bảo engine tìm thấy pdfium.dll (dev: ở gốc workspace). +fn ensure_pdfium_env() { + if std::env::var("FOFREEXIT_PDFIUM_PATH").is_err() { + std::env::set_var("FOFREEXIT_PDFIUM_PATH", workspace_root()); + } +} + +fn pdfium() -> Result { + ensure_pdfium_env(); + ff_engine::bind_pdfium().map_err(|e| e.to_string()) +} + +// ---- Kiểu dữ liệu trả về frontend ---- + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct PageMeta { + index: u16, + width_pt: f32, + height_pt: f32, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct OutlineMeta { + title: String, + page_index: Option, + level: u32, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct DocMeta { + page_count: u16, + pages: Vec, + outline: Vec, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct RectMeta { + left: f32, + bottom: f32, + right: f32, + top: f32, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct SearchHitMeta { + page_index: u16, + char_start: usize, + char_len: usize, + rect: Option, +} + +// ---- Commands ---- + +/// Mở tài liệu: trả số trang, kích thước từng trang, và outline. +#[tauri::command] +fn open_document(path: String) -> Result { + let pdfium = pdfium()?; + let p = PathBuf::from(&path); + + let dims = ff_engine::page_dims(&pdfium, &p, None).map_err(|e| e.to_string())?; + let outline = ff_engine::outline(&pdfium, &p, None).map_err(|e| e.to_string())?; + + Ok(DocMeta { + page_count: dims.len() as u16, + pages: dims + .into_iter() + .map(|d| PageMeta { + index: d.index, + width_pt: d.width_pt, + height_pt: d.height_pt, + }) + .collect(), + outline: outline + .into_iter() + .map(|o| OutlineMeta { + title: o.title, + page_index: o.page_index, + level: o.level, + }) + .collect(), + }) +} + +/// Render một trang ra data URL PNG với chiều rộng `width` px. +#[tauri::command] +fn render_page(path: String, page: u16, width: u32) -> Result { + let pdfium = pdfium()?; + let p = PathBuf::from(&path); + let rendered = + ff_engine::render::render_page(&pdfium, &p, page, width, None).map_err(|e| e.to_string())?; + + let mut buf = Cursor::new(Vec::new()); + rendered + .image + .write_to(&mut buf, image::ImageFormat::Png) + .map_err(|e| e.to_string())?; + let b64 = base64::engine::general_purpose::STANDARD.encode(buf.get_ref()); + Ok(format!("data:image/png;base64,{b64}")) +} + +/// Tìm chuỗi trong tài liệu. +#[tauri::command] +fn search_document( + path: String, + query: String, + case_sensitive: bool, +) -> Result, String> { + let pdfium = pdfium()?; + let p = PathBuf::from(&path); + let hits = + ff_engine::search(&pdfium, &p, &query, case_sensitive, None).map_err(|e| e.to_string())?; + Ok(hits + .into_iter() + .map(|h| SearchHitMeta { + page_index: h.page_index, + char_start: h.char_start, + char_len: h.char_len, + rect: h.rect.map(|r| RectMeta { + left: r.left, + bottom: r.bottom, + right: r.right, + top: r.top, + }), + }) + .collect()) +} + +/// Lấy text của một trang (cho chức năng copy). +#[tauri::command] +fn page_text(path: String, page: u16) -> Result { + let pdfium = pdfium()?; + let p = PathBuf::from(&path); + ff_engine::extract_text(&pdfium, &p, page, None).map_err(|e| e.to_string()) +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct CharBoxMeta { + ch: String, + left: f32, + bottom: f32, + right: f32, + top: f32, +} + +/// Hộp bao từng ký tự của một trang (dựng text-layer để chọn & copy). +#[tauri::command] +fn page_text_layer(path: String, page: u16) -> Result, String> { + let pdfium = pdfium()?; + let p = PathBuf::from(&path); + let boxes = ff_engine::page_char_boxes(&pdfium, &p, page, None).map_err(|e| e.to_string())?; + Ok(boxes + .into_iter() + .map(|b| CharBoxMeta { + ch: b.ch, + left: b.left, + bottom: b.bottom, + right: b.right, + top: b.top, + }) + .collect()) +} + +/// Mở hộp thoại chọn file PDF; trả về đường dẫn đã chọn (hoặc None nếu huỷ). +#[tauri::command] +fn pick_pdf(app: tauri::AppHandle) -> Option { + app.dialog() + .file() + .add_filter("PDF", &["pdf"]) + .blocking_pick_file() + .map(|fp| fp.to_string()) +} + +/// Hộp thoại lưu file PDF; trả về đường dẫn (hoặc None nếu huỷ). +#[tauri::command] +fn pick_save_pdf(app: tauri::AppHandle) -> Option { + app.dialog() + .file() + .add_filter("PDF", &["pdf"]) + .set_file_name("annotated.pdf") + .blocking_save_file() + .map(|fp| fp.to_string()) +} + +/// Hộp chữ nhật đơn giản (1 quad) dùng cho `AnnotSpecDto.quads`. +#[derive(serde::Deserialize)] +#[serde(rename_all = "camelCase")] +struct RectDto { + left: f32, + bottom: f32, + right: f32, + top: f32, +} + +/// DTO nhận từ frontend cho một annotation. +#[derive(serde::Deserialize)] +#[serde(rename_all = "camelCase")] +struct AnnotSpecDto { + kind: String, + page_index: u16, + left: f32, + bottom: f32, + right: f32, + top: f32, + /// Highlight/Underline/Strikeout theo text nhiều dòng: 1 quad/dòng. + /// Rỗng/thiếu → engine suy ra 1 quad duy nhất từ left/bottom/right/top. + #[serde(default)] + quads: Vec, + color: [u8; 4], + contents: Option, + #[serde(default = "default_font_size")] + font_size: f32, + #[serde(default)] + bold: bool, + #[serde(default)] + italic: bool, + #[serde(default)] + underline: bool, +} + +fn default_font_size() -> f32 { + 14.0 +} + +/// Tạo annotation theo specs rồi lưu sang `output`. +#[tauri::command] +fn apply_annotations( + input: String, + output: String, + specs: Vec, +) -> Result<(), String> { + use ff_engine::{AnnotKind, AnnotSpec, Rect}; + let pdfium = pdfium()?; + let mut mapped = Vec::with_capacity(specs.len()); + for s in specs { + let kind = match s.kind.as_str() { + "highlight" => AnnotKind::Highlight, + "underline" => AnnotKind::Underline, + "strikeout" => AnnotKind::Strikeout, + "square" => AnnotKind::Square, + "freetext" => AnnotKind::FreeText, + "note" => AnnotKind::Note, + other => return Err(format!("loại annotation không hỗ trợ: {other}")), + }; + mapped.push(AnnotSpec { + kind, + page_index: s.page_index, + rect: Rect { + left: s.left, + bottom: s.bottom, + right: s.right, + top: s.top, + }, + quads: s + .quads + .into_iter() + .map(|q| Rect { left: q.left, bottom: q.bottom, right: q.right, top: q.top }) + .collect(), + color: s.color, + contents: s.contents, + font_size: s.font_size, + bold: s.bold, + italic: s.italic, + underline: s.underline, + }); + } + ff_engine::apply_annotations( + &pdfium, + std::path::Path::new(&input), + std::path::Path::new(&output), + &mapped, + ) + .map_err(|e| e.to_string()) +} + +/// Đường dẫn file PDF mẫu để mở khi khởi động. +#[tauri::command] +fn default_pdf() -> String { + workspace_root() + .join("corpus") + .join("sample-multipage.pdf") + .to_string_lossy() + .into_owned() +} + +/// File PDF được truyền qua command-line (Explorer gọi `fofreexit-app.exe "C:\...\a.pdf"` +/// khi double-click hoặc "Open with FoFreeXit"). `None` nếu mở app trực tiếp (không kèm file). +#[tauri::command] +fn initial_file() -> Option { + let arg = std::env::args().nth(1)?; + let path = std::path::PathBuf::from(&arg); + let is_pdf = path + .extension() + .map(|e| e.eq_ignore_ascii_case("pdf")) + .unwrap_or(false); + if is_pdf && path.exists() { + Some(arg) + } else { + None + } +} + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .invoke_handler(tauri::generate_handler![ + open_document, + render_page, + search_document, + page_text, + page_text_layer, + pick_pdf, + pick_save_pdf, + apply_annotations, + default_pdf, + initial_file + ]) + .run(tauri::generate_context!()) + .expect("lỗi khi chạy ứng dụng Tauri"); +} diff --git a/app/src-tauri/tauri.conf.json b/app/src-tauri/tauri.conf.json new file mode 100644 index 0000000..090ca17 --- /dev/null +++ b/app/src-tauri/tauri.conf.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "FoFreeXit", + "version": "0.1.0", + "identifier": "com.fofreexit.app", + "build": { + "frontendDist": "../src" + }, + "app": { + "withGlobalTauri": true, + "windows": [ + { + "label": "main", + "title": "FoFreeXit — PDF Viewer (Phase 1)", + "width": 1100, + "height": 850 + } + ], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/icon.ico", + "icons/icon.png" + ] + } +} diff --git a/app/src/index.html b/app/src/index.html new file mode 100644 index 0000000..8bf589b --- /dev/null +++ b/app/src/index.html @@ -0,0 +1,74 @@ + + + + + + FoFreeXit + + + +
+ FoFreeXit + Phase 1 · Viewer + + + + + / — + + + + + + + + + + + + — + + + +
+ +
+ +
+ Chú thích: + + + + + + + + + + + + + + +
+ +
+ + +
+
+
+
+ + + + diff --git a/app/src/main.js b/app/src/main.js new file mode 100644 index 0000000..eb42492 --- /dev/null +++ b/app/src/main.js @@ -0,0 +1,1412 @@ +const { invoke } = window.__TAURI__.core; +const $ = (id) => document.getElementById(id); + +const PT_PER_PX = 96 / 72; // 1pt = 1.333px ở zoom 100% +const DPR = window.devicePixelRatio || 1; + +const state = { + path: null, + pages: [], // [{index,widthPt,heightPt}] + zoom: 1.0, // 1.0 = 100% + slots: [], // phần tử DOM theo trang + visible: new Set(), // trang đang trong vùng nhìn + current: 0, // trang hiện tại (trên cùng vùng nhìn) + hits: [], // kết quả tìm kiếm + hitIdx: -1, + textLayers: {}, // cache hộp ký tự theo trang + tool: null, // công cụ chú thích đang chọn + color: [255, 230, 0], // màu chú thích (RGB) + annotSpecs: [], // chú thích chưa lưu + selectedId: null, // annotation đang chọn + recentColors: [], // màu dùng gần đây + undoStack: [], // snapshot annotSpecs trước mỗi hành động (Ctrl+Z) + redoStack: [], +}; +const UNDO_LIMIT = 50; +let annotIdSeq = 1; +const PRESET_COLORS = [ + [255, 230, 0], [255, 145, 0], [255, 0, 0], [233, 30, 99], + [156, 39, 176], [63, 81, 181], [33, 150, 243], [0, 188, 212], + [0, 150, 136], [76, 175, 80], [0, 0, 0], [120, 120, 120], +]; + +function displaySize(p) { + return { + w: Math.round(p.widthPt * PT_PER_PX * state.zoom), + h: Math.round(p.heightPt * PT_PER_PX * state.zoom), + }; +} + +// ---------- Khởi tạo ---------- + +function shortName(path) { + return path.split(/[\\/]/).pop(); +} + +async function loadDocument(path) { + try { + state.path = path; + state.textLayers = {}; + state.hits = []; + state.hitIdx = -1; + state.current = 0; + state.annotSpecs = []; + state.undoStack = []; + state.redoStack = []; + updateUndoRedoButtons(); + setTool(null); + updateAnnotCount(); + buildComments(); + $("searchBox").value = ""; + $("searchCount").textContent = "—"; + const meta = await invoke("open_document", { path }); + state.pages = meta.pages; + buildPages(); + buildThumbnails(); + buildOutline(meta.outline); + $("status").textContent = `${meta.pageCount} trang · ${shortName(path)}`; + updatePageTotal(); + updateCurrentPage(); + updateZoomLabel(); + } catch (e) { + $("status").textContent = "Lỗi mở tài liệu: " + e; + } +} + +async function boot() { + // Nếu app được mở qua "Open with FoFreeXit" / double-click file PDF trong + // Explorer, Windows truyền đường dẫn file qua command-line — ưu tiên mở nó. + const fromExplorer = await invoke("initial_file"); + loadDocument(fromExplorer || (await invoke("default_pdf"))); +} + +async function openFile() { + try { + const path = await invoke("pick_pdf"); + if (path) loadDocument(path); + } catch (e) { + $("status").textContent = "Lỗi chọn file: " + e; + } +} + +let pageObserver; + +function buildPages() { + const container = $("pages"); + container.innerHTML = ""; + state.slots = []; + state.visible.clear(); + + for (const p of state.pages) { + const slot = document.createElement("div"); + slot.className = "page-slot"; + slot.dataset.index = p.index; + const { w, h } = displaySize(p); + slot.style.width = w + "px"; + slot.style.height = h + "px"; + + const ph = document.createElement("div"); + ph.className = "ph"; + ph.textContent = `Trang ${p.index + 1}`; + slot.appendChild(ph); + + const overlay = document.createElement("div"); + overlay.className = "overlay"; + slot.appendChild(overlay); + + const annotlayer = document.createElement("div"); + annotlayer.className = "annotlayer"; + slot.appendChild(annotlayer); + + container.appendChild(slot); + state.slots[p.index] = slot; + } + + if (pageObserver) pageObserver.disconnect(); + pageObserver = new IntersectionObserver(onIntersect, { + root: $("viewport"), + rootMargin: "500px 0px", + threshold: 0.01, + }); + for (const slot of state.slots) pageObserver.observe(slot); + $("viewport").scrollTop = 0; +} + +function onIntersect(entries) { + for (const e of entries) { + const idx = Number(e.target.dataset.index); + if (e.isIntersecting) { + state.visible.add(idx); + renderSlot(idx); + } else { + state.visible.delete(idx); + } + } + updateCurrentPage(); +} + +function zoomKey() { + return state.zoom.toFixed(3); +} + +async function renderSlot(idx) { + const slot = state.slots[idx]; + if (!slot) return; + if (slot.dataset.renderedZoom === zoomKey()) return; // đã render ở zoom này + slot.dataset.renderedZoom = zoomKey(); + + const p = state.pages[idx]; + const renderWidth = Math.round(p.widthPt * PT_PER_PX * state.zoom * DPR); + try { + const dataUrl = await invoke("render_page", { + path: state.path, + page: idx, + width: renderWidth, + }); + let img = slot.querySelector("img"); + if (!img) { + img = document.createElement("img"); + slot.insertBefore(img, slot.firstChild); + } + img.src = dataUrl; + const ph = slot.querySelector(".ph"); + if (ph) ph.remove(); + buildTextLayer(idx); + drawAnnotsForPage(idx); + } catch (e) { + slot.dataset.renderedZoom = ""; // cho phép thử lại + $("status").textContent = "Lỗi render trang " + (idx + 1) + ": " + e; + } +} + +// Dựng lớp text trong suốt cho phép chọn & copy text trên ảnh trang. +async function buildTextLayer(idx) { + const slot = state.slots[idx]; + if (!slot) return; + let layer = slot.querySelector(".textlayer"); + if (!layer) { + layer = document.createElement("div"); + layer.className = "textlayer"; + slot.appendChild(layer); + } + let boxes = state.textLayers[idx]; + if (!boxes) { + try { + boxes = await invoke("page_text_layer", { path: state.path, page: idx }); + state.textLayers[idx] = boxes; + } catch { + return; + } + } + const p = state.pages[idx]; + const scale = PT_PER_PX * state.zoom; + layer.innerHTML = ""; + const frag = document.createDocumentFragment(); + + // Gom ký tự thành "từ" (mỗi từ = 1 span) để double-click chọn cả từ, + // kéo/Shift+Click chọn dải, và copy giữ khoảng trắng (chèn text node " "). + let word = null; + const flush = () => { + if (word && word.text) { + const w = (word.right - word.left) * scale; + const h = (word.top - word.bottom) * scale; + const span = document.createElement("span"); + span.textContent = word.text; + span.style.left = word.left * scale + "px"; + span.style.top = (p.heightPt - word.top) * scale + "px"; + span.style.width = Math.max(w, 1) + "px"; + span.style.height = h + "px"; + span.style.fontSize = h * 0.82 + "px"; + span.style.lineHeight = h + "px"; + frag.appendChild(span); + } + word = null; + }; + + for (const b of boxes) { + const isWs = !b.ch || /\s/.test(b.ch); + if (isWs) { + flush(); + frag.appendChild(document.createTextNode(b.ch && /\n/.test(b.ch) ? "\n" : " ")); + continue; + } + const h = b.top - b.bottom; + if (h <= 0) continue; + if (word) { + const sameLine = Math.abs(b.bottom - word.bottom) <= 0.6 * (word.top - word.bottom); + const gap = b.left - word.right; + if (!sameLine || gap > 0.3 * (word.top - word.bottom)) { + flush(); + frag.appendChild(document.createTextNode(" ")); + } + } + if (!word) { + word = { text: b.ch, left: b.left, right: b.right, top: b.top, bottom: b.bottom }; + } else { + word.text += b.ch; + word.left = Math.min(word.left, b.left); + word.right = Math.max(word.right, b.right); + word.top = Math.max(word.top, b.top); + word.bottom = Math.min(word.bottom, b.bottom); + } + } + flush(); + layer.appendChild(frag); +} + +function updateCurrentPage() { + const vp = $("viewport"); + const probe = vp.scrollTop + vp.clientHeight * 0.35; + let cur = 0; + for (const slot of state.slots) { + if (!slot) continue; + if (slot.offsetTop <= probe) cur = Number(slot.dataset.index); + else break; + } + if (cur !== state.current) { + state.current = cur; + if (document.activeElement !== $("pageInput")) $("pageInput").value = cur + 1; + document.querySelectorAll(".thumb").forEach((t) => { + t.classList.toggle("active", Number(t.dataset.index) === cur); + }); + } +} + +function updatePageTotal() { + $("pageTotal").textContent = state.pages.length || "—"; + $("pageInput").value = state.pages.length ? state.current + 1 : ""; +} + +function goToPageInput() { + const n = parseInt($("pageInput").value, 10); + if (!Number.isFinite(n)) { $("pageInput").value = state.current + 1; return; } + const idx = Math.max(0, Math.min(state.pages.length - 1, n - 1)); + goToPage(idx); + $("pageInput").value = idx + 1; +} + +function gotoPrevPage() { goToPage(Math.max(0, state.current - 1)); } +function gotoNextPage() { goToPage(Math.min(state.pages.length - 1, state.current + 1)); } + +// ---------- Thumbnails ---------- + +let thumbObserver; +const THUMB_W = 130; + +function buildThumbnails() { + const box = $("thumbs"); + box.innerHTML = ""; + if (thumbObserver) thumbObserver.disconnect(); + // Lazy: chỉ render thumbnail khi cuộn tới (quan trọng với file 1000+ trang). + thumbObserver = new IntersectionObserver(onThumbIntersect, { + root: box, + rootMargin: "400px 0px", + threshold: 0.01, + }); + for (const p of state.pages) { + const el = document.createElement("div"); + el.className = "thumb"; + el.dataset.index = p.index; + // Giữ chỗ đúng tỉ lệ để placeholder có chiều cao (observer hoạt động đúng). + const thumbH = Math.round(THUMB_W * (p.heightPt / p.widthPt)); + el.style.minHeight = thumbH + 18 + "px"; + el.innerHTML = `t${p.index}
${p.index + 1}
`; + el.addEventListener("click", () => goToPage(p.index)); + box.appendChild(el); + thumbObserver.observe(el); + } +} + +function onThumbIntersect(entries) { + for (const e of entries) { + if (!e.isIntersecting) continue; + const el = e.target; + if (el.dataset.loaded) continue; + el.dataset.loaded = "1"; + const idx = Number(el.dataset.index); + invoke("render_page", { path: state.path, page: idx, width: 150 }) + .then((url) => { + const img = el.querySelector("img"); + img.src = url; + img.style.height = ""; // trả lại auto theo tỉ lệ + el.style.minHeight = ""; + }) + .catch(() => { el.dataset.loaded = ""; }); + } +} + +// ---------- Outline ---------- + +function buildOutline(items) { + const box = $("outline"); + box.innerHTML = ""; + if (!items.length) { + box.innerHTML = `
Không có outline
`; + return; + } + for (const it of items) { + const el = document.createElement("div"); + el.className = "oitem"; + el.style.paddingLeft = 6 + it.level * 14 + "px"; + el.textContent = it.title || "(không tiêu đề)"; + if (it.pageIndex != null) { + el.addEventListener("click", () => goToPage(it.pageIndex)); + } else { + el.style.color = "#777"; + } + box.appendChild(el); + } +} + +// ---------- Điều hướng ---------- + +function goToPage(idx) { + const slot = state.slots[idx]; + if (slot) slot.scrollIntoView({ behavior: "smooth", block: "start" }); +} + +// ---------- Zoom ---------- + +function setZoom(z) { + finishEditing(); + closeNotePopup(); + closeColorPopover(); + state.zoom = Math.max(0.25, Math.min(5, z)); + // Phản hồi tức thì & mượt: chỉ đổi kích thước slot → ảnh sẵn có co giãn theo. + for (const p of state.pages) { + const slot = state.slots[p.index]; + if (!slot) continue; + const { w, h } = displaySize(p); + slot.style.width = w + "px"; + slot.style.height = h + "px"; + } + // Overlay/annotation rẻ → vẽ lại ngay để bám theo. + drawHighlightsForVisible(); + for (const idx of state.visible) drawAnnotsForPage(idx); + updateZoomLabel(); + // Render NÉT bằng PDFium chỉ sau khi ngừng zoom (tránh flood gây lag/crash). + scheduleSharpRerender(); +} + +let sharpTimer = null; +function scheduleSharpRerender() { + clearTimeout(sharpTimer); + sharpTimer = setTimeout(() => { + for (const idx of state.visible) { + const slot = state.slots[idx]; + if (slot) { + slot.dataset.renderedZoom = ""; // buộc render lại ở zoom mới + clearOverlay(slot); + } + renderSlot(idx); + } + drawHighlightsForVisible(); + for (const idx of state.visible) drawAnnotsForPage(idx); + }, 180); +} + +const ZOOM_PRESETS = [50, 75, 100, 125, 150, 200, 300, 400]; +function buildZoomSelect() { + const sel = $("zoomSelect"); + sel.innerHTML = ""; + for (const pct of ZOOM_PRESETS) { + const o = document.createElement("option"); + o.value = pct; o.textContent = pct + "%"; + sel.appendChild(o); + } +} +function updateZoomLabel() { + const sel = $("zoomSelect"); + const pct = Math.round(state.zoom * 100); + let custom = sel.querySelector('option[data-custom="1"]'); + const matchesPreset = ZOOM_PRESETS.includes(pct); + if (matchesPreset) { + if (custom) custom.remove(); + sel.value = String(pct); + } else { + if (!custom) { + custom = document.createElement("option"); + custom.dataset.custom = "1"; + sel.appendChild(custom); + } + custom.value = String(pct); + custom.textContent = pct + "%"; + sel.value = String(pct); + } +} + +// Zoom giữ nguyên điểm dưới con trỏ chuột (Ctrl + lăn chuột). +function zoomAtPoint(newZoom, clientX, clientY) { + const vp = $("viewport"); + const rect = vp.getBoundingClientRect(); + const px = clientX - rect.left; + const py = clientY - rect.top; + const cx = vp.scrollLeft + px; + const cy = vp.scrollTop + py; + const old = state.zoom; + setZoom(newZoom); + const f = state.zoom / old; + vp.scrollLeft = cx * f - px; + vp.scrollTop = cy * f - py; +} + +function fitWidth() { + if (!state.pages.length) return; + const avail = $("viewport").clientWidth - 48; + const p = state.pages[state.current] || state.pages[0]; + setZoom(avail / (p.widthPt * PT_PER_PX)); +} + +function fitPage() { + if (!state.pages.length) return; + const vp = $("viewport"); + const availW = vp.clientWidth - 48; + const availH = vp.clientHeight - 48; + const p = state.pages[state.current] || state.pages[0]; + const zw = availW / (p.widthPt * PT_PER_PX); + const zh = availH / (p.heightPt * PT_PER_PX); + setZoom(Math.min(zw, zh)); +} + +// ---------- Tìm kiếm ---------- + +let searchTimer; +async function runSearch() { + const q = $("searchBox").value.trim(); + clearAllHighlights(); + state.hits = []; + state.hitIdx = -1; + if (!q) { $("searchCount").textContent = "—"; return; } + try { + const hits = await invoke("search_document", { + path: state.path, + query: q, + caseSensitive: $("searchCase").checked, + }); + state.hits = hits; + $("searchCount").textContent = hits.length ? `0/${hits.length}` : "0"; + if (hits.length) gotoHit(0); + drawHighlightsForVisible(); + } catch (e) { + $("searchCount").textContent = "lỗi"; + $("status").textContent = "Lỗi tìm kiếm: " + e; + } +} + +function gotoHit(i) { + if (!state.hits.length) return; + state.hitIdx = (i + state.hits.length) % state.hits.length; + const hit = state.hits[state.hitIdx]; + $("searchCount").textContent = `${state.hitIdx + 1}/${state.hits.length}`; + goToPage(hit.pageIndex); + // chờ cuộn rồi vẽ highlight + setTimeout(() => { drawHighlightsForVisible(); }, 120); +} + +function clearOverlay(slot) { + const ov = slot.querySelector(".overlay"); + if (ov) ov.innerHTML = ""; +} +function clearAllHighlights() { + for (const slot of state.slots) if (slot) clearOverlay(slot); +} + +function drawHighlightsForVisible() { + clearAllHighlights(); + for (const idx of state.visible) drawHighlightsForPage(idx); + // luôn vẽ trang chứa hit hiện tại + if (state.hitIdx >= 0) drawHighlightsForPage(state.hits[state.hitIdx].pageIndex); +} + +function drawHighlightsForPage(pageIdx) { + const slot = state.slots[pageIdx]; + if (!slot) return; + const p = state.pages[pageIdx]; + const ov = slot.querySelector(".overlay"); + if (!ov) return; + const scale = PT_PER_PX * state.zoom; + state.hits.forEach((h, i) => { + if (h.pageIndex !== pageIdx || !h.rect) return; + const r = h.rect; + const div = document.createElement("div"); + div.className = "hl" + (i === state.hitIdx ? " current" : ""); + div.style.left = r.left * scale + "px"; + div.style.top = (p.heightPt - r.top) * scale + "px"; + div.style.width = (r.right - r.left) * scale + "px"; + div.style.height = (r.top - r.bottom) * scale + "px"; + ov.appendChild(div); + }); +} + +// ---------- Chú thích (annotations) ---------- + +function hexToRgb(hex) { + const n = parseInt(hex.slice(1), 16); + return [(n >> 16) & 255, (n >> 8) & 255, n & 255]; +} +function rgbCss(c) { return `rgb(${c[0]},${c[1]},${c[2]})`; } +function escapeHtml(s) { + return s.replace(/[&<>]/g, (c) => ({ "&": "&", "<": "<", ">": ">" }[c])); +} + +// Highlight/Underline/Strikeout bám theo TEXT đã chọn (như Foxit), không phải +// 1 rectangle tự do — khác với Square/FreeText/Note (vẽ/đặt tự do trên trang). +function isTextMarkupTool(tool) { + return tool === "highlight" || tool === "underline" || tool === "strikeout"; +} + +function setTool(tool) { + state.tool = state.tool === tool ? null : tool; + document.querySelectorAll(".atool").forEach((b) => + b.classList.toggle("active", b.dataset.tool === state.tool) + ); + document.body.classList.toggle("tool-active", !!state.tool); + document.body.classList.toggle("tool-mark", isTextMarkupTool(state.tool)); + $("annotHint").textContent = state.tool + ? state.tool === "note" + ? "Bấm lên trang để đặt ghi chú" + : isTextMarkupTool(state.tool) + ? "Kéo chọn văn bản trên trang để tô (bấm lại nút để tắt)" + : "Kéo chuột trên trang để vẽ" + : ""; +} + +function updateAnnotCount() { + $("annotCount").textContent = state.annotSpecs.length; + $("saveAnnots").disabled = state.annotSpecs.length === 0; +} + +// ===== Undo/Redo (Ctrl+Z / Ctrl+Y) ===== +// Snapshot toàn bộ annotSpecs trước mỗi hành động thay đổi (tạo/xoá/sửa nội +// dung-định dạng/đổi màu) — đơn giản & an toàn cho quy mô số lượng chú thích +// của 1 tài liệu, không cần theo dõi diff từng trường. +function snapshotAnnots() { + return JSON.parse(JSON.stringify(state.annotSpecs)); +} +function pushUndo() { + state.undoStack.push(snapshotAnnots()); + if (state.undoStack.length > UNDO_LIMIT) state.undoStack.shift(); + state.redoStack = []; + updateUndoRedoButtons(); +} +function updateUndoRedoButtons() { + $("undoBtn").disabled = state.undoStack.length === 0; + $("redoBtn").disabled = state.redoStack.length === 0; +} +function redrawAllAnnotPages() { + for (const slot of state.slots) { + if (slot) drawAnnotsForPage(Number(slot.dataset.index)); + } +} +function applyAnnotSnapshot(snapshot) { + finishEditing(); + closeNotePopup(); + state.annotSpecs = snapshot; + state.selectedId = null; + redrawAllAnnotPages(); + updateAnnotCount(); + updateUndoRedoButtons(); + buildComments(); +} +function undo() { + if (!state.undoStack.length) return; + const prev = state.undoStack.pop(); + state.redoStack.push(snapshotAnnots()); + applyAnnotSnapshot(prev); +} +function redo() { + if (!state.redoStack.length) return; + const next = state.redoStack.pop(); + state.undoStack.push(snapshotAnnots()); + applyAnnotSnapshot(next); +} + +// Vẽ preview toàn bộ chú thích chưa lưu của 1 trang. +function drawAnnotsForPage(idx) { + const slot = state.slots[idx]; + if (!slot) return; + const layer = slot.querySelector(".annotlayer"); + if (!layer) return; + layer.innerHTML = ""; + const p = state.pages[idx]; + const scale = PT_PER_PX * state.zoom; + const isMarkup = (k) => k === "highlight" || k === "underline" || k === "strikeout"; + + for (const s of state.annotSpecs) { + if (s.pageIndex !== idx) continue; + if (editing && editing.id === s.id) continue; // đang sửa thì bỏ qua preview + const col = rgbCss(s.color); + + if (isMarkup(s.kind)) { + // Mỗi quad (= 1 dòng text đã chọn) vẽ riêng — không phải 1 khối phủ cả + // khoảng trắng giữa các dòng (đúng như Foxit). + const quads = s.quads && s.quads.length ? s.quads : [{ left: s.left, bottom: s.bottom, right: s.right, top: s.top }]; + quads.forEach((q, qi) => { + const left = q.left * scale; + const top = (p.heightPt - q.top) * scale; + const w = (q.right - q.left) * scale; + const h = (q.top - q.bottom) * scale; + const el = document.createElement("div"); + el.dataset.id = s.id; + if (s.kind === "highlight") { + el.className = "a-hl a-sel"; + el.style.background = `rgba(${s.color[0]},${s.color[1]},${s.color[2]},.4)`; + Object.assign(el.style, { left: left + "px", top: top + "px", width: w + "px", height: h + "px" }); + } else if (s.kind === "underline") { + el.className = "a-line a-sel"; + el.style.borderTopColor = col; + Object.assign(el.style, { left: left + "px", top: top + h - 2 + "px", width: w + "px", height: "4px" }); + } else { + el.className = "a-line a-sel"; + el.style.borderTopColor = col; + Object.assign(el.style, { left: left + "px", top: top + h / 2 + "px", width: w + "px", height: "4px" }); + } + el.addEventListener("click", (ev) => { ev.stopPropagation(); selectAnnot(s.id); }); + if (s.id === state.selectedId) { + el.classList.add("selected"); + if (qi === quads.length - 1) { + const del = document.createElement("div"); + del.className = "a-del"; + del.textContent = "✕"; + del.title = "Xoá (Delete)"; + del.addEventListener("click", (ev) => { ev.stopPropagation(); deleteSpec(s.id); }); + el.appendChild(del); + } + } + layer.appendChild(el); + }); + continue; + } + + const left = s.left * scale; + const top = (p.heightPt - s.top) * scale; + const w = (s.right - s.left) * scale; + const h = (s.top - s.bottom) * scale; + const el = document.createElement("div"); + el.dataset.id = s.id; + if (s.kind === "square") { + el.className = "a-box a-sel"; + el.style.borderColor = col; + Object.assign(el.style, { left: left + "px", top: top + "px", width: w + "px", height: h + "px" }); + } else if (s.kind === "freetext") { + el.className = "a-text a-sel"; + el.style.borderColor = col; + el.style.color = col; + el.style.fontSize = (s.fontSize || 14) * scale + "px"; + el.style.fontWeight = s.bold ? "bold" : "normal"; + el.style.fontStyle = s.italic ? "italic" : "normal"; + el.style.textDecoration = s.underline ? "underline" : "none"; + el.textContent = s.contents || "Văn bản…"; + Object.assign(el.style, { left: left + "px", top: top + "px", width: Math.max(w, 40) + "px", minHeight: h + "px" }); + el.addEventListener("dblclick", (ev) => { ev.stopPropagation(); editTextBox(s); }); + } else if (s.kind === "note") { + el.className = "a-note a-sel"; + el.textContent = "📝"; + el.style.background = `rgb(${s.color[0]},${s.color[1]},${s.color[2]})`; + Object.assign(el.style, { left: left + "px", top: top + "px" }); + el.addEventListener("click", (ev) => { ev.stopPropagation(); openNotePopup(s); }); + } + if (s.kind !== "note") { + el.addEventListener("click", (ev) => { ev.stopPropagation(); selectAnnot(s.id); }); + } + if (s.id === state.selectedId) { + el.classList.add("selected"); + const del = document.createElement("div"); + del.className = "a-del"; + del.textContent = "✕"; + del.title = "Xoá (Delete)"; + del.addEventListener("click", (ev) => { ev.stopPropagation(); deleteSpec(s.id); }); + el.appendChild(del); + } + layer.appendChild(el); + } +} + +function selectAnnot(id) { + state.selectedId = id; + finishEditing(); + redrawVisibleAnnots(); +} +function deselectAnnot() { + if (state.selectedId == null) return; + state.selectedId = null; + redrawVisibleAnnots(); +} +function redrawVisibleAnnots() { + for (const idx of state.visible) drawAnnotsForPage(idx); +} +function deleteSpec(id) { + const i = state.annotSpecs.findIndex((s) => s.id === id); + if (i < 0) return; + pushUndo(); + const pg = state.annotSpecs[i].pageIndex; + state.annotSpecs.splice(i, 1); + if (state.selectedId === id) state.selectedId = null; + drawAnnotsForPage(pg); + updateAnnotCount(); + buildComments(); +} + +function cssToPdf(idx, cssX, cssY) { + const p = state.pages[idx]; + const scale = PT_PER_PX * state.zoom; + return { x: cssX / scale, y: p.heightPt - cssY / scale }; +} + +// ===== Sửa Text box tại chỗ (in-place) + thanh Format ===== +let editing = null; // { id, el, bar } + +function editTextBox(spec) { + finishEditing(); + pushUndo(); // ghi lại trạng thái TRƯỚC khi sửa nội dung/định dạng text box + state.selectedId = null; + state.tool = null; + document.querySelectorAll(".atool").forEach((b) => b.classList.remove("active")); + document.body.classList.remove("tool-active"); + + const slot = state.slots[spec.pageIndex]; + const layer = slot.querySelector(".annotlayer"); + const scale = PT_PER_PX * state.zoom; + const left = spec.left * scale; + const top = (state.pages[spec.pageIndex].heightPt - spec.top) * scale; + const w = Math.max((spec.right - spec.left) * scale, 60); + const h = Math.max((spec.top - spec.bottom) * scale, 20); + + const ed = document.createElement("div"); + ed.className = "a-editor"; + ed.contentEditable = "true"; + ed.textContent = spec.contents || ""; + Object.assign(ed.style, { + left: left + "px", top: top + "px", width: w + "px", minHeight: h + "px", + color: rgbCss(spec.color), + fontSize: (spec.fontSize || 14) * scale + "px", + fontWeight: spec.bold ? "bold" : "normal", + fontStyle: spec.italic ? "italic" : "normal", + textDecoration: spec.underline ? "underline" : "none", + }); + layer.appendChild(ed); + drawAnnotsForPage(spec.pageIndex); // ẩn preview của spec đang sửa + + editing = { id: spec.id, el: ed }; + showFmtBar(spec, ed); + ed.focus(); + // đặt con trỏ cuối + const sel = window.getSelection(); + sel.selectAllChildren(ed); + sel.collapseToEnd(); + + ed.addEventListener("keydown", (e) => { + if (e.key === "Escape") { e.preventDefault(); finishEditing(); } + }); +} + +function finishEditing() { + if (!editing) return; + const spec = state.annotSpecs.find((s) => s.id === editing.id); + const ed = editing.el; + if (spec && ed) { + spec.contents = ed.innerText.trim(); + // mở rộng rect theo chiều cao thực tế của editor + const scale = PT_PER_PX * state.zoom; + const realH = ed.offsetHeight / scale; + spec.bottom = spec.top - Math.max(realH, 14); + } + if (ed && ed.parentNode) ed.remove(); + if (editing.bar && editing.bar.parentNode) editing.bar.remove(); + const pg = spec ? spec.pageIndex : null; + editing = null; + // Xoá text box rỗng (không nhập gì). + if (spec && spec.kind === "freetext" && !spec.contents) { + const i = state.annotSpecs.indexOf(spec); + if (i >= 0) state.annotSpecs.splice(i, 1); + } + if (pg != null) drawAnnotsForPage(pg); + updateAnnotCount(); + buildComments(); +} + +// Thanh định dạng nổi cho text box (size, B, I, U, màu) +function showFmtBar(spec, editorEl) { + const bar = document.createElement("div"); + bar.className = "fmtbar"; + const r = editorEl.getBoundingClientRect(); + bar.style.left = r.left + "px"; + bar.style.top = r.top - 40 + "px"; + + const sizes = [8, 10, 12, 14, 18, 24, 32, 48]; + const sizeSel = document.createElement("select"); + sizeSel.title = "Cỡ chữ"; + for (const s of sizes) { + const o = document.createElement("option"); + o.value = s; o.textContent = s; + if (s === (spec.fontSize || 14)) o.selected = true; + sizeSel.appendChild(o); + } + sizeSel.addEventListener("change", () => { + spec.fontSize = Number(sizeSel.value); + editorEl.style.fontSize = spec.fontSize * PT_PER_PX * state.zoom + "px"; + editorEl.focus(); + }); + + const mkToggle = (label, prop, cssApply) => { + const b = document.createElement("button"); + b.textContent = label; + b.className = "fmtbtn" + (spec[prop] ? " on" : ""); + b.addEventListener("mousedown", (e) => e.preventDefault()); + b.addEventListener("click", () => { + spec[prop] = !spec[prop]; + b.classList.toggle("on", spec[prop]); + cssApply(spec[prop]); + editorEl.focus(); + }); + return b; + }; + + bar.appendChild(sizeSel); + bar.appendChild(mkToggle("B", "bold", (on) => editorEl.style.fontWeight = on ? "bold" : "normal")); + const it = mkToggle("I", "italic", (on) => editorEl.style.fontStyle = on ? "italic" : "normal"); + it.style.fontStyle = "italic"; + bar.appendChild(it); + const un = mkToggle("U", "underline", (on) => editorEl.style.textDecoration = on ? "underline" : "none"); + un.style.textDecoration = "underline"; + bar.appendChild(un); + + const colorBtn = document.createElement("button"); + colorBtn.className = "fmtbtn fmt-color"; + colorBtn.innerHTML = `A`; + colorBtn.addEventListener("mousedown", (e) => e.preventDefault()); + colorBtn.addEventListener("click", () => { + openColorPopover(colorBtn, spec.color, (rgb) => { + spec.color = rgb; + editorEl.style.color = rgbCss(rgb); + colorBtn.querySelector(".sw").style.background = rgbCss(rgb); + editorEl.focus(); + }); + }); + bar.appendChild(colorBtn); + + document.body.appendChild(bar); + editing.bar = bar; +} + +// ===== Note popup (xem/sửa/đổi màu/xoá) ===== +let notePopupEl = null; +function openNotePopup(spec) { + closeNotePopup(); + pushUndo(); // ghi lại trạng thái TRƯỚC khi sửa nội dung/màu ghi chú + const slot = state.slots[spec.pageIndex]; + const layer = slot.querySelector(".annotlayer"); + const icon = layer.querySelector(`.a-note[data-id="${spec.id}"]`); + const r = (icon || slot).getBoundingClientRect(); + + const pop = document.createElement("div"); + pop.className = "notepop"; + pop.style.left = r.right + 6 + "px"; + pop.style.top = r.top + "px"; + pop.innerHTML = ` +
Ghi chú✕
+ +
+ + +
`; + document.body.appendChild(pop); + notePopupEl = pop; + + const ta = pop.querySelector(".np-text"); + ta.addEventListener("input", () => { + spec.contents = ta.value; + buildComments(); + }); + pop.querySelector(".np-close").addEventListener("click", closeNotePopup); + pop.querySelector(".np-del").addEventListener("click", () => { + closeNotePopup(); + deleteSpec(spec.id); + }); + pop.querySelector(".np-color").addEventListener("click", (e) => { + openColorPopover(e.currentTarget, spec.color, (rgb) => { + spec.color = rgb; + pop.querySelector(".np-color .sw").style.background = rgbCss(rgb); + drawAnnotsForPage(spec.pageIndex); + }); + }); + ta.focus(); +} +function closeNotePopup() { + if (notePopupEl) { notePopupEl.remove(); notePopupEl = null; } +} + +// ===== Color popover (preset + gần đây + tuỳ chọn) ===== +let colorPopEl = null; +function openColorPopover(anchor, currentRgb, onPick) { + closeColorPopover(); + const r = anchor.getBoundingClientRect(); + const pop = document.createElement("div"); + pop.className = "colorpop"; + pop.style.left = r.left + "px"; + pop.style.top = r.bottom + 4 + "px"; + + const addSwatch = (rgb, container) => { + const s = document.createElement("div"); + s.className = "cs"; + s.style.background = rgbCss(rgb); + if (rgb[0] === currentRgb[0] && rgb[1] === currentRgb[1] && rgb[2] === currentRgb[2]) s.classList.add("cur"); + s.addEventListener("click", () => { + pushRecentColor(rgb); + onPick(rgb.slice()); + closeColorPopover(); + }); + container.appendChild(s); + }; + + const grid = document.createElement("div"); + grid.className = "cgrid"; + for (const c of PRESET_COLORS) addSwatch(c, grid); + pop.appendChild(grid); + + if (state.recentColors.length) { + const lbl = document.createElement("div"); + lbl.className = "clbl"; lbl.textContent = "Gần đây"; + pop.appendChild(lbl); + const rg = document.createElement("div"); + rg.className = "cgrid"; + for (const c of state.recentColors) addSwatch(c, rg); + pop.appendChild(rg); + } + + const custom = document.createElement("label"); + custom.className = "ccustom"; + custom.innerHTML = `Tuỳ chọn… `; + custom.querySelector("input").addEventListener("input", (e) => { + const rgb = hexToRgb(e.target.value); + pushRecentColor(rgb); + onPick(rgb); + }); + custom.querySelector("input").addEventListener("change", closeColorPopover); + pop.appendChild(custom); + + document.body.appendChild(pop); + colorPopEl = pop; +} +function closeColorPopover() { + if (colorPopEl) { colorPopEl.remove(); colorPopEl = null; } +} +function pushRecentColor(rgb) { + state.recentColors = state.recentColors.filter((c) => !(c[0] === rgb[0] && c[1] === rgb[1] && c[2] === rgb[2])); + state.recentColors.unshift(rgb.slice()); + state.recentColors = state.recentColors.slice(0, 8); +} +function rgbToHex(c) { + return "#" + c.map((v) => v.toString(16).padStart(2, "0")).join(""); +} + +let drag = null; +function onPagesMouseDown(e) { + if (!state.tool) { + // click vùng trống: bỏ chọn + đóng popup + kết thúc sửa + if (!e.target.closest(".a-editor")) { + finishEditing(); + closeNotePopup(); + closeColorPopover(); + if (!e.target.dataset || e.target.dataset.id == null) deselectAnnot(); + } + return; + } + // Highlight/Underline/Strikeout: để trình duyệt tự xử lý chọn text (textlayer + // pointer-events đã mở qua .tool-mark) — tạo annotation ở mouseup từ Selection. + if (isTextMarkupTool(state.tool)) return; + const slot = e.target.closest && e.target.closest(".page-slot"); + if (!slot) return; + e.preventDefault(); + const r = slot.getBoundingClientRect(); + drag = { + idx: Number(slot.dataset.index), + x0: e.clientX - r.left, + y0: e.clientY - r.top, + x1: e.clientX - r.left, + y1: e.clientY - r.top, + }; +} +function onPagesMouseMove(e) { + if (!drag) return; + const slot = state.slots[drag.idx]; + const r = slot.getBoundingClientRect(); + drag.x1 = e.clientX - r.left; + drag.y1 = e.clientY - r.top; + const layer = slot.querySelector(".annotlayer"); + let prev = layer.querySelector(".a-preview"); + if (!prev) { + prev = document.createElement("div"); + prev.className = "a-hl a-preview"; + layer.appendChild(prev); + } + const l = Math.min(drag.x0, drag.x1); + const t = Math.min(drag.y0, drag.y1); + prev.style.cssText = + `left:${l}px;top:${t}px;width:${Math.abs(drag.x1 - drag.x0)}px;height:${Math.abs(drag.y1 - drag.y0)}px;` + + `background:rgba(${state.color[0]},${state.color[1]},${state.color[2]},.3)`; +} + +// Mỗi "từ" trong text layer là 1 định vị tuyệt đối riêng (để bám đúng +// pixel PDFium) — vì vậy Range.getClientRects() trả về 1 rect/TỪ, không phải +// 1 rect/DÒNG như với text chảy bình thường. Gộp các rect chồng lấp theo +// chiều dọc (cùng 1 dòng) thành 1 rect duy nhất, để highlight 1 cụm từ liền +// mạch chứ không bị đứt từng từ với khoảng trắng hở giữa. +function mergeRectsIntoLines(rects) { + const sorted = rects.slice().sort((a, b) => a.top - b.top); + const lines = []; + for (const r of sorted) { + const line = lines.find((l) => { + const overlap = Math.min(l.bottom, r.bottom) - Math.max(l.top, r.top); + return overlap > 0.5 * Math.min(l.bottom - l.top, r.bottom - r.top); + }); + if (line) { + line.left = Math.min(line.left, r.left); + line.right = Math.max(line.right, r.right); + line.top = Math.min(line.top, r.top); + line.bottom = Math.max(line.bottom, r.bottom); + } else { + lines.push({ left: r.left, right: r.right, top: r.top, bottom: r.bottom }); + } + } + return lines; +} + +// Tạo Highlight/Underline/Strikeout từ vùng TEXT người dùng vừa chọn (Selection +// API) — bám đúng từng dòng như Foxit, không phải 1 rectangle tự do. +function createMarkupFromSelection() { + const sel = window.getSelection(); + if (!sel || sel.isCollapsed || sel.rangeCount === 0) return; + const range = sel.getRangeAt(0); + const anchorNode = range.commonAncestorContainer; + const anchorEl = anchorNode.nodeType === 1 ? anchorNode : anchorNode.parentElement; + const slot = anchorEl && anchorEl.closest(".page-slot"); + if (!slot) { sel.removeAllRanges(); return; } + + const idx = Number(slot.dataset.index); + const slotRect = slot.getBoundingClientRect(); + const rawRects = Array.from(range.getClientRects()).filter((r) => r.width > 0.5 && r.height > 0.5); + sel.removeAllRanges(); + if (!rawRects.length) return; + const clientRects = mergeRectsIntoLines(rawRects); + + const quads = clientRects.map((r) => { + const a = cssToPdf(idx, r.left - slotRect.left, r.top - slotRect.top); + const b = cssToPdf(idx, r.right - slotRect.left, r.bottom - slotRect.top); + return { + left: Math.min(a.x, b.x), right: Math.max(a.x, b.x), + bottom: Math.min(a.y, b.y), top: Math.max(a.y, b.y), + }; + }); + const bounds = quads.reduce( + (acc, q) => acc ? { + left: Math.min(acc.left, q.left), right: Math.max(acc.right, q.right), + bottom: Math.min(acc.bottom, q.bottom), top: Math.max(acc.top, q.top), + } : { ...q }, + null + ); + + const spec = { + id: annotIdSeq++, + kind: state.tool, + pageIndex: idx, + left: bounds.left, bottom: bounds.bottom, right: bounds.right, top: bounds.top, + quads, + color: [...state.color], + contents: "", + fontSize: 14, + bold: false, + italic: false, + underline: false, + }; + pushUndo(); + state.annotSpecs.push(spec); + pushRecentColor(state.color); + // Giữ tool active để tô tiếp liên tục (như Foxit) — bấm lại nút hoặc Esc để tắt. + drawAnnotsForPage(idx); + updateAnnotCount(); + buildComments(); +} + +function onPagesMouseUp() { + if (state.tool && isTextMarkupTool(state.tool)) { + createMarkupFromSelection(); + return; + } + if (!drag) return; + const d = drag; + drag = null; + const slot = state.slots[d.idx]; + const prev = slot.querySelector(".a-preview"); + if (prev) prev.remove(); + + const a = cssToPdf(d.idx, d.x0, d.y0); + const b = cssToPdf(d.idx, d.x1, d.y1); + const rect = { + left: Math.min(a.x, b.x), + right: Math.max(a.x, b.x), + bottom: Math.min(a.y, b.y), + top: Math.max(a.y, b.y), + }; + const tool = state.tool; + const scale = PT_PER_PX * state.zoom; + const tiny = rect.right - rect.left < 2 || rect.top - rect.bottom < 2; + + if (tool === "note") { + const sz = 18 / scale; + rect.right = rect.left + sz; + rect.bottom = rect.top - sz; + } else if (tool === "freetext") { + if (tiny) { + rect.right = rect.left + 160 / scale; + rect.top = rect.bottom + 24 / scale; + } + } else if (tiny) { + return; + } + + const spec = { + id: annotIdSeq++, + kind: tool, + pageIndex: d.idx, + left: rect.left, + bottom: rect.bottom, + right: rect.right, + top: rect.top, + color: [...state.color], + contents: "", + fontSize: 14, + bold: false, + italic: false, + underline: false, + }; + pushUndo(); + state.annotSpecs.push(spec); + pushRecentColor(state.color); + + // FreeText/Note: gõ ngay → về chế độ chọn (như Foxit). Square: giữ tool active + // để vẽ tiếp liên tục. + if (tool === "freetext" || tool === "note") setTool(null); + drawAnnotsForPage(d.idx); + updateAnnotCount(); + buildComments(); + + if (tool === "freetext") editTextBox(spec); + else if (tool === "note") openNotePopup(spec); +} + +async function saveAnnots() { + if (!state.annotSpecs.length) return; + finishEditing(); + const out = await invoke("pick_save_pdf"); + if (!out) return; + try { + const specs = state.annotSpecs.map((s) => ({ + kind: s.kind, + pageIndex: s.pageIndex, + left: s.left, bottom: s.bottom, right: s.right, top: s.top, + quads: s.quads || [], + color: [s.color[0], s.color[1], s.color[2], 255], + contents: s.contents || null, + fontSize: s.fontSize || 14, + bold: !!s.bold, + italic: !!s.italic, + underline: !!s.underline, + })); + await invoke("apply_annotations", { input: state.path, output: out, specs }); + const n = state.annotSpecs.length; + state.annotSpecs = []; + updateAnnotCount(); + $("status").textContent = `Đã lưu ${n} chú thích → ${shortName(out)}`; + loadDocument(out); + } catch (e) { + $("status").textContent = "Lỗi lưu chú thích: " + e; + } +} + +function buildComments() { + const box = $("comments"); + box.innerHTML = ""; + if (!state.annotSpecs.length) { + box.innerHTML = `
Chưa có chú thích chưa lưu. Chọn công cụ ở thanh trên và vẽ lên trang, rồi bấm "Lưu chú thích".
`; + return; + } + const labels = { + highlight: "Tô sáng", underline: "Gạch chân", strikeout: "Gạch ngang", + square: "Khung", freetext: "Text box", note: "Ghi chú", + }; + for (const s of state.annotSpecs) { + const el = document.createElement("div"); + el.className = "citem"; + el.innerHTML = + `✕` + + `` + + `${labels[s.kind] || s.kind} · trang ${s.pageIndex + 1}` + + (s.contents ? `
${escapeHtml(s.contents)}` : ""); + el.addEventListener("click", (ev) => { + if (ev.target.classList.contains("cdel")) { + deleteSpec(s.id); + } else { + goToPage(s.pageIndex); + selectAnnot(s.id); + if (s.kind === "note") openNotePopup(s); + } + }); + box.appendChild(el); + } +} + +// ---------- Copy ---------- + +async function copyCurrentPage() { + try { + const txt = await invoke("page_text", { path: state.path, page: state.current }); + await navigator.clipboard.writeText(txt); + $("status").textContent = `Đã copy text trang ${state.current + 1} (${txt.length} ký tự)`; + } catch (e) { + $("status").textContent = "Lỗi copy: " + e; + } +} + +// ---------- Sự kiện ---------- + +$("openBtn").addEventListener("click", openFile); +$("zoomIn").addEventListener("click", () => setZoom(state.zoom * 1.25)); +$("zoomOut").addEventListener("click", () => setZoom(state.zoom / 1.25)); +$("zoomFit").addEventListener("click", fitWidth); +$("zoomFitPage").addEventListener("click", fitPage); +buildZoomSelect(); +$("zoomSelect").addEventListener("change", (e) => setZoom(Number(e.target.value) / 100)); +$("copyPage").addEventListener("click", copyCurrentPage); + +$("pagePrev").addEventListener("click", gotoPrevPage); +$("pageNext").addEventListener("click", gotoNextPage); +$("pageInput").addEventListener("keydown", (e) => { + if (e.key === "Enter") { e.preventDefault(); goToPageInput(); } +}); +$("pageInput").addEventListener("blur", goToPageInput); + +$("searchBox").addEventListener("input", () => { + clearTimeout(searchTimer); + searchTimer = setTimeout(runSearch, 300); +}); +$("searchBox").addEventListener("keydown", (e) => { + if (e.key === "Enter") { e.preventDefault(); gotoHit(state.hitIdx + (e.shiftKey ? -1 : 1)); } +}); +$("searchCase").addEventListener("change", runSearch); +$("searchNext").addEventListener("click", () => gotoHit(state.hitIdx + 1)); +$("searchPrev").addEventListener("click", () => gotoHit(state.hitIdx - 1)); +$("viewport").addEventListener("scroll", () => { + updateCurrentPage(); + if (state.hits.length) drawHighlightsForVisible(); + closeColorPopover(); + closeNotePopup(); + finishEditing(); +}); +// Ctrl + lăn chuột: zoom tại vị trí con trỏ. +// Gộp nhiều nấc lăn trong 1 khung hình (rAF) để mượt, không dồn render. +let wheelFactor = 1; +let wheelRAF = 0; +let wheelX = 0; +let wheelY = 0; +$("viewport").addEventListener( + "wheel", + (e) => { + if (!e.ctrlKey) return; + e.preventDefault(); + wheelFactor *= e.deltaY < 0 ? 1.1 : 1 / 1.1; + wheelX = e.clientX; + wheelY = e.clientY; + if (!wheelRAF) { + wheelRAF = requestAnimationFrame(() => { + wheelRAF = 0; + const f = wheelFactor; + wheelFactor = 1; + zoomAtPoint(state.zoom * f, wheelX, wheelY); + }); + } + }, + { passive: false } +); + +$("tabThumbs").addEventListener("click", () => switchTab("thumbs")); +$("tabOutline").addEventListener("click", () => switchTab("outline")); +$("tabComments").addEventListener("click", () => switchTab("comments")); +function switchTab(which) { + for (const [tab, panel] of [["tabThumbs", "thumbs"], ["tabOutline", "outline"], ["tabComments", "comments"]]) { + const on = panel === which; + $(tab).classList.toggle("active", on); + $(panel).classList.toggle("hidden", !on); + } +} + +// Công cụ chú thích +document.querySelectorAll(".atool").forEach((b) => + b.addEventListener("click", () => setTool(b.dataset.tool)) +); +function refreshColorSwatch() { + const sw = $("annotSw"); + if (sw) sw.style.background = rgbCss(state.color); +} +refreshColorSwatch(); +$("annotColorBtn").addEventListener("click", () => { + openColorPopover($("annotColorBtn"), state.color, (rgb) => { + state.color = rgb; + refreshColorSwatch(); + // áp cho annotation đang chọn (nếu có) + if (state.selectedId != null) { + const s = state.annotSpecs.find((x) => x.id === state.selectedId); + if (s) { pushUndo(); s.color = rgb.slice(); drawAnnotsForPage(s.pageIndex); buildComments(); } + } + }); +}); +$("saveAnnots").addEventListener("click", saveAnnots); +$("undoBtn").addEventListener("click", undo); +$("redoBtn").addEventListener("click", redo); +$("pages").addEventListener("mousedown", onPagesMouseDown); +window.addEventListener("mousemove", onPagesMouseMove); +window.addEventListener("mouseup", onPagesMouseUp); + +// Phím tắt chuẩn của trình xem PDF (Foxit/Adobe): điều hướng trang, zoom, +// tìm kiếm, xoá/bỏ chọn annotation. +window.addEventListener("keydown", (e) => { + const typing = e.target.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName); + + if (e.key === "Escape") { + finishEditing(); closeNotePopup(); closeColorPopover(); deselectAnnot(); setTool(null); + return; + } + if ((e.key === "Delete" || e.key === "Backspace") && !typing && state.selectedId != null) { + e.preventDefault(); + deleteSpec(state.selectedId); + return; + } + if (e.ctrlKey && (e.key === "f" || e.key === "F")) { + e.preventDefault(); + $("searchBox").focus(); + $("searchBox").select(); + return; + } + if (e.ctrlKey && (e.key === "=" || e.key === "+")) { e.preventDefault(); setZoom(state.zoom * 1.25); return; } + if (e.ctrlKey && e.key === "-") { e.preventDefault(); setZoom(state.zoom / 1.25); return; } + if (e.ctrlKey && e.key === "0") { e.preventDefault(); setZoom(1); return; } + // Ctrl+Z hoàn tác / Ctrl+Y hoặc Ctrl+Shift+Z làm lại — không chặn khi đang gõ + // trong ô text (để trình duyệt tự xử lý undo cấp ký tự trong contenteditable). + if (e.ctrlKey && !e.shiftKey && (e.key === "z" || e.key === "Z") && !typing) { + e.preventDefault(); + undo(); + return; + } + if (e.ctrlKey && (e.key === "y" || e.key === "Y" || (e.shiftKey && (e.key === "z" || e.key === "Z"))) && !typing) { + e.preventDefault(); + redo(); + return; + } + if (typing) return; + if (e.key === "PageDown") { e.preventDefault(); gotoNextPage(); return; } + if (e.key === "PageUp") { e.preventDefault(); gotoPrevPage(); return; } + if (e.key === "Home") { e.preventDefault(); goToPage(0); return; } + if (e.key === "End") { e.preventDefault(); goToPage(state.pages.length - 1); return; } +}); + +window.addEventListener("DOMContentLoaded", boot); diff --git a/app/src/styles.css b/app/src/styles.css new file mode 100644 index 0000000..81a82f2 --- /dev/null +++ b/app/src/styles.css @@ -0,0 +1,268 @@ +:root { color-scheme: dark; --accent: #4d8bff; } +* { box-sizing: border-box; } +html, body { height: 100%; margin: 0; } +body { + font-family: "Segoe UI", system-ui, sans-serif; + background: #525659; + color: #eee; + display: flex; + flex-direction: column; +} + +/* Toolbar */ +.toolbar { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + background: #323639; + border-bottom: 1px solid #1c1f21; + flex: 0 0 auto; +} +.brand { color: var(--accent); font-size: 16px; } +.phase { color: #9aa0a6; font-size: 12px; } +.sep { width: 1px; height: 22px; background: #4a4f52; margin: 0 4px; } +.spacer { flex: 1; } +.status, .pageind, .searchcount, .zoom { color: #9aa0a6; font-size: 12px; } +.zoom { min-width: 44px; text-align: center; } +.searchcount { min-width: 60px; text-align: center; } +.pageof { color: #9aa0a6; font-size: 12px; } +.pagenum { + width: 42px; text-align: center; background: #1f2224; color: #eee; + border: 1px solid #4a4f52; border-radius: 6px; padding: 4px 4px; font-size: 13px; +} +.searchopt { + display: flex; align-items: center; gap: 3px; color: #9aa0a6; font-size: 12px; + cursor: pointer; user-select: none; +} +button { + background: #4a4f52; + color: #fff; + border: none; + border-radius: 6px; + padding: 4px 9px; + cursor: pointer; + font-size: 13px; +} +button:hover { background: #595f63; } +button:disabled { opacity: .4; cursor: default; } +#copyPage { background: var(--accent); } +select.zoom { + background: #1f2224; color: #eee; border: 1px solid #4a4f52; + border-radius: 6px; padding: 4px 4px; font-size: 13px; min-width: 64px; +} +input[type="search"] { + background: #1f2224; + color: #eee; + border: 1px solid #4a4f52; + border-radius: 6px; + padding: 4px 8px; + width: 220px; +} + +/* Annotation toolbar */ +.annobar { + display: flex; + align-items: center; + gap: 8px; + padding: 5px 12px; + background: #2b2f31; + border-bottom: 1px solid #1c1f21; + flex: 0 0 auto; +} +.annolabel { color: #9aa0a6; font-size: 12px; display: flex; align-items: center; gap: 4px; } +.atool { background: #3a3f42; } +.atool.active { background: var(--accent); box-shadow: 0 0 0 2px rgba(77,139,255,.4); } +#saveAnnots { background: #2e7d32; } +#saveAnnots:disabled { background: #555; } +#annotColor { width: 28px; height: 22px; padding: 0; border: none; background: none; cursor: pointer; } + +/* Body layout */ +.body { flex: 1; display: flex; min-height: 0; } + +/* Khi đang chọn công cụ chú thích: tắt chọn text, đổi con trỏ */ +body.tool-active .textlayer { pointer-events: none; } +body.tool-active .page-slot { cursor: crosshair; } +/* Highlight/Underline/Strikeout: NGƯỢC LẠI — bám theo text đã CHỌN (như Foxit), + nên phải giữ textlayer bắt được chuột để chọn text bình thường. */ +body.tool-mark .textlayer { pointer-events: auto; } +body.tool-mark .page-slot { cursor: text; } + +/* Lớp annotation (preview trước khi lưu) */ +.annotlayer { position: absolute; inset: 0; pointer-events: none; } +.annotlayer .a-hl { position: absolute; background: rgba(255,230,0,.4); } +.annotlayer .a-box { position: absolute; border: 1.5px solid; } +.annotlayer .a-line { position: absolute; height: 0; border-top: 2px solid; } +.annotlayer .a-text { + position: absolute; border: 1px dashed; padding: 2px 4px; + font-size: 12px; color: #111; background: rgba(255,255,255,.6); overflow: hidden; +} +.annotlayer .a-note { + position: absolute; width: 18px; height: 18px; pointer-events: auto; + background: #ffd400; border: 1px solid #b59000; border-radius: 3px; + font-size: 12px; text-align: center; line-height: 18px; cursor: help; +} + +/* Annotation: chọn & xoá */ +.a-sel { pointer-events: auto; cursor: pointer; } +body.tool-active .annotlayer * { pointer-events: none; } +.annotlayer .selected { outline: 2px solid #4d8bff; outline-offset: 1px; } +.annotlayer .a-del { + position: absolute; right: -10px; top: -10px; width: 18px; height: 18px; + background: #e53935; color: #fff; border-radius: 50%; font-size: 11px; + line-height: 18px; text-align: center; cursor: pointer; pointer-events: auto; + box-shadow: 0 1px 4px rgba(0,0,0,.4); +} +.annotlayer .a-line { min-height: 4px; } + +/* Text box editor tại chỗ */ +.a-editor { + position: absolute; pointer-events: auto; background: rgba(255,255,255,.9); + border: 1px solid #4d8bff; outline: none; padding: 2px 4px; line-height: 1.25; + white-space: pre-wrap; word-break: break-word; box-shadow: 0 2px 10px rgba(0,0,0,.3); +} + +/* Thanh định dạng nổi */ +.fmtbar { + position: fixed; z-index: 50; display: flex; gap: 3px; align-items: center; + background: #2b2f31; border: 1px solid #1c1f21; border-radius: 7px; + padding: 4px 6px; box-shadow: 0 4px 16px rgba(0,0,0,.5); +} +.fmtbar select { background: #1f2224; color: #eee; border: 1px solid #4a4f52; border-radius: 4px; padding: 2px; } +.fmtbtn { + width: 26px; height: 24px; background: #3a3f42; color: #fff; border: none; + border-radius: 4px; cursor: pointer; font-weight: bold; padding: 0; + display: inline-flex; align-items: center; justify-content: center; gap: 2px; +} +.fmtbtn.on { background: var(--accent); } +.fmtbtn .sw, .citem .csw, #annotSw, .np-color .sw, .fmt-color .sw { + display: inline-block; width: 12px; height: 12px; border-radius: 2px; + border: 1px solid rgba(255,255,255,.5); vertical-align: middle; +} +#annotSw { width: 14px; height: 14px; } + +/* Note popup */ +.notepop { + position: fixed; z-index: 50; width: 230px; background: #fffbea; color: #222; + border: 1px solid #c9b400; border-radius: 6px; box-shadow: 0 6px 20px rgba(0,0,0,.4); +} +.np-head { display: flex; justify-content: space-between; align-items: center; + background: #ffe600; padding: 4px 8px; font-size: 12px; font-weight: bold; border-radius: 6px 6px 0 0; } +.np-close { cursor: pointer; } +.np-text { width: 100%; min-height: 90px; border: none; outline: none; resize: vertical; + padding: 8px; background: transparent; color: #222; font-family: inherit; font-size: 13px; box-sizing: border-box; } +.np-foot { display: flex; justify-content: space-between; padding: 6px 8px; border-top: 1px solid #e0d480; } +.np-foot button { background: #eee; color: #333; font-size: 12px; } +.np-del { color: #c62828 !important; } + +/* Color popover */ +.colorpop { + position: fixed; z-index: 60; background: #2b2f31; border: 1px solid #1c1f21; + border-radius: 7px; padding: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.5); +} +.cgrid { display: grid; grid-template-columns: repeat(6, 20px); gap: 5px; } +.cs { width: 20px; height: 20px; border-radius: 4px; cursor: pointer; border: 2px solid transparent; } +.cs:hover { border-color: #fff; } +.cs.cur { border-color: #4d8bff; } +.clbl { color: #9aa0a6; font-size: 11px; margin: 8px 0 4px; } +.ccustom { display: block; margin-top: 8px; color: #ccc; font-size: 12px; cursor: pointer; } +.ccustom input { vertical-align: middle; margin-left: 4px; } + +/* Comments panel */ +.comments .citem { + padding: 6px; border-radius: 5px; cursor: pointer; font-size: 12px; + border: 1px solid #3a3f42; margin-bottom: 6px; +} +.comments .citem:hover { background: #3a3f42; } +.comments .citem .ckind { color: var(--accent); font-weight: bold; } +.comments .citem .cdel { float: right; color: #e57373; cursor: pointer; } +.comments .empty { color: #777; font-size: 12px; } + +/* Sidebar */ +.sidebar { + width: 220px; + flex: 0 0 220px; + background: #2b2f31; + border-right: 1px solid #1c1f21; + display: flex; + flex-direction: column; + min-height: 0; +} +.tabs { display: flex; flex: 0 0 auto; } +.tab { + flex: 1; + border-radius: 0; + background: #2b2f31; + color: #9aa0a6; + padding: 8px; +} +.tab.active { color: #fff; box-shadow: inset 0 -2px 0 var(--accent); } +.panel { flex: 1; overflow: auto; padding: 8px; } +.panel.hidden { display: none; } + +/* Thumbnails */ +.thumbs { display: flex; flex-direction: column; gap: 10px; align-items: center; } +.thumb { cursor: pointer; text-align: center; width: 100%; } +.thumb img { + width: 130px; + background: #fff; + border: 2px solid transparent; + box-shadow: 0 1px 6px rgba(0,0,0,.5); +} +.thumb.active img { border-color: var(--accent); } +.thumb .n { font-size: 11px; color: #9aa0a6; margin-top: 2px; } + +/* Outline */ +.outline .oitem { + padding: 5px 6px; + border-radius: 5px; + cursor: pointer; + font-size: 13px; + color: #d6d9dc; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.outline .oitem:hover { background: #3a3f42; } + +/* Viewer */ +.viewport { flex: 1; overflow: auto; min-height: 0; } +.pages { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + padding: 20px; +} +.page-slot { + position: relative; + background: #fff; + box-shadow: 0 4px 18px rgba(0,0,0,.5); + flex: 0 0 auto; +} +.page-slot img { display: block; width: 100%; height: 100%; } +.page-slot .ph { + position: absolute; inset: 0; + display: flex; align-items: center; justify-content: center; + color: #888; font-size: 13px; +} +.overlay { position: absolute; inset: 0; pointer-events: none; } + +/* Text layer: span trong suốt phủ lên ảnh để chọn & copy text */ +.textlayer { position: absolute; inset: 0; overflow: hidden; } +.textlayer span { + position: absolute; + color: transparent; + white-space: pre; + overflow: hidden; + cursor: text; + transform-origin: 0 0; +} +.textlayer span::selection { background: rgba(77, 139, 255, .45); } +.page-slot img { user-select: none; -webkit-user-drag: none; } +.hl { + position: absolute; + background: rgba(255, 214, 0, .38); + outline: 1px solid rgba(255, 184, 0, .9); +} +.hl.current { background: rgba(255, 138, 0, .55); } diff --git a/corpus/README.md b/corpus/README.md new file mode 100644 index 0000000..dae4e73 --- /dev/null +++ b/corpus/README.md @@ -0,0 +1,19 @@ +# Corpus PDF mẫu + +Bộ file PDF dùng để test & hồi quy. Sẽ mở rộng dần theo roadmap. + +| File | Mô tả | Dùng cho | +|------|-------|----------| +| `hello.pdf` | PDF tối giản 1 trang, text Helvetica, xref hợp lệ | Smoke test render (Phase 1) | +| `sample-multipage.pdf` | 3 trang Letter, nội dung biết trước + outline (Chapter 1/2/3 → trang 0/1/2) | Test page_dims, extract_text, search, outline; demo viewer | +| `big-1000.pdf` | 1000 trang ("Trang N"); trang index 500 có "ZZMARKER" | Stress-test hiệu năng/lazy-load (mở 55ms, render 110ms, search 79ms) | + +## Cần bổ sung (các phase sau) +- File nhiều trang (100+, 1000+) — hiệu năng & lazy load. +- File scan (ảnh) — OCR (Phase 7). +- File mã hoá (mật khẩu) — bảo mật (Phase 5). +- File hỏng/xref sai — kiểm thử độ bền parser. +- File tiếng Việt (font nhúng, tổ hợp dấu), CJK, RTL — edit text (Phase 4). +- File có AcroForm — form (Phase 6). + +> Lưu ý bản quyền: chỉ thêm file tự tạo hoặc có giấy phép cho phép phân phối. diff --git a/corpus/big-1000.pdf b/corpus/big-1000.pdf new file mode 100644 index 0000000..640b092 --- /dev/null +++ b/corpus/big-1000.pdf @@ -0,0 +1,11020 @@ +%PDF-1.7 +1 0 obj +<< /Type /Catalog /Pages 2 0 R >> +endobj +2 0 obj +<< /Type /Pages /Kids [4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R 55 0 R 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R 70 0 R 71 0 R 72 0 R 73 0 R 74 0 R 75 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R 102 0 R 103 0 R 104 0 R 105 0 R 106 0 R 107 0 R 108 0 R 109 0 R 110 0 R 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R 118 0 R 119 0 R 120 0 R 121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R 127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R 133 0 R 134 0 R 135 0 R 136 0 R 137 0 R 138 0 R 139 0 R 140 0 R 141 0 R 142 0 R 143 0 R 144 0 R 145 0 R 146 0 R 147 0 R 148 0 R 149 0 R 150 0 R 151 0 R 152 0 R 153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R 159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R 165 0 R 166 0 R 167 0 R 168 0 R 169 0 R 170 0 R 171 0 R 172 0 R 173 0 R 174 0 R 175 0 R 176 0 R 177 0 R 178 0 R 179 0 R 180 0 R 181 0 R 182 0 R 183 0 R 184 0 R 185 0 R 186 0 R 187 0 R 188 0 R 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 203 0 R 204 0 R 205 0 R 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 211 0 R 212 0 R 213 0 R 214 0 R 215 0 R 216 0 R 217 0 R 218 0 R 219 0 R 220 0 R 221 0 R 222 0 R 223 0 R 224 0 R 225 0 R 226 0 R 227 0 R 228 0 R 229 0 R 230 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R 238 0 R 239 0 R 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R 250 0 R 251 0 R 252 0 R 253 0 R 254 0 R 255 0 R 256 0 R 257 0 R 258 0 R 259 0 R 260 0 R 261 0 R 262 0 R 263 0 R 264 0 R 265 0 R 266 0 R 267 0 R 268 0 R 269 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 277 0 R 278 0 R 279 0 R 280 0 R 281 0 R 282 0 R 283 0 R 284 0 R 285 0 R 286 0 R 287 0 R 288 0 R 289 0 R 290 0 R 291 0 R 292 0 R 293 0 R 294 0 R 295 0 R 296 0 R 297 0 R 298 0 R 299 0 R 300 0 R 301 0 R 302 0 R 303 0 R 304 0 R 305 0 R 306 0 R 307 0 R 308 0 R 309 0 R 310 0 R 311 0 R 312 0 R 313 0 R 314 0 R 315 0 R 316 0 R 317 0 R 318 0 R 319 0 R 320 0 R 321 0 R 322 0 R 323 0 R 324 0 R 325 0 R 326 0 R 327 0 R 328 0 R 329 0 R 330 0 R 331 0 R 332 0 R 333 0 R 334 0 R 335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R 342 0 R 343 0 R 344 0 R 345 0 R 346 0 R 347 0 R 348 0 R 349 0 R 350 0 R 351 0 R 352 0 R 353 0 R 354 0 R 355 0 R 356 0 R 357 0 R 358 0 R 359 0 R 360 0 R 361 0 R 362 0 R 363 0 R 364 0 R 365 0 R 366 0 R 367 0 R 368 0 R 369 0 R 370 0 R 371 0 R 372 0 R 373 0 R 374 0 R 375 0 R 376 0 R 377 0 R 378 0 R 379 0 R 380 0 R 381 0 R 382 0 R 383 0 R 384 0 R 385 0 R 386 0 R 387 0 R 388 0 R 389 0 R 390 0 R 391 0 R 392 0 R 393 0 R 394 0 R 395 0 R 396 0 R 397 0 R 398 0 R 399 0 R 400 0 R 401 0 R 402 0 R 403 0 R 404 0 R 405 0 R 406 0 R 407 0 R 408 0 R 409 0 R 410 0 R 411 0 R 412 0 R 413 0 R 414 0 R 415 0 R 416 0 R 417 0 R 418 0 R 419 0 R 420 0 R 421 0 R 422 0 R 423 0 R 424 0 R 425 0 R 426 0 R 427 0 R 428 0 R 429 0 R 430 0 R 431 0 R 432 0 R 433 0 R 434 0 R 435 0 R 436 0 R 437 0 R 438 0 R 439 0 R 440 0 R 441 0 R 442 0 R 443 0 R 444 0 R 445 0 R 446 0 R 447 0 R 448 0 R 449 0 R 450 0 R 451 0 R 452 0 R 453 0 R 454 0 R 455 0 R 456 0 R 457 0 R 458 0 R 459 0 R 460 0 R 461 0 R 462 0 R 463 0 R 464 0 R 465 0 R 466 0 R 467 0 R 468 0 R 469 0 R 470 0 R 471 0 R 472 0 R 473 0 R 474 0 R 475 0 R 476 0 R 477 0 R 478 0 R 479 0 R 480 0 R 481 0 R 482 0 R 483 0 R 484 0 R 485 0 R 486 0 R 487 0 R 488 0 R 489 0 R 490 0 R 491 0 R 492 0 R 493 0 R 494 0 R 495 0 R 496 0 R 497 0 R 498 0 R 499 0 R 500 0 R 501 0 R 502 0 R 503 0 R 504 0 R 505 0 R 506 0 R 507 0 R 508 0 R 509 0 R 510 0 R 511 0 R 512 0 R 513 0 R 514 0 R 515 0 R 516 0 R 517 0 R 518 0 R 519 0 R 520 0 R 521 0 R 522 0 R 523 0 R 524 0 R 525 0 R 526 0 R 527 0 R 528 0 R 529 0 R 530 0 R 531 0 R 532 0 R 533 0 R 534 0 R 535 0 R 536 0 R 537 0 R 538 0 R 539 0 R 540 0 R 541 0 R 542 0 R 543 0 R 544 0 R 545 0 R 546 0 R 547 0 R 548 0 R 549 0 R 550 0 R 551 0 R 552 0 R 553 0 R 554 0 R 555 0 R 556 0 R 557 0 R 558 0 R 559 0 R 560 0 R 561 0 R 562 0 R 563 0 R 564 0 R 565 0 R 566 0 R 567 0 R 568 0 R 569 0 R 570 0 R 571 0 R 572 0 R 573 0 R 574 0 R 575 0 R 576 0 R 577 0 R 578 0 R 579 0 R 580 0 R 581 0 R 582 0 R 583 0 R 584 0 R 585 0 R 586 0 R 587 0 R 588 0 R 589 0 R 590 0 R 591 0 R 592 0 R 593 0 R 594 0 R 595 0 R 596 0 R 597 0 R 598 0 R 599 0 R 600 0 R 601 0 R 602 0 R 603 0 R 604 0 R 605 0 R 606 0 R 607 0 R 608 0 R 609 0 R 610 0 R 611 0 R 612 0 R 613 0 R 614 0 R 615 0 R 616 0 R 617 0 R 618 0 R 619 0 R 620 0 R 621 0 R 622 0 R 623 0 R 624 0 R 625 0 R 626 0 R 627 0 R 628 0 R 629 0 R 630 0 R 631 0 R 632 0 R 633 0 R 634 0 R 635 0 R 636 0 R 637 0 R 638 0 R 639 0 R 640 0 R 641 0 R 642 0 R 643 0 R 644 0 R 645 0 R 646 0 R 647 0 R 648 0 R 649 0 R 650 0 R 651 0 R 652 0 R 653 0 R 654 0 R 655 0 R 656 0 R 657 0 R 658 0 R 659 0 R 660 0 R 661 0 R 662 0 R 663 0 R 664 0 R 665 0 R 666 0 R 667 0 R 668 0 R 669 0 R 670 0 R 671 0 R 672 0 R 673 0 R 674 0 R 675 0 R 676 0 R 677 0 R 678 0 R 679 0 R 680 0 R 681 0 R 682 0 R 683 0 R 684 0 R 685 0 R 686 0 R 687 0 R 688 0 R 689 0 R 690 0 R 691 0 R 692 0 R 693 0 R 694 0 R 695 0 R 696 0 R 697 0 R 698 0 R 699 0 R 700 0 R 701 0 R 702 0 R 703 0 R 704 0 R 705 0 R 706 0 R 707 0 R 708 0 R 709 0 R 710 0 R 711 0 R 712 0 R 713 0 R 714 0 R 715 0 R 716 0 R 717 0 R 718 0 R 719 0 R 720 0 R 721 0 R 722 0 R 723 0 R 724 0 R 725 0 R 726 0 R 727 0 R 728 0 R 729 0 R 730 0 R 731 0 R 732 0 R 733 0 R 734 0 R 735 0 R 736 0 R 737 0 R 738 0 R 739 0 R 740 0 R 741 0 R 742 0 R 743 0 R 744 0 R 745 0 R 746 0 R 747 0 R 748 0 R 749 0 R 750 0 R 751 0 R 752 0 R 753 0 R 754 0 R 755 0 R 756 0 R 757 0 R 758 0 R 759 0 R 760 0 R 761 0 R 762 0 R 763 0 R 764 0 R 765 0 R 766 0 R 767 0 R 768 0 R 769 0 R 770 0 R 771 0 R 772 0 R 773 0 R 774 0 R 775 0 R 776 0 R 777 0 R 778 0 R 779 0 R 780 0 R 781 0 R 782 0 R 783 0 R 784 0 R 785 0 R 786 0 R 787 0 R 788 0 R 789 0 R 790 0 R 791 0 R 792 0 R 793 0 R 794 0 R 795 0 R 796 0 R 797 0 R 798 0 R 799 0 R 800 0 R 801 0 R 802 0 R 803 0 R 804 0 R 805 0 R 806 0 R 807 0 R 808 0 R 809 0 R 810 0 R 811 0 R 812 0 R 813 0 R 814 0 R 815 0 R 816 0 R 817 0 R 818 0 R 819 0 R 820 0 R 821 0 R 822 0 R 823 0 R 824 0 R 825 0 R 826 0 R 827 0 R 828 0 R 829 0 R 830 0 R 831 0 R 832 0 R 833 0 R 834 0 R 835 0 R 836 0 R 837 0 R 838 0 R 839 0 R 840 0 R 841 0 R 842 0 R 843 0 R 844 0 R 845 0 R 846 0 R 847 0 R 848 0 R 849 0 R 850 0 R 851 0 R 852 0 R 853 0 R 854 0 R 855 0 R 856 0 R 857 0 R 858 0 R 859 0 R 860 0 R 861 0 R 862 0 R 863 0 R 864 0 R 865 0 R 866 0 R 867 0 R 868 0 R 869 0 R 870 0 R 871 0 R 872 0 R 873 0 R 874 0 R 875 0 R 876 0 R 877 0 R 878 0 R 879 0 R 880 0 R 881 0 R 882 0 R 883 0 R 884 0 R 885 0 R 886 0 R 887 0 R 888 0 R 889 0 R 890 0 R 891 0 R 892 0 R 893 0 R 894 0 R 895 0 R 896 0 R 897 0 R 898 0 R 899 0 R 900 0 R 901 0 R 902 0 R 903 0 R 904 0 R 905 0 R 906 0 R 907 0 R 908 0 R 909 0 R 910 0 R 911 0 R 912 0 R 913 0 R 914 0 R 915 0 R 916 0 R 917 0 R 918 0 R 919 0 R 920 0 R 921 0 R 922 0 R 923 0 R 924 0 R 925 0 R 926 0 R 927 0 R 928 0 R 929 0 R 930 0 R 931 0 R 932 0 R 933 0 R 934 0 R 935 0 R 936 0 R 937 0 R 938 0 R 939 0 R 940 0 R 941 0 R 942 0 R 943 0 R 944 0 R 945 0 R 946 0 R 947 0 R 948 0 R 949 0 R 950 0 R 951 0 R 952 0 R 953 0 R 954 0 R 955 0 R 956 0 R 957 0 R 958 0 R 959 0 R 960 0 R 961 0 R 962 0 R 963 0 R 964 0 R 965 0 R 966 0 R 967 0 R 968 0 R 969 0 R 970 0 R 971 0 R 972 0 R 973 0 R 974 0 R 975 0 R 976 0 R 977 0 R 978 0 R 979 0 R 980 0 R 981 0 R 982 0 R 983 0 R 984 0 R 985 0 R 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 994 0 R 995 0 R 996 0 R 997 0 R 998 0 R 999 0 R 1000 0 R 1001 0 R 1002 0 R 1003 0 R] /Count 1000 >> +endobj +3 0 obj +<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> +endobj +4 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1004 0 R >> +endobj +5 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1005 0 R >> +endobj +6 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1006 0 R >> +endobj +7 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1007 0 R >> +endobj +8 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1008 0 R >> +endobj +9 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1009 0 R >> +endobj +10 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1010 0 R >> +endobj +11 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1011 0 R >> +endobj +12 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1012 0 R >> +endobj +13 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1013 0 R >> +endobj +14 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1014 0 R >> +endobj +15 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1015 0 R >> +endobj +16 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1016 0 R >> +endobj +17 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1017 0 R >> +endobj +18 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1018 0 R >> +endobj +19 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1019 0 R >> +endobj +20 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1020 0 R >> +endobj +21 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1021 0 R >> +endobj +22 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1022 0 R >> +endobj +23 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1023 0 R >> +endobj +24 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1024 0 R >> +endobj +25 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1025 0 R >> +endobj +26 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1026 0 R >> +endobj +27 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1027 0 R >> +endobj +28 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1028 0 R >> +endobj +29 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1029 0 R >> +endobj +30 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1030 0 R >> +endobj +31 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1031 0 R >> +endobj +32 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1032 0 R >> +endobj +33 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1033 0 R >> +endobj +34 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1034 0 R >> +endobj +35 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1035 0 R >> +endobj +36 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1036 0 R >> +endobj +37 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1037 0 R >> +endobj +38 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1038 0 R >> +endobj +39 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1039 0 R >> +endobj +40 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1040 0 R >> +endobj +41 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1041 0 R >> +endobj +42 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1042 0 R >> +endobj +43 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1043 0 R >> +endobj +44 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1044 0 R >> +endobj +45 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1045 0 R >> +endobj +46 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1046 0 R >> +endobj +47 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1047 0 R >> +endobj +48 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1048 0 R >> +endobj +49 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1049 0 R >> +endobj +50 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1050 0 R >> +endobj +51 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1051 0 R >> +endobj +52 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1052 0 R >> +endobj +53 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1053 0 R >> +endobj +54 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1054 0 R >> +endobj +55 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1055 0 R >> +endobj +56 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1056 0 R >> +endobj +57 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1057 0 R >> +endobj +58 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1058 0 R >> +endobj +59 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1059 0 R >> +endobj +60 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1060 0 R >> +endobj +61 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1061 0 R >> +endobj +62 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1062 0 R >> +endobj +63 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1063 0 R >> +endobj +64 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1064 0 R >> +endobj +65 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1065 0 R >> +endobj +66 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1066 0 R >> +endobj +67 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1067 0 R >> +endobj +68 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1068 0 R >> +endobj +69 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1069 0 R >> +endobj +70 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1070 0 R >> +endobj +71 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1071 0 R >> +endobj +72 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1072 0 R >> +endobj +73 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1073 0 R >> +endobj +74 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1074 0 R >> +endobj +75 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1075 0 R >> +endobj +76 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1076 0 R >> +endobj +77 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1077 0 R >> +endobj +78 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1078 0 R >> +endobj +79 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1079 0 R >> +endobj +80 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1080 0 R >> +endobj +81 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1081 0 R >> +endobj +82 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1082 0 R >> +endobj +83 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1083 0 R >> +endobj +84 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1084 0 R >> +endobj +85 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1085 0 R >> +endobj +86 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1086 0 R >> +endobj +87 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1087 0 R >> +endobj +88 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1088 0 R >> +endobj +89 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1089 0 R >> +endobj +90 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1090 0 R >> +endobj +91 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1091 0 R >> +endobj +92 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1092 0 R >> +endobj +93 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1093 0 R >> +endobj +94 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1094 0 R >> +endobj +95 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1095 0 R >> +endobj +96 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1096 0 R >> +endobj +97 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1097 0 R >> +endobj +98 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1098 0 R >> +endobj +99 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1099 0 R >> +endobj +100 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1100 0 R >> +endobj +101 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1101 0 R >> +endobj +102 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1102 0 R >> +endobj +103 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1103 0 R >> +endobj +104 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1104 0 R >> +endobj +105 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1105 0 R >> +endobj +106 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1106 0 R >> +endobj +107 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1107 0 R >> +endobj +108 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1108 0 R >> +endobj +109 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1109 0 R >> +endobj +110 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1110 0 R >> +endobj +111 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1111 0 R >> +endobj +112 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1112 0 R >> +endobj +113 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1113 0 R >> +endobj +114 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1114 0 R >> +endobj +115 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1115 0 R >> +endobj +116 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1116 0 R >> +endobj +117 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1117 0 R >> +endobj +118 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1118 0 R >> +endobj +119 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1119 0 R >> +endobj +120 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1120 0 R >> +endobj +121 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1121 0 R >> +endobj +122 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1122 0 R >> +endobj +123 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1123 0 R >> +endobj +124 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1124 0 R >> +endobj +125 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1125 0 R >> +endobj +126 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1126 0 R >> +endobj +127 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1127 0 R >> +endobj +128 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1128 0 R >> +endobj +129 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1129 0 R >> +endobj +130 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1130 0 R >> +endobj +131 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1131 0 R >> +endobj +132 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1132 0 R >> +endobj +133 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1133 0 R >> +endobj +134 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1134 0 R >> +endobj +135 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1135 0 R >> +endobj +136 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1136 0 R >> +endobj +137 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1137 0 R >> +endobj +138 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1138 0 R >> +endobj +139 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1139 0 R >> +endobj +140 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1140 0 R >> +endobj +141 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1141 0 R >> +endobj +142 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1142 0 R >> +endobj +143 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1143 0 R >> +endobj +144 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1144 0 R >> +endobj +145 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1145 0 R >> +endobj +146 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1146 0 R >> +endobj +147 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1147 0 R >> +endobj +148 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1148 0 R >> +endobj +149 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1149 0 R >> +endobj +150 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1150 0 R >> +endobj +151 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1151 0 R >> +endobj +152 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1152 0 R >> +endobj +153 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1153 0 R >> +endobj +154 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1154 0 R >> +endobj +155 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1155 0 R >> +endobj +156 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1156 0 R >> +endobj +157 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1157 0 R >> +endobj +158 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1158 0 R >> +endobj +159 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1159 0 R >> +endobj +160 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1160 0 R >> +endobj +161 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1161 0 R >> +endobj +162 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1162 0 R >> +endobj +163 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1163 0 R >> +endobj +164 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1164 0 R >> +endobj +165 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1165 0 R >> +endobj +166 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1166 0 R >> +endobj +167 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1167 0 R >> +endobj +168 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1168 0 R >> +endobj +169 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1169 0 R >> +endobj +170 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1170 0 R >> +endobj +171 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1171 0 R >> +endobj +172 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1172 0 R >> +endobj +173 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1173 0 R >> +endobj +174 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1174 0 R >> +endobj +175 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1175 0 R >> +endobj +176 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1176 0 R >> +endobj +177 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1177 0 R >> +endobj +178 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1178 0 R >> +endobj +179 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1179 0 R >> +endobj +180 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1180 0 R >> +endobj +181 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1181 0 R >> +endobj +182 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1182 0 R >> +endobj +183 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1183 0 R >> +endobj +184 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1184 0 R >> +endobj +185 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1185 0 R >> +endobj +186 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1186 0 R >> +endobj +187 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1187 0 R >> +endobj +188 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1188 0 R >> +endobj +189 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1189 0 R >> +endobj +190 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1190 0 R >> +endobj +191 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1191 0 R >> +endobj +192 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1192 0 R >> +endobj +193 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1193 0 R >> +endobj +194 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1194 0 R >> +endobj +195 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1195 0 R >> +endobj +196 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1196 0 R >> +endobj +197 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1197 0 R >> +endobj +198 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1198 0 R >> +endobj +199 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1199 0 R >> +endobj +200 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1200 0 R >> +endobj +201 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1201 0 R >> +endobj +202 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1202 0 R >> +endobj +203 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1203 0 R >> +endobj +204 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1204 0 R >> +endobj +205 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1205 0 R >> +endobj +206 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1206 0 R >> +endobj +207 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1207 0 R >> +endobj +208 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1208 0 R >> +endobj +209 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1209 0 R >> +endobj +210 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1210 0 R >> +endobj +211 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1211 0 R >> +endobj +212 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1212 0 R >> +endobj +213 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1213 0 R >> +endobj +214 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1214 0 R >> +endobj +215 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1215 0 R >> +endobj +216 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1216 0 R >> +endobj +217 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1217 0 R >> +endobj +218 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1218 0 R >> +endobj +219 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1219 0 R >> +endobj +220 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1220 0 R >> +endobj +221 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1221 0 R >> +endobj +222 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1222 0 R >> +endobj +223 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1223 0 R >> +endobj +224 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1224 0 R >> +endobj +225 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1225 0 R >> +endobj +226 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1226 0 R >> +endobj +227 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1227 0 R >> +endobj +228 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1228 0 R >> +endobj +229 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1229 0 R >> +endobj +230 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1230 0 R >> +endobj +231 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1231 0 R >> +endobj +232 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1232 0 R >> +endobj +233 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1233 0 R >> +endobj +234 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1234 0 R >> +endobj +235 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1235 0 R >> +endobj +236 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1236 0 R >> +endobj +237 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1237 0 R >> +endobj +238 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1238 0 R >> +endobj +239 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1239 0 R >> +endobj +240 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1240 0 R >> +endobj +241 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1241 0 R >> +endobj +242 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1242 0 R >> +endobj +243 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1243 0 R >> +endobj +244 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1244 0 R >> +endobj +245 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1245 0 R >> +endobj +246 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1246 0 R >> +endobj +247 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1247 0 R >> +endobj +248 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1248 0 R >> +endobj +249 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1249 0 R >> +endobj +250 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1250 0 R >> +endobj +251 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1251 0 R >> +endobj +252 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1252 0 R >> +endobj +253 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1253 0 R >> +endobj +254 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1254 0 R >> +endobj +255 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1255 0 R >> +endobj +256 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1256 0 R >> +endobj +257 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1257 0 R >> +endobj +258 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1258 0 R >> +endobj +259 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1259 0 R >> +endobj +260 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1260 0 R >> +endobj +261 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1261 0 R >> +endobj +262 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1262 0 R >> +endobj +263 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1263 0 R >> +endobj +264 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1264 0 R >> +endobj +265 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1265 0 R >> +endobj +266 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1266 0 R >> +endobj +267 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1267 0 R >> +endobj +268 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1268 0 R >> +endobj +269 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1269 0 R >> +endobj +270 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1270 0 R >> +endobj +271 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1271 0 R >> +endobj +272 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1272 0 R >> +endobj +273 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1273 0 R >> +endobj +274 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1274 0 R >> +endobj +275 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1275 0 R >> +endobj +276 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1276 0 R >> +endobj +277 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1277 0 R >> +endobj +278 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1278 0 R >> +endobj +279 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1279 0 R >> +endobj +280 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1280 0 R >> +endobj +281 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1281 0 R >> +endobj +282 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1282 0 R >> +endobj +283 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1283 0 R >> +endobj +284 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1284 0 R >> +endobj +285 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1285 0 R >> +endobj +286 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1286 0 R >> +endobj +287 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1287 0 R >> +endobj +288 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1288 0 R >> +endobj +289 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1289 0 R >> +endobj +290 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1290 0 R >> +endobj +291 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1291 0 R >> +endobj +292 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1292 0 R >> +endobj +293 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1293 0 R >> +endobj +294 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1294 0 R >> +endobj +295 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1295 0 R >> +endobj +296 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1296 0 R >> +endobj +297 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1297 0 R >> +endobj +298 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1298 0 R >> +endobj +299 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1299 0 R >> +endobj +300 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1300 0 R >> +endobj +301 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1301 0 R >> +endobj +302 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1302 0 R >> +endobj +303 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1303 0 R >> +endobj +304 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1304 0 R >> +endobj +305 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1305 0 R >> +endobj +306 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1306 0 R >> +endobj +307 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1307 0 R >> +endobj +308 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1308 0 R >> +endobj +309 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1309 0 R >> +endobj +310 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1310 0 R >> +endobj +311 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1311 0 R >> +endobj +312 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1312 0 R >> +endobj +313 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1313 0 R >> +endobj +314 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1314 0 R >> +endobj +315 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1315 0 R >> +endobj +316 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1316 0 R >> +endobj +317 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1317 0 R >> +endobj +318 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1318 0 R >> +endobj +319 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1319 0 R >> +endobj +320 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1320 0 R >> +endobj +321 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1321 0 R >> +endobj +322 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1322 0 R >> +endobj +323 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1323 0 R >> +endobj +324 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1324 0 R >> +endobj +325 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1325 0 R >> +endobj +326 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1326 0 R >> +endobj +327 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1327 0 R >> +endobj +328 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1328 0 R >> +endobj +329 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1329 0 R >> +endobj +330 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1330 0 R >> +endobj +331 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1331 0 R >> +endobj +332 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1332 0 R >> +endobj +333 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1333 0 R >> +endobj +334 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1334 0 R >> +endobj +335 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1335 0 R >> +endobj +336 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1336 0 R >> +endobj +337 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1337 0 R >> +endobj +338 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1338 0 R >> +endobj +339 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1339 0 R >> +endobj +340 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1340 0 R >> +endobj +341 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1341 0 R >> +endobj +342 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1342 0 R >> +endobj +343 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1343 0 R >> +endobj +344 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1344 0 R >> +endobj +345 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1345 0 R >> +endobj +346 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1346 0 R >> +endobj +347 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1347 0 R >> +endobj +348 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1348 0 R >> +endobj +349 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1349 0 R >> +endobj +350 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1350 0 R >> +endobj +351 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1351 0 R >> +endobj +352 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1352 0 R >> +endobj +353 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1353 0 R >> +endobj +354 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1354 0 R >> +endobj +355 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1355 0 R >> +endobj +356 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1356 0 R >> +endobj +357 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1357 0 R >> +endobj +358 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1358 0 R >> +endobj +359 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1359 0 R >> +endobj +360 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1360 0 R >> +endobj +361 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1361 0 R >> +endobj +362 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1362 0 R >> +endobj +363 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1363 0 R >> +endobj +364 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1364 0 R >> +endobj +365 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1365 0 R >> +endobj +366 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1366 0 R >> +endobj +367 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1367 0 R >> +endobj +368 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1368 0 R >> +endobj +369 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1369 0 R >> +endobj +370 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1370 0 R >> +endobj +371 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1371 0 R >> +endobj +372 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1372 0 R >> +endobj +373 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1373 0 R >> +endobj +374 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1374 0 R >> +endobj +375 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1375 0 R >> +endobj +376 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1376 0 R >> +endobj +377 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1377 0 R >> +endobj +378 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1378 0 R >> +endobj +379 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1379 0 R >> +endobj +380 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1380 0 R >> +endobj +381 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1381 0 R >> +endobj +382 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1382 0 R >> +endobj +383 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1383 0 R >> +endobj +384 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1384 0 R >> +endobj +385 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1385 0 R >> +endobj +386 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1386 0 R >> +endobj +387 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1387 0 R >> +endobj +388 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1388 0 R >> +endobj +389 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1389 0 R >> +endobj +390 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1390 0 R >> +endobj +391 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1391 0 R >> +endobj +392 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1392 0 R >> +endobj +393 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1393 0 R >> +endobj +394 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1394 0 R >> +endobj +395 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1395 0 R >> +endobj +396 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1396 0 R >> +endobj +397 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1397 0 R >> +endobj +398 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1398 0 R >> +endobj +399 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1399 0 R >> +endobj +400 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1400 0 R >> +endobj +401 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1401 0 R >> +endobj +402 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1402 0 R >> +endobj +403 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1403 0 R >> +endobj +404 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1404 0 R >> +endobj +405 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1405 0 R >> +endobj +406 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1406 0 R >> +endobj +407 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1407 0 R >> +endobj +408 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1408 0 R >> +endobj +409 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1409 0 R >> +endobj +410 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1410 0 R >> +endobj +411 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1411 0 R >> +endobj +412 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1412 0 R >> +endobj +413 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1413 0 R >> +endobj +414 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1414 0 R >> +endobj +415 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1415 0 R >> +endobj +416 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1416 0 R >> +endobj +417 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1417 0 R >> +endobj +418 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1418 0 R >> +endobj +419 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1419 0 R >> +endobj +420 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1420 0 R >> +endobj +421 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1421 0 R >> +endobj +422 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1422 0 R >> +endobj +423 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1423 0 R >> +endobj +424 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1424 0 R >> +endobj +425 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1425 0 R >> +endobj +426 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1426 0 R >> +endobj +427 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1427 0 R >> +endobj +428 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1428 0 R >> +endobj +429 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1429 0 R >> +endobj +430 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1430 0 R >> +endobj +431 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1431 0 R >> +endobj +432 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1432 0 R >> +endobj +433 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1433 0 R >> +endobj +434 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1434 0 R >> +endobj +435 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1435 0 R >> +endobj +436 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1436 0 R >> +endobj +437 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1437 0 R >> +endobj +438 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1438 0 R >> +endobj +439 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1439 0 R >> +endobj +440 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1440 0 R >> +endobj +441 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1441 0 R >> +endobj +442 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1442 0 R >> +endobj +443 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1443 0 R >> +endobj +444 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1444 0 R >> +endobj +445 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1445 0 R >> +endobj +446 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1446 0 R >> +endobj +447 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1447 0 R >> +endobj +448 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1448 0 R >> +endobj +449 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1449 0 R >> +endobj +450 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1450 0 R >> +endobj +451 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1451 0 R >> +endobj +452 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1452 0 R >> +endobj +453 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1453 0 R >> +endobj +454 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1454 0 R >> +endobj +455 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1455 0 R >> +endobj +456 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1456 0 R >> +endobj +457 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1457 0 R >> +endobj +458 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1458 0 R >> +endobj +459 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1459 0 R >> +endobj +460 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1460 0 R >> +endobj +461 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1461 0 R >> +endobj +462 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1462 0 R >> +endobj +463 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1463 0 R >> +endobj +464 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1464 0 R >> +endobj +465 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1465 0 R >> +endobj +466 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1466 0 R >> +endobj +467 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1467 0 R >> +endobj +468 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1468 0 R >> +endobj +469 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1469 0 R >> +endobj +470 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1470 0 R >> +endobj +471 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1471 0 R >> +endobj +472 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1472 0 R >> +endobj +473 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1473 0 R >> +endobj +474 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1474 0 R >> +endobj +475 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1475 0 R >> +endobj +476 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1476 0 R >> +endobj +477 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1477 0 R >> +endobj +478 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1478 0 R >> +endobj +479 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1479 0 R >> +endobj +480 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1480 0 R >> +endobj +481 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1481 0 R >> +endobj +482 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1482 0 R >> +endobj +483 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1483 0 R >> +endobj +484 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1484 0 R >> +endobj +485 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1485 0 R >> +endobj +486 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1486 0 R >> +endobj +487 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1487 0 R >> +endobj +488 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1488 0 R >> +endobj +489 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1489 0 R >> +endobj +490 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1490 0 R >> +endobj +491 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1491 0 R >> +endobj +492 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1492 0 R >> +endobj +493 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1493 0 R >> +endobj +494 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1494 0 R >> +endobj +495 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1495 0 R >> +endobj +496 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1496 0 R >> +endobj +497 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1497 0 R >> +endobj +498 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1498 0 R >> +endobj +499 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1499 0 R >> +endobj +500 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1500 0 R >> +endobj +501 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1501 0 R >> +endobj +502 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1502 0 R >> +endobj +503 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1503 0 R >> +endobj +504 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1504 0 R >> +endobj +505 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1505 0 R >> +endobj +506 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1506 0 R >> +endobj +507 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1507 0 R >> +endobj +508 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1508 0 R >> +endobj +509 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1509 0 R >> +endobj +510 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1510 0 R >> +endobj +511 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1511 0 R >> +endobj +512 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1512 0 R >> +endobj +513 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1513 0 R >> +endobj +514 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1514 0 R >> +endobj +515 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1515 0 R >> +endobj +516 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1516 0 R >> +endobj +517 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1517 0 R >> +endobj +518 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1518 0 R >> +endobj +519 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1519 0 R >> +endobj +520 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1520 0 R >> +endobj +521 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1521 0 R >> +endobj +522 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1522 0 R >> +endobj +523 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1523 0 R >> +endobj +524 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1524 0 R >> +endobj +525 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1525 0 R >> +endobj +526 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1526 0 R >> +endobj +527 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1527 0 R >> +endobj +528 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1528 0 R >> +endobj +529 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1529 0 R >> +endobj +530 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1530 0 R >> +endobj +531 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1531 0 R >> +endobj +532 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1532 0 R >> +endobj +533 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1533 0 R >> +endobj +534 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1534 0 R >> +endobj +535 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1535 0 R >> +endobj +536 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1536 0 R >> +endobj +537 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1537 0 R >> +endobj +538 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1538 0 R >> +endobj +539 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1539 0 R >> +endobj +540 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1540 0 R >> +endobj +541 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1541 0 R >> +endobj +542 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1542 0 R >> +endobj +543 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1543 0 R >> +endobj +544 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1544 0 R >> +endobj +545 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1545 0 R >> +endobj +546 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1546 0 R >> +endobj +547 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1547 0 R >> +endobj +548 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1548 0 R >> +endobj +549 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1549 0 R >> +endobj +550 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1550 0 R >> +endobj +551 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1551 0 R >> +endobj +552 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1552 0 R >> +endobj +553 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1553 0 R >> +endobj +554 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1554 0 R >> +endobj +555 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1555 0 R >> +endobj +556 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1556 0 R >> +endobj +557 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1557 0 R >> +endobj +558 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1558 0 R >> +endobj +559 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1559 0 R >> +endobj +560 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1560 0 R >> +endobj +561 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1561 0 R >> +endobj +562 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1562 0 R >> +endobj +563 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1563 0 R >> +endobj +564 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1564 0 R >> +endobj +565 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1565 0 R >> +endobj +566 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1566 0 R >> +endobj +567 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1567 0 R >> +endobj +568 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1568 0 R >> +endobj +569 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1569 0 R >> +endobj +570 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1570 0 R >> +endobj +571 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1571 0 R >> +endobj +572 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1572 0 R >> +endobj +573 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1573 0 R >> +endobj +574 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1574 0 R >> +endobj +575 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1575 0 R >> +endobj +576 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1576 0 R >> +endobj +577 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1577 0 R >> +endobj +578 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1578 0 R >> +endobj +579 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1579 0 R >> +endobj +580 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1580 0 R >> +endobj +581 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1581 0 R >> +endobj +582 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1582 0 R >> +endobj +583 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1583 0 R >> +endobj +584 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1584 0 R >> +endobj +585 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1585 0 R >> +endobj +586 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1586 0 R >> +endobj +587 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1587 0 R >> +endobj +588 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1588 0 R >> +endobj +589 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1589 0 R >> +endobj +590 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1590 0 R >> +endobj +591 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1591 0 R >> +endobj +592 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1592 0 R >> +endobj +593 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1593 0 R >> +endobj +594 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1594 0 R >> +endobj +595 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1595 0 R >> +endobj +596 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1596 0 R >> +endobj +597 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1597 0 R >> +endobj +598 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1598 0 R >> +endobj +599 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1599 0 R >> +endobj +600 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1600 0 R >> +endobj +601 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1601 0 R >> +endobj +602 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1602 0 R >> +endobj +603 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1603 0 R >> +endobj +604 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1604 0 R >> +endobj +605 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1605 0 R >> +endobj +606 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1606 0 R >> +endobj +607 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1607 0 R >> +endobj +608 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1608 0 R >> +endobj +609 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1609 0 R >> +endobj +610 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1610 0 R >> +endobj +611 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1611 0 R >> +endobj +612 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1612 0 R >> +endobj +613 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1613 0 R >> +endobj +614 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1614 0 R >> +endobj +615 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1615 0 R >> +endobj +616 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1616 0 R >> +endobj +617 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1617 0 R >> +endobj +618 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1618 0 R >> +endobj +619 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1619 0 R >> +endobj +620 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1620 0 R >> +endobj +621 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1621 0 R >> +endobj +622 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1622 0 R >> +endobj +623 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1623 0 R >> +endobj +624 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1624 0 R >> +endobj +625 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1625 0 R >> +endobj +626 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1626 0 R >> +endobj +627 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1627 0 R >> +endobj +628 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1628 0 R >> +endobj +629 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1629 0 R >> +endobj +630 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1630 0 R >> +endobj +631 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1631 0 R >> +endobj +632 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1632 0 R >> +endobj +633 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1633 0 R >> +endobj +634 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1634 0 R >> +endobj +635 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1635 0 R >> +endobj +636 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1636 0 R >> +endobj +637 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1637 0 R >> +endobj +638 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1638 0 R >> +endobj +639 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1639 0 R >> +endobj +640 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1640 0 R >> +endobj +641 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1641 0 R >> +endobj +642 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1642 0 R >> +endobj +643 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1643 0 R >> +endobj +644 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1644 0 R >> +endobj +645 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1645 0 R >> +endobj +646 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1646 0 R >> +endobj +647 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1647 0 R >> +endobj +648 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1648 0 R >> +endobj +649 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1649 0 R >> +endobj +650 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1650 0 R >> +endobj +651 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1651 0 R >> +endobj +652 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1652 0 R >> +endobj +653 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1653 0 R >> +endobj +654 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1654 0 R >> +endobj +655 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1655 0 R >> +endobj +656 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1656 0 R >> +endobj +657 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1657 0 R >> +endobj +658 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1658 0 R >> +endobj +659 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1659 0 R >> +endobj +660 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1660 0 R >> +endobj +661 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1661 0 R >> +endobj +662 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1662 0 R >> +endobj +663 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1663 0 R >> +endobj +664 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1664 0 R >> +endobj +665 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1665 0 R >> +endobj +666 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1666 0 R >> +endobj +667 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1667 0 R >> +endobj +668 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1668 0 R >> +endobj +669 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1669 0 R >> +endobj +670 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1670 0 R >> +endobj +671 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1671 0 R >> +endobj +672 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1672 0 R >> +endobj +673 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1673 0 R >> +endobj +674 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1674 0 R >> +endobj +675 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1675 0 R >> +endobj +676 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1676 0 R >> +endobj +677 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1677 0 R >> +endobj +678 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1678 0 R >> +endobj +679 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1679 0 R >> +endobj +680 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1680 0 R >> +endobj +681 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1681 0 R >> +endobj +682 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1682 0 R >> +endobj +683 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1683 0 R >> +endobj +684 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1684 0 R >> +endobj +685 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1685 0 R >> +endobj +686 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1686 0 R >> +endobj +687 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1687 0 R >> +endobj +688 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1688 0 R >> +endobj +689 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1689 0 R >> +endobj +690 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1690 0 R >> +endobj +691 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1691 0 R >> +endobj +692 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1692 0 R >> +endobj +693 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1693 0 R >> +endobj +694 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1694 0 R >> +endobj +695 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1695 0 R >> +endobj +696 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1696 0 R >> +endobj +697 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1697 0 R >> +endobj +698 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1698 0 R >> +endobj +699 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1699 0 R >> +endobj +700 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1700 0 R >> +endobj +701 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1701 0 R >> +endobj +702 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1702 0 R >> +endobj +703 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1703 0 R >> +endobj +704 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1704 0 R >> +endobj +705 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1705 0 R >> +endobj +706 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1706 0 R >> +endobj +707 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1707 0 R >> +endobj +708 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1708 0 R >> +endobj +709 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1709 0 R >> +endobj +710 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1710 0 R >> +endobj +711 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1711 0 R >> +endobj +712 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1712 0 R >> +endobj +713 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1713 0 R >> +endobj +714 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1714 0 R >> +endobj +715 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1715 0 R >> +endobj +716 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1716 0 R >> +endobj +717 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1717 0 R >> +endobj +718 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1718 0 R >> +endobj +719 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1719 0 R >> +endobj +720 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1720 0 R >> +endobj +721 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1721 0 R >> +endobj +722 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1722 0 R >> +endobj +723 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1723 0 R >> +endobj +724 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1724 0 R >> +endobj +725 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1725 0 R >> +endobj +726 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1726 0 R >> +endobj +727 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1727 0 R >> +endobj +728 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1728 0 R >> +endobj +729 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1729 0 R >> +endobj +730 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1730 0 R >> +endobj +731 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1731 0 R >> +endobj +732 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1732 0 R >> +endobj +733 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1733 0 R >> +endobj +734 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1734 0 R >> +endobj +735 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1735 0 R >> +endobj +736 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1736 0 R >> +endobj +737 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1737 0 R >> +endobj +738 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1738 0 R >> +endobj +739 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1739 0 R >> +endobj +740 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1740 0 R >> +endobj +741 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1741 0 R >> +endobj +742 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1742 0 R >> +endobj +743 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1743 0 R >> +endobj +744 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1744 0 R >> +endobj +745 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1745 0 R >> +endobj +746 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1746 0 R >> +endobj +747 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1747 0 R >> +endobj +748 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1748 0 R >> +endobj +749 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1749 0 R >> +endobj +750 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1750 0 R >> +endobj +751 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1751 0 R >> +endobj +752 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1752 0 R >> +endobj +753 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1753 0 R >> +endobj +754 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1754 0 R >> +endobj +755 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1755 0 R >> +endobj +756 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1756 0 R >> +endobj +757 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1757 0 R >> +endobj +758 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1758 0 R >> +endobj +759 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1759 0 R >> +endobj +760 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1760 0 R >> +endobj +761 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1761 0 R >> +endobj +762 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1762 0 R >> +endobj +763 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1763 0 R >> +endobj +764 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1764 0 R >> +endobj +765 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1765 0 R >> +endobj +766 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1766 0 R >> +endobj +767 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1767 0 R >> +endobj +768 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1768 0 R >> +endobj +769 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1769 0 R >> +endobj +770 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1770 0 R >> +endobj +771 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1771 0 R >> +endobj +772 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1772 0 R >> +endobj +773 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1773 0 R >> +endobj +774 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1774 0 R >> +endobj +775 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1775 0 R >> +endobj +776 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1776 0 R >> +endobj +777 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1777 0 R >> +endobj +778 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1778 0 R >> +endobj +779 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1779 0 R >> +endobj +780 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1780 0 R >> +endobj +781 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1781 0 R >> +endobj +782 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1782 0 R >> +endobj +783 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1783 0 R >> +endobj +784 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1784 0 R >> +endobj +785 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1785 0 R >> +endobj +786 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1786 0 R >> +endobj +787 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1787 0 R >> +endobj +788 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1788 0 R >> +endobj +789 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1789 0 R >> +endobj +790 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1790 0 R >> +endobj +791 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1791 0 R >> +endobj +792 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1792 0 R >> +endobj +793 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1793 0 R >> +endobj +794 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1794 0 R >> +endobj +795 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1795 0 R >> +endobj +796 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1796 0 R >> +endobj +797 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1797 0 R >> +endobj +798 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1798 0 R >> +endobj +799 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1799 0 R >> +endobj +800 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1800 0 R >> +endobj +801 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1801 0 R >> +endobj +802 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1802 0 R >> +endobj +803 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1803 0 R >> +endobj +804 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1804 0 R >> +endobj +805 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1805 0 R >> +endobj +806 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1806 0 R >> +endobj +807 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1807 0 R >> +endobj +808 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1808 0 R >> +endobj +809 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1809 0 R >> +endobj +810 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1810 0 R >> +endobj +811 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1811 0 R >> +endobj +812 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1812 0 R >> +endobj +813 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1813 0 R >> +endobj +814 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1814 0 R >> +endobj +815 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1815 0 R >> +endobj +816 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1816 0 R >> +endobj +817 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1817 0 R >> +endobj +818 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1818 0 R >> +endobj +819 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1819 0 R >> +endobj +820 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1820 0 R >> +endobj +821 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1821 0 R >> +endobj +822 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1822 0 R >> +endobj +823 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1823 0 R >> +endobj +824 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1824 0 R >> +endobj +825 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1825 0 R >> +endobj +826 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1826 0 R >> +endobj +827 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1827 0 R >> +endobj +828 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1828 0 R >> +endobj +829 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1829 0 R >> +endobj +830 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1830 0 R >> +endobj +831 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1831 0 R >> +endobj +832 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1832 0 R >> +endobj +833 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1833 0 R >> +endobj +834 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1834 0 R >> +endobj +835 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1835 0 R >> +endobj +836 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1836 0 R >> +endobj +837 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1837 0 R >> +endobj +838 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1838 0 R >> +endobj +839 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1839 0 R >> +endobj +840 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1840 0 R >> +endobj +841 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1841 0 R >> +endobj +842 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1842 0 R >> +endobj +843 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1843 0 R >> +endobj +844 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1844 0 R >> +endobj +845 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1845 0 R >> +endobj +846 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1846 0 R >> +endobj +847 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1847 0 R >> +endobj +848 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1848 0 R >> +endobj +849 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1849 0 R >> +endobj +850 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1850 0 R >> +endobj +851 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1851 0 R >> +endobj +852 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1852 0 R >> +endobj +853 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1853 0 R >> +endobj +854 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1854 0 R >> +endobj +855 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1855 0 R >> +endobj +856 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1856 0 R >> +endobj +857 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1857 0 R >> +endobj +858 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1858 0 R >> +endobj +859 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1859 0 R >> +endobj +860 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1860 0 R >> +endobj +861 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1861 0 R >> +endobj +862 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1862 0 R >> +endobj +863 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1863 0 R >> +endobj +864 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1864 0 R >> +endobj +865 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1865 0 R >> +endobj +866 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1866 0 R >> +endobj +867 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1867 0 R >> +endobj +868 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1868 0 R >> +endobj +869 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1869 0 R >> +endobj +870 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1870 0 R >> +endobj +871 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1871 0 R >> +endobj +872 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1872 0 R >> +endobj +873 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1873 0 R >> +endobj +874 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1874 0 R >> +endobj +875 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1875 0 R >> +endobj +876 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1876 0 R >> +endobj +877 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1877 0 R >> +endobj +878 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1878 0 R >> +endobj +879 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1879 0 R >> +endobj +880 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1880 0 R >> +endobj +881 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1881 0 R >> +endobj +882 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1882 0 R >> +endobj +883 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1883 0 R >> +endobj +884 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1884 0 R >> +endobj +885 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1885 0 R >> +endobj +886 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1886 0 R >> +endobj +887 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1887 0 R >> +endobj +888 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1888 0 R >> +endobj +889 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1889 0 R >> +endobj +890 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1890 0 R >> +endobj +891 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1891 0 R >> +endobj +892 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1892 0 R >> +endobj +893 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1893 0 R >> +endobj +894 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1894 0 R >> +endobj +895 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1895 0 R >> +endobj +896 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1896 0 R >> +endobj +897 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1897 0 R >> +endobj +898 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1898 0 R >> +endobj +899 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1899 0 R >> +endobj +900 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1900 0 R >> +endobj +901 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1901 0 R >> +endobj +902 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1902 0 R >> +endobj +903 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1903 0 R >> +endobj +904 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1904 0 R >> +endobj +905 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1905 0 R >> +endobj +906 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1906 0 R >> +endobj +907 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1907 0 R >> +endobj +908 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1908 0 R >> +endobj +909 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1909 0 R >> +endobj +910 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1910 0 R >> +endobj +911 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1911 0 R >> +endobj +912 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1912 0 R >> +endobj +913 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1913 0 R >> +endobj +914 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1914 0 R >> +endobj +915 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1915 0 R >> +endobj +916 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1916 0 R >> +endobj +917 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1917 0 R >> +endobj +918 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1918 0 R >> +endobj +919 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1919 0 R >> +endobj +920 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1920 0 R >> +endobj +921 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1921 0 R >> +endobj +922 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1922 0 R >> +endobj +923 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1923 0 R >> +endobj +924 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1924 0 R >> +endobj +925 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1925 0 R >> +endobj +926 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1926 0 R >> +endobj +927 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1927 0 R >> +endobj +928 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1928 0 R >> +endobj +929 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1929 0 R >> +endobj +930 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1930 0 R >> +endobj +931 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1931 0 R >> +endobj +932 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1932 0 R >> +endobj +933 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1933 0 R >> +endobj +934 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1934 0 R >> +endobj +935 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1935 0 R >> +endobj +936 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1936 0 R >> +endobj +937 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1937 0 R >> +endobj +938 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1938 0 R >> +endobj +939 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1939 0 R >> +endobj +940 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1940 0 R >> +endobj +941 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1941 0 R >> +endobj +942 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1942 0 R >> +endobj +943 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1943 0 R >> +endobj +944 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1944 0 R >> +endobj +945 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1945 0 R >> +endobj +946 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1946 0 R >> +endobj +947 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1947 0 R >> +endobj +948 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1948 0 R >> +endobj +949 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1949 0 R >> +endobj +950 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1950 0 R >> +endobj +951 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1951 0 R >> +endobj +952 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1952 0 R >> +endobj +953 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1953 0 R >> +endobj +954 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1954 0 R >> +endobj +955 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1955 0 R >> +endobj +956 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1956 0 R >> +endobj +957 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1957 0 R >> +endobj +958 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1958 0 R >> +endobj +959 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1959 0 R >> +endobj +960 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1960 0 R >> +endobj +961 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1961 0 R >> +endobj +962 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1962 0 R >> +endobj +963 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1963 0 R >> +endobj +964 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1964 0 R >> +endobj +965 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1965 0 R >> +endobj +966 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1966 0 R >> +endobj +967 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1967 0 R >> +endobj +968 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1968 0 R >> +endobj +969 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1969 0 R >> +endobj +970 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1970 0 R >> +endobj +971 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1971 0 R >> +endobj +972 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1972 0 R >> +endobj +973 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1973 0 R >> +endobj +974 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1974 0 R >> +endobj +975 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1975 0 R >> +endobj +976 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1976 0 R >> +endobj +977 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1977 0 R >> +endobj +978 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1978 0 R >> +endobj +979 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1979 0 R >> +endobj +980 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1980 0 R >> +endobj +981 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1981 0 R >> +endobj +982 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1982 0 R >> +endobj +983 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1983 0 R >> +endobj +984 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1984 0 R >> +endobj +985 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1985 0 R >> +endobj +986 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1986 0 R >> +endobj +987 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1987 0 R >> +endobj +988 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1988 0 R >> +endobj +989 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1989 0 R >> +endobj +990 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1990 0 R >> +endobj +991 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1991 0 R >> +endobj +992 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1992 0 R >> +endobj +993 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1993 0 R >> +endobj +994 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1994 0 R >> +endobj +995 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1995 0 R >> +endobj +996 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1996 0 R >> +endobj +997 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1997 0 R >> +endobj +998 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1998 0 R >> +endobj +999 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 1999 0 R >> +endobj +1000 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 2000 0 R >> +endobj +1001 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 2001 0 R >> +endobj +1002 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 2002 0 R >> +endobj +1003 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 3 0 R >> >> /Contents 2003 0 R >> +endobj +1004 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 1) Tj ET +endstream +endobj +1005 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 2) Tj ET +endstream +endobj +1006 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 3) Tj ET +endstream +endobj +1007 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 4) Tj ET +endstream +endobj +1008 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 5) Tj ET +endstream +endobj +1009 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 6) Tj ET +endstream +endobj +1010 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 7) Tj ET +endstream +endobj +1011 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 8) Tj ET +endstream +endobj +1012 0 obj +<< /Length 39 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 9) Tj ET +endstream +endobj +1013 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 10) Tj ET +endstream +endobj +1014 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 11) Tj ET +endstream +endobj +1015 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 12) Tj ET +endstream +endobj +1016 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 13) Tj ET +endstream +endobj +1017 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 14) Tj ET +endstream +endobj +1018 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 15) Tj ET +endstream +endobj +1019 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 16) Tj ET +endstream +endobj +1020 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 17) Tj ET +endstream +endobj +1021 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 18) Tj ET +endstream +endobj +1022 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 19) Tj ET +endstream +endobj +1023 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 20) Tj ET +endstream +endobj +1024 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 21) Tj ET +endstream +endobj +1025 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 22) Tj ET +endstream +endobj +1026 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 23) Tj ET +endstream +endobj +1027 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 24) Tj ET +endstream +endobj +1028 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 25) Tj ET +endstream +endobj +1029 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 26) Tj ET +endstream +endobj +1030 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 27) Tj ET +endstream +endobj +1031 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 28) Tj ET +endstream +endobj +1032 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 29) Tj ET +endstream +endobj +1033 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 30) Tj ET +endstream +endobj +1034 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 31) Tj ET +endstream +endobj +1035 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 32) Tj ET +endstream +endobj +1036 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 33) Tj ET +endstream +endobj +1037 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 34) Tj ET +endstream +endobj +1038 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 35) Tj ET +endstream +endobj +1039 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 36) Tj ET +endstream +endobj +1040 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 37) Tj ET +endstream +endobj +1041 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 38) Tj ET +endstream +endobj +1042 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 39) Tj ET +endstream +endobj +1043 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 40) Tj ET +endstream +endobj +1044 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 41) Tj ET +endstream +endobj +1045 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 42) Tj ET +endstream +endobj +1046 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 43) Tj ET +endstream +endobj +1047 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 44) Tj ET +endstream +endobj +1048 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 45) Tj ET +endstream +endobj +1049 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 46) Tj ET +endstream +endobj +1050 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 47) Tj ET +endstream +endobj +1051 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 48) Tj ET +endstream +endobj +1052 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 49) Tj ET +endstream +endobj +1053 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 50) Tj ET +endstream +endobj +1054 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 51) Tj ET +endstream +endobj +1055 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 52) Tj ET +endstream +endobj +1056 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 53) Tj ET +endstream +endobj +1057 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 54) Tj ET +endstream +endobj +1058 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 55) Tj ET +endstream +endobj +1059 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 56) Tj ET +endstream +endobj +1060 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 57) Tj ET +endstream +endobj +1061 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 58) Tj ET +endstream +endobj +1062 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 59) Tj ET +endstream +endobj +1063 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 60) Tj ET +endstream +endobj +1064 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 61) Tj ET +endstream +endobj +1065 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 62) Tj ET +endstream +endobj +1066 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 63) Tj ET +endstream +endobj +1067 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 64) Tj ET +endstream +endobj +1068 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 65) Tj ET +endstream +endobj +1069 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 66) Tj ET +endstream +endobj +1070 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 67) Tj ET +endstream +endobj +1071 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 68) Tj ET +endstream +endobj +1072 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 69) Tj ET +endstream +endobj +1073 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 70) Tj ET +endstream +endobj +1074 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 71) Tj ET +endstream +endobj +1075 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 72) Tj ET +endstream +endobj +1076 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 73) Tj ET +endstream +endobj +1077 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 74) Tj ET +endstream +endobj +1078 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 75) Tj ET +endstream +endobj +1079 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 76) Tj ET +endstream +endobj +1080 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 77) Tj ET +endstream +endobj +1081 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 78) Tj ET +endstream +endobj +1082 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 79) Tj ET +endstream +endobj +1083 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 80) Tj ET +endstream +endobj +1084 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 81) Tj ET +endstream +endobj +1085 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 82) Tj ET +endstream +endobj +1086 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 83) Tj ET +endstream +endobj +1087 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 84) Tj ET +endstream +endobj +1088 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 85) Tj ET +endstream +endobj +1089 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 86) Tj ET +endstream +endobj +1090 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 87) Tj ET +endstream +endobj +1091 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 88) Tj ET +endstream +endobj +1092 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 89) Tj ET +endstream +endobj +1093 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 90) Tj ET +endstream +endobj +1094 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 91) Tj ET +endstream +endobj +1095 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 92) Tj ET +endstream +endobj +1096 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 93) Tj ET +endstream +endobj +1097 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 94) Tj ET +endstream +endobj +1098 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 95) Tj ET +endstream +endobj +1099 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 96) Tj ET +endstream +endobj +1100 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 97) Tj ET +endstream +endobj +1101 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 98) Tj ET +endstream +endobj +1102 0 obj +<< /Length 40 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 99) Tj ET +endstream +endobj +1103 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 100) Tj ET +endstream +endobj +1104 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 101) Tj ET +endstream +endobj +1105 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 102) Tj ET +endstream +endobj +1106 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 103) Tj ET +endstream +endobj +1107 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 104) Tj ET +endstream +endobj +1108 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 105) Tj ET +endstream +endobj +1109 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 106) Tj ET +endstream +endobj +1110 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 107) Tj ET +endstream +endobj +1111 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 108) Tj ET +endstream +endobj +1112 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 109) Tj ET +endstream +endobj +1113 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 110) Tj ET +endstream +endobj +1114 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 111) Tj ET +endstream +endobj +1115 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 112) Tj ET +endstream +endobj +1116 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 113) Tj ET +endstream +endobj +1117 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 114) Tj ET +endstream +endobj +1118 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 115) Tj ET +endstream +endobj +1119 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 116) Tj ET +endstream +endobj +1120 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 117) Tj ET +endstream +endobj +1121 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 118) Tj ET +endstream +endobj +1122 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 119) Tj ET +endstream +endobj +1123 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 120) Tj ET +endstream +endobj +1124 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 121) Tj ET +endstream +endobj +1125 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 122) Tj ET +endstream +endobj +1126 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 123) Tj ET +endstream +endobj +1127 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 124) Tj ET +endstream +endobj +1128 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 125) Tj ET +endstream +endobj +1129 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 126) Tj ET +endstream +endobj +1130 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 127) Tj ET +endstream +endobj +1131 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 128) Tj ET +endstream +endobj +1132 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 129) Tj ET +endstream +endobj +1133 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 130) Tj ET +endstream +endobj +1134 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 131) Tj ET +endstream +endobj +1135 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 132) Tj ET +endstream +endobj +1136 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 133) Tj ET +endstream +endobj +1137 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 134) Tj ET +endstream +endobj +1138 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 135) Tj ET +endstream +endobj +1139 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 136) Tj ET +endstream +endobj +1140 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 137) Tj ET +endstream +endobj +1141 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 138) Tj ET +endstream +endobj +1142 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 139) Tj ET +endstream +endobj +1143 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 140) Tj ET +endstream +endobj +1144 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 141) Tj ET +endstream +endobj +1145 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 142) Tj ET +endstream +endobj +1146 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 143) Tj ET +endstream +endobj +1147 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 144) Tj ET +endstream +endobj +1148 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 145) Tj ET +endstream +endobj +1149 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 146) Tj ET +endstream +endobj +1150 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 147) Tj ET +endstream +endobj +1151 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 148) Tj ET +endstream +endobj +1152 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 149) Tj ET +endstream +endobj +1153 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 150) Tj ET +endstream +endobj +1154 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 151) Tj ET +endstream +endobj +1155 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 152) Tj ET +endstream +endobj +1156 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 153) Tj ET +endstream +endobj +1157 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 154) Tj ET +endstream +endobj +1158 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 155) Tj ET +endstream +endobj +1159 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 156) Tj ET +endstream +endobj +1160 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 157) Tj ET +endstream +endobj +1161 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 158) Tj ET +endstream +endobj +1162 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 159) Tj ET +endstream +endobj +1163 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 160) Tj ET +endstream +endobj +1164 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 161) Tj ET +endstream +endobj +1165 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 162) Tj ET +endstream +endobj +1166 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 163) Tj ET +endstream +endobj +1167 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 164) Tj ET +endstream +endobj +1168 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 165) Tj ET +endstream +endobj +1169 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 166) Tj ET +endstream +endobj +1170 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 167) Tj ET +endstream +endobj +1171 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 168) Tj ET +endstream +endobj +1172 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 169) Tj ET +endstream +endobj +1173 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 170) Tj ET +endstream +endobj +1174 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 171) Tj ET +endstream +endobj +1175 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 172) Tj ET +endstream +endobj +1176 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 173) Tj ET +endstream +endobj +1177 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 174) Tj ET +endstream +endobj +1178 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 175) Tj ET +endstream +endobj +1179 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 176) Tj ET +endstream +endobj +1180 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 177) Tj ET +endstream +endobj +1181 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 178) Tj ET +endstream +endobj +1182 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 179) Tj ET +endstream +endobj +1183 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 180) Tj ET +endstream +endobj +1184 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 181) Tj ET +endstream +endobj +1185 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 182) Tj ET +endstream +endobj +1186 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 183) Tj ET +endstream +endobj +1187 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 184) Tj ET +endstream +endobj +1188 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 185) Tj ET +endstream +endobj +1189 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 186) Tj ET +endstream +endobj +1190 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 187) Tj ET +endstream +endobj +1191 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 188) Tj ET +endstream +endobj +1192 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 189) Tj ET +endstream +endobj +1193 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 190) Tj ET +endstream +endobj +1194 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 191) Tj ET +endstream +endobj +1195 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 192) Tj ET +endstream +endobj +1196 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 193) Tj ET +endstream +endobj +1197 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 194) Tj ET +endstream +endobj +1198 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 195) Tj ET +endstream +endobj +1199 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 196) Tj ET +endstream +endobj +1200 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 197) Tj ET +endstream +endobj +1201 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 198) Tj ET +endstream +endobj +1202 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 199) Tj ET +endstream +endobj +1203 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 200) Tj ET +endstream +endobj +1204 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 201) Tj ET +endstream +endobj +1205 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 202) Tj ET +endstream +endobj +1206 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 203) Tj ET +endstream +endobj +1207 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 204) Tj ET +endstream +endobj +1208 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 205) Tj ET +endstream +endobj +1209 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 206) Tj ET +endstream +endobj +1210 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 207) Tj ET +endstream +endobj +1211 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 208) Tj ET +endstream +endobj +1212 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 209) Tj ET +endstream +endobj +1213 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 210) Tj ET +endstream +endobj +1214 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 211) Tj ET +endstream +endobj +1215 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 212) Tj ET +endstream +endobj +1216 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 213) Tj ET +endstream +endobj +1217 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 214) Tj ET +endstream +endobj +1218 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 215) Tj ET +endstream +endobj +1219 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 216) Tj ET +endstream +endobj +1220 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 217) Tj ET +endstream +endobj +1221 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 218) Tj ET +endstream +endobj +1222 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 219) Tj ET +endstream +endobj +1223 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 220) Tj ET +endstream +endobj +1224 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 221) Tj ET +endstream +endobj +1225 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 222) Tj ET +endstream +endobj +1226 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 223) Tj ET +endstream +endobj +1227 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 224) Tj ET +endstream +endobj +1228 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 225) Tj ET +endstream +endobj +1229 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 226) Tj ET +endstream +endobj +1230 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 227) Tj ET +endstream +endobj +1231 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 228) Tj ET +endstream +endobj +1232 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 229) Tj ET +endstream +endobj +1233 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 230) Tj ET +endstream +endobj +1234 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 231) Tj ET +endstream +endobj +1235 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 232) Tj ET +endstream +endobj +1236 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 233) Tj ET +endstream +endobj +1237 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 234) Tj ET +endstream +endobj +1238 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 235) Tj ET +endstream +endobj +1239 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 236) Tj ET +endstream +endobj +1240 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 237) Tj ET +endstream +endobj +1241 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 238) Tj ET +endstream +endobj +1242 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 239) Tj ET +endstream +endobj +1243 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 240) Tj ET +endstream +endobj +1244 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 241) Tj ET +endstream +endobj +1245 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 242) Tj ET +endstream +endobj +1246 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 243) Tj ET +endstream +endobj +1247 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 244) Tj ET +endstream +endobj +1248 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 245) Tj ET +endstream +endobj +1249 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 246) Tj ET +endstream +endobj +1250 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 247) Tj ET +endstream +endobj +1251 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 248) Tj ET +endstream +endobj +1252 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 249) Tj ET +endstream +endobj +1253 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 250) Tj ET +endstream +endobj +1254 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 251) Tj ET +endstream +endobj +1255 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 252) Tj ET +endstream +endobj +1256 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 253) Tj ET +endstream +endobj +1257 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 254) Tj ET +endstream +endobj +1258 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 255) Tj ET +endstream +endobj +1259 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 256) Tj ET +endstream +endobj +1260 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 257) Tj ET +endstream +endobj +1261 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 258) Tj ET +endstream +endobj +1262 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 259) Tj ET +endstream +endobj +1263 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 260) Tj ET +endstream +endobj +1264 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 261) Tj ET +endstream +endobj +1265 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 262) Tj ET +endstream +endobj +1266 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 263) Tj ET +endstream +endobj +1267 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 264) Tj ET +endstream +endobj +1268 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 265) Tj ET +endstream +endobj +1269 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 266) Tj ET +endstream +endobj +1270 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 267) Tj ET +endstream +endobj +1271 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 268) Tj ET +endstream +endobj +1272 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 269) Tj ET +endstream +endobj +1273 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 270) Tj ET +endstream +endobj +1274 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 271) Tj ET +endstream +endobj +1275 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 272) Tj ET +endstream +endobj +1276 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 273) Tj ET +endstream +endobj +1277 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 274) Tj ET +endstream +endobj +1278 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 275) Tj ET +endstream +endobj +1279 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 276) Tj ET +endstream +endobj +1280 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 277) Tj ET +endstream +endobj +1281 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 278) Tj ET +endstream +endobj +1282 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 279) Tj ET +endstream +endobj +1283 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 280) Tj ET +endstream +endobj +1284 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 281) Tj ET +endstream +endobj +1285 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 282) Tj ET +endstream +endobj +1286 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 283) Tj ET +endstream +endobj +1287 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 284) Tj ET +endstream +endobj +1288 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 285) Tj ET +endstream +endobj +1289 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 286) Tj ET +endstream +endobj +1290 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 287) Tj ET +endstream +endobj +1291 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 288) Tj ET +endstream +endobj +1292 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 289) Tj ET +endstream +endobj +1293 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 290) Tj ET +endstream +endobj +1294 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 291) Tj ET +endstream +endobj +1295 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 292) Tj ET +endstream +endobj +1296 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 293) Tj ET +endstream +endobj +1297 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 294) Tj ET +endstream +endobj +1298 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 295) Tj ET +endstream +endobj +1299 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 296) Tj ET +endstream +endobj +1300 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 297) Tj ET +endstream +endobj +1301 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 298) Tj ET +endstream +endobj +1302 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 299) Tj ET +endstream +endobj +1303 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 300) Tj ET +endstream +endobj +1304 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 301) Tj ET +endstream +endobj +1305 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 302) Tj ET +endstream +endobj +1306 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 303) Tj ET +endstream +endobj +1307 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 304) Tj ET +endstream +endobj +1308 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 305) Tj ET +endstream +endobj +1309 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 306) Tj ET +endstream +endobj +1310 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 307) Tj ET +endstream +endobj +1311 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 308) Tj ET +endstream +endobj +1312 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 309) Tj ET +endstream +endobj +1313 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 310) Tj ET +endstream +endobj +1314 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 311) Tj ET +endstream +endobj +1315 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 312) Tj ET +endstream +endobj +1316 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 313) Tj ET +endstream +endobj +1317 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 314) Tj ET +endstream +endobj +1318 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 315) Tj ET +endstream +endobj +1319 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 316) Tj ET +endstream +endobj +1320 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 317) Tj ET +endstream +endobj +1321 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 318) Tj ET +endstream +endobj +1322 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 319) Tj ET +endstream +endobj +1323 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 320) Tj ET +endstream +endobj +1324 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 321) Tj ET +endstream +endobj +1325 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 322) Tj ET +endstream +endobj +1326 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 323) Tj ET +endstream +endobj +1327 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 324) Tj ET +endstream +endobj +1328 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 325) Tj ET +endstream +endobj +1329 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 326) Tj ET +endstream +endobj +1330 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 327) Tj ET +endstream +endobj +1331 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 328) Tj ET +endstream +endobj +1332 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 329) Tj ET +endstream +endobj +1333 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 330) Tj ET +endstream +endobj +1334 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 331) Tj ET +endstream +endobj +1335 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 332) Tj ET +endstream +endobj +1336 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 333) Tj ET +endstream +endobj +1337 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 334) Tj ET +endstream +endobj +1338 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 335) Tj ET +endstream +endobj +1339 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 336) Tj ET +endstream +endobj +1340 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 337) Tj ET +endstream +endobj +1341 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 338) Tj ET +endstream +endobj +1342 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 339) Tj ET +endstream +endobj +1343 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 340) Tj ET +endstream +endobj +1344 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 341) Tj ET +endstream +endobj +1345 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 342) Tj ET +endstream +endobj +1346 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 343) Tj ET +endstream +endobj +1347 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 344) Tj ET +endstream +endobj +1348 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 345) Tj ET +endstream +endobj +1349 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 346) Tj ET +endstream +endobj +1350 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 347) Tj ET +endstream +endobj +1351 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 348) Tj ET +endstream +endobj +1352 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 349) Tj ET +endstream +endobj +1353 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 350) Tj ET +endstream +endobj +1354 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 351) Tj ET +endstream +endobj +1355 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 352) Tj ET +endstream +endobj +1356 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 353) Tj ET +endstream +endobj +1357 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 354) Tj ET +endstream +endobj +1358 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 355) Tj ET +endstream +endobj +1359 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 356) Tj ET +endstream +endobj +1360 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 357) Tj ET +endstream +endobj +1361 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 358) Tj ET +endstream +endobj +1362 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 359) Tj ET +endstream +endobj +1363 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 360) Tj ET +endstream +endobj +1364 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 361) Tj ET +endstream +endobj +1365 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 362) Tj ET +endstream +endobj +1366 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 363) Tj ET +endstream +endobj +1367 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 364) Tj ET +endstream +endobj +1368 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 365) Tj ET +endstream +endobj +1369 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 366) Tj ET +endstream +endobj +1370 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 367) Tj ET +endstream +endobj +1371 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 368) Tj ET +endstream +endobj +1372 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 369) Tj ET +endstream +endobj +1373 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 370) Tj ET +endstream +endobj +1374 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 371) Tj ET +endstream +endobj +1375 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 372) Tj ET +endstream +endobj +1376 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 373) Tj ET +endstream +endobj +1377 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 374) Tj ET +endstream +endobj +1378 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 375) Tj ET +endstream +endobj +1379 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 376) Tj ET +endstream +endobj +1380 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 377) Tj ET +endstream +endobj +1381 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 378) Tj ET +endstream +endobj +1382 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 379) Tj ET +endstream +endobj +1383 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 380) Tj ET +endstream +endobj +1384 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 381) Tj ET +endstream +endobj +1385 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 382) Tj ET +endstream +endobj +1386 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 383) Tj ET +endstream +endobj +1387 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 384) Tj ET +endstream +endobj +1388 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 385) Tj ET +endstream +endobj +1389 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 386) Tj ET +endstream +endobj +1390 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 387) Tj ET +endstream +endobj +1391 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 388) Tj ET +endstream +endobj +1392 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 389) Tj ET +endstream +endobj +1393 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 390) Tj ET +endstream +endobj +1394 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 391) Tj ET +endstream +endobj +1395 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 392) Tj ET +endstream +endobj +1396 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 393) Tj ET +endstream +endobj +1397 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 394) Tj ET +endstream +endobj +1398 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 395) Tj ET +endstream +endobj +1399 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 396) Tj ET +endstream +endobj +1400 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 397) Tj ET +endstream +endobj +1401 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 398) Tj ET +endstream +endobj +1402 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 399) Tj ET +endstream +endobj +1403 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 400) Tj ET +endstream +endobj +1404 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 401) Tj ET +endstream +endobj +1405 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 402) Tj ET +endstream +endobj +1406 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 403) Tj ET +endstream +endobj +1407 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 404) Tj ET +endstream +endobj +1408 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 405) Tj ET +endstream +endobj +1409 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 406) Tj ET +endstream +endobj +1410 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 407) Tj ET +endstream +endobj +1411 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 408) Tj ET +endstream +endobj +1412 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 409) Tj ET +endstream +endobj +1413 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 410) Tj ET +endstream +endobj +1414 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 411) Tj ET +endstream +endobj +1415 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 412) Tj ET +endstream +endobj +1416 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 413) Tj ET +endstream +endobj +1417 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 414) Tj ET +endstream +endobj +1418 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 415) Tj ET +endstream +endobj +1419 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 416) Tj ET +endstream +endobj +1420 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 417) Tj ET +endstream +endobj +1421 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 418) Tj ET +endstream +endobj +1422 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 419) Tj ET +endstream +endobj +1423 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 420) Tj ET +endstream +endobj +1424 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 421) Tj ET +endstream +endobj +1425 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 422) Tj ET +endstream +endobj +1426 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 423) Tj ET +endstream +endobj +1427 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 424) Tj ET +endstream +endobj +1428 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 425) Tj ET +endstream +endobj +1429 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 426) Tj ET +endstream +endobj +1430 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 427) Tj ET +endstream +endobj +1431 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 428) Tj ET +endstream +endobj +1432 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 429) Tj ET +endstream +endobj +1433 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 430) Tj ET +endstream +endobj +1434 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 431) Tj ET +endstream +endobj +1435 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 432) Tj ET +endstream +endobj +1436 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 433) Tj ET +endstream +endobj +1437 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 434) Tj ET +endstream +endobj +1438 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 435) Tj ET +endstream +endobj +1439 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 436) Tj ET +endstream +endobj +1440 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 437) Tj ET +endstream +endobj +1441 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 438) Tj ET +endstream +endobj +1442 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 439) Tj ET +endstream +endobj +1443 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 440) Tj ET +endstream +endobj +1444 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 441) Tj ET +endstream +endobj +1445 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 442) Tj ET +endstream +endobj +1446 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 443) Tj ET +endstream +endobj +1447 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 444) Tj ET +endstream +endobj +1448 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 445) Tj ET +endstream +endobj +1449 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 446) Tj ET +endstream +endobj +1450 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 447) Tj ET +endstream +endobj +1451 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 448) Tj ET +endstream +endobj +1452 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 449) Tj ET +endstream +endobj +1453 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 450) Tj ET +endstream +endobj +1454 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 451) Tj ET +endstream +endobj +1455 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 452) Tj ET +endstream +endobj +1456 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 453) Tj ET +endstream +endobj +1457 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 454) Tj ET +endstream +endobj +1458 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 455) Tj ET +endstream +endobj +1459 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 456) Tj ET +endstream +endobj +1460 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 457) Tj ET +endstream +endobj +1461 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 458) Tj ET +endstream +endobj +1462 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 459) Tj ET +endstream +endobj +1463 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 460) Tj ET +endstream +endobj +1464 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 461) Tj ET +endstream +endobj +1465 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 462) Tj ET +endstream +endobj +1466 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 463) Tj ET +endstream +endobj +1467 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 464) Tj ET +endstream +endobj +1468 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 465) Tj ET +endstream +endobj +1469 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 466) Tj ET +endstream +endobj +1470 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 467) Tj ET +endstream +endobj +1471 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 468) Tj ET +endstream +endobj +1472 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 469) Tj ET +endstream +endobj +1473 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 470) Tj ET +endstream +endobj +1474 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 471) Tj ET +endstream +endobj +1475 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 472) Tj ET +endstream +endobj +1476 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 473) Tj ET +endstream +endobj +1477 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 474) Tj ET +endstream +endobj +1478 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 475) Tj ET +endstream +endobj +1479 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 476) Tj ET +endstream +endobj +1480 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 477) Tj ET +endstream +endobj +1481 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 478) Tj ET +endstream +endobj +1482 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 479) Tj ET +endstream +endobj +1483 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 480) Tj ET +endstream +endobj +1484 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 481) Tj ET +endstream +endobj +1485 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 482) Tj ET +endstream +endobj +1486 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 483) Tj ET +endstream +endobj +1487 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 484) Tj ET +endstream +endobj +1488 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 485) Tj ET +endstream +endobj +1489 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 486) Tj ET +endstream +endobj +1490 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 487) Tj ET +endstream +endobj +1491 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 488) Tj ET +endstream +endobj +1492 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 489) Tj ET +endstream +endobj +1493 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 490) Tj ET +endstream +endobj +1494 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 491) Tj ET +endstream +endobj +1495 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 492) Tj ET +endstream +endobj +1496 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 493) Tj ET +endstream +endobj +1497 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 494) Tj ET +endstream +endobj +1498 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 495) Tj ET +endstream +endobj +1499 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 496) Tj ET +endstream +endobj +1500 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 497) Tj ET +endstream +endobj +1501 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 498) Tj ET +endstream +endobj +1502 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 499) Tj ET +endstream +endobj +1503 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 500) Tj ET +endstream +endobj +1504 0 obj +<< /Length 64 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 501) 0 -30 Td (ZZMARKER) Tj Tj ET +endstream +endobj +1505 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 502) Tj ET +endstream +endobj +1506 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 503) Tj ET +endstream +endobj +1507 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 504) Tj ET +endstream +endobj +1508 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 505) Tj ET +endstream +endobj +1509 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 506) Tj ET +endstream +endobj +1510 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 507) Tj ET +endstream +endobj +1511 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 508) Tj ET +endstream +endobj +1512 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 509) Tj ET +endstream +endobj +1513 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 510) Tj ET +endstream +endobj +1514 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 511) Tj ET +endstream +endobj +1515 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 512) Tj ET +endstream +endobj +1516 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 513) Tj ET +endstream +endobj +1517 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 514) Tj ET +endstream +endobj +1518 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 515) Tj ET +endstream +endobj +1519 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 516) Tj ET +endstream +endobj +1520 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 517) Tj ET +endstream +endobj +1521 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 518) Tj ET +endstream +endobj +1522 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 519) Tj ET +endstream +endobj +1523 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 520) Tj ET +endstream +endobj +1524 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 521) Tj ET +endstream +endobj +1525 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 522) Tj ET +endstream +endobj +1526 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 523) Tj ET +endstream +endobj +1527 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 524) Tj ET +endstream +endobj +1528 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 525) Tj ET +endstream +endobj +1529 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 526) Tj ET +endstream +endobj +1530 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 527) Tj ET +endstream +endobj +1531 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 528) Tj ET +endstream +endobj +1532 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 529) Tj ET +endstream +endobj +1533 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 530) Tj ET +endstream +endobj +1534 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 531) Tj ET +endstream +endobj +1535 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 532) Tj ET +endstream +endobj +1536 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 533) Tj ET +endstream +endobj +1537 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 534) Tj ET +endstream +endobj +1538 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 535) Tj ET +endstream +endobj +1539 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 536) Tj ET +endstream +endobj +1540 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 537) Tj ET +endstream +endobj +1541 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 538) Tj ET +endstream +endobj +1542 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 539) Tj ET +endstream +endobj +1543 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 540) Tj ET +endstream +endobj +1544 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 541) Tj ET +endstream +endobj +1545 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 542) Tj ET +endstream +endobj +1546 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 543) Tj ET +endstream +endobj +1547 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 544) Tj ET +endstream +endobj +1548 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 545) Tj ET +endstream +endobj +1549 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 546) Tj ET +endstream +endobj +1550 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 547) Tj ET +endstream +endobj +1551 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 548) Tj ET +endstream +endobj +1552 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 549) Tj ET +endstream +endobj +1553 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 550) Tj ET +endstream +endobj +1554 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 551) Tj ET +endstream +endobj +1555 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 552) Tj ET +endstream +endobj +1556 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 553) Tj ET +endstream +endobj +1557 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 554) Tj ET +endstream +endobj +1558 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 555) Tj ET +endstream +endobj +1559 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 556) Tj ET +endstream +endobj +1560 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 557) Tj ET +endstream +endobj +1561 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 558) Tj ET +endstream +endobj +1562 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 559) Tj ET +endstream +endobj +1563 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 560) Tj ET +endstream +endobj +1564 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 561) Tj ET +endstream +endobj +1565 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 562) Tj ET +endstream +endobj +1566 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 563) Tj ET +endstream +endobj +1567 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 564) Tj ET +endstream +endobj +1568 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 565) Tj ET +endstream +endobj +1569 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 566) Tj ET +endstream +endobj +1570 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 567) Tj ET +endstream +endobj +1571 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 568) Tj ET +endstream +endobj +1572 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 569) Tj ET +endstream +endobj +1573 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 570) Tj ET +endstream +endobj +1574 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 571) Tj ET +endstream +endobj +1575 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 572) Tj ET +endstream +endobj +1576 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 573) Tj ET +endstream +endobj +1577 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 574) Tj ET +endstream +endobj +1578 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 575) Tj ET +endstream +endobj +1579 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 576) Tj ET +endstream +endobj +1580 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 577) Tj ET +endstream +endobj +1581 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 578) Tj ET +endstream +endobj +1582 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 579) Tj ET +endstream +endobj +1583 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 580) Tj ET +endstream +endobj +1584 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 581) Tj ET +endstream +endobj +1585 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 582) Tj ET +endstream +endobj +1586 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 583) Tj ET +endstream +endobj +1587 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 584) Tj ET +endstream +endobj +1588 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 585) Tj ET +endstream +endobj +1589 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 586) Tj ET +endstream +endobj +1590 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 587) Tj ET +endstream +endobj +1591 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 588) Tj ET +endstream +endobj +1592 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 589) Tj ET +endstream +endobj +1593 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 590) Tj ET +endstream +endobj +1594 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 591) Tj ET +endstream +endobj +1595 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 592) Tj ET +endstream +endobj +1596 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 593) Tj ET +endstream +endobj +1597 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 594) Tj ET +endstream +endobj +1598 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 595) Tj ET +endstream +endobj +1599 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 596) Tj ET +endstream +endobj +1600 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 597) Tj ET +endstream +endobj +1601 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 598) Tj ET +endstream +endobj +1602 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 599) Tj ET +endstream +endobj +1603 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 600) Tj ET +endstream +endobj +1604 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 601) Tj ET +endstream +endobj +1605 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 602) Tj ET +endstream +endobj +1606 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 603) Tj ET +endstream +endobj +1607 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 604) Tj ET +endstream +endobj +1608 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 605) Tj ET +endstream +endobj +1609 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 606) Tj ET +endstream +endobj +1610 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 607) Tj ET +endstream +endobj +1611 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 608) Tj ET +endstream +endobj +1612 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 609) Tj ET +endstream +endobj +1613 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 610) Tj ET +endstream +endobj +1614 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 611) Tj ET +endstream +endobj +1615 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 612) Tj ET +endstream +endobj +1616 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 613) Tj ET +endstream +endobj +1617 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 614) Tj ET +endstream +endobj +1618 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 615) Tj ET +endstream +endobj +1619 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 616) Tj ET +endstream +endobj +1620 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 617) Tj ET +endstream +endobj +1621 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 618) Tj ET +endstream +endobj +1622 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 619) Tj ET +endstream +endobj +1623 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 620) Tj ET +endstream +endobj +1624 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 621) Tj ET +endstream +endobj +1625 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 622) Tj ET +endstream +endobj +1626 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 623) Tj ET +endstream +endobj +1627 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 624) Tj ET +endstream +endobj +1628 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 625) Tj ET +endstream +endobj +1629 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 626) Tj ET +endstream +endobj +1630 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 627) Tj ET +endstream +endobj +1631 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 628) Tj ET +endstream +endobj +1632 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 629) Tj ET +endstream +endobj +1633 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 630) Tj ET +endstream +endobj +1634 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 631) Tj ET +endstream +endobj +1635 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 632) Tj ET +endstream +endobj +1636 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 633) Tj ET +endstream +endobj +1637 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 634) Tj ET +endstream +endobj +1638 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 635) Tj ET +endstream +endobj +1639 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 636) Tj ET +endstream +endobj +1640 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 637) Tj ET +endstream +endobj +1641 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 638) Tj ET +endstream +endobj +1642 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 639) Tj ET +endstream +endobj +1643 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 640) Tj ET +endstream +endobj +1644 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 641) Tj ET +endstream +endobj +1645 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 642) Tj ET +endstream +endobj +1646 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 643) Tj ET +endstream +endobj +1647 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 644) Tj ET +endstream +endobj +1648 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 645) Tj ET +endstream +endobj +1649 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 646) Tj ET +endstream +endobj +1650 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 647) Tj ET +endstream +endobj +1651 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 648) Tj ET +endstream +endobj +1652 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 649) Tj ET +endstream +endobj +1653 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 650) Tj ET +endstream +endobj +1654 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 651) Tj ET +endstream +endobj +1655 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 652) Tj ET +endstream +endobj +1656 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 653) Tj ET +endstream +endobj +1657 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 654) Tj ET +endstream +endobj +1658 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 655) Tj ET +endstream +endobj +1659 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 656) Tj ET +endstream +endobj +1660 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 657) Tj ET +endstream +endobj +1661 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 658) Tj ET +endstream +endobj +1662 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 659) Tj ET +endstream +endobj +1663 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 660) Tj ET +endstream +endobj +1664 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 661) Tj ET +endstream +endobj +1665 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 662) Tj ET +endstream +endobj +1666 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 663) Tj ET +endstream +endobj +1667 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 664) Tj ET +endstream +endobj +1668 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 665) Tj ET +endstream +endobj +1669 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 666) Tj ET +endstream +endobj +1670 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 667) Tj ET +endstream +endobj +1671 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 668) Tj ET +endstream +endobj +1672 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 669) Tj ET +endstream +endobj +1673 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 670) Tj ET +endstream +endobj +1674 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 671) Tj ET +endstream +endobj +1675 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 672) Tj ET +endstream +endobj +1676 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 673) Tj ET +endstream +endobj +1677 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 674) Tj ET +endstream +endobj +1678 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 675) Tj ET +endstream +endobj +1679 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 676) Tj ET +endstream +endobj +1680 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 677) Tj ET +endstream +endobj +1681 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 678) Tj ET +endstream +endobj +1682 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 679) Tj ET +endstream +endobj +1683 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 680) Tj ET +endstream +endobj +1684 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 681) Tj ET +endstream +endobj +1685 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 682) Tj ET +endstream +endobj +1686 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 683) Tj ET +endstream +endobj +1687 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 684) Tj ET +endstream +endobj +1688 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 685) Tj ET +endstream +endobj +1689 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 686) Tj ET +endstream +endobj +1690 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 687) Tj ET +endstream +endobj +1691 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 688) Tj ET +endstream +endobj +1692 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 689) Tj ET +endstream +endobj +1693 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 690) Tj ET +endstream +endobj +1694 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 691) Tj ET +endstream +endobj +1695 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 692) Tj ET +endstream +endobj +1696 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 693) Tj ET +endstream +endobj +1697 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 694) Tj ET +endstream +endobj +1698 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 695) Tj ET +endstream +endobj +1699 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 696) Tj ET +endstream +endobj +1700 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 697) Tj ET +endstream +endobj +1701 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 698) Tj ET +endstream +endobj +1702 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 699) Tj ET +endstream +endobj +1703 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 700) Tj ET +endstream +endobj +1704 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 701) Tj ET +endstream +endobj +1705 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 702) Tj ET +endstream +endobj +1706 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 703) Tj ET +endstream +endobj +1707 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 704) Tj ET +endstream +endobj +1708 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 705) Tj ET +endstream +endobj +1709 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 706) Tj ET +endstream +endobj +1710 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 707) Tj ET +endstream +endobj +1711 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 708) Tj ET +endstream +endobj +1712 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 709) Tj ET +endstream +endobj +1713 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 710) Tj ET +endstream +endobj +1714 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 711) Tj ET +endstream +endobj +1715 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 712) Tj ET +endstream +endobj +1716 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 713) Tj ET +endstream +endobj +1717 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 714) Tj ET +endstream +endobj +1718 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 715) Tj ET +endstream +endobj +1719 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 716) Tj ET +endstream +endobj +1720 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 717) Tj ET +endstream +endobj +1721 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 718) Tj ET +endstream +endobj +1722 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 719) Tj ET +endstream +endobj +1723 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 720) Tj ET +endstream +endobj +1724 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 721) Tj ET +endstream +endobj +1725 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 722) Tj ET +endstream +endobj +1726 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 723) Tj ET +endstream +endobj +1727 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 724) Tj ET +endstream +endobj +1728 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 725) Tj ET +endstream +endobj +1729 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 726) Tj ET +endstream +endobj +1730 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 727) Tj ET +endstream +endobj +1731 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 728) Tj ET +endstream +endobj +1732 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 729) Tj ET +endstream +endobj +1733 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 730) Tj ET +endstream +endobj +1734 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 731) Tj ET +endstream +endobj +1735 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 732) Tj ET +endstream +endobj +1736 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 733) Tj ET +endstream +endobj +1737 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 734) Tj ET +endstream +endobj +1738 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 735) Tj ET +endstream +endobj +1739 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 736) Tj ET +endstream +endobj +1740 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 737) Tj ET +endstream +endobj +1741 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 738) Tj ET +endstream +endobj +1742 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 739) Tj ET +endstream +endobj +1743 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 740) Tj ET +endstream +endobj +1744 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 741) Tj ET +endstream +endobj +1745 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 742) Tj ET +endstream +endobj +1746 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 743) Tj ET +endstream +endobj +1747 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 744) Tj ET +endstream +endobj +1748 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 745) Tj ET +endstream +endobj +1749 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 746) Tj ET +endstream +endobj +1750 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 747) Tj ET +endstream +endobj +1751 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 748) Tj ET +endstream +endobj +1752 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 749) Tj ET +endstream +endobj +1753 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 750) Tj ET +endstream +endobj +1754 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 751) Tj ET +endstream +endobj +1755 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 752) Tj ET +endstream +endobj +1756 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 753) Tj ET +endstream +endobj +1757 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 754) Tj ET +endstream +endobj +1758 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 755) Tj ET +endstream +endobj +1759 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 756) Tj ET +endstream +endobj +1760 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 757) Tj ET +endstream +endobj +1761 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 758) Tj ET +endstream +endobj +1762 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 759) Tj ET +endstream +endobj +1763 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 760) Tj ET +endstream +endobj +1764 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 761) Tj ET +endstream +endobj +1765 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 762) Tj ET +endstream +endobj +1766 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 763) Tj ET +endstream +endobj +1767 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 764) Tj ET +endstream +endobj +1768 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 765) Tj ET +endstream +endobj +1769 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 766) Tj ET +endstream +endobj +1770 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 767) Tj ET +endstream +endobj +1771 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 768) Tj ET +endstream +endobj +1772 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 769) Tj ET +endstream +endobj +1773 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 770) Tj ET +endstream +endobj +1774 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 771) Tj ET +endstream +endobj +1775 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 772) Tj ET +endstream +endobj +1776 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 773) Tj ET +endstream +endobj +1777 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 774) Tj ET +endstream +endobj +1778 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 775) Tj ET +endstream +endobj +1779 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 776) Tj ET +endstream +endobj +1780 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 777) Tj ET +endstream +endobj +1781 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 778) Tj ET +endstream +endobj +1782 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 779) Tj ET +endstream +endobj +1783 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 780) Tj ET +endstream +endobj +1784 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 781) Tj ET +endstream +endobj +1785 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 782) Tj ET +endstream +endobj +1786 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 783) Tj ET +endstream +endobj +1787 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 784) Tj ET +endstream +endobj +1788 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 785) Tj ET +endstream +endobj +1789 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 786) Tj ET +endstream +endobj +1790 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 787) Tj ET +endstream +endobj +1791 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 788) Tj ET +endstream +endobj +1792 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 789) Tj ET +endstream +endobj +1793 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 790) Tj ET +endstream +endobj +1794 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 791) Tj ET +endstream +endobj +1795 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 792) Tj ET +endstream +endobj +1796 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 793) Tj ET +endstream +endobj +1797 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 794) Tj ET +endstream +endobj +1798 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 795) Tj ET +endstream +endobj +1799 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 796) Tj ET +endstream +endobj +1800 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 797) Tj ET +endstream +endobj +1801 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 798) Tj ET +endstream +endobj +1802 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 799) Tj ET +endstream +endobj +1803 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 800) Tj ET +endstream +endobj +1804 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 801) Tj ET +endstream +endobj +1805 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 802) Tj ET +endstream +endobj +1806 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 803) Tj ET +endstream +endobj +1807 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 804) Tj ET +endstream +endobj +1808 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 805) Tj ET +endstream +endobj +1809 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 806) Tj ET +endstream +endobj +1810 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 807) Tj ET +endstream +endobj +1811 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 808) Tj ET +endstream +endobj +1812 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 809) Tj ET +endstream +endobj +1813 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 810) Tj ET +endstream +endobj +1814 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 811) Tj ET +endstream +endobj +1815 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 812) Tj ET +endstream +endobj +1816 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 813) Tj ET +endstream +endobj +1817 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 814) Tj ET +endstream +endobj +1818 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 815) Tj ET +endstream +endobj +1819 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 816) Tj ET +endstream +endobj +1820 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 817) Tj ET +endstream +endobj +1821 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 818) Tj ET +endstream +endobj +1822 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 819) Tj ET +endstream +endobj +1823 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 820) Tj ET +endstream +endobj +1824 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 821) Tj ET +endstream +endobj +1825 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 822) Tj ET +endstream +endobj +1826 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 823) Tj ET +endstream +endobj +1827 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 824) Tj ET +endstream +endobj +1828 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 825) Tj ET +endstream +endobj +1829 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 826) Tj ET +endstream +endobj +1830 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 827) Tj ET +endstream +endobj +1831 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 828) Tj ET +endstream +endobj +1832 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 829) Tj ET +endstream +endobj +1833 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 830) Tj ET +endstream +endobj +1834 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 831) Tj ET +endstream +endobj +1835 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 832) Tj ET +endstream +endobj +1836 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 833) Tj ET +endstream +endobj +1837 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 834) Tj ET +endstream +endobj +1838 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 835) Tj ET +endstream +endobj +1839 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 836) Tj ET +endstream +endobj +1840 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 837) Tj ET +endstream +endobj +1841 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 838) Tj ET +endstream +endobj +1842 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 839) Tj ET +endstream +endobj +1843 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 840) Tj ET +endstream +endobj +1844 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 841) Tj ET +endstream +endobj +1845 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 842) Tj ET +endstream +endobj +1846 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 843) Tj ET +endstream +endobj +1847 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 844) Tj ET +endstream +endobj +1848 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 845) Tj ET +endstream +endobj +1849 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 846) Tj ET +endstream +endobj +1850 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 847) Tj ET +endstream +endobj +1851 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 848) Tj ET +endstream +endobj +1852 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 849) Tj ET +endstream +endobj +1853 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 850) Tj ET +endstream +endobj +1854 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 851) Tj ET +endstream +endobj +1855 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 852) Tj ET +endstream +endobj +1856 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 853) Tj ET +endstream +endobj +1857 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 854) Tj ET +endstream +endobj +1858 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 855) Tj ET +endstream +endobj +1859 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 856) Tj ET +endstream +endobj +1860 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 857) Tj ET +endstream +endobj +1861 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 858) Tj ET +endstream +endobj +1862 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 859) Tj ET +endstream +endobj +1863 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 860) Tj ET +endstream +endobj +1864 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 861) Tj ET +endstream +endobj +1865 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 862) Tj ET +endstream +endobj +1866 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 863) Tj ET +endstream +endobj +1867 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 864) Tj ET +endstream +endobj +1868 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 865) Tj ET +endstream +endobj +1869 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 866) Tj ET +endstream +endobj +1870 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 867) Tj ET +endstream +endobj +1871 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 868) Tj ET +endstream +endobj +1872 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 869) Tj ET +endstream +endobj +1873 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 870) Tj ET +endstream +endobj +1874 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 871) Tj ET +endstream +endobj +1875 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 872) Tj ET +endstream +endobj +1876 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 873) Tj ET +endstream +endobj +1877 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 874) Tj ET +endstream +endobj +1878 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 875) Tj ET +endstream +endobj +1879 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 876) Tj ET +endstream +endobj +1880 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 877) Tj ET +endstream +endobj +1881 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 878) Tj ET +endstream +endobj +1882 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 879) Tj ET +endstream +endobj +1883 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 880) Tj ET +endstream +endobj +1884 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 881) Tj ET +endstream +endobj +1885 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 882) Tj ET +endstream +endobj +1886 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 883) Tj ET +endstream +endobj +1887 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 884) Tj ET +endstream +endobj +1888 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 885) Tj ET +endstream +endobj +1889 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 886) Tj ET +endstream +endobj +1890 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 887) Tj ET +endstream +endobj +1891 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 888) Tj ET +endstream +endobj +1892 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 889) Tj ET +endstream +endobj +1893 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 890) Tj ET +endstream +endobj +1894 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 891) Tj ET +endstream +endobj +1895 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 892) Tj ET +endstream +endobj +1896 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 893) Tj ET +endstream +endobj +1897 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 894) Tj ET +endstream +endobj +1898 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 895) Tj ET +endstream +endobj +1899 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 896) Tj ET +endstream +endobj +1900 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 897) Tj ET +endstream +endobj +1901 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 898) Tj ET +endstream +endobj +1902 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 899) Tj ET +endstream +endobj +1903 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 900) Tj ET +endstream +endobj +1904 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 901) Tj ET +endstream +endobj +1905 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 902) Tj ET +endstream +endobj +1906 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 903) Tj ET +endstream +endobj +1907 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 904) Tj ET +endstream +endobj +1908 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 905) Tj ET +endstream +endobj +1909 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 906) Tj ET +endstream +endobj +1910 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 907) Tj ET +endstream +endobj +1911 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 908) Tj ET +endstream +endobj +1912 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 909) Tj ET +endstream +endobj +1913 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 910) Tj ET +endstream +endobj +1914 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 911) Tj ET +endstream +endobj +1915 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 912) Tj ET +endstream +endobj +1916 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 913) Tj ET +endstream +endobj +1917 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 914) Tj ET +endstream +endobj +1918 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 915) Tj ET +endstream +endobj +1919 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 916) Tj ET +endstream +endobj +1920 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 917) Tj ET +endstream +endobj +1921 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 918) Tj ET +endstream +endobj +1922 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 919) Tj ET +endstream +endobj +1923 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 920) Tj ET +endstream +endobj +1924 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 921) Tj ET +endstream +endobj +1925 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 922) Tj ET +endstream +endobj +1926 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 923) Tj ET +endstream +endobj +1927 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 924) Tj ET +endstream +endobj +1928 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 925) Tj ET +endstream +endobj +1929 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 926) Tj ET +endstream +endobj +1930 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 927) Tj ET +endstream +endobj +1931 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 928) Tj ET +endstream +endobj +1932 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 929) Tj ET +endstream +endobj +1933 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 930) Tj ET +endstream +endobj +1934 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 931) Tj ET +endstream +endobj +1935 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 932) Tj ET +endstream +endobj +1936 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 933) Tj ET +endstream +endobj +1937 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 934) Tj ET +endstream +endobj +1938 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 935) Tj ET +endstream +endobj +1939 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 936) Tj ET +endstream +endobj +1940 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 937) Tj ET +endstream +endobj +1941 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 938) Tj ET +endstream +endobj +1942 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 939) Tj ET +endstream +endobj +1943 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 940) Tj ET +endstream +endobj +1944 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 941) Tj ET +endstream +endobj +1945 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 942) Tj ET +endstream +endobj +1946 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 943) Tj ET +endstream +endobj +1947 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 944) Tj ET +endstream +endobj +1948 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 945) Tj ET +endstream +endobj +1949 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 946) Tj ET +endstream +endobj +1950 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 947) Tj ET +endstream +endobj +1951 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 948) Tj ET +endstream +endobj +1952 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 949) Tj ET +endstream +endobj +1953 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 950) Tj ET +endstream +endobj +1954 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 951) Tj ET +endstream +endobj +1955 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 952) Tj ET +endstream +endobj +1956 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 953) Tj ET +endstream +endobj +1957 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 954) Tj ET +endstream +endobj +1958 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 955) Tj ET +endstream +endobj +1959 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 956) Tj ET +endstream +endobj +1960 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 957) Tj ET +endstream +endobj +1961 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 958) Tj ET +endstream +endobj +1962 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 959) Tj ET +endstream +endobj +1963 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 960) Tj ET +endstream +endobj +1964 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 961) Tj ET +endstream +endobj +1965 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 962) Tj ET +endstream +endobj +1966 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 963) Tj ET +endstream +endobj +1967 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 964) Tj ET +endstream +endobj +1968 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 965) Tj ET +endstream +endobj +1969 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 966) Tj ET +endstream +endobj +1970 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 967) Tj ET +endstream +endobj +1971 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 968) Tj ET +endstream +endobj +1972 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 969) Tj ET +endstream +endobj +1973 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 970) Tj ET +endstream +endobj +1974 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 971) Tj ET +endstream +endobj +1975 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 972) Tj ET +endstream +endobj +1976 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 973) Tj ET +endstream +endobj +1977 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 974) Tj ET +endstream +endobj +1978 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 975) Tj ET +endstream +endobj +1979 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 976) Tj ET +endstream +endobj +1980 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 977) Tj ET +endstream +endobj +1981 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 978) Tj ET +endstream +endobj +1982 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 979) Tj ET +endstream +endobj +1983 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 980) Tj ET +endstream +endobj +1984 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 981) Tj ET +endstream +endobj +1985 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 982) Tj ET +endstream +endobj +1986 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 983) Tj ET +endstream +endobj +1987 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 984) Tj ET +endstream +endobj +1988 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 985) Tj ET +endstream +endobj +1989 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 986) Tj ET +endstream +endobj +1990 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 987) Tj ET +endstream +endobj +1991 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 988) Tj ET +endstream +endobj +1992 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 989) Tj ET +endstream +endobj +1993 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 990) Tj ET +endstream +endobj +1994 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 991) Tj ET +endstream +endobj +1995 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 992) Tj ET +endstream +endobj +1996 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 993) Tj ET +endstream +endobj +1997 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 994) Tj ET +endstream +endobj +1998 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 995) Tj ET +endstream +endobj +1999 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 996) Tj ET +endstream +endobj +2000 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 997) Tj ET +endstream +endobj +2001 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 998) Tj ET +endstream +endobj +2002 0 obj +<< /Length 41 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 999) Tj ET +endstream +endobj +2003 0 obj +<< /Length 42 >> +stream +BT /F1 24 Tf 72 700 Td (Trang 1000) Tj ET +endstream +endobj +xref +0 2004 65535 f +0000000009 00000 n +0000000058 00000 n +0000008014 00000 n +0000008084 00000 n +0000008213 00000 n +0000008342 00000 n +0000008471 00000 n +0000008600 00000 n +0000008729 00000 n +0000008858 00000 n +0000008988 00000 n +0000009118 00000 n +0000009248 00000 n +0000009378 00000 n +0000009508 00000 n +0000009638 00000 n +0000009768 00000 n +0000009898 00000 n +0000010028 00000 n +0000010158 00000 n +0000010288 00000 n +0000010418 00000 n +0000010548 00000 n +0000010678 00000 n +0000010808 00000 n +0000010938 00000 n +0000011068 00000 n +0000011198 00000 n +0000011328 00000 n +0000011458 00000 n +0000011588 00000 n +0000011718 00000 n +0000011848 00000 n +0000011978 00000 n +0000012108 00000 n +0000012238 00000 n +0000012368 00000 n +0000012498 00000 n +0000012628 00000 n +0000012758 00000 n +0000012888 00000 n +0000013018 00000 n +0000013148 00000 n +0000013278 00000 n +0000013408 00000 n +0000013538 00000 n +0000013668 00000 n +0000013798 00000 n +0000013928 00000 n +0000014058 00000 n +0000014188 00000 n +0000014318 00000 n +0000014448 00000 n +0000014578 00000 n +0000014708 00000 n +0000014838 00000 n +0000014968 00000 n +0000015098 00000 n +0000015228 00000 n +0000015358 00000 n +0000015488 00000 n +0000015618 00000 n +0000015748 00000 n +0000015878 00000 n +0000016008 00000 n +0000016138 00000 n +0000016268 00000 n +0000016398 00000 n +0000016528 00000 n +0000016658 00000 n +0000016788 00000 n +0000016918 00000 n +0000017048 00000 n +0000017178 00000 n +0000017308 00000 n +0000017438 00000 n +0000017568 00000 n +0000017698 00000 n +0000017828 00000 n +0000017958 00000 n +0000018088 00000 n +0000018218 00000 n +0000018348 00000 n +0000018478 00000 n +0000018608 00000 n +0000018738 00000 n +0000018868 00000 n +0000018998 00000 n +0000019128 00000 n +0000019258 00000 n +0000019388 00000 n +0000019518 00000 n +0000019648 00000 n +0000019778 00000 n +0000019908 00000 n +0000020038 00000 n +0000020168 00000 n +0000020298 00000 n +0000020428 00000 n +0000020558 00000 n +0000020689 00000 n +0000020820 00000 n +0000020951 00000 n +0000021082 00000 n +0000021213 00000 n +0000021344 00000 n +0000021475 00000 n +0000021606 00000 n +0000021737 00000 n +0000021868 00000 n +0000021999 00000 n +0000022130 00000 n +0000022261 00000 n +0000022392 00000 n +0000022523 00000 n +0000022654 00000 n +0000022785 00000 n +0000022916 00000 n +0000023047 00000 n +0000023178 00000 n +0000023309 00000 n +0000023440 00000 n +0000023571 00000 n +0000023702 00000 n +0000023833 00000 n +0000023964 00000 n +0000024095 00000 n +0000024226 00000 n +0000024357 00000 n +0000024488 00000 n +0000024619 00000 n +0000024750 00000 n +0000024881 00000 n +0000025012 00000 n +0000025143 00000 n +0000025274 00000 n +0000025405 00000 n +0000025536 00000 n +0000025667 00000 n +0000025798 00000 n +0000025929 00000 n +0000026060 00000 n +0000026191 00000 n +0000026322 00000 n +0000026453 00000 n +0000026584 00000 n +0000026715 00000 n +0000026846 00000 n +0000026977 00000 n +0000027108 00000 n +0000027239 00000 n +0000027370 00000 n +0000027501 00000 n +0000027632 00000 n +0000027763 00000 n +0000027894 00000 n +0000028025 00000 n +0000028156 00000 n +0000028287 00000 n +0000028418 00000 n +0000028549 00000 n +0000028680 00000 n +0000028811 00000 n +0000028942 00000 n +0000029073 00000 n +0000029204 00000 n +0000029335 00000 n +0000029466 00000 n +0000029597 00000 n +0000029728 00000 n +0000029859 00000 n +0000029990 00000 n +0000030121 00000 n +0000030252 00000 n +0000030383 00000 n +0000030514 00000 n +0000030645 00000 n +0000030776 00000 n +0000030907 00000 n +0000031038 00000 n +0000031169 00000 n +0000031300 00000 n +0000031431 00000 n +0000031562 00000 n +0000031693 00000 n +0000031824 00000 n +0000031955 00000 n +0000032086 00000 n +0000032217 00000 n +0000032348 00000 n +0000032479 00000 n +0000032610 00000 n +0000032741 00000 n +0000032872 00000 n +0000033003 00000 n +0000033134 00000 n +0000033265 00000 n +0000033396 00000 n +0000033527 00000 n +0000033658 00000 n +0000033789 00000 n +0000033920 00000 n +0000034051 00000 n +0000034182 00000 n +0000034313 00000 n +0000034444 00000 n +0000034575 00000 n +0000034706 00000 n +0000034837 00000 n +0000034968 00000 n +0000035099 00000 n +0000035230 00000 n +0000035361 00000 n +0000035492 00000 n +0000035623 00000 n +0000035754 00000 n +0000035885 00000 n +0000036016 00000 n +0000036147 00000 n +0000036278 00000 n +0000036409 00000 n +0000036540 00000 n +0000036671 00000 n +0000036802 00000 n +0000036933 00000 n +0000037064 00000 n +0000037195 00000 n +0000037326 00000 n +0000037457 00000 n +0000037588 00000 n +0000037719 00000 n +0000037850 00000 n +0000037981 00000 n +0000038112 00000 n +0000038243 00000 n +0000038374 00000 n +0000038505 00000 n +0000038636 00000 n +0000038767 00000 n +0000038898 00000 n +0000039029 00000 n +0000039160 00000 n +0000039291 00000 n +0000039422 00000 n +0000039553 00000 n +0000039684 00000 n +0000039815 00000 n +0000039946 00000 n +0000040077 00000 n +0000040208 00000 n +0000040339 00000 n +0000040470 00000 n +0000040601 00000 n +0000040732 00000 n +0000040863 00000 n +0000040994 00000 n +0000041125 00000 n +0000041256 00000 n +0000041387 00000 n +0000041518 00000 n +0000041649 00000 n +0000041780 00000 n +0000041911 00000 n +0000042042 00000 n +0000042173 00000 n +0000042304 00000 n +0000042435 00000 n +0000042566 00000 n +0000042697 00000 n +0000042828 00000 n +0000042959 00000 n +0000043090 00000 n +0000043221 00000 n +0000043352 00000 n +0000043483 00000 n +0000043614 00000 n +0000043745 00000 n +0000043876 00000 n +0000044007 00000 n +0000044138 00000 n +0000044269 00000 n +0000044400 00000 n +0000044531 00000 n +0000044662 00000 n +0000044793 00000 n +0000044924 00000 n +0000045055 00000 n +0000045186 00000 n +0000045317 00000 n +0000045448 00000 n +0000045579 00000 n +0000045710 00000 n +0000045841 00000 n +0000045972 00000 n +0000046103 00000 n +0000046234 00000 n +0000046365 00000 n +0000046496 00000 n +0000046627 00000 n +0000046758 00000 n +0000046889 00000 n +0000047020 00000 n +0000047151 00000 n +0000047282 00000 n +0000047413 00000 n +0000047544 00000 n +0000047675 00000 n +0000047806 00000 n +0000047937 00000 n +0000048068 00000 n +0000048199 00000 n +0000048330 00000 n +0000048461 00000 n +0000048592 00000 n +0000048723 00000 n +0000048854 00000 n +0000048985 00000 n +0000049116 00000 n +0000049247 00000 n +0000049378 00000 n +0000049509 00000 n +0000049640 00000 n +0000049771 00000 n +0000049902 00000 n +0000050033 00000 n +0000050164 00000 n +0000050295 00000 n +0000050426 00000 n +0000050557 00000 n +0000050688 00000 n +0000050819 00000 n +0000050950 00000 n +0000051081 00000 n +0000051212 00000 n +0000051343 00000 n +0000051474 00000 n +0000051605 00000 n +0000051736 00000 n +0000051867 00000 n +0000051998 00000 n +0000052129 00000 n +0000052260 00000 n +0000052391 00000 n +0000052522 00000 n +0000052653 00000 n +0000052784 00000 n +0000052915 00000 n +0000053046 00000 n +0000053177 00000 n +0000053308 00000 n +0000053439 00000 n +0000053570 00000 n +0000053701 00000 n +0000053832 00000 n +0000053963 00000 n +0000054094 00000 n +0000054225 00000 n +0000054356 00000 n +0000054487 00000 n +0000054618 00000 n +0000054749 00000 n +0000054880 00000 n +0000055011 00000 n +0000055142 00000 n +0000055273 00000 n +0000055404 00000 n +0000055535 00000 n +0000055666 00000 n +0000055797 00000 n +0000055928 00000 n +0000056059 00000 n +0000056190 00000 n +0000056321 00000 n +0000056452 00000 n +0000056583 00000 n +0000056714 00000 n +0000056845 00000 n +0000056976 00000 n +0000057107 00000 n +0000057238 00000 n +0000057369 00000 n +0000057500 00000 n +0000057631 00000 n +0000057762 00000 n +0000057893 00000 n +0000058024 00000 n +0000058155 00000 n +0000058286 00000 n +0000058417 00000 n +0000058548 00000 n +0000058679 00000 n +0000058810 00000 n +0000058941 00000 n +0000059072 00000 n +0000059203 00000 n +0000059334 00000 n +0000059465 00000 n +0000059596 00000 n +0000059727 00000 n +0000059858 00000 n +0000059989 00000 n +0000060120 00000 n +0000060251 00000 n +0000060382 00000 n +0000060513 00000 n +0000060644 00000 n +0000060775 00000 n +0000060906 00000 n +0000061037 00000 n +0000061168 00000 n +0000061299 00000 n +0000061430 00000 n +0000061561 00000 n +0000061692 00000 n +0000061823 00000 n +0000061954 00000 n +0000062085 00000 n +0000062216 00000 n +0000062347 00000 n +0000062478 00000 n +0000062609 00000 n +0000062740 00000 n +0000062871 00000 n +0000063002 00000 n +0000063133 00000 n +0000063264 00000 n +0000063395 00000 n +0000063526 00000 n +0000063657 00000 n +0000063788 00000 n +0000063919 00000 n +0000064050 00000 n +0000064181 00000 n +0000064312 00000 n +0000064443 00000 n +0000064574 00000 n +0000064705 00000 n +0000064836 00000 n +0000064967 00000 n +0000065098 00000 n +0000065229 00000 n +0000065360 00000 n +0000065491 00000 n +0000065622 00000 n +0000065753 00000 n +0000065884 00000 n +0000066015 00000 n +0000066146 00000 n +0000066277 00000 n +0000066408 00000 n +0000066539 00000 n +0000066670 00000 n +0000066801 00000 n +0000066932 00000 n +0000067063 00000 n +0000067194 00000 n +0000067325 00000 n +0000067456 00000 n +0000067587 00000 n +0000067718 00000 n +0000067849 00000 n +0000067980 00000 n +0000068111 00000 n +0000068242 00000 n +0000068373 00000 n +0000068504 00000 n +0000068635 00000 n +0000068766 00000 n +0000068897 00000 n +0000069028 00000 n +0000069159 00000 n +0000069290 00000 n +0000069421 00000 n +0000069552 00000 n +0000069683 00000 n +0000069814 00000 n +0000069945 00000 n +0000070076 00000 n +0000070207 00000 n +0000070338 00000 n +0000070469 00000 n +0000070600 00000 n +0000070731 00000 n +0000070862 00000 n +0000070993 00000 n +0000071124 00000 n +0000071255 00000 n +0000071386 00000 n +0000071517 00000 n +0000071648 00000 n +0000071779 00000 n +0000071910 00000 n +0000072041 00000 n +0000072172 00000 n +0000072303 00000 n +0000072434 00000 n +0000072565 00000 n +0000072696 00000 n +0000072827 00000 n +0000072958 00000 n +0000073089 00000 n +0000073220 00000 n +0000073351 00000 n +0000073482 00000 n +0000073613 00000 n +0000073744 00000 n +0000073875 00000 n +0000074006 00000 n +0000074137 00000 n +0000074268 00000 n +0000074399 00000 n +0000074530 00000 n +0000074661 00000 n +0000074792 00000 n +0000074923 00000 n +0000075054 00000 n +0000075185 00000 n +0000075316 00000 n +0000075447 00000 n +0000075578 00000 n +0000075709 00000 n +0000075840 00000 n +0000075971 00000 n +0000076102 00000 n +0000076233 00000 n +0000076364 00000 n +0000076495 00000 n +0000076626 00000 n +0000076757 00000 n +0000076888 00000 n +0000077019 00000 n +0000077150 00000 n +0000077281 00000 n +0000077412 00000 n +0000077543 00000 n +0000077674 00000 n +0000077805 00000 n +0000077936 00000 n +0000078067 00000 n +0000078198 00000 n +0000078329 00000 n +0000078460 00000 n +0000078591 00000 n +0000078722 00000 n +0000078853 00000 n +0000078984 00000 n +0000079115 00000 n +0000079246 00000 n +0000079377 00000 n +0000079508 00000 n +0000079639 00000 n +0000079770 00000 n +0000079901 00000 n +0000080032 00000 n +0000080163 00000 n +0000080294 00000 n +0000080425 00000 n +0000080556 00000 n +0000080687 00000 n +0000080818 00000 n +0000080949 00000 n +0000081080 00000 n +0000081211 00000 n +0000081342 00000 n +0000081473 00000 n +0000081604 00000 n +0000081735 00000 n +0000081866 00000 n +0000081997 00000 n +0000082128 00000 n +0000082259 00000 n +0000082390 00000 n +0000082521 00000 n +0000082652 00000 n +0000082783 00000 n +0000082914 00000 n +0000083045 00000 n +0000083176 00000 n +0000083307 00000 n +0000083438 00000 n +0000083569 00000 n +0000083700 00000 n +0000083831 00000 n +0000083962 00000 n +0000084093 00000 n +0000084224 00000 n +0000084355 00000 n +0000084486 00000 n +0000084617 00000 n +0000084748 00000 n +0000084879 00000 n +0000085010 00000 n +0000085141 00000 n +0000085272 00000 n +0000085403 00000 n +0000085534 00000 n +0000085665 00000 n +0000085796 00000 n +0000085927 00000 n +0000086058 00000 n +0000086189 00000 n +0000086320 00000 n +0000086451 00000 n +0000086582 00000 n +0000086713 00000 n +0000086844 00000 n +0000086975 00000 n +0000087106 00000 n +0000087237 00000 n +0000087368 00000 n +0000087499 00000 n +0000087630 00000 n +0000087761 00000 n +0000087892 00000 n +0000088023 00000 n +0000088154 00000 n +0000088285 00000 n +0000088416 00000 n +0000088547 00000 n +0000088678 00000 n +0000088809 00000 n +0000088940 00000 n +0000089071 00000 n +0000089202 00000 n +0000089333 00000 n +0000089464 00000 n +0000089595 00000 n +0000089726 00000 n +0000089857 00000 n +0000089988 00000 n +0000090119 00000 n +0000090250 00000 n +0000090381 00000 n +0000090512 00000 n +0000090643 00000 n +0000090774 00000 n +0000090905 00000 n +0000091036 00000 n +0000091167 00000 n +0000091298 00000 n +0000091429 00000 n +0000091560 00000 n +0000091691 00000 n +0000091822 00000 n +0000091953 00000 n +0000092084 00000 n +0000092215 00000 n +0000092346 00000 n +0000092477 00000 n +0000092608 00000 n +0000092739 00000 n +0000092870 00000 n +0000093001 00000 n +0000093132 00000 n +0000093263 00000 n +0000093394 00000 n +0000093525 00000 n +0000093656 00000 n +0000093787 00000 n +0000093918 00000 n +0000094049 00000 n +0000094180 00000 n +0000094311 00000 n +0000094442 00000 n +0000094573 00000 n +0000094704 00000 n +0000094835 00000 n +0000094966 00000 n +0000095097 00000 n +0000095228 00000 n +0000095359 00000 n +0000095490 00000 n +0000095621 00000 n +0000095752 00000 n +0000095883 00000 n +0000096014 00000 n +0000096145 00000 n +0000096276 00000 n +0000096407 00000 n +0000096538 00000 n +0000096669 00000 n +0000096800 00000 n +0000096931 00000 n +0000097062 00000 n +0000097193 00000 n +0000097324 00000 n +0000097455 00000 n +0000097586 00000 n +0000097717 00000 n +0000097848 00000 n +0000097979 00000 n +0000098110 00000 n +0000098241 00000 n +0000098372 00000 n +0000098503 00000 n +0000098634 00000 n +0000098765 00000 n +0000098896 00000 n +0000099027 00000 n +0000099158 00000 n +0000099289 00000 n +0000099420 00000 n +0000099551 00000 n +0000099682 00000 n +0000099813 00000 n +0000099944 00000 n +0000100075 00000 n +0000100206 00000 n +0000100337 00000 n +0000100468 00000 n +0000100599 00000 n +0000100730 00000 n +0000100861 00000 n +0000100992 00000 n +0000101123 00000 n +0000101254 00000 n +0000101385 00000 n +0000101516 00000 n +0000101647 00000 n +0000101778 00000 n +0000101909 00000 n +0000102040 00000 n +0000102171 00000 n +0000102302 00000 n +0000102433 00000 n +0000102564 00000 n +0000102695 00000 n +0000102826 00000 n +0000102957 00000 n +0000103088 00000 n +0000103219 00000 n +0000103350 00000 n +0000103481 00000 n +0000103612 00000 n +0000103743 00000 n +0000103874 00000 n +0000104005 00000 n +0000104136 00000 n +0000104267 00000 n +0000104398 00000 n +0000104529 00000 n +0000104660 00000 n +0000104791 00000 n +0000104922 00000 n +0000105053 00000 n +0000105184 00000 n +0000105315 00000 n +0000105446 00000 n +0000105577 00000 n +0000105708 00000 n +0000105839 00000 n +0000105970 00000 n +0000106101 00000 n +0000106232 00000 n +0000106363 00000 n +0000106494 00000 n +0000106625 00000 n +0000106756 00000 n +0000106887 00000 n +0000107018 00000 n +0000107149 00000 n +0000107280 00000 n +0000107411 00000 n +0000107542 00000 n +0000107673 00000 n +0000107804 00000 n +0000107935 00000 n +0000108066 00000 n +0000108197 00000 n +0000108328 00000 n +0000108459 00000 n +0000108590 00000 n +0000108721 00000 n +0000108852 00000 n +0000108983 00000 n +0000109114 00000 n +0000109245 00000 n +0000109376 00000 n +0000109507 00000 n +0000109638 00000 n +0000109769 00000 n +0000109900 00000 n +0000110031 00000 n +0000110162 00000 n +0000110293 00000 n +0000110424 00000 n +0000110555 00000 n +0000110686 00000 n +0000110817 00000 n +0000110948 00000 n +0000111079 00000 n +0000111210 00000 n +0000111341 00000 n +0000111472 00000 n +0000111603 00000 n +0000111734 00000 n +0000111865 00000 n +0000111996 00000 n +0000112127 00000 n +0000112258 00000 n +0000112389 00000 n +0000112520 00000 n +0000112651 00000 n +0000112782 00000 n +0000112913 00000 n +0000113044 00000 n +0000113175 00000 n +0000113306 00000 n +0000113437 00000 n +0000113568 00000 n +0000113699 00000 n +0000113830 00000 n +0000113961 00000 n +0000114092 00000 n +0000114223 00000 n +0000114354 00000 n +0000114485 00000 n +0000114616 00000 n +0000114747 00000 n +0000114878 00000 n +0000115009 00000 n +0000115140 00000 n +0000115271 00000 n +0000115402 00000 n +0000115533 00000 n +0000115664 00000 n +0000115795 00000 n +0000115926 00000 n +0000116057 00000 n +0000116188 00000 n +0000116319 00000 n +0000116450 00000 n +0000116581 00000 n +0000116712 00000 n +0000116843 00000 n +0000116974 00000 n +0000117105 00000 n +0000117236 00000 n +0000117367 00000 n +0000117498 00000 n +0000117629 00000 n +0000117760 00000 n +0000117891 00000 n +0000118022 00000 n +0000118153 00000 n +0000118284 00000 n +0000118415 00000 n +0000118546 00000 n +0000118677 00000 n +0000118808 00000 n +0000118939 00000 n +0000119070 00000 n +0000119201 00000 n +0000119332 00000 n +0000119463 00000 n +0000119594 00000 n +0000119725 00000 n +0000119856 00000 n +0000119987 00000 n +0000120118 00000 n +0000120249 00000 n +0000120380 00000 n +0000120511 00000 n +0000120642 00000 n +0000120773 00000 n +0000120904 00000 n +0000121035 00000 n +0000121166 00000 n +0000121297 00000 n +0000121428 00000 n +0000121559 00000 n +0000121690 00000 n +0000121821 00000 n +0000121952 00000 n +0000122083 00000 n +0000122214 00000 n +0000122345 00000 n +0000122476 00000 n +0000122607 00000 n +0000122738 00000 n +0000122869 00000 n +0000123000 00000 n +0000123131 00000 n +0000123262 00000 n +0000123393 00000 n +0000123524 00000 n +0000123655 00000 n +0000123786 00000 n +0000123917 00000 n +0000124048 00000 n +0000124179 00000 n +0000124310 00000 n +0000124441 00000 n +0000124572 00000 n +0000124703 00000 n +0000124834 00000 n +0000124965 00000 n +0000125096 00000 n +0000125227 00000 n +0000125358 00000 n +0000125489 00000 n +0000125620 00000 n +0000125751 00000 n +0000125882 00000 n +0000126013 00000 n +0000126144 00000 n +0000126275 00000 n +0000126406 00000 n +0000126537 00000 n +0000126668 00000 n +0000126799 00000 n +0000126930 00000 n +0000127061 00000 n +0000127192 00000 n +0000127323 00000 n +0000127454 00000 n +0000127585 00000 n +0000127716 00000 n +0000127847 00000 n +0000127978 00000 n +0000128109 00000 n +0000128240 00000 n +0000128371 00000 n +0000128502 00000 n +0000128633 00000 n +0000128764 00000 n +0000128895 00000 n +0000129026 00000 n +0000129157 00000 n +0000129288 00000 n +0000129419 00000 n +0000129550 00000 n +0000129681 00000 n +0000129812 00000 n +0000129943 00000 n +0000130074 00000 n +0000130205 00000 n +0000130336 00000 n +0000130467 00000 n +0000130598 00000 n +0000130729 00000 n +0000130860 00000 n +0000130991 00000 n +0000131122 00000 n +0000131253 00000 n +0000131384 00000 n +0000131515 00000 n +0000131646 00000 n +0000131777 00000 n +0000131908 00000 n +0000132039 00000 n +0000132170 00000 n +0000132301 00000 n +0000132432 00000 n +0000132563 00000 n +0000132694 00000 n +0000132825 00000 n +0000132956 00000 n +0000133087 00000 n +0000133218 00000 n +0000133349 00000 n +0000133480 00000 n +0000133611 00000 n +0000133742 00000 n +0000133873 00000 n +0000134004 00000 n +0000134135 00000 n +0000134266 00000 n +0000134397 00000 n +0000134528 00000 n +0000134659 00000 n +0000134790 00000 n +0000134921 00000 n +0000135052 00000 n +0000135183 00000 n +0000135314 00000 n +0000135445 00000 n +0000135576 00000 n +0000135707 00000 n +0000135838 00000 n +0000135969 00000 n +0000136100 00000 n +0000136231 00000 n +0000136362 00000 n +0000136493 00000 n +0000136624 00000 n +0000136755 00000 n +0000136886 00000 n +0000137017 00000 n +0000137148 00000 n +0000137279 00000 n +0000137410 00000 n +0000137541 00000 n +0000137672 00000 n +0000137803 00000 n +0000137934 00000 n +0000138065 00000 n +0000138196 00000 n +0000138327 00000 n +0000138458 00000 n +0000138590 00000 n +0000138722 00000 n +0000138854 00000 n +0000138986 00000 n +0000139077 00000 n +0000139168 00000 n +0000139259 00000 n +0000139350 00000 n +0000139441 00000 n +0000139532 00000 n +0000139623 00000 n +0000139714 00000 n +0000139805 00000 n +0000139897 00000 n +0000139989 00000 n +0000140081 00000 n +0000140173 00000 n +0000140265 00000 n +0000140357 00000 n +0000140449 00000 n +0000140541 00000 n +0000140633 00000 n +0000140725 00000 n +0000140817 00000 n +0000140909 00000 n +0000141001 00000 n +0000141093 00000 n +0000141185 00000 n +0000141277 00000 n +0000141369 00000 n +0000141461 00000 n +0000141553 00000 n +0000141645 00000 n +0000141737 00000 n +0000141829 00000 n +0000141921 00000 n +0000142013 00000 n +0000142105 00000 n +0000142197 00000 n +0000142289 00000 n +0000142381 00000 n +0000142473 00000 n +0000142565 00000 n +0000142657 00000 n +0000142749 00000 n +0000142841 00000 n +0000142933 00000 n +0000143025 00000 n +0000143117 00000 n +0000143209 00000 n +0000143301 00000 n +0000143393 00000 n +0000143485 00000 n +0000143577 00000 n +0000143669 00000 n +0000143761 00000 n +0000143853 00000 n +0000143945 00000 n +0000144037 00000 n +0000144129 00000 n +0000144221 00000 n +0000144313 00000 n +0000144405 00000 n +0000144497 00000 n +0000144589 00000 n +0000144681 00000 n +0000144773 00000 n +0000144865 00000 n +0000144957 00000 n +0000145049 00000 n +0000145141 00000 n +0000145233 00000 n +0000145325 00000 n +0000145417 00000 n +0000145509 00000 n +0000145601 00000 n +0000145693 00000 n +0000145785 00000 n +0000145877 00000 n +0000145969 00000 n +0000146061 00000 n +0000146153 00000 n +0000146245 00000 n +0000146337 00000 n +0000146429 00000 n +0000146521 00000 n +0000146613 00000 n +0000146705 00000 n +0000146797 00000 n +0000146889 00000 n +0000146981 00000 n +0000147073 00000 n +0000147165 00000 n +0000147257 00000 n +0000147349 00000 n +0000147441 00000 n +0000147533 00000 n +0000147625 00000 n +0000147717 00000 n +0000147809 00000 n +0000147901 00000 n +0000147993 00000 n +0000148085 00000 n +0000148178 00000 n +0000148271 00000 n +0000148364 00000 n +0000148457 00000 n +0000148550 00000 n +0000148643 00000 n +0000148736 00000 n +0000148829 00000 n +0000148922 00000 n +0000149015 00000 n +0000149108 00000 n +0000149201 00000 n +0000149294 00000 n +0000149387 00000 n +0000149480 00000 n +0000149573 00000 n +0000149666 00000 n +0000149759 00000 n +0000149852 00000 n +0000149945 00000 n +0000150038 00000 n +0000150131 00000 n +0000150224 00000 n +0000150317 00000 n +0000150410 00000 n +0000150503 00000 n +0000150596 00000 n +0000150689 00000 n +0000150782 00000 n +0000150875 00000 n +0000150968 00000 n +0000151061 00000 n +0000151154 00000 n +0000151247 00000 n +0000151340 00000 n +0000151433 00000 n +0000151526 00000 n +0000151619 00000 n +0000151712 00000 n +0000151805 00000 n +0000151898 00000 n +0000151991 00000 n +0000152084 00000 n +0000152177 00000 n +0000152270 00000 n +0000152363 00000 n +0000152456 00000 n +0000152549 00000 n +0000152642 00000 n +0000152735 00000 n +0000152828 00000 n +0000152921 00000 n +0000153014 00000 n +0000153107 00000 n +0000153200 00000 n +0000153293 00000 n +0000153386 00000 n +0000153479 00000 n +0000153572 00000 n +0000153665 00000 n +0000153758 00000 n +0000153851 00000 n +0000153944 00000 n +0000154037 00000 n +0000154130 00000 n +0000154223 00000 n +0000154316 00000 n +0000154409 00000 n +0000154502 00000 n +0000154595 00000 n +0000154688 00000 n +0000154781 00000 n +0000154874 00000 n +0000154967 00000 n +0000155060 00000 n +0000155153 00000 n +0000155246 00000 n +0000155339 00000 n +0000155432 00000 n +0000155525 00000 n +0000155618 00000 n +0000155711 00000 n +0000155804 00000 n +0000155897 00000 n +0000155990 00000 n +0000156083 00000 n +0000156176 00000 n +0000156269 00000 n +0000156362 00000 n +0000156455 00000 n +0000156548 00000 n +0000156641 00000 n +0000156734 00000 n +0000156827 00000 n +0000156920 00000 n +0000157013 00000 n +0000157106 00000 n +0000157199 00000 n +0000157292 00000 n +0000157385 00000 n +0000157478 00000 n +0000157571 00000 n +0000157664 00000 n +0000157757 00000 n +0000157850 00000 n +0000157943 00000 n +0000158036 00000 n +0000158129 00000 n +0000158222 00000 n +0000158315 00000 n +0000158408 00000 n +0000158501 00000 n +0000158594 00000 n +0000158687 00000 n +0000158780 00000 n +0000158873 00000 n +0000158966 00000 n +0000159059 00000 n +0000159152 00000 n +0000159245 00000 n +0000159338 00000 n +0000159431 00000 n +0000159524 00000 n +0000159617 00000 n +0000159710 00000 n +0000159803 00000 n +0000159896 00000 n +0000159989 00000 n +0000160082 00000 n +0000160175 00000 n +0000160268 00000 n +0000160361 00000 n +0000160454 00000 n +0000160547 00000 n +0000160640 00000 n +0000160733 00000 n +0000160826 00000 n +0000160919 00000 n +0000161012 00000 n +0000161105 00000 n +0000161198 00000 n +0000161291 00000 n +0000161384 00000 n +0000161477 00000 n +0000161570 00000 n +0000161663 00000 n +0000161756 00000 n +0000161849 00000 n +0000161942 00000 n +0000162035 00000 n +0000162128 00000 n +0000162221 00000 n +0000162314 00000 n +0000162407 00000 n +0000162500 00000 n +0000162593 00000 n +0000162686 00000 n +0000162779 00000 n +0000162872 00000 n +0000162965 00000 n +0000163058 00000 n +0000163151 00000 n +0000163244 00000 n +0000163337 00000 n +0000163430 00000 n +0000163523 00000 n +0000163616 00000 n +0000163709 00000 n +0000163802 00000 n +0000163895 00000 n +0000163988 00000 n +0000164081 00000 n +0000164174 00000 n +0000164267 00000 n +0000164360 00000 n +0000164453 00000 n +0000164546 00000 n +0000164639 00000 n +0000164732 00000 n +0000164825 00000 n +0000164918 00000 n +0000165011 00000 n +0000165104 00000 n +0000165197 00000 n +0000165290 00000 n +0000165383 00000 n +0000165476 00000 n +0000165569 00000 n +0000165662 00000 n +0000165755 00000 n +0000165848 00000 n +0000165941 00000 n +0000166034 00000 n +0000166127 00000 n +0000166220 00000 n +0000166313 00000 n +0000166406 00000 n +0000166499 00000 n +0000166592 00000 n +0000166685 00000 n +0000166778 00000 n +0000166871 00000 n +0000166964 00000 n +0000167057 00000 n +0000167150 00000 n +0000167243 00000 n +0000167336 00000 n +0000167429 00000 n +0000167522 00000 n +0000167615 00000 n +0000167708 00000 n +0000167801 00000 n +0000167894 00000 n +0000167987 00000 n +0000168080 00000 n +0000168173 00000 n +0000168266 00000 n +0000168359 00000 n +0000168452 00000 n +0000168545 00000 n +0000168638 00000 n +0000168731 00000 n +0000168824 00000 n +0000168917 00000 n +0000169010 00000 n +0000169103 00000 n +0000169196 00000 n +0000169289 00000 n +0000169382 00000 n +0000169475 00000 n +0000169568 00000 n +0000169661 00000 n +0000169754 00000 n +0000169847 00000 n +0000169940 00000 n +0000170033 00000 n +0000170126 00000 n +0000170219 00000 n +0000170312 00000 n +0000170405 00000 n +0000170498 00000 n +0000170591 00000 n +0000170684 00000 n +0000170777 00000 n +0000170870 00000 n +0000170963 00000 n +0000171056 00000 n +0000171149 00000 n +0000171242 00000 n +0000171335 00000 n +0000171428 00000 n +0000171521 00000 n +0000171614 00000 n +0000171707 00000 n +0000171800 00000 n +0000171893 00000 n +0000171986 00000 n +0000172079 00000 n +0000172172 00000 n +0000172265 00000 n +0000172358 00000 n +0000172451 00000 n +0000172544 00000 n +0000172637 00000 n +0000172730 00000 n +0000172823 00000 n +0000172916 00000 n +0000173009 00000 n +0000173102 00000 n +0000173195 00000 n +0000173288 00000 n +0000173381 00000 n +0000173474 00000 n +0000173567 00000 n +0000173660 00000 n +0000173753 00000 n +0000173846 00000 n +0000173939 00000 n +0000174032 00000 n +0000174125 00000 n +0000174218 00000 n +0000174311 00000 n +0000174404 00000 n +0000174497 00000 n +0000174590 00000 n +0000174683 00000 n +0000174776 00000 n +0000174869 00000 n +0000174962 00000 n +0000175055 00000 n +0000175148 00000 n +0000175241 00000 n +0000175334 00000 n +0000175427 00000 n +0000175520 00000 n +0000175613 00000 n +0000175706 00000 n +0000175799 00000 n +0000175892 00000 n +0000175985 00000 n +0000176078 00000 n +0000176171 00000 n +0000176264 00000 n +0000176357 00000 n +0000176450 00000 n +0000176543 00000 n +0000176636 00000 n +0000176729 00000 n +0000176822 00000 n +0000176915 00000 n +0000177008 00000 n +0000177101 00000 n +0000177194 00000 n +0000177287 00000 n +0000177380 00000 n +0000177473 00000 n +0000177566 00000 n +0000177659 00000 n +0000177752 00000 n +0000177845 00000 n +0000177938 00000 n +0000178031 00000 n +0000178124 00000 n +0000178217 00000 n +0000178310 00000 n +0000178403 00000 n +0000178496 00000 n +0000178589 00000 n +0000178682 00000 n +0000178775 00000 n +0000178868 00000 n +0000178961 00000 n +0000179054 00000 n +0000179147 00000 n +0000179240 00000 n +0000179333 00000 n +0000179426 00000 n +0000179519 00000 n +0000179612 00000 n +0000179705 00000 n +0000179798 00000 n +0000179891 00000 n +0000179984 00000 n +0000180077 00000 n +0000180170 00000 n +0000180263 00000 n +0000180356 00000 n +0000180449 00000 n +0000180542 00000 n +0000180635 00000 n +0000180728 00000 n +0000180821 00000 n +0000180914 00000 n +0000181007 00000 n +0000181100 00000 n +0000181193 00000 n +0000181286 00000 n +0000181379 00000 n +0000181472 00000 n +0000181565 00000 n +0000181658 00000 n +0000181751 00000 n +0000181844 00000 n +0000181937 00000 n +0000182030 00000 n +0000182123 00000 n +0000182216 00000 n +0000182309 00000 n +0000182402 00000 n +0000182495 00000 n +0000182588 00000 n +0000182681 00000 n +0000182774 00000 n +0000182867 00000 n +0000182960 00000 n +0000183053 00000 n +0000183146 00000 n +0000183239 00000 n +0000183332 00000 n +0000183425 00000 n +0000183518 00000 n +0000183611 00000 n +0000183704 00000 n +0000183797 00000 n +0000183890 00000 n +0000183983 00000 n +0000184076 00000 n +0000184169 00000 n +0000184262 00000 n +0000184355 00000 n +0000184448 00000 n +0000184541 00000 n +0000184634 00000 n +0000184727 00000 n +0000184820 00000 n +0000184913 00000 n +0000185006 00000 n +0000185099 00000 n +0000185192 00000 n +0000185285 00000 n +0000185378 00000 n +0000185494 00000 n +0000185587 00000 n +0000185680 00000 n +0000185773 00000 n +0000185866 00000 n +0000185959 00000 n +0000186052 00000 n +0000186145 00000 n +0000186238 00000 n +0000186331 00000 n +0000186424 00000 n +0000186517 00000 n +0000186610 00000 n +0000186703 00000 n +0000186796 00000 n +0000186889 00000 n +0000186982 00000 n +0000187075 00000 n +0000187168 00000 n +0000187261 00000 n +0000187354 00000 n +0000187447 00000 n +0000187540 00000 n +0000187633 00000 n +0000187726 00000 n +0000187819 00000 n +0000187912 00000 n +0000188005 00000 n +0000188098 00000 n +0000188191 00000 n +0000188284 00000 n +0000188377 00000 n +0000188470 00000 n +0000188563 00000 n +0000188656 00000 n +0000188749 00000 n +0000188842 00000 n +0000188935 00000 n +0000189028 00000 n +0000189121 00000 n +0000189214 00000 n +0000189307 00000 n +0000189400 00000 n +0000189493 00000 n +0000189586 00000 n +0000189679 00000 n +0000189772 00000 n +0000189865 00000 n +0000189958 00000 n +0000190051 00000 n +0000190144 00000 n +0000190237 00000 n +0000190330 00000 n +0000190423 00000 n +0000190516 00000 n +0000190609 00000 n +0000190702 00000 n +0000190795 00000 n +0000190888 00000 n +0000190981 00000 n +0000191074 00000 n +0000191167 00000 n +0000191260 00000 n +0000191353 00000 n +0000191446 00000 n +0000191539 00000 n +0000191632 00000 n +0000191725 00000 n +0000191818 00000 n +0000191911 00000 n +0000192004 00000 n +0000192097 00000 n +0000192190 00000 n +0000192283 00000 n +0000192376 00000 n +0000192469 00000 n +0000192562 00000 n +0000192655 00000 n +0000192748 00000 n +0000192841 00000 n +0000192934 00000 n +0000193027 00000 n +0000193120 00000 n +0000193213 00000 n +0000193306 00000 n +0000193399 00000 n +0000193492 00000 n +0000193585 00000 n +0000193678 00000 n +0000193771 00000 n +0000193864 00000 n +0000193957 00000 n +0000194050 00000 n +0000194143 00000 n +0000194236 00000 n +0000194329 00000 n +0000194422 00000 n +0000194515 00000 n +0000194608 00000 n +0000194701 00000 n +0000194794 00000 n +0000194887 00000 n +0000194980 00000 n +0000195073 00000 n +0000195166 00000 n +0000195259 00000 n +0000195352 00000 n +0000195445 00000 n +0000195538 00000 n +0000195631 00000 n +0000195724 00000 n +0000195817 00000 n +0000195910 00000 n +0000196003 00000 n +0000196096 00000 n +0000196189 00000 n +0000196282 00000 n +0000196375 00000 n +0000196468 00000 n +0000196561 00000 n +0000196654 00000 n +0000196747 00000 n +0000196840 00000 n +0000196933 00000 n +0000197026 00000 n +0000197119 00000 n +0000197212 00000 n +0000197305 00000 n +0000197398 00000 n +0000197491 00000 n +0000197584 00000 n +0000197677 00000 n +0000197770 00000 n +0000197863 00000 n +0000197956 00000 n +0000198049 00000 n +0000198142 00000 n +0000198235 00000 n +0000198328 00000 n +0000198421 00000 n +0000198514 00000 n +0000198607 00000 n +0000198700 00000 n +0000198793 00000 n +0000198886 00000 n +0000198979 00000 n +0000199072 00000 n +0000199165 00000 n +0000199258 00000 n +0000199351 00000 n +0000199444 00000 n +0000199537 00000 n +0000199630 00000 n +0000199723 00000 n +0000199816 00000 n +0000199909 00000 n +0000200002 00000 n +0000200095 00000 n +0000200188 00000 n +0000200281 00000 n +0000200374 00000 n +0000200467 00000 n +0000200560 00000 n +0000200653 00000 n +0000200746 00000 n +0000200839 00000 n +0000200932 00000 n +0000201025 00000 n +0000201118 00000 n +0000201211 00000 n +0000201304 00000 n +0000201397 00000 n +0000201490 00000 n +0000201583 00000 n +0000201676 00000 n +0000201769 00000 n +0000201862 00000 n +0000201955 00000 n +0000202048 00000 n +0000202141 00000 n +0000202234 00000 n +0000202327 00000 n +0000202420 00000 n +0000202513 00000 n +0000202606 00000 n +0000202699 00000 n +0000202792 00000 n +0000202885 00000 n +0000202978 00000 n +0000203071 00000 n +0000203164 00000 n +0000203257 00000 n +0000203350 00000 n +0000203443 00000 n +0000203536 00000 n +0000203629 00000 n +0000203722 00000 n +0000203815 00000 n +0000203908 00000 n +0000204001 00000 n +0000204094 00000 n +0000204187 00000 n +0000204280 00000 n +0000204373 00000 n +0000204466 00000 n +0000204559 00000 n +0000204652 00000 n +0000204745 00000 n +0000204838 00000 n +0000204931 00000 n +0000205024 00000 n +0000205117 00000 n +0000205210 00000 n +0000205303 00000 n +0000205396 00000 n +0000205489 00000 n +0000205582 00000 n +0000205675 00000 n +0000205768 00000 n +0000205861 00000 n +0000205954 00000 n +0000206047 00000 n +0000206140 00000 n +0000206233 00000 n +0000206326 00000 n +0000206419 00000 n +0000206512 00000 n +0000206605 00000 n +0000206698 00000 n +0000206791 00000 n +0000206884 00000 n +0000206977 00000 n +0000207070 00000 n +0000207163 00000 n +0000207256 00000 n +0000207349 00000 n +0000207442 00000 n +0000207535 00000 n +0000207628 00000 n +0000207721 00000 n +0000207814 00000 n +0000207907 00000 n +0000208000 00000 n +0000208093 00000 n +0000208186 00000 n +0000208279 00000 n +0000208372 00000 n +0000208465 00000 n +0000208558 00000 n +0000208651 00000 n +0000208744 00000 n +0000208837 00000 n +0000208930 00000 n +0000209023 00000 n +0000209116 00000 n +0000209209 00000 n +0000209302 00000 n +0000209395 00000 n +0000209488 00000 n +0000209581 00000 n +0000209674 00000 n +0000209767 00000 n +0000209860 00000 n +0000209953 00000 n +0000210046 00000 n +0000210139 00000 n +0000210232 00000 n +0000210325 00000 n +0000210418 00000 n +0000210511 00000 n +0000210604 00000 n +0000210697 00000 n +0000210790 00000 n +0000210883 00000 n +0000210976 00000 n +0000211069 00000 n +0000211162 00000 n +0000211255 00000 n +0000211348 00000 n +0000211441 00000 n +0000211534 00000 n +0000211627 00000 n +0000211720 00000 n +0000211813 00000 n +0000211906 00000 n +0000211999 00000 n +0000212092 00000 n +0000212185 00000 n +0000212278 00000 n +0000212371 00000 n +0000212464 00000 n +0000212557 00000 n +0000212650 00000 n +0000212743 00000 n +0000212836 00000 n +0000212929 00000 n +0000213022 00000 n +0000213115 00000 n +0000213208 00000 n +0000213301 00000 n +0000213394 00000 n +0000213487 00000 n +0000213580 00000 n +0000213673 00000 n +0000213766 00000 n +0000213859 00000 n +0000213952 00000 n +0000214045 00000 n +0000214138 00000 n +0000214231 00000 n +0000214324 00000 n +0000214417 00000 n +0000214510 00000 n +0000214603 00000 n +0000214696 00000 n +0000214789 00000 n +0000214882 00000 n +0000214975 00000 n +0000215068 00000 n +0000215161 00000 n +0000215254 00000 n +0000215347 00000 n +0000215440 00000 n +0000215533 00000 n +0000215626 00000 n +0000215719 00000 n +0000215812 00000 n +0000215905 00000 n +0000215998 00000 n +0000216091 00000 n +0000216184 00000 n +0000216277 00000 n +0000216370 00000 n +0000216463 00000 n +0000216556 00000 n +0000216649 00000 n +0000216742 00000 n +0000216835 00000 n +0000216928 00000 n +0000217021 00000 n +0000217114 00000 n +0000217207 00000 n +0000217300 00000 n +0000217393 00000 n +0000217486 00000 n +0000217579 00000 n +0000217672 00000 n +0000217765 00000 n +0000217858 00000 n +0000217951 00000 n +0000218044 00000 n +0000218137 00000 n +0000218230 00000 n +0000218323 00000 n +0000218416 00000 n +0000218509 00000 n +0000218602 00000 n +0000218695 00000 n +0000218788 00000 n +0000218881 00000 n +0000218974 00000 n +0000219067 00000 n +0000219160 00000 n +0000219253 00000 n +0000219346 00000 n +0000219439 00000 n +0000219532 00000 n +0000219625 00000 n +0000219718 00000 n +0000219811 00000 n +0000219904 00000 n +0000219997 00000 n +0000220090 00000 n +0000220183 00000 n +0000220276 00000 n +0000220369 00000 n +0000220462 00000 n +0000220555 00000 n +0000220648 00000 n +0000220741 00000 n +0000220834 00000 n +0000220927 00000 n +0000221020 00000 n +0000221113 00000 n +0000221206 00000 n +0000221299 00000 n +0000221392 00000 n +0000221485 00000 n +0000221578 00000 n +0000221671 00000 n +0000221764 00000 n +0000221857 00000 n +0000221950 00000 n +0000222043 00000 n +0000222136 00000 n +0000222229 00000 n +0000222322 00000 n +0000222415 00000 n +0000222508 00000 n +0000222601 00000 n +0000222694 00000 n +0000222787 00000 n +0000222880 00000 n +0000222973 00000 n +0000223066 00000 n +0000223159 00000 n +0000223252 00000 n +0000223345 00000 n +0000223438 00000 n +0000223531 00000 n +0000223624 00000 n +0000223717 00000 n +0000223810 00000 n +0000223903 00000 n +0000223996 00000 n +0000224089 00000 n +0000224182 00000 n +0000224275 00000 n +0000224368 00000 n +0000224461 00000 n +0000224554 00000 n +0000224647 00000 n +0000224740 00000 n +0000224833 00000 n +0000224926 00000 n +0000225019 00000 n +0000225112 00000 n +0000225205 00000 n +0000225298 00000 n +0000225391 00000 n +0000225484 00000 n +0000225577 00000 n +0000225670 00000 n +0000225763 00000 n +0000225856 00000 n +0000225949 00000 n +0000226042 00000 n +0000226135 00000 n +0000226228 00000 n +0000226321 00000 n +0000226414 00000 n +0000226507 00000 n +0000226600 00000 n +0000226693 00000 n +0000226786 00000 n +0000226879 00000 n +0000226972 00000 n +0000227065 00000 n +0000227158 00000 n +0000227251 00000 n +0000227344 00000 n +0000227437 00000 n +0000227530 00000 n +0000227623 00000 n +0000227716 00000 n +0000227809 00000 n +0000227902 00000 n +0000227995 00000 n +0000228088 00000 n +0000228181 00000 n +0000228274 00000 n +0000228367 00000 n +0000228460 00000 n +0000228553 00000 n +0000228646 00000 n +0000228739 00000 n +0000228832 00000 n +0000228925 00000 n +0000229018 00000 n +0000229111 00000 n +0000229204 00000 n +0000229297 00000 n +0000229390 00000 n +0000229483 00000 n +0000229576 00000 n +0000229669 00000 n +0000229762 00000 n +0000229855 00000 n +0000229948 00000 n +0000230041 00000 n +0000230134 00000 n +0000230227 00000 n +0000230320 00000 n +0000230413 00000 n +0000230506 00000 n +0000230599 00000 n +0000230692 00000 n +0000230785 00000 n +0000230878 00000 n +0000230971 00000 n +0000231064 00000 n +0000231157 00000 n +0000231250 00000 n +0000231343 00000 n +0000231436 00000 n +0000231529 00000 n +0000231622 00000 n +0000231715 00000 n +0000231808 00000 n +trailer +<< /Size 2004 /Root 1 0 R >> +startxref +231902 +%%EOF diff --git a/corpus/hello.pdf b/corpus/hello.pdf new file mode 100644 index 0000000..946ecec --- /dev/null +++ b/corpus/hello.pdf @@ -0,0 +1,31 @@ +%PDF-1.7 +1 0 obj +<< /Type /Catalog /Pages 2 0 R >> +endobj +2 0 obj +<< /Type /Pages /Kids [3 0 R] /Count 1 >> +endobj +3 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 5 0 R >> >> /Contents 4 0 R >> +endobj +4 0 obj +<< /Length 57 >> +stream +BT /F1 24 Tf 72 700 Td (Hello FoFreeXit - Phase 1) Tj ET +endstream +endobj +5 0 obj +<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> +endobj +xref 6 +0000000000 65535 f +0000000009 00000 n +0000000058 00000 n +0000000115 00000 n +0000000241 00000 n +0000000347 00000 n +trailer +<< /Size 6 /Root 1 0 R >> +startxref +417 +%%EOF diff --git a/corpus/sample-multipage.pdf b/corpus/sample-multipage.pdf new file mode 100644 index 0000000..3ce1ab7 --- /dev/null +++ b/corpus/sample-multipage.pdf @@ -0,0 +1,69 @@ +%PDF-1.7 +1 0 obj +<< /Type /Catalog /Pages 2 0 R /Outlines 7 0 R >> +endobj +2 0 obj +<< /Type /Pages /Kids [3 0 R 4 0 R 5 0 R] /Count 3 >> +endobj +3 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 6 0 R >> >> /Contents 11 0 R >> +endobj +4 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 6 0 R >> >> /Contents 12 0 R >> +endobj +5 0 obj +<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 6 0 R >> >> /Contents 13 0 R >> +endobj +6 0 obj +<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> +endobj +7 0 obj +<< /Type /Outlines /First 8 0 R /Last 10 0 R /Count 3 >> +endobj +8 0 obj +<< /Title (Chapter 1) /Parent 7 0 R /Next 9 0 R /Dest [3 0 R /Fit] >> +endobj +9 0 obj +<< /Title (Chapter 2) /Parent 7 0 R /Prev 8 0 R /Next 10 0 R /Dest [4 0 R /Fit] >> +endobj +10 0 obj +<< /Title (Chapter 3) /Parent 7 0 R /Prev 9 0 R /Dest [5 0 R /Fit] >> +endobj +11 0 obj +<< /Length 92 >> +stream +BT /F1 18 Tf 72 720 Td (FoFreeXit Test Document) Tj 0 -28 Td (Page one content alpha) Tj ET +endstream +endobj +12 0 obj +<< /Length 64 >> +stream +BT /F1 18 Tf 72 720 Td (Page two content beta searchterm) Tj ET +endstream +endobj +13 0 obj +<< /Length 56 >> +stream +BT /F1 18 Tf 72 720 Td (Page three content gamma) Tj ET +endstream +endobj +xref +0 14 65535 f +0000000009 00000 n +0000000074 00000 n +0000000143 00000 n +0000000270 00000 n +0000000397 00000 n +0000000524 00000 n +0000000594 00000 n +0000000666 00000 n +0000000751 00000 n +0000000849 00000 n +0000000935 00000 n +0000001077 00000 n +0000001191 00000 n +trailer +<< /Size 14 /Root 1 0 R >> +startxref +1297 +%%EOF diff --git a/crates/ff-cli/Cargo.toml b/crates/ff-cli/Cargo.toml new file mode 100644 index 0000000..566869a --- /dev/null +++ b/crates/ff-cli/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "ff-cli" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "FoFreeXit command-line interface (runs engine features headless, for testing)" + +[[bin]] +name = "ff" +path = "src/main.rs" + +[dependencies] +ff-engine = { path = "../ff-engine" } +anyhow.workspace = true +clap = { version = "4", features = ["derive"] } diff --git a/crates/ff-cli/src/main.rs b/crates/ff-cli/src/main.rs new file mode 100644 index 0000000..a6f5bd8 --- /dev/null +++ b/crates/ff-cli/src/main.rs @@ -0,0 +1,203 @@ +//! ff — CLI của FoFreeXit. Chạy các tính năng engine không cần UI (để test). + +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use clap::{Parser, Subcommand}; + +#[derive(Parser)] +#[command(name = "ff", version, about = "FoFreeXit CLI")] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Subcommand)] +enum Command { + /// In số trang của một file PDF. + Info { + /// Đường dẫn file PDF. + input: PathBuf, + /// Mật khẩu (nếu file mã hoá). + #[arg(long)] + password: Option, + }, + /// Render một trang ra ảnh PNG. + Render { + /// Đường dẫn file PDF đầu vào. + input: PathBuf, + /// Đường dẫn PNG đầu ra. + output: PathBuf, + /// Số trang (0-based). + #[arg(long, default_value_t = 0)] + page: u16, + /// Chiều rộng ảnh mục tiêu (px). + #[arg(long, default_value_t = 1240)] + width: u32, + /// Mật khẩu (nếu file mã hoá). + #[arg(long)] + password: Option, + }, + /// In kích thước (points) của mọi trang. + Pages { + input: PathBuf, + #[arg(long)] + password: Option, + }, + /// In text trích từ một trang. + Text { + input: PathBuf, + #[arg(long, default_value_t = 0)] + page: u16, + #[arg(long)] + password: Option, + }, + /// Tìm chuỗi trong tài liệu; in số kết quả và vị trí. + Search { + input: PathBuf, + /// Chuỗi cần tìm. + query: String, + /// Phân biệt hoa/thường. + #[arg(long)] + case_sensitive: bool, + #[arg(long)] + password: Option, + }, + /// In outline (bookmarks) của tài liệu. + Outline { + input: PathBuf, + #[arg(long)] + password: Option, + }, + /// (debug) In hộp bao từng ký tự của một trang. + Chars { + input: PathBuf, + #[arg(long, default_value_t = 0)] + page: u16, + #[arg(long)] + password: Option, + }, + /// Liệt kê annotation trong tài liệu. + Annots { input: PathBuf }, +} + +fn main() -> Result<()> { + let cli = Cli::parse(); + let pdfium = ff_engine::bind_pdfium().context("khởi tạo PDFium")?; + + match cli.command { + Command::Info { input, password } => { + let n = ff_engine::page_count(&pdfium, &input, password.as_deref()) + .with_context(|| format!("đọc {}", input.display()))?; + println!("{} trang: {}", input.display(), n); + } + Command::Render { + input, + output, + page, + width, + password, + } => { + let img = ff_engine::render_page_png( + &pdfium, + &input, + page, + &output, + width, + password.as_deref(), + ) + .with_context(|| format!("render {} trang {}", input.display(), page))?; + println!( + "Đã render trang {} ({}x{}px) -> {}", + page, + img.width, + img.height, + output.display() + ); + } + Command::Pages { input, password } => { + let dims = ff_engine::page_dims(&pdfium, &input, password.as_deref()) + .with_context(|| format!("đọc {}", input.display()))?; + for d in &dims { + println!("trang {}: {:.1} x {:.1} pt", d.index, d.width_pt, d.height_pt); + } + println!("tổng: {} trang", dims.len()); + } + Command::Text { + input, + page, + password, + } => { + let t = ff_engine::extract_text(&pdfium, &input, page, password.as_deref()) + .with_context(|| format!("trích text {} trang {}", input.display(), page))?; + println!("{t}"); + } + Command::Search { + input, + query, + case_sensitive, + password, + } => { + let hits = ff_engine::search(&pdfium, &input, &query, case_sensitive, password.as_deref()) + .with_context(|| format!("tìm \"{query}\" trong {}", input.display()))?; + for h in &hits { + match h.rect { + Some(r) => println!( + "trang {} @char {} (len {}) rect [{:.0},{:.0},{:.0},{:.0}]", + h.page_index, h.char_start, h.char_len, r.left, r.bottom, r.right, r.top + ), + None => println!( + "trang {} @char {} (len {})", + h.page_index, h.char_start, h.char_len + ), + } + } + println!("tổng: {} kết quả", hits.len()); + } + Command::Outline { input, password } => { + let items = ff_engine::outline(&pdfium, &input, password.as_deref()) + .with_context(|| format!("đọc outline {}", input.display()))?; + for it in &items { + let p = it + .page_index + .map(|p| format!("-> trang {p}")) + .unwrap_or_else(|| "(không rõ trang)".into()); + println!("{}{} {}", " ".repeat(it.level as usize), it.title, p); + } + println!("tổng: {} mục", items.len()); + } + Command::Chars { + input, + page, + password, + } => { + let boxes = ff_engine::page_char_boxes(&pdfium, &input, page, password.as_deref()) + .with_context(|| format!("char boxes {} trang {}", input.display(), page))?; + for (i, b) in boxes.iter().enumerate() { + println!( + "{i:3} {:?} L{:.1} B{:.1} R{:.1} T{:.1}", + b.ch, b.left, b.bottom, b.right, b.top + ); + } + println!("tổng: {} ký tự", boxes.len()); + } + Command::Annots { input } => { + let items = ff_engine::list_annotations(&pdfium, &input) + .with_context(|| format!("đọc annotation {}", input.display()))?; + for a in &items { + println!( + "trang {} [{}] rect [{:.0},{:.0},{:.0},{:.0}] {}", + a.page_index, + a.kind, + a.rect.left, + a.rect.bottom, + a.rect.right, + a.rect.top, + a.contents.as_deref().unwrap_or("") + ); + } + println!("tổng: {} annotation", items.len()); + } + } + Ok(()) +} diff --git a/crates/ff-cos/Cargo.toml b/crates/ff-cos/Cargo.toml new file mode 100644 index 0000000..3a84de0 --- /dev/null +++ b/crates/ff-cos/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ff-cos" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "FoFreeXit COS layer: low-level PDF object model (dict/array/stream/xref)" + +[dependencies] +thiserror.workspace = true diff --git a/crates/ff-cos/src/lib.rs b/crates/ff-cos/src/lib.rs new file mode 100644 index 0000000..7d11648 --- /dev/null +++ b/crates/ff-cos/src/lib.rs @@ -0,0 +1,10 @@ +//! ff-cos — COS (Carousel Object System) layer. +//! +//! Tầng object thấp của PDF: Object/Dictionary/Array/Stream/Name/Ref/XRef. +//! Tương ứng "Cos layer" của Adobe và QPDF. Hiện là khung trống; sẽ được +//! xây dựng dần từ Phase 3 (ghi file vững) trở đi. Phase 1 chưa cần. +//! +//! Xem docs/04-architecture.md. + +/// Phiên bản đặc tả PDF tối thiểu mà engine nhắm tới. +pub const TARGET_PDF_VERSION: &str = "1.7"; diff --git a/crates/ff-engine/Cargo.toml b/crates/ff-engine/Cargo.toml new file mode 100644 index 0000000..20d4442 --- /dev/null +++ b/crates/ff-engine/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ff-engine" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "FoFreeXit engine: render/edit/io over PDFium + QPDF" + +[dependencies] +ff-cos = { path = "../ff-cos" } +ff-pdmodel = { path = "../ff-pdmodel" } +anyhow.workspace = true +thiserror.workspace = true +pdfium-render = "0.8" +image = "0.25" +lopdf = "0.36" +ttf-parser = "0.25" diff --git a/crates/ff-engine/src/annot.rs b/crates/ff-engine/src/annot.rs new file mode 100644 index 0000000..9a6dca8 --- /dev/null +++ b/crates/ff-engine/src/annot.rs @@ -0,0 +1,808 @@ +//! Annotation (chú thích): tạo/ghi & đọc lại. Phase 2. +//! +//! Dùng PDFium (qua pdfium-render) để tạo annotation rồi lưu ra file mới. +//! Đường GHI file được test round-trip (ghi → mở lại → còn nguyên) vì lưu sai +//! có thể hỏng file người dùng. + +use std::collections::BTreeMap; +use std::path::Path; + +use pdfium_render::prelude::*; + +use crate::text::Rect; +use crate::EngineError; + +/// Loại annotation hỗ trợ ở Phase 2 (mở rộng dần). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AnnotKind { + Highlight, + Underline, + Strikeout, + Square, + /// Hộp văn bản (free text) — `contents` là nội dung hiển thị. + FreeText, + /// Ghi chú dán (sticky note) — `contents` là nội dung popup. + Note, +} + +/// Mô tả một annotation cần tạo. +#[derive(Clone, Debug)] +pub struct AnnotSpec { + pub kind: AnnotKind, + pub page_index: u16, + /// Bao toàn bộ annotation (Square/FreeText/Note dùng trực tiếp; với + /// Highlight/Underline/Strikeout đây là hộp bao toàn bộ — bounds thực tế + /// vẽ ra theo `quads`). + pub rect: Rect, + /// Highlight/Underline/Strikeout theo TEXT thật thường trải nhiều dòng — + /// mỗi dòng là 1 quad riêng (giống Foxit: chọn văn bản nhiều dòng tạo + /// nhiều quad, không phải 1 khối chữ nhật phủ luôn cả khoảng trắng giữa + /// dòng). Rỗng = suy ra 1 quad duy nhất từ `rect` (tương thích cũ). + pub quads: Vec, + /// Màu RGBA (0–255). Với text = màu chữ; markup = màu tô/viền. + pub color: [u8; 4], + pub contents: Option, + /// Định dạng cho FreeText (text box). + pub font_size: f32, + pub bold: bool, + pub italic: bool, + pub underline: bool, +} + +impl AnnotSpec { + /// Giá trị mặc định tiện cho test/markup (không phải text box). `quads` + /// rỗng → 1 quad duy nhất suy ra từ `rect`. + pub fn markup(kind: AnnotKind, page_index: u16, rect: Rect, color: [u8; 4]) -> Self { + AnnotSpec { + kind, + page_index, + rect, + quads: Vec::new(), + color, + contents: None, + font_size: 14.0, + bold: false, + italic: false, + underline: false, + } + } +} + +/// Thông tin một annotation đọc được từ file. +#[derive(Clone, Debug, PartialEq)] +pub struct AnnotInfo { + pub page_index: u16, + pub kind: String, + pub rect: Rect, + pub contents: Option, + /// Số attachment point (quad) — markup nhiều dòng sẽ >1. + pub quad_count: usize, +} + +fn to_pdf_rect(r: &Rect) -> PdfRect { + PdfRect::new( + PdfPoints::new(r.bottom), + PdfPoints::new(r.left), + PdfPoints::new(r.top), + PdfPoints::new(r.right), + ) +} + +/// QuadPoints cho text-markup theo thứ tự PDFium/Acrobat mong đợi: +/// (top-left, top-right, bottom-left, bottom-right). Lưu ý `PdfQuadPoints::from_rect` +/// dùng thứ tự khác (LL,LR,UR,UL) khiến highlight bị xoắn thành sọc mỏng. +fn quad_from_rect(r: &PdfRect) -> PdfQuadPoints { + PdfQuadPoints::new( + r.left(), r.top(), // x1,y1 = top-left + r.right(), r.top(), // x2,y2 = top-right + r.left(), r.bottom(), // x3,y3 = bottom-left + r.right(), r.bottom(), // x4,y4 = bottom-right + ) +} + +fn from_pdf_rect(r: &PdfRect) -> Rect { + Rect { + left: r.left().value, + bottom: r.bottom().value, + right: r.right().value, + top: r.top().value, + } +} + +fn is_text_kind(k: AnnotKind) -> bool { + matches!(k, AnnotKind::FreeText | AnnotKind::Note) +} + +/// Quad thật sự cần vẽ cho markup: dùng `quads` (1 quad/dòng) nếu có, +/// nếu không suy ra 1 quad duy nhất từ `rect` (tương thích spec cũ/đơn giản). +fn effective_quads(spec: &AnnotSpec) -> Vec { + if spec.quads.is_empty() { + vec![to_pdf_rect(&spec.rect)] + } else { + spec.quads.iter().map(to_pdf_rect).collect() + } +} + +/// Hộp bao nhỏ nhất chứa toàn bộ quad — dùng làm `/Rect` của annotation. +fn union_pdf_rect(quads: &[PdfRect]) -> PdfRect { + let mut left = quads[0].left().value; + let mut bottom = quads[0].bottom().value; + let mut right = quads[0].right().value; + let mut top = quads[0].top().value; + for q in &quads[1..] { + left = left.min(q.left().value); + bottom = bottom.min(q.bottom().value); + right = right.max(q.right().value); + top = top.max(q.top().value); + } + PdfRect::new( + PdfPoints::new(bottom), + PdfPoints::new(left), + PdfPoints::new(top), + PdfPoints::new(right), + ) +} + +/// Tạo các annotation theo `specs` rồi lưu sang `output`. Không sửa `input`. +/// +/// - Markup/shape (Highlight/Underline/Strikeout/Square): tạo bằng PDFium. +/// - Text (FreeText/Note): ghi bằng lopdf với /DA + /DR đầy đủ (font, cỡ, màu, +/// đậm/nghiêng) để GIỮ ĐỊNH DẠNG khi lưu — đúng như Foxit. +pub fn apply_annotations( + pdfium: &Pdfium, + input: &Path, + output: &Path, + specs: &[AnnotSpec], +) -> Result<(), EngineError> { + // ----- Pass 1: PDFium tạo markup/shape, luôn ghi ra `output` (kể cả copy) ----- + { + let document = pdfium + .load_pdf_from_file(input, None) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + + let mut by_page: BTreeMap> = BTreeMap::new(); + for s in specs.iter().filter(|s| !is_text_kind(s.kind)) { + by_page.entry(s.page_index).or_default().push(s); + } + + for (page_index, page_specs) in by_page { + let mut page = document + .pages() + .get(page_index) + .map_err(|e| EngineError::Pdfium(format!("trang {page_index}: {e}")))?; + + for spec in page_specs { + let color = + PdfColor::new(spec.color[0], spec.color[1], spec.color[2], spec.color[3]); + let annots = page.annotations_mut(); + let err = |e: PdfiumError| EngineError::Pdfium(format!("tạo annotation: {e}")); + + // Mỗi quad = 1 dòng văn bản đã chọn (như Foxit: chọn văn bản nhiều + // dòng tạo nhiều quad trong CÙNG 1 annotation, không phải 1 khối + // chữ nhật phủ cả khoảng trắng giữa dòng). `create_*_annotation()` + // trả về kiểu cụ thể khác nhau nên không gộp match-arm được — + // tách riêng từng loại, logic giống nhau. + match spec.kind { + AnnotKind::Highlight => { + let quads = effective_quads(spec); + let bounds = union_pdf_rect(&quads); + let mut a = annots.create_highlight_annotation().map_err(err)?; + a.set_bounds(bounds).map_err(err)?; + for q in &quads { + a.attachment_points_mut() + .create_attachment_point_at_end(quad_from_rect(q)) + .map_err(err)?; + } + a.set_fill_color(color).map_err(err)?; + } + AnnotKind::Underline => { + let quads = effective_quads(spec); + let bounds = union_pdf_rect(&quads); + let mut a = annots.create_underline_annotation().map_err(err)?; + a.set_bounds(bounds).map_err(err)?; + for q in &quads { + a.attachment_points_mut() + .create_attachment_point_at_end(quad_from_rect(q)) + .map_err(err)?; + } + a.set_stroke_color(color).map_err(err)?; + } + AnnotKind::Strikeout => { + let quads = effective_quads(spec); + let bounds = union_pdf_rect(&quads); + let mut a = annots.create_strikeout_annotation().map_err(err)?; + a.set_bounds(bounds).map_err(err)?; + for q in &quads { + a.attachment_points_mut() + .create_attachment_point_at_end(quad_from_rect(q)) + .map_err(err)?; + } + a.set_stroke_color(color).map_err(err)?; + } + AnnotKind::Square => { + let rect = to_pdf_rect(&spec.rect); + let mut a = annots.create_square_annotation().map_err(err)?; + a.set_bounds(rect).map_err(err)?; + a.set_stroke_color(color).map_err(err)?; + } + AnnotKind::FreeText | AnnotKind::Note => unreachable!(), + } + } + } + + document + .save_to_file(output) + .map_err(|e| EngineError::Pdfium(format!("lưu file: {e}")))?; + } + + // ----- Pass 2: lopdf ghi FreeText/Note với định dạng đầy đủ ----- + let text: Vec<&AnnotSpec> = specs.iter().filter(|s| is_text_kind(s.kind)).collect(); + if !text.is_empty() { + add_text_annotations(output, &text)?; + } + Ok(()) +} + +// ---- Ghi FreeText/Note bằng lopdf (giữ định dạng qua /DA + /DR) ---- + +use lopdf::{Dictionary, Document as LoDoc, Object as LoObj, ObjectId, StringFormat}; + +// ---- Type1 fonts (dự phòng cho ASCII) ---- + +struct DrFonts { + helv: ObjectId, + bold: ObjectId, + obl: ObjectId, + boldobl: ObjectId, +} + +fn ensure_type1_fonts(doc: &mut LoDoc) -> DrFonts { + let mut mk = |bf: &str| { + let mut d = Dictionary::new(); + d.set("Type", LoObj::Name(b"Font".to_vec())); + d.set("Subtype", LoObj::Name(b"Type1".to_vec())); + d.set("BaseFont", LoObj::Name(bf.as_bytes().to_vec())); + d.set("Encoding", LoObj::Name(b"WinAnsiEncoding".to_vec())); + doc.add_object(LoObj::Dictionary(d)) + }; + DrFonts { + helv: mk("Helvetica"), + bold: mk("Helvetica-Bold"), + obl: mk("Helvetica-Oblique"), + boldobl: mk("Helvetica-BoldOblique"), + } +} + +fn pdf_text_string(s: &str) -> LoObj { + if s.is_ascii() { + LoObj::String(s.as_bytes().to_vec(), StringFormat::Literal) + } else { + // UTF-16BE với BOM 0xFEFF + let mut bytes = vec![0xFE, 0xFF]; + for u in s.encode_utf16() { + bytes.push((u >> 8) as u8); + bytes.push((u & 0xFF) as u8); + } + LoObj::String(bytes, StringFormat::Hexadecimal) + } +} + +// ---- Unicode font (Type0/CIDFontType2) cho tiếng Việt ---- + +/// Tìm file TTF có Unicode trên hệ thống theo đậm/nghiêng (Windows/Linux/Mac). +/// Thử đúng file biến thể (vd `arialbd.ttf`) trước, rồi mới hạ cấp dần về regular +/// của family khác — để FreeText giữ đúng đậm/nghiêng như Foxit. +fn find_font_bytes(bold: bool, italic: bool) -> Option> { + #[cfg(windows)] + { + // [regular, bold, italic, bold-italic] cho từng family phổ biến trên Windows. + const FAMILIES: &[[&str; 4]] = &[ + ["arial.ttf", "arialbd.ttf", "ariali.ttf", "arialbi.ttf"], + ["segoeui.ttf", "segoeuib.ttf", "segoeuii.ttf", "segoeuiz.ttf"], + ["calibri.ttf", "calibrib.ttf", "calibrii.ttf", "calibriz.ttf"], + ["verdana.ttf", "verdanab.ttf", "verdanai.ttf", "verdanaz.ttf"], + ["tahoma.ttf", "tahomabd.ttf", "tahoma.ttf", "tahomabd.ttf"], + ]; + let idx = match (bold, italic) { + (false, false) => 0, + (true, false) => 1, + (false, true) => 2, + (true, true) => 3, + }; + for fam in FAMILIES { + if let Ok(bytes) = std::fs::read(format!(r"C:\Windows\Fonts\{}", fam[idx])) { + return Some(bytes); + } + } + // Không có biến thể đúng → hạ cấp về regular của family đầu tiên có sẵn. + for fam in FAMILIES { + if let Ok(bytes) = std::fs::read(format!(r"C:\Windows\Fonts\{}", fam[0])) { + return Some(bytes); + } + } + None + } + #[cfg(target_os = "macos")] + { + let _ = (bold, italic); + let candidates: &[&str] = &[ + "/System/Library/Fonts/Supplemental/Arial.ttf", + "/Library/Fonts/Arial.ttf", + "/System/Library/Fonts/Helvetica.ttc", + ]; + candidates.iter().find_map(|p| std::fs::read(p).ok()) + } + #[cfg(not(any(windows, target_os = "macos")))] + { + let _ = (bold, italic); + let candidates: &[&str] = &[ + "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", + "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf", + "/usr/share/fonts/TTF/DejaVuSans.ttf", + "/usr/share/fonts/dejavu/DejaVuSans.ttf", + ]; + candidates.iter().find_map(|p| std::fs::read(p).ok()) + } +} + +/// Nhúng TTF vào doc như Type0/CIDFontType2 (Identity-H). `used_text` gồm toàn bộ +/// nội dung sẽ hiển thị bằng font này — dùng để dựng `/W` (độ rộng glyph) đúng; +/// PDF spec quy định widths của Type0/CIDFont LUÔN lấy từ /W + /DW, KHÔNG lấy từ +/// bảng hmtx trong font nhúng — thiếu /W khiến mọi glyph bị coi là rộng /DW (1 em), +/// chữ bị dãn cách quá rộng. Trả về object ID Type0 font. +fn embed_type0_font(doc: &mut LoDoc, font_bytes: &[u8], used_text: &str) -> Result { + let face = ttf_parser::Face::parse(font_bytes, 0) + .map_err(|e| EngineError::Pdfium(format!("ttf-parser: {:?}", e)))?; + + let upem = face.units_per_em() as f32; + let scale = |v: i16| (v as f32 * 1000.0 / upem) as i64; + let bb = face.global_bounding_box(); + + // Độ rộng (1000 units/em) cho mọi glyph thực sự dùng tới, kể cả dấu cách và + // ký tự '?' (dự phòng khi thiếu glyph) — đủ để mọi Tj trong AP stream khớp. + let mut widths: BTreeMap = BTreeMap::new(); + for ch in used_text.chars().chain([' ', '?']) { + let gid = face + .glyph_index(ch) + .unwrap_or_else(|| face.glyph_index('?').unwrap_or(ttf_parser::GlyphId(0))); + let w = face + .glyph_hor_advance(gid) + .map_or(1000, |a| (a as f32 * 1000.0 / upem) as i64); + widths.insert(gid.0, w); + } + let w_array: Vec = widths + .into_iter() + .flat_map(|(gid, w)| vec![LoObj::Integer(gid as i64), LoObj::Array(vec![LoObj::Integer(w)])]) + .collect(); + + // 1. Font file stream (CIDFontType2 dùng /FontFile2) + let mut fs_dict = Dictionary::new(); + fs_dict.set("Length1", LoObj::Integer(font_bytes.len() as i64)); + let font_file_id = doc.add_object(LoObj::Stream(lopdf::Stream::new( + fs_dict, + font_bytes.to_vec(), + ))); + + // 2. FontDescriptor + let mut fd = Dictionary::new(); + fd.set("Type", LoObj::Name(b"FontDescriptor".to_vec())); + fd.set("FontName", LoObj::Name(b"ArialMT".to_vec())); + fd.set("Flags", LoObj::Integer(32)); // Nonsymbolic + fd.set("Ascent", LoObj::Integer(scale(face.ascender()))); + fd.set("Descent", LoObj::Integer(scale(face.descender()))); + fd.set("CapHeight", LoObj::Integer(scale(face.ascender()) * 7 / 10)); + fd.set("StemV", LoObj::Integer(80)); + fd.set("ItalicAngle", LoObj::Integer(0)); + fd.set( + "FontBBox", + LoObj::Array(vec![ + LoObj::Integer(scale(bb.x_min)), + LoObj::Integer(scale(bb.y_min)), + LoObj::Integer(scale(bb.x_max)), + LoObj::Integer(scale(bb.y_max)), + ]), + ); + fd.set("FontFile2", LoObj::Reference(font_file_id)); + let fd_id = doc.add_object(LoObj::Dictionary(fd)); + + // 3. CIDFont (CIDFontType2 = TrueType) + let mut cidfont = Dictionary::new(); + cidfont.set("Type", LoObj::Name(b"Font".to_vec())); + cidfont.set("Subtype", LoObj::Name(b"CIDFontType2".to_vec())); + cidfont.set("BaseFont", LoObj::Name(b"ArialMT".to_vec())); + let mut cidsys = Dictionary::new(); + cidsys.set("Registry", LoObj::String(b"Adobe".to_vec(), StringFormat::Literal)); + cidsys.set("Ordering", LoObj::String(b"Identity".to_vec(), StringFormat::Literal)); + cidsys.set("Supplement", LoObj::Integer(0)); + cidfont.set("CIDSystemInfo", LoObj::Dictionary(cidsys)); + cidfont.set("FontDescriptor", LoObj::Reference(fd_id)); + cidfont.set("DW", LoObj::Integer(1000)); + cidfont.set("W", LoObj::Array(w_array)); + cidfont.set("CIDToGIDMap", LoObj::Name(b"Identity".to_vec())); + let cidfont_id = doc.add_object(LoObj::Dictionary(cidfont)); + + // 4. Type0 wrapper + let mut font0 = Dictionary::new(); + font0.set("Type", LoObj::Name(b"Font".to_vec())); + font0.set("Subtype", LoObj::Name(b"Type0".to_vec())); + font0.set("BaseFont", LoObj::Name(b"ArialMT-Identity-H".to_vec())); + font0.set("Encoding", LoObj::Name(b"Identity-H".to_vec())); + font0.set("DescendantFonts", LoObj::Array(vec![LoObj::Reference(cidfont_id)])); + Ok(doc.add_object(LoObj::Dictionary(font0))) +} + +/// Mã hoá chuỗi thành CID bytes (Identity-H: glyph ID 2 bytes big-endian mỗi char). +fn encode_cid(text: &str, face: &ttf_parser::Face) -> Vec { + let mut out = Vec::with_capacity(text.chars().count() * 2); + for ch in text.chars() { + let gid = face + .glyph_index(ch) + .unwrap_or_else(|| face.glyph_index('?').unwrap_or(ttf_parser::GlyphId(0))); + out.push((gid.0 >> 8) as u8); + out.push((gid.0 & 0xFF) as u8); + } + out +} + +/// Advance width (point) cho một ký tự theo font_size. +fn char_adv(ch: char, face: &ttf_parser::Face, fs: f32) -> f32 { + let upem = face.units_per_em() as f32; + face.glyph_index(ch) + .and_then(|gid| face.glyph_hor_advance(gid)) + .map_or(fs * 0.5, |adv| adv as f32 / upem * fs) +} + +/// Ngắt văn bản thành dòng không vượt quá max_w (pt). +fn wrap_lines(text: &str, face: &ttf_parser::Face, fs: f32, max_w: f32) -> Vec { + let mut lines = Vec::new(); + for para in text.split('\n') { + let words: Vec<&str> = para.split_whitespace().collect(); + if words.is_empty() { + lines.push(String::new()); + continue; + } + let sp = char_adv(' ', face, fs); + let mut cur = String::new(); + let mut cur_w = 0.0f32; + for word in words { + let ww: f32 = word.chars().map(|c| char_adv(c, face, fs)).sum(); + if cur.is_empty() { + cur.push_str(word); + cur_w = ww; + } else if cur_w + sp + ww <= max_w { + cur.push(' '); + cur.push_str(word); + cur_w += sp + ww; + } else { + lines.push(cur); + cur = word.to_string(); + cur_w = ww; + } + } + lines.push(cur); + } + if lines.is_empty() { + lines.push(String::new()); + } + lines +} + +/// Dựng Form XObject (AP /N) cho FreeText với font Unicode. +/// Vẽ nền trắng + viền xám + text nhiều dòng, có word-wrap. +fn build_unicode_ap( + doc: &mut LoDoc, + spec: &AnnotSpec, + font0_id: ObjectId, + font_bytes: &[u8], +) -> Result { + let face = ttf_parser::Face::parse(font_bytes, 0) + .map_err(|e| EngineError::Pdfium(format!("ttf-parser AP: {:?}", e)))?; + + let box_w = spec.rect.right - spec.rect.left; + let box_h = spec.rect.top - spec.rect.bottom; + let fs = spec.font_size; + let upem = face.units_per_em() as f32; + let ascender = face.ascender() as f32 / upem * fs; + let (cr, cg, cb) = ( + spec.color[0] as f32 / 255.0, + spec.color[1] as f32 / 255.0, + spec.color[2] as f32 / 255.0, + ); + + let margin = 2.0f32; + let usable_w = (box_w - margin * 2.0).max(1.0); + let text = spec.contents.as_deref().unwrap_or(""); + let lines = wrap_lines(text, &face, fs, usable_w); + let line_h = fs * 1.2; + let y_start = box_h - margin - ascender; + + // Dựng content stream + let mut cs = String::new(); + // Nền trắng + viền xám + cs.push_str("q\n1 1 1 rg\n"); + cs.push_str(&format!("0 0 {:.2} {:.2} re f\n", box_w, box_h)); + cs.push_str("0.5 0.5 0.5 RG\n0.5 w\n"); + cs.push_str(&format!("0 0 {:.2} {:.2} re S\n", box_w, box_h)); + // Text + cs.push_str("BT\n"); + cs.push_str(&format!("/F0 {:.2} Tf\n", fs)); + cs.push_str(&format!("{:.4} {:.4} {:.4} rg\n", cr, cg, cb)); + cs.push_str(&format!("{:.2} TL\n", line_h)); + cs.push_str(&format!("1 0 0 1 {:.2} {:.2} Tm\n", margin, y_start)); + + for (i, line) in lines.iter().enumerate() { + if i > 0 { + cs.push_str("T*\n"); + } + let cid_bytes = encode_cid(line, &face); + let hex: String = cid_bytes.iter().map(|b| format!("{:02X}", b)).collect(); + cs.push_str(&format!("<{}> Tj\n", hex)); + + // Gạch chân nếu cần (tính từ baseline xuống ~0.1*fs) + if spec.underline && !line.is_empty() { + let line_w: f32 = line.chars().map(|c| char_adv(c, &face, fs)).sum(); + let ul_y = y_start - i as f32 * line_h - fs * 0.1; + cs.push_str("ET\n"); + cs.push_str(&format!("{:.4} {:.4} {:.4} RG\n", cr, cg, cb)); + cs.push_str(&format!("0.5 w\n{:.2} {:.2} m {:.2} {:.2} l S\n", + margin, ul_y, margin + line_w, ul_y)); + cs.push_str("BT\n"); + cs.push_str(&format!("/F0 {:.2} Tf\n", fs)); + cs.push_str(&format!("{:.4} {:.4} {:.4} rg\n", cr, cg, cb)); + cs.push_str(&format!("{:.2} TL\n", line_h)); + cs.push_str(&format!("1 0 0 1 {:.2} {:.2} Tm\n", + margin, y_start - i as f32 * line_h)); + } + } + cs.push_str("ET\nQ\n"); + + let content = cs.into_bytes(); + + // Resources + let mut fr = Dictionary::new(); + fr.set("F0", LoObj::Reference(font0_id)); + let mut res = Dictionary::new(); + res.set("Font", LoObj::Dictionary(fr)); + + // Form XObject + let mut xd = Dictionary::new(); + xd.set("Type", LoObj::Name(b"XObject".to_vec())); + xd.set("Subtype", LoObj::Name(b"Form".to_vec())); + xd.set("FormType", LoObj::Integer(1)); + xd.set( + "BBox", + LoObj::Array(vec![ + LoObj::Real(0.0), LoObj::Real(0.0), + LoObj::Real(box_w), LoObj::Real(box_h), + ]), + ); + xd.set("Resources", LoObj::Dictionary(res)); + xd.set("Length", LoObj::Integer(content.len() as i64)); + Ok(doc.add_object(LoObj::Stream(lopdf::Stream::new(xd, content)))) +} + +// ---- Orchestration ---- + +fn add_text_annotations(path: &Path, specs: &[&AnnotSpec]) -> Result<(), EngineError> { + let mut doc = + LoDoc::load(path).map_err(|e| EngineError::Pdfium(format!("lopdf load: {e}")))?; + + let type1 = ensure_type1_fonts(&mut doc); + + // Nhúng font hệ thống (Type0/CIDFont) cho MỌI FreeText (ASCII lẫn Unicode) — để + // AP stream tự dựng (đo độ rộng glyph từ font thật, hỗ trợ word-wrap & underline + // nhất quán) áp dụng cho tất cả, không chỉ tiếng Việt. Nhúng riêng theo từng tổ + // hợp đậm/nghiêng thực sự dùng tới (đúng biến thể font, vd arialbd.ttf). + let mut combos: BTreeMap<(bool, bool), String> = BTreeMap::new(); + for s in specs.iter().filter(|s| matches!(s.kind, AnnotKind::FreeText)) { + let entry = combos.entry((s.bold, s.italic)).or_default(); + if let Some(c) = &s.contents { + entry.push_str(c); + entry.push('\n'); + } + } + let mut text_fonts: BTreeMap<(bool, bool), (ObjectId, Vec)> = BTreeMap::new(); + for (key, combined) in combos { + if let Some(bytes) = find_font_bytes(key.0, key.1) { + if let Ok(id) = embed_type0_font(&mut doc, &bytes, &combined) { + text_fonts.insert(key, (id, bytes)); + } + } + } + + let pages = doc.get_pages(); + for spec in specs { + let page_id = match pages.get(&(spec.page_index as u32 + 1)) { + Some(id) => *id, + None => continue, + }; + let annot_id = build_text_annot( + &mut doc, + spec, + &type1, + text_fonts + .get(&(spec.bold, spec.italic)) + .map(|(id, b)| (*id, b.as_slice())), + )?; + attach_annot(&mut doc, page_id, annot_id)?; + } + + doc.save(path) + .map_err(|e| EngineError::Pdfium(format!("lopdf save: {e}")))?; + Ok(()) +} + +fn build_text_annot( + doc: &mut LoDoc, + spec: &AnnotSpec, + type1: &DrFonts, + unicode_font: Option<(ObjectId, &[u8])>, +) -> Result { + let r = &spec.rect; + let (cr, cg, cb) = ( + spec.color[0] as f32 / 255.0, + spec.color[1] as f32 / 255.0, + spec.color[2] as f32 / 255.0, + ); + let contents = pdf_text_string(spec.contents.as_deref().unwrap_or("")); + + let mut d = Dictionary::new(); + d.set("Type", LoObj::Name(b"Annot".to_vec())); + + match spec.kind { + AnnotKind::FreeText => { + d.set("Subtype", LoObj::Name(b"FreeText".to_vec())); + d.set( + "Rect", + LoObj::Array(vec![ + LoObj::Real(r.left), + LoObj::Real(r.bottom), + LoObj::Real(r.right), + LoObj::Real(r.top), + ]), + ); + d.set("Contents", contents); + d.set("F", LoObj::Integer(4)); + + // Mọi FreeText (ASCII lẫn Unicode) dùng AP stream tự dựng từ font hệ + // thống thật — đo độ rộng glyph chính xác nên word-wrap & underline + // nhất quán. Chỉ fallback Type1/DA-only khi không tìm được font nào. + if let Some((font0_id, font_bytes)) = unicode_font { + let da = format!("/F0 {:.2} Tf {:.4} {:.4} {:.4} rg", spec.font_size, cr, cg, cb); + let mut dr_font = Dictionary::new(); + dr_font.set("F0", LoObj::Reference(font0_id)); + let mut dr = Dictionary::new(); + dr.set("Font", LoObj::Dictionary(dr_font)); + d.set("DA", LoObj::String(da.into_bytes(), StringFormat::Literal)); + d.set("DR", LoObj::Dictionary(dr)); + + let ap_id = build_unicode_ap(doc, spec, font0_id, font_bytes)?; + let mut ap_dict = Dictionary::new(); + ap_dict.set("N", LoObj::Reference(ap_id)); + d.set("AP", LoObj::Dictionary(ap_dict)); + } else { + set_type1_da(&mut d, spec, type1, cr, cg, cb); + } + } + AnnotKind::Note => { + d.set("Subtype", LoObj::Name(b"Text".to_vec())); + d.set( + "Rect", + LoObj::Array(vec![ + LoObj::Real(r.left), + LoObj::Real(r.top - 18.0), + LoObj::Real(r.left + 18.0), + LoObj::Real(r.top), + ]), + ); + d.set("Contents", contents); + d.set( + "C", + LoObj::Array(vec![LoObj::Real(cr), LoObj::Real(cg), LoObj::Real(cb)]), + ); + d.set("Name", LoObj::Name(b"Note".to_vec())); + d.set("Open", LoObj::Boolean(false)); + } + _ => unreachable!(), + } + Ok(doc.add_object(LoObj::Dictionary(d))) +} + +fn set_type1_da(d: &mut Dictionary, spec: &AnnotSpec, fonts: &DrFonts, cr: f32, cg: f32, cb: f32) { + let (fname, fid) = match (spec.bold, spec.italic) { + (true, true) => ("HeBO", fonts.boldobl), + (true, false) => ("HeBo", fonts.bold), + (false, true) => ("HeOb", fonts.obl), + (false, false) => ("Helv", fonts.helv), + }; + let da = format!("/{} {:.2} Tf {:.4} {:.4} {:.4} rg", fname, spec.font_size, cr, cg, cb); + let mut dr_font = Dictionary::new(); + dr_font.set(fname, LoObj::Reference(fid)); + let mut dr = Dictionary::new(); + dr.set("Font", LoObj::Dictionary(dr_font)); + d.set("DA", LoObj::String(da.into_bytes(), StringFormat::Literal)); + d.set("DR", LoObj::Dictionary(dr)); +} + +enum AnnotsLoc { + Ref(ObjectId), + Inline, + None, +} + +fn attach_annot(doc: &mut LoDoc, page_id: ObjectId, annot_id: ObjectId) -> Result<(), EngineError> { + let loc = { + let page = doc + .get_object(page_id) + .and_then(|o| o.as_dict()) + .map_err(|e| EngineError::Pdfium(format!("đọc page dict: {e}")))?; + match page.get(b"Annots") { + Ok(LoObj::Reference(r)) => AnnotsLoc::Ref(*r), + Ok(LoObj::Array(_)) => AnnotsLoc::Inline, + _ => AnnotsLoc::None, + } + }; + let me = |e: lopdf::Error| EngineError::Pdfium(format!("sửa Annots: {e}")); + match loc { + AnnotsLoc::Ref(rid) => { + let arr = doc.get_object_mut(rid).and_then(|o| o.as_array_mut()).map_err(me)?; + arr.push(LoObj::Reference(annot_id)); + } + AnnotsLoc::Inline => { + let page = doc.get_object_mut(page_id).and_then(|o| o.as_dict_mut()).map_err(me)?; + let arr = page.get_mut(b"Annots").and_then(|o| o.as_array_mut()).map_err(me)?; + arr.push(LoObj::Reference(annot_id)); + } + AnnotsLoc::None => { + let page = doc.get_object_mut(page_id).and_then(|o| o.as_dict_mut()).map_err(me)?; + page.set("Annots", LoObj::Array(vec![LoObj::Reference(annot_id)])); + } + } + Ok(()) +} + +/// Đọc danh sách annotation trong toàn tài liệu. +pub fn list_annotations( + pdfium: &Pdfium, + input: &Path, +) -> Result, EngineError> { + let document = pdfium + .load_pdf_from_file(input, None) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + + let mut out = Vec::new(); + for (pi, page) in document.pages().iter().enumerate() { + for annot in page.annotations().iter() { + let rect = annot.bounds().map(|r| from_pdf_rect(&r)).unwrap_or(Rect { + left: 0.0, + bottom: 0.0, + right: 0.0, + top: 0.0, + }); + out.push(AnnotInfo { + page_index: pi as u16, + kind: format!("{:?}", annot.annotation_type()), + rect, + contents: annot.contents(), + quad_count: annot.attachment_points().len(), + }); + } + } + Ok(out) +} + +/// Đếm số annotation trên một trang. +pub fn count_annotations( + pdfium: &Pdfium, + input: &Path, + page_index: u16, +) -> Result { + let document = pdfium + .load_pdf_from_file(input, None) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + let page = document + .pages() + .get(page_index) + .map_err(|e| EngineError::Pdfium(format!("trang {page_index}: {e}")))?; + Ok(page.annotations().len() as usize) +} diff --git a/crates/ff-engine/src/lib.rs b/crates/ff-engine/src/lib.rs new file mode 100644 index 0000000..714a022 --- /dev/null +++ b/crates/ff-engine/src/lib.rs @@ -0,0 +1,30 @@ +//! ff-engine — engine xử lý PDF của FoFreeXit. +//! +//! Phase 1: bọc PDFium (qua crate `pdfium-render`, tải động `pdfium.dll`) +//! để mở tài liệu, đếm trang và render trang ra ảnh. Các module edit/io/font/ +//! ocr... sẽ thêm dần ở các phase sau (xem docs/03-roadmap.md, 04-architecture.md). + +pub mod annot; +pub mod meta; +pub mod render; +pub mod text; + +pub use annot::{ + apply_annotations, count_annotations, list_annotations, AnnotInfo, AnnotKind, AnnotSpec, +}; +pub use meta::{outline, page_dims, OutlineItem, PageDim}; +pub use render::{bind_pdfium, page_count, render_page_png, PageImage}; +pub use text::{extract_text, page_char_boxes, search, CharBox, Rect, SearchHit}; + +/// Lỗi cấp engine. +#[derive(Debug, thiserror::Error)] +pub enum EngineError { + #[error("không tìm thấy thư viện PDFium. Đặt biến môi trường FOFREEXIT_PDFIUM_PATH trỏ tới thư mục chứa pdfium.dll, hoặc chạy `scripts/fetch-pdfium`. Chi tiết: {0}")] + PdfiumNotFound(String), + + #[error("lỗi PDFium: {0}")] + Pdfium(String), + + #[error(transparent)] + Io(#[from] std::io::Error), +} diff --git a/crates/ff-engine/src/meta.rs b/crates/ff-engine/src/meta.rs new file mode 100644 index 0000000..22c6943 --- /dev/null +++ b/crates/ff-engine/src/meta.rs @@ -0,0 +1,72 @@ +//! Metadata tài liệu: kích thước trang & outline (bookmarks). + +use std::path::Path; + +use pdfium_render::prelude::*; + +use crate::EngineError; + +/// Kích thước một trang theo điểm PDF (points, 1/72 inch). +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct PageDim { + pub index: u16, + pub width_pt: f32, + pub height_pt: f32, +} + +/// Một mục trong outline (bookmark). +#[derive(Debug, Clone, PartialEq)] +pub struct OutlineItem { + pub title: String, + /// Trang đích (0-based) nếu xác định được. + pub page_index: Option, + /// Độ sâu trong cây outline (0 = cấp cao nhất). + pub level: u32, +} + +/// Lấy kích thước mọi trang. +pub fn page_dims( + pdfium: &Pdfium, + input: &Path, + password: Option<&str>, +) -> Result, EngineError> { + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + + let mut dims = Vec::new(); + for (i, page) in document.pages().iter().enumerate() { + dims.push(PageDim { + index: i as u16, + width_pt: page.width().value, + height_pt: page.height().value, + }); + } + Ok(dims) +} + +/// Lấy outline (bookmarks) dạng phẳng theo thứ tự duyệt sâu (DFS). +pub fn outline( + pdfium: &Pdfium, + input: &Path, + password: Option<&str>, +) -> Result, EngineError> { + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + + let mut items = Vec::new(); + for bookmark in document.bookmarks().iter() { + let title = bookmark.title().unwrap_or_default(); + let page_index = bookmark + .destination() + .and_then(|dest| dest.page_index().ok()) + .map(|idx| idx as u16); + items.push(OutlineItem { + title, + page_index, + level: 0, + }); + } + Ok(items) +} diff --git a/crates/ff-engine/src/render.rs b/crates/ff-engine/src/render.rs new file mode 100644 index 0000000..1728ead --- /dev/null +++ b/crates/ff-engine/src/render.rs @@ -0,0 +1,111 @@ +//! Render PDF qua PDFium (tải động pdfium.dll qua pdfium-render). + +use std::path::{Path, PathBuf}; + +use pdfium_render::prelude::*; + +use crate::EngineError; + +/// Ảnh một trang đã render (RGBA8). +pub struct PageImage { + pub width: u32, + pub height: u32, + pub image: image::DynamicImage, +} + +/// Khởi tạo PDFium: tìm và nạp thư viện động. +/// +/// Thứ tự tìm: biến môi trường `FOFREEXIT_PDFIUM_PATH` (thư mục chứa lib) → +/// thư mục làm việc hiện tại → thư mục chứa file thực thi → thư viện hệ thống. +pub fn bind_pdfium() -> Result { + let mut tried: Vec = Vec::new(); + + let mut candidates: Vec = Vec::new(); + if let Ok(dir) = std::env::var("FOFREEXIT_PDFIUM_PATH") { + candidates.push(PathBuf::from(dir)); + } + if let Ok(cwd) = std::env::current_dir() { + candidates.push(cwd.clone()); + candidates.push(cwd.join("pdfium")); + } + if let Ok(exe) = std::env::current_exe() { + if let Some(dir) = exe.parent() { + candidates.push(dir.to_path_buf()); + } + } + + for dir in candidates { + let lib = Pdfium::pdfium_platform_library_name_at_path(&dir); + match Pdfium::bind_to_library(&lib) { + Ok(bindings) => return Ok(Pdfium::new(bindings)), + Err(e) => tried.push(format!("{} ({e})", lib.display())), + } + } + + // Cuối cùng thử thư viện hệ thống. + match Pdfium::bind_to_system_library() { + Ok(bindings) => Ok(Pdfium::new(bindings)), + Err(e) => { + tried.push(format!("system library ({e})")); + Err(EngineError::PdfiumNotFound(tried.join("; "))) + } + } +} + +/// Đếm số trang của tài liệu. +pub fn page_count(pdfium: &Pdfium, input: &Path, password: Option<&str>) -> Result { + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + Ok(document.pages().len()) +} + +/// Render một trang (0-based) ra ảnh với chiều rộng mục tiêu `target_width` px. +pub fn render_page( + pdfium: &Pdfium, + input: &Path, + page_index: u16, + target_width: u32, + password: Option<&str>, +) -> Result { + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + + let page = document + .pages() + .get(page_index) + .map_err(|e| EngineError::Pdfium(format!("không lấy được trang {page_index}: {e}")))?; + + let config = PdfRenderConfig::new() + .set_target_width(target_width as i32) + .set_maximum_height((target_width as i32) * 4); + + let bitmap = page + .render_with_config(&config) + .map_err(|e| EngineError::Pdfium(format!("render trang {page_index} thất bại: {e}")))?; + + let image = bitmap.as_image(); + Ok(PageImage { + width: image.width(), + height: image.height(), + image, + }) +} + +/// Render một trang và ghi ra file PNG. +pub fn render_page_png( + pdfium: &Pdfium, + input: &Path, + page_index: u16, + output: &Path, + target_width: u32, + password: Option<&str>, +) -> Result { + let rendered = render_page(pdfium, input, page_index, target_width, password)?; + rendered + .image + .save(output) + .map_err(|e| EngineError::Pdfium(format!("ghi PNG thất bại: {e}")))?; + Ok(rendered) +} diff --git a/crates/ff-engine/src/text.rs b/crates/ff-engine/src/text.rs new file mode 100644 index 0000000..1f7a04d --- /dev/null +++ b/crates/ff-engine/src/text.rs @@ -0,0 +1,204 @@ +//! Trích xuất & tìm kiếm text trên trang PDF. + +use std::path::Path; + +use pdfium_render::prelude::*; + +use crate::EngineError; + +/// Hình chữ nhật theo điểm PDF (gốc toạ độ ở góc dưới-trái trang). +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Rect { + pub left: f32, + pub bottom: f32, + pub right: f32, + pub top: f32, +} + +/// Một kết quả tìm kiếm. +#[derive(Debug, Clone, PartialEq)] +pub struct SearchHit { + pub page_index: u16, + /// Vị trí ký tự bắt đầu trong text của trang. + pub char_start: usize, + /// Số ký tự khớp. + pub char_len: usize, + /// Khung bao (hợp của các ký tự khớp). Có thể None nếu không lấy được bounds. + pub rect: Option, +} + +/// Hộp bao một ký tự trên trang (cho text-layer / selection). +#[derive(Debug, Clone, PartialEq)] +pub struct CharBox { + /// Ký tự (chuỗi để xử lý cả ký tự ngoài BMP / không có glyph). + pub ch: String, + pub left: f32, + pub bottom: f32, + pub right: f32, + pub top: f32, +} + +/// Lấy hộp bao từng ký tự của một trang, theo thứ tự đọc (giống `extract_text`). +/// Dùng để dựng "text layer" cho phép chọn & copy text trên ảnh render. +pub fn page_char_boxes( + pdfium: &Pdfium, + input: &Path, + page_index: u16, + password: Option<&str>, +) -> Result, EngineError> { + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + let page = document + .pages() + .get(page_index) + .map_err(|e| EngineError::Pdfium(format!("trang {page_index}: {e}")))?; + let text = page + .text() + .map_err(|e| EngineError::Pdfium(format!("đọc text trang {page_index}: {e}")))?; + + let mut boxes: Vec = Vec::new(); + for ch in text.chars().iter() { + let s = ch + .unicode_char() + .map(|c| c.to_string()) + .unwrap_or_default(); + + // Ưu tiên loose_bounds (gồm advance/khoảng cách) cho ký tự như dấu cách. + let bounds = ch.loose_bounds().or_else(|_| ch.tight_bounds()).ok(); + let bx = match bounds { + Some(b) => CharBox { + ch: s, + left: b.left().value, + bottom: b.bottom().value, + right: b.right().value, + top: b.top().value, + }, + None => { + // Không có hộp (vd. dấu cách ở vài file): suy ra hộp mảnh ngay sau + // ký tự trước để giữ thứ tự & vị trí hợp lý cho selection. + let prev = boxes.last(); + let (l, b, r, t) = match prev { + Some(p) => { + let h = (p.top - p.bottom).max(6.0); + (p.right, p.bottom, p.right + h * 0.3, p.top) + } + None => (0.0, 0.0, 0.0, 0.0), + }; + CharBox { ch: s, left: l, bottom: b, right: r, top: t } + } + }; + boxes.push(bx); + } + Ok(boxes) +} + +/// Trích toàn bộ text của một trang. +pub fn extract_text( + pdfium: &Pdfium, + input: &Path, + page_index: u16, + password: Option<&str>, +) -> Result { + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + let page = document + .pages() + .get(page_index) + .map_err(|e| EngineError::Pdfium(format!("trang {page_index}: {e}")))?; + let text = page + .text() + .map_err(|e| EngineError::Pdfium(format!("đọc text trang {page_index}: {e}")))?; + Ok(text.all()) +} + +/// Tìm `query` trong toàn tài liệu. `case_sensitive=false` -> không phân biệt hoa thường. +pub fn search( + pdfium: &Pdfium, + input: &Path, + query: &str, + case_sensitive: bool, + password: Option<&str>, +) -> Result, EngineError> { + if query.is_empty() { + return Ok(Vec::new()); + } + let document = pdfium + .load_pdf_from_file(input, password) + .map_err(|e| EngineError::Pdfium(e.to_string()))?; + + let needle: Vec = query + .chars() + .map(|c| fold(c, case_sensitive)) + .collect(); + + let mut hits = Vec::new(); + for (pi, page) in document.pages().iter().enumerate() { + let text = match page.text() { + Ok(t) => t, + Err(_) => continue, + }; + let full = text.all(); + let hay: Vec = full.chars().map(|c| fold(c, case_sensitive)).collect(); + + // Tìm tất cả vị trí khớp (sliding window đơn giản). + if hay.len() < needle.len() { + continue; + } + let mut start = 0usize; + while start + needle.len() <= hay.len() { + if hay[start..start + needle.len()] == needle[..] { + let rect = char_range_rect(&text, start, needle.len()); + hits.push(SearchHit { + page_index: pi as u16, + char_start: start, + char_len: needle.len(), + rect, + }); + start += needle.len(); + } else { + start += 1; + } + } + } + Ok(hits) +} + +fn fold(c: char, case_sensitive: bool) -> char { + if case_sensitive { + c + } else { + // Hạ thường đơn giản; với ASCII là đủ, Unicode dùng to_lowercase ký tự đầu. + c.to_lowercase().next().unwrap_or(c) + } +} + +/// Khung bao hợp của các ký tự [start, start+len) trên trang. +fn char_range_rect(text: &PdfPageText, start: usize, len: usize) -> Option { + let mut acc: Option = None; + for ch in text.chars().iter() { + let idx = ch.index(); + if idx < start || idx >= start + len { + continue; + } + if let Ok(b) = ch.tight_bounds() { + let r = Rect { + left: b.left().value, + bottom: b.bottom().value, + right: b.right().value, + top: b.top().value, + }; + acc = Some(match acc { + None => r, + Some(a) => Rect { + left: a.left.min(r.left), + bottom: a.bottom.min(r.bottom), + right: a.right.max(r.right), + top: a.top.max(r.top), + }, + }); + } + } + acc +} diff --git a/crates/ff-engine/tests/annot_roundtrip.rs b/crates/ff-engine/tests/annot_roundtrip.rs new file mode 100644 index 0000000..e26eb13 --- /dev/null +++ b/crates/ff-engine/tests/annot_roundtrip.rs @@ -0,0 +1,362 @@ +//! Round-trip test cho annotation (đường GHI file — phần rủi ro nhất Phase 2): +//! tạo annotation → lưu file mới → mở lại → còn đúng số lượng/loại → render ra +//! đúng màu. Dùng sample-multipage.pdf. + +use std::path::PathBuf; + +use ff_engine::{AnnotKind, AnnotSpec, Rect}; + +fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .canonicalize() + .expect("workspace root") +} + +fn pdfium() -> pdfium_render::prelude::Pdfium { + if std::env::var("FOFREEXIT_PDFIUM_PATH").is_err() { + std::env::set_var("FOFREEXIT_PDFIUM_PATH", workspace_root()); + } + ff_engine::bind_pdfium().expect("nạp PDFium") +} + +#[test] +fn highlight_and_square_roundtrip() { + let pdf = pdfium(); + let input = workspace_root().join("corpus").join("sample-multipage.pdf"); + let output = std::env::temp_dir().join("ff_annot_roundtrip.pdf"); + let _ = std::fs::remove_file(&output); + + // Highlight vàng phủ từ "content" ở trang 0 (toạ độ đã biết từ test search), + // và một khung vuông đỏ ở trang 1. + let specs = vec![ + AnnotSpec::markup( + AnnotKind::Highlight, + 0, + Rect { left: 155.0, bottom: 690.0, right: 213.0, top: 706.0 }, + [255, 255, 0, 255], + ), + AnnotSpec::markup( + AnnotKind::Square, + 1, + Rect { left: 100.0, bottom: 600.0, right: 300.0, top: 700.0 }, + [255, 0, 0, 255], + ), + ]; + + ff_engine::apply_annotations(&pdf, &input, &output, &specs).expect("apply_annotations"); + assert!(output.exists(), "file output chưa được tạo"); + + // Mở lại: đúng số lượng. + assert_eq!( + ff_engine::count_annotations(&pdf, &output, 0).expect("count p0"), + 1, + "trang 0 phải có 1 annotation" + ); + assert_eq!( + ff_engine::count_annotations(&pdf, &output, 1).expect("count p1"), + 1, + "trang 1 phải có 1 annotation" + ); + + // Đúng loại + contents giữ lại. + let list = ff_engine::list_annotations(&pdf, &output).expect("list"); + assert_eq!(list.len(), 2, "tổng phải 2 annotation: {list:?}"); + let kinds: Vec<&str> = list.iter().map(|a| a.kind.as_str()).collect(); + assert!(kinds.iter().any(|k| k.contains("Highlight")), "thiếu Highlight: {kinds:?}"); + assert!(kinds.iter().any(|k| k.contains("Square")), "thiếu Square: {kinds:?}"); + + // Render trang 0 (có annotation) -> phải có pixel vàng (highlight). + let img = ff_engine::render::render_page(&pdf, &output, 0, 800, None).expect("render"); + let rgba = img.image.to_rgba8(); + let yellow = rgba + .pixels() + .filter(|p| p.0[0] > 200 && p.0[1] > 200 && p.0[2] < 120) + .count(); + assert!(yellow > 50, "không thấy highlight vàng được render ({yellow} px)"); +} + +/// Highlight phải bám theo TỪNG DÒNG văn bản (như chọn text rồi tô sáng trong +/// Foxit), không phải 1 khối chữ nhật phủ luôn khoảng trắng giữa 2 dòng. +/// Dùng 2 quad cho 2 dòng "FoFreeXit Test Document" (y≈716-736) và "Page one +/// content alpha" (y≈690-706) — khoảng trống giữa 2 dòng (y≈707-715) phải +/// KHÔNG bị tô vàng. +#[test] +fn multiline_highlight_uses_per_line_quads() { + let pdf = pdfium(); + let input = workspace_root().join("corpus").join("sample-multipage.pdf"); + let output = std::env::temp_dir().join("ff_annot_multiline_hl.pdf"); + let _ = std::fs::remove_file(&output); + + let line1 = Rect { left: 72.0, bottom: 716.0, right: 280.0, top: 736.0 }; + let line2 = Rect { left: 72.0, bottom: 690.0, right: 280.0, top: 706.0 }; + let bounds = Rect { left: 72.0, bottom: 690.0, right: 280.0, top: 736.0 }; + let spec = AnnotSpec { + kind: AnnotKind::Highlight, + page_index: 0, + rect: bounds, + quads: vec![line1, line2], + color: [255, 255, 0, 255], + contents: None, + font_size: 14.0, + bold: false, + italic: false, + underline: false, + }; + ff_engine::apply_annotations(&pdf, &input, &output, &[spec]).expect("apply"); + + let list = ff_engine::list_annotations(&pdf, &output).expect("list"); + assert_eq!(list.len(), 1, "phải đúng 1 annotation: {list:?}"); + assert_eq!( + list[0].quad_count, 2, + "highlight 2 dòng phải có 2 quad (attachment points): {:?}", list[0] + ); + + // Render & kiểm 2 dải có vàng, dải trống giữa 2 dòng thì không. + let img = ff_engine::render::render_page(&pdf, &output, 0, 800, None).expect("render"); + let rgba = img.image.to_rgba8(); + let (iw, ih) = rgba.dimensions(); + let scale = 800.0 / 612.0f32; + let is_yellow = |x: u32, y: u32| { + let p = rgba.get_pixel(x.min(iw - 1), y.min(ih - 1)); + p.0[0] > 200 && p.0[1] > 200 && p.0[2] < 150 + }; + let count_band = |top_pt: f32, bot_pt: f32| -> u32 { + let y0 = ((792.0 - top_pt) * scale) as u32; + let y1 = ((792.0 - bot_pt) * scale) as u32; + let x0 = (72.0 * scale) as u32; + let x1 = (280.0 * scale) as u32; + (y0..=y1).flat_map(|y| (x0..=x1).map(move |x| (x, y))).filter(|&(x, y)| is_yellow(x, y)).count() as u32 + }; + + let band_line1 = count_band(736.0, 716.0); + let band_line2 = count_band(706.0, 690.0); + let band_gap = count_band(715.0, 707.0); // khoảng trống giữa 2 dòng + + assert!(band_line1 > 50, "dòng 1 không có pixel vàng ({band_line1}px)"); + assert!(band_line2 > 50, "dòng 2 không có pixel vàng ({band_line2}px)"); + assert!( + band_gap < band_line1.min(band_line2) / 4, + "khoảng trống giữa 2 dòng bị tô vàng như 1 khối liền ({band_gap}px so với dòng1={band_line1}px, dòng2={band_line2}px) — highlight đang phủ cả khoảng trắng, không bám theo dòng" + ); +} + +#[test] +fn underline_and_strikeout_roundtrip() { + let pdf = pdfium(); + let input = workspace_root().join("corpus").join("sample-multipage.pdf"); + let output = std::env::temp_dir().join("ff_annot_markup.pdf"); + let _ = std::fs::remove_file(&output); + + let specs = vec![ + AnnotSpec::markup( + AnnotKind::Underline, + 0, + Rect { left: 155.0, bottom: 690.0, right: 213.0, top: 706.0 }, + [0, 0, 255, 255], + ), + AnnotSpec::markup( + AnnotKind::Strikeout, + 0, + Rect { left: 72.0, bottom: 716.0, right: 151.0, top: 736.0 }, + [255, 0, 0, 255], + ), + ]; + ff_engine::apply_annotations(&pdf, &input, &output, &specs).expect("apply"); + + let list = ff_engine::list_annotations(&pdf, &output).expect("list"); + let kinds: Vec<&str> = list.iter().map(|a| a.kind.as_str()).collect(); + assert!(kinds.iter().any(|k| k.contains("Underline")), "thiếu Underline: {kinds:?}"); + assert!(kinds.iter().any(|k| k.contains("Strikeout")), "thiếu Strikeout: {kinds:?}"); + + // Render được, không trắng trơn (có nét màu của underline/strikeout). + let img = ff_engine::render::render_page(&pdf, &output, 0, 800, None).expect("render"); + let colored = img + .image + .to_rgba8() + .pixels() + .filter(|p| (p.0[2] > 180 && p.0[0] < 100) || (p.0[0] > 180 && p.0[1] < 100 && p.0[2] < 100)) + .count(); + assert!(colored > 20, "không thấy nét màu underline/strikeout ({colored} px)"); +} + +#[test] +fn freetext_and_note_roundtrip() { + let pdf = pdfium(); + let input = workspace_root().join("corpus").join("sample-multipage.pdf"); + let output = std::env::temp_dir().join("ff_annot_text.pdf"); + let _ = std::fs::remove_file(&output); + + // FreeText màu xanh, cỡ 22, đậm (ASCII để kiểm định dạng render được); + // Note nội dung tiếng Việt (kiểm round-trip UTF-16). + let specs = vec![ + AnnotSpec { + kind: AnnotKind::FreeText, + page_index: 0, + rect: Rect { left: 90.0, bottom: 560.0, right: 360.0, top: 620.0 }, + quads: vec![], + color: [0, 0, 255, 255], + contents: Some("Hello 22 blue".into()), + font_size: 22.0, + bold: true, + italic: false, + underline: false, + }, + AnnotSpec { + kind: AnnotKind::Note, + page_index: 0, + rect: Rect { left: 400.0, bottom: 600.0, right: 418.0, top: 618.0 }, + quads: vec![], + color: [255, 200, 0, 255], + contents: Some("ghi chú dán tiếng Việt".into()), + font_size: 14.0, + bold: false, + italic: false, + underline: false, + }, + ]; + ff_engine::apply_annotations(&pdf, &input, &output, &specs).expect("apply"); + + let list = ff_engine::list_annotations(&pdf, &output).expect("list"); + let kinds: Vec<&str> = list.iter().map(|a| a.kind.as_str()).collect(); + assert!(kinds.iter().any(|k| k.contains("FreeText")), "thiếu FreeText: {kinds:?}"); + assert!(kinds.iter().any(|k| k.contains("Text")), "thiếu Text(note): {kinds:?}"); + // Nội dung được giữ lại (gồm tiếng Việt qua UTF-16). + assert!( + list.iter().any(|a| a.contents.as_deref() == Some("Hello 22 blue")), + "mất contents FreeText: {list:?}" + ); + assert!( + list.iter().any(|a| a.contents.as_deref() == Some("ghi chú dán tiếng Việt")), + "mất contents Note (tiếng Việt): {list:?}" + ); + + // Render trang 0: chữ FreeText màu xanh phải xuất hiện (DA hoạt động). + let img = ff_engine::render::render_page(&pdf, &output, 0, 800, None).expect("render"); + let blue = img + .image + .to_rgba8() + .pixels() + .filter(|p| p.0[2] > 180 && p.0[0] < 90 && p.0[1] < 90) + .count(); + assert!(blue > 40, "không thấy chữ FreeText màu xanh được render ({blue} px)"); +} + +/// Kiểm tra FreeText tiếng Việt render được (font Unicode nhúng + AP stream). +/// Annotation [72, 400, 360, 470] trên trang 612×792pt, render 800px. +#[test] +fn vietnamese_freetext_renders() { + let pdf = pdfium(); + let input = workspace_root().join("corpus").join("sample-multipage.pdf"); + let output = std::env::temp_dir().join("ff_viet_freetext.pdf"); + let _ = std::fs::remove_file(&output); + + let specs = vec![AnnotSpec { + kind: AnnotKind::FreeText, + page_index: 0, + rect: Rect { left: 72.0, bottom: 400.0, right: 360.0, top: 470.0 }, + quads: vec![], + color: [0, 0, 0, 255], // chữ đen để dễ kiểm + contents: Some("Tiếng Việt: thử nghiệm font Unicode".into()), + font_size: 14.0, + bold: false, + italic: false, + underline: false, + }]; + ff_engine::apply_annotations(&pdf, &input, &output, &specs).expect("apply"); + assert!(output.exists(), "không tạo được file"); + + // Kiểm contents vẫn đúng + let list = ff_engine::list_annotations(&pdf, &output).expect("list"); + assert!( + list.iter().any(|a| a.contents.as_deref() == Some("Tiếng Việt: thử nghiệm font Unicode")), + "mất contents tiếng Việt: {list:?}" + ); + + // Render và kiểm có pixels đen trong vùng annotation: + // trang 612×792pt, render 800px → scale ≈ 1.307 + // pixel_y_top = (792 - 470) * scale ≈ 421, pixel_y_bot = (792 - 400) * scale ≈ 513 + // pixel_x_left = 72 * scale ≈ 94, pixel_x_right = 360 * scale ≈ 471 + let img = ff_engine::render::render_page(&pdf, &output, 0, 800, None).expect("render"); + let rgba = img.image.to_rgba8(); + let (iw, ih) = rgba.dimensions(); + let scale = 800.0 / 612.0f32; + let x0 = (72.0 * scale) as u32; + let x1 = (360.0 * scale) as u32; + let y0 = ((792.0 - 470.0) * scale) as u32; + let y1 = ((792.0 - 400.0) * scale) as u32; + let x1 = x1.min(iw - 1); + let y1 = y1.min(ih - 1); + + // Đếm pixels không phải trắng trong vùng annotation + let dark: u32 = (y0..=y1) + .flat_map(|y| (x0..=x1).map(move |x| (x, y))) + .filter(|&(x, y)| { + let p = rgba.get_pixel(x, y); + // pixel tối (nền trắng mà có glyph → lọc non-white) + (p.0[0] as u32 + p.0[1] as u32 + p.0[2] as u32) < 700 + }) + .count() as u32; + + assert!( + dark > 50, + "tiếng Việt không render trong vùng annotation ({dark} dark px trong [{x0},{y0}]-[{x1},{y1}] của {iw}×{ih})" + ); +} + +/// Kiểm underline trong FreeText AP stream tự dựng: so sánh số pixel tối trong +/// vùng annotation giữa bản có underline=true và underline=false — bản có gạch +/// chân phải nhiều pixel tối hơn rõ rệt (thêm 1 đường kẻ ngang dưới chữ). +#[test] +fn freetext_underline_renders() { + let pdf = pdfium(); + let input = workspace_root().join("corpus").join("sample-multipage.pdf"); + + fn count_dark(pdf: &pdfium_render::prelude::Pdfium, path: &std::path::Path) -> u32 { + let img = ff_engine::render::render_page(pdf, path, 0, 800, None).expect("render"); + let rgba = img.image.to_rgba8(); + let (iw, ih) = rgba.dimensions(); + let scale = 800.0 / 612.0f32; + let x0 = (72.0 * scale) as u32; + let x1 = ((300.0 * scale) as u32).min(iw - 1); + let y0 = ((792.0 - 650.0) * scale) as u32; + let y1 = (((792.0 - 600.0) * scale) as u32).min(ih - 1); + (y0..=y1) + .flat_map(|y| (x0..=x1).map(move |x| (x, y))) + .filter(|&(x, y)| { + let p = rgba.get_pixel(x, y); + (p.0[0] as u32 + p.0[1] as u32 + p.0[2] as u32) < 700 + }) + .count() as u32 + } + + let make_spec = |underline: bool| AnnotSpec { + kind: AnnotKind::FreeText, + page_index: 0, + rect: Rect { left: 72.0, bottom: 600.0, right: 300.0, top: 650.0 }, + quads: vec![], + color: [0, 0, 0, 255], + contents: Some("Underline".into()), + font_size: 20.0, + bold: false, + italic: false, + underline, + }; + + let no_ul = std::env::temp_dir().join("ff_freetext_no_underline.pdf"); + let with_ul = std::env::temp_dir().join("ff_freetext_with_underline.pdf"); + let _ = std::fs::remove_file(&no_ul); + let _ = std::fs::remove_file(&with_ul); + + ff_engine::apply_annotations(&pdf, &input, &no_ul, &[make_spec(false)]).expect("apply no-ul"); + ff_engine::apply_annotations(&pdf, &input, &with_ul, &[make_spec(true)]).expect("apply with-ul"); + + let dark_no_ul = count_dark(&pdf, &no_ul); + let dark_with_ul = count_dark(&pdf, &with_ul); + + assert!( + dark_with_ul > dark_no_ul + 50, + "gạch chân không render rõ rệt: no_underline={dark_no_ul}px, with_underline={dark_with_ul}px" + ); +} diff --git a/crates/ff-engine/tests/big_doc.rs b/crates/ff-engine/tests/big_doc.rs new file mode 100644 index 0000000..eeb102a --- /dev/null +++ b/crates/ff-engine/tests/big_doc.rs @@ -0,0 +1,61 @@ +//! Stress test với tài liệu lớn (corpus/big-1000.pdf — 1000 trang). +//! Mỗi trang có text "Trang N"; riêng trang index 500 có thêm "ZZMARKER". + +use std::path::PathBuf; +use std::time::Instant; + +fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .canonicalize() + .expect("workspace root") +} + +fn fixture() -> PathBuf { + workspace_root().join("corpus").join("big-1000.pdf") +} + +fn pdfium() -> pdfium_render::prelude::Pdfium { + if std::env::var("FOFREEXIT_PDFIUM_PATH").is_err() { + std::env::set_var("FOFREEXIT_PDFIUM_PATH", workspace_root()); + } + ff_engine::bind_pdfium().expect("nạp PDFium") +} + +#[test] +fn big_doc_page_count() { + let dims = ff_engine::page_dims(&pdfium(), &fixture(), None).expect("page_dims"); + assert_eq!(dims.len(), 1000, "phải có 1000 trang"); +} + +#[test] +fn big_doc_render_first_and_last() { + let pdf = pdfium(); + for idx in [0u16, 999u16] { + let t = Instant::now(); + let r = ff_engine::render::render_page(&pdf, &fixture(), idx, 600, None) + .unwrap_or_else(|e| panic!("render trang {idx}: {e}")); + let ms = t.elapsed().as_millis(); + // Không trắng trơn. + let dark = r + .image + .to_rgba8() + .pixels() + .filter(|p| p.0[3] > 10 && p.0[0] < 128 && p.0[1] < 128 && p.0[2] < 128) + .count(); + assert!(dark > 100, "trang {idx} trắng trơn ({dark} px tối)"); + // Ngưỡng rộng rãi để bắt hồi quy hiệu năng nghiêm trọng (không phải benchmark). + assert!(ms < 5000, "render trang {idx} quá chậm: {ms} ms"); + } +} + +#[test] +fn big_doc_search_single_marker() { + let t = Instant::now(); + let hits = ff_engine::search(&pdfium(), &fixture(), "ZZMARKER", false, None).expect("search"); + let ms = t.elapsed().as_millis(); + assert_eq!(hits.len(), 1, "ZZMARKER phải có đúng 1 kết quả"); + assert_eq!(hits[0].page_index, 500, "ZZMARKER phải ở trang index 500"); + assert!(ms < 10000, "search toàn tài liệu quá chậm: {ms} ms"); +} diff --git a/crates/ff-engine/tests/render_smoke.rs b/crates/ff-engine/tests/render_smoke.rs new file mode 100644 index 0000000..fe4e812 --- /dev/null +++ b/crates/ff-engine/tests/render_smoke.rs @@ -0,0 +1,62 @@ +//! Smoke test cho pipeline render Phase 1. +//! +//! Dùng golden test "ổn định" (không hash byte vì kết quả render có thể đổi +//! theo phiên bản PDFium): kiểm tra mở được file, đúng số trang, đúng tỉ lệ +//! kích thước, và trang KHÔNG trắng trơn (có pixel tối = đã vẽ nội dung). + +use std::path::PathBuf; + +/// Thư mục gốc workspace (từ crate dir đi lên 2 cấp: crates/ff-engine -> root). +fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .canonicalize() + .expect("canonicalize workspace root") +} + +fn ensure_pdfium_path() { + // Trỏ engine tới pdfium.dll ở gốc workspace (tải bằng scripts/fetch-pdfium.ps1). + if std::env::var("FOFREEXIT_PDFIUM_PATH").is_err() { + std::env::set_var("FOFREEXIT_PDFIUM_PATH", workspace_root()); + } +} + +#[test] +fn renders_hello_sample() { + ensure_pdfium_path(); + let pdfium = ff_engine::bind_pdfium().expect("nạp PDFium (chạy scripts/fetch-pdfium.ps1?)"); + + let pdf = workspace_root().join("corpus").join("hello.pdf"); + assert!(pdf.exists(), "thiếu file mẫu: {}", pdf.display()); + + // Đúng số trang. + let pages = ff_engine::page_count(&pdfium, &pdf, None).expect("đếm trang"); + assert_eq!(pages, 1, "hello.pdf phải có 1 trang"); + + // Render trang 0. + let target_width = 800; + let rendered = ff_engine::render::render_page(&pdfium, &pdf, 0, target_width, None) + .expect("render trang 0"); + + // Đúng chiều rộng mục tiêu. + assert_eq!(rendered.width, target_width, "chiều rộng render sai"); + + // Trang Letter (612x792) -> tỉ lệ cao/rộng ~ 792/612 = 1.294. + let ratio = rendered.height as f32 / rendered.width as f32; + assert!( + (ratio - 792.0 / 612.0).abs() < 0.02, + "tỉ lệ trang sai: {ratio}" + ); + + // Trang phải có nội dung: đếm pixel "tối" (chữ đen trên nền trắng). + let rgba = rendered.image.to_rgba8(); + let dark = rgba + .pixels() + .filter(|p| p.0[3] > 10 && p.0[0] < 128 && p.0[1] < 128 && p.0[2] < 128) + .count(); + assert!( + dark > 200, + "trang gần như trắng trơn (chỉ {dark} pixel tối) -> render hỏng?" + ); +} diff --git a/crates/ff-engine/tests/viewer_features.rs b/crates/ff-engine/tests/viewer_features.rs new file mode 100644 index 0000000..42320c9 --- /dev/null +++ b/crates/ff-engine/tests/viewer_features.rs @@ -0,0 +1,113 @@ +//! Test các năng lực viewer ở tầng engine: kích thước trang, trích text, +//! tìm kiếm, outline. Dựa trên fixture corpus/sample-multipage.pdf có nội dung +//! biết trước: +//! trang 0: "FoFreeXit Test Document" / "Page one content alpha" +//! trang 1: "Page two content beta searchterm" +//! trang 2: "Page three content gamma" +//! outline: Chapter 1/2/3 -> trang 0/1/2 + +use std::path::PathBuf; + +fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .canonicalize() + .expect("workspace root") +} + +fn fixture() -> PathBuf { + workspace_root().join("corpus").join("sample-multipage.pdf") +} + +fn pdfium() -> pdfium_render::prelude::Pdfium { + if std::env::var("FOFREEXIT_PDFIUM_PATH").is_err() { + std::env::set_var("FOFREEXIT_PDFIUM_PATH", workspace_root()); + } + ff_engine::bind_pdfium().expect("nạp PDFium") +} + +#[test] +fn page_dims_letter_3pages() { + let dims = ff_engine::page_dims(&pdfium(), &fixture(), None).expect("page_dims"); + assert_eq!(dims.len(), 3, "phải có 3 trang"); + for d in &dims { + assert!((d.width_pt - 612.0).abs() < 0.5, "rộng sai: {}", d.width_pt); + assert!((d.height_pt - 792.0).abs() < 0.5, "cao sai: {}", d.height_pt); + } +} + +#[test] +fn extract_text_per_page() { + let pdf = pdfium(); + let p0 = ff_engine::extract_text(&pdf, &fixture(), 0, None).expect("text trang 0"); + assert!(p0.contains("FoFreeXit Test Document"), "thiếu tiêu đề: {p0:?}"); + assert!(p0.contains("alpha"), "thiếu 'alpha': {p0:?}"); + + let p1 = ff_engine::extract_text(&pdf, &fixture(), 1, None).expect("text trang 1"); + assert!(p1.contains("searchterm"), "thiếu 'searchterm': {p1:?}"); +} + +#[test] +fn search_counts_and_locations() { + let pdf = pdfium(); + + // "content" xuất hiện 1 lần/trang -> 3 kết quả, ở trang 0,1,2. + let hits = ff_engine::search(&pdf, &fixture(), "content", false, None).expect("search"); + assert_eq!(hits.len(), 3, "'content' phải có 3 kết quả: {hits:?}"); + let pages: Vec = hits.iter().map(|h| h.page_index).collect(); + assert_eq!(pages, vec![0, 1, 2], "vị trí trang sai: {pages:?}"); + + // Ít nhất một kết quả có khung bao (rect) hợp lệ. + assert!( + hits.iter().any(|h| h.rect.is_some()), + "không kết quả nào có rect" + ); + + // "searchterm" chỉ ở trang 1, đúng 1 kết quả. + let st = ff_engine::search(&pdf, &fixture(), "searchterm", false, None).expect("search"); + assert_eq!(st.len(), 1); + assert_eq!(st[0].page_index, 1); +} + +#[test] +fn search_case_sensitivity() { + let pdf = pdfium(); + // Không phân biệt hoa thường: khớp. + let ci = ff_engine::search(&pdf, &fixture(), "SEARCHTERM", false, None).expect("search ci"); + assert_eq!(ci.len(), 1, "case-insensitive phải khớp"); + // Phân biệt hoa thường: không khớp (text gốc là chữ thường). + let cs = ff_engine::search(&pdf, &fixture(), "SEARCHTERM", true, None).expect("search cs"); + assert_eq!(cs.len(), 0, "case-sensitive không được khớp"); +} + +#[test] +fn char_boxes_match_text_and_bounds() { + let boxes = ff_engine::page_char_boxes(&pdfium(), &fixture(), 0, None).expect("char boxes"); + assert!(!boxes.is_empty(), "phải có ký tự"); + + // Ghép ký tự theo thứ tự đọc -> chứa đúng nội dung trang. + let concat: String = boxes.iter().map(|b| b.ch.as_str()).collect(); + assert!(concat.contains("FoFreeXit"), "thiếu 'FoFreeXit': {concat:?}"); + assert!(concat.contains("Document"), "thiếu 'Document'"); + assert!(concat.contains("content"), "thiếu 'content'"); + assert!(concat.contains("alpha"), "thiếu 'alpha'"); + + // Mọi hộp nằm trong khổ trang Letter (612x792), cho dung sai nhỏ. + for b in &boxes { + assert!(b.left >= -1.0 && b.right <= 613.0, "x ngoài trang: {b:?}"); + assert!(b.bottom >= -1.0 && b.top <= 793.0, "y ngoài trang: {b:?}"); + } +} + +#[test] +fn outline_three_chapters() { + let items = ff_engine::outline(&pdfium(), &fixture(), None).expect("outline"); + assert_eq!(items.len(), 3, "phải có 3 mục outline: {items:?}"); + assert_eq!(items[0].title, "Chapter 1"); + assert_eq!(items[1].title, "Chapter 2"); + assert_eq!(items[2].title, "Chapter 3"); + assert_eq!(items[0].page_index, Some(0)); + assert_eq!(items[1].page_index, Some(1)); + assert_eq!(items[2].page_index, Some(2)); +} diff --git a/crates/ff-pdmodel/Cargo.toml b/crates/ff-pdmodel/Cargo.toml new file mode 100644 index 0000000..08646d5 --- /dev/null +++ b/crates/ff-pdmodel/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "ff-pdmodel" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "FoFreeXit PD layer: high-level document model (page/text/image/annotation)" + +[dependencies] +ff-cos = { path = "../ff-cos" } +thiserror.workspace = true diff --git a/crates/ff-pdmodel/src/lib.rs b/crates/ff-pdmodel/src/lib.rs new file mode 100644 index 0000000..ef33c64 --- /dev/null +++ b/crates/ff-pdmodel/src/lib.rs @@ -0,0 +1,14 @@ +//! ff-pdmodel — PD (Page Description) layer. +//! +//! Tầng tài liệu cao: Document/Page/Resources/ContentStream/TextRun/ +//! ImageObject/Annotation/AcroForm... Tương ứng "PD layer" của Adobe. +//! Khung trống ở Phase 1; phát triển từ Phase 2 (annotation) trở đi. +//! +//! Xem docs/04-architecture.md. + +/// Kích thước trang theo điểm (points, 1/72 inch). +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct PageSize { + pub width: f32, + pub height: f32, +} diff --git a/docs/01-research.md b/docs/01-research.md new file mode 100644 index 0000000..27166d8 --- /dev/null +++ b/docs/01-research.md @@ -0,0 +1,157 @@ +# 01 — Nghiên cứu: Tính năng, Khó khăn, Thuật toán, Thư viện + +## A. Tính năng của Foxit PDF Editor + +Foxit có 3 dòng: **PDF Editor**, **PDF Editor Pro**, **PDF Editor Pro+** (subscription, kèm AI/cloud). +Giá tham khảo (2025–2026): subscription từ ~$11.99/tháng; **lifetime/perpetual ~$159–$210**; Pro+ chỉ bán subscription. Enterprise báo giá riêng. + +### Nhóm tính năng (theo mức độ quan trọng với người dùng) + +#### 1. Xem & điều hướng (View) — *table stakes, miễn phí ở mọi reader* +- Render PDF chính xác, mượt; zoom, fit, thumbnails, bookmarks/outline, search full-text. +- Continuous scroll, two-page, reading mode, dark mode. +- Mở file lớn nhanh (lazy load từng trang). + +#### 2. Chú thích (Annotate / Comment) — *quan trọng, dùng hằng ngày* +- Highlight, underline, strikethrough, squiggly. +- Sticky notes, text box, callout, stamp, drawing (pencil/shapes), measure. +- Reply/threads cho comment, import/export annotation (FDF/XFDF). + +#### 3. **Chỉnh sửa nội dung (Edit) — TÍNH NĂNG "ĐÁNG TIỀN" SỐ 1** ⭐ +- **Sửa text trực tiếp** trên trang (reflow trong đoạn, đổi font/size/màu). +- Thêm/xoá/di chuyển/đổi kích thước **ảnh** và **đối tượng** (object). +- Edit cả paragraph, link/unlink text box, OCR rồi sửa text trên ảnh scan. +- Đây là rào cản kỹ thuật lớn nhất và là lý do chính người dùng trả tiền — các reader miễn phí (đa số) **không** làm được. + +#### 4. Tổ chức trang (Organize) — *quan trọng, đáng tiền* +- Chèn/xoá/xoay/trích/thay/đảo trang, **merge & split**, crop, đánh số, header/footer, watermark, background. +- Sắp xếp kéo-thả thumbnail. + +#### 5. Chuyển đổi (Convert) — *rất đáng tiền* ⭐ +- PDF ↔ Word/Excel/PowerPoint, PDF → ảnh, ảnh/Office → PDF. +- Chất lượng chuyển đổi (giữ layout) là điểm bán hàng then chốt. + +#### 6. **OCR** — *rất đáng tiền* ⭐ +- Nhận dạng text trên scan (đa ngôn ngữ), tạo "searchable PDF". +- Foxit 2025.2 quảng cáo OCR vượt Adobe ở chữ số/checkbox/handwriting. + +#### 7. Form (AcroForm / XFA) — *đáng tiền với doanh nghiệp* +- Điền form, **tạo form** (text field, checkbox, radio, dropdown, button), nhận dạng field tự động, import/export dữ liệu form. + +#### 8. Bảo mật & chữ ký — *đáng tiền với doanh nghiệp* ⭐ +- Mật khẩu (mở/permission), **mã hoá AES**, redaction (bôi đen vĩnh viễn), xoá metadata ẩn. +- **Chữ ký số** (digital signature/PKI), chứng thực, timestamp; **eSign** (cloud). + +#### 9. So sánh & cộng tác +- Compare 2 phiên bản PDF, shared review, cloud collaboration (Pro+). + +#### 10. AI (Pro+) — *xu hướng mới* +- Tóm tắt, hỏi-đáp tài liệu, dịch, chat với PDF. + +### ➜ Kết luận: Tính năng khiến người dùng phải mua license +Theo thứ tự "moat" (khó làm + người dùng sẵn sàng trả tiền): +1. **Edit text/object trực tiếp** (rào cản kỹ thuật cao nhất). +2. **Convert PDF→Office giữ layout** (Word/Excel). +3. **OCR** chất lượng cao, đa ngôn ngữ. +4. **Bảo mật**: redaction thật, mã hoá, chữ ký số. +5. **Tạo & xử lý form** (AcroForm). +6. **Organize**: merge/split/crop hàng loạt. + +> Chiến lược FoFreeXit: chiếm các tính năng (1), (4), (6), (organize) trước — vốn có thể tự làm tốt trên nền engine mở. (2) Convert và (3) OCR sẽ tận dụng dự án mở khác (LibreOffice headless, Tesseract). AI để sau cùng. + +--- + +## B. Khó khăn kỹ thuật (xếp theo độ khó) + +### B1. Bản chất định dạng PDF +- PDF **không phải định dạng để chỉnh sửa**: nó mô tả "vẽ gì ở toạ độ nào", không lưu cấu trúc đoạn/dòng/bảng như Word. Text là chuỗi lệnh `Tj/TJ` đặt glyph theo toạ độ → **không có khái niệm "đoạn văn"**. +- Đặc tả PDF (ISO 32000) cực lớn; vô số file "hợp lệ một phần", file hỏng, file sinh bởi công cụ lạ → cần **độ bền (robustness)** rất cao. + +### B2. Sửa text trực tiếp (khó nhất) ⭐ +- Phải **tái dựng dòng/đoạn** từ các glyph rời rạc (gom theo toạ độ, baseline, khoảng cách) → suy ra "text run". +- Khi sửa: cần **đo lại chiều rộng glyph** theo font thật, **reflow** phần còn lại của dòng/đoạn, xử lý ligature, kerning, justification. +- **Font**: file có thể nhúng font subset (chỉ chứa glyph đã dùng) → muốn gõ ký tự mới phải có glyph đó; nếu không, phải **substitute font** giống nhất rồi nhúng/subset lại. Encoding phức tạp (CID, CMap, Type0, Type3). +- Văn bản phức tạp: RTL (Ả Rập/Do Thái), chữ Đông Á (CJK), **tiếng Việt dấu** (tổ hợp dấu), shaping (HarfBuzz). + +### B3. Render chính xác +- Render giống Acrobat: blend modes, transparency groups, soft mask, shading/gradient, pattern, overprint, ICC color management, CMYK. +- Hiệu năng: file hàng nghìn trang, ảnh độ phân giải cao → cần cache, tile, đa luồng, GPU (tuỳ chọn). + +### B4. OCR +- Tích hợp engine (Tesseract), tiền xử lý ảnh (deskew, denoise, binarize), bố cục (layout analysis), khớp toạ độ text vào trang để tạo lớp text vô hình → searchable PDF. + +### B5. Convert PDF → Office +- "Bài toán ngược": từ glyph dựng lại đoạn/bảng/cột/heading của Word. **Rất khó giữ layout**. Đây là nơi cả Adobe lẫn Foxit đều chưa hoàn hảo. + +### B6. Bảo mật làm đúng +- **Redaction**: phải **xoá thật** nội dung khỏi content stream + metadata + ảnh, không chỉ vẽ hộp đen lên trên (lỗi này từng làm lộ tài liệu chính phủ). +- Mã hoá RC4/AES, permission, public-key security handler; **chữ ký số** đúng chuẩn PAdES (byte range, /ByteRange, incremental update không phá chữ ký cũ). + +### B7. Ghi file an toàn +- **Incremental update** (ghi thêm cuối file, giữ chữ ký) vs **full rewrite** (gọn, tối ưu). Cần xử lý xref/xref-stream, object stream, linearization ("fast web view"). +- Không làm hỏng file gốc; undo/redo cho thao tác sửa. + +### B8. UX desktop chất lượng cao +- Tương tác mượt (chọn text qua nhiều trang, kéo object), đa nền tảng, in ấn đúng, accessibility, đa ngôn ngữ UI. + +--- + +## C. Thuật toán & kiến trúc của Foxit / Adobe (học hỏi được gì) + +> Foxit & Adobe là mã đóng; dưới đây là suy luận từ tài liệu SDK công khai, cấu trúc đặc tả PDF, và kiến trúc các engine mở tương đương. Mục tiêu: **học mô hình kiến trúc**, không sao chép. + +### C1. Foxit +- **Core engine viết bằng C++**; cung cấp SDK với binding C++, C#, C, Java, Python. Kiến trúc tách lớp rõ: **Core (parser + render + edit) → API → UI**. +- Render engine riêng (không dùng PDFium công khai), tối ưu tốc độ & bộ nhớ — Foxit nổi tiếng "nhẹ và nhanh". +- Mô hình edit dựa trên **page object model**: trang = tập object (text/path/image/form-xobject), edit = thao tác trên object rồi serialize lại content stream. + +### C2. Adobe Acrobat +- Lõi C/C++ lâu đời (PDF do Adobe phát minh). **PDFL (PDF Library)** + Acrobat core; tách "Cos layer" (Carousel Object System — model object thấp tầng: dict/array/stream) và "PD layer" (Page Description — trang, annotation, form). +- Bài học quan trọng: **mô hình 2 tầng**: + - *Tầng object thấp (COS)*: đọc/ghi cấu trúc PDF (dictionary, stream, xref) — tương ứng QPDF/pikepdf. + - *Tầng tài liệu cao (PD)*: trang, annotation, form, content stream parsed thành object — tương ứng PDFium/MuPDF. +- Liquid Mode (mobile reflow) của Adobe dùng ML để suy ra cấu trúc đọc → cho thấy hướng "tái dựng cấu trúc" là bài toán AI/heuristic. + +### ➜ Bài học kiến trúc áp dụng cho FoFreeXit +1. **Tách 2 tầng**: `cos` (cấu trúc) và `pdmodel` (trang/object/annotation) — đúng như Adobe/PDFBox làm. +2. **Page Object Model** cho editing: parse content stream → cây object → sửa → serialize. +3. **Undo/redo** ở tầng model bằng command pattern. +4. Tách hẳn **engine** (không phụ thuộc UI) khỏi **UI**, để test tự động và tái dùng (CLI, server). + +--- + +## D. Khảo sát thư viện PDF (mọi ngôn ngữ) & giấy phép + +> Giấy phép là yếu tố sống còn: muốn phân phối tự do, **tránh AGPL** (MuPDF, iText) trừ khi chấp nhận copyleft hoặc mua license. + +| Thư viện | Ngôn ngữ | Render | Edit text/obj | Cấu trúc/repair | Giấy phép | Ghi chú | +|----------|----------|:------:|:------:|:------:|----------|------| +| **PDFium** | C/C++ | ⭐ rất tốt | ✔ có API (`FPDFPageObj_*`, `FPDFText_*`) | một phần | **BSD-3 (permissive)** | Engine của Chrome; binary prebuilt sẵn (bblanchon/pdfium-binaries). Nền tảng lý tưởng. | +| **QPDF** | C++ | ✘ | ✘ (cấu trúc) | ⭐ xuất sắc | Apache-2.0 | Repair, linearize, encrypt, object stream. Bổ trợ cho PDFium. | +| pikepdf | Python | ✘ | ✘ | ⭐ (wrap QPDF) | MPL-2.0 | Bản Python của QPDF, tốt cho prototype. | +| MuPDF | C | ⭐ | ✔ | ✔ | **AGPL/commercial** | Mạnh nhưng copyleft → tránh cho bản đóng. | +| PyMuPDF | Python | ⭐ | ✔ | ✔ | **AGPL/commercial** | Tốt để prototype/nghiên cứu, không ship. | +| iText | Java/.NET | một phần | ✔ tạo | ✔ | **AGPL/commercial $$$** | Tránh trừ khi mua. | +| Apache PDFBox | Java | ✔ ok | ✔ | ✔ | **Apache-2.0** | Permissive, full-feature, tham khảo thuật toán rất tốt (mã đọc được). | +| PDF.js | JS | ✔ (web) | ✘ (gần như render-only) | một phần | Apache-2.0 | Của Mozilla; tốt cho web viewer, không edit sâu. | +| pdf-lib | JS/TS | ✘ | ✔ (tạo/sửa cơ bản) | ✔ | MIT | Thuần JS, tạo & sửa nhẹ. | +| pdfcpu | Go | ✘ | thao tác trang | ✔ | Apache-2.0 | CLI mạnh cho organize/encrypt. | +| lopdf / pdf-rs / printpdf | Rust | một phần | ✔ thấp tầng / tạo | ✔ | MIT/Apache | Ecosystem Rust đang lớn, chưa bằng PDFium. | +| Tesseract | C++ | — | — (OCR) | — | Apache-2.0 | Engine OCR mở tốt nhất. | +| HarfBuzz | C++ | — | text shaping | — | MIT | Bắt buộc cho shaping (Việt/CJK/RTL). | +| FreeType | C | — | font rasterize | — | FTL/GPL | Đọc & render font. | +| LibreOffice (headless) | C++ | — | convert | — | MPL-2.0 | Dùng `soffice --convert-to` cho PDF↔Office. | + +### ➜ Tận dụng được gì +- **Nền engine**: PDFium (render + edit object) + QPDF (cấu trúc/encrypt/repair) — cả hai permissive → **không phải viết parser/renderer từ đầu**. +- **OCR**: Tesseract. **Shaping**: HarfBuzz. **Font**: FreeType. **Convert Office**: LibreOffice headless. +- **Tham khảo thuật toán** (đọc mã được): Apache PDFBox (Java, permissive) cho cách dựng text run, content stream, form; pdf.js cho rendering model. +- **Tránh**: MuPDF/PyMuPDF/iText cho bản phân phối (AGPL) — chỉ dùng để học/prototype. + +## Nguồn tham khảo +- [Foxit vs Adobe 2025](https://pdfpro.com/blog/general/foxit-vs-adobe) · [Foxit pricing](https://www.trustradius.com/products/foxit-pdf-editor/pricing) · [Foxit Editor blog](https://www.foxit.com/blog/the-new-foxit-pdf-editor-and-pdf-editor/) +- [Foxit PDF SDK for C++](https://developers.foxit.com/developer-hub/document/developer-guide-pdf-sdk/) +- [PDFium fpdf_edit.h](https://pdfium.googlesource.com/pdfium/+/refs/heads/main/public/fpdf_edit.h) · [PDFium LICENSE](https://pdfium.googlesource.com/pdfium/+/main/LICENSE) +- [pikepdf](https://github.com/pikepdf/pikepdf) · [Survey of Open-Source PDF Solutions (PDFA)](https://pdfa.org/wp-content/uploads/2021/06/Survey-of-OpenSource-Solutions.pdf) +- [Comparing open source PDF libraries (2025) — Joyfill](https://joyfill.io/blog/comparing-open-source-pdf-libraries-2025-edition) · [awesome-pdf](https://github.com/py-pdf/awesome-pdf) +- [MuPDF license](https://mupdf.readthedocs.io/en/1.27.0/license.html) diff --git a/docs/02-tech-stack.md b/docs/02-tech-stack.md new file mode 100644 index 0000000..12a56ea --- /dev/null +++ b/docs/02-tech-stack.md @@ -0,0 +1,93 @@ +# 02 — Lựa chọn ngôn ngữ, framework & engine + +## Nguyên tắc quyết định +1. **Permissive license** cho toàn bộ thành phần ship (BSD/Apache/MIT) → tránh AGPL. +2. **Không viết lại engine PDF từ đầu** ở giai đoạn đầu → dùng PDFium + QPDF. +3. Tách **Engine (không UI)** khỏi **App (UI)** để test & tái dùng. +4. Tối ưu cho **Windows trước** (thị trường Foxit), nhưng giữ đường ra **đa nền tảng**. +5. Dự án do AI hỗ trợ qua nhiều session → ưu tiên **ngôn ngữ có ecosystem PDF mạnh + tooling tốt + dễ test**, hơn là "ngôn ngữ dev người quen tay". + +--- + +## Tầng ENGINE (lõi xử lý PDF) — quyết định gần như bắt buộc + +**Chọn: PDFium (BSD-3) làm engine render + edit object, + QPDF (Apache-2.0) cho cấu trúc/mã hoá/repair.** + +Lý do: cả hai permissive, trưởng thành, được hậu thuẫn lớn (Google/Chromium). PDFium chính là thứ Chrome/Edge dùng để hiển thị PDF → render chất lượng production. Có binary prebuilt (bblanchon/pdfium-binaries) → khỏi build từ nguồn (vốn rất khổ). PDFium là **C/C++** → FFI tự nhiên nhất từ C++; binding sẵn cho .NET (PDFiumCore/PdfiumViewer), Rust (pdfium-render), Python (pypdfium2). + +Bổ trợ chuyên biệt: **Tesseract** (OCR), **HarfBuzz** (shaping), **FreeType** (font), **LibreOffice headless** (convert Office). Tham khảo thuật toán: **Apache PDFBox** (đọc mã được, permissive). + +--- + +## ✅ QUYẾT ĐỊNH ĐÃ CHỐT (2026-06-16): **Rust + Tauri** + +Tầng App/UI dùng **Rust + Tauri**; engine **PDFium (pdfium-render) + QPDF**; viewer có thể nhúng **PDF.js** trong webview cho tốc độ, dùng PDFium cho edit/save. Lý do chốt: an toàn bộ nhớ khi xử lý file không tin cậy, hiệu năng cao, license sạch, UI hiện đại phát triển nhanh, phù hợp dự án dài hơi nhiều session. Các lựa chọn A/C/D bên dưới giữ lại để tham khảo/đối chiếu. + +## Tầng APP (ngôn ngữ + UI framework) — các lựa chọn đã cân nhắc + +So sánh 4 lựa chọn khả thi: + +### Lựa chọn A — C++ + Qt (giống Foxit/Adobe nhất) +- **+** FFI với PDFium = 0 ma sát (cùng C++); hiệu năng tối đa; Qt là framework desktop mạnh nhất, đa nền tảng, in ấn/đồ hoạ tốt. +- **+** Đây là con đường "đẳng cấp Foxit" thực sự. +- **−** Tốc độ phát triển chậm, build phức tạp (CMake/vcpkg), quản lý bộ nhớ thủ công, refactor tốn công. +- **License Qt:** LGPL (dùng được miễn phí nếu link động) hoặc thương mại. + +### Lựa chọn B — Rust + Tauri (hiện đại, an toàn) ⭐ *khuyến nghị nếu muốn cân bằng* +- **+** An toàn bộ nhớ (ít crash/CVE — rất hợp với phần mềm "đọc file lạ"). `pdfium-render` (binding PDFium) trưởng thành. Tauri = UI web (HTML/CSS/TS) nhẹ, bundle nhỏ. +- **+** Có thể nhúng **PDF.js** trong webview cho viewer nhanh, dùng PDFium (Rust) cho edit/save. +- **+** Cargo/tooling tuyệt vời, test dễ, cross-platform. +- **−** Ecosystem PDF Rust non hơn C++; cần FFI sang PDFium (đã có sẵn binding). +- **License:** Rust crates đa số MIT/Apache; Tauri MIT/Apache. + +### Lựa chọn C — C# / .NET 8 + Avalonia (năng suất cao, Windows-first) +- **+** Năng suất phát triển cao nhất; XAML/MVVM quen thuộc; Avalonia đa nền tảng (hoặc WPF nếu chỉ Windows). Binding PDFium .NET sẵn. +- **+** Dễ tuyển/đọc code, dễ test (xUnit). +- **−** FFI sang native qua P/Invoke (ổn nhưng có chi phí marshaling); GC pause với file rất lớn cần chú ý. +- **License:** .NET & Avalonia MIT. + +### Lựa chọn D — TypeScript + Electron + PDF.js (nhanh ra mắt, web-native) +- **+** Dev UI nhanh nhất, hệ sinh thái khổng lồ, dễ làm bản web sau này. +- **−** PDF.js gần như render-only → edit/save phải tự build hoặc nhúng native (pdfium qua WASM/node-addon); Electron nặng RAM; hiệu năng kém nhất với file lớn. **Yếu nhất cho tính năng EDIT** — điểm cốt lõi của dự án. + +### Bảng tổng hợp + +| Tiêu chí | A: C++/Qt | B: Rust/Tauri | C: C#/Avalonia | D: TS/Electron | +|---|:--:|:--:|:--:|:--:| +| Ma sát FFI PDFium | ⭐ | ✔ | ✔ | △ | +| Hiệu năng / file lớn | ⭐ | ⭐ | ✔ | △ | +| An toàn bộ nhớ | △ | ⭐ | ✔ | ✔ | +| Tốc độ phát triển | △ | ✔ | ⭐ | ⭐ | +| Sức mạnh tính năng EDIT | ⭐ | ⭐ | ✔ | △ | +| Cross-platform | ⭐ | ⭐ | ⭐ | ⭐ | +| Độ "đẳng cấp Foxit" | ⭐ | ✔ | ✔ | △ | + +### ➜ Khuyến nghị +- **Cân bằng tốt nhất (khuyến nghị chính): B — Rust + Tauri.** An toàn (quan trọng khi xử lý file không tin cậy), hiệu năng cao, binding PDFium tốt, UI hiện đại nhanh phát triển, license sạch. Phù hợp dự án dài hơi do AI hỗ trợ. +- **Nếu ưu tiên "đúng chuẩn Foxit", chấp nhận chậm: A — C++/Qt.** +- **Nếu ưu tiên ra tính năng nhanh trên Windows: C — C#/Avalonia.** +- **Không khuyến nghị D** làm kiến trúc chính vì điểm yếu ở tính năng EDIT (lõi giá trị của dự án). + +> **Điểm chung mọi lựa chọn:** Tầng *Engine* (PDFium + QPDF + Tesseract...) gần như không đổi. Lựa chọn ngôn ngữ chủ yếu ảnh hưởng tầng *App/UI*. Vì vậy nên **đóng gói Engine sau một API ổn định** (FFI/IPC) để có thể đổi UI mà không đập lõi. + +--- + +## Kiến trúc đề xuất (độc lập với lựa chọn UI) + +``` +┌──────────────────────────────────────────┐ +│ UI Layer │ (Qt / Tauri-web / Avalonia) +│ Viewer · Annotate · Edit · Organize │ +├──────────────────────────────────────────┤ +│ App / Commands │ undo/redo, document state, MVVM +├──────────────────────────────────────────┤ +│ FoFreeXit Core API (stable) │ ← biên giới ổn định (FFI/IPC) +│ pdmodel: Page, TextRun, Image, Annot... │ ← tầng "PD" kiểu Adobe +│ cos: Object, Dict, Stream, XRef │ ← tầng "COS" kiểu Adobe +├──────────────────────────────────────────┤ +│ PDFium │ QPDF │ Tesseract │ HarfBuzz │ (engine permissive) +│ render+edit│ struct │ OCR │ shaping │ +└──────────────────────────────────────────┘ +``` + +Chi tiết hoá tiếp ở [04-architecture.md](04-architecture.md) sau khi chốt stack. diff --git a/docs/03-roadmap.md b/docs/03-roadmap.md new file mode 100644 index 0000000..5d84b83 --- /dev/null +++ b/docs/03-roadmap.md @@ -0,0 +1,91 @@ +# 03 — Lộ trình dự án (Roadmap) + +## Mục tiêu tổng (North Star) +Một ứng dụng desktop có thể **xem, chú thích, tổ chức trang, và chỉnh sửa text/ảnh trực tiếp** trên PDF, kèm bảo mật cơ bản — đủ để một người dùng Foxit phổ thông **bỏ Foxit** cho công việc hằng ngày. + +## Phương pháp làm việc +- **Engine-first, UI-second** trong mỗi tính năng: làm được ở tầng core + test CLI trước, rồi mới gắn UI. +- Mỗi phase kết thúc bằng **bản chạy được (demo) + test tự động + cập nhật docs**. +- **Bộ PDF mẫu** (test corpus) tích luỹ dần: file thường, file scan, file mã hoá, file hỏng, CJK/Việt/RTL, form, file nghìn trang. +- Quy ước: nhánh/commit theo phase; mỗi tính năng có "DoD" (Definition of Done) checklist. +- **Không** chuyển phase khi DoD chưa đạt và test chưa xanh. + +--- + +## Phase 0 — Nghiên cứu & Kế hoạch ✅ (đang ở đây) +**DoD:** docs 01–03 hoàn tất; chốt ngôn ngữ/framework; dựng skeleton repo. + +## Phase 1 — Nền tảng & Viewer (MVP xem được) +**Mục tiêu:** Mở và hiển thị PDF chính xác, mượt. +- Tích hợp PDFium (prebuilt) qua FFI; dựng Core API tối thiểu (`open`, `pageCount`, `renderPage`). +- Viewer: scroll liên tục, zoom/fit, thumbnails, outline/bookmarks, **tìm kiếm text**, chọn & copy text. +- Mở file lớn (lazy render + cache tile). +**DoD:** mở 20 file mẫu (gồm file 1000+ trang, CJK, Việt) không crash; render khớp mắt thường với Chrome; search & copy hoạt động; có test render-hash cho trang mẫu. + +## Phase 2 — Chú thích (Annotate) +**Mục tiêu:** Bộ comment dùng hằng ngày. +- Highlight/underline/strikethrough, sticky note, text box, free draw, shapes, stamp. +- Lưu annotation vào PDF (annotation dict), import/export **XFDF**. +- Hiển thị & sửa/xoá annotation; danh sách comment ở sidebar. +**DoD:** tạo/sửa/xoá mọi loại trên; lưu & mở lại giữ nguyên; Acrobat/Foxit đọc được annotation ta ghi; export/import XFDF round-trip. + +## Phase 3 — Tổ chức trang (Organize) + Lưu file vững +**Mục tiêu:** Quản lý trang & ghi file an toàn. +- Chèn/xoá/xoay/trích/thay/đảo trang; **merge & split**; crop; đánh số; header/footer; watermark/background. +- Engine ghi file: incremental update **và** full rewrite (qua QPDF); giữ không hỏng file; **undo/redo** toàn cục. +**DoD:** mọi thao tác trang round-trip đúng; merge 50 file OK; ghi không làm hỏng file mã hoá; undo/redo ổn định; test so khớp cấu trúc trang. + +## Phase 4 — ⭐ Chỉnh sửa nội dung (Edit) — TÍNH NĂNG LÕI +**Mục tiêu:** Sửa text & object trực tiếp — moat chính. +- **Page Object Model**: parse content stream → cây object (text/path/image/xobject). +- Sửa **ảnh/object**: di chuyển, resize, xoá, thêm ảnh (dễ hơn → làm trước). +- Sửa **text**: gom glyph → text run/line/paragraph (heuristic theo baseline & spacing); edit inline; đo lại width theo font (FreeType/HarfBuzz); **reflow** trong text box; xử lý font nhúng/subset + font substitution; hỗ trợ **tiếng Việt** (tổ hợp dấu) sớm, CJK/RTL sau. +- Thêm text box mới, đổi font/size/màu. +**DoD:** sửa được text 1 dòng & 1 đoạn trên ≥80% file mẫu thường; thêm/xoá/di chuyển ảnh; lưu mở lại đúng; tiếng Việt hiển thị & sửa đúng dấu; có test corpus chuyên cho edit. + +## Phase 5 — Bảo mật & Chữ ký +**Mục tiêu:** Tính năng đáng tiền cho doanh nghiệp. +- Mật khẩu mở/permission; mã hoá **AES-256**; xoá mật khẩu. +- **Redaction thật** (xoá nội dung + ảnh + metadata, không chỉ vẽ đè) + kiểm chứng đã xoá. +- Xoá metadata/ẩn; **chữ ký số** (PAdES, byte range, incremental update giữ chữ ký). +**DoD:** mã hoá/giải mã round-trip; redaction qua kiểm chứng không còn text bị bôi; ký số được Acrobat xác thực hợp lệ. + +## Phase 6 — Form (AcroForm) +**Mục tiêu:** Điền & tạo form. +- Điền form có sẵn, lưu; flatten form. +- Tạo field: text/checkbox/radio/dropdown/button; import/export dữ liệu (FDF/CSV). +**DoD:** điền & lưu giữ dữ liệu; tạo form mới mở được ở Acrobat; export/import round-trip. + +## Phase 7 — OCR & Convert +**Mục tiêu:** Hai tính năng "đáng tiền" còn lại, qua dự án mở. +- **OCR**: Tesseract + tiền xử lý ảnh + layout → tạo searchable PDF (lớp text vô hình khớp toạ độ). Đa ngôn ngữ gồm tiếng Việt. +- **Convert**: PDF→ảnh (sẵn từ PDFium); Office↔PDF qua **LibreOffice headless**; PDF→Word/Excel (giữ layout — bài toán khó, làm bản "đủ dùng" trước). +**DoD:** OCR scan tạo PDF search được (Việt + Anh); convert Office↔PDF ổn; PDF→Word giữ được text & bố cục cơ bản. + +## Phase 8 — Hoàn thiện & Phát hành +- So sánh 2 PDF (compare); in ấn đúng; preferences; đa ngôn ngữ UI (Việt/Anh); accessibility. +- Installer (Windows MSI/winget; sau đó mac/Linux); auto-update; crash reporting. +- Tối ưu hiệu năng & bộ nhớ; hardening bảo mật (fuzzing parser). +**DoD:** cài đặt sạch trên máy mới; vượt bộ test hồi quy đầy đủ; tài liệu người dùng. + +## Phase 9 (tuỳ chọn) — AI +- Tóm tắt, hỏi-đáp tài liệu, dịch (dùng Claude API / model cục bộ). Làm sau cùng vì không phải lý do chính thay thế Foxit. + +--- + +## Thứ tự ưu tiên giá trị (nếu phải cắt giảm) +**1→2→3→4** là "core sản phẩm thay Foxit cho cá nhân". **5,6** thêm giá trị doanh nghiệp. **7** ngang hàng giá trị nhưng phụ thuộc dự án ngoài. **8** bắt buộc để phát hành. **9** là bonus. + +## Rủi ro & giảm thiểu +| Rủi ro | Giảm thiểu | +|---|---| +| Edit text quá khó (Phase 4) | Làm object/ảnh trước; text bắt đầu từ ca đơn giản; tận dụng PDFium edit API + PDFBox tham khảo | +| Build/FFI PDFium phức tạp | Dùng binary prebuilt + binding có sẵn | +| Convert PDF→Word kém | Hạ kỳ vọng: "đủ dùng" trước; dựa LibreOffice | +| File lạ làm crash | Test corpus file hỏng + fuzzing; chọn ngôn ngữ an toàn bộ nhớ | +| Phạm vi phình to | DoD nghiêm ngặt; không nhảy phase khi chưa xanh | + +## Bộ chỉ số thành công sản phẩm +- Mở đúng ≥99% file PDF đời thực trong corpus. +- Người dùng Foxit phổ thông làm được: xem, comment, sắp trang, sửa text/ảnh, đặt mật khẩu — **không cần Foxit**. +- Không thua Foxit rõ rệt về tốc độ mở & render. diff --git a/docs/04-architecture.md b/docs/04-architecture.md new file mode 100644 index 0000000..a18780e --- /dev/null +++ b/docs/04-architecture.md @@ -0,0 +1,63 @@ +# 04 — Kiến trúc kỹ thuật (khung — sẽ chi tiết hoá sau khi chốt stack) + +> Tài liệu này sẽ được hoàn thiện ở đầu Phase 1, sau khi đã chốt ngôn ngữ/framework ở [02-tech-stack.md](02-tech-stack.md). + +## Mô hình 2 tầng (học từ Adobe COS/PD và Apache PDFBox) + +- **`cos` (Carousel Object System)** — tầng object thấp: `Object`, `Dictionary`, `Array`, `Stream`, `Name`, `Ref`, `XRef`. Đọc/ghi cấu trúc file PDF thô. (Chủ yếu tựa QPDF.) +- **`pdmodel`** — tầng tài liệu cao: `Document`, `Page`, `Resources`, `ContentStream`, `TextRun`, `ImageObject`, `PathObject`, `Annotation`, `AcroForm`, `Field`. (Tựa PDFium + logic riêng.) + +## Các module chính +- `engine/render` — bọc PDFium render (tile, cache, đa luồng). +- `engine/text` — gom glyph → run/line/paragraph; chọn/copy; tìm kiếm. +- `engine/edit` — Page Object Model; sửa text/object; serialize content stream. +- `engine/font` — FreeType + HarfBuzz: đo width, shaping, subset, substitution. +- `engine/io` — mở/lưu (incremental + full rewrite via QPDF), repair, linearize, encrypt. +- `engine/annot` — annotation CRUD + XFDF. +- `engine/security` — mã hoá, redaction, chữ ký số (PAdES). +- `engine/form` — AcroForm điền/tạo/flatten. +- `engine/ocr` — Tesseract + tiền xử lý + tạo lớp text. +- `engine/convert` — cầu nối LibreOffice headless; PDF→ảnh; PDF→Office. +- `core-api` — biên giới ổn định (FFI/IPC) cho UI. +- `app/*` — UI theo framework đã chọn. +- `cli` — công cụ dòng lệnh cho test/automation (chạy mọi tính năng không cần UI). + +## Nguyên tắc +- Engine **không phụ thuộc UI**; mọi tính năng phải gọi được từ `cli` → test tự động. +- Edit dùng **command pattern** → undo/redo. +- Mọi thao tác ghi đều có đường **không phá file gốc** (atomic write / backup). + +## Test strategy +- Unit test cho `cos`/`pdmodel`. +- Golden/render-hash test cho viewer. +- Round-trip test cho annotate/organize/form/security. +- Corpus test (file đời thực, file hỏng, đa ngôn ngữ) + fuzzing parser. + +## Hạng mục cần quyết khi vào Phase 1 +- [x] Ngôn ngữ/UI: **Rust + Tauri** (chốt 2026-06-16). +- [ ] Phân phối PDFium: dùng prebuilt `bblanchon/pdfium-binaries` qua crate `pdfium-render` (chốt version cụ thể đầu Phase 1). +- [ ] Biên giới core-api: trong Tauri, engine Rust chạy cùng tiến trình; cân nhắc tách tiến trình parser để **sandbox** file không tin cậy (quyết định khi làm hardening). +- [ ] Bố cục repo (mono-repo Cargo workspace, xem dưới). + +## Bố cục repo dự kiến (Rust + Tauri, Cargo workspace) +``` +FoFreeXit/ +├─ Cargo.toml # workspace +├─ crates/ +│ ├─ ff-cos/ # tầng object thấp (cấu trúc PDF) +│ ├─ ff-pdmodel/ # tầng tài liệu cao (page/text/annot/...) +│ ├─ ff-engine/ # render/edit/io/font/ocr... (bọc PDFium/QPDF/Tesseract) +│ └─ ff-cli/ # CLI chạy mọi tính năng không cần UI (để test) +├─ app/ # Tauri app +│ ├─ src-tauri/ # Rust backend (gọi ff-engine) +│ └─ src/ # frontend (TS/HTML/CSS, PDF.js viewer) +├─ tests/ # integration tests +├─ corpus/ # PDF mẫu (thường/scan/mã hoá/hỏng/CJK/Việt/form) +└─ docs/ +``` + +## Bước khởi động Phase 1 (gợi ý cho session sau) +1. Khởi tạo Cargo workspace + crate `ff-cli`, `ff-engine`. +2. Thêm `pdfium-render` + tải prebuilt PDFium; viết lệnh CLI `render ` → xác nhận engine chạy. +3. Khởi tạo Tauri app, hiển thị 1 trang PDF render từ engine. +4. Dựng `corpus/` ban đầu (vài file đa dạng) + test render-hash đầu tiên. diff --git a/docs/05-dev-setup.md b/docs/05-dev-setup.md new file mode 100644 index 0000000..d81b665 --- /dev/null +++ b/docs/05-dev-setup.md @@ -0,0 +1,63 @@ +# 05 — Hướng dẫn build & chạy (dev) + +> Cập nhật ở cuối Phase 1. Áp dụng cho Windows x64 (môi trường dev hiện tại). + +## Yêu cầu môi trường +- **Rust** (MSVC toolchain), cài qua rustup. Kiểm: `rustc --version` (hiện 1.96.0). +- **Visual Studio Build Tools** + workload **Desktop development with C++** (cung cấp `cl.exe`/`link.exe` cho linker MSVC). +- **WebView2 Runtime** (cho Tauri; Windows 11 thường có sẵn). +- **PDFium**: `pdfium.dll` prebuilt — tải bằng `scripts/fetch-pdfium.ps1` (đặt vào gốc workspace + `pdfium/`). +- (Tauri) Node không bắt buộc: app dùng frontend tĩnh, chạy thẳng bằng `cargo run`. + +## Lấy PDFium +```powershell +# Tải pdfium.dll (bblanchon/pdfium-binaries) về gốc workspace +powershell -File scripts/fetch-pdfium.ps1 +``` +Engine tìm `pdfium.dll` theo thứ tự: `FOFREEXIT_PDFIUM_PATH` → cwd → `./pdfium` → thư mục exe → thư viện hệ thống. + +## Cấu trúc +``` +crates/ff-cos # COS layer (khung) +crates/ff-pdmodel # PD layer (khung) +crates/ff-engine # render qua PDFium (Phase 1: render.rs) +crates/ff-cli # CLI "ff" (info, render) +app/src # frontend tĩnh (HTML/CSS/JS) +app/src-tauri # backend Tauri (crate riêng, workspace tách) +corpus/ # PDF mẫu để test +scripts/ # tiện ích (fetch-pdfium) +``` + +## CLI +```powershell +# Đếm trang +cargo run -p ff-cli -- info corpus\hello.pdf +# Render trang 0 ra PNG, rộng 800px +cargo run -p ff-cli -- render corpus\hello.pdf out.png --page 0 --width 800 +# Kích thước mọi trang +cargo run -p ff-cli -- pages corpus\sample-multipage.pdf +# Trích text 1 trang +cargo run -p ff-cli -- text corpus\sample-multipage.pdf --page 1 +# Tìm kiếm (in vị trí + toạ độ) +cargo run -p ff-cli -- search corpus\sample-multipage.pdf content +# Outline / bookmarks +cargo run -p ff-cli -- outline corpus\sample-multipage.pdf +``` + +## Test +```powershell +cargo test -p ff-engine # smoke test render (cần pdfium.dll) +``` + +## Chạy app desktop (Tauri) +```powershell +cd app\src-tauri +cargo run # mở cửa sổ, hiển thị corpus\hello.pdf +``` +> App là một Cargo workspace **riêng** (có `[workspace]` trống trong `app/src-tauri/Cargo.toml`) +> nên lệnh `cargo` ở gốc repo không build app, và ngược lại. Đây là chủ ý để tránh +> xung đột profile build giữa thư viện và Tauri. + +## Ghi chú +- Bản dev set `FOFREEXIT_PDFIUM_PATH` tự động về gốc workspace (xem `app/src-tauri/src/main.rs`). + Bản release sẽ bundle `pdfium.dll` như resource (việc của Phase 8). diff --git a/docs/06-phase1-summary.md b/docs/06-phase1-summary.md new file mode 100644 index 0000000..182cfe3 --- /dev/null +++ b/docs/06-phase1-summary.md @@ -0,0 +1,50 @@ +# 06 — Tổng kết Phase 1 (Engine core + Viewer) + +> Trạng thái: **HOÀN TẤT** các mục lõi. 10/10 test tự động xanh. Đã xác minh UI bằng screenshot & thao tác thực. + +## 1. Đã xây dựng những gì + +### Hạ tầng & toolchain +- Cài Rust 1.96 (MSVC) + Visual Studio Build Tools 2026 (workload C++) + WebView2. +- Tải PDFium prebuilt (`pdfium.dll`) qua [scripts/fetch-pdfium.ps1](../scripts/fetch-pdfium.ps1). +- **Cargo workspace**: `crates/ff-cos`, `crates/ff-pdmodel`, `crates/ff-engine`, `crates/ff-cli`. +- **App Tauri** tại `app/` (workspace tách riêng) — chạy bằng `cd app/src-tauri; cargo run`. + +### Engine (`ff-engine`, dùng PDFium qua `pdfium-render`) +| Hàm | Chức năng | +|-----|-----------| +| `bind_pdfium` | Nạp thư viện PDFium động | +| `render_page` / `render_page_png` | Render trang ra ảnh (RGBA/PNG) theo chiều rộng | +| `page_count`, `page_dims` | Số trang & kích thước từng trang | +| `extract_text` | Trích text một trang | +| `search` | Tìm chuỗi (có/không phân biệt hoa thường) + **toạ độ rect** từng kết quả | +| `outline` | Đọc bookmarks + trang đích | +| `page_char_boxes` | Hộp bao từng ký tự (cho text-layer chọn/copy) | + +### CLI (`ff`) — chạy mọi tính năng không cần UI (phục vụ test) +`info`, `render`, `pages`, `text`, `search`, `outline`. + +### App desktop (Tauri + frontend tĩnh) +- **Mở file** qua hộp thoại native (`📂 Mở`) — lọc *.pdf. +- **Xem**: cuộn liên tục nhiều trang, **lazy render** (chỉ render trang trong tầm nhìn) → mở mượt file 1000+ trang. +- **Zoom** −/+/Fit (re-render sắc nét theo devicePixelRatio). +- **Thumbnails** sidebar (lazy-render, đánh dấu trang hiện tại). +- **Outline** sidebar (click → nhảy trang). +- **Tìm kiếm** + highlight chính xác từng kết quả, điều hướng ◀ x/y ▶, highlight bám đúng cả khi zoom. +- **Chọn & copy text**: text-layer trong suốt phủ đúng từng glyph; chọn bằng chuột/Shift+Click + Ctrl+C, hoặc nút **Copy** (cả trang). + +## 2. Test tự động (10/10 xanh) — `cargo test` +- `render_smoke`: mở & render `hello.pdf`, trang không trắng trơn. +- `viewer_features` (6): `page_dims`, `extract_text`, `search` (số lượng+vị trí), phân biệt hoa thường, `outline`, `char_boxes` (ghép ký tự = nội dung + hộp nằm trong khổ trang). +- `big_doc` (3): file **1000 trang** — đúng số trang; render trang đầu/cuối < 5s & không trắng; search toàn tài liệu ra đúng 1 kết quả < 10s. + +Hiệu năng đo thực tế trên `big-1000.pdf`: mở 55ms · render 1 trang 110ms · search toàn bộ 79ms. + +## 3. Giới hạn đã biết của Phase 1 (sẽ tinh chỉnh) +- ~~Double-click chọn 1 ký tự~~ → **ĐÃ SỬA**: text-layer gom ký tự thành "từ", double-click chọn cả từ; copy giữ khoảng trắng (chèn text node giữa các từ). Đã verify: double-click → chọn nguyên từ "FoFreeXit". +- Chưa có: in ấn, xoay trang khi xem, nhớ file mở gần đây, kéo-thả file vào cửa sổ. +- `render_page` nạp lại tài liệu mỗi lần gọi (chưa cache document trong bộ nhớ) — đủ nhanh hiện tại, sẽ tối ưu bằng cache khi cần. +- Bản dev tìm `pdfium.dll` ở gốc workspace; bản phát hành (Phase 8) sẽ bundle. + +## 4. Kiến trúc vẫn đúng định hướng +2 tầng COS/PD đã đặt khung (`ff-cos`, `ff-pdmodel`); engine tách hẳn UI, gọi được qua CLI + Tauri. Sẵn sàng cho Phase 2 (Annotate). diff --git a/docs/07-phase1-user-tests.md b/docs/07-phase1-user-tests.md new file mode 100644 index 0000000..16aa90e --- /dev/null +++ b/docs/07-phase1-user-tests.md @@ -0,0 +1,76 @@ +# 07 — Checklist test thủ công cho Phase 1 (dành cho người dùng) + +Mục tiêu: bạn tự kiểm tra viewer, ghi lại chỗ nào chưa ổn để cải thiện **trước khi sang Phase 2**. + +## Cách chạy app +```powershell +cd c:\Project\FoFreeXit\app\src-tauri +cargo run +``` +(Lần đầu mở sẵn `corpus/sample-multipage.pdf`. Nếu thiếu `pdfium.dll`: chạy `scripts/fetch-pdfium.ps1`.) + +## Bảng test — đánh dấu ✅/❌ và ghi chú + +### A. Mở file +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| A1 | Bấm **📂 Mở**, chọn 1 PDF thật của bạn | Mở & hiển thị đúng | | +| A2 | Mở file **rất lớn** (vài trăm–1000+ trang) | Mở nhanh, không treo | | +| A3 | Mở file **scan** (ảnh, không có text) | Hiển thị được (sẽ không chọn được text — đúng) | | +| A4 | Mở file **tiếng Việt có dấu** | Chữ + dấu hiển thị đúng | | +| A5 | Mở file **mã hoá/đặt mật khẩu** | (Dự kiến lỗi — Phase 5 mới hỗ trợ) ghi lại hiện tượng | | +| A6 | Mở file **hỏng/khác thường** | Không crash; báo lỗi gọn | | + +### B. Xem & điều hướng +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| B1 | Cuộn lên/xuống nhiều trang | Mượt, trang hiện dần | | +| B2 | Chỉ số "Trang x/y" khi cuộn | Cập nhật đúng trang đang xem | | +| B3 | Bấm thumbnail | Nhảy đúng trang | | +| B4 | Tab **Outline**, bấm mục | Nhảy đúng trang đích | | +| B5 | So sánh hiển thị với Foxit/Chrome cùng file | Trông giống nhau | | + +### C. Zoom +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| C1 | Bấm + / − nhiều lần | Phóng to/thu nhỏ, chữ vẫn nét | | +| C2 | Bấm **Fit** | Vừa bề rộng cửa sổ | | +| C3 | Zoom rồi cuộn | Không vỡ layout, không lag nặng | | + +### D. Tìm kiếm +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| D1 | Gõ 1 từ có trong file | Hiện "k/n", nhảy tới kết quả, **ô vàng/cam đúng chỗ** | | +| D2 | Bấm ◀ ▶ duyệt kết quả | Nhảy lần lượt, đổi highlight | | +| D3 | Tìm từ tiếng Việt có dấu | Tìm đúng | | +| D4 | Tìm từ không tồn tại | Hiện 0, không lỗi | | + +### E. Chọn & copy text +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| E1 | **Kéo chuột** chọn 1 đoạn text | Bôi xanh đúng vùng | | +| E2 | Ctrl+C rồi dán ra Notepad | Đúng nội dung, đúng thứ tự | | +| E3 | **Double-click** 1 từ | (Hiện chỉ chọn 1 ký tự — đã biết, sẽ sửa) | | +| E4 | Nút **Copy** | Copy text cả trang hiện tại | | +| E5 | Copy đoạn **tiếng Việt có dấu** | Dấu không bị mất/lỗi | | + +### F. Ổn định & hiệu năng +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| F1 | Mở/đóng/đổi nhiều file liên tiếp | Không rò bộ nhớ rõ rệt, không crash | | +| F2 | Mở file lớn rồi cuộn nhanh | RAM/CPU chấp nhận được | | +| F3 | Phóng to hết cỡ file lớn | Không treo | | + +## Mẫu phản hồi gửi lại +Với mỗi mục ❌ hoặc chưa hài lòng, ghi theo mẫu: +``` +[Mã test] (vd D1) — File: — Hiện tượng: — +Kỳ vọng: — Mức ưu tiên: cao/vừa/thấp +``` +Ví dụ: +``` +B5 — File: hop_dong.pdf — Hiện tượng: chữ mờ hơn Foxit khi zoom 100% — +Kỳ vọng: nét như Foxit — Ưu tiên: vừa +``` + +> Gửi danh sách phản hồi này lại, tôi sẽ sửa hết các điểm chưa đạt của Phase 1 **trước khi** bắt đầu Phase 2 (Annotate). diff --git a/docs/08-phase2-summary.md b/docs/08-phase2-summary.md new file mode 100644 index 0000000..e1d97dd --- /dev/null +++ b/docs/08-phase2-summary.md @@ -0,0 +1,42 @@ +# 08 — Tổng kết Phase 2 (Annotate) + +> Trạng thái: **lõi HOÀN TẤT**. 13/13 test tự động xanh. Đường GHI file (rủi ro nhất) đã round-trip + verify ảnh. + +## 1. Đã làm + +### Engine (`crates/ff-engine/src/annot.rs`) +- `apply_annotations(input, output, specs)`: tạo annotation rồi **lưu sang file mới** (không sửa file gốc), qua `document.save_to_file`. +- 6 loại: **Highlight, Underline, Strikeout** (text-markup, dùng QuadPoints), **Square** (khung), **FreeText** (hộp văn bản), **Note** (ghi chú dán). +- `list_annotations` / `count_annotations`: đọc lại annotation (loại, vùng, nội dung). +- Bài học: QuadPoints highlight phải theo thứ tự TL,TR,BL,BR (helper `quad_from_rect`) — `PdfQuadPoints::from_rect` của thư viện dùng thứ tự khác làm highlight bị xoắn. + +### Tauri commands (`app/src-tauri/src/main.rs`) +- `apply_annotations(input, output, specs)` — map DTO (JS) → engine. +- `pick_save_pdf()` — hộp thoại Lưu. + +### UI (`app/src`) +- Thanh **Chú thích**: 6 công cụ (Tô sáng, Gạch chân, Gạch ngang, Khung, Text box, Ghi chú) + chọn **màu** + nút **Lưu chú thích (n)**. +- **Vẽ bằng chuột**: kéo vùng trên trang → tạo chú thích, **preview tức thì** (lớp `.annotlayer`), toạ độ màn hình→điểm PDF chính xác (cùng phép biến đổi đã kiểm ở search/text-layer). +- Tab **Chú thích** (sidebar): danh sách chú thích chưa lưu, click để nhảy trang, ✕ để xoá. +- **Lưu**: nút → hộp thoại → ghi file mới (annotation thật) rồi mở lại để render. +- CLI: `ff annots ` liệt kê annotation; `ff chars ` (debug). + +## 2. Test tự động (13/13 xanh) +- `annot_roundtrip` (3): Highlight+Square; Underline+Strikeout; FreeText+Note — ghi → mở lại → đúng loại/nội dung + render đúng màu. +- Cùng các test Phase 1 (viewer_features 6, big_doc 3, render_smoke 1). + +## 3. Đã kiểm bằng tay/ảnh +- Round-trip render: highlight vàng phủ khít "content", khung đỏ (ảnh `tmp-out/annot-*.png`). +- UI: vẽ highlight/underline/strikeout/box hiển thị preview đúng vị trí, đổi màu/đổi công cụ, đếm số chú thích (ảnh `tmp-out/annot-draw.png`). + +> Ghi chú kỹ thuật: tự-động-hoá chuột Win32 KHÔNG mô phỏng được thao tác "kéo" trong WebView2 (mousemove giả lập bị lọc) — nên drag-vẽ và drag-chọn-text chỉ kiểm được bằng ảnh khi events lọt, hoặc bằng thao tác rời (click/shift-click). Với chuột thật của người dùng, kéo hoạt động bình thường. + +## 4. Còn lại / follow-up (chưa làm) +- **Ink** (vẽ tay tự do). +- **Sửa/di chuyển/xoá** annotation đã lưu (hiện chỉ xoá cái *chưa* lưu). +- Liệt kê annotation **đã lưu** trong tab Chú thích (hiện chỉ liệt kê cái chưa lưu). +- **Import/Export XFDF**. +- Độ trung thực cross-viewer (appearance stream) cho FreeText/Note ở Acrobat. + +## 5. Cần người dùng xác nhận (vì kéo-chuột thật không tự test được) +Xem checklist: [docs/09-phase2-user-tests.md](09-phase2-user-tests.md). diff --git a/docs/09-phase2-user-tests.md b/docs/09-phase2-user-tests.md new file mode 100644 index 0000000..c0a0659 --- /dev/null +++ b/docs/09-phase2-user-tests.md @@ -0,0 +1,33 @@ +# 09 — Checklist test thủ công Phase 2 (Annotate) + +Phần kéo-chuột không tự động test được trong WebView2 (xem ghi chú ở [08-phase2-summary.md](08-phase2-summary.md)), nên cần bạn thử bằng chuột thật. + +## Chạy +```powershell +cd c:\Project\FoFreeXit\app\src-tauri +cargo run +``` + +## Bảng test +| # | Thao tác | Kỳ vọng | KQ | +|---|----------|---------|----| +| G1 | Chọn **Tô sáng**, kéo qua một dòng chữ | Vệt vàng phủ đúng vùng kéo | | +| G2 | Chọn **Gạch chân**, kéo qua chữ | Đường kẻ dưới chữ | | +| G3 | Chọn **Gạch ngang**, kéo qua chữ | Đường kẻ giữa chữ | | +| G4 | Chọn **Khung**, kéo một vùng | Khung chữ nhật | | +| G5 | Đổi **Màu** rồi vẽ | Chú thích đúng màu mới | | +| G6 | Chọn **Text box**, kéo vùng, gõ chữ | Hộp chữ hiện nội dung | | +| G7 | Chọn **Ghi chú**, bấm lên trang, gõ chữ | Icon ghi chú 📝 (rê chuột thấy nội dung) | | +| G8 | Tab **Chú thích** (sidebar) | Liệt kê các chú thích vừa vẽ; bấm để nhảy trang; ✕ để xoá | | +| G9 | Bấm **Lưu chú thích**, chọn nơi lưu | Tạo file PDF mới; app mở lại file đó | | +| G10 | Mở file vừa lưu bằng **Foxit/Adobe/Chrome** | Annotation hiển thị đúng ở phần mềm khác | | +| G11 | Vẽ trên file **nhiều trang**, cuộn qua lại | Chú thích đúng trang, đúng vị trí khi cuộn/zoom | | +| G12 | Vẽ rồi **zoom** in/out | Chú thích co giãn theo, vẫn đúng chỗ | | + +## Mẫu phản hồi +``` +[Mã] (vd G10) — Phần mềm mở: — Hiện tượng: — +Kỳ vọng: <...> — Ưu tiên: cao/vừa/thấp +``` + +> Đặc biệt cần biết **G10** (file lưu ra mở ở phần mềm khác có đúng không) và **G9** (lưu có thành công không), vì đó là đường GHI file. Engine đã test round-trip nội bộ, nhưng xác nhận cross-viewer của bạn rất giá trị. diff --git a/final target and rule.md b/final target and rule.md new file mode 100644 index 0000000..7025f4b --- /dev/null +++ b/final target and rule.md @@ -0,0 +1,26 @@ +# FINAL TARGET & RULE — FoFreeXit + +> File này là LUẬT TỐI THƯỢỢNG của dự án. Mọi task đã, đang và sẽ làm đều PHẢI tuân thủ. + +## MỤC TIÊU CUỐI CÙNG +**Mục tiêu là tạo ra phần mềm có cách dùng, hiệu năng, chức năng, giao diện và trải nghiệm y hệt Foxit.** + +## LUẬT BẤT BIẾN (NO-COMPROMISE RULE) +**Nếu tính năng Foxit có mà thư viện không đáp ứng được thì hãy update code cho thư viện nếu có thể, nếu không thì tìm thư viện khác hoặc tự code để xử lý vấn đề. Không thỏa hiệp. Mọi tính năng đã, đang và sẽ làm phải có trải nghiệm và chức năng tương đương Foxit, không thỏa hiệp cắt giảm tính năng vì bất kì lí do gì. Làm được bằng bất kì cách nào.** + +## DIỄN GIẢI ÁP DỤNG (bắt buộc với mọi task) +1. Trước khi làm bất kỳ tính năng nào: **tìm hiểu Foxit làm tính năng đó thế nào** (UI, thao tác, tuỳ chọn, định dạng, cách sửa/xoá, màu sắc...) và lấy đó làm chuẩn nghiệm thu. +2. **Không được cắt giảm** vì "thư viện không hỗ trợ". Thứ tự xử lý khi vướng thư viện: + a. Sửa/patch/fork thư viện (vendor as path dependency) để thêm khả năng còn thiếu. + b. Nếu không được → tìm thư viện khác phù hợp hơn. + c. Nếu không được → tự viết (thao tác tầng PDF object, appearance stream, v.v.). +3. Mỗi tính năng phải đạt **cả 5 mặt**: cách dùng, hiệu năng, chức năng, giao diện, trải nghiệm — tương đương Foxit. +4. Mỗi tính năng phải có **test/nghiệm thu** chứng minh đạt chuẩn Foxit trước khi coi là xong; nêu rõ phần nào chưa đạt (nếu tạm thời) và kế hoạch đạt 100%. +5. Không dùng dialog trình duyệt (prompt/alert) thay cho UI chuyên nghiệp. + +## CHECKLIST GẮN KÈM MỌI TASK +- [ ] Đã nghiên cứu Foxit làm tính năng này thế nào? +- [ ] UI/thao tác/tuỳ chọn có tương đương Foxit? +- [ ] Có vướng thư viện không? Nếu có, đã patch/đổi/tự-code (KHÔNG cắt giảm)? +- [ ] Có test/nghiệm thu so với chuẩn Foxit? +- [ ] Hiệu năng & trải nghiệm mượt như Foxit? diff --git a/scripts/fetch-pdfium.ps1 b/scripts/fetch-pdfium.ps1 new file mode 100644 index 0000000..4f1616f --- /dev/null +++ b/scripts/fetch-pdfium.ps1 @@ -0,0 +1,24 @@ +# Tải PDFium prebuilt (bblanchon/pdfium-binaries) cho Windows x64 +# và đặt pdfium.dll vào thư mục gốc workspace để ff-engine nạp được. +# +# Dùng: powershell -ExecutionPolicy Bypass -File scripts/fetch-pdfium.ps1 + +$ErrorActionPreference = "Stop" +$root = Split-Path -Parent $PSScriptRoot +$pdfiumDir = Join-Path $root "pdfium" +$tmp = Join-Path $env:TEMP "pdfium-win-x64.tgz" +$url = "https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-win-x64.tgz" + +Write-Output "Tải PDFium từ: $url" +Invoke-WebRequest -Uri $url -OutFile $tmp -UseBasicParsing + +New-Item -ItemType Directory -Force -Path $pdfiumDir | Out-Null +Write-Output "Giải nén vào: $pdfiumDir" +tar -xzf $tmp -C $pdfiumDir + +$dll = Join-Path $pdfiumDir "bin\pdfium.dll" +if (-not (Test-Path $dll)) { throw "Không tìm thấy pdfium.dll sau khi giải nén ($dll)" } + +# Copy pdfium.dll ra gốc workspace để bind_pdfium tìm thấy trong cwd. +Copy-Item $dll (Join-Path $root "pdfium.dll") -Force +Write-Output "Xong. pdfium.dll đã đặt tại gốc workspace: $(Join-Path $root 'pdfium.dll')"