diff --git a/pyWebLayout/style/fonts.py b/pyWebLayout/style/fonts.py index b538eca..d62f797 100644 --- a/pyWebLayout/style/fonts.py +++ b/pyWebLayout/style/fonts.py @@ -2,6 +2,7 @@ from PIL import ImageFont from enum import Enum from typing import Tuple, Union, Optional +import os class FontWeight(Enum): @@ -63,8 +64,17 @@ class Font: # Load the font file or use default self._load_font() + def _get_bundled_font_path(self): + """Get the path to the bundled font""" + # Get the directory containing this module + current_dir = os.path.dirname(os.path.abspath(__file__)) + # Navigate to the assets/fonts directory + assets_dir = os.path.join(os.path.dirname(current_dir), 'assets', 'fonts') + bundled_font_path = os.path.join(assets_dir, 'DejaVuSans.ttf') + return bundled_font_path if os.path.exists(bundled_font_path) else None + def _load_font(self): - """Load the font using PIL's ImageFont with better system fonts""" + """Load the font using PIL's ImageFont with consistent bundled font""" try: if self._font_path: self._font = ImageFont.truetype( @@ -72,8 +82,15 @@ class Font: self._font_size ) else: - # Try to load better system fonts - font_candidates = [ + # Try bundled font first for consistency across environments + bundled_font_path = self._get_bundled_font_path() + + font_candidates = [] + if bundled_font_path: + font_candidates.append(bundled_font_path) + + # Fallback to system fonts if bundled font is not available + font_candidates.extend([ # Linux fonts "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf", "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", @@ -83,7 +100,7 @@ class Font: "C:/Windows/Fonts/calibri.ttf", # Windows # Fallback to default None - ] + ]) self._font = None for font_path in font_candidates: diff --git a/tests/test_multiline_rendering.py b/tests/test_multiline_rendering.py index e096a5c..0de8d58 100644 --- a/tests/test_multiline_rendering.py +++ b/tests/test_multiline_rendering.py @@ -133,7 +133,7 @@ class TestMultilineRendering(unittest.TestCase): def test_three_line_sentence(self): """Test sentence that should wrap to three lines""" sentence = "This is a much longer sentence that contains many more words and should definitely wrap across three lines when rendered with the specified width constraints." - line_width = 180 + line_width = 280 actual_lines, lines, combined_image = self._create_multiline_test( sentence, line_width, 25, font_size=12 @@ -144,16 +144,15 @@ class TestMultilineRendering(unittest.TestCase): combined_image.save(filename) self.test_images.append(filename) - # Assertions - Allow for font variations across environments - # Different fonts can cause different text widths and line wrapping behavior + # Assertions self.assertGreaterEqual(actual_lines, 2, "Should have at least two lines") - self.assertLessEqual(actual_lines, 8, "Should not exceed 8 lines for this sentence (allowing for font variations)") + self.assertLessEqual(actual_lines, 5, "Should not exceed 5 lines for this sentence") self.assertTrue(os.path.exists(filename), "Test image should be created") def test_four_line_sentence(self): """Test sentence that should wrap to four lines""" sentence = "Here we have an even longer sentence with significantly more content that will require four lines to properly display all the text when using the constrained width setting." - line_width = 160 + line_width = 200 actual_lines, lines, combined_image = self._create_multiline_test( sentence, line_width, 25, font_size=12 @@ -164,10 +163,9 @@ class TestMultilineRendering(unittest.TestCase): combined_image.save(filename) self.test_images.append(filename) - # Assertions - Allow for font variations across environments - # Different fonts can cause different text widths and line wrapping behavior + # Assertions self.assertGreaterEqual(actual_lines, 3, "Should have at least three lines") - self.assertLessEqual(actual_lines, 9, "Should not exceed 9 lines for this sentence (allowing for font variations)") + self.assertLessEqual(actual_lines, 6, "Should not exceed 6 lines for this sentence") self.assertTrue(os.path.exists(filename), "Test image should be created") def test_single_line_sentence(self):