Skip to main content

vello_cpu/
text_debug.rs

1// Copyright 2026 the Vello Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Debug helpers for glyph atlas and CPU text resources.
5
6#![allow(dead_code, reason = "only used for debugging purposes")]
7
8#[cfg(feature = "png")]
9use crate::Pixmap;
10#[cfg(feature = "png")]
11use crate::render::Resources;
12use crate::text::GlyphAtlasResources;
13#[cfg(feature = "png")]
14use alloc::format;
15use glifo::GlyphCacheKey;
16use glifo::atlas::GlyphCacheStats;
17
18#[cfg(feature = "png")]
19impl GlyphAtlasResources {
20    /// Save all atlas pages to PNG files with a custom path prefix.
21    ///
22    /// Files are saved as `{path_prefix}_atlas_page_{index}.png`.
23    pub(crate) fn save_atlas_pages_to(&self, path_prefix: &str) {
24        for (i, pixmap) in self.pixmaps.iter().enumerate() {
25            let path = format!("{path_prefix}_atlas_page_{i}.png");
26            let _ = save_pixmap_to_png(pixmap, std::path::Path::new(&path));
27        }
28    }
29
30    /// Save all atlas pages to PNG files for debugging.
31    ///
32    /// Files are saved to `examples/_output/vello_cpu_atlas_page_{index}.png`.
33    pub(crate) fn save_atlas_pages(&self) {
34        for (i, pixmap) in self.pixmaps.iter().enumerate() {
35            let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
36            path.pop(); // up from vello_cpu to sparse_strips
37            path.pop(); // up from sparse_strips to workspace root
38            path.push("examples");
39            path.push("_output");
40            let _ = std::fs::create_dir_all(&path);
41            path.push(format!("vello_cpu_atlas_page_{i}.png"));
42            let _ = save_pixmap_to_png(pixmap, &path);
43        }
44    }
45}
46
47impl GlyphAtlasResources {
48    /// Get detailed statistics about cached glyphs.
49    pub(crate) fn stats(&self) -> GlyphCacheStats {
50        self.glyph_atlas.stats(self.pixmaps.len())
51    }
52
53    /// Log detailed atlas statistics at info level.
54    pub(crate) fn log_atlas_stats(&self) {
55        self.glyph_atlas.log_atlas_stats(self.pixmaps.len());
56    }
57
58    /// Returns all cached glyph keys (for debugging).
59    pub(crate) fn all_keys(&self) -> impl Iterator<Item = &GlyphCacheKey> {
60        self.glyph_atlas.all_keys()
61    }
62
63    /// Log all cached keys grouped by glyph ID at info level.
64    pub(crate) fn log_keys_grouped(&self) {
65        self.glyph_atlas.log_keys_grouped();
66    }
67}
68
69#[cfg(feature = "png")]
70impl Resources {
71    pub(crate) fn save_glyph_atlas_pages(&self) {
72        if let Some(glyph_resources) = &self.glyph_resources {
73            glyph_resources.save_atlas_pages();
74        }
75    }
76
77    pub(crate) fn save_glyph_atlas_pages_to(&self, path_prefix: &str) {
78        if let Some(glyph_resources) = &self.glyph_resources {
79            glyph_resources.save_atlas_pages_to(path_prefix);
80        }
81    }
82}
83
84/// Save a pixmap to a PNG file (diagnostic utility).
85#[cfg(feature = "png")]
86pub(crate) fn save_pixmap_to_png(pixmap: &Pixmap, path: &std::path::Path) -> std::io::Result<()> {
87    use std::fs::File;
88    use std::io::BufWriter;
89
90    if let Some(parent) = path.parent() {
91        std::fs::create_dir_all(parent)?;
92    }
93
94    let file = File::create(path)?;
95    let w = BufWriter::new(file);
96
97    let mut encoder = png::Encoder::new(w, pixmap.width() as u32, pixmap.height() as u32);
98    encoder.set_color(png::ColorType::Rgba);
99    encoder.set_depth(png::BitDepth::Eight);
100
101    let mut writer = encoder.write_header().map_err(std::io::Error::other)?;
102
103    writer
104        .write_image_data(pixmap.data_as_u8_slice())
105        .map_err(std::io::Error::other)?;
106
107    Ok(())
108}