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 # pebble-misc
This repo will be my dumping ground for misc. Pebble stuff. 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.
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.
+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]))