dynimg 0.1.10__tar.gz → 0.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dynimg-0.1.10 → dynimg-0.1.11}/Cargo.lock +1 -1
- {dynimg-0.1.10 → dynimg-0.1.11}/Cargo.toml +1 -1
- {dynimg-0.1.10 → dynimg-0.1.11}/PKG-INFO +1 -1
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/google-fonts.html +1 -1
- {dynimg-0.1.10 → dynimg-0.1.11}/pyproject.toml +1 -1
- {dynimg-0.1.10 → dynimg-0.1.11}/scripts/render-examples.sh +2 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/src/lib.rs +26 -15
- {dynimg-0.1.10 → dynimg-0.1.11}/.claude/settings.local.json +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/.github/workflows/build-wheels.yml +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/.github/workflows/ci.yml +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/.github/workflows/release.yml +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/.gitignore +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/.pearls/CLAUDE.md +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/.pearls/issues.jsonl +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/CLAUDE.md +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/LICENSE +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/Makefile +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/README.md +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/codebook.toml +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/assets/PlaywriteINGuides-Regular.ttf +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/assets/RobotoMono-Bold.ttf +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/assets/RobotoMono-Bold.woff2 +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/assets/logo.svg +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/assets/servo.css +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/assets/style.css +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/inline-only.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/local-assets.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/local-font-woff2.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/local-font.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/mixed-assets.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/og-image.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/quote.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/remote-image.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/servo.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/examples/social-card.html +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/python/dynimg/__init__.py +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/python/dynimg/__init__.pyi +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/python/dynimg/py.typed +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/src/main.rs +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/src/python.rs +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/test_wheels/.gitignore +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/test_wheels/README.md +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/test_wheels/debug_parser.py +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/test_wheels/debug_verbose.py +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/test_wheels/test_dynimg.py +0 -0
- {dynimg-0.1.10 → dynimg-0.1.11}/test_wheels/test_from_ci.sh +0 -0
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<h1>Google Fonts Example</h1>
|
|
63
63
|
<p>
|
|
64
64
|
This example attempts to use
|
|
65
|
-
<span class="highlight">
|
|
65
|
+
<span class="highlight">Playwrite IN Guides</span> and
|
|
66
66
|
<span class="highlight">Inter</span> from Google Fonts.
|
|
67
67
|
</p>
|
|
68
68
|
<div class="note">
|
|
@@ -71,6 +71,7 @@ echo ""
|
|
|
71
71
|
echo "--- Mixed Assets (requires both flags) ---"
|
|
72
72
|
run_test "Without flags" false "$DYNIMG" "$EXAMPLES_DIR/mixed-assets.html" -o "$OUTPUT_DIR/mixed-no-flags.png"
|
|
73
73
|
run_test "With --allow-net only" false "$DYNIMG" "$EXAMPLES_DIR/mixed-assets.html" -o "$OUTPUT_DIR/mixed-net-only.png" --allow-net
|
|
74
|
+
run_test "With --allow-net only" false "$DYNIMG" "$EXAMPLES_DIR/mixed-assets.html" -o "$OUTPUT_DIR/mixed-net-only.webp" --allow-net
|
|
74
75
|
run_test "With --assets only" false "$DYNIMG" "$EXAMPLES_DIR/mixed-assets.html" -o "$OUTPUT_DIR/mixed-assets-only.png" --assets "$ASSETS_DIR"
|
|
75
76
|
run_test "With both flags" false "$DYNIMG" "$EXAMPLES_DIR/mixed-assets.html" -o "$OUTPUT_DIR/mixed-both-flags.png" --allow-net --assets "$ASSETS_DIR"
|
|
76
77
|
run_test "With both flags" false "$DYNIMG" "$EXAMPLES_DIR/google-fonts.html" -o "$OUTPUT_DIR/google-fonts.png" --allow-net --assets "$ASSETS_DIR"
|
|
@@ -78,6 +79,7 @@ run_test "With both flags" false "$DYNIMG" "$EXAMPLES_DIR/google-fonts.html" -o
|
|
|
78
79
|
echo ""
|
|
79
80
|
echo "--- OG Image Templates ---"
|
|
80
81
|
run_test "og-image.html" false "$DYNIMG" "$EXAMPLES_DIR/og-image.html" -o "$OUTPUT_DIR/og-image.png"
|
|
82
|
+
run_test "og-image.html" false "$DYNIMG" "$EXAMPLES_DIR/og-image.html" -o "$OUTPUT_DIR/og-image.webp"
|
|
81
83
|
run_test "social-card.html" false "$DYNIMG" "$EXAMPLES_DIR/social-card.html" -o "$OUTPUT_DIR/social-card.png"
|
|
82
84
|
run_test "quote.html" false "$DYNIMG" "$EXAMPLES_DIR/quote.html" -o "$OUTPUT_DIR/quote.png"
|
|
83
85
|
|
|
@@ -451,18 +451,22 @@ async fn render_document(
|
|
|
451
451
|
) -> Result<RenderedImage, Error> {
|
|
452
452
|
// Resolve resource requests
|
|
453
453
|
if let Some(p) = provider {
|
|
454
|
-
|
|
454
|
+
// Wait for all network requests including cascading requests.
|
|
455
|
+
// CSS stylesheets may trigger font fetches when processed, so we need
|
|
456
|
+
// multiple consecutive "empty" checks to ensure all cascading requests complete.
|
|
457
|
+
// Using 5 cycles provides safety margin for complex pages with many resources.
|
|
458
|
+
let mut consecutive_empty = 0u32;
|
|
459
|
+
const REQUIRED_EMPTY_CYCLES: u32 = 5;
|
|
460
|
+
|
|
461
|
+
while consecutive_empty < REQUIRED_EMPTY_CYCLES {
|
|
455
462
|
document.resolve(0.0);
|
|
456
|
-
if p.is_empty() {
|
|
457
|
-
break;
|
|
458
|
-
}
|
|
459
463
|
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
|
|
460
|
-
}
|
|
461
464
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
465
|
+
if p.is_empty() {
|
|
466
|
+
consecutive_empty += 1;
|
|
467
|
+
} else {
|
|
468
|
+
consecutive_empty = 0;
|
|
469
|
+
}
|
|
466
470
|
}
|
|
467
471
|
}
|
|
468
472
|
|
|
@@ -521,11 +525,13 @@ fn write_png(path: &Path, buffer: &[u8], width: u32, height: u32) -> Result<(),
|
|
|
521
525
|
fn encode_png(buffer: &[u8], width: u32, height: u32) -> Result<Vec<u8>, Error> {
|
|
522
526
|
const PPM: u32 = (144.0 * 39.3701) as u32;
|
|
523
527
|
|
|
524
|
-
|
|
528
|
+
// Pre-allocate output (PNG is typically 10-50% of raw size after compression)
|
|
529
|
+
let mut output = Vec::with_capacity(buffer.len() / 4);
|
|
525
530
|
{
|
|
526
531
|
let mut encoder = png::Encoder::new(&mut output, width, height);
|
|
527
532
|
encoder.set_color(png::ColorType::Rgba);
|
|
528
533
|
encoder.set_depth(png::BitDepth::Eight);
|
|
534
|
+
encoder.set_compression(png::Compression::Fast);
|
|
529
535
|
encoder.set_pixel_dims(Some(png::PixelDimensions {
|
|
530
536
|
xppu: PPM,
|
|
531
537
|
yppu: PPM,
|
|
@@ -552,14 +558,19 @@ fn write_jpeg(
|
|
|
552
558
|
}
|
|
553
559
|
|
|
554
560
|
fn encode_jpeg(buffer: &[u8], width: u32, height: u32, quality: u8) -> Result<Vec<u8>, Error> {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
561
|
+
// Pre-allocate RGB buffer (3 bytes per pixel instead of 4)
|
|
562
|
+
let pixel_count = (width * height) as usize;
|
|
563
|
+
let mut rgb_buffer = Vec::with_capacity(pixel_count * 3);
|
|
564
|
+
|
|
565
|
+
// Convert RGBA to RGB in-place
|
|
566
|
+
for chunk in buffer.chunks_exact(4) {
|
|
567
|
+
rgb_buffer.extend_from_slice(&chunk[..3]);
|
|
568
|
+
}
|
|
559
569
|
|
|
560
570
|
let img = image::RgbImage::from_raw(width, height, rgb_buffer).ok_or(Error::InvalidBuffer)?;
|
|
561
571
|
|
|
562
|
-
|
|
572
|
+
// Pre-allocate output (estimate ~10% of raw size for compressed JPEG)
|
|
573
|
+
let mut output = Vec::with_capacity(pixel_count / 10);
|
|
563
574
|
let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, quality);
|
|
564
575
|
encoder.encode_image(&img)?;
|
|
565
576
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|