mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
change how font is loaded via systemctl - added direct paths
This commit is contained in:
@@ -46,35 +46,11 @@ class CacheManager:
|
||||
self.logger.warning("ConfigManager not available, using default cache intervals")
|
||||
|
||||
def _get_writable_cache_dir(self) -> Optional[str]:
|
||||
"""Tries to find or create a writable cache directory in a few common locations."""
|
||||
# Attempt 1: User's home directory (handling sudo)
|
||||
"""Tries to find or create a writable cache directory, preferring a system path when available."""
|
||||
# Attempt 1: System-wide persistent cache directory (preferred for services)
|
||||
try:
|
||||
real_user = os.environ.get('SUDO_USER') or os.environ.get('USER', 'default')
|
||||
if real_user and real_user != 'root':
|
||||
home_dir = os.path.expanduser(f"~{real_user}")
|
||||
else:
|
||||
home_dir = os.path.expanduser('~')
|
||||
|
||||
user_cache_dir = os.path.join(home_dir, '.ledmatrix_cache')
|
||||
os.makedirs(user_cache_dir, exist_ok=True)
|
||||
|
||||
# Test writability
|
||||
test_file = os.path.join(user_cache_dir, '.writetest')
|
||||
with open(test_file, 'w') as f:
|
||||
f.write('test')
|
||||
os.remove(test_file)
|
||||
return user_cache_dir
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Could not use user-specific cache directory: {e}")
|
||||
|
||||
# Attempt 2: System-wide persistent cache directory (for sudo scenarios)
|
||||
try:
|
||||
# Try /var/cache/ledmatrix first (most standard)
|
||||
system_cache_dir = '/var/cache/ledmatrix'
|
||||
|
||||
# Check if directory exists and we can write to it
|
||||
if os.path.exists(system_cache_dir):
|
||||
# Test if we can write to the existing directory
|
||||
test_file = os.path.join(system_cache_dir, '.writetest')
|
||||
try:
|
||||
with open(test_file, 'w') as f:
|
||||
@@ -84,13 +60,30 @@ class CacheManager:
|
||||
except (IOError, OSError):
|
||||
self.logger.warning(f"Directory exists but is not writable: {system_cache_dir}")
|
||||
else:
|
||||
# Try to create the directory
|
||||
os.makedirs(system_cache_dir, exist_ok=True)
|
||||
if os.access(system_cache_dir, os.W_OK):
|
||||
return system_cache_dir
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Could not use /var/cache/ledmatrix: {e}")
|
||||
|
||||
# Attempt 2: User's home directory (handling sudo), but avoid /root preference
|
||||
try:
|
||||
real_user = os.environ.get('SUDO_USER') or os.environ.get('USER', 'default')
|
||||
if real_user and real_user != 'root':
|
||||
home_dir = os.path.expanduser(f"~{real_user}")
|
||||
else:
|
||||
# When running as root and /var/cache/ledmatrix failed, still allow fallback to /root
|
||||
home_dir = os.path.expanduser('~')
|
||||
user_cache_dir = os.path.join(home_dir, '.ledmatrix_cache')
|
||||
os.makedirs(user_cache_dir, exist_ok=True)
|
||||
test_file = os.path.join(user_cache_dir, '.writetest')
|
||||
with open(test_file, 'w') as f:
|
||||
f.write('test')
|
||||
os.remove(test_file)
|
||||
return user_cache_dir
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Could not use user-specific cache directory: {e}")
|
||||
|
||||
# Attempt 3: /opt/ledmatrix/cache (alternative persistent location)
|
||||
try:
|
||||
opt_cache_dir = '/opt/ledmatrix/cache'
|
||||
@@ -240,6 +233,16 @@ class CacheManager:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.logger.error(f"Atomic write failed for key '{key}': {e}")
|
||||
# Attempt one-time fallback write directly into /var/cache/ledmatrix if available
|
||||
try:
|
||||
fallback_dir = '/var/cache/ledmatrix'
|
||||
if os.path.isdir(fallback_dir) and os.access(fallback_dir, os.W_OK):
|
||||
fallback_path = os.path.join(fallback_dir, os.path.basename(cache_path))
|
||||
with open(fallback_path, 'w') as tmp_file:
|
||||
json.dump(data, tmp_file, indent=4, cls=DateTimeEncoder)
|
||||
self.logger.warning(f"Cache wrote to fallback location: {fallback_path}")
|
||||
except Exception as e2:
|
||||
self.logger.error(f"Fallback cache write also failed: {e2}")
|
||||
|
||||
except (IOError, OSError) as e:
|
||||
self.logger.error(f"Failed to save cache for key '{key}': {e}")
|
||||
|
||||
@@ -98,9 +98,11 @@ class DisplayManager:
|
||||
self.draw = ImageDraw.Draw(self.image)
|
||||
logger.info(f"Image canvas created with dimensions: {self.matrix.width}x{self.matrix.height}")
|
||||
|
||||
# Initialize font with Press Start 2P
|
||||
# Initialize font with Press Start 2P using an absolute path so services don't fall back
|
||||
try:
|
||||
self.font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p_path = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
self.font = ImageFont.truetype(ps2p_path, 8)
|
||||
logger.info("Initial Press Start 2P font loaded successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to load initial font: {e}")
|
||||
@@ -290,12 +292,14 @@ class DisplayManager:
|
||||
def _load_fonts(self):
|
||||
"""Load fonts with proper error handling."""
|
||||
try:
|
||||
# Load Press Start 2P font
|
||||
self.regular_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
# Load Press Start 2P font using absolute path to avoid fallback when run under systemd
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p_path = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
self.regular_font = ImageFont.truetype(ps2p_path, 8)
|
||||
logger.info("Press Start 2P font loaded successfully")
|
||||
|
||||
# Use the same font for small text, just at a smaller size
|
||||
self.small_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
# Use the same font for small text (currently same size; adjust size here if needed)
|
||||
self.small_font = ImageFont.truetype(ps2p_path, 8)
|
||||
logger.info("Press Start 2P small font loaded successfully")
|
||||
|
||||
# Load 5x7 BDF font for calendar events
|
||||
|
||||
@@ -336,8 +336,10 @@ class BaseMiLBManager:
|
||||
date_font = getattr(self.display_manager, 'small_font', None)
|
||||
time_font = getattr(self.display_manager, 'small_font', None)
|
||||
if date_font is None or time_font is None:
|
||||
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
time_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
date_font = ImageFont.truetype(ps2p, 8)
|
||||
time_font = ImageFont.truetype(ps2p, 8)
|
||||
self.logger.debug(f"[MiLB] Fonts prepared successfully")
|
||||
except Exception as e:
|
||||
self.logger.error(f"[MiLB] Failed to prepare fonts: {e}")
|
||||
@@ -403,7 +405,9 @@ class BaseMiLBManager:
|
||||
away_score = str(game_data['away_score'])
|
||||
home_score = str(game_data['home_score'])
|
||||
score_text = f"{away_score}-{home_score}"
|
||||
score_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
score_font = ImageFont.truetype(ps2p, 12)
|
||||
|
||||
# Calculate position for the score text
|
||||
score_width = draw.textlength(score_text, font=score_font)
|
||||
@@ -415,7 +419,10 @@ class BaseMiLBManager:
|
||||
# Draw records for upcoming and recent games
|
||||
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
|
||||
try:
|
||||
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
||||
# Resolve 4x6 font via absolute path
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
record_font = ImageFont.truetype(font_4x6, 6)
|
||||
except IOError:
|
||||
record_font = ImageFont.load_default()
|
||||
|
||||
|
||||
@@ -264,8 +264,10 @@ class BaseMLBManager:
|
||||
game_time_str = self._format_game_time(game_data['start_time'])
|
||||
|
||||
# Draw date and time using NHL-style fonts
|
||||
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
time_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
date_font = ImageFont.truetype(ps2p, 8)
|
||||
time_font = ImageFont.truetype(ps2p, 8)
|
||||
|
||||
# Draw date in center
|
||||
date_width = draw.textlength(game_date, font=date_font)
|
||||
@@ -302,7 +304,7 @@ class BaseMLBManager:
|
||||
away_score = str(game_data['away_score'])
|
||||
home_score = str(game_data['home_score'])
|
||||
display_text = f"{away_score}-{home_score}"
|
||||
font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
||||
font = ImageFont.truetype(ps2p, 12)
|
||||
display_width = draw.textlength(display_text, font=font)
|
||||
display_x = (width - display_width) // 2
|
||||
display_y = (height - font.size) // 2
|
||||
@@ -330,7 +332,7 @@ class BaseMLBManager:
|
||||
away_score = str(game_data['away_score'])
|
||||
home_score = str(game_data['home_score'])
|
||||
score_text = f"{away_score}-{home_score}"
|
||||
score_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
||||
score_font = ImageFont.truetype(ps2p, 12)
|
||||
|
||||
# Calculate position for the score text
|
||||
score_width = draw.textlength(score_text, font=score_font)
|
||||
|
||||
@@ -193,11 +193,14 @@ class BaseNBAManager:
|
||||
"""Load fonts used by the scoreboard."""
|
||||
fonts = {}
|
||||
try:
|
||||
# Try to load the Press Start 2P font first
|
||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
||||
# Try to load the Press Start 2P font first using absolute paths
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['status'] = ImageFont.truetype(font_4x6, 6)
|
||||
logging.info("[NBA] Successfully loaded Press Start 2P font for all text elements")
|
||||
except IOError:
|
||||
logging.warning("[NBA] Press Start 2P font not found, trying 4x6 font.")
|
||||
|
||||
@@ -240,7 +240,9 @@ class BaseNCAABaseballManager:
|
||||
status_x = (width - status_width) // 2
|
||||
status_y = 2
|
||||
self.display_manager.draw = draw
|
||||
status_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using a default small font
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
status_font = ImageFont.truetype(font_4x6, 6) # Using a default small font
|
||||
self._draw_text_with_outline(draw, status_text, (status_x, status_y), status_font)
|
||||
|
||||
game_time = datetime.fromisoformat(game_data['start_time'].replace('Z', '+00:00'))
|
||||
@@ -263,8 +265,9 @@ class BaseNCAABaseballManager:
|
||||
|
||||
game_time_str = self._format_game_time(game_data['start_time'])
|
||||
|
||||
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
time_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
date_font = ImageFont.truetype(ps2p, 8)
|
||||
time_font = ImageFont.truetype(ps2p, 8)
|
||||
|
||||
date_width = draw.textlength(game_date, font=date_font)
|
||||
date_x = (width - date_width) // 2
|
||||
@@ -279,7 +282,7 @@ class BaseNCAABaseballManager:
|
||||
# For recent/final games, show scores and status
|
||||
elif game_data['status'] in ['status_final', 'final', 'completed']:
|
||||
status_text = "Final"
|
||||
status_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using a default small font
|
||||
status_font = ImageFont.truetype(font_4x6, 6) # Using a default small font
|
||||
status_width = draw.textlength(status_text, font=status_font)
|
||||
status_x = (width - status_width) // 2
|
||||
status_y = 2
|
||||
@@ -289,7 +292,7 @@ class BaseNCAABaseballManager:
|
||||
away_score = str(game_data['away_score'])
|
||||
home_score = str(game_data['home_score'])
|
||||
score_text = f"{away_score}-{home_score}"
|
||||
score_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
||||
score_font = ImageFont.truetype(ps2p, 12)
|
||||
|
||||
score_width = draw.textlength(score_text, font=score_font)
|
||||
score_x = (width - score_width) // 2
|
||||
@@ -298,7 +301,7 @@ class BaseNCAABaseballManager:
|
||||
|
||||
if self.show_records and game_data['status'] in ['status_scheduled', 'status_final', 'final', 'completed']:
|
||||
try:
|
||||
record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
||||
record_font = ImageFont.truetype(font_4x6, 6)
|
||||
except IOError:
|
||||
record_font = ImageFont.load_default()
|
||||
|
||||
@@ -339,7 +342,7 @@ class BaseNCAABaseballManager:
|
||||
# Define colors for odds text
|
||||
# Use a small readable font for odds; fall back to default if not available
|
||||
try:
|
||||
odds_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
||||
odds_font = ImageFont.truetype(font_4x6, 6)
|
||||
except IOError:
|
||||
odds_font = ImageFont.load_default()
|
||||
odds_color = (255, 0, 0) # Red text
|
||||
|
||||
@@ -211,11 +211,14 @@ class BaseNCAAFBManager: # Renamed class
|
||||
"""Load fonts used by the scoreboard."""
|
||||
fonts = {}
|
||||
try:
|
||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using 4x6 for status
|
||||
fonts['detail'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Added detail font
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['status'] = ImageFont.truetype(font_4x6, 6) # Using 4x6 for status
|
||||
fonts['detail'] = ImageFont.truetype(font_4x6, 6) # Added detail font
|
||||
logging.info("[NCAAFB] Successfully loaded fonts") # Changed log prefix
|
||||
except IOError:
|
||||
logging.warning("[NCAAFB] Fonts not found, using default PIL font.") # Changed log prefix
|
||||
|
||||
@@ -213,11 +213,13 @@ class BaseNCAAMBasketballManager:
|
||||
"""Load fonts used by the scoreboard."""
|
||||
fonts = {}
|
||||
try:
|
||||
# Try to load the Press Start 2P font first
|
||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['status'] = ImageFont.truetype(font_4x6, 6)
|
||||
logging.info("[NCAAMBasketball] Successfully loaded Press Start 2P font for all text elements")
|
||||
except IOError:
|
||||
logging.warning("[NCAAMBasketball] Press Start 2P font not found, trying 4x6 font.")
|
||||
|
||||
@@ -182,11 +182,14 @@ class BaseNFLManager: # Renamed class
|
||||
"""Load fonts used by the scoreboard."""
|
||||
fonts = {}
|
||||
try:
|
||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Using 4x6 for status
|
||||
fonts['detail'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Added detail font
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
fonts['score'] = ImageFont.truetype(ps2p, 10)
|
||||
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['status'] = ImageFont.truetype(font_4x6, 6) # Using 4x6 for status
|
||||
fonts['detail'] = ImageFont.truetype(font_4x6, 6) # Added detail font
|
||||
logging.info("[NFL] Successfully loaded fonts")
|
||||
except IOError:
|
||||
logging.warning("[NFL] Fonts not found, using default PIL font.")
|
||||
|
||||
@@ -162,11 +162,13 @@ class BaseNHLManager:
|
||||
"""Load fonts used by the scoreboard."""
|
||||
fonts = {}
|
||||
try:
|
||||
# Try to load the Press Start 2P font first
|
||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 12)
|
||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['team'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
fonts['score'] = ImageFont.truetype(ps2p, 12)
|
||||
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['team'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['status'] = ImageFont.truetype(font_4x6, 6)
|
||||
logging.info("[NHL] Successfully loaded Press Start 2P font for all text elements")
|
||||
except IOError:
|
||||
logging.warning("[NHL] Press Start 2P font not found, trying 4x6 font.")
|
||||
|
||||
@@ -185,10 +185,12 @@ class OddsTickerManager:
|
||||
def _load_fonts(self) -> Dict[str, ImageFont.FreeTypeFont]:
|
||||
"""Load fonts for the ticker display."""
|
||||
try:
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
return {
|
||||
'small': ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 6),
|
||||
'medium': ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8),
|
||||
'large': ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10)
|
||||
'small': ImageFont.truetype(ps2p, 6),
|
||||
'medium': ImageFont.truetype(ps2p, 8),
|
||||
'large': ImageFont.truetype(ps2p, 10)
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error loading fonts: {e}")
|
||||
|
||||
@@ -312,10 +312,13 @@ class BaseSoccerManager:
|
||||
"""Load fonts used by the scoreboard."""
|
||||
fonts = {}
|
||||
try:
|
||||
fonts['score'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 10) # Slightly larger score
|
||||
fonts['time'] = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
fonts['team'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Keep team abbr small
|
||||
fonts['status'] = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6) # Keep status small
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
fonts['score'] = ImageFont.truetype(ps2p, 10) # Slightly larger score
|
||||
fonts['time'] = ImageFont.truetype(ps2p, 8)
|
||||
fonts['team'] = ImageFont.truetype(font_4x6, 6) # Keep team abbr small
|
||||
fonts['status'] = ImageFont.truetype(font_4x6, 6) # Keep status small
|
||||
logging.info("[Soccer] Successfully loaded custom fonts")
|
||||
except IOError:
|
||||
logging.warning("[Soccer] Custom fonts not found, using default PIL font.")
|
||||
@@ -410,7 +413,8 @@ class BaseSoccerManager:
|
||||
draw = ImageDraw.Draw(logo)
|
||||
# Optionally add text to placeholder
|
||||
try:
|
||||
placeholder_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 12)
|
||||
font_4x6 = os.path.abspath(os.path.join(script_dir, "../assets/fonts/4x6-font.ttf"))
|
||||
placeholder_font = ImageFont.truetype(font_4x6, 12)
|
||||
text_width = draw.textlength(team_abbrev, font=placeholder_font)
|
||||
text_x = (36 - text_width) // 2
|
||||
text_y = 10
|
||||
|
||||
@@ -428,7 +428,10 @@ class StockManager:
|
||||
fallback = Image.new('RGBA', (32, 32), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(fallback)
|
||||
try:
|
||||
font = ImageFont.truetype("assets/fonts/OpenSans-Regular.ttf", 16)
|
||||
# Resolve font path absolutely to avoid fallback under systemd
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
font_path = os.path.abspath(os.path.join(script_dir, "../assets/fonts/OpenSans-Regular.ttf"))
|
||||
font = ImageFont.truetype(font_path, 16)
|
||||
except:
|
||||
font = ImageFont.load_default()
|
||||
|
||||
|
||||
@@ -96,12 +96,10 @@ class TextDisplay:
|
||||
def _load_font(self):
|
||||
"""Load the specified font file (TTF or BDF)."""
|
||||
font_path = self.font_path
|
||||
if not os.path.isabs(font_path) and not font_path.startswith('assets/'):
|
||||
base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
font_path = os.path.join(base_path, font_path)
|
||||
elif not os.path.isabs(font_path) and font_path.startswith('assets/'):
|
||||
base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
font_path = os.path.join(base_path, font_path)
|
||||
# Resolve relative paths against project root based on this file location
|
||||
if not os.path.isabs(font_path):
|
||||
base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
font_path = os.path.join(base_path, font_path)
|
||||
|
||||
logger.info(f"Attempting to load font: {font_path} at size {self.font_size}")
|
||||
|
||||
|
||||
@@ -337,7 +337,8 @@ class WeatherManager:
|
||||
# --- Right Side (Below Condition): Current Temp ---
|
||||
temp = round(weather_data['main']['temp'])
|
||||
temp_text = f"{temp}°"
|
||||
temp_font = self.display_manager.small_font # Using small font
|
||||
# Ensure we use the intended PS2P font managed by DisplayManager
|
||||
temp_font = getattr(self.display_manager, 'regular_font', self.display_manager.small_font)
|
||||
temp_text_width = draw.textlength(temp_text, font=temp_font)
|
||||
temp_x = self.display_manager.matrix.width - temp_text_width - 1 # Align right
|
||||
temp_y = condition_y + 8 # Position below condition text (adjust 8 based on font size)
|
||||
|
||||
@@ -38,7 +38,9 @@ class YouTubeDisplay:
|
||||
|
||||
def _initialize_display(self):
|
||||
"""Initialize display components."""
|
||||
self.font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ps2p = os.path.abspath(os.path.join(script_dir, "../assets/fonts/PressStart2P-Regular.ttf"))
|
||||
self.font = ImageFont.truetype(ps2p, 8)
|
||||
try:
|
||||
self.youtube_logo = Image.open("assets/youtube_logo.png")
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user