Bitmap Font editor for CX using CX

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
Hi
Ive started my first tool for CX. Previously Ive only used fixed width fonts, so thought I would start to us Bitmap Fonts you can load using Font.Load
Not sure what tools other people use, but thought I should make a contribution with a tool, written in CX for CX

Obviously WIP
602
 

magic

Active Member
3rd Party Module Dev
3rd Party Tool Dev
Joined
Mar 5, 2018
Very interesting! At this moment, I use bmfont. It's ok but lack of many thing. I really hope a project like this
 

magic

Active Member
3rd Party Module Dev
3rd Party Tool Dev
Joined
Mar 5, 2018
No idea what features would be in your tool but it look interesting.
FYI 3d looking font look beautiful.
 

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
Before everyone jumps to conclusions, the initial scope of this project is to be able to import a font on png and then set the width,height,offsets and char width of each character.
The tools hasnt built these fonts (yet) ;-)

Once the above is done, I can then look at a font builder. I have ideas. The main gotcha is the lack of official save PNG. I want the tool to be CX native, which means I will have to build a savePNG function
 
Last edited:

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
Latest hurdles to jump through... any help would be appriciated.
  1. Loading a PNG thats not in the app path. Does image.Load() work for files returned by RequestFile()?
  2. TTF file formats.... dont think TTF can be loaded using OpenGL
  3. SavePNG. No such thing as an uncompressed PNG (unlike BMP). I would have to plug into a 3rd party lib to create this. I'm also assuming I will have the same issue with paths
 

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
Reading more into the PNG implementation, it looks like there is an uncompressed section for DEFLATE.
 

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
After playing with Saving PNG all day (Ive hit a brick wall with that), I decided to tackle the first issue
Loading a PNG thats not in the app path. Does image.Load() work for files returned by RequestFile()?
This was an easy fix with KludgePath.. not sure if this should be offical or not. I added a line for full windows paths to be compiled for GLFW
Cerberus X:
Function KludgePath:String( path:String )
    If path.StartsWith( "." ) Or path.StartsWith( "/" ) Return path
    Local i:=path.Find( ":/" )
    If i<>-1 And path.Find("/")=i+1 Return path
#If TARGET="glfw"
    ' check for windows drive in path
    If path.Find( ":\" )=1 Return path
#end
    Return "cerberus://data/"+path
End
PS love the Function name ;-)
 

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
Look into the fonttool sources of the Vortex modules.
Hi, so ive been trying to get htis working with no luck at all. I did notice the stb-image-write.h and stb-truetype.h is used in vortex.
These are already included in the glfw target distribution but I dont know how to use them.

I tried creating my own module with stb-image-write.h, but it errors as the the scope is badly defined as headers arent pre-called. If I try to remedy this, my cpp code says it cant find the std-image.write.h include.

Also, not sure how to reference the ones already included in the glfw target.

Sadly this has slowed down development. Any help here would be appreciated,
thank you
 

MikeHart

Administrator
Joined
Jun 19, 2017
Location
Germany
I will see what i can do over the weekend. I got ttf loading some months ago so i can definitely share this.
Writing pngs, will see what i can find.
 

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
I will see what i can do over the weekend. I got ttf loading some months ago so i can definitely share this.
Writing pngs, will see what i can find.
At the mo, saving a PNG could open up more opportunities. I could add it to my trans to save android icon files as well (instead of using imagemagik)
I might have another look later during lunch
Thank you!
 

Rich

Active Member
3rd Party Module Dev
Joined
Sep 9, 2017
I will see what i can do over the weekend. I got ttf loading some months ago so i can definitely share this.
Writing pngs, will see what i can find.
So far this is what i have...
main application snippet
Code:
Import png
SavePng("test.png",cnvs)
png.cxs:
Import brl.databuffer
Import mojo2.graphics

Import "png.cpp"

Function SavePNG(file:String,cnvs:Canvas)
    Local db:DataBuffer = New DataBuffer(cnvs.Width()*cnvs.Height()*4)
    cnvs.ReadPixels(0,0,cnvs.Width(),cnvs.Height(),db)
    
    _savepng(file,cnvs.Width(),cnvs.Height(),db)
End

Extern
Function _savepng:void(file:String, w:Int, h:Int, db:DataBuffer)
png.cpp:
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb-image-write.h"

void _savepng(fchar const *filename, int w, int h, const void *data) {
    stbi_write_png(file:String, w:Int, h:Int, 4, db:DataBuffer, 0)
}
Issues with the above:
It cant find stb-image-write.h no matter what path i put in. I have even included it my module and it cant find it. Line: #include "stb/stb-image-write.h"
stbi_write_png requires a *char pointer, but _data is private in DataBuffer()

Ive tried to code it so that png.cxs calls stb_write_image without a wrapper cpp file, but it errors as the scopr is incorrect (I havent referenced the function before calling it)
 

MikeHart

Administrator
Joined
Jun 19, 2017
Location
Germany
Ok, here it goes:

SavePng.cxs:
Strict

' Simple mojo2 script.

' Import the mojo framework
Import mojo2
Import png



'*******************************************************************   
' Define the myClass that extends the App Class.   
Class myClass Extends App
    Field canvas:Canvas
    '---------------------------------------------------------------
     ' The OnCreate Method inside the App class is always called at the start of your app.
     ' It is a perfect place to load resources into your app.
    Method OnCreate:Int()
        ' By setting the update rate to 0, there will be always an OnRender call after OnUpdate. No matter how long it takes.
        ' It will also run as fast as your sync rate of your hardware runs.
        SetUpdateRate(60)               
        canvas = New Canvas
        Return 0
    End
    
    '---------------------------------------------------------------
     ' The OnUpdate Method is called at the beginning of a new frame.
     ' The interval it is called depends on how you have set the update rate, which by default is set to 60 times a second.
     ' The mojo framework tries to make sure that it will be able to call OnUpdate this many times in a second. And if needed, skip
     ' calls to OnRender to reach the goal.
    Method OnUpdate:Int()
        If KeyHit(KEY_P)
            SavePNG("screen.png",canvas)
        Endif
        Return 0
    End
    
    '---------------------------------------------------------------
    ' The OnRender method will be called after the OnUpdate method.
    ' It is the place to draw your images or other visual elements. ~n
    Method OnRender:Int()
        ' Clear the canvas with a black color.
        canvas.Clear (0,0.5,0)   
        ' Now draw the multiple text lines. They need to be split into a strng array.
        canvas.DrawText( String("Cerberus X~nHello World!").Split("~n")),DeviceWidth()/2,DeviceHeight()/2,0.5,0.5
        ' Flush the canvas so it becomes visible.       
        canvas.Flush

        Return 0
    End
End

'---------------------------------------------------------------
' The Main function is the starting point of every Cerberus X app.
Function Main:Int()
    ' Create an instance of your class that you have defined above.
    New myClass       
    Return 0
End
png.cxs:
Import brl.databuffer
Import mojo2.graphics

Import "png.cpp"

Extern
Function _savepng:Void(file:String, w:Int, h:Int, db:DataBuffer)

Public

Function SavePNG:Void(file:String,cnvs:Canvas)
    'Print("width="+cnvs.Width()+"   height="+cnvs.Height())
    Local db:DataBuffer = New DataBuffer(cnvs.Width()*cnvs.Height()*4)
    cnvs.ReadPixels(0,0,cnvs.Width(),cnvs.Height(),db)
    'Print("length db="+db.Length())

    _savepng(file,cnvs.Width(),cnvs.Height(),db)
End
png.cpp:
static String::CString<char> C_STR( const String &t ){ return t.ToCString<char>(); };

void _savepng(String filename, int w, int h, BBDataBuffer *db) {
    std::vector<unsigned char> colorBuffer(w * h * 4, 255);
    int i;
    int i2;
    for (int x = 0; x < w; x++) {
        for (int y = 0; y < h; y++) {
            i = x + y*w;
            i2 = x + ((h-1)*w)-y*w;
            colorBuffer[i*4]   = db->PeekByte(i2*4); //Red
            colorBuffer[i*4+1] = db->PeekByte(i2*4+1); //Green
            colorBuffer[i*4+2] = db->PeekByte(i2*4+2); //Blue
            colorBuffer[i*4+3] = db->PeekByte(i2*4+3); // alpha
        }
    }
 
    stbi_write_png(C_STR(filename), w, h, 4, &colorBuffer[0], 0);
}

And finally, replace the glfw target with the one in the zip file I have attached. I had to link to the stb_image_write header inside the stb directory.

Maybe it could have worked, if you import the header file inside png.cxs too.
 

Attachments

Top Bottom