Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ab3d17e067 | |||
| f864f15d79 | |||
| 402bb38a59 | |||
| e51ad0cd72 | |||
| 664c0dc1cb |
@@ -0,0 +1,18 @@
|
||||
# Strip upstream (ArtCraft / Discord) branding. Run: perl tools/craft-skills/skills/debrand/debrand.pl . (--check in CI)
|
||||
delete docs/brand
|
||||
# MIT/Apache texts stay verbatim. The copyright holder line stays everywhere (legal requirement).
|
||||
keep ^(LICENSE-(MIT|APACHE)|\.debrand)$
|
||||
dropline ^crates/ui-egui/src/i18n/.*\.tsv$ :: \t.*(?:ArtCraft|Discord)
|
||||
dropline ^ATTRIBUTION\.md$ :: \|\s*`docs/brand/
|
||||
sub (?s)\n\*\*One narrow exception: the ArtCraft brand\.\*\*.*?Never add other files under this licence[^\n]*\n =>
|
||||
sub (?s)\nThe ArtCraft name, wordmark and logos in docs/brand/.*?LICENSE-brand\.txt\.\n =>
|
||||
sub drawn in ArtCraft, vectorised => drawn by hand, vectorised
|
||||
sub drawn in ArtCraft and vectorised => drawn by hand and vectorised
|
||||
sub drawn by the project owner in ArtCraft; => drawn by the project owner;
|
||||
sub made in ArtCraft \( => drawn by hand (
|
||||
sub , and the ArtCraft mark \(Storyteller trademark from docs/brand/, not covered by this licence\) =>
|
||||
sub \n[ ]*- Community links: Discord button in the title bar, plus Home, About, Help menu, CLI and README\. =>
|
||||
sub https://getartcraft\.com/apps/pdfcraft => https://github.com/storytold/pdfcraft
|
||||
sub https://discord\.gg/artcraft => https://github.com/storytold/pdfcraft/issues
|
||||
forbid (?i)artcraft(?! Team and the PdfCraft contributors)
|
||||
forbid (?i)discord
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "tools/craft-skills"]
|
||||
path = tools/craft-skills
|
||||
url = https://git.marcospaulo.dev.br/storytold/craft-skills.git
|
||||
@@ -37,8 +37,6 @@ Every asset must be one of:
|
||||
- **Public domain.**
|
||||
- **Contributor-original:** created, photographed or generated by a contributor who owns it and licenses it under the project licence (`MIT OR Apache-2.0`).
|
||||
|
||||
**One narrow exception: the ArtCraft brand.** The ArtCraft name, wordmark and logos in `docs/brand/` are trademarks of the ArtCraft Team and are **not** open source (manifest identifier `LicenseRef-Storyteller-Trademark`, terms in `docs/brand/LICENSE-brand.txt`). They may be used only unmodified, only within PdfCraft, and only as `kind = "logo"` entries from that directory, to identify the project. Forks and modified versions must remove them. Never add other files under this licence, and never modify the logos.
|
||||
|
||||
Anything else is forbidden, including assets whose licence you cannot prove from the source. Examples:
|
||||
- system fonts (Apple, Microsoft, Google Android system UI fonts that are not openly licensed);
|
||||
- emoji artwork from Apple, Microsoft or Samsung;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Every asset PdfCraft includes, bundles or uses to build its published material, with its author, source and licence. The policy is in [AGENTS.md](AGENTS.md) §1. The machine-readable list, with SHA-256 hashes, is [ATTRIBUTION.toml](ATTRIBUTION.toml). Licence texts are kept beside the assets and summarised in [NOTICE](NOTICE).
|
||||
|
||||
## In this repository (269)
|
||||
## In this repository (261)
|
||||
|
||||
| Asset | Title | Author | Licence | Source | Used for |
|
||||
|---|---|---|---|---|---|
|
||||
@@ -222,30 +222,22 @@ Every asset PdfCraft includes, bundles or uses to build its published material,
|
||||
| `vendor/hayro-interpret/assets/FoxitSymbol.pfb` | FoxitSymbol (standard-14 substitute font) | Foxit Software Inc. / PDFium Authors | BSD-3-Clause | https://pdfium.googlesource.com/pdfium (via hayro-interpret 0.7.0 assets/) | Renders non-embedded standard-14 fonts (vendored hayro-interpret) |
|
||||
| `vendor/hayro-interpret/assets/CGATS001Compat-v2-micro.icc` | CGATS001Compat v2 micro ICC profile | Clinton Ingram (saucecontrol/Compact-ICC-Profiles) | CC0-1.0 | https://github.com/saucecontrol/Compact-ICC-Profiles | Default CMYK colour conversion (vendored hayro-interpret) |
|
||||
| `vendor/hayro-interpret/assets/LAB.icc` | Lab abstract ICC profile | The Hayro Authors (generated with LittleCMS 2) | MIT OR Apache-2.0 | https://github.com/LaurenzV/hayro (hayro-interpret 0.7.0 assets/) | Lab colour space conversion (vendored hayro-interpret) |
|
||||
| `docs/brand/artcraft-logo-white.png` | ArtCraft brand: artcraft-logo-white | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-logo-white.svg` | ArtCraft brand: artcraft-logo-white | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-logo.png` | ArtCraft brand: artcraft-logo | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-logo.svg` | ArtCraft brand: artcraft-logo | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-mark-black.png` | ArtCraft brand: artcraft-mark-black | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-mark-black.svg` | ArtCraft brand: artcraft-mark-black | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-mark.png` | ArtCraft brand: artcraft-mark | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `docs/brand/artcraft-mark.svg` | ArtCraft brand: artcraft-mark | ArtCraft Team | LicenseRef-Storyteller-Trademark | ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it. |
|
||||
| `assets/app-icon/pdfcraft.svg` | PdfCraft app icon (master vector) | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Master artwork; every other app-icon file is rendered from it (packaging/icons.sh) |
|
||||
| `assets/app-icon/pdfcraft-small.svg` | PdfCraft app icon (light vector) | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | README header and assets/app-icon/README.md |
|
||||
| `assets/app-icon/pdfcraft-1024.png` | PdfCraft app icon, 1024 px on Apple's icon grid | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Runtime window/Dock icon on macOS (apps/pdfcraft/src/main.rs) |
|
||||
| `assets/app-icon/pdfcraft.icns` | PdfCraft app icon (macOS .icns) | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | macOS app bundle icon |
|
||||
| `assets/app-icon/pdfcraft.ico` | PdfCraft app icon (Windows .ico, 16-256 px) | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Embedded in pdfcraft.exe by apps/pdfcraft/build.rs (Explorer, taskbar, Start menu, Alt-Tab) |
|
||||
| `assets/app-icon/pdfcraft.svg` | PdfCraft app icon (master vector) | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Master artwork; every other app-icon file is rendered from it (packaging/icons.sh) |
|
||||
| `assets/app-icon/pdfcraft-small.svg` | PdfCraft app icon (light vector) | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | README header and assets/app-icon/README.md |
|
||||
| `assets/app-icon/pdfcraft-1024.png` | PdfCraft app icon, 1024 px on Apple's icon grid | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Runtime window/Dock icon on macOS (apps/pdfcraft/src/main.rs) |
|
||||
| `assets/app-icon/pdfcraft.icns` | PdfCraft app icon (macOS .icns) | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | macOS app bundle icon |
|
||||
| `assets/app-icon/pdfcraft.ico` | PdfCraft app icon (Windows .ico, 16-256 px) | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Embedded in pdfcraft.exe by apps/pdfcraft/build.rs (Explorer, taskbar, Start menu, Alt-Tab) |
|
||||
| `assets/app-icon/pdfcraft-document.svg` | PdfCraft PDF document icon (master vector) | Lucide Icons and Contributors (document outline); PdfCraft contributors (PDF badge, lettering and composition) | ISC AND (MIT OR Apache-2.0) | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/file-text.svg); contributor-original composition (assets/app-icon/README.md) | Master artwork for the Windows PDF file type icon; rendered by packaging/icons.sh, without fonts or external images |
|
||||
| `assets/app-icon/pdfcraft-document.ico` | PdfCraft PDF document icon (Windows .ico, 16-256 px) | Lucide Icons and Contributors (document outline); PdfCraft contributors (PDF badge, lettering and composition) | ISC AND (MIT OR Apache-2.0) | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/file-text.svg); contributor-original composition (assets/app-icon/README.md) | Embedded in pdfcraft.exe as resource 2; the Windows installer uses it for PdfCraft.Document and Applications/pdfcraft.exe PDF file associations |
|
||||
| `assets/app-icon/hicolor/16x16/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 16 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/24x24/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 24 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/32x32/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 32 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/48x48/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 48 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 64 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/128x128/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 128 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/256x256/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 256 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop); runtime window icon on Windows and Linux (apps/pdfcraft/src/main.rs) |
|
||||
| `assets/app-icon/hicolor/512x512/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 512 px | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/scalable/apps/ai.storyteller.pdfcraft.svg` | PdfCraft app icon (Linux scalable) | PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/16x16/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 16 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/24x24/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 24 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/32x32/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 32 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/48x48/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 48 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 64 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/128x128/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 128 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/256x256/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 256 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop); runtime window icon on Windows and Linux (apps/pdfcraft/src/main.rs) |
|
||||
| `assets/app-icon/hicolor/512x512/apps/ai.storyteller.pdfcraft.png` | PdfCraft app icon, 512 px | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `assets/app-icon/hicolor/scalable/apps/ai.storyteller.pdfcraft.svg` | PdfCraft app icon (Linux scalable) | PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.pdfcraft.desktop) |
|
||||
| `docs/images/pdfcraft-bookmarks.png` | PdfCraft screenshot: Bookmarks | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: navigation. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-dark.png` | PdfCraft screenshot: Dark theme | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: themes. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-find.png` | PdfCraft screenshot: Find text | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: search. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
@@ -256,7 +248,7 @@ Every asset PdfCraft includes, bundles or uses to build its published material,
|
||||
| `docs/images/pdfcraft-properties.png` | PdfCraft screenshot: Document properties | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: metadata. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-scripts.png` | PdfCraft screenshot: Scripts of the world | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: rendering. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-split.png` | PdfCraft screenshot: Split dialog | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: split. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-tools.png` | PdfCraft screenshot: All tools | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: tool catalogue. Shows PdfCraft UI, Lucide icons, the showcase PDF built from the [[fetched]] OFL fonts, and the ArtCraft mark (Storyteller trademark from docs/brand/, not covered by this licence) |
|
||||
| `docs/images/pdfcraft-tools.png` | PdfCraft screenshot: All tools | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: tool catalogue. Shows PdfCraft UI, Lucide icons, the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-twoup.png` | PdfCraft screenshot: Two-up reading | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: layouts. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `docs/images/pdfcraft-viewer.png` | PdfCraft screenshot: Viewer with comments | PdfCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README hero. Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts |
|
||||
| `assets/icons/pin.svg` | Lucide icon "pin" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/pin.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
|
||||
@@ -7,7 +7,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Greek UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "23a9402d3ebbcff69aed133706e6e428a804ae06a7dba4923892cca5c98e92d1"
|
||||
sha256 = "3921fe79c00778e37c1e406c7cb55cb4302179a77a5e3858002b08fa36e8acac"
|
||||
|
||||
# ATTRIBUTION.toml: one entry per asset (AGENTS.md §1). The source of truth for provenance and licences.
|
||||
# ATTRIBUTION.md is generated from this file: `cargo xtask assets --write`. Checked by `cargo xtask assets` (part of `xtask ci`).
|
||||
@@ -30,7 +30,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Simplified Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "1863437c886142b2bccce3f44a538ae80d0ceea81074b84dfdfe8d9a4a4227ab"
|
||||
sha256 = "f5fad6bb00197e9f2838ee7993793934931c544df26260af3c608ebf496000a4"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/zh-hant.tsv"
|
||||
@@ -41,7 +41,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Traditional Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "6c8604d5cd71412c6a673b75001c7ef629727839eca1449147c7d6ec4bf0be99"
|
||||
sha256 = "99948b56b54e4c7404487dac789d4d2ea6db6c974f98446431e27058ba0581e0"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/cs.tsv"
|
||||
@@ -52,7 +52,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Czech UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "5ae2e315a9b99b4c0dfaf7be019c4d430ace17b4fbbfea5a2779b3e972846a21"
|
||||
sha256 = "4d596b908be29b5c8ea19adcb477b2fcfeae950aa6c7d61bd3ac00282e5c1a0e"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/pt-br.tsv"
|
||||
@@ -63,7 +63,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Brazilian Portuguese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "8b9e22fa25339e4aedb0542b8bf6f68dfd97bc3634105199e1951475e30eed53"
|
||||
sha256 = "068006b48bc0b51ae48f58f63953aab01836368f449c9ee7f6b4e75bfdf792c5"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/es.tsv"
|
||||
@@ -74,7 +74,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Spanish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "6d81592677f2b4eb3b97ba5810de9752da969545d91897e27033f37310696ffc"
|
||||
sha256 = "5ddbeb437aa0484ca00eeb8c43626c93ea791ad33df2e87dfa3f21ee90fef888"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/fr.tsv"
|
||||
@@ -85,7 +85,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "French UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "fb9c91a98c6975bc24249e8ae750fd46b9245ac5d2d7381f1e21319b9adbcaac"
|
||||
sha256 = "afa4783cbf25c4ea565ebb5054d17e7d788385f84fb3c36d5df43590b692b7e7"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/de.tsv"
|
||||
@@ -96,7 +96,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "German UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "f36aefae1a1ba6d576a4647fbfdd65b9b5086bfb266ea260e513244adc7af05a"
|
||||
sha256 = "d87786458823f73edc272c16867a34af92b5d0f44dae0c2da2e32979882772b8"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/te.tsv"
|
||||
@@ -107,7 +107,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Telugu UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "656940b456a6c2401f8bd3107a71cedcae5e52cd446e86e806285b6322d8ed8e"
|
||||
sha256 = "be81007bd64aa19869644c8dc67fa8e86517cacae64e16f40224b7cf5532b874"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/it.tsv"
|
||||
@@ -118,7 +118,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Italian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "14884c08a550600d310a794ceb0b2bb864987a074178ee49b657578b66625bef"
|
||||
sha256 = "08f69d32e8096e1e6e8a5b229f421ac7bd0a9a181fd348c4cf00743f99a621da"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/pl.tsv"
|
||||
@@ -129,7 +129,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Polish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "be960bdf9b6eeac2d95db91325076ee79c9b2efdcc4e459c7400e7ddb05fab3a"
|
||||
sha256 = "ea41c8ac1686df513d3a9a5df532a8ea1b5593d2f17cab8dd092b59078800920"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ru.tsv"
|
||||
@@ -140,7 +140,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Russian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "bada9b6f0b3775e4dab1213d9759070f7551d8a6142de10159268c88a04d3f0c"
|
||||
sha256 = "14d2b860c7a41a9ee97693f06bcb9883fb0473c081969ccc2856d58f1638f0d5"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/hu.tsv"
|
||||
@@ -151,7 +151,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Hungarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "efb75d8575df9e1dd4610602f20545b3a14a3a0814060efc27eb7cab591ccccb"
|
||||
sha256 = "fc8677aae2b865da4ef33f7e37d98d1192e42a142eb28cfcb634d66c1b01893c"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/bg.tsv"
|
||||
@@ -162,7 +162,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Bulgarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "ca305b188abc8d9c261901dde10f7cd8518520983fdf88d2358374b352ad3d5a"
|
||||
sha256 = "92bb4043ba29387002e72f25534554dfea145b672c1661f1e22ff211b17467da"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/kk.tsv"
|
||||
@@ -173,7 +173,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Kazakh UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "77afe7d7fa215c99e8e627a758178d79c51e08e33564e00b97b8840aeb91a9dd"
|
||||
sha256 = "af65b636ec28f5090305fc31530ab6d55d506ec9c6d70ced4ca06833e7b33f2a"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ja.tsv"
|
||||
@@ -184,7 +184,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Japanese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "f004b06f4e7eb8f4a99e22e1abfd97c95795b2215080e4008574522e54eda74c"
|
||||
sha256 = "d5ef8c9e6fbd6cff1def83db9504831515e581596f3b3a24fdc8ebc96d374d78"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/uk.tsv"
|
||||
@@ -195,7 +195,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Ukrainian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "cd9ecaf661533cbd3b055cfd3994602f6739c83061d1e225ba43ee6f229068cf"
|
||||
sha256 = "bfa948a04194a55672be730d4a441541eecef7bfbe9d6b30be031c823e272f4d"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ar.tsv"
|
||||
@@ -206,7 +206,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Arabic UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "a8a66390b2d80b4708c4f854318b923eef7f0f5932439fb5ef25f2651980f24e"
|
||||
sha256 = "31d173155c9d515da9a197c48465b39a9914be81d7f337699a88355610807a29"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/tr.tsv"
|
||||
@@ -217,7 +217,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Turkish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "5688538845a80c154feabd096badbf097485dea8a7402fede4ef7d71466e9d6a"
|
||||
sha256 = "84b13198f333575af3b8762f9ac5c3cc7b7a26e172b806ba64b32b80e07d6a91"
|
||||
|
||||
[[asset]]
|
||||
path = "assets/icons/accessibility.svg"
|
||||
@@ -2698,98 +2698,10 @@ kind = "font"
|
||||
usage = "Showcase PDF (cargo xtask demo-pdf)"
|
||||
sha256 = "acd98e64795781b2058f07b18475e0ecee2a0fe2b42a49e2f9e37d0d6bf66ce6"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-logo-white.png"
|
||||
title = "ArtCraft brand: artcraft-logo-white"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "8b86aeb06a12a90ba77a60e0d90329272310e244ee5c1f9b161b391280ca79d8"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-logo-white.svg"
|
||||
title = "ArtCraft brand: artcraft-logo-white"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "a3e03dc49f9ad4225b8517d5424309c8d1c864d3996d862190d9cc797d5af427"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-logo.png"
|
||||
title = "ArtCraft brand: artcraft-logo"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "08fc6d9d3717e8f13417bac6f9025b50e11d1e0b32e9e000883d2fe0c4a0c67b"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-logo.svg"
|
||||
title = "ArtCraft brand: artcraft-logo"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "3188971e1affdf4f6be4fa65f715376a7a305e6aa741ec78b0296c8f934eff08"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-mark-black.png"
|
||||
title = "ArtCraft brand: artcraft-mark-black"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "5954cc0306e1b9d7beb47097e2e842157113a39d9aba078b57304902687936a9"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-mark-black.svg"
|
||||
title = "ArtCraft brand: artcraft-mark-black"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "570adcb4f7ba8ca0647f97074476bab81d3272988f1cdee52efa21bf026036a4"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-mark.png"
|
||||
title = "ArtCraft brand: artcraft-mark"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "9d372157a949c147318561e629b11561c28b7cbc14c84b516a3fe6e84d8fbbad"
|
||||
|
||||
[[asset]]
|
||||
path = "docs/brand/artcraft-mark.svg"
|
||||
title = "ArtCraft brand: artcraft-mark"
|
||||
author = "ArtCraft Team"
|
||||
source = "ArtCraft Team brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft)"
|
||||
licence = "LicenseRef-Storyteller-Trademark"
|
||||
licence_file = "docs/brand/LICENSE-brand.txt"
|
||||
kind = "logo"
|
||||
usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. ArtCraft Team trademark, not open source; may be used only unmodified within PdfCraft; forks and modified versions must remove it."
|
||||
sha256 = "f87af81b6fa411da8820eed2bfdcc54c0ee9cd453b4e868c64f56c69db142d0e"
|
||||
|
||||
[[asset]]
|
||||
path = "assets/app-icon/pdfcraft.svg"
|
||||
title = "PdfCraft app icon (master vector)"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2800,7 +2712,7 @@ sha256 = "52b384a10a2a7fdd3145d9822972cfd568ef0cb7312549bd4399addd89d45a6d"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/pdfcraft-small.svg"
|
||||
title = "PdfCraft app icon (light vector)"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2811,7 +2723,7 @@ sha256 = "b036304c11ef5dcad36636d06ca0bf331b51e47650d25d3c916a0e1eabf544c7"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/pdfcraft-1024.png"
|
||||
title = "PdfCraft app icon, 1024 px on Apple's icon grid"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2822,7 +2734,7 @@ sha256 = "da577d3f21fbcf5c739067787a9e683be2b064d76813b5d5fec9074a7a106538"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/pdfcraft.icns"
|
||||
title = "PdfCraft app icon (macOS .icns)"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2833,7 +2745,7 @@ sha256 = "2425148222873de241d267aba667a8b234ecdd0149f2ca8bb6e79443b743b1e8"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/pdfcraft.ico"
|
||||
title = "PdfCraft app icon (Windows .ico, 16-256 px)"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2866,7 +2778,7 @@ sha256 = "ba3f9128b368fc6d17d376cf62dbdbc22455451c5c8c4779210d7a2a7409b9e6"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/16x16/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 16 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2877,7 +2789,7 @@ sha256 = "9b77095cbe75dcba6b74a1fdcd4064812850efaf7a12edebefc9ded5eabb49da"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/24x24/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 24 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2888,7 +2800,7 @@ sha256 = "a4cd466687f6c5cb59eef3fc564bdba1c8f0d9e324754eeebab82f18823efae7"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/32x32/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 32 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2899,7 +2811,7 @@ sha256 = "e22279013a5ed5c02571e1e4e9bc4cef9aa0847fcb733a285b2916fabd16bf78"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/48x48/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 48 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2910,7 +2822,7 @@ sha256 = "55daf2d5575f6c4e4c4975c9f1c74231178f1801963a8b19f68dfa9bc50cb22f"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 64 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2921,7 +2833,7 @@ sha256 = "2975c200f341e247b5fa18f568fb27d390e3fa01e9b2ad37acb48d0e1cc8a124"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/128x128/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 128 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2932,7 +2844,7 @@ sha256 = "6ef927ca252b40bc9b5d8843d84137334362f8aa1acbb1bf8c15a02affd25b2b"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/256x256/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 256 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2943,7 +2855,7 @@ sha256 = "cde7ee8c5ee38f9fc40a429fd9e6d99a035bcd321701fce331bb13bac126614d"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/512x512/apps/ai.storyteller.pdfcraft.png"
|
||||
title = "PdfCraft app icon, 512 px"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -2954,7 +2866,7 @@ sha256 = "5ede733e93b96f4eb8d94299232cf2f9605fa19b0d913f95fe9828c316a2d066"
|
||||
[[asset]]
|
||||
path = "assets/app-icon/hicolor/scalable/apps/ai.storyteller.pdfcraft.svg"
|
||||
title = "PdfCraft app icon (Linux scalable)"
|
||||
author = "PdfCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)"
|
||||
author = "PdfCraft contributors (drawn by the project owner; vectorised with craftrules vectorize_tile.py)"
|
||||
source = "Contributor-original (see assets/app-icon/README.md)"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "assets/app-icon/LICENSE.txt"
|
||||
@@ -3080,7 +2992,7 @@ source = "this repository"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "image"
|
||||
usage = "README: tool catalogue. Shows PdfCraft UI, Lucide icons, the showcase PDF built from the [[fetched]] OFL fonts, and the ArtCraft mark (Storyteller trademark from docs/brand/, not covered by this licence)"
|
||||
usage = "README: tool catalogue. Shows PdfCraft UI, Lucide icons, the showcase PDF built from the [[fetched]] OFL fonts"
|
||||
sha256 = "61731a921902e285d40826d401f1ef25624dabb8c8ac1f8f0c09c1292a17ee1a"
|
||||
|
||||
[[asset]]
|
||||
@@ -3339,4 +3251,4 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Slovene UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "8590f5acce1da70d6a3ce58de073bf4f86815651ff74a59625980c6c52e051b7"
|
||||
sha256 = "2446e6fc374a36b1dcc385a4ea3c57a52d188fa3a245221c54a2f51d5cfb78f4"
|
||||
|
||||
@@ -1093,7 +1093,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-ui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=5c874d51eeb3de70e735c8ce87a59a7dedd47675#5c874d51eeb3de70e735c8ce87a59a7dedd47675"
|
||||
source = "git+https://git.marcospaulo.dev.br/masi/craft-libs?rev=22544b6d619d4f16779b8bdfa3f0b642a86fc065#22544b6d619d4f16779b8bdfa3f0b642a86fc065"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"serde",
|
||||
@@ -3552,7 +3552,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -3572,7 +3572,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-a11y"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-content",
|
||||
"pdfcraft-cos",
|
||||
@@ -3583,7 +3583,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-annot"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"hayro-syntax",
|
||||
"pdfcraft-cos",
|
||||
@@ -3594,7 +3594,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-audit"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-content",
|
||||
"pdfcraft-cos",
|
||||
@@ -3605,7 +3605,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-automation"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"image",
|
||||
@@ -3622,7 +3622,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-cli"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"pdfcraft-audit",
|
||||
@@ -3637,18 +3637,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-compare"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-content"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-cos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-cos"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"hayro-syntax",
|
||||
"pdfcraft-crypt",
|
||||
@@ -3660,7 +3660,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-create"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"hayro-syntax",
|
||||
@@ -3675,7 +3675,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-crypt"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"md-5",
|
||||
@@ -3687,7 +3687,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-edit"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"hayro-syntax",
|
||||
"pdfcraft-annot",
|
||||
@@ -3701,7 +3701,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-engine"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"icu_properties",
|
||||
@@ -3738,14 +3738,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-export"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-filters"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"proptest",
|
||||
@@ -3755,7 +3755,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-fonts"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"harfrust",
|
||||
"pdfcraft-cos",
|
||||
@@ -3764,7 +3764,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-forms"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"hayro-syntax",
|
||||
"pdfcraft-content",
|
||||
@@ -3776,18 +3776,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-geom"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-js"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"boa_engine",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-measure"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-annot",
|
||||
"pdfcraft-content",
|
||||
@@ -3799,14 +3799,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-model"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-cos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-ocr"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"ocrs",
|
||||
"pdfcraft-fonts",
|
||||
@@ -3816,7 +3816,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-optimize"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"image",
|
||||
"pdfcraft-annot",
|
||||
@@ -3829,7 +3829,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-organize"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"hayro-syntax",
|
||||
"pdfcraft-content",
|
||||
@@ -3839,7 +3839,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-platform"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"futures-lite",
|
||||
@@ -3848,7 +3848,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-preflight"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-cos",
|
||||
"pdfcraft-model",
|
||||
@@ -3856,7 +3856,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-print"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-content",
|
||||
"pdfcraft-cos",
|
||||
@@ -3866,7 +3866,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-redact"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-annot",
|
||||
"pdfcraft-content",
|
||||
@@ -3880,7 +3880,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-render"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"flate2",
|
||||
@@ -3898,7 +3898,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-sign"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"aws-lc-rs",
|
||||
@@ -3932,7 +3932,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-ui-egui"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"base64 0.22.1",
|
||||
@@ -3972,7 +3972,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-web"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -3984,7 +3984,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-xfa"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"image",
|
||||
@@ -3998,7 +3998,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pdfcraft-xfdf"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
dependencies = [
|
||||
"pdfcraft-annot",
|
||||
"pdfcraft-cos",
|
||||
|
||||
@@ -5,7 +5,7 @@ exclude = ["vendor"]
|
||||
default-members = ["crates/*", "apps/pdfcraft", "apps/pdfcraft-cli", "xtask"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
rust-version = "1.90"
|
||||
@@ -13,7 +13,7 @@ repository = "https://github.com/storytold/pdfcraft"
|
||||
|
||||
[workspace.dependencies]
|
||||
# Shared frontend components; engines remain independent of egui.
|
||||
craft-ui = { git = "https://github.com/storytold/craft-libs", version = "0.1.0", rev = "5c874d51eeb3de70e735c8ce87a59a7dedd47675", features = ["serde"] }
|
||||
craft-ui = { git = "https://git.marcospaulo.dev.br/masi/craft-libs", version = "0.1.0", rev = "22544b6d619d4f16779b8bdfa3f0b642a86fc065", features = ["serde"] }
|
||||
# internal
|
||||
pdfcraft-geom = { path = "crates/geom", version = "0.6.0" }
|
||||
pdfcraft-filters = { path = "crates/filters", version = "0.6.0" }
|
||||
|
||||
@@ -3,10 +3,6 @@ Copyright (c) 2026 ArtCraft Team and the PdfCraft contributors.
|
||||
Licensed under the MIT License or the Apache License, Version 2.0, at your option
|
||||
(LICENSE-MIT, LICENSE-APACHE).
|
||||
|
||||
The ArtCraft name, wordmark and logos in docs/brand/ are trademarks of the ArtCraft Team. They are
|
||||
not open source and are not covered by the license above; their terms are in
|
||||
docs/brand/LICENSE-brand.txt.
|
||||
|
||||
Third-party material
|
||||
|
||||
This product bundles third-party material under its own licenses, listed below. The per-file
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="docs/brand/artcraft-logo-white.svg">
|
||||
<img alt="ArtCraft" src="docs/brand/artcraft-logo.svg" width="200">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
<h1 align="center">PdfCraft</h1>
|
||||
|
||||
<p align="center">
|
||||
@@ -23,16 +13,6 @@
|
||||
<img alt="No account, no telemetry" src="https://img.shields.io/badge/no%20account-no%20telemetry-0a7563">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><img alt="Join the ArtCraft community on Discord" src="https://img.shields.io/badge/Join%20us%20on%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" height="40"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/apps/pdfcraft"><b>PdfCraft on getartcraft.com</b></a> ·
|
||||
<a href="https://getartcraft.com/">ArtCraft</a> ·
|
||||
<a href="https://getartcraft.com/apps">All Crafting Apps</a>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
@@ -41,10 +21,6 @@
|
||||
<sub>The PdfCraft Showcase, a 13-page specimen PDF, open with the All tools panel and threaded comments.</sub>
|
||||
</p>
|
||||
|
||||
> [!NOTE]
|
||||
> **ArtCraft is a community of artists from all walks of life.** Digital, generative, music,
|
||||
> games — if you make things, you're one of us. **[Come say hi on Discord](https://discord.gg/artcraft).**
|
||||
|
||||
<p align="center">
|
||||
<a href="#highlights">Highlights</a> ·
|
||||
<a href="#read-anything-beautifully">Read</a> ·
|
||||
@@ -64,16 +40,6 @@
|
||||
|
||||
---
|
||||
|
||||
## Community
|
||||
|
||||
PdfCraft is part of [ArtCraft](https://getartcraft.com). Come say hello, get help and follow development:
|
||||
|
||||
- **Discord: [discord.gg/artcraft](https://discord.gg/artcraft)**. This is the fastest way to get help and share feedback. The app has a Discord button in its title bar.
|
||||
- **Web page:** [getartcraft.com/apps/pdfcraft](https://getartcraft.com/apps/pdfcraft)
|
||||
- **Source:** [github.com/storytold/pdfcraft](https://github.com/storytold/pdfcraft)
|
||||
|
||||
The ArtCraft name and logos in `docs/brand/` are trademarks of the ArtCraft Team and are not open source. They may be used only unmodified, and only as part of PdfCraft (see `docs/brand/LICENSE-brand.txt`). Forks and modified versions must remove them.
|
||||
|
||||
## Highlights
|
||||
|
||||
<table>
|
||||
@@ -428,9 +394,7 @@ The summary is in **[ROADMAP.md](ROADMAP.md)**; the full assessment by dimension
|
||||
|
||||
## Downloads
|
||||
|
||||
**New to PdfCraft?** Download it from the [PdfCraft page on getartcraft.com](https://getartcraft.com/apps/pdfcraft). That's the easiest way to install it.
|
||||
|
||||
**Want a specific build or format?** On GitHub, the [latest release](https://github.com/storytold/pdfcraft/releases/latest) has every build listed below, and [all releases](https://github.com/storytold/pdfcraft/releases) has earlier versions and their notes. `<ver>` in the file names is the version number, and `SHA256SUMS.txt` lists a checksum for every file.
|
||||
On GitHub, the [latest release](https://github.com/storytold/pdfcraft/releases/latest) has every build listed below, and [all releases](https://github.com/storytold/pdfcraft/releases) has earlier versions and their notes. `<ver>` in the file names is the version number, and `SHA256SUMS.txt` lists a checksum for every file.
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -494,42 +458,18 @@ Every other Linux build needs glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+, Fe
|
||||
## The Crafting Apps
|
||||
|
||||
PdfCraft is one of the **Crafting Apps**: free, open-source creative tools from the
|
||||
[ArtCraft](https://getartcraft.com/) team, each written from scratch in Rust and each able to
|
||||
[storytold](https://github.com/storytold) team, each written from scratch in Rust and each able to
|
||||
stand on its own.
|
||||
|
||||
| | App | What it's for | Code | Learn more |
|
||||
|:-:|---|---|---|---|
|
||||
| <img src="https://raw.githubusercontent.com/storytold/photocraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.photocraft.png" alt="" width="32" height="32"> | **PhotoCraft** | Image editing: layers, masks, type and real PSD files | [GitHub](https://github.com/storytold/photocraft) | [Website](https://getartcraft.com/apps/photocraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/vectorcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.vectorcraft.png" alt="" width="32" height="32"> | **VectorCraft** | Vector illustration | [GitHub](https://github.com/storytold/vectorcraft) | [Website](https://getartcraft.com/apps/vectorcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/filmcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.filmcraft.png" alt="" width="32" height="32"> | **FilmCraft** | Video editing, color and sound | [GitHub](https://github.com/storytold/filmcraft) | [Website](https://getartcraft.com/apps/filmcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/lightcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.lightcraft.png" alt="" width="32" height="32"> | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) | [Website](https://getartcraft.com/apps/lightcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/pdfcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png" alt="" width="32" height="32"> | **PdfCraft** | **Reading, organizing and protecting PDFs · you are here** | [GitHub](https://github.com/storytold/pdfcraft) | [Website](https://getartcraft.com/apps/pdfcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/effectcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.effectcraft.png" alt="" width="32" height="32"> | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) | [Website](https://getartcraft.com/apps/effectcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/designcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.designcraft.png" alt="" width="32" height="32"> | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) | [Website](https://getartcraft.com/apps/designcraft) |
|
||||
|
||||
And [**ArtCraft**](https://getartcraft.com/) itself, our AI image and video studio for artists who want real control.
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><img alt="Join the ArtCraft community on Discord" src="https://img.shields.io/badge/Join%20us%20on%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" height="40"></a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">Come make things with us</h3>
|
||||
|
||||
<p align="center">
|
||||
Our Discord is where artists of every kind hang out: people who paint, shoot, draw, cut film,
|
||||
set type, and people still figuring out what they like to make. Share what you're working on,
|
||||
ask for help, tell us what's broken, or tell us what you wish these tools could do.
|
||||
Whatever your medium and however long you've been at it, you're welcome here.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><b>discord.gg/artcraft</b></a> ·
|
||||
<a href="https://getartcraft.com/">getartcraft.com</a> ·
|
||||
<a href="https://getartcraft.com/apps">The Crafting Apps</a> ·
|
||||
<a href="https://getartcraft.com/apps/pdfcraft">PdfCraft</a>
|
||||
</p>
|
||||
| | App | What it's for | Code |
|
||||
|:-:|---|---|---|
|
||||
| <img src="https://raw.githubusercontent.com/storytold/photocraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.photocraft.png" alt="" width="32" height="32"> | **PhotoCraft** | Image editing: layers, masks, type and real PSD files | [GitHub](https://github.com/storytold/photocraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/vectorcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.vectorcraft.png" alt="" width="32" height="32"> | **VectorCraft** | Vector illustration | [GitHub](https://github.com/storytold/vectorcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/filmcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.filmcraft.png" alt="" width="32" height="32"> | **FilmCraft** | Video editing, color and sound | [GitHub](https://github.com/storytold/filmcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/lightcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.lightcraft.png" alt="" width="32" height="32"> | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/pdfcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png" alt="" width="32" height="32"> | **PdfCraft** | **Reading, organizing and protecting PDFs · you are here** | [GitHub](https://github.com/storytold/pdfcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/effectcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.effectcraft.png" alt="" width="32" height="32"> | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/designcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.designcraft.png" alt="" width="32" height="32"> | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) |
|
||||
|
||||
---
|
||||
|
||||
@@ -543,18 +483,7 @@ with its author, source and license in [ATTRIBUTION.md](ATTRIBUTION.md). Release
|
||||
the Japanese fonts of [craft-fonts](https://github.com/storytold/craft-fonts/blob/main/ATTRIBUTION.md)
|
||||
(SIL Open Font License 1.1).
|
||||
|
||||
The ArtCraft name, wordmark and logos in [`docs/brand/`](docs/brand/) are trademarks of the
|
||||
ArtCraft Team and are not covered by this license. They may be used only unmodified, and only as
|
||||
part of this repository and PdfCraft, under [`docs/brand/LICENSE-brand.txt`](docs/brand/LICENSE-brand.txt).
|
||||
Forks and modified versions must remove them.
|
||||
|
||||
<sub>Adobe, Photoshop, Illustrator, Premiere Pro, Lightroom, Acrobat, After Effects and InDesign are trademarks or registered trademarks of Adobe Inc. in the United States and/or other countries. PdfCraft is an independent, open-source project and is not affiliated with, sponsored by or endorsed by Adobe Inc.; these names are used only to describe the workflows it is compatible with.</sub>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/"><img alt="ArtCraft" src="docs/brand/artcraft-mark.svg" width="28"></a><br>
|
||||
<sub>Made by the <a href="https://getartcraft.com/">ArtCraft</a> team and community.</sub>
|
||||
</p>
|
||||
|
||||
Tools and Inspector panels can be dragged into tab groups, split beside the PDF, or floated within the app window. Read and full-screen modes keep their existing focused document view. Drag a panel header to a target edge or another header. Its context menu offers Float panel, Move to group, and Close panel. Existing panel toggles reopen panels at their saved location; Reset Panel Layout restores the app layout. Floating panels remain inside the current app window.
|
||||
|
||||
Advanced `ui.dock` operations use the same validated transaction as pointer gestures:
|
||||
|
||||
@@ -303,7 +303,6 @@ Newest first: the date, what moved, and the new overall estimate.
|
||||
- Bookmark editing and page numbering (Number pages), with undo, agent tools and UI.
|
||||
- A render watchdog: pathological pages are skipped after 20 s instead of spinning forever.
|
||||
- The agent control channel no longer reports success when the window is hidden.
|
||||
- Community links: Discord button in the title bar, plus Home, About, Help menu, CLI and README.
|
||||
- Overall ≈ 10%.
|
||||
- **2026-10-01 (session 6):**
|
||||
- UI control channel: agents can inspect the widget tree, click, type, press keys, run commands and take screenshots of the running app. Off unless the app is started with `--control`; loopback only, token-authenticated.
|
||||
|
||||
@@ -63,8 +63,7 @@ pdfcraft-cli run --script steps.json [--root DIR] [{\"tool\": \"doc_open
|
||||
mcp_usage!(),
|
||||
"\
|
||||
pdfcraft-cli ui --control FILE <method> [key=value …] [--out shot.png]
|
||||
drive a running app started with --control FILE
|
||||
help and feedback: https://discord.gg/artcraft"
|
||||
drive a running app started with --control FILE"
|
||||
);
|
||||
|
||||
fn main() -> ExitCode {
|
||||
@@ -142,8 +141,6 @@ fn stdout_line(line: std::fmt::Arguments<'_>) -> Result<(), CliError> {
|
||||
|
||||
fn version() -> Result<(), CliError> {
|
||||
stdout_line(format_args!("pdfcraft-cli {}", env!("CARGO_PKG_VERSION")))?;
|
||||
stdout_line(format_args!("Discord: {} (help and feedback)", pdfcraft_engine::links::DISCORD))?;
|
||||
stdout_line(format_args!("Web: {}", pdfcraft_engine::links::APP_PAGE))?;
|
||||
stdout_line(format_args!("Source: {}", pdfcraft_engine::links::GITHUB))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -64,6 +64,25 @@ fn settings_dir() -> Option<std::path::PathBuf> {
|
||||
eframe::storage_dir("PdfCraft")
|
||||
}
|
||||
|
||||
/// Windows and Linux: no OS title bar; the top row is the title bar
|
||||
/// (`pdfcraft_ui_egui::titlebar`). macOS keeps its traffic lights over the integrated top row.
|
||||
const CUSTOM_TITLEBAR: bool = !cfg!(target_os = "macos");
|
||||
|
||||
/// Whether this start draws its own title bar: Windows and Linux do, unless Preferences ▸ Appearance ▸
|
||||
/// Use System Title Bar asks for the system's. Read from the saved settings before the window
|
||||
/// opens; a missing or unreadable file keeps the default.
|
||||
fn custom_titlebar(settings_dir: Option<&std::path::Path>) -> bool {
|
||||
let system_title_bar = settings_dir
|
||||
.and_then(|d| std::fs::read_to_string(d.join("app.ron")).ok())
|
||||
.is_some_and(|s| {
|
||||
s.contains(r#"system_title_bar\":true"#)
|
||||
|| s.contains(r#"system_title_bar\": true"#)
|
||||
|| s.contains(r#""system_title_bar":true"#)
|
||||
|| s.contains(r#""system_title_bar": true"#)
|
||||
});
|
||||
CUSTOM_TITLEBAR && !system_title_bar
|
||||
}
|
||||
|
||||
/// Move the settings and crash-recovery folders of the app's former name, PrintCraft, to the new
|
||||
/// name once, so an upgrade keeps recent files, preferences and unsaved work. Best effort: a
|
||||
/// folder is left alone when the new one already exists or the move fails. A portable copy leaves
|
||||
@@ -188,7 +207,8 @@ fn main() -> eframe::Result {
|
||||
single_instance::Claim::Alone => None,
|
||||
};
|
||||
let choice = renderer_choice(std::env::var("PDFCRAFT_RENDERER").ok().as_deref());
|
||||
let launch = Launch { files, options, control_file, create_images, integrated };
|
||||
let custom_titlebar = custom_titlebar(settings_dir().as_deref());
|
||||
let launch = Launch { files, options, control_file, create_images, integrated, custom_titlebar };
|
||||
// Finder, Open With and the Dock deliver files as Apple events, not arguments; catch the one
|
||||
// that launched us as well as later ones. Lives until the event loop returns.
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -198,7 +218,7 @@ fn main() -> eframe::Result {
|
||||
let first = if choice == RendererChoice::Gl { eframe::Renderer::Glow } else { eframe::Renderer::Wgpu };
|
||||
let result = eframe::run_native(
|
||||
"PdfCraft",
|
||||
native_options(integrated, first),
|
||||
native_options(custom_titlebar, integrated, first),
|
||||
app_creator(
|
||||
launch.clone(),
|
||||
Rc::clone(&started),
|
||||
@@ -216,7 +236,7 @@ fn main() -> eframe::Result {
|
||||
log::error!("the GPU renderer (wgpu) didn't start: {e}. Starting with OpenGL instead; set PDFCRAFT_RENDERER=gl to skip wgpu.");
|
||||
eframe::run_native(
|
||||
"PdfCraft",
|
||||
native_options(integrated, eframe::Renderer::Glow),
|
||||
native_options(custom_titlebar, integrated, eframe::Renderer::Glow),
|
||||
app_creator(
|
||||
launch,
|
||||
started,
|
||||
@@ -256,7 +276,7 @@ fn retry_with_gl(choice: RendererChoice, app_started: bool) -> bool {
|
||||
}
|
||||
|
||||
/// The window and renderer settings for one run.
|
||||
fn native_options(integrated: bool, renderer: eframe::Renderer) -> eframe::NativeOptions {
|
||||
fn native_options(custom_titlebar: bool, integrated: bool, renderer: eframe::Renderer) -> eframe::NativeOptions {
|
||||
let mut viewport = egui::ViewportBuilder::default()
|
||||
.with_title("PdfCraft")
|
||||
.with_inner_size([1440.0, 920.0])
|
||||
@@ -269,7 +289,9 @@ fn native_options(integrated: bool, renderer: eframe::Renderer) -> eframe::Nativ
|
||||
Ok(icon) => viewport = viewport.with_icon(icon),
|
||||
Err(e) => log::warn!("app icon: {e}"),
|
||||
}
|
||||
if integrated {
|
||||
if custom_titlebar {
|
||||
viewport = viewport.with_decorations(false).with_fullsize_content_view(true).with_titlebar_shown(false).with_title_shown(false);
|
||||
} else if integrated {
|
||||
viewport = viewport.with_fullsize_content_view(true).with_titlebar_shown(false).with_title_shown(false);
|
||||
}
|
||||
let persistence_path = settings_dir().map(|d| d.join("app.ron"));
|
||||
@@ -289,6 +311,7 @@ struct Launch {
|
||||
control_file: Option<String>,
|
||||
create_images: bool,
|
||||
integrated: bool,
|
||||
custom_titlebar: bool,
|
||||
}
|
||||
|
||||
fn app_creator<'a>(
|
||||
@@ -297,7 +320,7 @@ fn app_creator<'a>(
|
||||
instance: Option<&'a single_instance::Server>,
|
||||
#[cfg(target_os = "macos")] apple_events: &'a apple_events::AppleEvents,
|
||||
) -> eframe::AppCreator<'a> {
|
||||
let Launch { files, options, control_file, create_images, integrated } = launch;
|
||||
let Launch { files, options, control_file, create_images, integrated, custom_titlebar } = launch;
|
||||
Box::new(move |cc| {
|
||||
started.set(true);
|
||||
let mut app = PdfCraftApp::new();
|
||||
@@ -311,6 +334,7 @@ fn app_creator<'a>(
|
||||
app.restore(&json);
|
||||
}
|
||||
app.integrated_titlebar = integrated;
|
||||
app.custom_titlebar = custom_titlebar;
|
||||
app.system_text_scale = text_scale::system();
|
||||
app.update_source = Some(std::sync::Arc::new(updates::latest_release));
|
||||
app.printer_source = Some(pdfcraft_ui_egui::system_printers());
|
||||
@@ -731,8 +755,8 @@ mod tests {
|
||||
assert!(!retry_with_gl(RendererChoice::Wgpu, false));
|
||||
assert!(!retry_with_gl(RendererChoice::Gl, false));
|
||||
// Each run states its renderer rather than relying on eframe's default.
|
||||
assert_eq!(native_options(false, eframe::Renderer::Wgpu).renderer, eframe::Renderer::Wgpu);
|
||||
assert_eq!(native_options(false, eframe::Renderer::Glow).renderer, eframe::Renderer::Glow);
|
||||
assert_eq!(native_options(false, false, eframe::Renderer::Wgpu).renderer, eframe::Renderer::Wgpu);
|
||||
assert_eq!(native_options(false, false, eframe::Renderer::Glow).renderer, eframe::Renderer::Glow);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -878,7 +902,7 @@ mod tests {
|
||||
// and an error wgpu raises before anything reaches the driver: a texture one pixel wider
|
||||
// than the device allows.
|
||||
use eframe::wgpu;
|
||||
let native = super::native_options(false, eframe::Renderer::Wgpu);
|
||||
let native = super::native_options(false, false, eframe::Renderer::Wgpu);
|
||||
let eframe::egui_wgpu::WgpuSetup::CreateNew(setup) = &native.wgpu_options.wgpu_setup else {
|
||||
panic!("default setup creates its own instance")
|
||||
};
|
||||
@@ -944,7 +968,7 @@ mod tests {
|
||||
#[test]
|
||||
fn pipeline_creation_error_is_returned_and_device_remains_usable() {
|
||||
use eframe::{egui_wgpu, wgpu};
|
||||
let mut native = super::native_options(false, eframe::Renderer::Wgpu);
|
||||
let mut native = super::native_options(false, false, eframe::Renderer::Wgpu);
|
||||
let egui_wgpu::WgpuSetup::CreateNew(setup) = &native.wgpu_options.wgpu_setup else { panic!("default setup creates its own instance") };
|
||||
let instance = pollster::block_on(native.wgpu_options.wgpu_setup.new_instance());
|
||||
let options = wgpu::RequestAdapterOptions { power_preference: setup.power_preference, ..Default::default() };
|
||||
@@ -1219,4 +1243,20 @@ mod tests {
|
||||
let class = entry.lines().find_map(|line| line.strip_prefix("StartupWMClass="));
|
||||
assert_eq!(class, Some(super::APP_ID));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_titlebar_detects_preferences() {
|
||||
let temp = std::env::temp_dir().join(format!("pdfcraft_test_titlebar_{}", std::process::id()));
|
||||
let _ = std::fs::create_dir_all(&temp);
|
||||
assert_eq!(super::custom_titlebar(Some(&temp)), super::CUSTOM_TITLEBAR);
|
||||
|
||||
std::fs::write(temp.join("app.ron"), r#"{"pdfcraft": "{\"system_title_bar\":true}"}"#).unwrap();
|
||||
assert!(!super::custom_titlebar(Some(&temp)));
|
||||
|
||||
std::fs::write(temp.join("app.ron"), r#"{"pdfcraft": "{\"system_title_bar\":false}"}"#).unwrap();
|
||||
assert_eq!(super::custom_titlebar(Some(&temp)), super::CUSTOM_TITLEBAR);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
PdfCraft app icon (pdfcraft.svg, pdfcraft-small.svg and every file derived from them in this
|
||||
directory: pdfcraft-1024.png, pdfcraft.icns, pdfcraft.ico, hicolor/).
|
||||
|
||||
Original artwork made for this project by the project owner, drawn in ArtCraft and vectorised for
|
||||
Original artwork made for this project by the project owner, drawn by hand and vectorised for
|
||||
PdfCraft (no third-party material). Licensed like the rest of PdfCraft, under either of
|
||||
|
||||
* Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
@@ -19,7 +19,7 @@ a full-bleed colour field, no frame or roundel, the animal looking at the viewer
|
||||
icons use the full-bleed tile. macOS icons put it on Apple's grid (an 824 px body centred on a transparent
|
||||
1024 px canvas).
|
||||
|
||||
**Provenance:** the project owner's original drawing, made in ArtCraft (2880 px, keyed to the palette), then
|
||||
**Provenance:** the project owner's original drawing, drawn by hand (2880 px, keyed to the palette), then
|
||||
vectorised with craftrules `assets/logo-options/_tools/vectorize_tile.py` (potrace; no filtering or
|
||||
warping). The source drawing is kept in craftrules at `assets/app-icons/pdfcraft/source.png`, not here.
|
||||
Licence: [LICENSE.txt](LICENSE.txt) (`MIT OR Apache-2.0`, like the repo).
|
||||
|
||||
@@ -131,7 +131,7 @@ impl McpServer {
|
||||
Ok(json!({
|
||||
"protocolVersion": version,
|
||||
"capabilities": { "tools": { "listChanged": false }, "resources": { "listChanged": false, "subscribe": false } },
|
||||
"serverInfo": { "name": "pdfcraft", "title": "PdfCraft", "version": env!("CARGO_PKG_VERSION"), "websiteUrl": pdfcraft_engine::links::APP_PAGE },
|
||||
"serverInfo": { "name": "pdfcraft", "title": "PdfCraft", "version": env!("CARGO_PKG_VERSION"), "websiteUrl": pdfcraft_engine::links::GITHUB },
|
||||
"instructions": if self.compact { format!("{INSTRUCTIONS}{COMPACT_INSTRUCTIONS}") } else { INSTRUCTIONS.to_string() },
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -353,10 +353,7 @@ pub const COMMANDS: &[CommandSpec] = &[
|
||||
c("page.split", "Split document…", PAGES, None, Assembly, "scissors"),
|
||||
c("page.number", "Number pages…", PAGES, None, Assembly, "hash"),
|
||||
c("help.shortcuts", "Keyboard shortcuts", HELP, None, Nothing, "circle-help"),
|
||||
c("help.discord", "Join the ArtCraft Discord", HELP, None, Nothing, "messages-square"),
|
||||
c("help.app_page", "PdfCraft web page", HELP, None, Nothing, "globe"),
|
||||
c("help.github", "PdfCraft on GitHub", HELP, None, Nothing, "code-xml"),
|
||||
c("help.website", "ArtCraft website", HELP, None, Nothing, "external-link"),
|
||||
c("help.check_updates", "Check for updates…", HELP, None, Nothing, "cloud"),
|
||||
c("help.about", "About PdfCraft", HELP, None, Nothing, "info"),
|
||||
];
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
//! Where PdfCraft and the ArtCraft community live on the web. One table, so the Help menu, the
|
||||
//! About dialog, the home screen, the CLI and the README agree.
|
||||
//! Where PdfCraft lives on the web. One table, so the Help menu, the About dialog, the home
|
||||
//! screen, the CLI and the README agree.
|
||||
|
||||
use icu_properties::props::Script;
|
||||
|
||||
/// The app's name in ArtCraft URLs (`getartcraft.com/apps/{APP}`, `github.com/storytold/{APP}`).
|
||||
/// The app's name in its GitHub URL (`github.com/storytold/{APP}`).
|
||||
pub const APP: &str = "pdfcraft";
|
||||
|
||||
pub const DISCORD: &str = "https://discord.gg/artcraft";
|
||||
pub const WEBSITE: &str = "https://getartcraft.com";
|
||||
pub const APP_PAGE: &str = "https://getartcraft.com/apps/pdfcraft";
|
||||
pub const GITHUB: &str = "https://github.com/storytold/pdfcraft";
|
||||
|
||||
/// A link and the registry command that opens it.
|
||||
@@ -21,13 +18,8 @@ pub struct Link {
|
||||
pub icon: &'static str,
|
||||
}
|
||||
|
||||
/// In the order they are shown. Discord comes first: it is where people get help fastest.
|
||||
pub const LINKS: &[Link] = &[
|
||||
Link { command: "help.discord", label: "Join the ArtCraft Discord", url: DISCORD, icon: "messages-square" },
|
||||
Link { command: "help.app_page", label: "PdfCraft web page", url: APP_PAGE, icon: "globe" },
|
||||
Link { command: "help.github", label: "PdfCraft on GitHub", url: GITHUB, icon: "code-xml" },
|
||||
Link { command: "help.website", label: "ArtCraft website", url: WEBSITE, icon: "external-link" },
|
||||
];
|
||||
/// In the order they are shown.
|
||||
pub const LINKS: &[Link] = &[Link { command: "help.github", label: "PdfCraft on GitHub", url: GITHUB, icon: "code-xml" }];
|
||||
|
||||
pub fn for_command(id: &str) -> Option<&'static Link> {
|
||||
LINKS.iter().find(|l| l.command == id)
|
||||
@@ -340,8 +332,7 @@ fn mixes_scripts(label: &str) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn urls_follow_the_artcraft_scheme() {
|
||||
assert_eq!(super::APP_PAGE, format!("{}/apps/{}", super::WEBSITE, super::APP));
|
||||
fn urls_follow_the_github_scheme() {
|
||||
assert_eq!(super::GITHUB, format!("https://github.com/storytold/{}", super::APP));
|
||||
for l in super::LINKS {
|
||||
assert!(l.url.starts_with("https://"), "{}", l.url);
|
||||
|
||||
@@ -7,14 +7,26 @@ use crate::PdfCraftApp;
|
||||
use crate::theme::{self, ThemeKind, ThemePreference, Tokens};
|
||||
|
||||
/// The themes each card offers. One of each today; a new theme is one more row here.
|
||||
pub const LIGHT_THEMES: &[(ThemeKind, &str)] = &[(ThemeKind::Light, "Light gray")];
|
||||
pub const DARK_THEMES: &[(ThemeKind, &str)] = &[(ThemeKind::Dark, "Dark gray")];
|
||||
pub const LIGHT_THEMES: &[(ThemeKind, &str)] = &[
|
||||
(ThemeKind::Light, "Light gray"),
|
||||
(ThemeKind::CatppuccinLatte, "Catppuccin Latte"),
|
||||
];
|
||||
pub const DARK_THEMES: &[(ThemeKind, &str)] = &[
|
||||
(ThemeKind::Dark, "Dark gray"),
|
||||
(ThemeKind::CatppuccinFrappe, "Catppuccin Frappé"),
|
||||
(ThemeKind::CatppuccinMacchiato, "Catppuccin Macchiato"),
|
||||
(ThemeKind::CatppuccinMocha, "Catppuccin Mocha"),
|
||||
];
|
||||
|
||||
fn mode_label(preference: ThemePreference) -> &'static str {
|
||||
match preference {
|
||||
ThemePreference::System => "Use system setting",
|
||||
ThemePreference::Light => "Light",
|
||||
ThemePreference::Dark => "Dark",
|
||||
ThemePreference::CatppuccinLatte => "Catppuccin Latte",
|
||||
ThemePreference::CatppuccinFrappe => "Catppuccin Frappé",
|
||||
ThemePreference::CatppuccinMacchiato => "Catppuccin Macchiato",
|
||||
ThemePreference::CatppuccinMocha => "Catppuccin Mocha",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +35,10 @@ fn mode_command(preference: ThemePreference) -> &'static str {
|
||||
ThemePreference::System => "view.theme.system",
|
||||
ThemePreference::Light => "view.theme.light",
|
||||
ThemePreference::Dark => "view.theme.dark",
|
||||
ThemePreference::CatppuccinLatte => "view.theme.catppuccinLatte",
|
||||
ThemePreference::CatppuccinFrappe => "view.theme.catppuccinFrappe",
|
||||
ThemePreference::CatppuccinMacchiato => "view.theme.catppuccinMacchiato",
|
||||
ThemePreference::CatppuccinMocha => "view.theme.catppuccinMocha",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +99,7 @@ fn preview(ui: &mut egui::Ui, kind: ThemeKind, width: f32) {
|
||||
|
||||
/// One theme card: its title, Active when it is what shows now, a preview of the chosen theme
|
||||
/// and a radio row per theme.
|
||||
fn card(ui: &mut egui::Ui, t: &Tokens, title: &str, active: bool, themes: &[(ThemeKind, &str)]) {
|
||||
fn card(ui: &mut egui::Ui, app: &mut PdfCraftApp, t: &Tokens, title: &str, active: bool, themes: &[(ThemeKind, &str)]) {
|
||||
egui::Frame::new()
|
||||
.fill(t.card)
|
||||
.stroke(egui::Stroke::new(1.0, if active { t.accent } else { t.border }))
|
||||
@@ -98,12 +114,22 @@ fn card(ui: &mut egui::Ui, t: &Tokens, title: &str, active: bool, themes: &[(The
|
||||
}
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
let shown = themes.first().map_or(ThemeKind::Light, |(kind, _)| *kind);
|
||||
let shown = themes.iter().find(|(k, _)| *k == app.theme).map_or(themes[0].0, |(k, _)| *k);
|
||||
preview(ui, shown, ui.available_width());
|
||||
ui.add_space(4.0);
|
||||
for (kind, label) in themes {
|
||||
// One theme per card today, so it is always the chosen one.
|
||||
let _ = ui.radio(*kind == shown, tl!(label));
|
||||
let selected = app.theme == *kind;
|
||||
if ui.radio(selected, tl!(label)).clicked() {
|
||||
let cmd = match kind {
|
||||
ThemeKind::Light => "view.theme.light",
|
||||
ThemeKind::Dark => "view.theme.dark",
|
||||
ThemeKind::CatppuccinLatte => "view.theme.catppuccinLatte",
|
||||
ThemeKind::CatppuccinFrappe => "view.theme.catppuccinFrappe",
|
||||
ThemeKind::CatppuccinMacchiato => "view.theme.catppuccinMacchiato",
|
||||
ThemeKind::CatppuccinMocha => "view.theme.catppuccinMocha",
|
||||
};
|
||||
app.execute(cmd);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -114,7 +140,15 @@ pub fn preferences_section(ui: &mut egui::Ui, app: &mut PdfCraftApp, t: &Tokens)
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(tl!("Appearance mode"));
|
||||
egui::ComboBox::from_id_salt("appearance-mode").selected_text(tl!(mode_label(app.theme_preference))).show_ui(ui, |ui| {
|
||||
for preference in [ThemePreference::System, ThemePreference::Light, ThemePreference::Dark] {
|
||||
for preference in [
|
||||
ThemePreference::System,
|
||||
ThemePreference::Light,
|
||||
ThemePreference::Dark,
|
||||
ThemePreference::CatppuccinLatte,
|
||||
ThemePreference::CatppuccinFrappe,
|
||||
ThemePreference::CatppuccinMacchiato,
|
||||
ThemePreference::CatppuccinMocha,
|
||||
] {
|
||||
if ui.selectable_label(app.theme_preference == preference, tl!(mode_label(preference))).clicked() {
|
||||
app.execute(mode_command(preference));
|
||||
ui.close();
|
||||
@@ -123,12 +157,21 @@ pub fn preferences_section(ui: &mut egui::Ui, app: &mut PdfCraftApp, t: &Tokens)
|
||||
});
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
let light_active = app.theme == ThemeKind::Light;
|
||||
let light_active = app.theme.is_light();
|
||||
ui.columns(2, |cols| {
|
||||
let [light, dark] = cols else { return };
|
||||
card(light, t, tl!("Light theme"), light_active, LIGHT_THEMES);
|
||||
card(dark, t, tl!("Dark theme"), !light_active, DARK_THEMES);
|
||||
card(light, app, t, tl!("Light theme"), light_active, LIGHT_THEMES);
|
||||
card(dark, app, t, tl!("Dark theme"), !light_active, DARK_THEMES);
|
||||
});
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
ui.add_space(6.0);
|
||||
let mut sys = app.system_title_bar;
|
||||
let label = "Use System Title Bar on Windows and Linux";
|
||||
if ui.checkbox(&mut sys, crate::i18n::t(label)).changed() {
|
||||
app.system_title_bar = sys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -31,20 +31,26 @@ pub fn tab_strip(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
|
||||
// macOS: the strip is the 28 pt title bar, so the traffic lights are centred in it; tabs and
|
||||
// buttons shrink to keep a margin above and below.
|
||||
let mac = cfg!(target_os = "macos") && app.integrated_titlebar;
|
||||
let custom = app.custom_titlebar;
|
||||
let left = if mac { MAC_CONTENT_LEFT as i8 } else { 8 };
|
||||
let right = if custom { (crate::titlebar::WIDTH + 8.0) as i8 } else { 10 };
|
||||
let (tab_h, button) = if mac { (MAC_TITLE_BAR - 2.0, 24.0) } else { (TAB_HEIGHT, STRIP_BUTTON) };
|
||||
egui::Panel::top("tab_strip")
|
||||
.exact_size(if mac { MAC_TITLE_BAR } else { TAB_STRIP })
|
||||
.frame(egui::Frame::NONE.fill(t.titlebar).inner_margin(egui::Margin { left, right: 10, top: 0, bottom: 0 }))
|
||||
.frame(egui::Frame::NONE.fill(t.titlebar).inner_margin(egui::Margin { left, right, top: 0, bottom: 0 }))
|
||||
.show(ui, |ui| {
|
||||
let full = ui.max_rect();
|
||||
let drag = ui.interact(full, ui.id().with("titledrag"), Sense::click_and_drag());
|
||||
if drag.drag_started() {
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::StartDrag);
|
||||
}
|
||||
if drag.double_clicked() {
|
||||
let max = ui.ctx().input(|i| i.viewport().maximized.unwrap_or(false));
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Maximized(!max));
|
||||
if custom || mac {
|
||||
crate::titlebar::drag_area(ui, full);
|
||||
} else {
|
||||
let drag = ui.interact(full, ui.id().with("titledrag"), Sense::click_and_drag());
|
||||
if drag.drag_started() {
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::StartDrag);
|
||||
}
|
||||
if drag.double_clicked() {
|
||||
let max = ui.ctx().input(|i| i.viewport().maximized.unwrap_or(false));
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Maximized(!max));
|
||||
}
|
||||
}
|
||||
ui.horizontal_centered(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 4.0;
|
||||
@@ -52,8 +58,8 @@ pub fn tab_strip(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
|
||||
app.active = None;
|
||||
app.combine_tab.focused = false;
|
||||
}
|
||||
// Keep the two icon buttons, Discord's text/padding and three gaps outside the scrolling tabs.
|
||||
let controls_width = ui.fonts_mut(|f| f.layout_no_wrap("Discord".into(), theme::medium(13.0), t.text).size().x) + 2.0 * button + 50.0;
|
||||
// Keep the two icon buttons and their gaps outside the scrolling tabs.
|
||||
let controls_width = 2.0 * button + 30.0;
|
||||
// Open stays in sight after the tabs: its icon, text and padding, and the gaps around it.
|
||||
let open_width = ui.fonts_mut(|f| f.layout_no_wrap(tl!("Open").into(), theme::medium(13.0), t.text).size().x) + 38.0 + 12.0;
|
||||
let mut tabs_width = (ui.available_width() - controls_width - open_width).max(0.0);
|
||||
@@ -175,27 +181,34 @@ pub fn tab_strip(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
|
||||
ThemePreference::System => ("monitor", tl!("Use system setting")),
|
||||
ThemePreference::Light => ("sun", tl!("Light gray")),
|
||||
ThemePreference::Dark => ("moon", tl!("Dark gray")),
|
||||
ThemePreference::CatppuccinLatte => ("sun", "Catppuccin Latte"),
|
||||
ThemePreference::CatppuccinFrappe => ("moon", "Catppuccin Frappé"),
|
||||
ThemePreference::CatppuccinMacchiato => ("moon", "Catppuccin Macchiato"),
|
||||
ThemePreference::CatppuccinMocha => ("moon", "Catppuccin Mocha"),
|
||||
};
|
||||
let tip = format!("{}: {label}", tl!("Display theme"));
|
||||
let response = icons::button(ui, icon, button, false, &tip);
|
||||
// A click cycles System, Light, Dark; a right-click opens the menu.
|
||||
// A click cycles System, Light, Dark, Catppuccin; a right-click opens the menu.
|
||||
if response.clicked() {
|
||||
app.execute(match app.theme_preference {
|
||||
ThemePreference::System => "view.theme.light",
|
||||
ThemePreference::Light => "view.theme.dark",
|
||||
ThemePreference::Dark => "view.theme.system",
|
||||
ThemePreference::Dark => "view.theme.catppuccinLatte",
|
||||
ThemePreference::CatppuccinLatte => "view.theme.catppuccinFrappe",
|
||||
ThemePreference::CatppuccinFrappe => "view.theme.catppuccinMacchiato",
|
||||
ThemePreference::CatppuccinMacchiato => "view.theme.catppuccinMocha",
|
||||
ThemePreference::CatppuccinMocha => "view.theme.system",
|
||||
});
|
||||
}
|
||||
egui::Popup::context_menu(&response).id(response.id.with("theme_menu")).show(|ui| appearance_menu(app, ui));
|
||||
if icons::button(ui, "circle-help", button, false, tl!("Keyboard shortcuts")).clicked() {
|
||||
app.dialog = Some(Dialog::Shortcuts);
|
||||
}
|
||||
// One click to the community, from anywhere in the app.
|
||||
if widgets::ghost_button_sized(ui, "messages-square", "Discord", tab_h).on_hover_text(pdfcraft_engine::links::DISCORD).clicked() {
|
||||
app.execute("help.discord");
|
||||
}
|
||||
});
|
||||
});
|
||||
if custom {
|
||||
crate::titlebar::caption_buttons(app, ui, full);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -205,6 +218,10 @@ fn theme_menu(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
|
||||
(ThemePreference::System, "view.theme.system", "Use system setting"),
|
||||
(ThemePreference::Light, "view.theme.light", "Light gray"),
|
||||
(ThemePreference::Dark, "view.theme.dark", "Dark gray"),
|
||||
(ThemePreference::CatppuccinLatte, "view.theme.catppuccinLatte", "Catppuccin Latte"),
|
||||
(ThemePreference::CatppuccinFrappe, "view.theme.catppuccinFrappe", "Catppuccin Frappé"),
|
||||
(ThemePreference::CatppuccinMacchiato, "view.theme.catppuccinMacchiato", "Catppuccin Macchiato"),
|
||||
(ThemePreference::CatppuccinMocha, "view.theme.catppuccinMocha", "Catppuccin Mocha"),
|
||||
] {
|
||||
if ui.radio(app.theme_preference == preference, tl!(label)).clicked() {
|
||||
app.execute(command);
|
||||
|
||||
@@ -9,7 +9,7 @@ use pdfcraft_engine::commands::{self, COMMANDS, CommandSpec, Shortcut};
|
||||
|
||||
use crate::{
|
||||
Dialog, Mode, PdfCraftApp, PropsTab, RightPanel, SaveTarget,
|
||||
theme::{ThemeKind, ThemePreference},
|
||||
theme::ThemePreference,
|
||||
widgets,
|
||||
};
|
||||
|
||||
@@ -261,13 +261,17 @@ impl PdfCraftApp {
|
||||
}
|
||||
"view.read_mode" => self.switch_mode(if self.mode == Mode::Read { Mode::AllTools } else { Mode::Read }, false),
|
||||
"view.theme" => {
|
||||
let next = if self.theme == ThemeKind::Light { ThemePreference::Dark } else { ThemePreference::Light };
|
||||
let next = if self.theme.is_light() { ThemePreference::Dark } else { ThemePreference::Light };
|
||||
self.set_theme_preference(next);
|
||||
}
|
||||
command if command.starts_with("measure.") => crate::measure_ui::command(self, command),
|
||||
"view.theme.system" => self.set_theme_preference(ThemePreference::System),
|
||||
"view.theme.light" => self.set_theme_preference(ThemePreference::Light),
|
||||
"view.theme.dark" => self.set_theme_preference(ThemePreference::Dark),
|
||||
"view.theme.catppuccinlatte" | "view.theme.catppuccinLatte" => self.set_theme_preference(ThemePreference::CatppuccinLatte),
|
||||
"view.theme.catppuccinfrappe" | "view.theme.catppuccinFrappe" => self.set_theme_preference(ThemePreference::CatppuccinFrappe),
|
||||
"view.theme.catppuccinmacchiato" | "view.theme.catppuccinMacchiato" => self.set_theme_preference(ThemePreference::CatppuccinMacchiato),
|
||||
"view.theme.catppuccinmocha" | "view.theme.catppuccinMocha" => self.set_theme_preference(ThemePreference::CatppuccinMocha),
|
||||
"comment.list" => self.choose_right_panel(Some(RightPanel::Comments)),
|
||||
tool if crate::comments::CommentTool::from_command(tool).is_some() => {
|
||||
let Some(tool) = crate::comments::CommentTool::from_command(tool) else { return false };
|
||||
|
||||
@@ -1093,7 +1093,6 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
||||
2 => crate::credits::models_ui(ui),
|
||||
_ => {
|
||||
ui.horizontal(|ui| {
|
||||
widgets::artcraft_mark(ui, 40.0);
|
||||
ui.vertical(|ui| {
|
||||
ui.label(egui::RichText::new("PdfCraft").font(theme::semibold(20.0)));
|
||||
ui.label(crate::i18n::fmt(tl!("Version {v}"), &[("v", env!("CARGO_PKG_VERSION"))]));
|
||||
@@ -1109,11 +1108,6 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
||||
.small(),
|
||||
);
|
||||
ui.add_space(12.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(egui::RichText::new(tl!("Part of")).color(t.text_muted));
|
||||
widgets::artcraft_logo(ui, 16.0);
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
if let Some(cmd) = widgets::community_links(ui) {
|
||||
link_command = Some(cmd);
|
||||
}
|
||||
|
||||
@@ -19,26 +19,6 @@ pub fn show(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
|
||||
.color(t.text_muted)
|
||||
.font(theme::regular(14.0)),
|
||||
);
|
||||
ui.add_space(14.0);
|
||||
egui::Frame::NONE
|
||||
.fill(t.card)
|
||||
.stroke(Stroke::new(1.0, t.border))
|
||||
.corner_radius(CornerRadius::same(12))
|
||||
.inner_margin(egui::Margin::same(14))
|
||||
.show(ui, |ui| {
|
||||
ui.set_width(ui.available_width());
|
||||
ui.horizontal(|ui| {
|
||||
widgets::artcraft_mark(ui, 28.0);
|
||||
ui.vertical(|ui| {
|
||||
ui.label(egui::RichText::new(tl!("Join the ArtCraft community")).font(theme::semibold(15.0)));
|
||||
ui.label(egui::RichText::new(tl!("Get help, share feedback and follow development on Discord.")).color(t.text_muted));
|
||||
});
|
||||
});
|
||||
ui.add_space(8.0);
|
||||
if let Some(cmd) = widgets::community_links(ui) {
|
||||
app.execute(cmd);
|
||||
}
|
||||
});
|
||||
ui.add_space(22.0);
|
||||
|
||||
egui::Frame::NONE
|
||||
|
||||
@@ -93,7 +93,6 @@
|
||||
Side panels اللوحات الجانبية
|
||||
Enable Acrobat JavaScript تفعيل Acrobat JavaScript
|
||||
OK موافق
|
||||
Join our Discord انضم إلى خادمنا على Discord
|
||||
Close إغلاق
|
||||
Next / previous match التطابق التالي / السابق
|
||||
Copy selected text نسخ النص المحدد
|
||||
@@ -161,8 +160,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter الصفحة الحالية — اكتب رقم صفحة أو تسميتها (مثل iv) ثم اضغط Enter
|
||||
Welcome to PdfCraft مرحبًا بك في PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. منضدة عمل مفتوحة المصدر لملفات PDF — محلية وخاصة وقابلة للبرمجة.
|
||||
Join the ArtCraft community انضم إلى مجتمع ArtCraft
|
||||
Get help, share feedback and follow development on Discord. احصل على المساعدة وشارك ملاحظاتك وتابع التطوير على Discord.
|
||||
Recommended tools أدوات مقترحة
|
||||
Use now استخدم الآن
|
||||
Open file فتح ملف
|
||||
@@ -303,10 +300,8 @@
|
||||
Split document… تقسيم المستند…
|
||||
Number pages… ترقيم الصفحات…
|
||||
Keyboard shortcuts اختصارات لوحة المفاتيح
|
||||
Join the ArtCraft Discord انضم إلى خادم ArtCraft على Discord
|
||||
PdfCraft web page صفحة PdfCraft على الويب
|
||||
PdfCraft on GitHub PdfCraft على GitHub
|
||||
ArtCraft website موقع ArtCraft
|
||||
Check for updates… التحقق من التحديثات…
|
||||
About PdfCraft حول PdfCraft
|
||||
Export a PDF تصدير ملف PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1789,13 +1789,8 @@
|
||||
Split document… Раздели документа…
|
||||
Number pages… Номерирай страниците…
|
||||
Keyboard shortcuts Клавишни комбинации
|
||||
Join the ArtCraft Discord Присъедини се към ArtCraft в Discord
|
||||
Join the ArtCraft community Присъедини се към общността на ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Получете помощ, споделете мнение и следете разработката в Discord.
|
||||
Join our Discord Присъедини се към нашия Discord
|
||||
PdfCraft web page Уебстраница на PdfCraft
|
||||
PdfCraft on GitHub PdfCraft в GitHub
|
||||
ArtCraft website Уебсайт на ArtCraft
|
||||
Check for updates… Провери за актуализации…
|
||||
About PdfCraft За PdfCraft
|
||||
JavaScript console… JavaScript конзола…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 8 and column 16.
|
@@ -112,10 +112,8 @@
|
||||
Split document… Rozdělit dokument…
|
||||
Number pages… Očíslovat stránky…
|
||||
Keyboard shortcuts Klávesové zkratky
|
||||
Join the ArtCraft Discord Připojit se ke komunitě ArtCraft na Discordu
|
||||
PdfCraft web page Webová stránka PdfCraft
|
||||
PdfCraft on GitHub PdfCraft na GitHubu
|
||||
ArtCraft website Web ArtCraft
|
||||
Check for updates… Zkontrolovat aktualizace…
|
||||
About PdfCraft O aplikaci PdfCraft
|
||||
Auto Automaticky
|
||||
@@ -218,7 +216,6 @@ key Space Mezerník
|
||||
{folder} is already pinned to Home Složka {folder} už je připnutá na úvodní obrazovce
|
||||
You can pin up to {n} folders. Unpin one first. Připnout lze nejvýše {n} složek. Nejdříve některou odepněte.
|
||||
Pinned {folder} to Home Složka {folder} je připnutá na úvodní obrazovce
|
||||
Join our Discord Připojit se k našemu Discordu
|
||||
Close Zavřít
|
||||
Next / previous match Další / předchozí shoda
|
||||
Copy selected text Kopírovat vybraný text
|
||||
@@ -275,8 +272,6 @@ key Space Mezerník
|
||||
Current page — type a page number or label (such as iv) and press Enter Aktuální stránka — zadejte číslo nebo označení stránky (třeba iv) a stiskněte Enter
|
||||
Welcome to PdfCraft Vítá vás PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Open-source dílna pro PDF — lokální, soukromá a skriptovatelná.
|
||||
Join the ArtCraft community Připojte se ke komunitě ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Získejte pomoc, sdílejte zpětnou vazbu a sledujte vývoj na Discordu.
|
||||
Recommended tools Doporučené nástroje
|
||||
Use now Použít
|
||||
Open file Otevřít soubor
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -65,7 +65,6 @@
|
||||
Flatten Fill & Sign when saving Ausfüllen und unterschreiben beim Speichern reduzieren
|
||||
Text, marks and signatures become part of the page. Other comments stay editable. Text, Markierungen und Unterschriften werden Teil der Seite. Andere Kommentare bleiben bearbeitbar.
|
||||
OK OK
|
||||
Join our Discord Unserem Discord beitreten
|
||||
Close Schließen
|
||||
Next / previous match Nächster / vorheriger Treffer
|
||||
Copy selected text Ausgewählten Text kopieren
|
||||
@@ -133,8 +132,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Aktuelle Seite – gib eine Seitenzahl oder -beschriftung ein (z. B. iv) und drücke die Eingabetaste
|
||||
Welcome to PdfCraft Willkommen bei PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Eine Open-Source-PDF-Werkbank – lokal, privat und skriptfähig.
|
||||
Join the ArtCraft community Tritt der ArtCraft-Community bei
|
||||
Get help, share feedback and follow development on Discord. Hol dir Hilfe, gib Feedback und verfolge die Entwicklung auf Discord.
|
||||
Recommended tools Empfohlene Werkzeuge
|
||||
Use now Jetzt verwenden
|
||||
Open file Datei öffnen
|
||||
@@ -275,10 +272,8 @@
|
||||
Split document… Dokument teilen…
|
||||
Number pages… Seiten nummerieren…
|
||||
Keyboard shortcuts Tastenkürzel
|
||||
Join the ArtCraft Discord Dem ArtCraft-Discord beitreten
|
||||
PdfCraft web page PdfCraft-Webseite
|
||||
PdfCraft on GitHub PdfCraft auf GitHub
|
||||
ArtCraft website ArtCraft-Website
|
||||
Check for updates… Nach Updates suchen…
|
||||
About PdfCraft Über PdfCraft
|
||||
Export a PDF PDF exportieren
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 51.
|
@@ -77,7 +77,6 @@
|
||||
Side panels Πλευρικοί πίνακες
|
||||
Enable Acrobat JavaScript Ενεργοποίηση Acrobat JavaScript
|
||||
OK Εντάξει
|
||||
Join our Discord Ελάτε στο Discord μας
|
||||
Close Κλείσιμο
|
||||
Next / previous match Επόμενο / προηγούμενο αποτέλεσμα
|
||||
Copy selected text Αντιγραφή επιλεγμένου κειμένου
|
||||
@@ -138,8 +137,6 @@
|
||||
Previous page Προηγούμενη σελίδα
|
||||
Welcome to PdfCraft Καλώς ορίσατε στο PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Ένα εργαλείο PDF ανοιχτού κώδικα — τοπικό, ιδιωτικό και αυτοματοποιήσιμο.
|
||||
Join the ArtCraft community Γίνετε μέλος της κοινότητας ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Βρείτε βοήθεια, μοιραστείτε σχόλια και παρακολουθήστε την ανάπτυξη στο Discord.
|
||||
Recommended tools Προτεινόμενα εργαλεία
|
||||
Use now Χρήση τώρα
|
||||
Open file Άνοιγμα αρχείου
|
||||
@@ -1654,10 +1651,8 @@
|
||||
Extract pages… Εξαγωγή σελίδων…
|
||||
Split document… Διαχωρισμός εγγράφου…
|
||||
Number pages… Αρίθμηση σελίδων…
|
||||
Join the ArtCraft Discord Συμμετοχή στο Discord του ArtCraft
|
||||
PdfCraft web page Ιστότοπος του PdfCraft
|
||||
PdfCraft on GitHub PdfCraft στο GitHub
|
||||
ArtCraft website Ιστότοπος ArtCraft
|
||||
Check for updates… Έλεγχος για ενημερώσεις…
|
||||
Export a PDF Εξαγωγή PDF
|
||||
Export to Εξαγωγή σε
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 474 and column 12.
|
@@ -86,7 +86,6 @@
|
||||
Side panels Paneles laterales
|
||||
Enable Acrobat JavaScript Activar Acrobat JavaScript
|
||||
OK Aceptar
|
||||
Join our Discord Únete a nuestro Discord
|
||||
Close Cerrar
|
||||
Next / previous match Coincidencia siguiente / anterior
|
||||
Copy selected text Copiar el texto seleccionado
|
||||
@@ -154,8 +153,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Página actual: escribe un número o una etiqueta de página (por ejemplo, iv) y pulsa Intro
|
||||
Welcome to PdfCraft Te damos la bienvenida a PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Un banco de trabajo PDF de código abierto: local, privado y automatizable.
|
||||
Join the ArtCraft community Únete a la comunidad de ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Recibe ayuda, comparte tu opinión y sigue el desarrollo en Discord.
|
||||
Recommended tools Herramientas recomendadas
|
||||
Use now Usar ahora
|
||||
Open file Abrir archivo
|
||||
@@ -296,10 +293,8 @@
|
||||
Split document… Dividir documento…
|
||||
Number pages… Numerar páginas…
|
||||
Keyboard shortcuts Atajos de teclado
|
||||
Join the ArtCraft Discord Únete al Discord de ArtCraft
|
||||
PdfCraft web page Página web de PdfCraft
|
||||
PdfCraft on GitHub PdfCraft en GitHub
|
||||
ArtCraft website Sitio web de ArtCraft
|
||||
Check for updates… Buscar actualizaciones…
|
||||
About PdfCraft Acerca de PdfCraft
|
||||
Export a PDF Exportar un PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 60.
|
@@ -65,7 +65,6 @@
|
||||
Flatten Fill & Sign when saving Aplatir Remplir et signer à l'enregistrement
|
||||
Text, marks and signatures become part of the page. Other comments stay editable. Le texte, les marques et les signatures deviennent partie de la page. Les autres commentaires restent modifiables.
|
||||
OK OK
|
||||
Join our Discord Rejoindre notre Discord
|
||||
Close Fermer
|
||||
Next / previous match Correspondance suivante / précédente
|
||||
Copy selected text Copier le texte sélectionné
|
||||
@@ -133,8 +132,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Page actuelle — saisissez un numéro ou une étiquette de page (comme iv) et appuyez sur Entrée
|
||||
Welcome to PdfCraft Bienvenue dans PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Un atelier PDF open source — local, privé et automatisable.
|
||||
Join the ArtCraft community Rejoindre la communauté ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Obtenez de l'aide, partagez vos retours et suivez le développement sur Discord.
|
||||
Recommended tools Outils recommandés
|
||||
Use now Utiliser
|
||||
Open file Ouvrir un fichier
|
||||
@@ -275,10 +272,8 @@
|
||||
Split document… Fractionner le document…
|
||||
Number pages… Numéroter les pages…
|
||||
Keyboard shortcuts Raccourcis clavier
|
||||
Join the ArtCraft Discord Rejoindre le Discord ArtCraft
|
||||
PdfCraft web page Page web de PdfCraft
|
||||
PdfCraft on GitHub PdfCraft sur GitHub
|
||||
ArtCraft website Site web d'ArtCraft
|
||||
Check for updates… Rechercher des mises à jour…
|
||||
About PdfCraft À propos de PdfCraft
|
||||
Export a PDF Exporter un PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 39.
|
@@ -63,7 +63,6 @@
|
||||
Side panels Oldalsó panelek
|
||||
Enable Acrobat JavaScript Acrobat JavaScript engedélyezése
|
||||
OK OK
|
||||
Join our Discord Csatlakozás a Discordhoz
|
||||
Close Bezárás
|
||||
Next / previous match Következő / előző találat
|
||||
Copy selected text Kijelölt szöveg másolása
|
||||
@@ -131,8 +130,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Aktuális oldal — írj be egy oldalszámot vagy címkét (például iv), majd nyomd meg az Entert
|
||||
Welcome to PdfCraft Üdvözöljük a PdfCraftban
|
||||
An open-source PDF workbench — local, private, and scriptable. Nyílt forráskódú PDF-munkapad — helyi, privát és parancsfájlokkal vezérelhető.
|
||||
Join the ArtCraft community Csatlakozz az ArtCraft közösséghez
|
||||
Get help, share feedback and follow development on Discord. Kérj segítséget, oszd meg a véleményed, és kövesd a fejlesztést a Discordon.
|
||||
Recommended tools Ajánlott eszközök
|
||||
Use now Használat most
|
||||
Open file Fájl megnyitása
|
||||
@@ -273,10 +270,8 @@
|
||||
Split document… Dokumentum felosztása…
|
||||
Number pages… Oldalak számozása…
|
||||
Keyboard shortcuts Billentyűparancsok
|
||||
Join the ArtCraft Discord Csatlakozás az ArtCraft Discordhoz
|
||||
PdfCraft web page A PdfCraft weblapja
|
||||
PdfCraft on GitHub PdfCraft a GitHubon
|
||||
ArtCraft website Az ArtCraft webhelye
|
||||
Check for updates… Frissítések keresése…
|
||||
About PdfCraft A PdfCraftról
|
||||
Export a PDF PDF exportálása
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 44.
|
@@ -89,7 +89,6 @@
|
||||
Side panels Pannelli laterali
|
||||
Enable Acrobat JavaScript Abilita JavaScript di Acrobat
|
||||
OK OK
|
||||
Join our Discord Unisciti al nostro Discord
|
||||
Close Chiudi
|
||||
Next / previous match Risultato successivo/precedente
|
||||
Copy selected text Copia testo selezionato
|
||||
@@ -157,8 +156,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Pagina corrente: digita un numero o un'etichetta di pagina (ad esempio iv) e premi Invio
|
||||
Welcome to PdfCraft Benvenuto in PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Un banco di lavoro PDF open source: locale, riservato e programmabile.
|
||||
Join the ArtCraft community Unisciti alla community di ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Chiedi aiuto, condividi commenti e segui lo sviluppo su Discord.
|
||||
Recommended tools Strumenti consigliati
|
||||
Use now Usa ora
|
||||
Open file Apri file
|
||||
@@ -299,10 +296,8 @@
|
||||
Split document… Dividi documento…
|
||||
Number pages… Numera pagine…
|
||||
Keyboard shortcuts Scorciatoie da tastiera
|
||||
Join the ArtCraft Discord Unisciti al Discord di ArtCraft
|
||||
PdfCraft web page Pagina web di PdfCraft
|
||||
PdfCraft on GitHub PdfCraft su GitHub
|
||||
ArtCraft website Sito web di ArtCraft
|
||||
Check for updates… Verifica aggiornamenti…
|
||||
About PdfCraft Informazioni su PdfCraft
|
||||
Export a PDF Esporta un PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -92,7 +92,6 @@
|
||||
Side panels サイドパネル
|
||||
Enable Acrobat JavaScript Acrobat JavaScript を有効にする
|
||||
OK OK
|
||||
Join our Discord Discord に参加
|
||||
Close 閉じる
|
||||
Next / previous match 次/前の検索結果
|
||||
Copy selected text 選択したテキストをコピー
|
||||
@@ -160,8 +159,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter 現在のページ:ページ番号またはラベル(例:iv)を入力して Enter
|
||||
Welcome to PdfCraft PdfCraft へようこそ
|
||||
An open-source PDF workbench — local, private, and scriptable. ローカルで処理し、プライバシーを守る、スクリプト対応のオープンソース PDF ツール。
|
||||
Join the ArtCraft community ArtCraft コミュニティに参加
|
||||
Get help, share feedback and follow development on Discord. Discord で質問やフィードバックを共有し、開発の進捗を確認できます。
|
||||
Recommended tools おすすめのツール
|
||||
Use now 使用する
|
||||
Open file ファイルを開く
|
||||
@@ -302,10 +299,8 @@
|
||||
Split document… 文書を分割…
|
||||
Number pages… ページ番号を設定…
|
||||
Keyboard shortcuts キーボードショートカット
|
||||
Join the ArtCraft Discord ArtCraft の Discord に参加
|
||||
PdfCraft web page PdfCraft の Web 版
|
||||
PdfCraft on GitHub GitHub の PdfCraft
|
||||
ArtCraft website ArtCraft のウェブサイト
|
||||
Check for updates… 更新を確認…
|
||||
About PdfCraft PdfCraft について
|
||||
Export a PDF PDF を書き出す
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -67,7 +67,6 @@
|
||||
Side panels Бүйірлік панельдер
|
||||
Enable Acrobat JavaScript Acrobat JavaScript-ті қосу
|
||||
OK ОК
|
||||
Join our Discord Discord-қа қосылыңыз
|
||||
Close Жабу
|
||||
Next / previous match Келесі / алдыңғы сәйкестік
|
||||
Copy selected text Таңдалған мәтінді көшіру
|
||||
@@ -122,8 +121,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Ағымдағы бет — бет нөмірін немесе белгісін (мысалы, iv) теріңіз де, Enter пернесін басыңыз
|
||||
Welcome to PdfCraft PdfCraft-ге қош келдіңіз
|
||||
An open-source PDF workbench — local, private, and scriptable. Ашық бастапқы кодты PDF жұмыс орны — жергілікті, жеке әрі скрипттерді қолдайтын.
|
||||
Join the ArtCraft community ArtCraft қауымдастығына қосылыңыз
|
||||
Get help, share feedback and follow development on Discord. Көмек алыңыз, пікір бөлісіңіз және Discord-тағы әзірлеуді қадағалаңыз.
|
||||
Recommended tools Ұсынылған құралдар
|
||||
Use now Дәл қазір пайдалану
|
||||
Open file Файлды ашу
|
||||
@@ -263,10 +260,8 @@
|
||||
Split document… Құжатты бөлу…
|
||||
Number pages… Беттерді нөмірлеу…
|
||||
Keyboard shortcuts Пернетақта тіркесімдері
|
||||
Join the ArtCraft Discord ArtCraft Discord-ына қосылыңыз
|
||||
PdfCraft web page PdfCraft веб-сайты
|
||||
PdfCraft on GitHub GitHub-тағы PdfCraft
|
||||
ArtCraft website ArtCraft веб-сайты
|
||||
Check for updates… Жаңартуларды тексеру…
|
||||
About PdfCraft PdfCraft туралы
|
||||
Export a PDF PDF экспорттау
|
||||
|
||||
|
@@ -88,7 +88,6 @@
|
||||
Side panels Panele boczne
|
||||
Enable Acrobat JavaScript Włącz Acrobat JavaScript
|
||||
OK OK
|
||||
Join our Discord Dołącz do naszego Discorda
|
||||
Close Zamknij
|
||||
Next / previous match Następne / poprzednie dopasowanie
|
||||
Copy selected text Kopiuj zaznaczony tekst
|
||||
@@ -156,8 +155,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Bieżąca strona — wpisz numer lub etykietę strony (np. iv) i naciśnij Enter
|
||||
Welcome to PdfCraft Witamy w PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Otwarty zestaw narzędzi do PDF — lokalny, prywatny i obsługujący skrypty.
|
||||
Join the ArtCraft community Dołącz do społeczności ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Uzyskaj pomoc, podziel się opinią i śledź rozwój na Discordzie.
|
||||
Recommended tools Polecane narzędzia
|
||||
Use now Użyj teraz
|
||||
Open file Otwórz plik
|
||||
@@ -297,10 +294,8 @@
|
||||
Split document… Podziel dokument…
|
||||
Number pages… Ponumeruj strony…
|
||||
Keyboard shortcuts Skróty klawiaturowe
|
||||
Join the ArtCraft Discord Dołącz do Discorda ArtCraft
|
||||
PdfCraft web page Strona internetowa PdfCraft
|
||||
PdfCraft on GitHub PdfCraft na GitHubie
|
||||
ArtCraft website Strona internetowa ArtCraft
|
||||
Check for updates… Sprawdź aktualizacje…
|
||||
About PdfCraft O PdfCraft
|
||||
Export a PDF Eksportuj PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1661,13 +1661,8 @@
|
||||
Split document… Dividir documento…
|
||||
Number pages… Numerar páginas…
|
||||
Keyboard shortcuts Atalhos de teclado
|
||||
Join the ArtCraft Discord Entrar no Discord do ArtCraft
|
||||
Join the ArtCraft community Entrar na comunidade ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Obtenha ajuda, compartilhe comentários e acompanhe o desenvolvimento no Discord.
|
||||
Join our Discord Entrar em nosso Discord
|
||||
PdfCraft web page Página da Web do PdfCraft
|
||||
PdfCraft on GitHub PdfCraft no GitHub
|
||||
ArtCraft website Site do ArtCraft
|
||||
Check for updates… Verificar atualizações…
|
||||
About PdfCraft Sobre o PdfCraft
|
||||
JavaScript console… Console JavaScript…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -86,7 +86,6 @@
|
||||
Flatten Fill & Sign when saving Расплющить «Заполнить и подписать» при сохранении
|
||||
Text, marks and signatures become part of the page. Other comments stay editable. Текст, пометки и подписи становятся частью страницы. Остальные комментарии можно по-прежнему править.
|
||||
OK OK
|
||||
Join our Discord Присоединяйтесь к нашему Discord
|
||||
Close Закрыть
|
||||
Next / previous match Следующее / предыдущее совпадение
|
||||
Copy selected text Копировать выделенный текст
|
||||
@@ -154,8 +153,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Текущая страница — введите номер или метку страницы (например, iv) и нажмите Enter
|
||||
Welcome to PdfCraft Добро пожаловать в PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Открытый PDF-редактор — локальный, приватный и программируемый.
|
||||
Join the ArtCraft community Присоединяйтесь к сообществу ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Получайте помощь, делитесь отзывами и следите за разработкой в Discord.
|
||||
Recommended tools Рекомендуемые инструменты
|
||||
Use now Использовать сейчас
|
||||
Open file Открыть файл
|
||||
@@ -296,10 +293,8 @@
|
||||
Split document… Разделить документ…
|
||||
Number pages… Пронумеровать страницы…
|
||||
Keyboard shortcuts Горячие клавиши
|
||||
Join the ArtCraft Discord Присоединяйтесь к Discord ArtCraft
|
||||
PdfCraft web page Веб-страница PdfCraft
|
||||
PdfCraft on GitHub PdfCraft на GitHub
|
||||
ArtCraft website Веб-сайт ArtCraft
|
||||
Check for updates… Проверить обновления…
|
||||
About PdfCraft О программе PdfCraft
|
||||
Export a PDF Экспортировать PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -229,7 +229,6 @@
|
||||
Archive documents Arhiviraj dokumente
|
||||
Area Ploščina
|
||||
Arrow Puščica
|
||||
ArtCraft website Spletna stran ArtCraft
|
||||
Ask about this document Vprašaj o tem dokumentu
|
||||
Asks GitHub for the latest release. Nothing is downloaded or installed automatically. Vpraša GitHub za najnovejšo izdajo. Ničesar se ne prenese ali namesti samodejno.
|
||||
Associated with content Povezano z vsebino
|
||||
@@ -854,7 +853,6 @@
|
||||
Full screen mode Celozaslonski način
|
||||
General Splošno
|
||||
Geospatial location Geoprostorska lokacija
|
||||
Get help, share feedback and follow development on Discord. Poiščite pomoč, delite povratne informacije in spremljajte razvoj na Discordu.
|
||||
Go to a page view Pojdi na pogled strani
|
||||
Go to page {p} Pojdi na stran {p}
|
||||
Go to page… Pojdi na stran…
|
||||
@@ -958,9 +956,6 @@
|
||||
JavaScript console… Konzola JavaScript…
|
||||
JavaScript is turned off (Preferences ▸ JavaScript). JavaScript je izklopljen (Nastavitve > JavaScript).
|
||||
JavaScript, e.g. getField("total").value JavaScript, npr. getField("total").value
|
||||
Join our Discord Discord kanal
|
||||
Join the ArtCraft Discord Pridružite se Discordu ArtCraft
|
||||
Join the ArtCraft community Pridružite se skupnosti ArtCraft
|
||||
July Julij
|
||||
June Junij
|
||||
Justify Obojestransko poravnano
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -69,7 +69,6 @@ comment menu Edit సవరించు
|
||||
Side panels సైడ్ ప్యానెల్లు
|
||||
Enable Acrobat JavaScript Acrobat JavaScriptను ప్రారంభించు
|
||||
OK సరే
|
||||
Join our Discord మా Discordలో చేరండి
|
||||
Close మూసివేయి
|
||||
Next / previous match తదుపరి / మునుపటి సరిపోలిక
|
||||
Copy selected text ఎంచుకున్న టెక్స్ట్ను కాపీ చేయి
|
||||
@@ -137,8 +136,6 @@ comment menu Edit సవరించు
|
||||
Current page — type a page number or label (such as iv) and press Enter ప్రస్తుత పేజీ — పేజీ సంఖ్యను లేదా లేబుల్ను (iv వంటిది) టైప్ చేసి Enter నొక్కండి
|
||||
Welcome to PdfCraft PdfCraftకు స్వాగతం
|
||||
An open-source PDF workbench — local, private, and scriptable. ఓపెన్-సోర్స్ PDF వర్క్బెంచ్ — మీ కంప్యూటర్లోనే నడుస్తుంది, గోప్యంగా ఉంటుంది, స్క్రిప్ట్లతో ఆటోమేట్ చేయవచ్చు.
|
||||
Join the ArtCraft community ArtCraft కమ్యూనిటీలో చేరండి
|
||||
Get help, share feedback and follow development on Discord. Discordలో సహాయం పొందండి, మీ అభిప్రాయాన్ని పంచుకోండి, అభివృద్ధిని అనుసరించండి.
|
||||
Recommended tools సిఫార్సు చేసిన సాధనాలు
|
||||
Use now ఇప్పుడే ఉపయోగించు
|
||||
Open file ఫైల్ను తెరువు
|
||||
@@ -279,10 +276,8 @@ comment menu Edit సవరించు
|
||||
Split document… పత్రాన్ని విభజించు…
|
||||
Number pages… పేజీలకు సంఖ్యలు వేయి…
|
||||
Keyboard shortcuts కీబోర్డ్ షార్ట్కట్లు
|
||||
Join the ArtCraft Discord ArtCraft Discordలో చేరండి
|
||||
PdfCraft web page PdfCraft వెబ్ పేజీ
|
||||
PdfCraft on GitHub GitHubలో PdfCraft
|
||||
ArtCraft website ArtCraft వెబ్సైట్
|
||||
Check for updates… అప్డేట్ల కోసం తనిఖీ చేయి…
|
||||
About PdfCraft PdfCraft గురించి
|
||||
Export a PDF PDFను ఎగుమతి చేయి
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 13 and column 16.
|
@@ -56,7 +56,6 @@
|
||||
Flatten Fill & Sign when saving Kaydederken Doldur ve İmzala'yı düzleştir
|
||||
Text, marks and signatures become part of the page. Other comments stay editable. Metin, işaretler ve imzalar sayfanın bir parçası olur. Diğer yorumlar düzenlenebilir kalır.
|
||||
OK Tamam
|
||||
Join our Discord Discord'umuza katılın
|
||||
Close Kapat
|
||||
Next / previous match Sonraki / önceki eşleşme
|
||||
Copy selected text Seçilen metni kopyala
|
||||
@@ -118,8 +117,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Geçerli sayfa — bir sayfa numarası veya etiketi (örneğin iv) yazıp Enter'a basın
|
||||
Welcome to PdfCraft PdfCraft'a Hoş Geldiniz
|
||||
An open-source PDF workbench — local, private, and scriptable. Açık kaynaklı bir PDF çalışma alanı — yerel, gizli ve komut dosyalarıyla yönetilebilir.
|
||||
Join the ArtCraft community ArtCraft topluluğuna katılın
|
||||
Get help, share feedback and follow development on Discord. Discord'da yardım alın, geri bildirim paylaşın ve geliştirmeyi takip edin.
|
||||
Recommended tools Önerilen araçlar
|
||||
Use now Şimdi kullan
|
||||
Open file Dosya aç
|
||||
@@ -260,10 +257,8 @@
|
||||
Split document… Belgeyi böl…
|
||||
Number pages… Sayfaları numaralandır…
|
||||
Keyboard shortcuts Klavye kısayolları
|
||||
Join the ArtCraft Discord ArtCraft Discord'una katıl
|
||||
PdfCraft web page PdfCraft web sayfası
|
||||
PdfCraft on GitHub GitHub'da PdfCraft
|
||||
ArtCraft website ArtCraft web sitesi
|
||||
Check for updates… Güncellemeleri denetle…
|
||||
About PdfCraft PdfCraft hakkında
|
||||
Export a PDF PDF'i dışa aktar
|
||||
|
||||
|
@@ -91,7 +91,6 @@
|
||||
Side panels Бічні панелі
|
||||
Enable Acrobat JavaScript Увімкнути Acrobat JavaScript
|
||||
OK OK
|
||||
Join our Discord Приєднатися до нашого Discord
|
||||
Close Закрити
|
||||
Next / previous match Наступний / попередній збіг
|
||||
Copy selected text Копіювати виділений текст
|
||||
@@ -159,8 +158,6 @@
|
||||
Current page — type a page number or label (such as iv) and press Enter Поточна сторінка — введіть номер або позначку сторінки (наприклад iv) і натисніть Enter
|
||||
Welcome to PdfCraft Вітаємо в PdfCraft
|
||||
An open-source PDF workbench — local, private, and scriptable. Відкритий інструментарій для PDF — локальний, приватний і з підтримкою сценаріїв.
|
||||
Join the ArtCraft community Приєднатися до спільноти ArtCraft
|
||||
Get help, share feedback and follow development on Discord. Отримуйте допомогу, діліться відгуками й стежте за розробкою в Discord.
|
||||
Recommended tools Рекомендовані інструменти
|
||||
Use now Використати зараз
|
||||
Open file Відкрити файл
|
||||
@@ -301,10 +298,8 @@
|
||||
Split document… Розділити документ…
|
||||
Number pages… Пронумерувати сторінки…
|
||||
Keyboard shortcuts Клавіатурні скорочення
|
||||
Join the ArtCraft Discord Приєднатися до Discord ArtCraft
|
||||
PdfCraft web page Вебсторінка PdfCraft
|
||||
PdfCraft on GitHub PdfCraft на GitHub
|
||||
ArtCraft website Вебсайт ArtCraft
|
||||
Check for updates… Перевірити оновлення…
|
||||
About PdfCraft Про PdfCraft
|
||||
Export a PDF Експортувати PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1796,13 +1796,8 @@
|
||||
Split document… 拆分文档…
|
||||
Number pages… 页面编号…
|
||||
Keyboard shortcuts 键盘快捷键
|
||||
Join the ArtCraft Discord 加入 ArtCraft Discord
|
||||
Join the ArtCraft community 加入 ArtCraft 社区
|
||||
Get help, share feedback and follow development on Discord. 在 Discord 上获取帮助、分享反馈并关注开发动态。
|
||||
Join our Discord 加入我们的 Discord
|
||||
PdfCraft web page PdfCraft 网页
|
||||
PdfCraft on GitHub GitHub 上的 PdfCraft
|
||||
ArtCraft website ArtCraft 官网
|
||||
Check for updates… 检查更新…
|
||||
About PdfCraft 关于 PdfCraft
|
||||
JavaScript console… JavaScript 控制台…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -1743,13 +1743,8 @@
|
||||
Split document… 分割文件…
|
||||
Number pages… 編訂頁碼…
|
||||
Keyboard shortcuts 鍵盤快速鍵
|
||||
Join the ArtCraft Discord 加入 ArtCraft Discord
|
||||
Join the ArtCraft community 加入 ArtCraft 社群
|
||||
Get help, share feedback and follow development on Discord. 在 Discord 取得協助、提供意見並追蹤開發進度。
|
||||
Join our Discord 加入 Discord 社群
|
||||
PdfCraft web page PdfCraft 網頁
|
||||
PdfCraft on GitHub GitHub 上的 PdfCraft
|
||||
ArtCraft website ArtCraft 網站
|
||||
Check for updates… 尋找更新…
|
||||
About PdfCraft 關於 PdfCraft
|
||||
JavaScript console… JavaScript 主控台…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -119,6 +119,7 @@ pub mod scroll_speed;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod system_fonts;
|
||||
pub mod theme;
|
||||
pub mod titlebar;
|
||||
pub mod ui_scale;
|
||||
pub mod updates;
|
||||
mod wheel_pager;
|
||||
@@ -507,6 +508,8 @@ pub struct PdfCraftApp {
|
||||
pub toast: Option<(String, f64)>,
|
||||
/// Whether the macOS title bar is drawn by us (traffic lights over our tab strip).
|
||||
pub integrated_titlebar: bool,
|
||||
pub custom_titlebar: bool,
|
||||
pub system_title_bar: bool,
|
||||
pub password_prompt: Option<PasswordPrompt>,
|
||||
pub unlock_prompt: Option<UnlockPrompt>,
|
||||
pub full_screen: bool,
|
||||
@@ -809,6 +812,8 @@ impl PdfCraftApp {
|
||||
pinned: Default::default(),
|
||||
toast: None,
|
||||
integrated_titlebar: false,
|
||||
custom_titlebar: false,
|
||||
system_title_bar: false,
|
||||
password_prompt: None,
|
||||
unlock_prompt: None,
|
||||
full_screen: false,
|
||||
@@ -1620,6 +1625,7 @@ impl PdfCraftApp {
|
||||
"reload_changed_files": self.reload_changed_files,
|
||||
"pinned_folders": self.pinned.folders,
|
||||
"theme": self.theme_preference,
|
||||
"system_title_bar": self.system_title_bar,
|
||||
"scroll_speed": self.scroll_speed,
|
||||
"default_mode": self.default_mode,
|
||||
"default_layout": canvas::display_token(self.view_defaults.layout, self.view_defaults.continuous),
|
||||
@@ -1703,6 +1709,9 @@ impl PdfCraftApp {
|
||||
if let Ok(preference) = serde_json::from_value::<ThemePreference>(v["theme"].clone()) {
|
||||
self.set_theme_preference(preference);
|
||||
}
|
||||
if let Some(on) = v["system_title_bar"].as_bool() {
|
||||
self.system_title_bar = on;
|
||||
}
|
||||
if let Ok(speed) = serde_json::from_value::<scroll_speed::ScrollSpeed>(v["scroll_speed"].clone()) {
|
||||
self.scroll_speed = speed;
|
||||
}
|
||||
@@ -1825,7 +1834,11 @@ impl PdfCraftApp {
|
||||
"system" => ThemePreference::System,
|
||||
"light" => ThemePreference::Light,
|
||||
"dark" => ThemePreference::Dark,
|
||||
_ => return Err("theme must be light, dark, or system".into()),
|
||||
"catppuccinlatte" | "catppuccin_latte" | "catppuccinLatte" => ThemePreference::CatppuccinLatte,
|
||||
"catppuccinfrappe" | "catppuccin_frappe" | "catppuccinFrappe" => ThemePreference::CatppuccinFrappe,
|
||||
"catppuccinmacchiato" | "catppuccin_macchiato" | "catppuccinMacchiato" => ThemePreference::CatppuccinMacchiato,
|
||||
"catppuccinmocha" | "catppuccin_mocha" | "catppuccinMocha" => ThemePreference::CatppuccinMocha,
|
||||
_ => return Err("theme must be light, dark, catppuccinLatte, catppuccinFrappe, catppuccinMacchiato, catppuccinMocha, or system".into()),
|
||||
};
|
||||
self.set_theme_preference(preference);
|
||||
}
|
||||
@@ -2441,6 +2454,9 @@ impl eframe::App for PdfCraftApp {
|
||||
dialogs::show(self, &ctx);
|
||||
self.show_progress(&ctx);
|
||||
widgets::toast(self, &ctx);
|
||||
if self.custom_titlebar {
|
||||
titlebar::resize_zones(ui);
|
||||
}
|
||||
self.finish_render_frame(&ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use craft_ui::theme::catppuccin::Flavor;
|
||||
use egui::{Color32, CornerRadius, FontData, FontDefinitions, FontFamily, FontId, Stroke, Visuals};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
|
||||
@@ -10,6 +11,46 @@ pub enum ThemeKind {
|
||||
#[default]
|
||||
Light,
|
||||
Dark,
|
||||
CatppuccinLatte,
|
||||
CatppuccinFrappe,
|
||||
CatppuccinMacchiato,
|
||||
CatppuccinMocha,
|
||||
}
|
||||
|
||||
impl ThemeKind {
|
||||
pub const ALL: [ThemeKind; 6] = [
|
||||
ThemeKind::Light,
|
||||
ThemeKind::Dark,
|
||||
ThemeKind::CatppuccinLatte,
|
||||
ThemeKind::CatppuccinFrappe,
|
||||
ThemeKind::CatppuccinMacchiato,
|
||||
ThemeKind::CatppuccinMocha,
|
||||
];
|
||||
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
ThemeKind::Light => "light",
|
||||
ThemeKind::Dark => "dark",
|
||||
ThemeKind::CatppuccinLatte => "catppuccinLatte",
|
||||
ThemeKind::CatppuccinFrappe => "catppuccinFrappe",
|
||||
ThemeKind::CatppuccinMacchiato => "catppuccinMacchiato",
|
||||
ThemeKind::CatppuccinMocha => "catppuccinMocha",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flavor(self) -> Option<Flavor> {
|
||||
match self {
|
||||
ThemeKind::CatppuccinLatte => Some(Flavor::Latte),
|
||||
ThemeKind::CatppuccinFrappe => Some(Flavor::Frappe),
|
||||
ThemeKind::CatppuccinMacchiato => Some(Flavor::Macchiato),
|
||||
ThemeKind::CatppuccinMocha => Some(Flavor::Mocha),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_light(self) -> bool {
|
||||
matches!(self, ThemeKind::Light | ThemeKind::CatppuccinLatte)
|
||||
}
|
||||
}
|
||||
|
||||
/// The saved user choice, independent of the light/dark colours currently displayed.
|
||||
@@ -19,6 +60,10 @@ pub enum ThemePreference {
|
||||
#[default]
|
||||
Light,
|
||||
Dark,
|
||||
CatppuccinLatte,
|
||||
CatppuccinFrappe,
|
||||
CatppuccinMacchiato,
|
||||
CatppuccinMocha,
|
||||
}
|
||||
|
||||
impl ThemePreference {
|
||||
@@ -28,6 +73,10 @@ impl ThemePreference {
|
||||
match self {
|
||||
Self::Light => ThemeKind::Light,
|
||||
Self::Dark => ThemeKind::Dark,
|
||||
Self::CatppuccinLatte => ThemeKind::CatppuccinLatte,
|
||||
Self::CatppuccinFrappe => ThemeKind::CatppuccinFrappe,
|
||||
Self::CatppuccinMacchiato => ThemeKind::CatppuccinMacchiato,
|
||||
Self::CatppuccinMocha => ThemeKind::CatppuccinMocha,
|
||||
Self::System => match system {
|
||||
Some(true) => ThemeKind::Dark,
|
||||
Some(false) => ThemeKind::Light,
|
||||
@@ -66,8 +115,40 @@ pub struct Tokens {
|
||||
pub radius: u8,
|
||||
}
|
||||
|
||||
fn catppuccin(kind: ThemeKind, f: Flavor) -> Tokens {
|
||||
let p = f.palette();
|
||||
let dark = f.is_dark();
|
||||
Tokens {
|
||||
kind,
|
||||
titlebar: p.mantle,
|
||||
chrome: p.base,
|
||||
panel: p.base,
|
||||
pasteboard: p.crust,
|
||||
card: p.surface0,
|
||||
border: p.surface1,
|
||||
divider: p.surface0,
|
||||
text: p.text,
|
||||
text_muted: p.subtext0,
|
||||
text_faint: p.overlay1,
|
||||
icon: p.subtext1,
|
||||
hover: p.surface0,
|
||||
pressed: p.surface1,
|
||||
selected: Color32::from_rgba_unmultiplied(p.mauve.r(), p.mauve.g(), p.mauve.b(), if dark { 55 } else { 40 }),
|
||||
accent: p.mauve,
|
||||
accent_text: if dark { p.lavender } else { p.mauve },
|
||||
accent_soft: Color32::from_rgba_unmultiplied(p.mauve.r(), p.mauve.g(), p.mauve.b(), if dark { 40 } else { 30 }),
|
||||
field: p.mantle,
|
||||
badge_new: p.mauve,
|
||||
page_shadow: if dark { Color32::from_black_alpha(120) } else { Color32::from_black_alpha(34) },
|
||||
radius: 6,
|
||||
}
|
||||
}
|
||||
|
||||
impl Tokens {
|
||||
pub fn for_kind(kind: ThemeKind) -> Self {
|
||||
if let Some(f) = kind.flavor() {
|
||||
return catppuccin(kind, f);
|
||||
}
|
||||
match kind {
|
||||
ThemeKind::Light => Self {
|
||||
kind,
|
||||
@@ -93,7 +174,7 @@ impl Tokens {
|
||||
page_shadow: Color32::from_black_alpha(34),
|
||||
radius: 6,
|
||||
},
|
||||
ThemeKind::Dark => Self {
|
||||
ThemeKind::Dark | ThemeKind::CatppuccinLatte | ThemeKind::CatppuccinFrappe | ThemeKind::CatppuccinMacchiato | ThemeKind::CatppuccinMocha => Self {
|
||||
kind,
|
||||
titlebar: Color32::from_rgb(0x1B, 0x1B, 0x1E),
|
||||
chrome: Color32::from_rgb(0x26, 0x26, 0x2A),
|
||||
@@ -125,7 +206,7 @@ impl Tokens {
|
||||
}
|
||||
|
||||
pub fn dark(&self) -> bool {
|
||||
self.kind == ThemeKind::Dark
|
||||
!self.kind.is_light()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,4 +460,20 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catppuccin_flavors_resolve_and_set_correct_kind() {
|
||||
for kind in [
|
||||
ThemeKind::CatppuccinLatte,
|
||||
ThemeKind::CatppuccinFrappe,
|
||||
ThemeKind::CatppuccinMacchiato,
|
||||
ThemeKind::CatppuccinMocha,
|
||||
] {
|
||||
assert!(kind.flavor().is_some());
|
||||
let t = Tokens::for_kind(kind);
|
||||
assert_eq!(t.kind, kind);
|
||||
assert_eq!(t.dark(), !kind.is_light());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
//! The window's own title bar on Windows and Linux, where the window has no OS decorations
|
||||
//! ([`PdfCraftApp::custom_titlebar`]): the tab strip row is the title bar. Empty space in it
|
||||
//! drags the window and a double-click there maximizes it, caption buttons at the far right
|
||||
//! minimize, maximize/restore and close, and thin invisible zones along the window's edges resize
|
||||
//! it. On macOS the traffic lights sit over the same row and only the drag works.
|
||||
|
||||
use egui::{CursorIcon, Id, LayerId, Order, PointerButton, Rect, ResizeDirection, Sense, Stroke, Ui, ViewportCommand, pos2, vec2};
|
||||
|
||||
use crate::PdfCraftApp;
|
||||
use crate::theme::Tokens;
|
||||
|
||||
/// One caption button: as wide as the native Windows ones.
|
||||
pub const BUTTON_WIDTH: f32 = 46.0;
|
||||
/// The three caption buttons together.
|
||||
pub const WIDTH: f32 = 3.0 * BUTTON_WIDTH;
|
||||
/// Height of the title row (tab strip) when it carries the caption buttons.
|
||||
pub const HEIGHT: f32 = 38.0;
|
||||
/// Resize zone thickness along an edge, and the side of a corner zone.
|
||||
const EDGE: f32 = 6.0;
|
||||
const CORNER: f32 = 12.0;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
enum Caption {
|
||||
Minimize,
|
||||
Maximize,
|
||||
Close,
|
||||
}
|
||||
|
||||
const CAPTIONS: [Caption; 3] = [Caption::Minimize, Caption::Maximize, Caption::Close];
|
||||
|
||||
fn caption_id(c: Caption) -> Id {
|
||||
Id::new(("titlebar-caption", c as u8))
|
||||
}
|
||||
|
||||
fn maximized(ctx: &egui::Context) -> bool {
|
||||
ctx.input(|i| i.viewport().maximized.unwrap_or(false))
|
||||
}
|
||||
|
||||
fn toggle_maximize(ctx: &egui::Context) {
|
||||
ctx.send_viewport_cmd(ViewportCommand::Maximized(!maximized(ctx)));
|
||||
}
|
||||
|
||||
pub fn drag_area(ui: &Ui, rect: Rect) {
|
||||
let ctx = ui.ctx();
|
||||
let resp = ui.interact(rect, Id::new("titlebar-drag"), Sense::click_and_drag());
|
||||
if ctx.input(|i| i.pointer.any_pressed()) {
|
||||
let bare = ctx.viewport(|v| v.hits.click.is_some_and(|w| w.id == resp.id));
|
||||
ctx.data_mut(|d| d.insert_temp(resp.id, bare));
|
||||
}
|
||||
if resp.double_clicked() {
|
||||
toggle_maximize(ctx);
|
||||
} else if resp.drag_started_by(PointerButton::Primary) && ctx.data(|d| d.get_temp(resp.id).unwrap_or(false)) {
|
||||
ctx.send_viewport_cmd(ViewportCommand::StartDrag);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn caption_buttons(app: &mut PdfCraftApp, ui: &mut Ui, bar: Rect) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let max = maximized(ui.ctx());
|
||||
let mut clicked = None;
|
||||
for (i, c) in CAPTIONS.into_iter().enumerate() {
|
||||
let r = Rect::from_min_size(pos2(bar.right() - WIDTH + i as f32 * BUTTON_WIDTH, bar.top()), vec2(BUTTON_WIDTH, bar.height()));
|
||||
let resp = ui.interact(r, caption_id(c), Sense::click());
|
||||
let close = c == Caption::Close;
|
||||
let fill = match (resp.is_pointer_button_down_on(), resp.hovered()) {
|
||||
(true, _) if close => egui::Color32::from_rgb(0xc4, 0x2b, 0x1c),
|
||||
(_, true) if close => egui::Color32::from_rgb(0xe8, 0x11, 0x23),
|
||||
(true, _) => t.pressed,
|
||||
(_, true) => t.hover,
|
||||
_ => egui::Color32::TRANSPARENT,
|
||||
};
|
||||
ui.painter().rect_filled(r, 0.0, fill);
|
||||
let ink = if close && resp.hovered() { egui::Color32::WHITE } else { t.icon };
|
||||
paint_glyph(ui, c, max, r.center(), Stroke::new(1.0, ink));
|
||||
let tip = caption_tip(c, max);
|
||||
resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, tip));
|
||||
if resp.on_hover_text(tip).clicked() {
|
||||
clicked = Some(c);
|
||||
}
|
||||
}
|
||||
match clicked {
|
||||
Some(Caption::Minimize) => ui.ctx().send_viewport_cmd(ViewportCommand::Minimized(true)),
|
||||
Some(Caption::Maximize) => toggle_maximize(ui.ctx()),
|
||||
Some(Caption::Close) => {
|
||||
let ctx = ui.ctx().clone();
|
||||
app.request_quit(&ctx);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn caption_tip(c: Caption, max: bool) -> &'static str {
|
||||
match c {
|
||||
Caption::Minimize => crate::i18n::t("Minimize\0".trim_end_matches('\0')),
|
||||
Caption::Maximize if max => crate::i18n::t("Restore\0".trim_end_matches('\0')),
|
||||
Caption::Maximize => crate::i18n::t("Maximize\0".trim_end_matches('\0')),
|
||||
Caption::Close => tl!("Close"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn paint_glyph(ui: &Ui, c: Caption, maximized: bool, at: egui::Pos2, s: Stroke) {
|
||||
let p = ui.painter();
|
||||
let g = Rect::from_center_size(at, vec2(10.0, 10.0));
|
||||
match c {
|
||||
Caption::Minimize => {
|
||||
p.line_segment([g.left_center(), g.right_center()], s);
|
||||
}
|
||||
Caption::Maximize if maximized => {
|
||||
let front = Rect::from_min_max(g.min + vec2(0.0, 2.0), g.max - vec2(2.0, 0.0));
|
||||
p.rect_stroke(front, 0.0, s, egui::StrokeKind::Middle);
|
||||
p.line(vec![g.min + vec2(2.0, 2.0), g.min + vec2(2.0, 0.0), g.right_top(), g.max - vec2(0.0, 2.0), g.max - vec2(2.0, 2.0)], s);
|
||||
}
|
||||
Caption::Maximize => {
|
||||
p.rect_stroke(g, 0.0, s, egui::StrokeKind::Middle);
|
||||
}
|
||||
Caption::Close => {
|
||||
p.line_segment([g.left_top(), g.right_bottom()], s);
|
||||
p.line_segment([g.right_top(), g.left_bottom()], s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn zones(w: Rect) -> [(Rect, ResizeDirection, CursorIcon); 8] {
|
||||
use ResizeDirection::*;
|
||||
let (e, c) = (EDGE, CORNER);
|
||||
[
|
||||
(Rect::from_min_max(w.left_top(), pos2(w.right(), w.top() + e)), North, CursorIcon::ResizeVertical),
|
||||
(Rect::from_min_max(pos2(w.left(), w.bottom() - e), w.right_bottom()), South, CursorIcon::ResizeVertical),
|
||||
(Rect::from_min_max(w.left_top(), pos2(w.left() + e, w.bottom())), West, CursorIcon::ResizeHorizontal),
|
||||
(Rect::from_min_max(pos2(w.right() - e, w.top()), w.right_bottom()), East, CursorIcon::ResizeHorizontal),
|
||||
(Rect::from_min_size(w.left_top(), vec2(c, c)), NorthWest, CursorIcon::ResizeNwSe),
|
||||
(Rect::from_min_size(w.right_top() - vec2(c, 0.0), vec2(c, c)), NorthEast, CursorIcon::ResizeNeSw),
|
||||
(Rect::from_min_size(w.left_bottom() - vec2(0.0, c), vec2(c, c)), SouthWest, CursorIcon::ResizeNeSw),
|
||||
(Rect::from_min_size(w.right_bottom() - vec2(c, c), vec2(c, c)), SouthEast, CursorIcon::ResizeNwSe),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn resize_zones(ui: &mut Ui) {
|
||||
let ctx = ui.ctx().clone();
|
||||
if maximized(&ctx) || ctx.input(|i| i.viewport().fullscreen.unwrap_or(false)) {
|
||||
return;
|
||||
}
|
||||
let w = ctx.content_rect();
|
||||
let layer = LayerId::new(Order::Foreground, Id::new("titlebar-resize"));
|
||||
let zui = ui.new_child(egui::UiBuilder::new().layer_id(layer).max_rect(w));
|
||||
for (i, (r, dir, cursor)) in zones(w).into_iter().enumerate() {
|
||||
let resp = zui.interact(r, Id::new(("titlebar-resize", i)), Sense::drag()).on_hover_cursor(cursor);
|
||||
if resp.drag_started_by(PointerButton::Primary) {
|
||||
ctx.send_viewport_cmd(ViewportCommand::BeginResize(dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use egui::{Event, Pos2, RawInput, ViewportId};
|
||||
|
||||
struct Win {
|
||||
ctx: egui::Context,
|
||||
app: PdfCraftApp,
|
||||
width: f32,
|
||||
time: f64,
|
||||
maximized: bool,
|
||||
}
|
||||
|
||||
impl Win {
|
||||
fn new(width: f32) -> Self {
|
||||
let ctx = egui::Context::default();
|
||||
let mut app = PdfCraftApp::new();
|
||||
app.custom_titlebar = true;
|
||||
crate::theme::apply(&ctx, app.theme);
|
||||
Self { ctx, app, width, time: 0.0, maximized: false }
|
||||
}
|
||||
|
||||
fn frame(&mut self, events: Vec<Event>) -> egui::FullOutput {
|
||||
self.time += 0.05;
|
||||
let mut input =
|
||||
RawInput { screen_rect: Some(Rect::from_min_size(Pos2::ZERO, vec2(self.width, 600.0))), time: Some(self.time), events, ..Default::default() };
|
||||
if let Some(v) = input.viewports.get_mut(&ViewportId::ROOT) {
|
||||
v.maximized = Some(self.maximized);
|
||||
}
|
||||
let app = &mut self.app;
|
||||
let width = self.width;
|
||||
let mut out = self.ctx.run_ui(input, |ui| {
|
||||
let bar = Rect::from_min_size(Pos2::ZERO, vec2(width, HEIGHT));
|
||||
drag_area(ui, bar);
|
||||
caption_buttons(app, ui, bar);
|
||||
resize_zones(ui);
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
out
|
||||
}
|
||||
|
||||
fn gesture(&mut self, path: &[Pos2]) -> Vec<ViewportCommand> {
|
||||
let button = |p: Pos2, pressed| Event::PointerButton { pos: p, button: PointerButton::Primary, pressed, modifiers: Default::default() };
|
||||
let mut events = vec![vec![Event::PointerMoved(path[0])], vec![button(path[0], true)]];
|
||||
events.extend(path[1..].iter().map(|p| vec![Event::PointerMoved(*p)]));
|
||||
events.push(vec![button(*path.last().unwrap_or(&path[0]), false)]);
|
||||
events.into_iter().flat_map(|e| self.frame(e).viewport_output.remove(&ViewportId::ROOT).map(|v| v.commands).unwrap_or_default()).collect()
|
||||
}
|
||||
|
||||
fn click(&mut self, p: Pos2) -> Vec<ViewportCommand> {
|
||||
self.gesture(&[p])
|
||||
}
|
||||
|
||||
fn caption(&self, c: Caption) -> Rect {
|
||||
self.ctx.read_response(caption_id(c)).map(|r| r.rect).unwrap_or(Rect::NOTHING)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn caption_buttons_take_the_right_end_of_the_row() {
|
||||
for width in [800.0, 1440.0] {
|
||||
let mut w = Win::new(width);
|
||||
w.frame(vec![]);
|
||||
w.frame(vec![]);
|
||||
let [min, max, close] = CAPTIONS.map(|c| w.caption(c));
|
||||
assert_eq!((close.right(), close.top()), (width, 0.0), "Close sits in the window's corner at {width}");
|
||||
assert!(close.height() >= 30.0 && [min, max, close].iter().all(|r| r.width() == BUTTON_WIDTH));
|
||||
assert_eq!((min.right(), max.right()), (max.left(), close.left()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minimize_maximize_and_close_follow_the_window_state() {
|
||||
let mut w = Win::new(1000.0);
|
||||
w.frame(vec![]);
|
||||
let (min, max, close) = (w.caption(Caption::Minimize).center(), w.caption(Caption::Maximize).center(), w.caption(Caption::Close).center());
|
||||
assert!(w.click(min).contains(&ViewportCommand::Minimized(true)));
|
||||
assert!(w.click(max).contains(&ViewportCommand::Maximized(true)));
|
||||
w.maximized = true;
|
||||
assert!(w.click(max).contains(&ViewportCommand::Maximized(false)), "Restore");
|
||||
assert!(w.click(close).contains(&ViewportCommand::Close));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_row_space_drags_and_double_click_maximizes() {
|
||||
let mut w = Win::new(1440.0);
|
||||
w.frame(vec![]);
|
||||
let empty = pos2(700.0, 16.0);
|
||||
let cmds = w.gesture(&[empty, empty + vec2(12.0, 4.0), empty + vec2(30.0, 8.0)]);
|
||||
assert_eq!(cmds.iter().filter(|c| matches!(c, ViewportCommand::StartDrag)).count(), 1, "{cmds:?}");
|
||||
let mut cmds = w.click(empty);
|
||||
cmds.extend(w.click(empty));
|
||||
assert!(cmds.contains(&ViewportCommand::Maximized(true)), "{cmds:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edge_zones_resize_unless_maximized() {
|
||||
use ResizeDirection::*;
|
||||
let mut w = Win::new(1000.0);
|
||||
w.frame(vec![]);
|
||||
for (p, dir) in [
|
||||
(pos2(1.0, 300.0), West),
|
||||
(pos2(998.0, 300.0), East),
|
||||
(pos2(500.0, 1.0), North),
|
||||
(pos2(500.0, 598.0), South),
|
||||
(pos2(2.0, 2.0), NorthWest),
|
||||
(pos2(997.0, 3.0), NorthEast),
|
||||
(pos2(3.0, 597.0), SouthWest),
|
||||
(pos2(998.0, 598.0), SouthEast),
|
||||
] {
|
||||
let cmds = w.gesture(&[p, p + vec2(6.0, 6.0)]);
|
||||
assert_eq!(cmds, vec![ViewportCommand::BeginResize(dir)], "at {p:?}");
|
||||
}
|
||||
w.maximized = true;
|
||||
let cmds = w.gesture(&[pos2(1.0, 300.0), pos2(8.0, 300.0)]);
|
||||
assert!(!cmds.iter().any(|c| matches!(c, ViewportCommand::BeginResize(_))), "{cmds:?}");
|
||||
}
|
||||
}
|
||||
@@ -326,35 +326,14 @@ pub fn progress_notice(app: &PdfCraftApp, ctx: &egui::Context) -> bool {
|
||||
cancel
|
||||
}
|
||||
|
||||
/// The ArtCraft wordmark (Storyteller's brand, docs/brand/; not open source), sized to `height`.
|
||||
pub fn artcraft_logo(ui: &mut egui::Ui, height: f32) -> Response {
|
||||
let dark = ui.visuals().dark_mode;
|
||||
let (uri, bytes): (&str, &'static [u8]) = if dark {
|
||||
("bytes://artcraft-logo-white.svg", include_bytes!("../../../docs/brand/artcraft-logo-white.svg"))
|
||||
} else {
|
||||
("bytes://artcraft-logo.svg", include_bytes!("../../../docs/brand/artcraft-logo.svg"))
|
||||
};
|
||||
ui.add(egui::Image::from_bytes(uri, bytes).max_height(height).alt_text("ArtCraft"))
|
||||
}
|
||||
|
||||
/// The ArtCraft mark (brand blue, works on light and dark), `size` points square.
|
||||
pub fn artcraft_mark(ui: &mut egui::Ui, size: f32) -> Response {
|
||||
ui.add(
|
||||
egui::Image::from_bytes("bytes://artcraft-mark.svg", include_bytes!("../../../docs/brand/artcraft-mark.svg"))
|
||||
.fit_to_exact_size(vec2(size, size))
|
||||
.alt_text("ArtCraft"),
|
||||
)
|
||||
}
|
||||
|
||||
/// Buttons for every community link (`pdfcraft_engine::links`), Discord first and prominent.
|
||||
/// Buttons for every project link (`pdfcraft_engine::links`).
|
||||
/// Returns the registry command of the one clicked.
|
||||
pub fn community_links(ui: &mut egui::Ui) -> Option<&'static str> {
|
||||
let mut clicked = None;
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.spacing_mut().item_spacing = vec2(8.0, 8.0);
|
||||
for (i, l) in pdfcraft_engine::links::LINKS.iter().enumerate() {
|
||||
let resp = if i == 0 { icon_pill(ui, l.icon, tl!("Join our Discord"), true) } else { icon_pill(ui, l.icon, tl!(l.label), false) };
|
||||
if resp.on_hover_text(l.url).clicked() {
|
||||
for l in pdfcraft_engine::links::LINKS {
|
||||
if icon_pill(ui, l.icon, tl!(l.label), false).on_hover_text(l.url).clicked() {
|
||||
clicked = Some(l.command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,8 +282,8 @@ fn tabs_shrink_to_fit_then_arrows_step_through_them_and_open_stays_in_sight() {
|
||||
}
|
||||
});
|
||||
let open = h.get_by_label("Open").rect();
|
||||
let discord = h.get_by_label("Discord").rect();
|
||||
assert!(open.right() <= discord.left(), "Open {open:?} must not run under Discord {discord:?}");
|
||||
let controls = h.get_by_label("Keyboard shortcuts").rect();
|
||||
assert!(open.right() <= controls.left(), "Open {open:?} must not run under the controls {controls:?}");
|
||||
let mut previous_right = f32::MIN;
|
||||
for i in 0..5 {
|
||||
let tab = h.get_by_label(&name(i)).rect();
|
||||
@@ -307,15 +307,15 @@ fn tabs_shrink_to_fit_then_arrows_step_through_them_and_open_stays_in_sight() {
|
||||
assert_eq!(enabled(&h, "Scroll tabs right"), Some(true), "and then there is more to the right");
|
||||
let open = h.get_by_label("Open").rect();
|
||||
let right = h.get_by_label("Scroll tabs right").rect();
|
||||
assert!(right.right() <= open.left() + 0.5 && open.right() <= h.get_by_label("Discord").rect().left());
|
||||
// Twenty: Open stays in sight left of Discord.
|
||||
assert!(right.right() <= open.left() + 0.5 && open.right() <= h.get_by_label("Keyboard shortcuts").rect().left());
|
||||
// Twenty: Open stays in sight left of the controls.
|
||||
for i in 0..13 {
|
||||
h.state_mut().open_bytes(&format!("more-{i:02}.pdf"), None, FIXTURE.to_vec()).unwrap();
|
||||
}
|
||||
h.run_steps(4);
|
||||
let open = h.get_by_label("Open").rect();
|
||||
let discord = h.get_by_label("Discord").rect();
|
||||
assert!(open.left() > 0.0 && open.right() <= discord.left(), "Open {open:?} stays in sight left of Discord {discord:?}");
|
||||
let controls = h.get_by_label("Keyboard shortcuts").rect();
|
||||
assert!(open.left() > 0.0 && open.right() <= controls.left(), "Open {open:?} stays in sight left of the controls {controls:?}");
|
||||
}
|
||||
|
||||
/// macOS (#789): with the integrated title bar, the strip is the 28 pt band AppKit centres the
|
||||
@@ -328,7 +328,7 @@ fn the_integrated_title_bar_is_the_traffic_light_band() {
|
||||
app.open_bytes("band.pdf", None, FIXTURE.to_vec()).unwrap();
|
||||
});
|
||||
let band = 28.0;
|
||||
for label in ["Home", "band.pdf", "Open", "Discord", "Keyboard shortcuts"] {
|
||||
for label in ["Home", "band.pdf", "Open", "Keyboard shortcuts"] {
|
||||
let r = h.get_by_label(label).rect();
|
||||
assert!(r.top() >= 0.0 && r.bottom() <= band, "{label}: {r:?} inside the {band} pt title bar");
|
||||
assert!(r.height() >= 24.0, "{label}: {r:?} stays clickable");
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//! Community links: the Discord button is one click away everywhere; Help menu, About dialog and
|
||||
//! home screen open the ArtCraft and PdfCraft pages.
|
||||
//! Project links: the Help menu and About dialog open the PdfCraft GitHub page.
|
||||
|
||||
use egui_kittest::Harness;
|
||||
use egui_kittest::kittest::Queryable;
|
||||
@@ -18,42 +17,16 @@ fn harness(setup: impl FnOnce(&mut PdfCraftApp) + 'static) -> Harness<'static, P
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discord_button_in_the_top_bar_opens_discord() {
|
||||
let mut h = harness(|_| {});
|
||||
h.get_by_label("Discord").click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().last_opened_url.as_deref(), Some(links::DISCORD));
|
||||
assert_eq!(links::DISCORD, "https://discord.gg/artcraft");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn home_screen_links() {
|
||||
for (label, url) in [
|
||||
("Join our Discord", links::DISCORD),
|
||||
("PdfCraft web page", "https://getartcraft.com/apps/pdfcraft"),
|
||||
("PdfCraft on GitHub", "https://github.com/storytold/pdfcraft"),
|
||||
("ArtCraft website", "https://getartcraft.com"),
|
||||
] {
|
||||
let mut h = harness(|_| {});
|
||||
h.get_by_label("Join the ArtCraft community");
|
||||
h.get_by_label(label).click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().last_opened_url.as_deref(), Some(url), "{label}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn about_dialog_shows_the_brand_and_links() {
|
||||
fn about_dialog_shows_the_links() {
|
||||
let pdf = b"%PDF-1.7\n1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj\n3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] >> endobj\ntrailer << /Root 1 0 R >>\n%%EOF";
|
||||
// With a document open, so the home screen's own links are not on screen.
|
||||
let mut h = harness(move |app| {
|
||||
app.open_bytes("one.pdf", None, pdf.to_vec()).unwrap();
|
||||
app.dialog = Some(Dialog::About);
|
||||
});
|
||||
assert!(h.query_all_by_label("ArtCraft").count() >= 2, "the mark and the wordmark (alt text)");
|
||||
h.get_by_label("Join our Discord").click();
|
||||
h.get_by_label("PdfCraft on GitHub").click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().last_opened_url.as_deref(), Some(links::DISCORD));
|
||||
assert_eq!(h.state().last_opened_url.as_deref(), Some(links::GITHUB));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
ArtCraft brand assets: license
|
||||
|
||||
The ArtCraft name, wordmark and mark (the "ArtCraft Marks"), including every file in this
|
||||
directory in every color, size and format, are owned by the ArtCraft Team. They are trademarks
|
||||
and are NOT open source. They are not covered by PdfCraft's MIT OR Apache-2.0 license, and nothing in
|
||||
that license, in NOTICE or in any other file of this repository grants any right to them.
|
||||
|
||||
Permission
|
||||
|
||||
The ArtCraft Team grants a limited, non-exclusive, non-transferable, revocable, royalty-free
|
||||
permission to use the ArtCraft Marks only:
|
||||
|
||||
1. as part of copies of this repository; and
|
||||
2. within PdfCraft itself, its documentation and its official builds, to identify PdfCraft as made
|
||||
by the ArtCraft team and community and to link to getartcraft.com and its community.
|
||||
|
||||
Conditions
|
||||
|
||||
The permission holds only while every one of these is true:
|
||||
|
||||
- The marks are used exactly as supplied in this directory. Do not redraw, recolor, crop,
|
||||
stretch, rotate, animate, outline or add effects to them, extract parts of them, or combine
|
||||
them with any other name, mark or artwork.
|
||||
- They are used only in the context of PdfCraft, and only to say that the ArtCraft team makes it.
|
||||
They must never suggest that the ArtCraft Team made, sponsors, endorses, certifies or supports
|
||||
any other product, service, fork, modified version, plug-in, organization or person.
|
||||
- Neither the marks nor the ArtCraft name appear in the name, logo, icon, domain, social media
|
||||
handle, app-store listing, advertising or marketing of anything other than PdfCraft.
|
||||
|
||||
Forks and modified versions
|
||||
|
||||
If you distribute or publish a modified version of PdfCraft, or any work derived from it, you must
|
||||
remove the ArtCraft Marks from it (or replace them with your own) and must not call it ArtCraft or
|
||||
present it as an ArtCraft product. You may say, in plain text, that your work is based on PdfCraft by
|
||||
the ArtCraft team. A fork kept only to propose changes back to this repository may keep the marks
|
||||
unchanged.
|
||||
|
||||
Everything else
|
||||
|
||||
Any use not expressly permitted here needs prior written permission from the ArtCraft Team
|
||||
(https://getartcraft.com/). The permission ends automatically for anyone who breaks these terms.
|
||||
All other rights are reserved.
|
||||
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 26 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -19.42 136.34 136.34" role="img" aria-label="ArtCraft">
|
||||
<title>ArtCraft</title>
|
||||
<path fill="#0b0b0c" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 341 B |
|
Before Width: | Height: | Size: 24 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -19.42 136.34 136.34" role="img" aria-label="ArtCraft">
|
||||
<title>ArtCraft</title>
|
||||
<path fill="#4e7bfb" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 341 B |
@@ -19,10 +19,10 @@
|
||||
<launchable type="desktop-id">ai.storyteller.pdfcraft.desktop</launchable>
|
||||
<icon type="stock">ai.storyteller.pdfcraft</icon>
|
||||
<!-- Only url types known to appstream 0.15 (Ubuntu 22.04, where CI validates): no vcs-browser. -->
|
||||
<url type="homepage">https://getartcraft.com/apps/pdfcraft</url>
|
||||
<url type="homepage">https://github.com/storytold/pdfcraft</url>
|
||||
<url type="bugtracker">https://github.com/storytold/pdfcraft/issues</url>
|
||||
<url type="help">https://github.com/storytold/pdfcraft</url>
|
||||
<url type="contact">https://discord.gg/artcraft</url>
|
||||
<url type="contact">https://github.com/storytold/pdfcraft/issues</url>
|
||||
<categories>
|
||||
<category>Office</category>
|
||||
<category>Viewer</category>
|
||||
|
||||
@@ -14,7 +14,7 @@ section: graphics
|
||||
priority: optional
|
||||
maintainer: ${PDFCRAFT_MAINTAINER}
|
||||
vendor: Learning Machines LLC
|
||||
homepage: https://getartcraft.com/apps/pdfcraft
|
||||
homepage: https://github.com/storytold/pdfcraft
|
||||
license: MIT OR Apache-2.0
|
||||
description: |-
|
||||
Open-source, native PDF workbench: read, comment, fill and sign forms,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
Produces, in $env:DIST (default: dist/release):
|
||||
pdfcraft-<version>-windows-<arch>.msi per-machine installer (WiX v5)
|
||||
pdfcraft-<version>-windows-<arch>-portable.zip pdfcraft.exe + pdfcraft-cli.exe + models\ + portable.txt
|
||||
pdfcraft-cli-<version>-windows-<arch>.zip pdfcraft-cli.exe standalone
|
||||
|
||||
The binaries link the C runtime statically (+crt-static), so neither the MSI nor the portable
|
||||
zip needs the Visual C++ redistributable. Signing is delegated to sign.ps1 (skipped with a
|
||||
@@ -25,6 +26,7 @@ param(
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Root = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||
Set-Location $Root
|
||||
|
||||
function Invoke-Native([string] $What, [scriptblock] $Block) {
|
||||
Write-Output "==> $What"
|
||||
@@ -56,6 +58,17 @@ if (-not $env:PDFCRAFT_BUILD_DATE) { $env:PDFCRAFT_BUILD_DATE = (Get-Date).ToUni
|
||||
Write-Output "PdfCraft $Version for Windows $Arch ($Target)"
|
||||
|
||||
if (-not $SkipBuild) {
|
||||
# Locate rc.exe if not in PATH
|
||||
if (-not (Get-Command rc.exe -ErrorAction SilentlyContinue)) {
|
||||
$kits = Join-Path ${env:ProgramFiles(x86)} 'Windows Kits\10\bin'
|
||||
$foundRc = Get-ChildItem -Path $kits -Recurse -Filter rc.exe -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -match '\\x64\\rc\.exe$' } |
|
||||
Sort-Object FullName -Descending | Select-Object -First 1
|
||||
if ($foundRc) {
|
||||
$env:PATH = "$($foundRc.DirectoryName);$env:PATH"
|
||||
}
|
||||
}
|
||||
|
||||
# Static CRT: no VC++ redistributable needed. Scoped to the target so host build scripts and
|
||||
# proc-macros are unaffected.
|
||||
$flagVar = 'CARGO_TARGET_' + ($Target.ToUpper() -replace '-', '_') + '_RUSTFLAGS'
|
||||
@@ -152,6 +165,19 @@ $Zip = Join-Path $Dist "pdfcraft-$Version-windows-$Arch-portable.zip"
|
||||
Remove-Item -Force $Zip -ErrorAction SilentlyContinue
|
||||
Compress-Archive -Path $Portable -DestinationPath $Zip
|
||||
|
||||
# ---- cli zip -----------------------------------------------------------------------------------
|
||||
$CliPortable = Join-Path $TargetDir "windows-package\pdfcraft-cli-$Version-windows-$Arch"
|
||||
Remove-Item -Recurse -Force $CliPortable -ErrorAction SilentlyContinue
|
||||
New-Item -ItemType Directory -Force -Path $CliPortable | Out-Null
|
||||
Copy-Item (Join-Path $Stage 'pdfcraft-cli.exe') $CliPortable
|
||||
foreach ($f in 'README.md', 'LICENSE', 'LICENSE-MIT', 'LICENSE-APACHE') {
|
||||
$p = Join-Path $Root $f
|
||||
if (Test-Path $p) { Copy-Item $p $CliPortable }
|
||||
}
|
||||
$CliZip = Join-Path $Dist "pdfcraft-cli-$Version-windows-$Arch.zip"
|
||||
Remove-Item -Force $CliZip -ErrorAction SilentlyContinue
|
||||
Compress-Archive -Path $CliPortable -DestinationPath $CliZip
|
||||
|
||||
# Smoke-test the CLI when this machine can run it. An ARM64 build made on an x64 runner can't run
|
||||
# here; .github/workflows/windows-arm64.yml installs and runs it on ARM64 instead.
|
||||
$HostArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()
|
||||
@@ -160,4 +186,4 @@ if ($Arch -ne 'arm64' -or $HostArch -eq 'arm64') {
|
||||
} else {
|
||||
Write-Output "skipping pdfcraft-cli --version: an $Arch build doesn't run on this $HostArch machine"
|
||||
}
|
||||
Get-Item $Msi, $Zip | Format-Table Name, Length
|
||||
Get-Item $Msi, $Zip, $CliZip | Format-Table Name, Length
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
Add/Remove Programs show a blank icon (#57). -->
|
||||
<Icon Id="PdfcraftIcon.ico" SourceFile="$(var.IconPath)" />
|
||||
<Property Id="ARPPRODUCTICON" Value="PdfcraftIcon.ico" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/pdfcraft" />
|
||||
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/pdfcraft" />
|
||||
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://github.com/storytold/pdfcraft" />
|
||||
<Property Id="ARPURLUPDATEINFO" Value="https://github.com/storytold/pdfcraft" />
|
||||
<Property Id="ARPHELPLINK" Value="https://github.com/storytold/pdfcraft/issues" />
|
||||
<!-- Desktop shortcut (#143): on by default, a checkbox in the full-UI welcome dialog, and
|
||||
INSTALLDESKTOPSHORTCUT=0 on the msiexec command line for unattended installs. Secure, so the
|
||||
choice made in the (unelevated) UI reaches the elevated install. -->
|
||||
|
||||
@@ -36,11 +36,6 @@ pub const ALLOWED_LICENCES: &[&str] = &[
|
||||
];
|
||||
|
||||
/// The closed list of Adobe-authored, non-visual technical data (AGENTS.md §1.1): (crate, path).
|
||||
/// Storyteller's own brand marks (the ArtCraft name and logos): shipped in the app and docs, but
|
||||
/// not licensed for reuse by forks. Allowed only for `kind = "logo"` entries under `docs/brand/`
|
||||
/// (AGENTS.md §1.2).
|
||||
pub const BRAND_LICENCE: &str = "LicenseRef-Storyteller-Trademark";
|
||||
|
||||
pub const ADOBE_DATA_ALLOWED: &[(&str, &str)] = &[("hayro-cmap", "assets/cmaps.brotli"), ("hayro-interpret", "src/font/generated/metrics.rs")];
|
||||
|
||||
/// File extensions that count as assets wherever they appear in the repository.
|
||||
@@ -235,10 +230,7 @@ pub fn check(root: &Path, m: &Manifest, repo_files: &[String], lock: &BTreeSet<(
|
||||
if !seen.insert(a.path.clone()) {
|
||||
problems.push(format!("{}: listed twice", a.path));
|
||||
}
|
||||
let brand = a.licence == BRAND_LICENCE && a.kind == "logo" && a.path.starts_with("docs/brand/");
|
||||
if !brand {
|
||||
licence_ok(&a.path, &a.licence, &mut problems);
|
||||
}
|
||||
licence_ok(&a.path, &a.licence, &mut problems);
|
||||
if !root.join(&a.licence_file).is_file() {
|
||||
problems.push(format!("{}: licence file {} is missing", a.path, a.licence_file));
|
||||
}
|
||||
@@ -543,22 +535,6 @@ mod tests {
|
||||
assert!(p.iter().any(|p| p.contains("SHA-256 does not match")), "{p:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn brand_licence_only_for_brand_logos() {
|
||||
let root = super::root();
|
||||
for (path, kind, pass) in [
|
||||
("docs/brand/artcraft-mark.svg", "logo", true),
|
||||
("docs/brand/artcraft-mark.svg", "icon", false),
|
||||
("assets/icons/mark.svg", "logo", false),
|
||||
] {
|
||||
let mut a = asset(path, "Storyteller", kind, BRAND_LICENCE);
|
||||
a.licence_file = "docs/brand/LICENSE-brand.txt".into();
|
||||
let m = Manifest { asset: vec![a], ..Default::default() };
|
||||
let p = check(&root, &m, &[], &BTreeSet::new());
|
||||
assert_eq!(p.iter().all(|p| !p.contains("allowlist")), pass, "{path} {kind}: {p:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn adobe_data_only_on_the_closed_list() {
|
||||
let l = lock(&[("hayro-cmap", "1.0.0"), ("other", "1.0.0")]);
|
||||
|
||||
@@ -106,14 +106,7 @@ fn update_attribution(root: &Path) -> Result<()> {
|
||||
let stem = file.trim_end_matches(".png");
|
||||
let scene = SCENES.iter().find(|(n, ..)| *n == stem);
|
||||
let (title, usage) = scene.map(|(_, t, u, _)| (*t, *u)).unwrap_or(("PdfCraft screenshot", "README"));
|
||||
// The home screen shows the ArtCraft mark: say so (it is a Storyteller trademark, not open
|
||||
// source; AGENTS.md §1.2), so the screenshot's licence is not read as covering it.
|
||||
let shows_home = scene.is_some_and(|(.., args)| args.windows(2).any(|w| w[0] == "--home" && w[1] == "on"));
|
||||
let contents = if shows_home {
|
||||
"Shows PdfCraft UI, Lucide icons, the showcase PDF built from the [[fetched]] OFL fonts, and the ArtCraft mark (Storyteller trademark from docs/brand/, not covered by this licence)"
|
||||
} else {
|
||||
"Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts"
|
||||
};
|
||||
let contents = "Shows only PdfCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts";
|
||||
let bytes = std::fs::read(root.join("docs/images").join(file))?;
|
||||
out.push_str(&format!(
|
||||
"\n[[asset]]\npath = \"docs/images/{file}\"\ntitle = \"PdfCraft screenshot: {title}\"\nauthor = \"PdfCraft contributors (generated by `cargo xtask screenshots`)\"\nsource = \"this repository\"\nlicence = \"MIT OR Apache-2.0\"\nlicence_file = \"LICENSE-MIT\"\nkind = \"image\"\nusage = \"{usage}. {contents}\"\nsha256 = \"{}\"\n",
|
||||
|
||||