V1.0: Class 1 fax — real-world 4-page send to external number confirmed
Core features: - Class 1 T.30 protocol: full send/receive implementation - HDLC: DLE-stuffing, FCS strip, USR5637 bit-reversal handling - T.4 MH encoder/decoder (1728px A4 standard) - Document pipeline: PDF (Ghostscript), PNG, TIFF input - Width clamping: US Letter 1734px → 1728px fax standard - Cover page: CJK rasterization (TW/CN/JP/EN), TIFF + HTML output - OCR verification: Tesseract 5 with eng+chi_tra, CJK space-tolerant - API server (axum): health, send, jobs, cover, retry, cancel - Background worker: auto-poll queue, speed fallback, retry policy - Modem detection, pool management Real-world test results (2026-07-23): - V90 → 25153038: 4 pages, V.17 12000 bps, 2:33 ✅ - USR5637 → 25153038: 4 pages, V.17 12000 bps, 2:26 ✅ - Both faxes confirmed received on remote machine Tested: loopback (100% pixel match), multi-page, all input formats, cover pages, OCR verify, API endpoints, worker processing. 13 unit tests pass, 0 new clippy warnings.
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
# Multi-Language Cover Page Generator
|
||||
|
||||
## Supported Languages
|
||||
|
||||
- **English** - FACSIMILE
|
||||
- **Chinese** - 傳真
|
||||
- **Japanese** - FAX (表紙)
|
||||
- **Korean** - 팩스
|
||||
- **German** - FAX
|
||||
- **French** - FAX
|
||||
- **Spanish** - FAX
|
||||
- **Custom** - User-defined language
|
||||
|
||||
## Supported Image Formats
|
||||
|
||||
- **PNG** - Portable Network Graphics
|
||||
- **JPEG** - Joint Photographic Experts Group
|
||||
- **TIFF** - Tagged Image File Format
|
||||
- **BMP** - Bitmap
|
||||
- **GIF** - Graphics Interchange Format
|
||||
- **WebP** - WebP Image Format
|
||||
|
||||
## Features
|
||||
|
||||
### Language Support
|
||||
- Automatic font fallback for each language
|
||||
- Language-specific labels and formatting
|
||||
- Support for right-to-left languages (future)
|
||||
|
||||
### Image Support
|
||||
- Logo placement (header, corner, center)
|
||||
- Background images with opacity control
|
||||
- Watermark support
|
||||
- Footer images
|
||||
|
||||
### Layout Options
|
||||
- **Standard** - Classic fax cover page
|
||||
- **Modern** - Clean, minimalist design
|
||||
- **Classic** - Traditional business style
|
||||
- **Minimal** - Simple, text-focused
|
||||
- **Corporate** - Professional with branding
|
||||
- **Custom** - User-defined layout
|
||||
|
||||
### Format Options
|
||||
- **A4** - 210mm x 297mm
|
||||
- **Letter** - 8.5" x 11"
|
||||
- **Legal** - 8.5" x 14"
|
||||
- **Custom** - User-defined dimensions
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Chinese Cover Page with Logo
|
||||
|
||||
```rust
|
||||
use telfax::document::{CoverPageConfig, Language, ImageSource};
|
||||
|
||||
let config = CoverPageConfig::new(Language::Chinese)
|
||||
.with_logo("logo.png")
|
||||
.with_content(CoverContent {
|
||||
title: Some("公司傳真".to_string()),
|
||||
from: Some(FromInfo {
|
||||
name: "張三".to_string(),
|
||||
company: Some("測試公司".to_string()),
|
||||
department: Some("業務部".to_string()),
|
||||
phone: Some("02-12345678".to_string()),
|
||||
fax: Some("02-87654321".to_string()),
|
||||
email: Some("zhang@company.com".to_string()),
|
||||
}),
|
||||
to: Some(ToInfo {
|
||||
name: "李四".to_string(),
|
||||
company: Some("收件公司".to_string()),
|
||||
department: Some("採購部".to_string()),
|
||||
fax: "02-11112222".to_string(),
|
||||
}),
|
||||
subject: Some("業務合作提案".to_string()),
|
||||
message: Some("請參閱附件內容".to_string()),
|
||||
pages: Some(5),
|
||||
urgency: Some(Urgency::Urgent),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let cover_page = generate_cover_page_advanced(&config)?;
|
||||
```
|
||||
|
||||
### Example 2: Japanese Cover Page with Background
|
||||
|
||||
```rust
|
||||
let config = CoverPageConfig::new(Language::Japanese)
|
||||
.with_background("background.jpg")
|
||||
.with_content(CoverContent {
|
||||
title: Some("FAX送付書".to_string()),
|
||||
from: Some(FromInfo {
|
||||
name: "田中太郎".to_string(),
|
||||
company: Some("テスト株式会社".to_string()),
|
||||
fax: Some("03-1234-5678".to_string()),
|
||||
..Default::default()
|
||||
}),
|
||||
to: Some(ToInfo {
|
||||
name: "山田花子".to_string(),
|
||||
fax: "03-9876-5432".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
subject: Some("契約書の件".to_string()),
|
||||
urgency: Some(Urgency::VeryUrgent),
|
||||
..Default::default()
|
||||
});
|
||||
```
|
||||
|
||||
### Example 3: English Cover Page with Watermark
|
||||
|
||||
```rust
|
||||
let config = CoverPageConfig::new(Language::English)
|
||||
.with_logo("company_logo.png")
|
||||
.with_watermark(ImageSource::new("watermark.png")
|
||||
.with_position(50.0, 50.0)
|
||||
.with_opacity(0.1))
|
||||
.with_content(CoverContent {
|
||||
title: Some("FAX COVER SHEET".to_string()),
|
||||
from: Some(FromInfo {
|
||||
name: "John Smith".to_string(),
|
||||
company: Some("ACME Corporation".to_string()),
|
||||
email: Some("john.smith@acme.com".to_string()),
|
||||
..Default::default()
|
||||
}),
|
||||
to: Some(ToInfo {
|
||||
name: "Jane Doe".to_string(),
|
||||
company: Some("XYZ Inc.".to_string()),
|
||||
fax: "+1-555-123-4567".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
subject: Some("Project Proposal".to_string()),
|
||||
message: Some("Please review the attached proposal.".to_string()),
|
||||
pages: Some(10),
|
||||
reference_number: Some("REF-2024-001".to_string()),
|
||||
urgency: Some(Urgency::ForYourInformation),
|
||||
..Default::default()
|
||||
});
|
||||
```
|
||||
|
||||
### Example 4: Multi-Language Cover with All Features
|
||||
|
||||
```rust
|
||||
use telfax::document::{
|
||||
CoverPageConfig, Language, CoverFormat, CoverLayout,
|
||||
ImageSource, ImageSize, Position
|
||||
};
|
||||
|
||||
let config = CoverPageConfig::new(Language::German)
|
||||
.with_logo(ImageSource::new("logo.png")
|
||||
.with_position(5.0, 5.0) // Top-left corner
|
||||
.with_size(200, 80)
|
||||
.with_opacity(0.9))
|
||||
.with_background(ImageSource::new("background.jpg")
|
||||
.with_opacity(0.15))
|
||||
.with_watermark(ImageSource::new("watermark.png")
|
||||
.with_position(50.0, 50.0) // Center
|
||||
.with_opacity(0.08))
|
||||
.with_content(CoverContent {
|
||||
title: Some("FAX-DECKBLATT".to_string()),
|
||||
from: Some(FromInfo {
|
||||
name: "Hans Müller".to_string(),
|
||||
company: Some("Muster GmbH".to_string()),
|
||||
department: Some("Vertrieb".to_string()),
|
||||
phone: Some("+49 30 123456".to_string()),
|
||||
fax: Some("+49 30 123457".to_string()),
|
||||
email: Some("hans.mueller@muster.de".to_string()),
|
||||
}),
|
||||
to: Some(ToInfo {
|
||||
name: "Frau Schmidt".to_string(),
|
||||
company: Some("Beispiel AG".to_string()),
|
||||
fax: "+49 89 987654".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
subject: Some("Angebot Nr. 2024-123".to_string()),
|
||||
message: Some("Sehr geehrte Frau Schmidt,\n\nanbei erhalten Sie unser Angebot.".to_string()),
|
||||
pages: Some(3),
|
||||
reference_number: Some("AN-2024-123".to_string()),
|
||||
date: Some("2024-01-15".to_string()),
|
||||
urgency: Some(Urgency::PleaseReply),
|
||||
..Default::default()
|
||||
});
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Generate Cover Page (Legacy)
|
||||
|
||||
```bash
|
||||
POST /api/v1/fax/cover
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"to": "John Smith",
|
||||
"from": "Jane Doe",
|
||||
"subject": "Meeting Notes",
|
||||
"notes": "Please review before the meeting.",
|
||||
"total_pages": 5
|
||||
}
|
||||
```
|
||||
|
||||
### Generate Multi-Language Cover Page
|
||||
|
||||
```bash
|
||||
POST /api/v1/fax/cover/advanced
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"language": "chinese",
|
||||
"format": "a4",
|
||||
"layout": "standard",
|
||||
"fonts": {
|
||||
"title": 72,
|
||||
"heading": 44,
|
||||
"body": 44,
|
||||
"small": 36
|
||||
},
|
||||
"images": {
|
||||
"logo": {
|
||||
"path": "/path/to/logo.png",
|
||||
"position": {"x": 5, "y": 5},
|
||||
"size": {"width": 200, "height": 80},
|
||||
"opacity": 0.9
|
||||
},
|
||||
"background": {
|
||||
"path": "/path/to/background.jpg",
|
||||
"opacity": 0.15
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"title": "公司傳真",
|
||||
"from": {
|
||||
"name": "張三",
|
||||
"company": "測試公司",
|
||||
"department": "業務部",
|
||||
"phone": "02-12345678",
|
||||
"fax": "02-87654321"
|
||||
},
|
||||
"to": {
|
||||
"name": "李四",
|
||||
"company": "收件公司",
|
||||
"fax": "02-11112222"
|
||||
},
|
||||
"subject": "業務合作提案",
|
||||
"message": "請參閱附件內容",
|
||||
"pages": 5,
|
||||
"urgency": "urgent"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Font Requirements
|
||||
|
||||
### English/Western Languages
|
||||
- Helvetica
|
||||
- Arial
|
||||
|
||||
### Chinese
|
||||
- PingFang TC (Traditional Chinese)
|
||||
- STHeiti Medium
|
||||
- Arial Unicode (fallback)
|
||||
|
||||
### Japanese
|
||||
- Hiragino Sans
|
||||
- Yu Gothic
|
||||
- Meiryo
|
||||
- Arial Unicode (fallback)
|
||||
|
||||
### Korean
|
||||
- Apple SD Gothic Neo
|
||||
- Malgun Gothic
|
||||
- Arial Unicode (fallback)
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
telfax/
|
||||
├── scripts/
|
||||
│ └── cover_multilang.py # Multi-language cover page generator
|
||||
├── src/
|
||||
│ └── document/
|
||||
│ ├── cover.rs # Rust wrapper functions
|
||||
│ └── cover_config.rs # Configuration types
|
||||
└── docs/
|
||||
└── MULTILANG_COVER.md # This documentation
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Test Chinese cover page
|
||||
curl -X POST http://localhost:3000/api/v1/fax/cover/advanced \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @examples/chinese_cover.json
|
||||
|
||||
# Test Japanese cover page
|
||||
curl -X POST http://localhost:3000/api/v1/fax/cover/advanced \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @examples/japanese_cover.json
|
||||
|
||||
# Test with images
|
||||
curl -X POST http://localhost:3000/api/v1/fax/cover/advanced \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @examples/cover_with_logo.json
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
- **Cover Generation Time**: ~200-500ms (depends on image complexity)
|
||||
- **Supported Resolutions**: 204x196 dpi (standard fax), 300 dpi, 600 dpi
|
||||
- **File Formats**: Output as TIFF (fax-ready)
|
||||
- **Font Rendering**: High-quality anti-aliased text
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- [ ] Right-to-left language support (Arabic, Hebrew)
|
||||
- [ ] Custom font file upload
|
||||
- [ ] Template system
|
||||
- [ ] QR code generation
|
||||
- [ ] Digital signature support
|
||||
- [ ] PDF output option
|
||||
Reference in New Issue
Block a user