From 25f3d28911e359c959a02306e65670f15aeca8dd Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Sat, 1 Aug 2026 21:52:40 -0400 Subject: [PATCH] Mega update (updates will be more normal from here on) --- README.md | 4 +- copyables/.clang-format | 7 + copyables/COPYABLES.md | 3 + fonts/FONTS.md | 5 + fonts/lecoish_mono_bold_20.bdf | 343 ++++++++++++++++++++++ fonts/lecoish_mono_bold_20.glyphs.toml | 2 + fonts/lecoish_mono_regular_20.bdf | 339 +++++++++++++++++++++ fonts/lecoish_mono_regular_20.glyphs.toml | 2 + tools/TOOLS.md | 5 + tools/clangd.zsh | 20 ++ tools/scale_bdf.py | 182 ++++++++++++ 11 files changed, 909 insertions(+), 3 deletions(-) create mode 100644 copyables/.clang-format create mode 100644 copyables/COPYABLES.md create mode 100644 fonts/FONTS.md create mode 100644 fonts/lecoish_mono_bold_20.bdf create mode 100644 fonts/lecoish_mono_bold_20.glyphs.toml create mode 100644 fonts/lecoish_mono_regular_20.bdf create mode 100644 fonts/lecoish_mono_regular_20.glyphs.toml create mode 100644 tools/TOOLS.md create mode 100755 tools/clangd.zsh create mode 100755 tools/scale_bdf.py diff --git a/README.md b/README.md index 9e10715..1aed504 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,2 @@ # pebble-misc -This repo will be my dumping ground for misc. Pebble stuff. - -Currently, it houses a printable template for hand-drawing Pebble watchfaces. The only watch from the template that I physically own right now is Chalk, so please verify the sizes are correct for the other models before trusting them. +This repo is my dumping ground for miscellaneous Pebble stuff. Please see the `.md` files in each folder for explanations on what everything is for. diff --git a/copyables/.clang-format b/copyables/.clang-format new file mode 100644 index 0000000..31aa732 --- /dev/null +++ b/copyables/.clang-format @@ -0,0 +1,7 @@ +--- +BasedOnStyle: LLVM +TabWidth: 4 +IndentWidth: 4 +UseTab: ForIndentation +ColumnLimit: 0 +... diff --git a/copyables/COPYABLES.md b/copyables/COPYABLES.md new file mode 100644 index 0000000..a20a444 --- /dev/null +++ b/copyables/COPYABLES.md @@ -0,0 +1,3 @@ +# Copyables +## .clang-format +This tells clang to use my preferred code formatting. diff --git a/fonts/FONTS.md b/fonts/FONTS.md new file mode 100644 index 0000000..46ba353 --- /dev/null +++ b/fonts/FONTS.md @@ -0,0 +1,5 @@ +# Fonts +## BDF Font Scaling +BDF fonts do not scale traditionally. In order to scale the fonts in this folder, use the `scale_bdf.py` script in the `tools` folder within this repo. It will output integer-scaled versions of these bitmap fonts. +## BDF Font Editing +The `.toml` files in this folder are for use in the [bited](https://github.com/molarmanful/bited) font editor. Open the corresponding `.bdf` and the resources in the `.toml` will be loaded automatically. diff --git a/fonts/lecoish_mono_bold_20.bdf b/fonts/lecoish_mono_bold_20.bdf new file mode 100644 index 0000000..5752f87 --- /dev/null +++ b/fonts/lecoish_mono_bold_20.bdf @@ -0,0 +1,343 @@ +STARTFONT 2.1 +FONT -bited-LECOISH-Regular-R-Normal--20-720-72-20-M-150-ISO10646-1 +SIZE 72 72 20 +FONTBOUNDINGBOX 14 20 0 0 +STARTPROPERTIES 24 +FOUNDRY "bited" +FAMILY_NAME "LECOISH" +WEIGHT_NAME "Regular" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 20 +POINT_SIZE 720 +RESOLUTION_X 72 +RESOLUTION_Y 20 +SPACING "M" +AVERAGE_WIDTH 150 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONT_ASCENT 20 +FONT_DESCENT 0 +CAP_HEIGHT 0 +X_HEIGHT 0 +COPYRIGHT "" +BITED_DWIDTH 16 +BITED_TABLE_WIDTH -16 +BITED_TABLE_CELL_SCALE 2 +BITED_EDITOR_GRID_SIZE 32 +BITED_EDITOR_CELL_SIZE 12 +ENDPROPERTIES +CHARS 13 +STARTCHAR U+0020 +ENCODING 32 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR U+002E +ENCODING 46 +SWIDTH 714 0 +DWIDTH 10 0 +BBX 4 3 3 0 +BITMAP +F0 +F0 +F0 +ENDCHAR +STARTCHAR U+0030 +ENCODING 48 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F03C +F03C +F03C +F03C +F03C +F03C +F03C +F03C +F03C +F03C +F03C +F03C +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0031 +ENCODING 49 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FF80 +FF80 +FF80 +FF80 +0780 +0780 +0780 +0780 +0780 +0780 +0780 +0780 +0780 +0780 +0780 +0780 +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0032 +ENCODING 50 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F03C +F03C +003C +003C +FFFC +FFFC +FFFC +FFFC +F000 +F000 +F000 +F000 +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0033 +ENCODING 51 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +003C +003C +003C +003C +7FFC +7FFC +7FFC +7FFC +003C +003C +003C +003C +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0034 +ENCODING 52 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +F03C +F03C +F03C +F03C +F03C +F03C +F03C +F03C +FFFC +FFFC +FFFC +FFFC +003C +003C +003C +003C +003C +003C +003C +003C +ENDCHAR +STARTCHAR U+0035 +ENCODING 53 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F000 +F000 +F000 +F000 +FFFC +FFFC +FFFC +FFFC +001C +001C +F01C +F01C +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0036 +ENCODING 54 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F000 +F000 +F000 +F000 +FFFC +FFFC +FFFC +FFFC +F03C +F03C +F03C +F03C +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0037 +ENCODING 55 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F03C +F03C +003C +003C +003C +003C +003C +003C +003C +003C +003C +003C +003C +003C +003C +003C +ENDCHAR +STARTCHAR U+0038 +ENCODING 56 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F03C +F03C +F03C +F03C +FFFC +FFFC +FFFC +FFFC +F03C +F03C +F03C +F03C +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+0039 +ENCODING 57 +SWIDTH 1142 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +F03C +F03C +F03C +F03C +FFFC +FFFC +FFFC +FFFC +001C +001C +001C +001C +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR U+003A +ENCODING 58 +SWIDTH 714 0 +DWIDTH 10 0 +BBX 4 17 3 0 +BITMAP +F0 +F0 +F0 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +F0 +F0 +F0 +ENDCHAR +ENDFONT diff --git a/fonts/lecoish_mono_bold_20.glyphs.toml b/fonts/lecoish_mono_bold_20.glyphs.toml new file mode 100644 index 0000000..9d39faf --- /dev/null +++ b/fonts/lecoish_mono_bold_20.glyphs.toml @@ -0,0 +1,2 @@ +[default] +is_abs = false diff --git a/fonts/lecoish_mono_regular_20.bdf b/fonts/lecoish_mono_regular_20.bdf new file mode 100644 index 0000000..fd750ad --- /dev/null +++ b/fonts/lecoish_mono_regular_20.bdf @@ -0,0 +1,339 @@ +STARTFONT 2.1 +FONT -bited-LECOISH-Regular-R-Normal--20-720-72-20-M-150-ISO10646-1 +SIZE 72 72 20 +FONTBOUNDINGBOX 12 20 0 0 +STARTPROPERTIES 24 +FOUNDRY "bited" +FAMILY_NAME "LECOISH" +WEIGHT_NAME "Regular" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 20 +POINT_SIZE 720 +RESOLUTION_X 72 +RESOLUTION_Y 20 +SPACING "M" +AVERAGE_WIDTH 150 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONT_ASCENT 20 +FONT_DESCENT 0 +CAP_HEIGHT 0 +X_HEIGHT 0 +COPYRIGHT "" +BITED_DWIDTH 16 +BITED_TABLE_WIDTH -16 +BITED_TABLE_CELL_SCALE 2 +BITED_EDITOR_GRID_SIZE 32 +BITED_EDITOR_CELL_SIZE 12 +ENDPROPERTIES +CHARS 13 +STARTCHAR U+0020 +ENCODING 32 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR U+002E +ENCODING 46 +SWIDTH 833 0 +DWIDTH 10 0 +BBX 4 2 3 0 +BITMAP +F0 +F0 +ENDCHAR +STARTCHAR U+0030 +ENCODING 48 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0031 +ENCODING 49 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FE00 +FE00 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +0600 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0032 +ENCODING 50 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C030 +C030 +0030 +0030 +0030 +0030 +0030 +0030 +FFF0 +FFF0 +C000 +C000 +C000 +C000 +C000 +C000 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0033 +ENCODING 51 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +7FF0 +7FF0 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0034 +ENCODING 52 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +FFF0 +FFF0 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +ENDCHAR +STARTCHAR U+0035 +ENCODING 53 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C000 +C000 +C000 +C000 +C000 +C000 +C000 +FFF0 +FFF0 +0030 +0030 +0030 +0030 +0030 +C030 +C030 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0036 +ENCODING 54 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C000 +C000 +C000 +C000 +C000 +C000 +C000 +FFF0 +FFF0 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0037 +ENCODING 55 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C030 +C030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +ENDCHAR +STARTCHAR U+0038 +ENCODING 56 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +FFF0 +FFF0 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+0039 +ENCODING 57 +SWIDTH 1333 0 +DWIDTH 16 0 +BBX 12 20 2 0 +BITMAP +FFF0 +FFF0 +C030 +C030 +C030 +C030 +C030 +C030 +C030 +FFF0 +FFF0 +0030 +0030 +0030 +0030 +0030 +0030 +0030 +FFF0 +FFF0 +ENDCHAR +STARTCHAR U+003A +ENCODING 58 +SWIDTH 833 0 +DWIDTH 10 0 +BBX 4 14 3 0 +BITMAP +F0 +F0 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +F0 +F0 +ENDCHAR +ENDFONT diff --git a/fonts/lecoish_mono_regular_20.glyphs.toml b/fonts/lecoish_mono_regular_20.glyphs.toml new file mode 100644 index 0000000..9d39faf --- /dev/null +++ b/fonts/lecoish_mono_regular_20.glyphs.toml @@ -0,0 +1,2 @@ +[default] +is_abs = false diff --git a/tools/TOOLS.md b/tools/TOOLS.md new file mode 100644 index 0000000..9c71412 --- /dev/null +++ b/tools/TOOLS.md @@ -0,0 +1,5 @@ +# Tools +## clangd.zsh +This is a simple script that generates a `.clangd` file pointing clang to your local Pebble SDK header. +## scale_bdf.py +This script integer scales BDF fonts. diff --git a/tools/clangd.zsh b/tools/clangd.zsh new file mode 100755 index 0000000..10a19d6 --- /dev/null +++ b/tools/clangd.zsh @@ -0,0 +1,20 @@ +#!/usr/bin/env zsh +echo "CompileFlags: + Add: + [ + -DPBL_DISPLAY_WIDTH=200, + -DPBL_DISPLAY_HEIGHT=228, + -xc, + -nostdinc, + -DPBL_COLOR, + -DPBL_RECT, + -I${HOME}/.pebble-sdk/SDKs/current/sdk-core/pebble/emery/include, + -include$(pwd)/build/include/message_keys.auto.h, + -I$(pwd)/build/emery, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/stdint.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/stdlib.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/time.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/string.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/lib/gcc/arm-none-eabi/14.2.1/include/stddef.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/lib/gcc/arm-none-eabi/14.2.1/include/stdbool.h, + ]" > ./.clangd diff --git a/tools/scale_bdf.py b/tools/scale_bdf.py new file mode 100755 index 0000000..13c1944 --- /dev/null +++ b/tools/scale_bdf.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +import sys + + +def scale_bitmap_rows(rows, bbx_width, factor): + new_width = bbx_width * factor + new_bytes = (new_width + 7) // 8 + new_bits = new_bytes * 8 + + old_bytes = (bbx_width + 7) // 8 + old_bits = old_bytes * 8 + + result = [] + for row_hex in rows: + hex_val = int(row_hex, 16) + + # Extract bits MSB-first — BDF pixels are left-aligned within + # ceil(width/8) bytes, MSB of first byte = leftmost pixel. + bits = [] + for bit_idx in range(bbx_width): + bit = (hex_val >> (old_bits - 1 - bit_idx)) & 1 + bits.append(bit) + + # Expand horizontally: each bit repeated `factor` times + expanded = [] + for b in bits: + expanded.extend([b] * factor) + + # Pack back into MSB-first, left-aligned hex + packed = 0 + for idx, b in enumerate(expanded): + if b: + packed |= 1 << (new_bits - 1 - idx) + + hex_str = format(packed, f'0{new_bytes * 2}X') + + # Expand vertically: duplicate the row `factor` times + for _ in range(factor): + result.append(hex_str) + + return result + + +def scale_bdf(input_path, output_path, factor): + if factor < 1 or not isinstance(factor, int): + print(f"Error: scale factor must be a positive integer, got {factor}") + sys.exit(1) + + with open(input_path) as f: + lines = f.readlines() + + out = [] + in_bitmap = False + bitmap_rows = [] + current_bbx_w = 0 + current_bbx_h = 0 + current_bbx_x = 0 + current_bbx_y = 0 + + for line in lines: + line = line.rstrip('\n') + + if in_bitmap: + if line == 'ENDCHAR': + scaled_rows = scale_bitmap_rows(bitmap_rows, current_bbx_w, factor) + out.extend(scaled_rows) + out.append('ENDCHAR') + in_bitmap = False + bitmap_rows = [] + else: + bitmap_rows.append(line) + continue + + if line == 'STARTCHAR': + in_bitmap = False + out.append(line) + elif line == 'BITMAP': + in_bitmap = True + out.append('BITMAP') + elif line.startswith('FONT '): + out.append(scale_font_line(line, factor)) + elif line.startswith('SIZE '): + parts = line.split() + out.append( + f'SIZE {int(parts[1]) * factor} {parts[2]} {parts[3]}' + ) + elif line.startswith('FONTBOUNDINGBOX '): + parts = line.split() + out.append( + f'FONTBOUNDINGBOX {int(parts[1]) * factor} ' + f'{int(parts[2]) * factor} ' + f'{int(parts[3]) * factor} ' + f'{int(parts[4]) * factor}' + ) + elif line.startswith('BBX '): + parts = line.split() + current_bbx_w = int(parts[1]) + current_bbx_h = int(parts[2]) + current_bbx_x = int(parts[3]) + current_bbx_y = int(parts[4]) + out.append( + f'BBX {current_bbx_w * factor} ' + f'{current_bbx_h * factor} ' + f'{current_bbx_x * factor} ' + f'{current_bbx_y * factor}' + ) + elif line.startswith('PIXEL_SIZE '): + parts = line.split() + out.append(f'PIXEL_SIZE {int(parts[1]) * factor}') + elif line.startswith('POINT_SIZE '): + parts = line.split() + out.append(f'POINT_SIZE {int(parts[1]) * factor}') + elif line.startswith('FONT_ASCENT '): + parts = line.split() + out.append(f'FONT_ASCENT {int(parts[1]) * factor}') + elif line.startswith('FONT_DESCENT '): + parts = line.split() + out.append(f'FONT_DESCENT {int(parts[1]) * factor}') + elif line.startswith('CAP_HEIGHT '): + parts = line.split() + val = int(parts[1]) + if val > 0: + out.append(f'CAP_HEIGHT {val * factor}') + else: + out.append(line) + elif line.startswith('X_HEIGHT '): + parts = line.split() + val = int(parts[1]) + if val > 0: + out.append(f'X_HEIGHT {val * factor}') + else: + out.append(line) + elif line.startswith('AVERAGE_WIDTH '): + parts = line.split() + out.append(f'AVERAGE_WIDTH {int(parts[1]) * factor}') + elif line.startswith('DWIDTH '): + parts = line.split() + out.append(f'DWIDTH {int(parts[1]) * factor} {parts[2]}') + elif line.startswith('SWIDTH '): + parts = line.split() + out.append(f'SWIDTH {int(parts[1]) * factor} {parts[2]}') + elif line.startswith('BITED_DWIDTH '): + parts = line.split() + out.append(f'BITED_DWIDTH {int(parts[1]) * factor}') + elif line.startswith('METRICSSET '): + pass # skip Apple metrics, they'll be regenerated + else: + out.append(line) + + with open(output_path, 'w') as f: + f.write('\n'.join(out) + '\n') + + print(f'Scaled {input_path} by {factor}x → {output_path}') + + +def scale_font_line(line, factor): + """Scale the XLFD FONT line.""" + # FONT -foundry-family-weight-slant-setwidth-addstyle-pixel-point-resx-resy... + # Fields are dash-separated + parts = line.split('-') + # parts[0] = 'FONT ' + # parts[7] = pixel size (should be int) + # parts[8] = point size (decipoints) + try: + pixel_size = int(parts[7]) + parts[7] = str(pixel_size * factor) + except (ValueError, IndexError): + pass + try: + point_size = int(parts[8]) + parts[8] = str(point_size * factor) + except (ValueError, IndexError): + pass + return '-'.join(parts) + + +if __name__ == '__main__': + if len(sys.argv) != 4: + print(f'Usage: {sys.argv[0]} ') + print(f'Example: {sys.argv[0]} lecoishmono.bdf lecoishmono_18.bdf 2') + sys.exit(1) + scale_bdf(sys.argv[1], sys.argv[2], int(sys.argv[3]))