Files
hcie-rust-v3.05/hcie-io/.kilo/plans/1780187392857-calm-circuit.md
2026-07-09 02:59:53 +03:00

11 KiB
Raw Permalink Blame History

Plan: Layer Effects (lfx2/lrFX) — Full Pipeline

Context

PSD'de layer efektleri (Drop Shadow, Outer Glow, Bevel & Emboss, Stroke vb.) lfx2 ve lrFX tagged block'larda saklanıyor. Şu an bu bloklar parse edilmiyor — sadece atlanıyor. hcie-io'da LayerStyle enum'u var ama blend_mode: String ile tanımlanmış (tip güvenli değil) ve hiçbir yerde kullanılmıyor.

Mevcut Durum

Crate İlgili kısım Durum
hcie-blend BlendMode enum (27 mod) Hazır, layer fx blend modes için kullanılabilir
hcie-blend blend_pixels() Hazır, efekt compositing için kullanılabilir
hcie-io LayerStyle enum ⚠️ Var ama blend_mode: String, parse yok
hcie-io lfx2/lrFX blokları Atlanıyor, parse edilmiyor
hcie-composite Layer struct styles alanı yok
hcie-composite composite_layers_parallel Efekt render yok

Mimari Karar: Yeni crate hcie-fx

hcie-blend sadece piksel matematiği (blend mode, LUT). Efektler YENİ piksel buffer üretiyor (gölgeler, parıltılar). Bu hcie-blend'in scope'unun dışında. hcie-filter mevcut pikselleri dönüştürüyor (blur, color adj). Efektler bağımsız katman oluşturuyor. hcie-composite pipeline'ı. hcie-io dosya I/O.

hcie-fx doğru yer: efekt veri yapılarını, binary parsing'i ve piksel render'ı sahiplenir. hcie-blend'e bağımlı (blend mode matematiği için). hcie-io ve hcie-composite'e bağımlı değil — onlar hcie-fx'e bağımlı.

hcie-blend ← hcie-fx → hcie-io (sadece tip paylaşımı)
               ↑
          hcie-composite

Dosya Yapısı

hcie-fx/
├── Cargo.toml
├── src/
│   ├── lib.rs              # re-exports, apply_layer_effects()
│   ├── types.rs            # LayerEffect enum, FxParams
│   ├── parser.rs           # parse_lfx2(), parse_lrFX()
│   ├── shadow.rs           # DropShadow, InnerShadow renderer
│   ├── glow.rs             # OuterGlow, InnerGlow renderer
│   ├── bevel.rs            # BevelEmboss renderer
│   ├── overlay.rs          # ColorOverlay, GradientOverlay, PatternOverlay
│   ├── stroke.rs           # Stroke renderer
│   └── satin.rs            # Satin renderer

Adım 1: hcie-fx/src/types.rs — Veri Yapıları

use hcie_blend::BlendMode;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum LayerEffect {
    DropShadow {
        enabled: bool,
        blend_mode: BlendMode,  // String değil!
        color: [u8; 4],
        opacity: f32,           // 0.0-1.0
        angle: f32,             // derece
        distance: f32,          // piksel
        spread: f32,            // 0-100%
        size: f32,              // piksel
        noise: f32,             // 0-100%
        contour: Option<ContourCurve>,
    },
    InnerShadow { /* aynı alanlar */ },
    OuterGlow {
        enabled: bool,
        blend_mode: BlendMode,
        color: [u8; 4],
        opacity: f32,
        spread: f32,
        size: f32,
        noise: f32,
        contour: Option<ContourCurve>,
    },
    InnerGlow { /* benzer */ },
    BevelEmboss {
        enabled: bool,
        style: BevelStyle,      // InnerBevel, OuterBevel, Emboss, PillowEmboss, StrokeEmboss
        technique: Technique,   // Smooth, ChiselHard, ChiselSoft
        depth: f32,
        direction: Direction,   // Up, Down
        size: f32,
        soften: f32,
        angle: f32,
        altitude: f32,
        highlight_blend: BlendMode,
        highlight_color: [u8; 4],
        highlight_opacity: f32,
        shadow_blend: BlendMode,
        shadow_color: [u8; 4],
        shadow_opacity: f32,
        contour: Option<ContourCurve>,
    },
    Satin {
        enabled: bool,
        blend_mode: BlendMode,
        color: [u8; 4],
        opacity: f32,
        angle: f32,
        distance: f32,
        size: f32,
        invert: bool,
    },
    ColorOverlay {
        enabled: bool,
        blend_mode: BlendMode,
        color: [u8; 4],
        opacity: f32,
    },
    GradientOverlay {
        enabled: bool,
        blend_mode: BlendMode,
        opacity: f32,
        angle: f32,
        scale: f32,
        gradient: GradientDef,
    },
    PatternOverlay {
        enabled: bool,
        blend_mode: BlendMode,
        opacity: f32,
        scale: f32,
        pattern_id: String,
    },
    Stroke {
        enabled: bool,
        position: StrokePosition, // Inside, Center, Outside
        fill_type: StrokeFill,    // Color, Gradient, Pattern
        blend_mode: BlendMode,
        opacity: f32,
        size: f32,
        color: [u8; 4],
    },
}

// Yardımcı tipler
pub struct ContourCurve { pub points: Vec<(f32, f32)> }
pub struct GradientDef { /* color stops, midpoint, angle, type */ }
pub enum BevelStyle { InnerBevel, OuterBevel, Emboss, PillowEmboss, StrokeEmboss }
pub enum Technique { Smooth, ChiselHard, ChiselSoft }
pub enum Direction { Up, Down }
pub enum StrokePosition { Inside, Center, Outside }
pub enum StrokeFill { Color([u8;4]), Gradient(GradientDef), Pattern(String) }

Adım 2: hcie-fx/src/parser.rs — Binary Parsing

lrFX bloğu (legacy, 396 byte)

Offset  Size  Description
0       4     Version (=0)
4       4     Count of effects
8       ...   Effect records (her biri 8BIM signature + veri)

Her efekt kaydı:

0       4     Signature ('cmnS' = common)
4       4     Size of common data
8       2     Enabled flag
10      4     Blend mode key (4-char, ör: 'Mltp' = Multiply)
14      1     Opacity (0-255)
15      4     Color (4 bytes RGBA)
19      ...   Effect-specific data

lfx2 bloğu (extended, 5496 byte)

Descriptor-based format. hcie-io'daki PsdReader ile parse edilebilir:

Version (4 bytes) = 16
Descriptor count
For each descriptor:
  Key (string)
  Type (classID)
  Value (type-dependent)

Blend mode mapping (4-char key → BlendMode):

'Nrml' → Normal, 'Dslv' → Dissolve, 'Drkn' → Darken,
'Mltp' → Multiply, 'CBrn' → ColorBurn, 'LBrn' → LinearBurn,
'Lghn' → Lighten, 'Scrn' → Screen, 'CDdg' → ColorDodge,
'LDdg' → LinearDodge, 'Ovrl' → Overlay, 'SftL' → SoftLight,
'HrdL' → HardLight, 'VvdL' → VividLight, 'LnrL' → LinearLight,
'PnLt' → PinLight, 'HrdM' → HardMix, 'Dffc' → Difference,
'Xclu' → Exclusion, 'H   ' → Hue, 'Strt' → Saturation,
'Clr ' → Color, 'Lmns' → Luminosity

Adım 3: hcie-fx/src/shadow.rs — Drop Shadow Renderer

pub fn render_drop_shadow(
    layer_alpha: &[u8],     // layer alpha channel (canvas_w * canvas_h)
    canvas_w: u32,
    canvas_h: u32,
    params: &DropShadowParams,
) -> Vec<u8> {
    // 1. Alpha'dan offset'li kopya oluştur (distance + angle)
    // 2. Gaussian blur uygula (size parametresi)
    // 3. Spread uygula (threshold + dilate)
    // 4. Noise ekle (opsiyonel)
    // 5. Color + opacity ile doldur
    // 6. RGBA buffer döndür
}

Diğer efektler benzer pattern:

  • Inner Shadow: maskelenmiş alpha ile aynı mantık
  • Outer Glow: shadow yerine glow (genellikle Screen blend)
  • Inner Glow: inner shadow gibi ama glow
  • Bevel & Emboss: directional lighting, bump map from alpha
  • Stroke: edge detection + fill
  • Color/Gradient/Pattern Overlay: doğrudan layer alpha ile maskelenmiş fill

Adım 4: hcie-io Entegrasyonu

4a: LayerStyle'ı hcie_fx::LayerEffect ile değiştir

hcie-io/src/lib.rs:

// Eski:
pub enum LayerStyle {
    DropShadow { ..., blend_mode: String },
    ...
}

// Yeni:
pub use hcie_fx::LayerEffect;  // Re-export
// veya hcie-io'nun kendi Layer'ında:
pub struct Layer {
    ...
    pub effects: Vec<hcie_fx::LayerEffect>,  // styles yerine
}

4b: parse_psd_sequential'de lfx2/lrFX parsing

hcie-io/src/lib.rs, tagged block loop'u içinde:

} else if key == "lfx2" {
    let block_data = r.read(block_len)?;
    match hcie_fx::parser::parse_lfx2(&block_data) {
        Ok(effects) => { layer_effects = effects; }
        Err(e) => { eprintln!("lfx2 parse error: {}", e); }
    }
} else if key == "lrFX" {
    let block_data = r.read(block_len)?;
    match hcie_fx::parser::parse_lrFX(&block_data) {
        Ok(effects) => { layer_effects = effects; }
        Err(e) => { eprintln!("lrFX parse error: {}", e); }
    }
}

4c: LayerRecord ve ParsedLayerData'ya effects ekle

struct LayerRecord {
    ...
    effects: Vec<hcie_fx::LayerEffect>,
}

pub struct ParsedLayerData {
    ...
    pub effects: Vec<hcie_fx::LayerEffect>,
}

Adım 5: hcie-composite Entegrasyonu

5a: Layer'a effects ekle

pub struct Layer {
    ...
    pub effects: Vec<hcie_fx::LayerEffect>,
}

5b: composite_layers_parallel'da efekt uygulama

Her layer compositing'den ÖNCE:

for (rev_i, layer) in layers.iter().enumerate() {
    if !layer.visible { continue; }

    // 1. Efektleri render et
    let effect_buf = if !layer.effects.is_empty() {
        hcie_fx::apply_layer_effects(&layer.pixels, layer.width, layer.height, &layer.effects)
    } else {
        vec![0u8; (layer.width * layer.height * 4) as usize]
    };

    // 2. Efekt buffer'ını layer pikselleriyle composite et
    //    (her efekt kendi blend_mode ve opacity'siyle)
    // 3. Sonucu normal layer compositing'e sok
}

5c: Efekt render sırası (PSD spec)

1. Inner Shadow
2. Inner Glow
3. Satin
4. Color Overlay
5. Gradient Overlay
6. Pattern Overlay
7. Stroke
8. Outer Shadow (Drop Shadow)
9. Outer Glow
10. Bevel & Emboss

Her efekt kendi piksel buffer'ını üretir, sonra layer ile blend edilir.

Adım 6: GUI Test

gui.rs'de:

  • LayerEntry'ye effects: Vec<hcie_fx::LayerEffect> ekle
  • Properties panelinde efekt listesini göster
  • Her efekt için enabled/disabled toggle
  • Efekt parametrelerini göster (şimdilik read-only)

Workspace Değişiklikleri

Cargo.toml (root)

[workspace]
members = [
    ...
    "hcie-fx",    # yeni
    ...
]

hcie-fx/Cargo.toml

[package]
name = "hcie-fx"
version = "0.1.0"
edition = "2021"

[dependencies]
hcie-blend = { path = "../hcie-blend" }
rayon = "1.10"
serde = { version = "1.0", features = ["derive"] }

[lib]
crate-type = ["staticlib", "rlib"]

hcie-io/Cargo.toml

[dependencies]
hcie-fx = { path = "../hcie-fx" }  # yeni

hcie-composite/Cargo.toml

[dependencies]
hcie-fx = { path = "../hcie-fx" }  # yeni

Uygulama Sırası

  1. hcie-fx crate oluştur — Cargo.toml, lib.rs, types.rs
  2. types.rs yaz — LayerEffect enum, helper tipler
  3. parser.rs yaz — lrFX parser (basit binary), lfx2 parser (descriptor)
  4. Test: parse — Example3-org.psd'deki lfx2/lrFX bloklarını parse et, debug print
  5. shadow.rs yaz — Drop Shadow renderer (en yaygın efekt)
  6. hcie-io entegrasyonu — lfx2/lrFX parsing, Layer.effects
  7. hcie-composite entegrasyonu — efekt render + compositing
  8. GUI test — efekt listesi gösterimi
  9. Diğer renderers — glow, bevel, stroke, overlay, satin (sırayla)

Kritik Bağlamlar

  • hcie-blend::BlendMode zaten 27 mode'u kapsıyor — layer fx için yeterli
  • hcie-blend::blend_pixels() efekt compositing'de kullanılacak
  • hcie-io'daki PsdReader binary parsing için kullanılabilir
  • lfx2 bloğu descriptor-based, lrFX legacy binary — ikisi de parse edilmeli
  • Efekt render'ı rayon ile paralelleştirilebilir (her scanline bağımsız)
  • PSD'de efekt blend modes 4-char key olarak saklanıyor ('Mltp', 'Scrn' vb.)