Python 3 + pygame
, 1365 1270 1261 bytes
Full program that takes a string from stdin, and displays the glyphs in a window.
Edit -95 bytes: Now shorter than Java!!! I've lost track of what all I golfed, but theres a hell of a lot of constants in here that replace repeated numbers and tuples, and various other stuff. Also note that the \x0c
s on line 8 represent literal ASCII formfeeds (codepoint 0C
)
Edit: @Steffan pointed out a few mistakes that were breaking code, fixed them.
Edit -9 bytes: Take this Java!! Big thanks to user in chat for helping me golf down the number section
from pygame import*
from math import*
A,c,l,S,d,T,U,V,W,X,Y,Z,I="red",draw.circle,draw.line,Surface,display,(w:=16,4),(x:=32,0),(w,60),(v:=48,60),(x,x),(y:=64,y),(x,y),()
def L(C,L,R,E):
s=S(Y);c(s,A,X,x,1);_={0:(T,V),1:(U,Z),2:((v,4),W),4:(X,Z),5:((4,w),(60,w)),6:((0,x),(y,x)),7:((4,v),(60,v)),8:((0,x),X),9:(X,(y,x))}
for i in C:c(s,A,{1:(v,w),2:(v,v),3:(w,v)}[i],8,1)
for i in L:l(s,A,*_[i])
if R:s=transform.rotate(s,R*45).subsurface(*b'\x0c\x0cKK')
for i in E:l(s,A,*_[i])
return s
def N(n):
s=S(Y);exec(3*"c(s,A,X,%i,1);"%(x,8,n//6*w))
for i in range(a:=n%6):z=lambda r:(x+r*sin(b:=2*pi*i/a),x-r*cos(b));l(s,A,z(8+n//6*8),z(x))
return s
t=input()
s=d.set_mode((y*len(t),y))
for i in range(len(t)):s.blit(L(*{"A":([3],I,1,I),"B":((1,3),I,1,I),"C":([2],I,1,I),"D":([2],I,1,[1]),"E":(I,(5,7),0,I),"F":(I,[5],0,I),"G":(I,(1,9),0,I),"H":((1,3),I,1,(0,2)),"I":(I,[1],0,I),"J":([3],[1],0,I),"K":(I,(4,9),1,[8]),"L":([2],[1],0,I),"M":(I,(0,2),0,I),"N":(I,[1],1,I),"O":(I,I,0,I),"P":([2],[1],0,I),"Q":([2],I,0,I),"R":([1],(1,9),0,I),"S":((1,3),I,0,I),"T":(I,(4,6),0,I),"U":([1],I,1,I),"V":([1],(1,6),1,I),"W":((1,3),(1,6),-1,I),"X":(I,(1,6),1,I),"Y":(I,(1,9),1,I),"Z":(I,[6],1,I),}[t[i]])if t[i].isalpha()else N(int(t[i]))if" "!=t[i]else S(Y),(y*i,0))
d.flip()
Some sample outputs:
HELLO WORLD
:
0123456789
:
MATORAN TESTING
:
Ungolfed and (somewhat) explained version
from pygame import*
from math import*
W="red"
def Letter(circles, lines, rot, extra): ## Function that contructs a letter glyph
S = Surface((64,64)) ## Surface to draw on
draw.circle(S,W,(32,32),32,1) ## Exterior circle
for i in circles: ## Draw the small circles
draw.circle(S,W,{0:(16,16),1:(48,16),2:(48,48),3:(16,48)}[i],8,1) ## This dict maps 0,1,2,3 to the different circle positions, clockwise from top left. Circle 0 is not used in the golfed version.
for i in lines: ## Draw the lines
draw.line(S,W,*{0:((16,4),(16,60)),1:((32,0),(32,64)), ## This dict maps numbers to the coords for various line segments.
2:((48,4),(48,60)),3:((32,0),(32,32)),4:((32,32),(32,64)), ## 0,1,2 are full length vertical lines, 4,5 are half length vertical lines
5:((4,16),(60,16)),6:((0,32),(64,32)),7:((4,48),(60,48)), ## 5,6,7 are full length horizontal lines, 8,9 are half length horizontal lines
8:((0,32),(32,32)),9:((32,32),(64,32))}[i]) ## 3 and 8 are not used in the golfed version
if rot: ## rotate the glyph 45 degrees, if necessary
S=transform.rotate(S,R*45).subsurface((12,12,75,75)) ## the R*45 is used in the golfed version to sometimes rotate the other direction, which allowed the removal of some circle/line keys from the dicts
for i in extra: ## draw the extra line segments necessary, names the same as above for consistency
draw.line(S,W,*{0:((16,4),(16,60)),1:((32,0),(32,64)),
2:((48,4),(48,60)),8:((0,32),(32,32))}[i])
return S ## return the surface
def Number(n): ## contructs a number glyph from its value
S = Surface((64,64)) ## Contruct a surface to draw on
draw.circle(S,W,(32,32),32,1) ## Exterior circle
draw.circle(S,W,(32,32),8,1) ## Central circle
draw.circle(S,W,(32,32),16*(n//6),1) ## Larger central circle, radius 0 if unneeded (radius 0 == nothing drawn)
for i in range(n%6): ## draw the spokes
a,r=(2*pi*i)/(n%6),8+n//6*8 ## current angle and the radius of the central circle
draw.line(S,W, ## draw the line, with appropriate endpoints
(32+sin(a)*r,32-cos(a)*r),
(32+sin(a)*32,32-cos(a)*32)
)
return S ## return the surface
T=input().upper() ## take input from stdin, .upper() to make ungolfed version more friendly
s=display.set_mode((64*len(T),64)) ## setup the display wide enough for the input text
for i in range(len(T)): ## loop through the characters
s.blit( ## blit (copy) the glyph surface onto the display
Letter(*{"A":((3,),(),1,()),"B":((1,3),(),1,()),"C":((2,),(),1,()), ## if its a letter, this (somewhat scary) dict maps
"D":((2,),(),1,(1,)),"E":((),(5,7),0,()),"F":((),(5,),0,()), ## the letter to the correct args for Letter()
"G":((),(1,9),0,()),"H":((1,3),(),1,(0,2)),"I":((),(1,),0,()),
"J":((3,),(1,),0,()),"K":((),(4,9),1,(8,)),"L":((2,),(1,),0,()),
"M":((),(0,2),0,()),"N":((),(1,),1,()),"O":((),(),0,()),
"P":((1,),(1,),0,()),"Q":((2,),(),0,()),
"R":((1,),(1,9),0,()),"S":((1,3),(),0,()),"T":((),(4,6),0,()),
"U":((1,),(),1,()),"V":((1,),(1,6),1,()),
"W":((0,2),(1,6),1,()),"X":((),(1,6),1,()),
"Y":((),(1,9),1,()),"Z":((),(6,),1,()),}[T[i]])
if T[i].isalpha() ## only send the char to Letter() if it is a letter
else Number(int(T[i])) ## otherwise send it to Number() as an int
if T[i]!=" " ## but if its a space, don't send it to either function
else Surface((64,64)), ## instead just make a new, empty surface
(64*i,0)) ## place at the right position
display.flip() ## render all chars