Author Topic: Variable Width Font?  (Read 304 times)

Lochlan

  • Sr. Member
  • ****
  • Posts: 408
Variable Width Font?
« on: September 23, 2014, 05:58:16 PM »
Have any of you tried implementing this in ASM or HuC?  Or for another (perhaps similar) platform?  I googled a bit and I think I understand the basic high-level concepts of variable width fonts, but I have no idea what an implementation would look like on PCE.  I'm looking for any places to start before I go digging.  Thanks!
I'm not sorry about this, as I'm not sorry about ANY attack by the goverrats.

ccovell

  • Hero Member
  • *****
  • Posts: 2245
Re: Variable Width Font?
« Reply #1 on: September 24, 2014, 02:38:08 AM »
"tepples" in the NES Dev world has made VWF code for the NES, I think.  Maybe he's released it under Creative Commons, as he's a fan of that thing.

Try doing a search for his name and VWF.

cabbage

  • Sr. Member
  • ****
  • Posts: 342
Re: Variable Width Font?
« Reply #2 on: September 24, 2014, 04:13:04 AM »
I made a proof-of-concept in HuC (screenshot attached) but didn't bother adding usefulness to it.

If you like, I can add some basic comments and upload the source, but really if you understand the theory behind VWF I'm sure you'll have little trouble writing a routine to suit your needs.

ccovell

  • Hero Member
  • *****
  • Posts: 2245
Re: Variable Width Font?
« Reply #3 on: September 24, 2014, 09:02:50 AM »
A VWF would be far more useful with sans-serif fonts to gain any advantage from it, as in that picture each character is almost the same width anyway.

Bonknuts

  • Hero Member
  • *****
  • Posts: 3292
Re: Variable Width Font?
« Reply #4 on: September 24, 2014, 10:56:02 AM »
Have any of you tried implementing this in ASM or HuC?  Or for another (perhaps similar) platform?  I googled a bit and I think I understand the basic high-level concepts of variable width fonts, but I have no idea what an implementation would look like on PCE.  I'm looking for any places to start before I go digging.  Thanks!


 It's pretty easy, once you get a solid understanding how it works for tile based systems. And the planar base system makes it easy as well.
Here's an example: ( starts @ 2:50 )

 You need to know a few things. 1) what the width for each character is. I create a width table for this, but you could technically check it on the fly (although that adds a good additional cpu resource). 2) have all your character left or right edge aligned. Since you're printing left to right, it's easiest to have them left edge aligned. I do this with no space - as in the single pixel column space follows it, but you can do it the other way too. Again, all this is prepped and done before assembling or compiling.

 The next thing you need to do is figure out the widest character of your set. This will determine if you need to write to a buffer of two consecutive tiles or more. If the largest character is 8 or less, then it won't span more than two tiles at ~any~ point. This is because the tile width is 8 pixels on the PCE. I usually keep all of my sets 8 pixels wide or less. It simplifies things.

 You need to do the same for height. Again, if you have any character taller than 8 pixels - you'll need to use another set of tiles below this. And you'll have to factor in line gap space. This can really complicate things if your tiles are slightly larger than 8 pixels tall, but have a line small line gap. This means you''ll need to either keep a line buffer in ram or read back vram to obtain the 'above' row of tiles for overlaying.  If that makes sense.

 The common method is to use only a smaller buffer in ram; 8x16 or 16x16. You usually don't buffer the whole line, because you're sequentially writing characters across the screen - one at a time. No need to constantly re-upload redundant parts of a line if it's already in vram. And like I mentioned earlier, for more complicated 'tall' characters and such - you can always read back the tiles you need to modify and then re-write them. It's slower, but still much faster than constantly reblitting a whole line for a single character updates.

 As for blitting or overlaying the characters, I use an internal counter to keep track of where I am in the buffer. If I start at a position of 0 (the left edge), and blit a 5 pixel wide character, I add 5 to the counter. If the counter is greater than 8 and I'm blitting another character, then I know to only blit it in the second tile of the buffer. I also check to see if the current position + the character to write is less than 16, if so then blit it. Else I need to reorder the buffer; I copy the contents of tile column #2 to tile column #1, and clear tile column #2. I AND off bits higher than $07 of the current position, and I increment the vram pointer to the next tile (not the next two tiles); I'm always writing two tile columns to vram, but I'm only incrementing by one tile on the vram pointer - on overflow.

 There is one other thing you need to take care of; line wrapping. You can either automatically check for this, or handled it via control codes in your script/text. Line wrapping is a problem for VWF, compared to FWF, because you could line wrap in a middle of a character. No good. So either check your line counter against the buffer pointer, along with the width of the current character to be written and clear the whole buffer and increment to the next tile set - or use a control code before the letter to write that does the same thing (clear the buffer, increment the vram tile position).

 Basically, in my example, I'm always writing two columns of tiles to vram. If encounter an 'overflow' past the second tile, I 'shift' everything over to the left and clear the right side and increment the vram pointer by one tile. Since my shift is exactly 8 pixels on each overflow, I just simply copy the right side to the left and clear the left; it's faster than achieves the same effect.

 I believe that's how it's typically done. But if not, it's how I do it. There are few details you need to take care of, but they depend on how you setup the text box/screen. But either way, you'll need a chunk of vram to act as a pseudo bitmap. And you'll have to clear this as well for new text strings or calls or similar, or do tilemap alterations if you plan to 'scroll' the text.

 If you want more complex features than that (like X/Y positioning at pixel resolution VS segmented buffer aligned resolution), then good luck with that or stick with FWF routine ;)
« Last Edit: September 24, 2014, 11:02:10 AM by Bonknuts »

Lochlan

  • Sr. Member
  • ****
  • Posts: 408
Re: Variable Width Font?
« Reply #5 on: September 25, 2014, 04:30:51 PM »
Thank you to everyone for your replies, and especially Bonknuts!  This is great information, time to hit my editor hard!

Quote from: cabbage link=topic=17745.msg372920#msg372920 date=1411571t584
If you like, I can add some basic comments and upload the source

Please do!  Thanks!
« Last Edit: September 25, 2014, 05:19:44 PM by Lochlan »
I'm not sorry about this, as I'm not sorry about ANY attack by the goverrats.