From b93f1c0346a61f5a9dfa23c0f552de91700fc59b Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Mon, 10 Nov 2025 08:21:44 +0100 Subject: [PATCH] Add ShowFonts app --- .../META-INF/MANIFEST.JSON | 24 ++++ .../assets/showfonts.py | 51 ++++++++ .../generate_icon.py | 110 ++++++++++++++++++ .../res/mipmap-mdpi/icon_64x64.png | Bin 0 -> 3584 bytes 4 files changed, 185 insertions(+) create mode 100644 internal_filesystem/apps/com.micropythonos.showfonts/META-INF/MANIFEST.JSON create mode 100644 internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py create mode 100644 internal_filesystem/apps/com.micropythonos.showfonts/generate_icon.py create mode 100644 internal_filesystem/apps/com.micropythonos.showfonts/res/mipmap-mdpi/icon_64x64.png diff --git a/internal_filesystem/apps/com.micropythonos.showfonts/META-INF/MANIFEST.JSON b/internal_filesystem/apps/com.micropythonos.showfonts/META-INF/MANIFEST.JSON new file mode 100644 index 00000000..cb484776 --- /dev/null +++ b/internal_filesystem/apps/com.micropythonos.showfonts/META-INF/MANIFEST.JSON @@ -0,0 +1,24 @@ +{ +"name": "ShowFonts", +"publisher": "MicroPythonOS", +"short_description": "Show installed fonts", +"long_description": "Visualize the installed fonts so the user can check them out.", +"icon_url": "https://apps.micropythonos.com/apps/com.micropythonos.showfonts/icons/com.micropythonos.showfonts_0.0.1_64x64.png", +"download_url": "https://apps.micropythonos.com/apps/com.micropythonos.showfonts/mpks/com.micropythonos.showfonts_0.0.1.mpk", +"fullname": "com.micropythonos.showfonts", +"version": "0.0.1", +"category": "development", +"activities": [ + { + "entrypoint": "assets/showfonts.py", + "classname": "ShowFonts", + "intent_filters": [ + { + "action": "main", + "category": "launcher" + } + ] + } + ] +} + diff --git a/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py b/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py new file mode 100644 index 00000000..9aa49c7c --- /dev/null +++ b/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py @@ -0,0 +1,51 @@ +from mpos.apps import Activity +import lvgl as lv + +class ShowFonts(Activity): + def onCreate(self): + screen = lv.obj() + #cont.set_size(320, 240) + #cont.set_scrollbar_mode(lv.SCROLLBAR_MODE.AUTO) + #cont.set_scroll_dir(lv.DIR.VER) + + # Make the screen focusable so it can be scrolled with the arrow keys + focusgroup = lv.group_get_default() + if focusgroup: + focusgroup.add_obj(screen) + + fonts = [ + (lv.font_montserrat_16, "Montserrat 16"), + (lv.font_unscii_16, "Unscii 16"), + (lv.font_unscii_8, "Unscii 8"), + (lv.font_dejavu_16_persian_hebrew, "DejaVu 16 Persian/Hebrew"), + ] + + dsc = lv.font_glyph_dsc_t() + y = 4 + + for font, name in fonts: + title = lv.label(screen) + title.set_text(name) + title.set_style_text_font(lv.font_montserrat_16, 0) + title.set_pos(4, y) + y += title.get_height() + 20 + + line_height = font.get_line_height() + 4 + x = 4 + + for cp in range(0x20, 0xFFFF + 1): + if font.get_glyph_dsc(font, dsc, cp, cp): + lbl = lv.label(screen) + lbl.set_style_text_font(font, 0) + lbl.set_text(chr(cp)) + lbl.set_pos(x, y) + + x += 20 + if x + 20 > screen.get_width(): + x = 4 + y += line_height + + y += line_height + + screen.set_height(y + 20) + self.setContentView(screen) diff --git a/internal_filesystem/apps/com.micropythonos.showfonts/generate_icon.py b/internal_filesystem/apps/com.micropythonos.showfonts/generate_icon.py new file mode 100644 index 00000000..8c0797d3 --- /dev/null +++ b/internal_filesystem/apps/com.micropythonos.showfonts/generate_icon.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +""" +Generate a 64x64 PNG icon with transparent background for the "ShowFonts" app. +The icon features a stylized bold 'F' with a subtle font preview overlay, +using modern flat design with vibrant colors. +""" + +import cairo +from pathlib import Path + +def create_showfonts_icon(output_path: str = "ShowFonts_icon.png"): + # Icon dimensions + WIDTH, HEIGHT = 64, 64 + RADIUS = 12 # Corner radius for rounded square background + + # Create surface with alpha channel + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) + ctx = cairo.Context(surface) + + # Fully transparent background + ctx.set_source_rgba(0, 0, 0, 0) + ctx.paint() + + # === Draw subtle rounded background (optional soft glow base) === + ctx.save() + rounded_rect(ctx, 4, 4, 56, 56, RADIUS) + ctx.set_source_rgba(0.1, 0.1, 0.1, 0.15) # Very subtle dark overlay + ctx.fill() + ctx.restore() + + # === Main colorful gradient background === + ctx.save() + rounded_rect(ctx, 6, 6, 52, 52, RADIUS - 2) + + # Create radial gradient for depth + grad = cairo.RadialGradient(32, 20, 5, 32, 32, 30) + grad.add_color_stop_rgb(0, 0.25, 0.6, 1.0) # Bright blue center + grad.add_color_stop_rgb(0.7, 0.1, 0.4, 0.9) # Mid tone + grad.add_color_stop_rgb(1, 0.05, 0.25, 0.7) # Deep blue edge + ctx.set_source(grad) + ctx.fill() + ctx.restore() + + # === Draw bold stylized 'F' === + ctx.save() + ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) + ctx.set_font_size(38) + + # Position 'F' centered + x_bearing, y_bearing, text_width, text_height = ctx.text_extents("F")[:4] + x = 32 - text_width / 2 - x_bearing + y = 38 - text_height / 2 - y_bearing + + ctx.move_to(x, y) + ctx.set_source_rgb(1.0, 1.0, 1.0) # Pure white + ctx.show_text("F") + ctx.restore() + + # === Add small font preview overlay (Aa) === + ctx.save() + ctx.select_font_face("Serif", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) + ctx.set_font_size(11) + + extents = ctx.text_extents("Aa") + x = 32 - extents.width / 2 - extents.x_bearing + y = 50 - extents.height / 2 - extents.y_bearing + + # Shadow for depth + ctx.move_to(x + 0.5, y + 0.5) + ctx.set_source_rgba(0, 0, 0, 0.3) + ctx.show_text("Aa") + + # Main text + ctx.move_to(x, y) + ctx.set_source_rgb(1.0, 1.0, 0.7) # Light yellow + ctx.show_text("Aa") + ctx.restore() + + # === Add subtle highlight on 'F' === + ctx.save() + ctx.set_line_width(1.5) + ctx.set_source_rgba(1, 1, 1, 0.4) + + # Top bar highlight + ctx.move_to(14, 20) + ctx.line_to(26, 20) + ctx.stroke() + + # Middle bar highlight + ctx.move_to(14, 29) + ctx.line_to(23, 29) + ctx.stroke() + ctx.restore() + + # Save to PNG + surface.write_to_png(output_path) + print(f"Icon saved to: {Path(output_path).resolve()}") + +def rounded_rect(ctx, x, y, width, height, radius): + """Draw a rounded rectangle path""" + from math import pi + ctx.move_to(x + radius, y) + ctx.arc(x + width - radius, y + radius, radius, pi * 1.5, pi * 2) + ctx.arc(x + width - radius, y + height - radius, radius, 0, pi * 0.5) + ctx.arc(x + radius, y + height - radius, radius, pi * 0.5, pi) + ctx.arc(x + radius, y + radius, radius, pi, pi * 1.5) + ctx.close_path() + +if __name__ == "__main__": + create_showfonts_icon() diff --git a/internal_filesystem/apps/com.micropythonos.showfonts/res/mipmap-mdpi/icon_64x64.png b/internal_filesystem/apps/com.micropythonos.showfonts/res/mipmap-mdpi/icon_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..b848f8e616170bb45775de5e6f715d8862117a63 GIT binary patch literal 3584 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 literal 0 HcmV?d00001