Files

248 lines
13 KiB
Markdown
Raw Permalink Normal View History

2026-07-09 02:59:53 +03:00
# FFI → Direct Rust Bağımlılığı Geçiş Planı
## Hedef
`hcie-engine-api`'de şu an dinamik `.so` üzerinden yüklenen tüm core rendering crate'lerini doğrudan Rust crate bağımlılığına çevirmek. Sadece AI ve Vision crate'leri FFI'de kalır (AI ajanlarının kod bozmasını engellemek için).
Bu sayede **regression #1** (her composite'te 330MB FFI pixel copy) tamamen ortadan kalkar.
## Kapsam
| Crate | Şu an | Yeni |
|---|---|---|
| `hcie-blend` | FFI `.so` | ✅ Direct Rust (zaten Cargo.toml'da var) |
| `hcie-brush-engine` | FFI `.so` | ✅ Direct Rust (zaten Cargo.toml'da var) |
| `hcie-draw` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| `hcie-filter` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| `hcie-composite` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| `hcie-io` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| `hcie-psd` | FFI `.so` | 🆕 Cargo.toml'a ekle (`package = "psd"`) |
| `hcie-kra` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| `hcie-native` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| `hcie-vector` | FFI `.so` | 🆕 Cargo.toml'a ekle |
| **`hcie-ai`** | FFI `.so` | 🔒 **FFI kalır** |
| **`hcie-vision`** | FFI `.so` | 🔒 **FFI kalır** |
## Adım Adım Değişiklikler
### Adım 1: `hcie-engine-api/Cargo.toml`
**Ekle:**
```toml
hcie-draw = { path = "../hcie-draw" }
hcie-composite = { path = "../hcie-composite" }
hcie-filter = { path = "../hcie-filter" }
hcie-io = { path = "../hcie-io" }
hcie-psd = { path = "../hcie-psd", package = "psd" }
hcie-kra = { path = "../hcie-kra" }
hcie-native = { path = "../hcie-native" }
hcie-vector = { path = "../hcie-vector" }
```
**Kaldır:**
```toml
bincode = "1.3" # artık sadece FFI serileştirme için kullanılıyordu
```
`libloading = "0.8"` kalır (hcie-ai + hcie-vision için hala gerekli).
### Adım 2: `hcie-engine-api/src/dynamic_loader.rs`
Tamamen yeniden yazılır. Sadece AI ve Vision kısımları FFI'de kalır.
**Silinecek:** ~900 satır (10 crate için FFI loader, symbol resolution, C struct tanımları)
**Değişecek wrapper fonksiyonlar** (imzaları aynı kalır, gövdeleri değişir):
| Eski | Yeni gövde |
|---|---|
| `blend_pixels(dst, src, mode, opacity)` | `hcie_blend::blend_pixels(dst, src, mode, opacity)` |
| `blend_buffers(dst, src, mode, opacity)` | `hcie_blend::blend_buffers(dst, src, mode, opacity)` *(yeni pub fn eklenmeli)* |
| `draw_line(layer, x0, y0, x1, y1, color, size, mask)` | `hcie_draw::draw_line(x0, y0, x1, y1, &mut layer.pixels, ...)` |
| `draw_filled_rect(layer, x1, y1, x2, y2, color, mask)` | `hcie_draw::draw_filled_rect(x1, y1, x2, y2, ...)` |
| `draw_filled_ellipse(layer, cx, cy, rx, ry, color, mask)` | `hcie_draw::draw_filled_ellipse(cx, cy, rx, ry, ...)` |
| `flood_fill(layer, x, y, color, tolerance, mask)` | `hcie_draw::flood_fill(x, y, color, tolerance, ...)` |
| `draw_brush_stroke(layer, points, color, tip, ...)` | `hcie_draw::draw_brush_stroke(points, &mut layer.pixels, ...)` |
| `draw_specialized_stroke(pixels, w, h, ...)` | `hcie_brush_engine::draw_specialized_stroke(pixels, w, h, ...)` |
| `apply_filter(id, params, pixels, w, h)` | `hcie_filter::apply_filter(...)` *(Layer wrapper gerekli)* |
| `composite_layers(layers, w, h) → Vec<u8>` | `hcie_composite::composite_layers(...)` *(Layer dönüşümü gerekli)* |
| `composite_layers_region(layers, w, h, x0, y0, x1, y1, out)` | `hcie_composite::composite_layers_region(...)` |
| `tiled::composite_tiled_into(layers, tiles, w, h, x0, y0, x1, y1, out)` | `hcie_composite::tiled::composite_tiled_into(...)` |
| `load_image(path) → Layer` | `hcie_io::load_image(path)` |
| `save_image(layer, path, format)` | `hcie_io::save_image(layer, path, format)` |
| `svg_import::import_svg(data)` | `hcie_io::svg_import::import_svg(data)` |
| `import_psd(path) → Vec<Layer>` | `hcie_psd::import_psd(path)` |
| `export_psd(layers, w, h, composited, path)` | `hcie_psd::export_psd(layers, w, h, composited, path)` |
| `import_kra(path) → Vec<Layer>` | `hcie_kra::import_kra(path)` |
| `export_kra(layers, w, h, composited, path)` | `hcie_kra::export_kra(layers, w, h, composited, path)` |
| `load_native(path) → Vec<Layer>` | `hcie_native::load_native(path)` |
| `save_native(layers, path)` | `hcie_native::save_native(layers, path)` |
| `vector::render_vector_shapes(layer)` | `hcie_vector::render_vector_shapes(layer)` |
| `vector::boolean_shapes(op, a, b)` | `hcie_vector::path_boolean::boolean_shapes(op, a, b)` |
### Adım 3: `hcie-engine-api/src/lib.rs` — Use import güncellemesi
Tüm `dynamic_loader::xxx` çağrılarının olduğu satırlar (toplam 22 çağrı noktası) aynı isimdeki yeni wrapper'lara yönlendirilir. Çağrı imzaları değişmediği için sadece `use` import'ları güncellenir.
**Kritik:** `composite_layers()` ve `tiled::composite_tiled_into()` çağrılmadan önce `&[hcie_protocol::Layer]``Vec<hcie_composite::Layer>` dönüşümü yapılmalıdır. Bu dönüşüm mantığı zaten `dynamic_loader::build_c_desc()`'te mevcut — sadece çıktı tipi `CCompositeLayerDesc` yerine `hcie_composite::Layer` olacak.
**Dönüşüm helper fonksiyonu** (dynamic_loader.rs'ye veya lib.rs'ye eklenir):
```rust
fn protocol_layers_to_composite(layers: &[Layer]) -> Vec<hcie_composite::Layer> {
layers.iter().map(|l| {
let (pixels, w, h) = /* effects_cache check */;
hcie_composite::Layer {
pixels: pixels.to_vec(), // ← TEK COPY BURADA
width: w, height: h,
visible: l.visible, opacity: l.opacity,
blend_mode: l.blend_mode as i32,
clipping_mask: l.clipping_mask,
fill_opacity: l.fill_opacity,
mask_pixels: l.mask_pixels.clone(),
mask_bounds: l.mask_bounds,
mask_default_color: l.mask_default_color,
adjustment: l.adjustment.clone(),
effects: l.effects.clone(),
styles: l.styles.clone(),
}
}).collect()
}
```
**Not:** V3'te bu copy yoktu çünkü referansla çalışıyordu. Burada kaçınılmaz bir copy var (çünkü `hcie_composite::Layer` owned `Vec<u8>` bekler). Ama eskiden FFI'da hem `CCompositeLayerDesc` yapısı kuruluyordu hem de FFI içinde tekrar copy yapılıyordu (2 copy). Şimdi sadece 1 copy kalır.
### Adım 4: Her Crate'te FFI Export Kodlarını Kaldır
Her crate'in `lib.rs`'sinden `#[no_mangle] pub unsafe extern "C" fn` fonksiyonları silinir. crate-type'dan `cdylib` kaldırılır.
**hcie-blend:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`
- `lib.rs`: Sil `blend_pixels_c`, `blend_buffers_c`
- `lib.rs`: **Ekle** `pub fn blend_buffers(dst: &mut [u8], src: &[u8], mode: BlendMode, opacity: f32)` — gövdesi `blend_buffers_c` fonksiyonunun içinden alınır (rayon parallel loop)
**hcie-draw:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`
- `lib.rs`: Sil `draw_line_c`, `draw_filled_rect_c`, `draw_filled_circle_c`, `flood_fill_c`, `draw_brush_stroke_c`
**hcie-filter:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`
- `lib.rs`: Sil `apply_filter_c`, `get_filter_ids_json_c`, `free_filter_list_string_c`
**hcie-composite:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`
- `lib.rs`: Sil `composite_layers_c`, `composite_layers_region_c`, `composite_tiled_c`
- `lib.rs`: `hcie_protocol`'u dev-dependencies'ten regular dependency'e çek (Layer tipini kullanmak için)
**hcie-io:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`, `ffi` feature'ını kaldır
- `lib.rs`: Sil `load_image_c`, `save_image_c`, `import_svg_c`, `free_buffer_c` ve `#[cfg(feature = "ffi")]` blokları
**hcie-psd:**
- `Cargo.toml`: `crate-type``["rlib"]`, `ffi` feature'ını kaldır
- `psd/src/lib.rs` veya `ffi.rs`: Sil `import_psd_c`, `export_psd_c`, `free_buffer_c`
**hcie-kra:**
- `Cargo.toml`: `crate-type``["rlib"]`, `ffi` feature'ını kaldır
- `lib.rs`: Sil `import_kra_c`, `export_kra_c`, `kra_free_buffer_c`
**hcie-native:**
- `Cargo.toml`: `crate-type``["rlib"]`, `ffi` feature'ını kaldır
- `lib.rs`: Sil `load_native_c`, `save_native_c`, `free_buffer_c`
**hcie-brush-engine:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`
- `lib.rs`: Sil `draw_specialized_stroke_c`
**hcie-vector:**
- `Cargo.toml`: `crate-type``["staticlib", "rlib"]`
- `lib.rs`: Sil `render_vector_shapes_c`, `vector_boolean_shapes_c`, `free_buffer_c`
### Adım 5: Build Script Güncellemesi
**`build_and_copy_plugins.sh`:**
- Sadece `hcie-ai` ve `hcie-vision` build adımları kalır (step 12, 13)
- Step 1-11 (hcie-color, hcie-blend, hcie-brush-engine, hcie-draw, hcie-composite, hcie-filter, hcie-io, hcie-vector, psd, hcie-kra, hcie-native) kaldırılır
**`build_brush_engine.sh`:**
- Tamamen silinebilir (hcie-brush-engine .so build'i build_and_copy_plugins.sh step 3 ile aynı)
### Adım 6: Derleme ve Doğrulama
```bash
cargo check --workspace # workspace üyeleri
cd hcie-engine-api && cargo check # engine-api
```
## Risk Değerlendirmesi
| Değişiklik | Risk | Açıklama |
|---|---|---|
| `hcie-blend` → direct | **Düşük** | İmzalar birebir aynı. Sadece `blend_buffers` Rust API'si eklenmeli. |
| `hcie-draw` → direct | **Düşük** | İmzalar birebir aynı (raw pixel buffer). |
| `hcie-brush-engine` → direct | **Düşük** | İmzalar birebir aynı. Zaten bağımlılık var. |
| `hcie-filter` → direct | **Orta** | `hcie_filter::Layer` tipi farklı. Dynamic loader'da `(&mut [u8], u32, u32)``hcie_filter::Layer` wrapper yazılmalı. |
| `hcie-composite` → direct | **Orta-Yüksek** | `hcie_composite::Layer` tipi farklı. `build_c_desc()` mantığı `hcie_composite::Layer`'e uyarlanmalı. 1 adet pixel copy kaçınılmaz (FFI'da 2 copy vardı). |
| `hcie-io` → direct | **Düşük** | İmzalar birebir aynı. Aynı `hcie_protocol::Layer` tipi. |
| `hcie-psd` / `hcie-kra` / `hcie-native` | **Orta** | Rust API imzaları kontrol edilmeli, büyük olasılıkla uyumlu. |
| `hcie-vector` → direct | **Düşük** | `render_vector_shapes(&mut Layer)` aynı. `boolean_shapes` path_boolean modülünde. |
| Build script değişikliği | **Düşük** | Sadece .so build adımları kaldırılır. |
| Plugin arama kodu | **Düşük** | Sadece AI/Vision için kalır. |
## Toplam Değişiklik İstatistiği (Tahmini)
| Dosya | Değişiklik |
|---|---|
| `hcie-engine-api/Cargo.toml` | +9 satır, -1 satır |
| `hcie-engine-api/src/dynamic_loader.rs` | ~900 satır silinir, ~200 satır yeniden yazılır |
| `hcie-engine-api/src/lib.rs` | ~5 satır import değişikliği |
| 10 crate'in `lib.rs`'si | ~30-80 satır FFI export silinir/her crate |
| 10 crate'in `Cargo.toml`'u | crate-type ve feature değişikliği |
| `build_and_copy_plugins.sh` | ~80 satır silinir (~110 → ~30) |
| `build_brush_engine.sh` | silinir (~30 satır) |
**Toplam:** ~300 satır eklenir, ~1300 satır silinir, ~100 satır değişir.
---
## Ek: Workspace + Git Hooks + Lock Güncellemesi
FFI→direct dönüşümüne **paralel** olarak yapıldı:
### Kök Workspace (Cargo.toml)
- `/mnt/extra/00_PROJECTS/hcie-rust-v4/Cargo.toml` — tüm 31 crate member olarak listelendi
- Eski workspace'ler (`hcie-egui-app/Cargo.toml`, `hcie-core-app/Cargo.toml`) → regular package'a çevrildi
- Tüm workspace dependency'leri (egui 0.34, serde, rayon, image vs.) root'tan yönetilir
- V3'teki `LOCKED_PERF_PROFILES` bloğu korundu
### Versiyon Çakışmaları Çözüldü
| Çakışma | Çözüm |
|---|---|
| egui 0.27/0.28/0.29/0.34 | Tümü 0.34'e çekildi (7 crate'te dev-dep güncellendi) |
| eframe 0.27/0.28/0.29/0.34 | Tümü 0.34'e çekildi |
| fontdue 0.7/0.9 | hcie-text 0.9'a çekildi |
| rfd 0.14/0.15 | hcie-io dev-dep 0.15'e çekildi |
### Git Hook Sistemi
V3'teki semantic etki analizi sistemi `.githooks/` dizinine kuruldu:
| Dosya | Açıklama |
|---|---|
| `.githooks/pre-commit` | Staged değişiklikleri `project_manifest.json` ile karşılaştırır. HIGH blast radius varsa `cargo test` zorunlu kılar, başarısızsa commit'i engeller. |
| `.githooks/post-commit` | Commit sonrası `generate_semantic_report.py` ile 3 katmanlı rapor üretir (Layer 1: bağımlılık grafiği, Layer 2: API diff, Layer 3: semver opsiyonel). |
| `.githooks/semantic_analyzer.py` | Pre-commit analiz motoru |
| `.githooks/generate_semantic_report.py` | 3 katmanlı raportör (1075 satır, V3'ten port edildi) |
| `.githooks/semantic_check.sh` | CLI wrapper (precommit/audit/full/quick/json) |
| `project_manifest.json` | 105 dosya entry'si, 23 crate, V3'ten uyarlanmış path'ler |
**Kurulum:**
```bash
git config core.hooksPath .githooks
```
### .gitignore
- Kök `.gitignore``/target/` ile tüm crate'ler tek target paylaşır
- Eski `hcie-egui-app/.gitignore` artık geçerli değil (workspace root'taki geçerli)
### lock.sh / unlock.sh
- Liste güncellendi: `hcie-pixel-bridge` unlock'ta gereksizdi → kaldırıldı
- FFI→direct sonrası `.so` build gerektirmeyen crate'ler de lock listesinde kalır (kaynak kodu AI ajanlarından korumak için)