freetypefont.bmx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. SuperStrict
  2. Module BRL.FreeTypeFont
  3. ModuleInfo "Version: 1.12"
  4. ModuleInfo "Author: Simon Armstrong, Mark Sibly"
  5. ModuleInfo "License: zlib/libpng"
  6. ModuleInfo "Copyright: Blitz Research Ltd"
  7. ModuleInfo "Modserver: BRL"
  8. ModuleInfo "History: 1.12"
  9. ModuleInfo "History: Added support for loading fonts from TBanks."
  10. ModuleInfo "History: 1.11"
  11. ModuleInfo "History: Added support for loading fonts from streams."
  12. ModuleInfo "History: 1.10"
  13. ModuleInfo "History: Module is now SuperStrict"
  14. ModuleInfo "History: 1.09 Release"
  15. ModuleInfo "History: Offset glyph rect to allow for smooth font border"
  16. ModuleInfo "History: 1.08 Release"
  17. ModuleInfo "History: Fixed freetypelib being reopened per font"
  18. ModuleInfo "History: 1.07 Release"
  19. ModuleInfo "History: Added one pixel blank border around SMOOTHFONT glyphs for ultra smooth subpixel positioning."
  20. ModuleInfo "History: 1.06 Release"
  21. ModuleInfo "History: Fixed memory (incbin::) fonts"
  22. ModuleInfo "History: 1.05 Release"
  23. ModuleInfo "History: Improved unicode support"
  24. ModuleInfo "History: Replaced stream hooks with New_Memory_Face"
  25. ModuleInfo "History: 1.04 Release"
  26. ModuleInfo "History: Added stream hooks"
  27. Import BRL.Font
  28. Import BRL.Pixmap
  29. Import Pub.FreeType
  30. Import BRL.Bank
  31. Private
  32. Function PadPixmap:TPixmap( p:TPixmap )
  33. Local t:TPixmap=TPixmap.Create( p.width+2,p.height+2,p.format )
  34. MemClear t.pixels,Size_T(t.capacity)
  35. t.Paste p,1,1
  36. Return t
  37. End Function
  38. Public
  39. Type TFreeTypeGlyph Extends TGlyph
  40. Field _pixmap:TPixmap
  41. Field _advance:Float,_x:Int,_y:Int,_w:Int,_h:Int
  42. Field _index:Int
  43. Method Pixels:TPixmap() Override
  44. If _pixmap Return _pixmap
  45. Return _pixmap
  46. End Method
  47. Method Advance:Float() Override
  48. Return _advance
  49. End Method
  50. Method GetRect( x:Int Var,y:Int Var,w:Int Var,h:Int Var ) Override
  51. x=_x
  52. y=_y
  53. w=_w
  54. h=_h
  55. End Method
  56. Method Index:Int() Override
  57. Return _index
  58. End Method
  59. End Type
  60. Type TFreeTypeFont Extends BRL.Font.TFont
  61. Field _ft_face:Byte Ptr
  62. Field _style:Int,_height:Int
  63. Field _ascend:Int,_descend:Int
  64. Field _glyphs:TFreeTypeGlyph[]
  65. Field _buf:Byte[]
  66. Method Delete()
  67. FT_Done_Face _ft_face
  68. End Method
  69. Method Style:Int() Override
  70. Return _style
  71. End Method
  72. Method Height:Int() Override
  73. Return _height
  74. End Method
  75. Method CountGlyphs:Int() Override
  76. Return _glyphs.length
  77. End Method
  78. Method CharToGlyph:Int( char:Int ) Override
  79. Return FT_Get_Char_Index( _ft_face,ULongInt(char) )-1
  80. End Method
  81. Method FamilyName:String()
  82. return bmx_freetype_Face_family_name(_ft_face)
  83. End Method
  84. Method StyleName:String()
  85. return bmx_freetype_Face_style_name(_ft_face)
  86. End Method
  87. Method LoadGlyph:TFreeTypeGlyph( index:Int ) Override
  88. Local glyph:TFreeTypeGlyph=_glyphs[index]
  89. If glyph Return glyph
  90. glyph=New TFreeTypeGlyph
  91. glyph._index=index
  92. _glyphs[index]=glyph
  93. If FT_Load_Glyph( _ft_face,UInt(index+1),FT_LOAD_RENDER ) Return glyph
  94. Local _slot:Byte Ptr = bmx_freetype_Face_glyph(_ft_face)
  95. Local width:Int = bmx_freetype_Slot_bitmap_width(_slot)
  96. Local rows:Int = bmx_freetype_Slot_bitmap_rows(_slot)
  97. Local pitch:Int = bmx_freetype_Slot_bitmap_pitch(_slot)
  98. Local advancex:Int = bmx_freetype_Slot_advance_x(_slot)
  99. Local buffer:Byte Ptr = bmx_freetype_Slot_bitmap_buffer(_slot)
  100. glyph._x=bmx_freetype_Slot_bitmapleft(_slot)
  101. glyph._y=-bmx_freetype_Slot_bitmaptop(_slot)+_ascend
  102. glyph._w=width
  103. glyph._h=rows
  104. glyph._advance=advancex Sar 6
  105. If width=0 Return glyph
  106. Local pixmap:TPixmap
  107. If bmx_freetype_Slot_bitmap_numgreys(_slot)
  108. pixmap=TPixmap.CreateStatic( buffer,width,rows,pitch,PF_A8 ).Copy()
  109. Else
  110. pixmap=CreatePixmap( width,rows,PF_A8 )
  111. Local b:Int
  112. For Local y:Int=0 Until rows
  113. Local dst:Byte Ptr=pixmap.PixelPtr(0,y)
  114. Local src:Byte Ptr=buffer+y*pitch
  115. For Local x:Int=0 Until width
  116. If (x&7)=0 b=src[x/8]
  117. If b & $80 dst[x]=$ff Else dst[x]=0
  118. b:+b
  119. Next
  120. Next
  121. EndIf
  122. If _style & SMOOTHFONT
  123. glyph._x:-1
  124. glyph._y:-1
  125. glyph._w:+2
  126. glyph._h:+2
  127. pixmap=PadPixmap(pixmap)
  128. EndIf
  129. glyph._pixmap=pixmap
  130. Return glyph
  131. End Method
  132. Method LoadGlyphs:TGlyph[]( text:String )
  133. Throw "Not supported"
  134. End Method
  135. Function Load:TFreeTypeFont( src:Object,size:Float,style:Int )
  136. Local buf:Byte[]
  137. Local ft_face:Byte Ptr = LoadFace(src, size, style, buf)
  138. If Not ft_face Then
  139. Return Null
  140. End If
  141. Local ft_size:Byte Ptr = bmx_freetype_Face_size(ft_face)
  142. Local font:TFreeTypeFont=New TFreeTypeFont
  143. font._ft_face=ft_face
  144. font._style=style
  145. font._height=bmx_freetype_Size_height(ft_size) Sar 6
  146. font._ascend=bmx_freetype_Size_ascend(ft_size) Sar 6
  147. font._descend=bmx_freetype_Size_descend(ft_size) Sar 6
  148. font._glyphs=New TFreeTypeGlyph[bmx_freetype_Face_numglyphs(ft_face)]
  149. font._buf=buf
  150. Return font
  151. End Function
  152. Function LoadFace:Byte Ptr( src:Object,size:Float,style:Int, buf:Byte[] Var )
  153. Global ft_lib:Byte Ptr
  154. If Not ft_lib
  155. If FT_Init_FreeType( Varptr ft_lib ) Return Null
  156. EndIf
  157. Local ft_face:Byte Ptr
  158. If TStream(src) Then
  159. Local stream:TStream = TStream(src)
  160. Local data:Byte[1024 * 90]
  161. Local dataSize:Int
  162. While Not stream.Eof()
  163. If dataSize = data.length
  164. data = data[..dataSize * 3 / 2]
  165. EndIf
  166. dataSize :+ stream.Read( (Byte Ptr data) + dataSize, data.length - dataSize )
  167. Wend
  168. If dataSize <> data.length
  169. data = data[..dataSize]
  170. EndIf
  171. If Not data.length Then
  172. Return Null
  173. End If
  174. buf = data
  175. If FT_New_Memory_Face( ft_lib, buf, LongInt(buf.length), 0, Varptr ft_face )
  176. Return Null
  177. EndIf
  178. Else If TBank(src) Then
  179. If Not TBank(src).Size() Then
  180. Return Null
  181. End If
  182. Local data:Byte Ptr = TBank(src).Lock()
  183. buf = New Byte[TBank(src).Size()]
  184. MemCopy(buf, data, TBank(src).Size())
  185. TBank(src).UnLock()
  186. If FT_New_Memory_Face( ft_lib, buf, LongInt(buf.length), 0, Varptr ft_face )
  187. Return Null
  188. EndIf
  189. Else If String(src) Then
  190. Local filename:String = String(src)
  191. If filename.Find( "::" )>0
  192. buf=LoadByteArray( filename )
  193. If Not buf.length Return Null
  194. If FT_New_Memory_Face( ft_lib,buf,LongInt(buf.length),0,Varptr ft_face )
  195. Return Null
  196. EndIf
  197. Else
  198. If FT_New_Face( ft_lib,filename,0,Varptr ft_face ) Return Null
  199. EndIf
  200. Else
  201. Return Null
  202. End If
  203. ' Freetype's char height is "FreeType 26.6 Fixed-Point"
  204. ' -> 26 bit for the integer part, 6 bit for the decimal places
  205. ' -> "64" equals to 1.0 in floating point numbers
  206. ' So the module only support fractional sizes with a detail of 1/64
  207. While size
  208. 'default DPI is 72 (setting 0,0 will use that)
  209. If Not FT_Set_Char_Size( ft_face, 0, LongInt(size * 64), 0,0 ) Then Exit
  210. ' If it failed, ensure to use only integer sizes now
  211. ' (eg. a bitmap font was tried to get loaded)
  212. ' First try will be the next integer (10.5 -> 10)
  213. size = Ceil(size) - 1
  214. Wend
  215. If Not size
  216. FT_Done_Face ft_face
  217. Return Null
  218. EndIf
  219. Return ft_face
  220. End Function
  221. End Type
  222. Type TFreeTypeFontLoader Extends TFontLoader
  223. Method LoadFont:TFreeTypeFont( url:Object,size:Float,style:Int ) Override
  224. Return TFreeTypeFont.Load( url,size,style )
  225. End Method
  226. End Type
  227. AddFontLoader New TFreeTypeFontLoader