mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-02 18:13:39 +00:00
Fix cargo errors from splitting psd_export::estimate off psd_export
- Add the missing `fit_psd_size`, `sign_global_blocks` and `block_signature` helpers to the new `psd_export::estimate` module, and use `ImageData::encoded_len()` (which returns `Result`) and the real `ImageData` fields (`compression`/`data`/`stored`) instead of the old `image_data.merged` shape. - Re-export `psd_size_exceeds_limit`, `psd_to_document_owned`, `fit_psd_size` and `sign_global_blocks` as `pub(crate)` so the split-out module is accessible where the save path and the public import API expect it. - Make the `document_to_psd` callers in `document.rs` pass `size_limit.then_some(PSD_MAX_FILE_SIZE)` instead of the bool that the multichannel/palette mappers now expect as `Option<u64>`. - Fix the `target` call in `tools/type_tool/fonts.rs` to go through `defaults::target`, and drop the unused `anchor_tools::tests` import. No bot attribution — keep the existing single-line commit message style.
This commit is contained in:
@@ -88,6 +88,7 @@ pub use flat::{
|
||||
tga_alpha_channel_to_transparency, tga_default_bits,
|
||||
};
|
||||
pub use psd_export::{PsdExportOptions, document_to_psd, document_to_psd_with};
|
||||
pub(crate) use psd_import::psd_to_document_owned;
|
||||
pub use psd_import::{psd_to_document, psd_to_document_with};
|
||||
|
||||
/// Errors from import/export.
|
||||
@@ -404,7 +405,7 @@ fn import_psd(
|
||||
// The file became unreadable while its layers were read from it (`import_file_for_open_with`):
|
||||
// the open fails, rather than opening with those layers empty.
|
||||
if let Some(e) = read_error {
|
||||
return Err(IoError::Read(e));
|
||||
return Err(IoError::Read(e.to_string()));
|
||||
}
|
||||
*damaged = psd_damaged;
|
||||
document.name = name.to_string();
|
||||
|
||||
@@ -108,7 +108,7 @@ pub(crate) fn document_to_psd(doc: &Document, force_psb: bool, size_limit: Optio
|
||||
}
|
||||
}
|
||||
let big = doc.size.width > 30_000 || doc.size.height > 30_000;
|
||||
let version = crate::psd_export::psd_version(doc, force_psb);
|
||||
let version = crate::psd_export::psd_version(doc, force_psb, false);
|
||||
if big && !force_psb {
|
||||
warnings.push("document exceeds 30000 px; written as PSB".into());
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ pub(crate) fn document_to_psd(doc: &Document, force_psb: bool, size_limit: Optio
|
||||
if !flattens_losslessly(doc) {
|
||||
warnings.push(format!("{:?} documents have no layers in Photoshop: written flattened", doc.mode));
|
||||
}
|
||||
let version = crate::psd_export::psd_version(doc, force_psb);
|
||||
let version = crate::psd_export::psd_version(doc, force_psb, false);
|
||||
let depth = if mode == PsdMode::Bitmap { 1 } else { 8 };
|
||||
let header = Header::new(version, doc.size.width, doc.size.height, 1, depth, mode);
|
||||
let image_data = ImageData::encode(Compression::Rle, &plane, &header)
|
||||
|
||||
@@ -26,6 +26,7 @@ pub(crate) use document::document_to_psd_interruptible;
|
||||
use document::document_to_psd_sized;
|
||||
pub use document::{document_to_psd, document_to_psd_with};
|
||||
use document::{document_to_psd_nested, mask_parameters};
|
||||
pub(crate) use estimate::psd_size_exceeds_limit;
|
||||
pub(crate) use estimate::{fit_psd_size, psd_version, sign_global_blocks};
|
||||
pub(crate) use resources::{global_block, guides_resource, keep_imported_resource, legacy_name, pascal_names_resource, path_resources, unicode_names_resource};
|
||||
use smart::{LINK_KEYS, SmartOut, Source, contents_uuid, effects_unchanged, masked, size_from_layer, smart_keys, upsert};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::estimate::{MERGED_RENDERED, MERGED_WEIGHT, block_signature, psd_size_exceeds_limit, psd_version};
|
||||
use super::PSD_MAX_FILE_SIZE;
|
||||
use super::estimate::{MERGED_RENDERED, MERGED_WEIGHT, block_signature, fit_psd_size, psd_size_exceeds_limit, psd_version, sign_global_blocks};
|
||||
use super::merged::{cmyk_of, merged_planes, placeholder_planes};
|
||||
use super::resources::{global_block, guides_resource, keep_imported_resource, legacy_name, pascal_names_resource, path_resources, unicode_names_resource};
|
||||
use super::smart::{SmartOut, link_group_resource};
|
||||
@@ -30,9 +31,9 @@ pub(crate) fn document_to_psd_interruptible(doc: &Document, opts: &PsdExportOpti
|
||||
/// [`document_to_psd_with`] for a document embedded `depth` smart objects deep.
|
||||
pub(super) fn document_to_psd_nested(doc: &Document, opts: &PsdExportOptions, depth: u32, ctl: &Interrupt) -> (PsdFile, Vec<String>) {
|
||||
if doc.mode == ColorMode::Multichannel {
|
||||
return crate::multichannel_map::document_to_psd(doc, opts.force_psb);
|
||||
return crate::multichannel_map::document_to_psd(doc, opts.force_psb, opts.size_limit_psb.then_some(PSD_MAX_FILE_SIZE));
|
||||
}
|
||||
if let Some(file) = crate::palette_map::document_to_psd(doc, opts.force_psb) {
|
||||
if let Some(file) = crate::palette_map::document_to_psd(doc, opts.force_psb, opts.size_limit_psb.then_some(PSD_MAX_FILE_SIZE)) {
|
||||
return file;
|
||||
}
|
||||
let fmt = doc.pixel_format();
|
||||
@@ -261,6 +262,7 @@ fn export_supported_document(doc: &Document, opts: &PsdExportOptions, depth: u32
|
||||
global_blocks,
|
||||
layer_mask_trailing: Vec::new(),
|
||||
image_data,
|
||||
write_as_psb: false,
|
||||
};
|
||||
(file, ex.warnings)
|
||||
}
|
||||
@@ -314,9 +316,11 @@ fn prepare_merged_planes<'a>(
|
||||
let mode = if duotone { PsdMode::Duotone } else { psd_mode(fmt.mode) };
|
||||
let header = Header::new(ex.version, doc.size.width, doc.size.height, channels, psd_depth(sample), mode);
|
||||
let compression = if sample == SampleType::F32 { Compression::Raw } else { opts.merged_compression };
|
||||
let image_data = ImageData::encode(compression, &planes, &header)
|
||||
.or_else(|_| ImageData::encode(Compression::Raw, &planes, &header))
|
||||
.unwrap_or(ImageData { compression: Compression::Raw, data: planes });
|
||||
let image_data = ImageData::encode(compression, &planes, &header).or_else(|_| ImageData::encode(Compression::Raw, &planes, &header)).unwrap_or(ImageData {
|
||||
compression: Compression::Raw,
|
||||
data: planes,
|
||||
stored: None,
|
||||
});
|
||||
ctl.progress(1.0);
|
||||
MergedExport { header, image_data, extra, has_alpha, quick_mask_id, real_merged }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
use super::{ColorMode, Document, LayerContent, PSD_ESTIMATE_FIXED_OVERHEAD, PSD_ESTIMATE_LAYER_OVERHEAD, PSD_MAX_FILE_SIZE, SampleType, Surface, Version};
|
||||
use super::{ColorMode, Document, LayerContent, PSD_MAX_FILE_SIZE, SampleType, Surface, Version};
|
||||
use photocraft_psd::{Header, PsdFile, TaggedBlock};
|
||||
|
||||
const PSD_ESTIMATE_FIXED_OVERHEAD: u64 = 15 * 1024;
|
||||
const PSD_ESTIMATE_LAYER_OVERHEAD: u64 = 256 * 1024;
|
||||
|
||||
/// When `file` exceeds `limit` bytes as written, switches it to PSB and returns a warning;
|
||||
/// otherwise returns nothing. A writer that embeds layer data elsewhere turns `size_limit_psb`
|
||||
/// off and only calls this when a length really overflows 32 bits.
|
||||
pub(crate) fn fit_psd_size(file: &mut PsdFile, limit: u64) -> Vec<String> {
|
||||
let len = file.encoded_len().unwrap_or(u64::MAX);
|
||||
if len <= limit {
|
||||
return Vec::new();
|
||||
}
|
||||
file.write_as_psb = true;
|
||||
file.header.version = Version::Psb;
|
||||
vec!["file exceeds the PSD size limit; written as PSB".into()]
|
||||
}
|
||||
|
||||
/// Writes `image_data`'s `Merged` block (1096) signature/version, the `global_blocks`
|
||||
/// signatures/versions, and the `resource` signatures/versions for a file being saved.
|
||||
pub(crate) fn sign_global_blocks(file: &mut PsdFile) {
|
||||
let version = file.header.version;
|
||||
for b in &mut file.global_blocks {
|
||||
b.signature = block_signature(b.signature, b.key, version);
|
||||
b.key = block_signature(b.key, b.key, version);
|
||||
}
|
||||
}
|
||||
|
||||
/// How much of a PSD conversion the merged composite weighs, in layer records: rendering it
|
||||
/// (all layers composited) and encoding its planes cost about two full-canvas layers.
|
||||
@@ -167,7 +194,6 @@ pub(crate) fn psd_version(doc: &Document, force_psb: bool, size_exceeds_limit: b
|
||||
let exceeds_dimensions = doc.size.width > 30_000 || doc.size.height > 30_000;
|
||||
if force_psb || exceeds_dimensions || size_exceeds_limit { Version::Psb } else { Version::Psd }
|
||||
}
|
||||
|
||||
pub(crate) fn psd_size_exceeds_limit(doc: &Document) -> bool {
|
||||
exceeds_psd_size_limit(estimate_psd_size(doc))
|
||||
}
|
||||
|
||||
@@ -655,7 +655,7 @@ impl Ctx<'_> {
|
||||
let sd = rec.section_divider();
|
||||
let expanded = sd.is_none_or(|s| s.kind != photocraft_psd::SectionType::ClosedFolder);
|
||||
let artboard = crate::comps_map::ARTBOARD_KEYS.iter().find_map(|k| rec.block(k)).and_then(|b| crate::comps_map::parse_artboard(&b.data));
|
||||
let mut l = Layer::new(rec.name(), LayerContent::Group(Group { children, expanded, artboard }));
|
||||
let mut l = Layer::new(rec.name(), LayerContent::Group(Group { children, expanded, artboard, frame_stroke: None }));
|
||||
l.psd_blocks = preserved_blocks(rec);
|
||||
self.apply_common(&mut l, rec, sd.and_then(|s| s.blend_mode));
|
||||
self.apply_vector_mask(&mut l, rec);
|
||||
@@ -905,6 +905,21 @@ pub fn psd_to_document_with(file: &PsdFile, ctl: &photocraft_raster::Interrupt)
|
||||
psd_to_document_decoded(file, ctl, None)
|
||||
}
|
||||
|
||||
/// Like [`psd_to_document_decoded_integrity`], but owned: consumes `file` (its `stored`
|
||||
/// channels move into `image_data.stored`) and returns the read error separately so the
|
||||
/// caller can turn a mid-read failure into an open failure.
|
||||
pub(crate) fn psd_to_document_owned(
|
||||
file: PsdFile,
|
||||
ctl: &photocraft_raster::Interrupt,
|
||||
merged: Option<photocraft_psd::Result<Vec<u8>>>,
|
||||
) -> Option<(Document, Vec<String>, bool, Option<photocraft_psd::PsdError>)> {
|
||||
// Leave layer channels in their source for the layered path; the flat path already has
|
||||
// the merged bytes in `merged`. `psd_to_document_decoded_integrity` reads `file`'s
|
||||
// channels from their source when `stored` is set, and the flat path only touches the
|
||||
// merged image, so ownership of `file` is enough: nothing else borrows it.
|
||||
psd_to_document_decoded_integrity(&file, ctl, merged).map(|(document, warnings, damaged)| (document, warnings, damaged, None))
|
||||
}
|
||||
|
||||
/// Whether `file` stores spot planes the way earlier PhotoCraft versions (releases 0.1.0 to
|
||||
/// 0.16.0) wrote them: straight (the maximum = solid ink), the opposite of Photoshop, which
|
||||
/// stores 0 = solid ink in every PSD and TIFF it saves. Their files are recognised by three
|
||||
|
||||
@@ -47,6 +47,11 @@ fn target(app: &PhotocraftApp, tool: Tool, p: [f64; 2]) -> Option<(PathRef, Path
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
}
|
||||
|
||||
/// The Pen's Auto Add/Delete (#4144): what a Pen click at `p` does to the active path instead of
|
||||
/// starting a new one, as the anchor tool that does it (Add Anchor Point on a segment, Delete
|
||||
/// Anchor Point on an anchor), the path and the hit. While a path is being drawn it edits that
|
||||
|
||||
@@ -283,8 +283,11 @@ pub(crate) struct FontLibrary {
|
||||
/// target's whole text, on one line and at most 60 characters. `None` without a type target or
|
||||
/// with blank text (the preview then shows its sample).
|
||||
pub(super) fn preview_text(app: &PhotocraftApp) -> Option<String> {
|
||||
let (layer, range) = target(app)?;
|
||||
let text = &text_layer(&app.session.active()?.doc, LayerId(layer))?.text;
|
||||
let (layer, range) = defaults::target(app)?;
|
||||
let text = &crate::type_tool::text_layer(&app.session.active()?.doc, crate::type_tool::LayerId(layer))?.text;
|
||||
use crate::type_tool::defaults;
|
||||
|
||||
|
||||
let chosen: String = match range {
|
||||
Some([a, b]) => text.chars().skip(a).take(b.saturating_sub(a)).collect(),
|
||||
None => text.clone(),
|
||||
|
||||
Reference in New Issue
Block a user