🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.terminals.tty5620
1 messages
1 total messages Started by DaviD W. Sanderson Sun, 12 Jan 1992 20:34
dmdtobdf - convert fixed-width DMD fonts to BDF format
#54
Author: DaviD W. Sanderson
Date: Sun, 12 Jan 1992 20:34
565 lines
15473 bytes
If you don't know what a DMD 5620 terminal is, you will not find this
useful.

About a year ago I posted a request for a utility to convert DMD fonts
to BDF format so that I could use them under X.  Nobody had one (I was
not too surprised), so I finally wrote one myself (in perl).  It only
works for fixed-width DMD fonts (they were the only kind I had
available).

If anyone has any DMD fonts they can share, I would like to know!

DaviD W. Sanderson (dws@cs.wisc.edu)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  dmdtobdf.pl dmdtobdf.1
# Wrapped by dws@skinner on Sun Jan 12 11:53:02 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dmdtobdf.pl' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dmdtobdf.pl'\"
else
echo shar: Extracting \"'dmdtobdf.pl'\" \(10823 characters\)
sed "s/^X//" >'dmdtobdf.pl' <<'END_OF_FILE'
Xeval 'exec perl -S $0 ${1+"$@"}'
X	if 0;
X
X#-------
X# $RCSfile: dmdtobdf.pl,v $$Revision: 1.2 $$Date: 1992/01/12 17:29:20 $
X#
X# dmdtobdf - read a DMD 5620 font from stdin, write corresponding BDF
X# font to stdout.
X#
X# usage: dmdtobdf [-v] [file]
X#
X# If given -v, will dump the DMD glyph bitmaps in a human-readable form
X# instead of writing the padded hex-encoded bitmaps.
X#
X# This does not work for proportional DMD fonts;
X# I have only used it for constant-width DMD fonts.
X#
X# DaviD W. Sanderson (dws@cs.wisc.edu)
X#
X# $Log: dmdtobdf.pl,v $
X# Revision 1.2  1992/01/12  17:29:20  dws
X# Cleaned up the organization and improved the comments.
X#
X# Revision 1.1  1992/01/11  11:27:01  dws
X# Initial revision
X#-------
X
Xrequire 'getopts.pl';
X
X$0 =~ s#.*/##;
X
Xsub Usage
X{
X	print "usage: $0 [-v] [file]\n";
X	exit 0;
X}
X
X&Getopts('v')	|| &Usage;
X
Xif(!$ARGV[0] && -t STDIN)
X{
X	&Usage;
X}
X
X#-------
X# DMD font file format
X#
X# Values are stored in MSB order.
X#
X# 0:	short	n;		number of chars in font
X# 2:	char	height;		height of bitmap
X# 3:	char	ascent;		top of bitmap to baseline
X# 4:	long	unused;		in case we think of more stuff
X#
X# 5:		(info)		n+1 character descriptors
X#
X# 5+(n+1)*6:	(bitmap)	glyph bitmaps
X#
X# Each character descriptor is as follows (6 bytes long):
X#
X# typedef struct Fontchar
X# {
X# 0:	short x;		left edge of bits
X# 2:	unsigned char top;	first non-zero scan-line
X# 3:	unsigned char bottom;	last non-zero scan-line
X# 4:	char left;		offset of baseline
X# 5:	unsigned char width;	width of baseline
X# } Fontchar;
X#
X# There is one bitmap for the glyphs, height bits high.
X# Each row of bits is stored in sequence, from top to bottom.
X#
X# Empirically, it seems to me that the values of the "top" and "bottom"
X# fields are not reliable, at least in the constant-width DMD fonts I
X# have examined.  They are not consistent about setting the values in
X# a meaningful way.
X#
X# Hence I regard all characters to be "height" high and "width" wide.
X# (at least the width values were consistent!)
X#-------
X
Xsub pFontChar	# charnum -> dump of FontChar info
X{
X	local($i) = @_;
X
X	sprintf("x=%4d top=%3d bot=%3d left=%3d wid=%3d"
X		,$info_x[$i]
X		,$info_top[$i]
X		,$info_bottom[$i]
X		,$info_left[$i]
X		,$info_width[$i]
X		);
X}
X
X#-------
X# writeBDF2_1 - writes a BDF version 2.1 description of the current
X# DMD font.
X#
X# Assumes:
X#	$height		(numbered from 1)
X#	$width		(numbered from 1)
X#	$ascent		(apparently numbered from 0)
X#	$n
X#	@row
X#	@info_x
X#	@info_width
X#-------
X# BDF maps are hex-encoded, padded on the right with zeros to the
X# nearest byte.
X#
X# If $opt_v is set, the DMD map is printed along with the Fontchar
X# contents.
X#-------
X# write bitmap for character
Xsub BDF2_1map		# c (index of character)
X{
X	local($c)	= @_;
X	local($r);
X	local($bits);
X	local($hex);
X	local($pad)	= '';
X
X	if($info_width[$c] % 8 != 0)
X	{
X	$pad = '0' x (int(($info_width[$c]+7)/8)*8 - $info_width[$c]);
X	}
X
X	if($opt_v)
X	{
X		print &pFontChar($c)."\n";
X	}
X
X	for($r = 0; $r < $height; $r++)
X	{
X		$bits = substr	( $row[$r]
X				, $info_x[$c]
X				, $info_width[$c]
X				);
X		if($opt_v)
X		{
X			# simply print the bits
X			$bits =~ tr/01/-#/;
X			print $bits;
X		}
X		else
X		{
X			# Encode the bits for BDF
X			for(unpack("C*", pack("B*", $bits.$pad)))
X			{
X				$hex = sprintf("%02x", $_);
X				$hex =~ tr/a-f/A-F/;
X				print $hex;
X			}
X		}
X
X		print "\n";
X	}
X}
X# write character information
Xsub writeBDF2_1char	# c (index of character)
X{
X	local($c)	= @_;
X
X	print "STARTCHAR ";
X	if($c < 0x20)
X	{
X		printf("^%c", 0x40|int($c));
X	}
X	elsif($c == 0x20)
X	{
X		print "SP";
X	}
X	elsif($c < 0x7F)
X	{
X		printf("%c", int($c));
X	}
X	elsif($c == 0x7F)
X	{
X		print "^?";
X	}
X	else
X	{
X		print "(?????)";
X	}
X	print "\n";
X
X	print "ENCODING $c\n";
X	print "SWIDTH $SWIDTHx 0\n";
X	print "DWIDTH $DWIDTHx 0\n";
X
X	print "BBX $FONTBOUNDINGBOX\n";
X	print "BITMAP\n";
X
X	# code to print out the bitmap
X	&BDF2_1map($c);
X
X	print "ENDCHAR\n";
X}
X# write font description
Xsub writeBDF2_1
X{
X	# These are arbitrary values.
X	# The computed values may depend on them.
X
X	local($COMMENT)		= '(null)';
X	local($FOUNDRY)		= 'dmd';
X	local($FAMILY_NAME)	= 'Fixed';
X	local($WEIGHT_NAME)	= 'Medium';
X	local($SLANT)		= 'R';
X	local($SETWIDTH_NAME)	= 'Normal';
X	local($ADD_STYLE_NAME)	= '';
X	local($RESOLUTION_X)	= 75;		# pixels per inch
X	local($RESOLUTION_Y)	= 75;		# pixels per inch
X	local($SPACING)		= 'C';
X	local($CHARSET_REGISTRY)= 'ISO8859';
X	local($CHARSET_ENCODING)= '1';
X
X	# These are values to be computed.
X
X	# FONT_DESCENT + FONT_ASCENT should be PIXEL_SIZE, I think
X	local($FONT_DESCENT)	= $height - $ascent - 1;
X	local($FONT_ASCENT)	= $ascent + 1;
X
X	#-------
X	# SWIDTHx is expressed in units of 1/1000th of the size of
X	# the character.
X	# The phrase "size of the character" appears to mean the height
X	# of the character.
X	# What this seems to mean is that
X	#
X	#                   width of char
X	# SWIDTHx == 1000 * --------------
X	#                   height of char
X	#
X	# Thus (if Hp is the height in points and Wp is the width in
X	# points)
X	#
X	# SWIDTHx
X	# ------- * Hp == Wp
X	#  1000
X	#
X	# and
X	#
X	# SWIDTHx        RESOLUTION_X dots/inch
X	# ------- * Hp * ---------------------- == Wd
X	#  1000          72.27 points/inch
X	#
X	# where Wd is the ideal width in dots (should be close to
X	# DWIDTHx)
X	#
X	# This is really all conjecture on my part, since the BDF
X	# doc is not exactly clear on this point, and doesn't include
X	# an explanation of how the example SWIDTHx values are found.
X	#-------
X	local($DWIDTHx)		= $width;	# pixels
X	local($SWIDTHx)		= int(1000*$width/$height);
X
X	local($PIXEL_SIZE)	= $height;	# pixels
X	local($AVERAGE_WIDTH)	= $DWIDTHx * 10;# decipixels
X
X	#-------
X	# POINT_SIZE is expressed in "decipoints".
X	# The X protocol defines points by 72.27 points = 1 inch
X	# Thus, POINT_SIZE may be computed from PIXEL_SIZE as
X	# follows:
X	#                1 inch              722.7 decipoints
X	# PIXEL_SIZE * ------------------- * ----------------
X	#              RESOLUTION_Y pixels     1 inch
X	#-------
X	local($POINT_SIZE)	= int(($PIXEL_SIZE * 722.7)/$RESOLUTION_Y);
X
X	local($FONT)		= '';
X
X	$FONT .=	"-$FOUNDRY";
X	$FONT .=	"-$FAMILY_NAME";
X	$FONT .=	"-$WEIGHT_NAME";
X	$FONT .=	"-$SLANT";
X	$FONT .=	"-$SETWIDTH_NAME";
X	$FONT .=	"-$ADD_STYLE_NAME";
X	$FONT .=	"-$PIXEL_SIZE";
X	$FONT .=	"-$POINT_SIZE";
X	$FONT .=	"-$RESOLUTION_X";
X	$FONT .=	"-$RESOLUTION_Y";
X	$FONT .=	"-$SPACING";
X	$FONT .=	"-$AVERAGE_WIDTH";
X	$FONT .=	"-$CHARSET_REGISTRY";
X	$FONT .=	"-$CHARSET_ENCODING";
X
X	local($FONTBOUNDINGBOX) = "$DWIDTHx $PIXEL_SIZE 0 -$FONT_DESCENT";
X
X	# print out the header
X
X	print "STARTFONT 2.1\n";
X	print "COMMENT $COMMENT\n";
X	print "FONT $FONT\n";
X	print "SIZE $PIXEL_SIZE $RESOLUTION_X $RESOLUTION_Y\n";
X	print "FONTBOUNDINGBOX $FONTBOUNDINGBOX\n";
X
X	print "STARTPROPERTIES 17\n";
X	print "FOUNDRY \"$FOUNDRY\"\n";				#  1
X	print "FAMILY_NAME \"$FAMILY_NAME\"\n";			#  2
X	print "WEIGHT_NAME \"$WEIGHT_NAME\"\n";			#  3
X	print "SLANT \"$SLANT\"\n";				#  4
X	print "SETWIDTH_NAME \"$SETWIDTH_NAME\"\n";		#  5
X	print "ADD_STYLE_NAME \"$ADD_STYLE_NAME\"\n";		#  6
X	print "PIXEL_SIZE $PIXEL_SIZE\n";			#  7
X	print "POINT_SIZE $POINT_SIZE\n";			#  8
X	print "RESOLUTION_X $RESOLUTION_X\n";			#  9
X	print "RESOLUTION_Y $RESOLUTION_Y\n";			# 10
X	print "SPACING \"$SPACING\"\n";				# 11
X	print "AVERAGE_WIDTH $AVERAGE_WIDTH\n";			# 12
X	print "CHARSET_REGISTRY \"$CHARSET_REGISTRY\"\n";	# 13
X	print "CHARSET_ENCODING \"$CHARSET_ENCODING\"\n";	# 14
X
X	print "DEFAULT_CHAR 0\n";				# 15
X	print "FONT_DESCENT $FONT_DESCENT\n";			# 16
X	print "FONT_ASCENT $FONT_ASCENT\n";			# 17
X	print "ENDPROPERTIES\n";
X
X	print "CHARS $n\n";
X	for($i = 0; $i < $n; $i++)
X	{
X		&writeBDF2_1char($i);
X	}
X	print "ENDFONT\n";
X}
X
X#-------
X# readDMD - Called with $_ set to the contents of a DMD font file.
X# Sets the intermediate variables.
X#
X# I imitate reading $_ by using $pos to keep track of the "current"
X# position in $_, and then using it as an unpack offset.
X#-------
Xsub readDMD
X{
X	local($pos)		= 0;	# offset into $_
X	local($nread);			# used in reading from $_
X	local($i);
X	local($x);
X
X	($n		# number of chars in font
X	,$height	# height of bitmap
X	,$ascent	# top of bitmap to baseline
X	,$unused	# in case we think of more stuff
X	)		= unpack("x$pos n c c N", $_);
X	$pos += 8;
X
X	#-------
X	# n+1 character descriptors
X	#
X	# read in $n+1 items, each 6 bytes
X	#
X	# @info is an array of the character descriptors
X	# @info_* are arrays of the values of the info fields.
X	#-------
X	$nread = 8;		# size of each structure
X				# (padded to 8 bytes, as it turns out)
X	for($i = 0; $i < $n+1; $i++)
X	{
X		$info[$i] = unpack("x$pos a$nread", $_);
X		$pos += $nread;
X
X		($info_x[$i]		# left edge of bits
X		,$info_top[$i]		# first non-zero scan-line
X		,$info_bottom[$i]	# last non-zero scan-line
X		,$info_left[$i]		# offset of baseline
X		,$info_width[$i]	# width of baseline
X		) =		unpack("n C C c C", $info[$i]);
X
X		#-------
X		# Make sure all characters are the same width.
X		#-------
X		if($width < 0)
X		{
X			$width = $info_width[$i];
X		}
X		elsif($info_width[$i] != 0 && $info_width[$i] != $width)
X		{
X			print "ERR: char $i is $info_width[$i] wide\n";
X		}
X	}
X
X	#-------
X	# dimensions of glyph bitmap in bits
X	#-------
X	local($Bwidth)	= $info_x[$n];
X	local($Bheight)	= $height;
X
X	#-------
X	# Bitmap is stored row by row
X	# Check that the width matches an integral number of bytes
X	#-------
X	#print "Bwidth          = $Bwidth\n";
X	if($Bwidth % 8 != 0)
X	{
X		# print "Bitmap width error???\n";
X		$Bwidth = int(($Bwidth + 7)/8) * 8;
X		#print "Bwidth adjusted-> $Bwidth\n";
X	}
X
X	#-------
X	# Check that the number of bytes remaining is what is required
X	# for the bitmap
X	#-------
X	local($bwidth)	= $Bwidth / 8;	# bytes per row
X	$x = length($_) - $pos;
X	if($bwidth * $Bheight != $x)
X	{
X		printf "expected bytes: %d\n", $bwidth * $Bheight;
X		printf "actual   bytes: %d\n", $x;
X		die "Bitmap space error???\n";
X	}
X
X	#-------
X	# Read in the bitmap.
X	#
X	# @row holds each row of the bitmap
X	#-------
X	$nread = $bwidth;
X	for($i = 0; $i < $Bheight; $i++)
X	{
X		$row[$i] = unpack("B*", unpack("x$pos a$nread", $_));
X		$pos += $nread;
X	}
X
X	if($pos != length($_))
X	{
X		die "internal Bitmap space error???\n";
X	}
X}
X
X#-------
X# DMDtoBDF - Called with $_ set to the contents of a DMD font file.
X#-------
Xsub DMDtoBDF
X{
X	#-------
X	# readDMD sets these variables
X	# writeBDF2_1 uses these variables
X	#
X	# The arrays are indexed from 0 .. $n.
X	# (the characters run from 0 .. $n-1).
X	#-------
X	local	($n		# number of chars in font
X		,$height	# height of bitmap
X		,$ascent	# top of bitmap to baseline
X		,$unused	# in case we think of more stuff
X
X		,@info_x	# left edge of bits
X		,@info_top	# first non-zero scan-line
X		,@info_bottom	# last non-zero scan-line
X		,@info_left	# offset of baseline
X		,@info_width	# width of baseline
X		);
X
X	local	($width)	= -1;	# width of font
X
X	&readDMD;
X	&writeBDF2_1;
X}
X
Xundef $/;	# slurp files whole
X
Xwhile(<>)
X{
X	&DMDtoBDF;
X}
END_OF_FILE
if test 10823 -ne `wc -c <'dmdtobdf.pl'`; then
    echo shar: \"'dmdtobdf.pl'\" unpacked with wrong size!
fi
# end of 'dmdtobdf.pl'
fi
if test -f 'dmdtobdf.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dmdtobdf.1'\"
else
echo shar: Extracting \"'dmdtobdf.1'\" \(1206 characters\)
sed "s/^X//" >'dmdtobdf.1' <<'END_OF_FILE'
X.\"-------
X.\" $RCSfile: dmdtobdf.1,v $$Revision: 1.1 $$Date: 1992/01/12 17:50:16 $
X.\"
X.\" dmdtobdf.1 - man page
X.\"
X.\" $Log: dmdtobdf.1,v $
X.\" Revision 1.1  1992/01/12  17:50:16  dws
X.\" Initial revision
X.\"
X.\"-------
X.TH DMDTOBDF 1 "12 Jan 1992"
X.SH NAME
Xdmdtobdf \- produce BDF font description for DMD fixed-width font
X.SH SYNOPSIS
X.B dmdtobdf
X.RB [ \-v ]
X.RI [ DMDfontfile ]
X.SH DESCRIPTION
X.I dmdtobdf 
Xallows you to use your favorite downloadable DMD fixed-width
Xterminal font on your X display.
XWhen given the DMD font file (either on stdin or named on the
Xcommand-line),
X.I dmdtobdf
Xwrites a corresponding BDF description of the font to stdout.
X.PP
XWhen the
X.B \-v
Xoption is supplied,
X.I dmdtobdf
Xwrites out a human-readable form of the glyph bitmaps
Xinstead of the hex-encoded BDF form.
X(This option is primarily for checking whether
X.I dmdtobdf
Xis reading the DMD font correctly.)
X.SH "SEE ALSO"
X.IR bdftosnf (1),
X.IR dxfc (1)
X(on DECstations),
X.IR xset (1)
X.SH BUGS
XMay not compute font metrics correctly.
XI welcome feedback on how to do it better.
XIn particular,
Xthe BDF and XLFD documents were not too clear on how
Xto derive SWIDTH values.
X.SH AUTHOR
XDaviD W. Sanderson (dws@cs.wisc.edu)
END_OF_FILE
if test 1206 -ne `wc -c <'dmdtobdf.1'`; then
    echo shar: \"'dmdtobdf.1'\" unpacked with wrong size!
fi
# end of 'dmdtobdf.1'
fi
echo shar: End of shell archive.
exit 0
-- 
DaviD W. Sanderson (dws@cs.wisc.edu)
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads