2
0

hbfreetypefont.bmx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. ' Copyright (c) 2024 Bruce A Henderson
  2. '
  3. ' Permission is hereby granted, free of charge, to any person obtaining a copy
  4. ' of this software and associated documentation files (the "Software"), to deal
  5. ' in the Software without restriction, including without limitation the rights
  6. ' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. ' copies of the Software, and to permit persons to whom the Software is
  8. ' furnished to do so, subject to the following conditions:
  9. '
  10. ' The above copyright notice and this permission notice shall be included in
  11. ' all copies or substantial portions of the Software.
  12. '
  13. ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. ' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. ' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. ' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. ' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. ' THE SOFTWARE.
  20. '
  21. SuperStrict
  22. Rem
  23. bbdoc: A font implementation that uses FreeType and HarfBuzz to render text.
  24. End Rem
  25. Module Text.HBFreeTypeFont
  26. ModuleInfo "CPP_OPTS: -std=c++11"
  27. ModuleInfo "CC_OPTS: -DHAVE_FREETYPE"
  28. ?linux
  29. ModuleInfo "CC_OPTS: `pkg-config --cflags freetype2`"
  30. ?
  31. Import "common.bmx"
  32. Private
  33. Function PadPixmap:TPixmap( p:TPixmap )
  34. Local t:TPixmap=TPixmap.Create( p.width+2,p.height+2,p.format )
  35. MemClear t.pixels,Size_T(t.capacity)
  36. t.Paste p,1,1
  37. Return t
  38. End Function
  39. Public
  40. Type THBFreeTypeFont Extends BRL.Font.TFont
  41. Field _ft_face:Byte Ptr
  42. Field _hb_font:Byte Ptr
  43. Field _style:Int
  44. Field _height:Int
  45. Field _ascend:Int
  46. Field _descend:Int
  47. Field _glyphs:TFreeTypeGlyph[]
  48. Field _buf:Byte[]
  49. Field _buffer:Byte Ptr
  50. Field _featuresLength:Int
  51. Field _features:Byte Ptr
  52. Field _glyphMap:TTreeMap<Int,SGlyphPosition> = New TTreeMap<Int,SGlyphPosition>
  53. Field _positionMap:TTreeMap<Int,SGlyphPosition> = New TTreeMap<Int,SGlyphPosition>
  54. Method Delete()
  55. bmx_hb_ft_font_destroy(_hb_font)
  56. bmx_hb_buffer_destroy(_buffer)
  57. bmx_hb_features_destroy(_features)
  58. FT_Done_Face _ft_face
  59. End Method
  60. Method Style:Int() Override
  61. Return _style
  62. End Method
  63. Method Height:Int() Override
  64. Return _height
  65. End Method
  66. Method CountGlyphs:Int() Override
  67. Return _glyphs.length
  68. End Method
  69. Method CharToGlyph:Int( char:Int ) Override
  70. Local info:SGlyphPosition
  71. If Not _glyphMap.TryGetValue(char, info) Then
  72. bmx_hb_buffer_calc_glyph_info(_hb_font, _buffer, _features, _featuresLength, char, info)
  73. _glyphMap.Add(char, info)
  74. _positionMap.Add(info.glyphIndex, info)
  75. End If
  76. Return info.glyphIndex
  77. End Method
  78. Method LoadGlyph:TFreeTypeGlyph( index:Int ) Override
  79. Local glyph:TFreeTypeGlyph=_glyphs[index]
  80. If glyph Return glyph
  81. glyph=New TFreeTypeGlyph
  82. _glyphs[index]=glyph
  83. If FT_Load_Glyph( _ft_face,UInt(index),FT_LOAD_RENDER ) Return glyph
  84. Local info:SGlyphPosition
  85. _positionMap.TryGetValue(index, info)
  86. BuildGlyph(glyph, info)
  87. Return glyph
  88. End Method
  89. Method BuildGlyph(glyph:TFreeTypeGlyph, info:SGlyphPosition)
  90. Local _slot:Byte Ptr = bmx_freetype_Face_glyph(_ft_face)
  91. Local width:Int = bmx_freetype_Slot_bitmap_width(_slot)
  92. Local rows:Int = bmx_freetype_Slot_bitmap_rows(_slot)
  93. Local pitch:Int = bmx_freetype_Slot_bitmap_pitch(_slot)
  94. Local advancex:Int = info.xAdvance
  95. Local buffer:Byte Ptr = bmx_freetype_Slot_bitmap_buffer(_slot)
  96. glyph._x=bmx_freetype_Slot_bitmapleft(_slot) + info.xOffset
  97. glyph._y=-bmx_freetype_Slot_bitmaptop(_slot)+_ascend + info.yOffset
  98. glyph._w=width
  99. glyph._h=rows
  100. glyph._advance=advancex Sar 6
  101. If width=0 Return
  102. If Not glyph._pixmap Then
  103. Local pixmap:TPixmap
  104. If bmx_freetype_Slot_bitmap_numgreys(_slot)
  105. pixmap=TPixmap.CreateStatic( buffer,width,rows,pitch,PF_A8 ).Copy()
  106. Else
  107. pixmap=CreatePixmap( width,rows,PF_A8 )
  108. Local b:Int
  109. For Local y:Int=0 Until rows
  110. Local dst:Byte Ptr=pixmap.PixelPtr(0,y)
  111. Local src:Byte Ptr=buffer+y*pitch
  112. For Local x:Int=0 Until width
  113. If (x&7)=0 b=src[x/8]
  114. If b & $80 dst[x]=$ff Else dst[x]=0
  115. b:+b
  116. Next
  117. Next
  118. EndIf
  119. If _style & SMOOTHFONT
  120. glyph._x:-1
  121. glyph._y:-1
  122. glyph._w:+2
  123. glyph._h:+2
  124. pixmap=PadPixmap(pixmap)
  125. EndIf
  126. glyph._pixmap=pixmap
  127. End If
  128. End Method
  129. Method LoadGlyphs:TGlyph[]( text:String )
  130. Local length:Int
  131. Local infos:SGlyphPosition Ptr = bmx_hb_buffer_calc_glyphs_info(_hb_font, _buffer, _features, _featuresLength, text, length)
  132. Local glyphs:TFreeTypeGlyph[] = New TFreeTypeGlyph[length]
  133. For Local i:Int = 0 Until length
  134. Local index:Int = infos[i].glyphIndex
  135. Local cachedGlyph:TFreeTypeGlyph = _glyphs[index]
  136. Local glyph:TFreeTypeGlyph = New TFreeTypeGlyph
  137. If cachedGlyph Then
  138. glyph._pixmap = cachedGlyph._pixmap
  139. End If
  140. glyphs[i] = glyph
  141. If FT_Load_Glyph( _ft_face,UInt(index),FT_LOAD_RENDER ) Continue
  142. BuildGlyph(glyph, infos[i])
  143. If Not cachedGlyph Then
  144. _glyphs[index] = glyph
  145. Else If Not cachedGlyph._pixmap Then
  146. cachedGlyph._pixmap = glyph._pixmap
  147. End If
  148. Next
  149. bmx_hb_buffer_calc_glyphs_info_destroy(infos)
  150. Return glyphs
  151. End Method
  152. Function Load:THBFreeTypeFont( src:Object,size:Float,style:Int )
  153. Local buf:Byte[]
  154. Local ft_face:Byte Ptr = TFreeTypeFont.LoadFace(src, size, style, buf)
  155. If Not ft_face Then
  156. Return Null
  157. End If
  158. Local ft_size:Byte Ptr = bmx_freetype_Face_size(ft_face)
  159. Local font:THBFreeTypeFont = New THBFreeTypeFont
  160. font._ft_face = ft_face
  161. font._hb_font = bmx_hb_ft_font_create(ft_face)
  162. font._style = style
  163. font._buf = buf
  164. font._buffer = bmx_hb_buffer_create()
  165. font._features = bmx_hb_ft_font_features(style, font._featuresLength)
  166. font._height=bmx_freetype_Size_height(ft_size) Sar 6
  167. font._ascend=bmx_freetype_Size_ascend(ft_size) Sar 6
  168. font._descend=bmx_freetype_Size_descend(ft_size) Sar 6
  169. font._glyphs=New TFreeTypeGlyph[bmx_freetype_Face_numglyphs(ft_face)]
  170. Return font
  171. End Function
  172. End Type
  173. Type THBFreeTypeFontLoader Extends TFontLoader
  174. Method LoadFont:THBFreeTypeFont( url:Object,size:Float,style:Int ) Override
  175. Return THBFreeTypeFont.Load( url,size,style )
  176. End Method
  177. End Type
  178. AddFontLoader New THBFreeTypeFontLoader