Mega update (updates will be more normal from here on)

This commit is contained in:
2026-08-01 21:52:40 -04:00
parent 59cf492531
commit 25f3d28911
11 changed files with 909 additions and 3 deletions
+1 -3
View File
@@ -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.
+7
View File
@@ -0,0 +1,7 @@
---
BasedOnStyle: LLVM
TabWidth: 4
IndentWidth: 4
UseTab: ForIndentation
ColumnLimit: 0
...
+3
View File
@@ -0,0 +1,3 @@
# Copyables
## .clang-format
This tells clang to use my preferred code formatting.
+5
View File
@@ -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.
+343
View File
@@ -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
+2
View File
@@ -0,0 +1,2 @@
[default]
is_abs = false
+339
View File
@@ -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
@@ -0,0 +1,2 @@
[default]
is_abs = false
+5
View File
@@ -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.
+20
View File
@@ -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
+182
View File
@@ -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]} <input.bdf> <output.bdf> <scale_factor>')
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]))