[package] name = "dr-ui" version.workspace = true edition.workspace = true rust-version.workspace = true license.workspace = true [dependencies] dr-types.workspace = true # TRACES: FR-DEV-6 # Reading Lightroom `.xmp` presets. Its own crate because the translation names # operations, which the interface may not — see `ui_names_no_operation.rs`. dr-preset-xmp.workspace = true # No `readback`. S1 wired Slint's texture import, so the develop view hands # the compositor the texture itself and there is no display round-trip left to # gate (ARCH §6.1, AC-8). The export path reads pixels back through # `export_pixels`, which is ungated and always was. # # `segment-readback` *is* on, and it is not a contradiction of the above. It # gates the region-graph transfer that local masking is built on: once per # image, on a worker, off the frame path. The display round-trip AC-8 forbids # stays behind its own switch, which remains off. See `dr-gpu/src/segment.rs`. dr-gpu = { workspace = true, features = ["segment-readback"] } # The semantic arm and its weights, for local adjustments (FR-DEV-3, D14). dr-segment = { workspace = true, features = ["semantic", "embedded-model"] } dr-decode.workspace = true serde_json.workspace = true tokio.workspace = true reqwest.workspace = true dr-plat.workspace = true dr-sync.workspace = true dr-xmp.workspace = true dr-sync-folder.workspace = true dr-sync-nextcloud.workspace = true dr-export.workspace = true # The panorama's geometry and its keypoint detector (§3.11). The detector's # runtime is the same tract the faces and masks already carry. dr-pano = { workspace = true, features = ["xfeat", "embedded-model"] } # The learned demosaic and denoise (FR-DEV-3g), under the same engine. dr-denoise = { workspace = true, features = ["native"] } dr-ingest.workspace = true # The sameness probe of a catalog duplicate (FR-CAT-11a): SHA-256 over the # ends of each copy, the digest the import already uses for whole files. sha2 = "0.10" dr-film.workspace = true # The lens profile database, here for the same reason dr-film is: dr-pipeline # knows the maths of lens correction and deliberately has no dependency with # which to find out which coefficients belong to which lens. The conversion # between the two crates' mirrored coefficient types happens in `develop.rs`, # because it is the only place that can see both. dr-lens.workspace = true dr-pipeline.workspace = true dr-catalog.workspace = true # The face pipeline, with the ONNX runtime: this is the layer that actually # runs the models over the library (docs/dev/faces.md). dr-face = { workspace = true, features = ["inference"] } # The engine behind both. `native` here means the *app* may look for a # runtime file; the build stays C-free either way (docs/dev/inference.md §3). dr-inference-engine = { workspace = true, features = ["native"] } dr-thumbs.workspace = true # For the drag ghost only: the composite under the cursor has to reach the # renderer through a file, and the fan of thumbnails needs alpha, which the # thumbnail store's JPEG cannot carry. See `collections_ui::drag_image_via_file`. png = "0.18" # The library module writes scan results straight into the catalog, so it # needs the same SQLite types dr-catalog exposes. rusqlite.workspace = true # The renderer is shared, but the backend is not: winit on desktop, # android-activity on Android, and enabling both makes the backend selector # pick at random. So the backend features live on the target-specific # dependencies below rather than here. # # `renderer-femtovg-wgpu` rather than `renderer-femtovg`: the latter is # FemtoVG over OpenGL, and a compositor drawing through GL cannot be handed a # `wgpu::Texture`. Importing one requires Slint itself to be rendering with # wgpu, and this is the FemtoVG backend that does (ARCH §6.1, spike S1). # # `unstable-wgpu-29` is the other half: the renderer feature makes Slint draw # with wgpu, and this one exposes the API to say so — `BackendSelector:: # require_wgpu_29` and `Image::try_from(wgpu::Texture)`. Unstable is Slint's # word for it; the surface is small and the alternative is the 7 ms round-trip. # # `renderer-femtovg` is *not* kept alongside as a fallback, though it would # still compile. Slint's winit backend prefers the wgpu FemtoVG renderer # whenever both are built, so the GL one would only ever be reached by someone # setting `SLINT_BACKEND=winit-femtovg` — and on that path an imported texture # is not drawn at all. FemtoVG-over-GL has no branch for a `wgpu::Texture`, so # it falls through to "render this image to a buffer", gets nothing back, and # draws nothing. A blank canvas with no error is a far worse failure than the # one below, so the fallback is removed rather than left as a trap. # # Consequence worth stating plainly: the desktop app now needs a working wgpu # adapter to open a window at all. Slint refuses a CPU adapter for this # renderer unless `SLINT_WGPU_CPU` is set in the environment. # # On Android the renderer is Skia, not FemtoVG — the android-activity backend # has no other — so `renderer-femtovg-wgpu` stays with winit below, and only # `unstable-wgpu-29` is shared. With it, `AndroidWindowAdapter` builds # `SkiaRenderer::default_wgpu_29`: Skia drawing on wgpu's Vulkan swapchain, # which is what lets it sample our texture. That swapchain used to tear in # portrait on a landscape-mounted panel (gfx-rs/wgpu#3345), and Android drew # with Skia over OpenGL behind a readback instead; the patched wgpu-hal and # Skia renderer in third_party/ pre-rotate it, which closed TD-1. slint = { workspace = true, features = ["compat-1-2", "unstable-wgpu-29"] } wgpu.workspace = true anyhow.workspace = true # `SettingsError` distinguishes an io failure from a malformed file, which the # settings page reports differently; anyhow would flatten both to a string. thiserror.workspace = true log.workspace = true pollster.workspace = true # Slint's element queries, for the `automation` feature only. Pinned to the # exact Slint release: it reaches into i-slint-core, which is versioned in # lockstep and has no stable API of its own. i-slint-backend-testing = { version = "=1.17.1", default-features = false, optional = true } # Runtime YAML only for `live-style`; release builds read the tokens the # Slint compiler folded in at build time and never touch style.yaml. serde_norway = { workspace = true, optional = true } # Backend per platform. Slint already declares its android-activity backend # under `cfg(target_os = "android")`, so this only has to name the feature; # cargo resolves it away entirely on desktop. [target.'cfg(not(target_os = "android"))'.dependencies] slint = { workspace = true, features = ["backend-winit", "renderer-femtovg-wgpu", "raw-window-handle-06"] } # The platform's own folder and file dialogues (`folder_dialog`): the XDG # portal on Linux — the one that reaches the user's disk from inside the # Flatpak, and needs no GTK — and the common item dialogue on Windows. Its # async-std feature is only the executor ashpd talks D-Bus on; zbus and # async-io are already in the tree for the keyring. rfd = { version = "0.16", default-features = false, features = ["xdg-portal", "wayland", "async-std"] } raw-window-handle = "0.6" # The manual's `file:` URL (`manual::desktop_open`): a Windows path and a # path with a space in it are both URLs only after encoding, and this is the # crate the workspace already encodes URLs with. url.workspace = true [target.'cfg(target_os = "android")'.dependencies] slint = { workspace = true, features = ["backend-android-activity-06"] } # Opening the sign-in URL needs an ACTION_VIEW Intent — Android has no # xdg-open. Version-matched to Slint's Android backend so both halves of the # process agree on the JavaVM types; ndk-context supplies the VM and activity # that android-activity's glue already stashed. jni = "0.22" ndk-context = "0.1" [build-dependencies] slint-build.workspace = true # build.rs generates theme.slint from style.yaml (S2). serde_norway.workspace = true [features] # Compile the scene model into the binary. # # On by default for the desktop app and *off* for Android, which unpacks the # same graph from APK assets instead — 24 MB of constant is worth avoiding in a # mobile install and not worth the plumbing to avoid on a desktop one. Without # it `segmentation::scene_categories` falls back to the installed-file lookup, # which is what a packaged desktop build uses too. scene-model = ["dr-segment/embedded-scene-model"] default = [] # Answer "where is the control labelled X?" over a Unix socket named by # `DR_AUTOMATION`, for the scripts that record the manual (src/automation.rs, # tools/manual). Off by default and never in a shipped build: it adds Slint's # element-query crate, and a listener nobody asked for has no place in a # release. `tools/manual/record.sh` builds with it. automation = ["dep:i-slint-backend-testing"] # Debug convenience: re-read style.yaml at startup so a palette can be tuned # without rebuilding. Costs the constant-folding of every token, so it stays # off by default and has no business in a release build. live-style = ["dep:serde_norway"] [dev-dependencies] # The face_index batch job wants a log level from the environment; the library # itself only ever calls `log`, and picks up whatever the application installs. env_logger.workspace = true # Standing in a test backend behind `dyn RemoteBackend`, which is an # `#[async_trait]` trait — implementing one needs the same attribute. async-trait.workspace = true # Runs the interface without a display: the film list's reachability test # drives the real window's event dispatch on Slint's testing backend. The same # pinned release as the `automation` dependency above, so nothing new is built. i-slint-backend-testing = { version = "=1.17.1", default-features = false }