so that mosaic graphics work. */
pre {
line-height: 1em;
}
h1 {
font-size: 5em;
font-stretch: expanded;
font-weight: inherit;
margin-top: 0;
margin-bottom: -0.2em;
line-height: 1.2em;
background: url(titlebg.jpg) 0% 0% / auto 100% no-repeat;
}
.fade {
display: block;
-webkit-mask-image: linear-gradient(to right, transparent 1em, white 3em);
mask-image: linear-gradient(to right, transparent 1em, white 3em);
}
h2 {
font-size: 2em;
font-stretch: ultra-condensed;
font-weight: inherit;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
h1, h2 {
margin-left: -24px;
}
ul {
list-style-type: "\2022 ";
}
img {
max-width: 100%;
}
input:not([type="image" i], [type="range" i], [type="checkbox" i],
[type="radio" i]) {
appearance: none;
font: inherit;
color: inherit;
background: inherit;
border: 0.1em solid;
margin: 0.5em 0.2em 0.4em 0.3em;
padding: 0.4em 0.3em 0.5em 0.2em;
line-height: 1;
}
.smallprint {
font-size: 0.5em;
}
/*
* When we're using text as a sample of Bedstead, it should be hidden
* from browsers without font support, and the image sample should
* be used instead.
*/
.text-sample {
font-size: 2.5em;
/* These may be overridden by the @media rule below. */
display: block;
speak: never;
}
.image-sample {
display: none;
}
@media braille, embossed, speech, tty, (grid) {
.text-sample {
display: none;
}
.image-sample {
display: block;
}
}
/* Colours that make Bedstead look better (imitating my green monitor) */
body, .fade {
background-color: #031109;
color: #33ff88;
}
:link, kbd, code, tt, .smallprint {
color: #38bf66;
}
:visited {
color: #22aa5b;
}
bedstead-3.261/compatcheck 0000775 0000000 0000000 00000012332 15141656716 0015524 0 ustar 00root root 0000000 0000000 #! /usr/bin/python3
# SPDX-License-Identifier: CC0-1.0
# This is a script to check the backward compatibility of fonts, and
# specifically of Bedstead. It takes two font files as arguments and
# checks whether upgrades from the first to the second will break
# anything. It should fail on anything that would require a change of
# major version number.
#
# Things that are checked:
#
# Glyph names. Existing PostScript files that refer to specific glyph
# names should continue to work. The script checks that all glyph
# names in the old font still exist, but not that they look right.
#
# Code points. Anything using a font through the 'cmap' table should
# continue to work. That means that any 'cmap' that exists should
# continue to exist, and that any mapping through any 'cmap' should
# continue to work. As with glyph names, the script checks for the
# existence of mappings, but not their content.
#
# Names. Applications use a font's name to refer to it. This script
# checks that the subset of names for which this seems reasonable
# match between the old and new fonts.
#
# Vendor ID. At least some versions of GNU Emacs like to use the
# OS/2.achVendID field to select fonts. So if that changes, Emacs
# might not find your favourite font.
#
# Some 'GSUB' lookups. For some features, the OpenType specification
# says that the various outputs of an alternate lookup should match
# across fonts in a family. This suggests that it's reasonable to
# depend on the behaviour of particular inputs to these lookups, and
# that they should thus be consistent within major versions. Unlike
# for most features above, we'd like to check that the semantics of
# the chosen glyphs haven't changed. This is made tricky by the fact
# the Bedstead 3.251 changed some glyph names while keeping the same
# semantics, and also changed the shape of some glyphs. Our approach
# is to look up both old and new glyph names in the new font and check
# that they have the same outline there. The only feature currently
# handled by this is 'aalt' (Access All Alternates).
from argparse import ArgumentParser
from fontTools import ttLib
from sys import exit
parser = ArgumentParser()
parser.add_argument("old")
parser.add_argument("new")
cfg = parser.parse_args()
ttold = ttLib.TTFont(cfg.old)
ttnew = ttLib.TTFont(cfg.new)
failed = False
def fail(msg):
failed = True
print(f"FAIL: {msg}")
if not (set(ttold.getGlyphOrder()) <= set(ttnew.getGlyphOrder())):
fail("Glyphs vanished: "
f"{set(ttold.getGlyphOrder()) - set(ttnew.getGlyphOrder())!r}")
for cmapold in ttold['cmap'].tables:
cmapnew = ttnew['cmap'].getcmap(cmapold.platformID, cmapold.platEncID)
if cmapnew == None:
fail("No cmap in new font for "
f"{(cmapold.platformID,cmapold.platEncID)}")
elif not (set(cmapold.cmap.keys()) <= set(cmapnew.cmap.keys())):
fail("Code points vanished from "
f"{(cmapold.platformID,cmapold.platEncID)}: "
f"{set(cmapold.cmap.keys()) - set(cmapnew.cmap.keys())!r}")
# Names that might be used to specify fonts.
specnames = {
1, # Font family name
2, # Font subfamily name
4, # Full font name
6, # PostScript FontName
16, # Typographic family name
17, # Typographic subfamily name
18, # Compatible full name
20, # PostScript CID findfont name
21, # WWS family name
22, # WWS subfamily name
25, # Variations PostScript name prefix
}
for oldname in ttold['name'].names:
if oldname.nameID in specnames:
newname = ttnew['name'].getName(oldname.nameID, oldname.platformID,
oldname.platEncID, oldname.langID)
if newname == None:
fail("No name in new font for "
f"nameID={oldname.nameID}, platformID={oldname.platformID}, "
f"platEncID={oldname.platEncID}, langID={oldname.langID}")
if newname.string != oldname.string:
fail("Name mismatch for "
f"nameID={oldname.nameID}, platformID={oldname.platformID}, "
f"platEncID={oldname.platEncID}, langID={oldname.langID}")
if ttold['OS/2'].achVendID != ttnew['OS/2'].achVendID:
fail("Vendor ID mismatch")
def feat_to_dict(gsub, tag):
# Assertions in this function trap various unhandled cases.
feature_records = [f for f in gsub.table.FeatureList.FeatureRecord
if f.FeatureTag == tag]
assert(len(feature_records) == 1)
for fr in feature_records:
assert(len(fr.Feature.LookupListIndex) == 1)
for llix in fr.Feature.LookupListIndex:
lookup = gsub.table.LookupList.Lookup[llix]
assert(lookup.LookupType == 3)
assert(len(lookup.SubTable) == 1)
for st in lookup.SubTable:
return st.alternates
def charstring(glyphname):
return ttnew['CFF '].cff[0].CharStrings[glyphname].bytecode
for feat in ['aalt']:
oldalt = feat_to_dict(ttold['GSUB'], feat)
newalt = feat_to_dict(ttnew['GSUB'], feat)
for k in sorted(set(oldalt.keys()) & set(newalt.keys())):
if ([charstring(x) for x in newalt[k][:len(oldalt[k])]] !=
[charstring(x) for x in oldalt[k]]):
fail(f"new '{feat}' lookup for {k} is not a prefix of old one")
if failed:
exit(1)
bedstead-3.261/df.ps 0000664 0000000 0000000 00000005342 15141656716 0014255 0 ustar 00root root 0000000 0000000 %!
% SPDX-License-Identifier: CC0-1.0
%
% This program produces a tileset image suitable for use with
% Dwarf Fortress. This is an image with 256 glyphs in a 16x16
% square, in white on magenta. The character set is (roughly)
% IBM Code Page 437.
%
% "size" should be defined in systemdict to be the pixel size of font
% to generate, e.g. using -dsize=10 as a command-line option to
% Ghostscript.
%
/pw size 16 mul 6 mul 10 div def
/ph size 16 mul def
<< /HWResolution [ 72 72 ]
/PageSize [ pw ph ] >> setpagedevice
1 0 1 setrgbcolor 0 0 pw ph rectfill
1 1 1 setrgbcolor
/Bedstead findfont size scalefont setfont
/row { %def
0 0 moveto
{ %forall
glyphshow
} forall
0 size neg translate
} def
0 size 15.2 mul translate
[ /space/smileface/invsmileface/heart/diamond/club/spade/bullet
/invbullet/circle/invcircle/male/female/musicalnote/musicalnotedbl/sun ] row
[ /triagrt/triaglf/arrowupdn/exclamdbl/paragraph/section/filledrect
/arrowupdnbse/arrowup/arrowdown/arrowright/arrowleft/orthogonal/arrowboth
/triagup/triagdn ] row
[ /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quotesingle
/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash ] row
[ /zero/one/two/three/four/five/six/seven
/eight/nine/colon/semicolon/less/equal/greater/question ] row
[ /at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O ] row
[ /P/Q/R/S/T/U/V/W
/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore ] row
[ /grave/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o ] row
[ /p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde/house ] row
[ /Ccedilla/udieresis/eacute/acircumflex/adieresis/agrave/aring/ccedilla
/ecircumflex/edieresis/egrave/idieresis/icircumflex/igrave/Adieresis
/Aring ] row
[ /Eacute/ae/AE/ocircumflex/odieresis/ograve/ucircumflex/ugrave
/ydieresis/Odieresis/Udieresis/cent/sterling/yen/peseta/florin ] row
[ /aacute/iacute/oacute/uacute/ntilde/Ntilde/ordfeminine/ordmasculine
/questiondown/revlogicalnot/logicalnot/onehalf/onequarter/exclamdown
/guillemotleft/guillemotright ] row
[ /ltshade/shade/dkshade/SF110000/SF090000/SF190000/SF200000/SF210000/SF220000
/SF230000/SF240000/SF250000/SF260000/SF270000/SF280000/SF030000 ] row
[ /SF020000/SF070000/SF060000/SF080000/SF100000/SF050000/SF360000/SF370000
/SF380000/SF390000/SF400000/SF410000/SF420000/SF430000/SF440000
/SF450000 ] row
[ /SF460000/SF470000/SF480000/SF490000/SF500000/SF510000/SF520000/SF530000
/SF540000/SF040000/SF010000/block/dnblock/lfblock/rtblock/upblock ] row
[ /alpha/germandbls/Gamma/pi/Sigma/sigma/mu/tau
/Phi/Theta/uni03A9/delta/infinity/phi1/epsilon/intersection ] row
[ /equivalence/plusminus/greaterequal/lessequal/integraltp/integralbt/divide
/approxequal/degree/uni2219/periodcentered/radical/uni207F/twosuperior
/filledbox/space ] row
showpage
bedstead-3.261/editor 0000775 0000000 0000000 00000023127 15141656716 0014535 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
# Interactive glyph editor for Bedstead.
#
# This program was written by Simon Tatham in 2013 and updated by Ben
# Harris in 2024.
#
# Simon Tatham and Ben Harris make this program available under the
# CC0 Public Domain Dedication.
'''Interactive glyph editor for Bedstead.
Uses Python/Tk to display a window with a pixel grid on the left side,
where the user can click or drag to toggle pixels on and off, and on
the right, shows the output of the Bedstead smoothing algorithm
applied to that grid of pixels.
This is done by running the `bedstead` executable itself to compute
the smoothed outline, so a copy of that executable is required to use
this editor.
'''
import argparse
import os
import re
import sys
import string
import subprocess
import tkinter
gutter = 20
pixel = 32
XSIZE, YSIZE = 5, 9
LEFT, TOP = 100, 700 # for transforming coordinates returned from bedstead
class EditorGui:
def __init__(self, bedstead):
self.bedstead = bedstead
self.tkroot = tkinter.Tk()
self.canvas = tkinter.Canvas(self.tkroot,
width=2 * (XSIZE*pixel) + 3*gutter,
height=YSIZE*pixel + 2*gutter,
bg='white')
self.bitmap = [0] * YSIZE
self.oldbitmap = self.bitmap[:]
self.pixels = [[None]*XSIZE for y in range(YSIZE)]
self.polygons = []
for x in range(XSIZE+1):
self.canvas.create_line(gutter + x*pixel, gutter,
gutter + x*pixel, gutter + YSIZE*pixel)
for y in range(YSIZE+1):
self.canvas.create_line(gutter, gutter + y*pixel,
gutter + XSIZE*pixel, gutter + y*pixel)
self.canvas.bind("", self.click)
self.canvas.bind("", self.drag)
self.canvas.bind("", self.paste)
self.tkroot.bind("", self.key)
self.canvas.pack()
def getpixel(self, x, y):
assert x >= 0 and x < XSIZE and y >= 0 and y < YSIZE
bit = 1 << (XSIZE-1 - x)
return self.bitmap[y] & bit
def setpixel(self, x, y, state):
assert x >= 0 and x < XSIZE and y >= 0 and y < YSIZE
bit = 1 << (XSIZE-1 - x)
if state and not (self.bitmap[y] & bit):
self.bitmap[y] |= bit
self.pixels[y][x] = self.canvas.create_rectangle(
gutter + x*pixel, gutter + y*pixel,
gutter + (x+1)*pixel, gutter + (y+1)*pixel,
fill='black')
elif not state and (self.bitmap[y] & bit):
self.bitmap[y] &= ~bit
self.canvas.delete(self.pixels[y][x])
self.pixels[y][x] = None
def regenerate(self):
if self.oldbitmap == self.bitmap:
return
self.oldbitmap = self.bitmap[:]
for pg in self.polygons:
self.canvas.delete(pg)
self.polygons = []
data = subprocess.check_output(
[self.bedstead] + list(map(str, self.bitmap)),
universal_newlines=True)
class CharstringInterpreter:
def __init__(self):
self.paths = []
self.path = None
self.stack = []
self.cursor = [0, 0]
self.skip = False
def rmoveto(self):
self.path = []
self.paths.append(self.path)
self.rlineto()
def rlineto(self):
while len(self.stack) >= 2:
self.cursor[0] += self.stack[0]
self.cursor[1] += self.stack[1]
self.stack = self.stack[2:]
self.path.append(self.cursor[:])
def op(self, word):
try:
if not self.skip:
self.stack.append(float(word))
self.skip = False
except:
if word == "rmoveto": self.rmoveto()
elif word == "rlineto": self.rlineto()
elif word in ("hstem", "vstem"): self.stack = []
elif word in ("cntrmask", "hintmask"): self.skip = True
elif word == "endchar": pass
else:
print("unknown charstring component " + repr(word))
interp = CharstringInterpreter()
data = re.sub(r"", "", data)
for word in data.split():
interp.op(word)
paths = [[[int((float(x)-LEFT)*pixel*0.01 + 2*gutter + XSIZE*pixel),
int((TOP - float(y))*pixel*0.01 + gutter)]
for x, y in path] for path in interp.paths]
# The output from 'bedstead' will be a set of disjoint paths,
# in the Postscript style (going one way around the outside of
# filled areas, and the other way around internal holes in
# those areas). Python/Tk doesn't know how to fill an
# arbitrary path in that representation, so instead we must
# convert into a set of individual Tk polygons (convex shapes
# with a single closed outline) and display them in the right
# order with the right colour.
#
# A neat way to arrange this is to compute the area enclosed
# by each polygon, essentially by integration: for each line
# segment (x0,y0)-(x1,y1), sum the y difference (y1-y0) times
# the average x value, which gives the area between that line
# segment and the corresponding segment of the x-axis. After
# we go all the way round an outline in this way, we'll have
# precisely the area enclosed by the outline, no matter how
# many times it doubles back on itself (because every piece of
# x-axis has been cancelled out by an outline going back the
# other way). Furthermore, the sign of the integral we've
# computed tells us whether the outline goes one way or the
# other around the area.
#
# So then we sort our paths into descending order of the
# absolute value of its computed area (guaranteeing that any
# path contained inside another appears after it, since it
# must enclose a strictly smaller area) and fill each one with
# a colour based on the area's sign.
#
# This strategy depends critically on 'bedstead' having given
# us sensible paths in the first place: it wouldn't handle an
# _arbitrary_ PostScript path, with loops allowed to overlap
# and intersect rather than being neatly nested.
pathswithmetadata = []
for path in paths:
area = 0
for i in range(len(path)):
x0, y0 = path[i-1]
x1, y1 = path[i]
area += (y1-y0) * (x0+x1)/2
pathswithmetadata.append([abs(area),
('black' if area<0 else 'white'),
path])
pathswithmetadata.sort(reverse=True)
for _, colour, path in pathswithmetadata:
if len(path) > 1:
args = sum(path, []) # x,y,x,y,...,x.y
pg = self.canvas.create_polygon(*args, fill=colour)
self.polygons.append(pg)
def click(self, event):
for dragstartx in gutter, 2*gutter + XSIZE*pixel:
x = (event.x - dragstartx) // pixel
y = (event.y - gutter) // pixel
if x >= 0 and x < XSIZE and y >= 0 and y < YSIZE:
self.dragstartx = dragstartx
self.dragstate = not self.getpixel(x,y)
self.setpixel(x, y, self.dragstate)
self.regenerate()
break
def paste(self, event):
s = self.tkroot.selection_get()
pat = re.compile("[0-7]+")
bitmap = []
for i in range(YSIZE):
m = pat.search(s)
if m is None:
print("Unable to interpret selection data {!r} as a "
"Bedstead glyph description".format(s))
return
bitmap.append(int(m.group(0), 8) & ((1 << XSIZE) - 1))
s = s[m.end(0):]
for y in range(YSIZE):
for x in range(XSIZE):
self.setpixel(x, y, 1 & (bitmap[y] >> (XSIZE-1 - x)))
self.regenerate()
def drag(self, event):
x = (event.x - self.dragstartx) // pixel
y = (event.y - gutter) // pixel
if 0 <= x < XSIZE and 0 <= y < YSIZE:
self.setpixel(x, y, self.dragstate)
self.regenerate()
def key(self, event):
if event.char in (' '):
bm = "".join(map(lambda n: "\\%02o" % n, self.bitmap))
print(' {"%s", U() },' % bm)
elif event.char in ('c','C'):
for y in range(YSIZE):
for x in range(XSIZE):
self.setpixel(x, y, 0)
self.regenerate()
elif event.char in ('q','Q','\x11'):
sys.exit(0)
def run(self):
tkinter.mainloop()
def main():
# By default, assume that the user ran 'make' in the bedstead
# source directory, so that the 'bedstead' executable is alongside
# the binary.
default_executable_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "bedstead")
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--bedstead", default=default_executable_path,
help="Location of the 'bedstead' executable.")
args = parser.parse_args()
editor = EditorGui(args.bedstead)
editor.run()
if __name__ == '__main__':
main()
bedstead-3.261/extended.ps 0000664 0000000 0000000 00000001151 15141656716 0015456 0 ustar 00root root 0000000 0000000 %!
% SPDX-License-Identifier: CC0-1.0
/bpx { 5 mul } bind def
<< /HWResolution [ 72 72 ] /PageSize [ 215 bpx 30 bpx ] >> setpagedevice
3 255 div 17 255 div 9 255 div setrgbcolor 0 0 215 bpx 30 bpx rectfill
51 255 div 255 255 div 136 255 div setrgbcolor
/Bedstead findfont 10 bpx scalefont setfont
0 22 bpx moveto (Bedstead) show
/Bedstead-UltraCondensed findfont 80 scalefont setfont
0 2 bpx moveto (Ultra Condensed) show
/Bedstead-Extended findfont 40 scalefont setfont
100 bpx 22 bpx moveto (Extended) show
/Bedstead-ExtraCondensed findfont 80 scalefont setfont
100 bpx 2 bpx moveto (Extra Condensed) show
showpage
bedstead-3.261/icon.ps 0000664 0000000 0000000 00000000635 15141656716 0014614 0 ustar 00root root 0000000 0000000 %!
% SPDX-License-Identifier: CC0-1.0
/bpy { size 8 div mul } bind def
/bpx { bpy 1.25 mul } bind def
<< /HWResolution [ 72 72 ] /PageSize [ size size ] >> setpagedevice
3 255 div 17 255 div 9 255 div setrgbcolor 0 0 size size rectfill
51 255 div 255 255 div 136 255 div setrgbcolor
/Bedstead-Extended findfont 10 bpy scalefont setfont
size 5 bpx sub 2 div 1 bpx sub
size 7 bpy sub 2 div
moveto (B) show
showpage
bedstead-3.261/index.xhtml 0000664 0000000 0000000 00000021615 15141656716 0015506 0 ustar 00root root 0000000 0000000
Bedstead MODE 7 for the 21st century
Bedstead
Bedstead is a family of outline fonts based on the characters
produced by the
Mullard SAA5050 series of Teletext Character Generators. The
SAA5050 is familiar to those of a certain age as the chip that
produced the MODE7 display on the BBC
Microcomputer. It generates characters from a 59 pixel
matrix, smoothing diagonal lines to produce an interlaced 1018
matrix for each character. Bedstead extends that algorithm to
continuity, converting a 59 pixel grid into an outline with
smooth diagonals.
Bedstead includes all the character designs from the SAA5050
and its various sister chips, including Cyrillic and Hebrew
alphabets. It also has a large number of custom-designed glyphs,
all of them of course based on the same 59 pixel grid.
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
峞峉峇峊峖峓峔峏
帢帣帠帤庰庤庢庛庣庥弇弮彖徆怷
苤苠苺苳苭虷虴虼虳衁衎衧衪衩觓
訄訇赲迣迡迮迠郱邽邿郕郅邾郇郋郈
蛂蛁蚺蛅蛈蚰蚹蚳蚸蛌
0123456789翹翻職!?.,:;'"()[]{}
-+繩<=>/\|瞿$瞼瞽瞻%&*#@繞穢簧
Styles
Bedstead is available in six widths. The standard version of
Bedstead is based on a square pixel grid. This is good for
displays with square pixels, but not entirely faithful to the
SAA5050. There is a second version, Bedstead Extended, that
more accurately reflects the character shapes generated by an
SAA5050 driving a 576i display.
To simulate teletext double-height mode, Bedstead and
Bedstead Extended each has a half-width version, Bedstead
Ultra Condensed and Bedstead Extra Condensed respectively.
Bedstead Condensed and Bedstead Semi Condensed provide intermediate
widths.
Bedstead
Ultra Condensed
Extended
Extra Condensed
Each width also comes in a bold variant based on the idea of a
variant SAA5050 that could advance its rising edges by one output
pixel, thickening the vertical and diagonal lines.
Semi-Graphics
Bedstead includes all of the teletext mosaic graphics
characters available from the SAA5050. These are encoded
at the standard code points defined by Unicode.
These characters are also encoded in the Private
Use area between U+EE00 and U+EE7F, in the same arrangement as
is used by
ZVBI.
為為為為為為為為為為為為為為為為馳馳馳馳馳馳馳馳
馴僧馴僧馴僧馴僧馴僧馴僧馴僧馴僧
洫為為洫為為洫為為洫為為洫為為洫為為洫為為洫為為
Bedstead also has 4-cell and 8-cell mosaic graphics, DEC- and
IBM-style box-drawing characters, and the large character pieces
supported by some HP terminals.
Generation
The outline version of Bedstead is generated by an ISO C program.
It emits an XML file that can be processed by
TTX
(part of
fontTools)
into an OpenType font.
The bitmap versions (in Bitmap Distribution Format) are then
generated from that OpenType font.
Copyright
The program that generates Bedstead and all of the
newly-designed glyphs have been released into the public domain.
I believe that the original SAA5050 bitmap font is essentially
in the public domain in the United Kingdom as a result of
Section55 of the Copyright, Designs and Patents Act 1988
as applied by
subparagraph14(5) of Schedule1. Im not a lawyer, though,
so this may well be wrong.
Downloads
bedstead-3.261.zip
Full source and binary distribution containing everything
below and more.
NEWS Release notes summarizing
whats changed between releases.
bedstead.c The C
program that generates the font.
- Finished OpenType fonts:
bedstead.otf
Bedstead
bedstead-extended.otf
Bedstead Extended
bedstead-semicondensed.otf
Bedstead Semi Condensed
bedstead-condensed.otf
Bedstead Condensed
bedstead-extracondensed.otf
Bedstead Extra Condensed
bedstead-ultracondensed.otf
Bedstead Ultra Condensed
bedstead-bold.otf
Bedstead Bold
bedstead-boldextended.otf
Bedstead Bold Extended
bedstead-boldsemicondensed.otf
Bedstead Bold Semi Condensed
bedstead-boldcondensed.otf
Bedstead Bold Condensed
bedstead-boldextracondensed.otf
Bedstead Bold Extra Condensed
bedstead-boldultracondensed.otf
Bedstead Bold Ultra Condensed
bedstead-10.bdf,
bedstead-20.bdf
Bitmap versions at 10and20 pixels high.
bedstead-bold-20.bdf
Bold bitmap version at 20pixels high.
bedstead-10-df.png,
bedstead-20-df.png
10-pixel and 20-pixel tilesets for use with
Dwarf Fortress.
bedstead-complement.pdf
A complete catalogue of glyphs in PDF.
The code to generate Bedstead is held in
Git.
You can get your own copy by running
git clone https://bjh21.me.uk/bedstead/.git
You can also
browse the repository on-line.
bedstead-3.261/panose-o.ggb 0000664 0000000 0000000 00000024271 15141656716 0015524 0 ustar 00root root 0000000 0000000 PK 潽;Y geogebra_thumbnail.pngYw8\賰&dDcD^鏡%DM0JDo
娙t┬t圂-輝煚w!9踙蹐洝桃葠綎綍鴮釸互(劈}('+
@驚趭ЪD氙=s笸|qjC
捙蟌h壈很 蜦eK;0Y^z岱捍4安m碧橆ec_`''&h傢oI禳H熀謏5菰k"|GYv#L掀畯蜭殶r>;6鉛e3蚙鏿}WD%擋yEjlp齬9羆ti⑤_歲;禗e支k'鑑h$UM餅ム篱禫憭
v刎eA韐轎@淌n;+埌"儈R0Yu壧台O磴s'鴱x覺qyxxq→力~嬬鴰2梣1U7rptt&y雜葆;^B[G[jV鈳1Q掁詈95822闈>\殃Ry鼀妍埠襢JjUv擁撮嘶鉚##員wQ⑤樿W驔{{嫪6_霽廎—揜e簏;SV粑
捫K8曚阮
摍^扶茹qj*--}CM<羱褭yU蓑Qb篹鮹群1<J擊駎屺言Ke枋W徬鞝礅W?pQ<埽D頖纚yщJN1D沿? ]/ぬq#BN艘)翁x71毿燰鴳嬿魃瘨=>趡=崿.755e%rqbb}獸橦.7趐*k9A)QS剩Erf砯蹝?`墘謅干%^E獩虙橡',匉+獀篆#峎
)狠緪謖 羸[b涫5!EE玥SQ&鱒誆8R{)l-菀鍣6擫汾-,~ 揈磑rI町.(tk溟uv祔[St8Lx臧壚:伏]LbZ殭{5 G*籜︶K偃C44Cmm烋
].X,V藏F嫮g杞3B汨DKB"蝵Q梀Ng覝alCk烿=[C(% 蚹.NbEnす~UtbE<_$<反>蜤g碣( 甗5漥﹡屔癉p証R蟨喟砓2|毘鬣e%d椒Qn1+亮-Y*uxC~偮 %;_P崷Dv陰鷒+玈b-(斯o C |倌屴B拱笅*!6狗.袎3\怛
B-R彃章}擃蟂/娣K@m媐D#u蠑嬬囿cF痷瀋G﹣qd5娑6鷜鏾+)]嗩Ci98n&
癥%A枚償>i劻J'}H墈d唋p0A蛜5笛_TVhD穇
圇e撚圈uP}3t侜fZl釁O@2=爹ф蒿梊Y G,綃J&*擦,幫扁82;=nAL0鵳[簡l窬*H
<煚0!躉鄻溘\Yl1昶閟B陏 h%A:};_ ^W/箌靡d半f"鶜6?鮕H浼H咪嚳D珞F鸒p.靚r焂=‥87.飫2X菠/つlV㏒*+K鷲4ω+番(陟憒,Ao巕署喣Zc`I恪}邡&:糢▋圬
g篞桁E氅摦=羧~@儤XS5;t-率B懖o&X庾hm窙嚙枅THP唹毫E怫k糷蘢
,餫穜>x{h審糶 *P嫷ksHTkl_瑩度曄c焨扇垺]n琶j077aKBv愾v#歜頨$!?#瑙忙UA/寓浟送憳G~2- 鸙8(s圯XX2#{F #烸眷圄Ь'/v"Teh圭*杲"x.!|5芼鑆v餼鏔#k+-農',2喊`-yIhl皜!*鞢嫶xdX磁兛鵹'j|N"9嘾!):+M@jS&04aD&刈k纏≡幎|㎜賅護!w+vB!8醉dM穚C^恤4!fp墩44'GMD^徟O>) 榳x惄L躣;齲%w墩菑>蹤萇3搤:3wp槽O鵳dug8h:樀晉嘝紟"g詢)J&
.d特D跅貜濣r驛焜/w8&觙'T夢M/'腞c袱x拒婞褩緇p鮞囊_'fW*蚝*眄f vV;ワa6螏
迅鱁殶頫槿o甚,註誇V錛USla交GuU銣-くB閞'K逗欋=}φA^T泙g.薉+慚l孓壂/lvgBBB_檦Q鏮;m穢%癭幋
黼芤蔕A模X)jZ{S麜5醽89)\>蓑94~飪xqW帄Bz7祊H|%:皓p擻x鴯酁!跪Rグ$藚ZH惙k
3R{`^騛.#u怉-^轆=TQ⊥脽c欣j澺jT鋼dM=N烋s綸xL"%~&I%﹏t樠DRCQ滾ver+}5BK銛u5}謜<7匆琠遍-tcom5僂唴O拉赬漀感[5?鷓&-z/許E7f,I弱4綟h爂Q:}AъHb;b累湖痱!r:鶂澸瀖秸X8s
}啵]h.8{f誣@.l3v*閡惡甜烸氍哷1怀U5鯇E膂xC{蜭xD^頌觸,p縍$崰袨
o闑瞰_/!'kc"鶄G郈o韔$諠掘k+甈咬
p耙#拵s浭谾"T'彼83咮"MkR舷舕"]み宰\脖t時O$q倏_n
.8樓`M8デ/OIf 箱品邲:Z稽蝕秺>纜偣縸巍`,梨梏9蜇{+痳iEIEEP曈!s夼姒奡7屋ps諈s窴%齕{魂鞮倛弊吙mV足}秒}柄暸v'Zy1篧.DT暇$洍~/fli洙
R圪沉洸<-誻蜢鋾泉K'H阜K'cN{~y吻pj9倬鷚dk葳狗6懂>zg116Pク F'&,`>)T,!竘BC
愉9伍yVZiS^Ⅶ:階fU/N歊莘]5=郪d齴株 0=雷4j苰u6裷r:!蘩
D;ic鼘蛨描喉.n%伈[K巫崏$鰾∣﹦c騫58
dVjV亦箍e效歭@1[?Gz塉貏F_銵崔./X'掂3`E霺f)颸|3bj勂窀RK齖蒮d綧亍
E出#^n
I
4稄#,JO藬Е璶b.榦g茛圊6踸BT7隔* Q瑆"霑Zmb藇vwU舟-g5脈{礎HW地bzV!f7'翷Y!oyT燊01H]r'W迻蔨!x釜!M#蓶>To/!矽-h*j"`蓊g瘛2C.唾跣r閟赲1I獑央咍臞^摙g鋮剻&"犈9猰5f.艾蘞^ @紙髧R*>爛 w8咁=鑆ㄤ7旦墉}菶B*岰pΩ(邲v%~М\4}x^J%{ 憚c蓽%_>'sf歇菤倓t0鋿j遜}w>oXG"
G4q圇Y;=W{郛p漯%蘇<5y誤膉) 4佈駁;窌儠鯬X{!φ)\4D`w0]撂оap笸涒u 腒dQ#xy^V%釢d成<"n d侕>4%丏瞼m拿疇l(昦 .!.IvL[$49o鱺zRV5fm蔽?謘}@楱A@*~93悶}蹡qW_鶪 D↓[侻,anV z姜Q$(鍍c?呸覓^(鷁i無--fo蹟*N`5賅R睞!剎-瞏+契n糰染639Y擱鴗/1祥暌OC[9o憭);Nj僗弼G;˙mk劈Z1躠毫/荎gL0/Fz5砆oXXX杲鼣鼊&M爰啁`3鐲騺o賸;Gm#$婠D9nr''鴱$AX@OM犉蟴摽{蓶xL