Browse Source

Added WIP ImageFont and AngelFont to mojo.

Mark Sibly 7 years ago
parent
commit
585210bd77

+ 196 - 0
modules/mojo/graphics/angelfont.monkey2

@@ -0,0 +1,196 @@
+Namespace mojo.graphics
+
+Private
+
+Function GetArg:String( name:String,args:String )
+	
+	Local i0:=args.Find( name+"=" )
+	If i0=-1 Return 0
+	
+	i0+=name.Length+1
+	
+	Local i1:=args.Find( " ",i0 )
+	If i1=-1 Return 0
+	
+	Return args.Slice( i0,i1 )
+End
+
+Function GetIntArg:Int( name:String,args:String )
+	
+	Return Int( GetArg( name,args ) )
+End
+		
+Public
+
+Class AngelFont Extends Font
+	
+	Method GetGlyph:Glyph( char:Int ) Override
+		
+		If char>=0 And char<_glyphs.Length Return _glyphs[char]
+		
+		Return _glyphs[0]
+	End
+	
+	Method GetGlyphPage:Image( char:Int ) Override
+
+		If char>=0 And char<_glyphs.Length Return _pages[ _glyphs[char].page ]
+		
+		Return _pages[0]
+	End
+	
+	Method GetKerning:Float( firstChar:Int,secondChar:Int ) Override
+		
+		If Not _kernings.Length Return 0
+		
+		Local min:=0,max:=_kernings.Length
+		
+		While max>min
+			
+			Local mid:=(min+max)/2
+			
+			If firstChar>_kernings[mid].first
+				min=mid+1
+			Else If firstChar<_kernings[mid].first
+				max=mid
+			Else If secondChar>_kernings[mid].second
+				min=mid+1
+			Else If secondChar<_kernings[mid].second
+				max=mid
+			Else
+				Return _kernings[mid].amount
+			Endif
+			
+		Wend
+		
+		Return 0
+	End
+	
+	Function Load:AngelFont( path:String,shader:Shader=Null,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
+		
+		If Not shader shader=Shader.Open( "font" )
+		
+		Local fnt:=LoadString( path,True )
+		If Not fnt
+			If Not ExtractRootDir( path ) fnt=LoadString( "font::"+path,True )
+			If Not fnt Return Null
+		Endif
+		
+		Local dir:=ExtractDir( path )
+		
+		Local lines:=fnt.Split( "~n" )
+		
+		Local pages:=New Stack<Image>
+		Local glyphs:=New Stack<Glyph>
+		Local kernings:=New Stack<Kerning>
+		
+		Local height:=0.0,minChar:=$ffff,maxChar:=0
+		
+		for Local i:=0 Until lines.Length
+			
+			Local line:=lines[i].Trim()
+			If Not line Continue
+			
+			Local i:=line.Find( " " )
+			If i=-1 Continue
+			
+			Local tag:=line.Slice( 0,i ).Trim()
+			Local args:=line.Slice( i+1 ).Trim()+" "
+			
+			Select tag
+			Case "common"
+				
+				height=GetIntArg( "lineHeight",args )
+				
+			Case "page"
+				
+				Local id:=GetIntArg( "id",args )
+				Local file:=GetArg( "file",args )
+				
+				Local fpath:=dir+file.Slice( 1,-1 )
+				
+				Local pixmap:=Pixmap.Load( fpath,PixelFormat.A8,True )
+				
+				Local image:=New Image( pixmap,textureFlags,shader )
+				
+				If id>=pages.Length pages.Resize( id+1 )
+					
+				pages[id]=image
+				
+			Case "char"
+				
+				Local id:=GetIntArg( "id",args )
+				Local x:=GetIntArg( "x",args )
+				Local y:=GetIntArg( "y",args )
+				Local w:=GetIntArg( "width",args )
+				Local h:=GetIntArg( "height",args )
+				Local tx:=GetIntArg( "xoffset",args )
+				Local ty:=GetIntArg( "yoffset",args )
+				Local advance:=GetIntArg( "xadvance",args )
+				Local page:=GetIntArg( "page",args )
+				Local chnl:=GetIntArg( "chnl",args )
+			
+				Local glyph:Glyph
+				glyph.rect=New Recti( x,y,x+w,y+h )
+				glyph.offset=New Vec2f( tx,ty )
+				glyph.advance=advance
+				glyph.page=page
+				
+				If id>=glyphs.Length glyphs.Resize( id+1 )
+					
+				glyphs[id]=glyph
+				
+				minChar=Min( id,minChar )
+				maxChar=Max( id,maxChar )
+				
+			Case "kerning"
+				
+				Local kerning:Kerning
+				kerning.first=GetIntArg( "first",args )
+				kerning.second=GetIntArg( "second",args )
+				kerning.amount=GetIntArg( "amount",args )
+				
+				kernings.Add( kerning )
+			End
+			
+		Next
+		
+		kernings.Sort( Lambda:Int( x:Kerning,y:Kerning )
+			If x.first<y.first Return -1
+			If x.first>y.first Return  1
+			If x.second<y.second Return -1
+			If x.second>y.second Return  1
+			Return 0
+		End )
+		
+'		Print "Kernings:"
+'		For Local k:=Eachin kernings
+'			Print "first="+k.first+" second="+k.second+" amount="+k.amount
+'		Next
+		
+		Local font:=New AngelFont( height,minChar,maxChar-minChar+1,glyphs.ToArray(),pages.ToArray(),kernings.ToArray() )
+		
+		Return font
+	End
+	
+	Private
+	
+	Field _glyphs:Glyph[]
+	Field _pages:Image[]
+	Field _kernings:Kerning[]
+	
+	Struct Kerning
+		Field first:Int
+		Field second:Int
+		Field amount:Int
+	End
+	
+	Method New( height:Float,firstChar:Int,numChars:Int,glyphs:Glyph[],pages:Image[],kernings:Kerning[] )
+		
+		Init( height,firstChar,numChars )
+		
+		_glyphs=glyphs
+		_pages=pages
+		_kernings=kernings
+	End
+
+End

+ 40 - 163
modules/mojo/graphics/font.monkey2

@@ -13,23 +13,7 @@ Struct Glyph
 	Field rect:Recti
 	Field offset:Vec2f
 	Field advance:Float
-
-	#rem monkeydoc Creates a new glyph.
-	#end
-	Method New( rect:Recti,offset:Vec2f,advance:Float )
-		Self.rect=rect
-		Self.offset=offset
-		Self.advance=advance
-	End
-
-End
-
-#rem monkeydoc @hidden
-#end
-Class GlyphPage
-
-	Field image:Image
-	Field glyphs:Glyph[]
+	Field page:Int
 
 End
 
@@ -43,183 +27,76 @@ Once a font is loaded it can be used with a canvas via the [[Canvas.Font]] prope
 
 #end
 Class Font Extends Resource
-
+	
 	#rem monkeydoc The font height in pixels.
 	#end
 	Property Height:Float()
 	
 		Return _height
 	End
-	
-	#rem monkeydoc Measures the width of some text when rendered by the font.
-	#end
-	Method TextWidth:Float( text:String )
-		Local w:=0.0
-		For Local char:=Eachin text
-			w+=GetGlyph( char ).advance
-		Next
-		Return w
-	End
 
-	#rem monkeydoc @hidden
-	
-	Gets the glyph page for a given char.
-	
-	Returns null if char does not have a glyph.
-	
-	#end	
-	Method GetGlyphPage:GlyphPage( char:Int )
-		Local page:=char Shr 8
-		If page<0 Or page>=_pages.Length Return Null
-		
-		Local gpage:=_pages[page]
-		If Not gpage Return Null
-		
-		If Not gpage.image OnLoadGlyphPage( page,gpage )
-				
-		Local index:=char & 255
-		If index>=gpage.glyphs.Length Return Null
+	#rem monkeydoc The first character in the font.
+	#end
+	Property FirstChar:Int()
 		
-		Return gpage
+		Return _firstChar
 	End
 	
-	#rem monkeydoc @hidden
-	
-	Gets the glyph for a given char.
-
+	#rem monkeydoc The number of characters in the font.
 	#end
-	Method GetGlyph:Glyph( char:Int )
-		Local page:=char Shr 8
-		If page<0 Or page>=_pages.Length Return _nullGlyph
-
-		Local gpage:=_pages[page]
-		If Not gpage Return _nullGlyph
-
-		If Not gpage.image OnLoadGlyphPage( page,gpage )
-				
-		Local index:=char & 255
-		If index>=gpage.glyphs.Length Return _nullGlyph
+	Property NumChars:Int()
 		
-		Return gpage.glyphs[index]
+		Return _numChars
 	End
 	
-	#rem monkeydoc Loads a font from a file.
-	
-	For the constructor with a `fontPath` parameter, the font must be a valid .ttf, .otf or .fon format font.
-		
-	For the constructor with an `imagePath` parameter, the font must be a valid image file containing a fixed size font with the characters laid out in left-to-right, top-to-bottom order.
-		
+	#rem monkeydoc Gets the glyph for a character.
 	#end
-	Function Load:Font( fontPath:String,height:Float,shader:Shader=Null,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
+	Method GetGlyph:Glyph( char:Int ) Abstract
+
+	#rem monkeydoc Gets the glyph page for a character.
+	#end
+	Method GetGlyphPage:Image( char:Int ) Abstract
 	
-		If Not shader shader=Shader.GetShader( "font" )
-		
-		Local font:=FreeTypeFont.Load( fontPath,height,shader,textureFlags )
-		If Not font And Not ExtractRootDir( fontPath ) font=FreeTypeFont.Load( "font::"+fontPath,height,shader,textureFlags )
-		
-		Return font
+	#rem monkeydoc Gets the kerning between 2 characters.
+	#end
+	Method GetKerning:Float( firstChar:Int,secondChar:Int ) Virtual
+		Return 0
 	End
-	
-	Function Load:Font( imagePath:String,charWidth:Int,charHeight:Int,firstChar:Int=32,numChars:Int=96,padding:Int=1,shader:Shader=Null,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
-		
-		Local pixmap:=Pixmap.Load( imagePath,Null,True )
-		
-		If Not pixmap And Not ExtractRootDir( imagePath )
-			pixmap=Pixmap.Load( "font::"+imagePath,Null,True )
-			If Not pixmap Return Null
-		Endif
-		
-		Local charsPerRow:=pixmap.Width/charWidth
-		Local numRows:=(numChars-1)/charsPerRow+1
-		
-		Local ipixmap:Pixmap
-		If padding
-			ipixmap=New Pixmap( charsPerRow*(charWidth+padding),numRows*(charHeight+padding),pixmap.Format )
-			ipixmap.Clear( Color.None )
-		Endif
-		
-		Local npages:=((firstChar+numChars-1) Shr 8)+1
-		
-		Local pages:=New GlyphPage[npages]
-		
-		Local page:GlyphPage,spos:=New Vec2i,gpos:=New Vec2i,gsize:=New Vec2i( charWidth,charHeight )
-		
-		For Local char:=firstChar Until firstChar+numChars
-			
-			If Not page Or (char & 255)=0
-				page=New GlyphPage
-				page.glyphs=New Glyph[256]
-				pages[char Shr 8]=page
-			Endif
-			
-			Local glyph:=New Glyph( New Recti( gpos,gpos+gsize ),Null,charWidth )
-			
-			page.glyphs[char&255]=glyph
-			
-			If ipixmap
-				Local src:=pixmap.Window( spos.x,spos.y,charWidth,charHeight )
-				ipixmap.Paste( src,gpos.x,gpos.y )
-			Endif
-			
-			spos.x+=charWidth
-			gpos.x+=charWidth+padding
-			If spos.x+charWidth>pixmap.Width
-				spos.y+=charHeight
-				gpos.y+=charHeight+padding
-				spos.x=0
-				gpos.x=0
-			Endif
-		Next
-		
-		If Not pages[0]
-			page=New GlyphPage
-			page.glyphs=New Glyph[1]
-			pages[0]=page
-		Endif
-		
-		pages[0].glyphs[0]=pages[firstChar Shr 8].glyphs[firstChar & 255]
+	#rem monkeydoc Measures the width of some text when rendered by the font.
+	#end
+	Method TextWidth:Float( text:String )
 		
-		Local image:=New Image( ipixmap ?Else pixmap,textureFlags,shader )
-		For Local page:=Eachin pages
-			page?.image=image
+		Local w:=0.0,lastChar:=0
+
+		For Local char:=Eachin text
+			w+=GetGlyph( char ).advance+GetKerning( lastChar,char )
+			lastChar=char
 		Next
 		
-		Local font:=New Font
-		
-		font.InitFont( charHeight,pages )
+		Return w
+	End
+
+	#rem monkeydoc Loads a font from a file.
+	#end
+	Function Load:Font( path:String,size:Float,shader:Shader=Null,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
 		
-		Return font
+		Return FreeTypeFont.Load( path,size,shader,textureFlags )
 	End
 	
 	Protected
 	
-	Method OnLoadGlyphPage( page:Int,gpage:GlyphPage ) Virtual
-	End
-	
-	Method InitFont( height:Float,pages:GlyphPage[] )
-	
-		_height=height
-		_pages=pages
+	Method Init( height:Float,firstChar:Int,numChars:Int )
 		
-		_nullGlyph=GetGlyph( 0 )
-	End
-	
-	Method OnDiscard() Override
-
-		For Local page:=Eachin _pages
-			If page.image page.image.Discard()
-		Next
-		
-		_pages=Null
+		_height=height
+		_firstChar=firstChar
+		_numChars=numChars
 	End
 	
 	Private
 	
 	Field _height:Float
-
-	Field _pages:GlyphPage[]
-	
-	Field _nullGlyph:Glyph
+	Field _firstChar:Int
+	Field _numChars:Int
 End
 
 Class ResourceManager Extension

+ 94 - 52
modules/mojo/graphics/freetypefont.monkey2

@@ -18,36 +18,94 @@ Public
 #rem monkeydoc @hidden
 #end
 Class FreeTypeFont Extends Font
+	
+	Method GetGlyph:Glyph( char:Int ) Override
+		
+		Local page:=char Shr 8
+		If page<0 Or page>=_pages.Length Return _nullGlyph
 
-	Function Load:FreeTypeFont( path:String,fheight:Float,shader:Shader,textureFlags:TextureFlags )
-	
-		Local ext:=ExtractExt( path )
-		If Not ext
-			Local font:=Load( path+".otf",fheight,shader,textureFlags )
-			If Not font font=Load( path+".ttf",fheight,shader,textureFlags )
-			If Not font font=Load( path+".fon",fheight,shader,textureFlags )
-			Return font
-		Endif
+		Local gpage:=_pages[page]
+		If Not gpage Return _nullGlyph
+
+		If Not gpage.image LoadGlyphPage( page,gpage )
+				
+		Local index:=char & 255
+		If index>=gpage.glyphs.Length Return _nullGlyph
+		
+		Return gpage.glyphs[index]
+	End
+	
+	Method GetGlyphPage:Image( char:Int ) Override
+		
+		Local page:=char Shr 8
+		If page<0 Or page>=_pages.Length Return Null
+		
+		Local gpage:=_pages[page]
+		If Not gpage Return Null
+		
+		If Not gpage.image LoadGlyphPage( page,gpage )
+				
+		Local index:=char & 255
+		If index>=gpage.glyphs.Length Return Null
+		
+		Return gpage.image
+	End
 	
+	Function Load:FreeTypeFont( path:String,height:Float,shader:Shader,textureFlags:TextureFlags )
+	
+		If Not shader shader=Shader.Open( "font" )
+		
 		If Not FreeType And FT_Init_FreeType( Varptr FreeType ) Return Null
 		
 		Local data:=DataBuffer.Load( path )
-		If Not data Return Null
+		If Not data
+			If Not ExtractRootDir( path ) data=DataBuffer.Load( "font::"+path )
+			If Not data Return Null
+		Endif
 		
 		Local face:FT_Face
-		If FT_New_Memory_Face( FreeType,data.Data,data.Length,0,Varptr face ) 
+		If FT_New_Memory_Face( FreeType,data.Data,data.Length,0,Varptr face )
 			data.Discard()
 			Return Null
 		Endif
 		
-		Local font:=New FreeTypeFont( data,face,fheight,shader,textureFlags )
+		Local font:=New FreeTypeFont( data,face,height,shader,textureFlags )
 		
 		Return font
 	End
 	
 	Protected
 	
-	Method OnLoadGlyphPage( page:Int,gpage:GlyphPage ) Override
+	Method OnDiscard() Override
+	
+		FT_Done_Face( _face )
+		
+		_data.Discard()
+		
+		_data=Null
+		_face=Null
+	End
+	
+	Private
+	
+	Class GlyphPage
+		Field image:Image
+		Field glyphs:Glyph[]
+	End
+	
+	Field _data:DataBuffer
+	Field _face:FT_Face
+	Field _shader:Shader
+	Field _textureFlags:TextureFlags
+	
+	Field _height:Int
+	Field _ascent:Int
+	
+	Field _pages:GlyphPage[]
+	
+	Field _nullGlyph:Glyph
+	
+	Method LoadGlyphPage( page:Int,gpage:GlyphPage )
 	
 		Const MaxTexWidth:=1024
 	
@@ -94,7 +152,7 @@ Class FreeTypeFont Extends Font
 		Local pixmap:=New Pixmap( texw,texh,PixelFormat.A8 )
 		pixmap.Clear( Color.None )
 	
-		Local glyphs:=New Glyph[numChars],nullGlyph:Glyph
+		Local glyphs:=New Glyph[numChars],glyph:Glyph,nullGlyph:Glyph
 		
 		tx=0;ty=0;maxh=0
 		
@@ -103,7 +161,7 @@ Class FreeTypeFont Extends Font
 			If i<0
 				If FT_Load_Char( _face,0,FT_LOAD_RENDER|FT_LOAD_FORCE_AUTOHINT ) FontError()
 			Else
-				If Not FT_Get_Char_Index( _face,firstChar+i ) Or FT_Load_Char( _face,firstChar+i,FT_LOAD_RENDER|FT_LOAD_FORCE_AUTOHINT ) 
+				If Not FT_Get_Char_Index( _face,firstChar+i ) Or FT_Load_Char( _face,firstChar+i,FT_LOAD_RENDER|FT_LOAD_FORCE_AUTOHINT )
 					glyphs[i]=nullGlyph
 					Continue
 				Endif
@@ -124,7 +182,9 @@ Class FreeTypeFont Extends Font
 			
 			tmp.Discard()
 			
-			Local glyph:=New Glyph( New Recti( tx,ty,tx+gw,ty+gh ),New Vec2f( slot->bitmap_left,_ascent-slot->bitmap_top ),slot->advance.x Shr 6 )
+			glyph.rect=New Recti( tx,ty,tx+gw,ty+gh )
+			glyph.offset=New Vec2f( slot->bitmap_left,_ascent-slot->bitmap_top )
+			glyph.advance=slot->advance.x Shr 6
 	
 			If i>=0 glyphs[i]=glyph Else nullGlyph=glyph
 	
@@ -138,28 +198,6 @@ Class FreeTypeFont Extends Font
 '		Print "Loading glyph page "+page+", image size="+gpage.image.Rect.Size
 	End
 	
-	Method OnDiscard() Override
-	
-		FT_Done_Face( _face )
-		
-		_data.Discard()
-		
-		_data=Null
-		_face=Null
-		_shader=Null
-		
-	End
-	
-	Private
-	
-	Field _data:DataBuffer
-	Field _face:FT_Face
-	Field _shader:Shader
-	Field _textureFlags:TextureFlags
-	
-	Field _height:Int
-	Field _ascent:Int
-	
 	Method New( data:DataBuffer,face:FT_Face,fheight:Float,shader:Shader,textureFlags:TextureFlags )
 		
 		_data=data
@@ -180,30 +218,34 @@ Class FreeTypeFont Extends Font
 		_height=(face->size->metrics.height+32) Shr 6
 		_ascent=(face->size->metrics.ascender+32) Shr 6
 
-		Local gindex:FT_UInt,nchars:=0
-		Local charcode:=FT_Get_First_Char( face,Varptr gindex )
+		Local gindex:FT_UInt
+		Local char:=FT_Get_First_Char( face,Varptr gindex )
+		Local minChar:=char,maxChar:=char,maxPage:=0
 		
-		Local pages:=New GlyphPage[256]
-		
-		Local maxpage:=0
+		_pages=New GlyphPage[256]
 		
 		While gindex
 		
-			Local page:Int=charcode Shr 8
-			
-			If page>=0 And page<pages.Length
+			Local page:Int=char Shr 8
 			
-				maxpage=Max( maxpage,page )
-
-				If Not pages[page] pages[page]=New GlyphPage
+			If page>=0 And page<_pages.Length And Not _pages[page]
+				
+				maxPage=Max( page,maxPage )
+				_pages[page]=New GlyphPage
 				
 			Endif
 			
-			charcode=FT_Get_Next_Char( face,charcode,Varptr gindex )
-
+			char=FT_Get_Next_Char( face,char,Varptr gindex )
+			
+			minChar=Min( char,minChar )
+			maxChar=Max( char,maxChar )
 		Wend
 		
-		InitFont( _height,pages.Slice( 0,maxpage+1 ) )
+		_pages=_pages.Slice( 0,maxPage+1 )
+		
+		Super.Init( _height,minChar,maxChar-minChar+1 )
+		
+		_nullGlyph=GetGlyph( 0 )
 	End
 	
 End

+ 93 - 0
modules/mojo/graphics/imagefont.monkey2

@@ -0,0 +1,93 @@
+Namespace mojo.graphics
+
+Using std.resource
+
+#rem monkeydoc @hidden The ImageFont class.
+#end
+Class ImageFont Extends Font
+	
+	Method New( pixmap:Pixmap,charWidth:Int,charHeight:Int,firstChar:Int=32,numChars:Int=96,padding:Int=1,shader:Shader=Null,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
+		
+		Local charsPerRow:=pixmap.Width/charWidth
+		Local numRows:=(numChars-1)/charsPerRow+1
+		
+		Local ipixmap:Pixmap
+		If padding
+			ipixmap=New Pixmap( charsPerRow*(charWidth+padding),numRows*(charHeight+padding),pixmap.Format )
+			ipixmap.Clear( Color.None )
+		Endif
+		
+		_glyphs=New Glyph[numChars]
+
+		Local spos:=New Vec2i,gpos:=New Vec2i,gsize:=New Vec2i( charWidth,charHeight )
+		
+		For Local i:=0 Until numChars
+			
+			Local char:=firstChar+i
+			
+			Local glyph:Glyph
+			glyph.rect=New Recti( gpos,gpos+gsize )
+			glyph.offset=Null
+			glyph.advance=charWidth
+			
+			_glyphs[i]=glyph
+			
+			If ipixmap
+				Local src:=pixmap.Window( spos.x,spos.y,charWidth,charHeight )
+				ipixmap.Paste( src,gpos.x,gpos.y )
+			Endif
+			
+			spos.x+=charWidth
+			gpos.x+=charWidth+padding
+			If spos.x+charWidth>pixmap.Width
+				spos.y+=charHeight
+				gpos.y+=charHeight+padding
+				spos.x=0
+				gpos.x=0
+			Endif
+			
+		Next
+
+		_page=New Image( ipixmap ?Else pixmap,textureFlags,shader )
+		
+		Init( charHeight,firstChar,numChars )
+	End
+	
+	Method GetGlyph:Glyph( char:Int ) Override
+		
+		char-=FirstChar
+		If char<0 Or char>=NumChars Return _glyphs[0]
+		
+		Return _glyphs[char]
+	End
+	
+	Method GetGlyphPage:Image( char:Int ) Override
+		
+		Return _page
+	End
+	
+	Function Load:ImageFont( path:String,charWidth:Int,charHeight:Int,firstChar:Int=32,numChars:Int=96,padding:Int=1,shader:Shader=Null,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
+		
+		Local pixmap:=Pixmap.Load( path,Null,True )
+		If Not pixmap
+			If Not ExtractRootDir( path ) pixmap=Pixmap.Load( "font::"+path,Null,True )
+			If Not pixmap Return Null
+		Endif
+
+		Local font:=New ImageFont( pixmap,charWidth,charHeight,firstChar,numChars,padding,shader,textureFlags )
+		
+		Return font
+	End
+		
+	Protected
+	
+	Method OnDiscard() Override
+		
+		_page.Discard()
+	End
+	
+	Private
+	
+	field _glyphs:Glyph[]
+	Field _page:Image
+End

+ 3 - 1
modules/mojo/mojo.monkey2

@@ -42,9 +42,11 @@ Using mojo..
 
 '2d graphics stuff
 #Import "graphics/canvas"
+#Import "graphics/image"
 #Import "graphics/font"
 #Import "graphics/freetypefont"
-#Import "graphics/image"
+#Import "graphics/imagefont"
+#Import "graphics/angelfont"
 #Import "graphics/shadowcaster"
 
 #Import "input/keyboard"