diff --git a/fonts/FONT-AWESOME-LICENSE.txt b/fonts/FONT-AWESOME-LICENSE.txt new file mode 100644 index 0000000..e69c5e3 --- /dev/null +++ b/fonts/FONT-AWESOME-LICENSE.txt @@ -0,0 +1,165 @@ +Fonticons, Inc. (https://fontawesome.com) + +-------------------------------------------------------------------------------- + +Font Awesome Free License + +Font Awesome Free is free, open source, and GPL friendly. You can use it for +commercial projects, open source projects, or really almost whatever you want. +Full Font Awesome Free license: https://fontawesome.com/license/free. + +-------------------------------------------------------------------------------- + +# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) + +The Font Awesome Free download is licensed under a Creative Commons +Attribution 4.0 International License and applies to all icons packaged +as SVG and JS file types. + +-------------------------------------------------------------------------------- + +# Fonts: SIL OFL 1.1 License + +In the Font Awesome Free download, the SIL OFL license applies to all icons +packaged as web and desktop font files. + +Copyright (c) 2024 Fonticons, Inc. (https://fontawesome.com) +with Reserved Font Name: "Font Awesome". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE +Version 1.1 - 26 February 2007 + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting — in part or in whole — any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +-------------------------------------------------------------------------------- + +# Code: MIT License (https://opensource.org/licenses/MIT) + +In the Font Awesome Free download, the MIT license applies to all non-font and +non-icon files. + +Copyright 2024 Fonticons, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +# Attribution + +Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font +Awesome Free files already contain embedded comments with sufficient +attribution, so you shouldn't need to do anything additional when using these +files normally. + +We've kept attribution comments terse, so we ask that you do not actively work +to remove them from files, especially code. They're a great way for folks to +learn about Font Awesome. + +-------------------------------------------------------------------------------- + +# Brand Icons + +All brand icons are trademarks of their respective owners. The use of these +trademarks does not indicate endorsement of the trademark holder by Font +Awesome, nor vice versa. **Please do not use brand logos for any purpose except +to represent the company, product, or service to which they refer.** diff --git a/fonts/fa-solid-900.ttf b/fonts/fa-solid-900.ttf new file mode 100644 index 0000000..e7e2ecf Binary files /dev/null and b/fonts/fa-solid-900.ttf differ diff --git a/screens/journey.py b/screens/journey.py index 4ac7c69..d3372ce 100644 --- a/screens/journey.py +++ b/screens/journey.py @@ -21,7 +21,7 @@ import requests from PIL import Image, ImageDraw from screens.base import Screen -from screens.render_utils import load_font, text_width, truncate_to_width +from screens.render_utils import ICON_BUS, ICON_TRAIN, load_font, load_icon_font, text_width, truncate_to_width logger = logging.getLogger(__name__) @@ -350,17 +350,19 @@ class JourneyScreen(Screen): draw.text((arrow_x + arrow_w + scale * 0.02, top_line_y), journey["arrival"], font=time_font, fill=BLACK) - # Detail line: a small badge per leg -- colored circle (blue = - # train, green = bus; pure panel colors, no dithering) with a - # "Z" (Zug) or "B" (Bus) letter in it, so the mode is legible at - # a glance rather than relying on color alone. Followed by the - # line name, then transfer/platform/notice info. Drawn as - # manually-placed segments instead of one joined string so each - # leg can carry its own badge. + # Detail line: a real train/bus pictogram per leg (Font Awesome + # Solid, vendored in fonts/fa-solid-900.ttf -- confirmed live to + # stay recognizable even at this render size, unlike a hand-drawn + # shape or emoji, which either look unclear that small or render + # as tofu since DejaVu Sans has no color-emoji glyphs). Blue for + # train, green for bus -- pure panel colors, no dithering. + # Followed by the line name, then transfer/platform/notice info. + # Drawn as manually-placed segments instead of one joined string + # so each leg can carry its own icon. detail_y = top_line_y + time_font.size * 1.25 right_edge = width - pad - icon_d = detail_font.size * 0.9 - icon_font = load_font(size=max(8, int(icon_d * 0.62)), bold=True) + icon_d = detail_font.size * 1.05 + icon_font = load_icon_font(size=int(icon_d)) cursor_x = pad def draw_segment(text, color=BLACK, avail=None): @@ -373,12 +375,11 @@ class JourneyScreen(Screen): def draw_mode_icon(x, mode): color = BLUE if mode == "train" else GREEN - letter = "Z" if mode == "train" else "B" + glyph = ICON_TRAIN if mode == "train" else ICON_BUS + l, t, r, b = draw.textbbox((0, 0), glyph, font=icon_font) + gw, gh = r - l, b - t top = detail_y + (detail_font.size - icon_d) / 2 - draw.ellipse((x, top, x + icon_d, top + icon_d), fill=color) - l, t, r, b = draw.textbbox((0, 0), letter, font=icon_font) - lw, lh = r - l, b - t - draw.text((x + (icon_d - lw) / 2 - l, top + (icon_d - lh) / 2 - t), letter, font=icon_font, fill=(255, 255, 255)) + draw.text((x - l, top + (icon_d - gh) / 2 - t), glyph, font=icon_font, fill=color) for idx, leg in enumerate(journey["legs"]): if cursor_x >= right_edge - icon_d: diff --git a/screens/render_utils.py b/screens/render_utils.py index fd6ee0d..d292fdc 100644 --- a/screens/render_utils.py +++ b/screens/render_utils.py @@ -23,6 +23,22 @@ def load_font(size: int, bold: bool = False) -> ImageFont.FreeTypeFont: return _font_cache[key] +# Font Awesome Free (Solid), vendored for real pictogram icons (train, bus, +# etc.) where a hand-drawn shape or a plain letter would be less clear at a +# glance than the real thing. SIL OFL licensed -- see fonts/FONT-AWESOME-LICENSE.txt. +def load_icon_font(size: int) -> ImageFont.FreeTypeFont: + key = ("fa-solid", size) + if key not in _font_cache: + _font_cache[key] = ImageFont.truetype(str(FONTS_DIR / "fa-solid-900.ttf"), size) + return _font_cache[key] + + +# Font Awesome Free Solid codepoints used by screens -- named here so callers +# don't need to embed raw Private-Use-Area unicode literals. +ICON_BUS = "" +ICON_TRAIN = "" + + def text_width(draw, text: str, font: ImageFont.FreeTypeFont) -> int: left, _, right, _ = draw.textbbox((0, 0), text, font=font) return right - left