Files
hcie-rust-v3.05/hcie-io/handoff.md
2026-07-09 02:59:53 +03:00

5.5 KiB
Raw Permalink Blame History

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

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í")