Proportional Font Routines

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: Proportional Font Routines

Post by uglifruit »

I can see the manual kerning route being sensible, actually. Then that asks different questions I suppose of how the text data is stored. If it's uncompressed there's a free 'bit' on each character to flag that it needs 'tucking in' one pixel (most common?). Then ctrl codes for anything less common (2 pixel, bigger gaps, etc).

I quite like that approach.
CLEAR 23855
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Proportional Font Routines

Post by Ast A. Moore »

Here’s an actual example of from the tutorial:

Code: Select all

	defm 1,"The CALL instruction places the address of the first char-",$d
	defm "acter of the string onto the stack, and our printer routine",$d
	defm "can simpl",2,-1,"y POP it from there.",0
Here, control code 1 means and indent (a preset value), $D means new line (the routine can automatically break words and create a new line, making sure it doesn’t cut a character midway, but the results are not rarely perfect), and 2 indicates kerning. What follows the 2 is the actual number of pixels to kern the next character left (negative values) or right (positive values). Zero is the end-of-string marker for the pinter routine.

Another control code (not shown in this example) is the text color. I normally only use it at the beginning of each paragraph, because of the color clash. However, if you carefully place your text, you can highlight different sections of it with different colors.

So, four control codes altogether. Adding more is not difficult but would impose extra overhead on processing each character of text in a string.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: Proportional Font Routines

Post by uglifruit »

Well, this is the fixed width version of my editor, that is now pretty well featured I think.

Image

Tap file

QAOP + M/Space to set pixels

W,S,9,0 to choose character (or N, to progress to the 'Next')

5,6,7,8 scrolls the screen

x clear editor

z revert to when you entered the character (undo)

c/v copy and paste

ENTER - two pages of preview text, in your font. 'e' edits the preview text on one of the screens.

T - changes the fixed width. This preview display uses 9 pixels per row, (which you can't alter, without a poke or two).

The font is stored at 61440. Exit to BASIC and SAVE "font" CODE 61440,768 if that's your thing (or just dump the memory from 61440)


I'm pleased with how this works. Simple, but quick and usable.
CLEAR 23855
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: Proportional Font Routines/editors!

Post by uglifruit »

Progress on this (which is all just a side project of me trying to make a new font for me ATTRibute graphics scroller).

I've now done two versions of the font editor:

1. A 'normal' font editor for editing 8x8 fixed width characters.
Image
Fixed Width Editor TAP file

2. A proportional font editor for editing 7x8 characters. The first byte of each character to store both the width and the +/- offset in the vertical direction for that letter. This means apostrophes can sit 'high', and commas (and letters with 'danglers') can be low (and it's quite possible to have fonts with a effective height of 9 or 10 pixels, all stored in the usual 768 bytes.

Image
Proportional Font Editor TAP file

Both there editors have now the following new commands:

R - 'rotate' letters (Rotating proportional 7x8 characters corrupts the data byte, but it's easy enough to K/L U/D to correct it)
CAPS+R - rotate ALL letters
F - flip a letter horizontally
CAPS+C - copies the system font to 61440 be edited by the user

Plus other keys:

Q,A,O,P with M/Space to toggle pixels
W,S,9,0 to choose the character you're editing (or N, to progress to the 'Next') - note there is no 'store' button. If you change it ... you change it!
5,6,7,8 scrolls the screen (left,down,up,right)
X clear current character
Z revert to when you first selected the character you're editing (a kind of brutal undo, to account for the lack of 'store')
C/V copy and paste (the copy paste buffer is shown)
ENTER - toggles two pages of preview text, in your font. This text isn't updated automatically in the new font, so press 'Enter' to check how it's looking.
CAPS+Q - exit to basic
E - edit the preview text

T - changes the fixed width of the fixed font *(only in the fixed font editor)
T - changes the fixed height (linespacing) of the font, in the preview window *(only in the proportional font editor)

These keys are exclusive to the proportional font editor
K/L - change the width of individual characters on the proportional font editor
U/D - changes the vertical offset up/down of individual characters on the proportional font editor

Most of the keys are shown on the screen.
The edited font is stored at 61440. Exit to BASIC and SAVE "font" CODE 61440,768 (or dump the memory from 61440)
M/c resides at 32768

At some point I'll bundle them together with some fonts on a TXZ file, and a BASIC loader and routine to saving/loading fonts to round the thing off and call it 'complete'. But these are definitely pretty much done now.


I've then been looking at storing the data that the proportional font can be printed with, and I've made a proportional printing routine (currently 322 bytes) that supports:

CHR$13 - carriage return
CHR$14 - new indented paragraph
CHR$15 - 'TAB' to four different positions (like PRINT, in BASIC - but with four positions)
theres also CHR$ codes to push the print position left/right/up/down by various amounts.

The thing I'm most pleased with is storing the data though for kerning one pixel to the left (the most common thing I'd use), to stop the data having unnecessary bloat with CTRL codes, if a character is stored 'inverted' (so 128+its normal ascii value) it is pushed kerned one pixel tighter to the left. (eg defb "A Useful T",128+"o","ol.") might be used to tuck the first 'o' slightly under the 'T'.)

I started doing 'word wrap' but with the kerning it became a pain to calculate when it was needed, and I'm envisaging this is more for hand tweaked 'text' based output, rather than variable things, so word-wrapping would makes 1.larger and 2.slower which are things I'm trying to avoid.

Here are some screenshots of me testing the print routine with proportional fonts I've been made:

Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Last edited by uglifruit on Wed Feb 26, 2020 2:51 pm, edited 1 time in total.
CLEAR 23855
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: Proportional Font Routines

Post by uglifruit »

And a few more...
Image

Image

Image

Image

(I know these are not the most exciting screenshots you'll see this week)!
CLEAR 23855
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: Proportional Font Routines

Post by uglifruit »

Another boring screenshot alert.

This shows the print routine just doing it's thing, but some of the characters have be kerned one-pixel to the left - but without increasing the data size at all. Characters to be pushed left one pixel are stored with bit 7 set.

Image
LEFT HAND SIDE, has hand kerned data. RIGHT HAND SIDE doesn't. (Notice the improvement on the capital letters).

Maybe it's a subtle difference that interests no-one else, but as an aesthetic improvement I think it's worth having (especially as it costs nothing to the data size).

The data does end up looking like this, though:

Code: Select all

defb    "H","e"+128,"re'",128+"s"," a d",128+"e","mo of a P",128+"R","O",128+"P","ORT",128+"I",128+"O","N",128+"A","L PRI",128+"N","T",128+"I",128+"N",128+"G",13
CLEAR 23855
Post Reply