Skip to content

Fix panic in Bitmap::decode on zero-width/height EBDT glyphs - #140

Open
youdie006 wants to merge 1 commit into
dfrg:mainfrom
youdie006:fix/139-bitmap-decode-zero-width-panic
Open

Fix panic in Bitmap::decode on zero-width/height EBDT glyphs#140
youdie006 wants to merge 1 commit into
dfrg:mainfrom
youdie006:fix/139-bitmap-decode-zero-width-panic

Conversation

@youdie006

Copy link
Copy Markdown

Summary

Fixes #139.

Bitmap::decode panics with chunk size must be non-zero on bitmap glyphs whose width (or height) is 0. Such glyphs are valid font data -- blank glyphs in embedded bitmap strikes (EBLC/EBDT) of CJK fonts such as SimSun (simsun.ttc). Any caller using Source::Bitmap(..) / Scaler::scale_bitmap* on such a font hits the panic while rendering ordinary text.

Root cause

For w == 0, the row stride ((w * bits) + 7) / 8 evaluates to 0, and slice::chunks(0) panics by contract. This happens in all three BitmapFormat::Alpha(1|2|4) branches (src/strike.rs). decoded_size() is also 0, so the earlier target.len() < size check does not filter these out. FreeType returns an empty bitmap for these glyphs rather than failing, so native apps render such fonts without issues.

Fix

Guard decode for zero-sized bitmaps and return an empty (successful) decode before reaching the row loop:

if w == 0 || h == 0 {
    return true;
}

Semantics: true (empty decode) vs false (fallback)

The issue suggested two options. This PR returns true (decode succeeds with an empty image), for two reasons:

  1. FreeType returns an empty bitmap, not a failure, for these glyphs.
  2. This crate's own bitmap::resize already does exactly if target_width == 0 || target_height == 0 { return true; } (src/scale/bitmap/mod.rs), treating zero dimensions as a successful empty result -- so decode returning true matches the existing convention.

The alternative is return false, which makes the caller fall back to the next Source (e.g. Outline). Happy to switch to false if you'd prefer blank bitmap glyphs to fall through to outline rendering -- let me know which semantics you want.

Test

Added an in-crate regression test (decode_zero_width_bitmap_does_not_panic) covering Alpha(1|2|4) zero-width bitmaps plus a zero-height case. Verified red/green:

  • Without the fix: panics at src/strike.rs:439: chunk size must be non-zero.
  • With the fix: passes; full cargo test green; cargo fmt --check clean; no new cargo clippy warnings.

This contribution was prepared with AI assistance and reviewed by me before submission.

Bitmap::decode panicked with 'chunk size must be non-zero' on bitmap glyphs
whose width (or height) is 0. Such glyphs are valid font data - blank glyphs in
embedded bitmap strikes (EBLC/EBDT) of CJK fonts such as SimSun. For w==0 the row
stride ((w*bits)+7)/8 evaluates to 0 and slice::chunks(0) panics; decoded_size()
is also 0 so the earlier target.len() < size check does not filter these out.
FreeType returns an empty bitmap for these glyphs rather than failing.

Guard decode for zero-sized bitmaps and return an empty (successful) decode
before the row loop. Returning true matches the crate's own bitmap::resize, which
already treats zero dimensions as a successful empty result, and FreeType's
empty-bitmap behavior.

Fixes dfrg#139
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic in Bitmap::decode on zero-width EBDT glyphs (SimSun): "chunk size must be non-zero"

1 participant