extern crate printpdf;
use printpdf::*;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::Write;
fn main() {
println!("Testing CSS vertical-align baseline alignment...");
let html = r##"
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: sans-serif;
font-size: 16px;
padding: 20px;
}
h1 {
font-size: 20px;
margin-bottom: 5px;
color: #333;
}
h2 {
font-size: 14px;
margin-top: 30px;
margin-bottom: 10px;
color: #666;
border-bottom: 1px solid #ccc;
}
.test-container {
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
background-color: #f9f9f9;
}
.baseline-demo {
background-color: #e8f4ff;
padding: 5px;
}
/* Inline boxes to simulate images with different alignments */
.inline-box {
display: inline-block;
width: 30px;
height: 20px;
background-color: #4a90d9;
border: 1px solid #2a70b9;
}
.inline-box-tall {
display: inline-block;
width: 20px;
height: 40px;
background-color: #d94a4a;
border: 1px solid #b92a2a;
}
.va-baseline { vertical-align: baseline; }
.va-top { vertical-align: top; }
.va-middle { vertical-align: middle; }
.va-bottom { vertical-align: bottom; }
.va-text-top { vertical-align: text-top; }
.va-text-bottom { vertical-align: text-bottom; }
.va-sub { vertical-align: sub; }
.va-super { vertical-align: super; }
.small-text { font-size: 10px; }
.large-text { font-size: 24px; }
.superscript { font-size: 10px; vertical-align: super; }
.subscript { font-size: 10px; vertical-align: sub; }
.label {
display: inline-block;
width: 80px;
font-size: 11px;
color: #666;
}
.note {
font-size: 11px;
color: #888;
margin-top: 5px;
}
</style>
</head>
<body>
<h1>CSS vertical-align Baseline Alignment Test</h1>
<h2>1. Text Baseline Alignment</h2>
<div class="test-container">
<p class="baseline-demo">
Normal text <span class="small-text">small text</span>
normal <span class="large-text">LARGE</span> normal again
</p>
<p class="note">All text should align on the same baseline regardless of size.</p>
</div>
<h2>2. Subscript and Superscript</h2>
<div class="test-container">
<p class="baseline-demo">
H<span class="subscript">2</span>O is water.
E = mc<span class="superscript">2</span> is famous.
X<span class="subscript">i</span><span class="superscript">j</span> matrix notation.
</p>
<p class="note">Sub/super scripts should be positioned below/above the baseline.</p>
</div>
<h2>3. Inline Boxes with vertical-align</h2>
<div class="test-container">
<p class="baseline-demo">
<span class="label">baseline:</span>
Text <span class="inline-box va-baseline"></span> text
</p>
<p class="baseline-demo">
<span class="label">top:</span>
Text <span class="inline-box va-top"></span> text
</p>
<p class="baseline-demo">
<span class="label">middle:</span>
Text <span class="inline-box va-middle"></span> text
</p>
<p class="baseline-demo">
<span class="label">bottom:</span>
Text <span class="inline-box va-bottom"></span> text
</p>
<p class="note">
Each box should be aligned differently within its line box.
</p>
</div>
<h2>4. Tall Inline Boxes</h2>
<div class="test-container">
<p class="baseline-demo">
<span class="label">baseline:</span>
Hello <span class="inline-box-tall va-baseline"></span> world
</p>
<p class="baseline-demo">
<span class="label">top:</span>
Hello <span class="inline-box-tall va-top"></span> world
</p>
<p class="baseline-demo">
<span class="label">middle:</span>
Hello <span class="inline-box-tall va-middle"></span> world
</p>
<p class="baseline-demo">
<span class="label">bottom:</span>
Hello <span class="inline-box-tall va-bottom"></span> world
</p>
<p class="note">
Tall boxes should expand the line box height when needed.
</p>
</div>
<h2>5. Mixed Content</h2>
<div class="test-container">
<p class="baseline-demo">
Start <span class="large-text">BIG</span>
<span class="inline-box va-middle"></span>
<span class="small-text">tiny</span>
<span class="inline-box-tall va-baseline"></span>
end
</p>
<p class="note">
Mixed sizes and inline boxes should all work together.
</p>
</div>
<h2>6. Implementation Status</h2>
<div class="test-container">
<p><strong>Currently implemented:</strong></p>
<ul>
<li>[x] Global vertical-align on UnifiedConstraints</li>
<li>[x] baseline, top, middle, bottom alignment modes</li>
<li>[x] sub, super for script positioning</li>
</ul>
<p><strong>Known limitations:</strong></p>
<ul>
<li>[!] Per-image vertical-align stored but not used in positioning</li>
<li>[!] text-top, text-bottom fall back to baseline</li>
<li>[!] Length/percentage values not supported</li>
</ul>
</div>
</body>
</html>
"##;
let images = BTreeMap::new();
let fonts = BTreeMap::new();
let mut options = GeneratePdfOptions::default();
options.page_width = Some(210.0); options.page_height = Some(297.0);
let mut warnings = Vec::new();
println!("Parsing HTML and generating PDF...");
let doc = match PdfDocument::from_html(&html, &images, &fonts, &options, &mut warnings) {
Ok(doc) => {
println!("[OK] Successfully generated PDF");
if !warnings.is_empty() {
println!("Warnings ({}):", warnings.len());
for warn in warnings.iter().take(10) {
println!(" - {:?}", warn);
}
if warnings.len() > 10 {
println!(" ... and {} more warnings", warnings.len() - 10);
}
}
doc
}
Err(e) => {
eprintln!("[ERROR] Failed to generate PDF: {}", e);
return;
}
};
let output_path = "baseline_alignment.pdf";
println!("Saving PDF to {}...", output_path);
let save_options = PdfSaveOptions::default();
let mut save_warnings = Vec::new();
let bytes = doc.save(&save_options, &mut save_warnings);
if !save_warnings.is_empty() {
println!("Save warnings:");
for warn in &save_warnings {
println!(" - {:?}", warn);
}
}
match File::create(output_path) {
Ok(mut file) => {
match file.write_all(&bytes) {
Ok(_) => {
println!("[OK] PDF saved successfully!");
println!("");
println!("Open {} to verify baseline alignment visually.", output_path);
println!("");
println!("What to check:");
println!("1. Text of different sizes should share a common baseline");
println!("2. Sub/superscripts should be positioned correctly");
println!("3. Inline boxes should align according to their vertical-align value");
println!("4. The line box should expand to fit tall inline elements");
}
Err(e) => eprintln!("[ERROR] Failed to write PDF: {}", e),
}
}
Err(e) => eprintln!("[ERROR] Failed to create file: {}", e),
}
}