From 039b6fcc5bc8d91ad709512a891ea65d60588124 Mon Sep 17 00:00:00 2001 From: Jens Kraemer Date: Thu, 6 Nov 2025 09:40:45 +0800 Subject: [PATCH] fixes rendering of images with a percentage as width or height Images with style='width: X%' were not being rendered in writeHTMLCell because the percentage was calculated against a reference size of 1 unit instead of the available content width. This resulted in images being ~0.3 units wide (essentially invisible). --- lib/rbpdf.rb | 9 ++++-- test/rbpdf_htmlcell_test.rb | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/lib/rbpdf.rb b/lib/rbpdf.rb index 62d312c3..91c84cd1 100755 --- a/lib/rbpdf.rb +++ b/lib/rbpdf.rb @@ -14805,11 +14805,16 @@ def openHTMLTagHandler(dom, key, cell) end iw = 0 if tag['width'] - iw = getHTMLUnitToUnits(tag['width'], 1, 'px', false) + # Calculate available width for percentage-based widths + available_width = @rtl ? (@x - @l_margin) : (@w - @r_margin - @x) + available_width -= 2 * @c_margin if available_width > 0 + iw = getHTMLUnitToUnits(tag['width'], available_width, 'px', false) end ih = 0 if tag['height'] - ih = getHTMLUnitToUnits(tag['height'], 1, 'px', false) + # Use page height for percentage-based heights + available_height = @h - @t_margin - @b_margin + ih = getHTMLUnitToUnits(tag['height'], available_height, 'px', false) end # store original margin values diff --git a/test/rbpdf_htmlcell_test.rb b/test/rbpdf_htmlcell_test.rb index 39f232ff..3625dc7b 100644 --- a/test/rbpdf_htmlcell_test.rb +++ b/test/rbpdf_htmlcell_test.rb @@ -77,4 +77,68 @@ class RbpdfTest < Test::Unit::TestCase no = pdf.get_num_pages assert_equal 1, no end + + test "write_html_cell with image percentage width" do + # Test that images with percentage-based width styles are actually embedded + pdf = RBPDF.new + pdf.add_page() + + # Test image path - using the logo_example.png from the repo + img_path = File.join(File.dirname(__FILE__), '..', 'logo_example.png') + + # Create PDF with image using percentage width + html_with_percentage = "

Image with percentage width:

" + pdf.write_html_cell(0, 0, '', '', html_with_percentage) + + # Check if the image was embedded + images = pdf.instance_variable_get('@images') + assert_equal 1, images.length, "Expected 1 image to be embedded in cache" + + # More importantly, check that the PDF actually contains image data + # by verifying the PDF size is much larger than an empty PDF + output = pdf.output('', 'S') + + # Create a reference PDF without any image + pdf_no_img = RBPDF.new + pdf_no_img.add_page() + pdf_no_img.write_html_cell(0, 0, '', '', '

Image with percentage width:

') + output_no_img = pdf_no_img.output('', 'S') + + # PDF with image should be significantly larger (image data embedded) + assert output.length > output_no_img.length + 10000, + "Expected PDF with image (#{output.length} bytes) to be much larger than PDF without image (#{output_no_img.length} bytes). Image may not have been embedded." + end + + test "write_html_cell with image percentage width generates output" do + pdf = RBPDF.new + pdf.add_page() + + img_path = File.join(File.dirname(__FILE__), '..', 'logo_example.png') + + # Test both plain and percentage width styles + html = <<-HTML +

Test: Image rendering with percentage width

+

Image without style (should work):

+ +

Image with width=50 attribute (should work):

+ +

Image with style width percentage (should work):

+ +

Image with style width pixels (should work):

+ + HTML + + pdf.write_html_cell(0, 0, '', '', html) + + # Generate PDF output to verify it doesn't crash + output = pdf.output('', 'S') + assert_not_nil output + assert output.length > 0 + + # Optionally write to file for manual inspection + if ENV['OUTPUT'] + File.write('test_image_percentage_width.pdf', output) + puts "Generated test_image_percentage_width.pdf for manual inspection" + end + end end