Author Topic: Variable Width Bitmap Font Help  (Read 6552 times)

0 Members and 2 Guests are viewing this topic.

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Variable Width Bitmap Font Help
« on: February 02, 2012 »
In my learning about bitmap fonts and how to lay them out in ascii order as well as a grid pattern with all the same size character width and height, I wanted to see if I could do a variable width bitmap font.

As you can see by the code and the binary, I got it working as I wanted. I know this isn't the best way in doing it, but for an initial test, I got it to work proper.

The main character grids are 64x64px, but like the letter ! and I etc, I only have them at width 19px (background colour is not drawn), starting at the utmost left/top border of the characters 64x64px grid. I then feed this 19px into the scroller routine to only jump the 19px instead of the full 64px, then also run the same loop (for some reason the XJ variable wouldn't parse into the draw routine) for the draw routine.

As I said, this works great. Seeing my screen is 640px wide. so 640/64 = 10 characters on screen at any one time... but now seeing I have the width varied, I need to use the lowest width available which is 19px. so 640/19 = 34 (rounded) chars on screen at any one time + 1 for rendering off screen, so I set this to 35 chars.

I did this in case I end up doing a text of 'oh yeh!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" for eg. hehe, so it wouldn't pre blit/render directly on screen which looked ugly. So in the attempt to do it, if most of my chars are 64px wide, then i'ts pre rendering 25 chars off screen, not 1.

Question..

Is there a way to calc whats already on screen pixel wise on the X res, as the chars are variable width, so I only pre render 1 char off screen on the right instead of 25?

Is there a better way/loop/whatever that I can do this character checking based on render-able pixel width in the bitmap than what I have done in code already?

I'm sure this has been done 10001 times before, but being a newbie, this is... well, all new to me ;P

Thanks in advance.

Bin + Source attached.

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1292
  • Karma: 466
    • View Profile
    • my stuff
Re: Variable Width Bitmap Font Help
« Reply #1 on: February 02, 2012 »
Can't you just draw the part of the character that's actually required?


Challenge Trophies Won:

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #2 on: February 02, 2012 »
@hellfie, probably could, that's why I asked :)

Not sure who here has dealt with a variable width bitmap font before, but any help/insight is appreciated.

At the moment it just takes the full 64x64 block of character and then eliminates the background colour, then I set the width based on the printable character into variable XJ.

Offline Raizor

  • Founder Member
  • Pentium
  • ********
  • Posts: 1154
  • Karma: 175
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #3 on: February 02, 2012 »
This topic might be relevant, I only had a quick scan.

Google often kicks up old threads on here when searching for something. It's often more effective than using the internal forum search. This came from a search for "freebasic variable width bitmap font" on Google.
raizor

Challenge Trophies Won:

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #4 on: February 02, 2012 »
@Raizor, thanks. I did search and stumble upon that post and did have a quick read of it. I then still wanted to post my own topic based on the brief test code I did (which works), but I wanted other more knowledgeable coders on here to give me heads up on if I actually did the method 'proper' so to speak, and if so or if not, how would one (or how would yourself do it) go about changing it up in loops to actually get the render-able widths 'on the fly' dependent on the character being represented instead of the full 64px by 64px character block being used.

Offline Raizor

  • Founder Member
  • Pentium
  • ********
  • Posts: 1154
  • Karma: 175
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #5 on: February 02, 2012 »
One way of doing it would be store store the widths of each character somewhere and look up the character details as you draw them. You could use the ASCII value of the character (32 / 0x20 for space) as a lookup.

I did something like this before. I had an array of 256 values and in each slot I store the width of the character with the corresponding ASCII value. So in array slot 32 you have the width of the space character, in slot 65 you have the width of the 'A' character etc.

Then, when you're drawing your characters for the scroller, get the corresponding ASCII value of the character - if we're drawing 'A', the value would be 65. Then get the width from the array by looking up the value in array slot 65. As you're drawing away, add the width of each character to a local variable so it keeps track of the total widths of all the characters you've drawn so far. This can serve as your X offset for the start position of the next character. Remember to add some space too, to stop the characters bunching up.

That's one approach. There are probably better ones ;)
raizor

Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #6 on: February 02, 2012 »
You could look into using types, I tend to use something like:

Code: [Select]
type gfx_buffer
  wwidth as integer
  height as integer
  pixels as uinteger ptr
end type

function create_gfx_buffer(byval w as integer,byval h as integer)as gfx_buffer ptr
  dim as gfx_buffer ptr buffer=new gfx_buffer
  buffer->wwidth=w
  buffer->height=h
  buffer->pixels=new uinteger[w*h]
  return buffer
end function

sub set_pixel(byval buffer as gfx_buffer ptr,_
                    byval x as integer,_
                    byval y as integer,_
                    byval argb as uinteger)
  if (x>=0)and(x<buffer->wwidth)and(y>=0)and(y<buffer->height) then
    buffer->pixels[x+y*buffer->wwidth]=argb
  end if
end sub

'something similar for get_pixel to read

'to use
dim as gfx_buffer ptr my_buffer=create_gfx_buffer(64,64)
set_pixel(my_buffer,x,y,colour)

this lets you create as many buffers you want of any sizes, even arrays of buffers of different sizes, and any routine that you write to draw or read from a buffer can be used with any other buffer too.
I've always found this to be extremely versatile, using them as textures and targets for 3d and you can set up the fb screenbuffer as one by pointing pixels to it instead of allocating the memory or it's perfect for tinyptc too.

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #7 on: February 04, 2012 »
@Stonemonkey.. thanks, but that's a lil' involved for me at the moment... me being a newbie and all.

@Raizor.. thanks...

At the moment I have it working, but since my char width varies from 19px upto 64px, I need to calculate the "number of chars" on screen at any one time via their pixels.

eg. !=19px, A=64px, so if i have !!!!!!!!!!AAAAA (10 chars !, 9 chars A on screen) then that means 19x10=190 and 64x9=576, 190+576=766px, but my screen is only 640 wide and my max char width is 64px, so 766-640 = 126-64px (so it renders offscreen) =62. Therefore its pre-rendering 62px that I don't want to.

If I set "SCROLLER1TEXT(SCP1,SD+332+SIN1,MID(ST1,TP1,14))" the number of chars on screen to 14 for eg. that means 14 characters of 64px = 896px, which is overdrawn by 192px (256-64), but if my text is all !!!, then its 14 characters of 19px = 266px, which then is greatly under drawn (374px+64px missing) and blits directly on screen which looks ugly.

What I'm trying to achieve at the moment is a variable in replacement to the number '14', which I'm having some difficulty doing at the moment. *facepalms*. It should be easy, but no. :/

I'm trying to add the widths of all the XJ additions, but XJ doesn't want to accumulate for some reason, so on debug all I don't see it adding together, I only see the XJ variable (pixel width) over an over for each char.

IDK, I'm a bit lost at the moment. Frustrated the sh*t outta me for a few hours. I know I can hard set the text on screen at once to 640/19+1=~35characters then I don't have any issues, but if its blitting characters 64px wide for a while, that means that 35 chars of 64px = 2240px and my screen is only 640px wide = 1536px overdrawn = bad = don't want that!

*End ramble, not sure if I made much sense, either way I needed to vent! but I still need to get this working the way I want.

Offline Raizor

  • Founder Member
  • Pentium
  • ********
  • Posts: 1154
  • Karma: 175
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #8 on: February 04, 2012 »
If you want to attach the project and files, I'll take a looksee.
raizor

Challenge Trophies Won:

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #9 on: February 04, 2012 »
@Raizor... much thanks again. As you can see in the code, I have the left border variable, so it blits offscreen -64+1 or -19+1, its the calculations for the right border (calulating how many pixels are on screen + XJ). I got a little bit further in my endeavors, but still stuck with the right border to make sure only 1 character does infact blit offscreen, not another 25 characters blit offscreen, or not enough blit onscreen. Trial and error... and frustration.

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #10 on: February 04, 2012 »
@Stonemonkey.. thanks, but that's a lil' involved for me at the moment... me being a newbie and all.
.......

That's ok, it takes a little bit of a leap to get into, it did for me. Once I took that leap though, it left me thinking that I'd been making things complicated for myself before. It's something to look into in your own time but don't think of it as something that's only for advanced programmers, the basic idea of types is really quite simple.

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #11 on: February 04, 2012 »
I'm all up for learning, thats why I joined up here on DBF as it was demo oriented, which I wanted to learn. I want to get the hang on tinyptc and 256 colour, timelines and loops, etc first then once I understand it more, I will move onto better things, like the code you suggested. But for now... I want to attempt this variable width bitmap font and get that adapted to suit tinyptc, sdl, opengl, etc etc.

I understand it's not the best method in doing a variable width bitmap font, I do understand the concept behind it all, but putting my thoughts into code is a lil' frustrating for me at the moment, as I'm still getting my head around all the different functions in FreeBasic and most is just trial and error, as well as checking out the code that I can find on here and other places that google provides me.

Again.... I really appreciate the help you all have given me so far, I just hope it wont stop due to my 1001 newbie questions.

And yes, I'm all up for better ways of doing code, loops, functions, blitting, etc etc etc. :) When it comes to my TCL and bash scripting, I tend to slap my thoughts down in text quickly before I forget them, get them running with debugging, then refine, redo code to make it quicker and better... same principal goes for coding, I push myself to learn better ways of doing things :) although I do have a big tendency to jump entirely in the deep end all the time. ;P

Offline Raizor

  • Founder Member
  • Pentium
  • ********
  • Posts: 1154
  • Karma: 175
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #12 on: February 04, 2012 »
@ttemper

I've had a go and attached the result to this post.

I've removed your old scroller code and added two new functions:

DoScroller - This is called each frame and draws the scroller to the screen. The position of each character in the scrolltext is calculated (using the current overall scroller offset [xOffset]). If the offset is within the horizontal bounds of the screen (with a 64 pixel padding of the screen at each side), then it's drawn.

GetCharStringWidth - This takes a single character (string) and returns the width of the corresponding character in the font. You could do away with this by pre-scanning the pixels in the font image and looking for a column of black/empty pixels to signify the end of a character, that would give you your font character offsets without having them hardcoded and also enable you to easily drop in new fonts. This is probably easier to do if all characters are on a single line (rather than split into rows as they are at present).

It seems to work ok. Things slow down a bit when there are a lot of thin characters on screen. This is because it's drawing more things in that frame update.  You probably want to do some work on the LFDRAWIMAGEDATA routine as this is doing a lot of intensive work for each pixel. You could do what Stonemonkey suggests and pre-process all the characters graphics and store them somewhere and then just blit/draw them from the store rather than doing all the complex pixel manipulation that's going on in LFDRAWIMAGEDATA at present. If you were to switch to OpenGL for the drawing in the future, that would certainly speed things up.

It would probably also be a good idea to use more meaningful variable names as this helps others understand the code (and you too when you come back to it after a break). Names like xxx, yyy, VLU, TT, Mong etc don't mean a lot. These may have come from someone else's code, but something to bear in mind :)

There's no sine stuff for the scroller at the moment, I didn't add anything like that in order to keep it simple and easy to follow.

Hope this helps.

Raizor
raizor

Challenge Trophies Won:

Offline ttemper

  • Amiga 1200
  • ****
  • Posts: 261
  • Karma: 7
    • View Profile
Re: Variable Width Bitmap Font Help
« Reply #13 on: February 05, 2012 »
@Raizor, wow that was quick. Much thanks... I will definitely cypher the code and see exactly how you have done it, I had a brief check and can understand what is going on, and with the notes... that helps also  ;D

With the scroller code, basically what I'm wanting to do is put together a "universal scroller structure" that I will use for all my future demos that I can adapt easily to any demo, fixed width or variable width charset, so that's why I want to concentrate on certain parts and get them proper before proceeding to the next challenge.

As for what Stonemonkey suggested, I think that is a great idea, but like I mentioned, a bit out of my knowledge at the moment, but I'm here to learn.

So yes, it does make sense to pre-process the bitmap charset graphics into its own buffer/array to make it less calculation when blitting, instead of all the "ok lets locate where letter J is on the bitmap graphic, then caclulate a 64x64 box, then only render the forground pixels, then calculate how wide it is" its just a "ok now where did I put letter J in memory, there it is... done" for each frame.

Some of the code structure is hard to decipher... and yeh I should put variable strings into proper 'terms/labels', something I will change my habits, so when I do get stuck, it's easier for you all to understand.

No need for sinewaves at the moment, that was just thrown in there for the hell of it.

Time to read over the code and understand what and how it processes it all. As for the LFDRAWIMAGEDATA routine... not real sure where to start in modifying it just yet.

Much much thanks again :)