Files
hcie-rust-v3.05/hcie-io/handoff.md
T

111 lines
5.5 KiB
Markdown
Raw Normal View History

2026-07-09 02:59:53 +03:00
# PSD Layer Style (fx) Test Files — Handoff
## Goal
Otomatik PSD layer style test pipeline: her efekt tipi için doğru formatta PSD dosyası → Photopea referans render → engine çıktısı ile karşılaştırma.
## Output
16 test PSD dosyası `/home/hc/Pictures/_psd_stil_test/` altında:
- `fx_baseline.psd` — efektsiz base
- `fx_drop_shadow.psd`, `fx_inner_shadow.psd`, `fx_outer_glow.psd`, `fx_inner_glow.psd`
- `fx_bevel_inner.psd`, `fx_bevel_outer.psd`, `fx_emboss.psd`, `fx_pillow_emboss.psd`
- `fx_satin.psd`, `fx_color_overlay.psd`, `fx_gradient_overlay.psd`, `fx_pattern_overlay.psd`
- `fx_stroke_inside.psd`, `fx_stroke_center.psd`, `fx_stroke_outside.psd`
## Changes Made
### `src/psd_saver.rs` — lfx2 descriptor writer (replaces lrFX)
- **Tag**: `"lrFX"``"lfx2"` (line 188)
- **`write_lfx2_block()`**: Writes lfx2 descriptor format matching Photopea output:
- Header: `[ver=0 u32][dver=16 u32]`
- `_read_body`: name(U+0000), classID('null'), count(2+n_effects)
- Fixed items: `Scl`(UntF #Prc 100), `masterFXSwitch`(bool true)
- Per-effect: Objc with effect-specific fields (see effect field lists below)
- **Effect descriptors** (`write_fx_descriptor`):
- `DrSh` (DropShadow): 14 fields — enab, Md, Opct, Clr, uglg, lagl, Dstn, Ckmt, blur, Nose, AntA, TrnS, layerConceals, Cntn
- `IrSh` (InnerShadow): 14 fields (same as DrSh)
- `OrGl` (OuterGlow): 10 fields — enab, Md, Opct, Clr, GlwT, blur, Ckmt, AntA, TrnS, Nose
- `IrGl` (InnerGlow): 10 fields — enab, Md, Opct, Clr, GlwS, blur, Ckmt, AntA, TrnS, Nose
- `ebbl` (BevelEmboss): 29 fields — enab, hglM, hglC, hglO, sdwM, sdwC, sdwO, bvlT, bvlS, uglg, lagl, Lald, srgR, blur, bvlD, TrnS, antialiasGloss, Sftn, useShape, MpgS, AntA, Inpr, useTexture, InvT, Algn, Scl, textureDepth, Ptrn, phase
- `lagl` (Satin): 10 fields — enab, Md, Opct, Clr, lagl, Dstn, blur, MpgS, Invr, AntA
- `sofi` (ColorOverlay): 5 fields — enab, Md, Opct, Clr, Cntn
- `GrFl` (GradientOverlay): 10 fields — enab, Md, Opct, Angl, Type, Rvrs, Algn, Scl, Ofst, Grad(Grdn)
- `PtFl` (PatternOverlay): 5 fields + Ptrn Objc with Nm, Idnt, phase
- `FrFX` (Stroke): 8 fields — enab, Styl, PntT, Md, Opct, Sz, Clr (+ TrnS if not Color fill)
### Descriptor helper functions
- `w_key4(buf, &[u8; 4])` — 4-byte OSType key (length prefix = 0)
- `w_key_var(buf, &[u8])` — variable-length key (length prefix = N)
- `w_ustr_null(buf)` — Unicode name: length=1, U+0000
- `w_ustr(buf, &str)` — Unicode name: length=N, UTF-16BE bytes
- `w_class_id(buf, &[u8; 4])` — classID with length=0 prefix
- `w_bool(buf, bool)`, `w_enum(buf, type, val)`, `w_untf(buf, unit, f64)`, `w_doub(buf, f64)`, `w_long(buf, i32)`
- `w_objc_start(buf)` — writes "Objc" tag
- `w_objc_body_start(buf, class_id, count)` — _read_body: name(U+0000) + classID + count
- `w_rgbc_color(buf, &[u8; 4])` — writes RGBC Objc with Rd/Grn/Bl doub
- `w_default_contour(buf)` — standard linear contour (TrnS/MpgS)
- `w_contour_with_key(buf, key)` — key + default contour
### `write_shmd_block()` — Photopea sheet metadata
- Structure: `[ver=1][8BIMcmls][sub_size=0][desc_size][descriptor...]`
- Descriptor items:
- `LyrI`: long 0
- `layerSettings`: VlLs → Objc null with 6 items:
- `compList`: VlLs[long 0]
- `enab`: bool true
- `Ofst`: Objc {Hrzn long 0, Vrtc long 0}
- `FXRefPoint`: Objc {Hrzn long 0, Vrtc long 0}
- `blendOptions`: Objc {Md enum Nrml, Opct UntF 100, fillOpacity UntF 100}
- `Lefx`: Objc — FULL effect descriptor copy (same as lfx2: Scl + masterFXSwitch + effects)
- Total: ~1038 bytes per single-effect layer
### Layer extra data additions
- **Blending ranges**: 40 bytes → 10 pairs of (u16=0, u16=65535)
- **iOpa block**: `8BIMiOpa` size=4, data=`[0xff, 0x00, 0x00, 0x00]`
- **brst block**: `8BIMbrst` size=0
- **lfx2 block**: `8BIMlfx2` size=N, descriptor data
- **shmd block**: `8BIMshmd` size=M, Photopea metadata
### `examples/generate_style_tests.rs`
- Generates all 16 PSD files: 15 single-effect + 1 baseline
- 512×512 canvas, asymmetric trapezoidal shape per layer
- Baseline has no effects; all others have exactly 1 effect
### Imports
- Added `GradientDef` to `use hcie_fx::types::{..., GradientDef}`
- Uses `hcie_blend::BlendMode` for blend mode mapping
## Key Format Decisions
### Objc format
Photopea Objc descriptor: NO outer wrapper. Direct `_read_body`:
```
"Objc" + name_len(u32) + name(u16×N) + classID_len(u32) + classID + count(u32) + items...
```
where name is always `U+0000` (len=1), and classID is length-prefixed (len=0 → 4-byte key).
### enum format
```"enum" + classID_len(u32=0) + type_id(4B) + classID_len(u32=0) + value(4B)```
### Nested Objc
Contour (TrnS/MpgS), Color (RGBC), Pattern (Ptrn), Gradient (Grdn) all use the same format recursively.
## How to Regenerate
```bash
cd /home/hc/Documents/00_PROJECTS/hcie-rust-v4
cargo run -p hcie-io --example generate_style_tests
```
Files go to `/home/hc/Pictures/_psd_stil_test/fx_*.psd`.
## Verification
- All 15 effect files have: lfx2 + shmd + iOpa + brst blocks
- fx_baseline.psd has no effect blocks (baseline reference)
- lfx2 binary format byte-identical in structure to working `hc_drop_shadow.psd`
- shmd mirrors the lfx2 descriptor inside `Lefx` section
## Remaining / Known Issues
- lfx2 format verified against Photopea output (`hc_drop_shadow.psd`)
- Files open in Photopea — effects should render based on shmd+lfx2 metadata
- GradientOverlay and PatternOverlay use minimal default gradient/pattern data
- BevelEmboss texture (Ptrn) uses hardcoded default UUID
- Contour names use ASCII "Linear" (Photopea uses localized names like "Lineární")