Font.monkey2 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. #Import "PoolMod"
  2. Private
  3. Global __Afont:AngelFont
  4. Public
  5. Function LoadAngelFont:AngelFont(url:String)
  6. Local font:AngelFont = New AngelFont()
  7. font.italicSkew = 0.15
  8. font.LoadFont(url)
  9. Return font
  10. End Function
  11. Function SetAngelFont:Void(font:AngelFont)
  12. __Afont = font
  13. End Function
  14. Function GetActiveFont:AngelFont()
  15. Return __Afont
  16. End
  17. Function ATextWidth:Int(str:String)
  18. Return __Afont.TextWidth(str)
  19. End Function
  20. Function AFontHeight:Int()
  21. If __Afont = Null RuntimeError("font not initialized")
  22. Return __Afont.height
  23. End function
  24. Function ATextHeight:Int(str:String)
  25. Return __Afont.TextHeight(str)
  26. End Function
  27. Function RenderText:Void(canvas:Canvas,txt:String,x:Float,y:Float)
  28. If __Afont = Null RuntimeError("font not initialized")
  29. __Afont.RenderText(canvas,txt,x,y)
  30. End Function
  31. Function GetChars:Char[]()
  32. If __Afont = Null RuntimeError("font not initialized")
  33. Return __Afont.chars
  34. End Function
  35. Class Char
  36. Field asc:Int
  37. Field x:Int
  38. Field y:Int
  39. Field width:Int
  40. Field height:Int = 0
  41. Field xOffset:Int = 0
  42. Field yOffset:Int = 0
  43. Field xAdvance:Int = 0
  44. Method New(x:Int,y:Int, w:Int, h:Int, xoff:Int=0, yoff:Int=0, xadv:Int=0)
  45. Self.x = x
  46. Self.y = y
  47. Self.width = w
  48. Self.height = h
  49. Self.xOffset = xoff
  50. Self.yOffset = yoff
  51. Self.xAdvance = xadv
  52. End
  53. Method Render(canvas:Canvas,fontImage:Image, linex:float,liney:Float)
  54. canvas.DrawRect(linex+xOffset,liney+yOffset,width,height,fontImage, x,y)
  55. End Method
  56. Method toString:String()
  57. Return String.FromChar(asc)+"="+asc
  58. End Method
  59. End Class
  60. Class KernPair
  61. Field first:String
  62. Field second:String
  63. Field amount:Int
  64. Method New(first:Int, second:Int, amount:Int)
  65. Self.first = first
  66. Self.second = second
  67. Self.amount = amount
  68. End
  69. #Rem
  70. Method toString:String()
  71. Return "first="+String.FromChar(first)+" second="+String.FromChar(second)+" amount="+amount
  72. End Method
  73. #End
  74. End Class
  75. Class AngelFont
  76. Private
  77. field _list:StringMap<AngelFont> = New StringMap<AngelFont>
  78. Field image:Image
  79. Field chars:Char[] = New Char[256]
  80. Field kernPairs:StringMap<KernPair> = New StringMap<KernPair>
  81. Field iniText:String
  82. Field xOffset:Int
  83. Field yOffset:Int
  84. Field prevMouseDown:Bool = False
  85. Public
  86. Const ALIGN_LEFT:Int = 0
  87. Const ALIGN_CENTER:Int = 1
  88. Const ALIGN_RIGHT:Int = 2
  89. Global error:String
  90. Field name:String
  91. Field useKerning:Bool = True
  92. Field lineGap:Int = 5
  93. Field height:Int = 0
  94. Field heightOffset:Int = 9999
  95. Field scrollY:Int = 0
  96. Field italicSkew:Float = 0.25
  97. Method New(url:String="")
  98. If url <> ""
  99. Self.LoadFont(url)
  100. Self.name = url
  101. _list.Add(url,Self)
  102. Endif
  103. End Method
  104. Method GetChars:Char[]()
  105. Return chars
  106. End
  107. Method LoadFont:Void(url:String)
  108. error = ""
  109. iniText = LoadString(url+".txt")
  110. Local lines:= iniText.Split(String.FromChar(10))
  111. For Local line:= Eachin lines
  112. line=line.Trim()
  113. If line.StartsWith("id,") Or line = "" Continue
  114. If line.StartsWith("first,")
  115. Continue
  116. Endif
  117. Local data:string[] = line.Split(",")
  118. For Local i:=0 Until data.Length
  119. data[i]=data[i].Trim()
  120. Next
  121. error += data.Length+"," '+"-"+line
  122. If data.Length > 0
  123. If data.Length = 3
  124. kernPairs.Add(String.FromChar(Int(data[0]))+"_"+String.FromChar(Int(data[1])), New KernPair(Int(data[0]), Int(data[1]), Int(data[2])))
  125. Else
  126. If data.Length >= 8
  127. chars[Int(data[0])] = New Char(Int(data[1]), Int(data[2]), Int(data[3]), Int(data[4]), Int(data[5]), Int(data[6]), Int(data[7]))
  128. Local ch := chars[Int(data[0])]
  129. If ch.height > Self.height Self.height = ch.height
  130. If ch.yOffset < Self.heightOffset Self.heightOffset = ch.yOffset
  131. Endif
  132. Endif
  133. Endif
  134. Next
  135. image = Image.Load(url+".png")
  136. End Method
  137. Method RenderItalic:Void(canvas:Canvas,txt:string,x:Float,y:Float)
  138. Local th:float=TextHeight(txt)
  139. canvas.PushMatrix()
  140. 'Transform 1,0,-italicSkew,1, x+th*italicSkew,y
  141. RenderText(canvas,txt,0,0)
  142. canvas.PopMatrix()
  143. End
  144. Method RenderBold:Void(canvas:Canvas,txt:String, x:Int, y:Int)
  145. RenderText(canvas,txt, x,y)
  146. RenderText(canvas,txt, x+1,y)
  147. End
  148. Method RenderText:Void(canvas:Canvas,txt:String, x:Int, y:Int)
  149. Local prevChar:String = ""
  150. xOffset = 0
  151. For Local i:= 0 Until txt.Length
  152. Local asc:Int = txt[i]
  153. Local ac:Char = chars[asc]
  154. Local thisChar:String = String.FromChar(asc)
  155. If ac <> Null
  156. If useKerning
  157. Local key:String = prevChar+"_"+thisChar
  158. If kernPairs.Contains(key)
  159. xOffset += kernPairs.Get(key).amount
  160. Endif
  161. Endif
  162. ac.Render(canvas,image, x+xOffset,y)
  163. xOffset += ac.xAdvance
  164. prevChar = thisChar
  165. Endif
  166. Next
  167. End Method
  168. Method RenderText:Void(canvas:Canvas,txt:String, x:Int, y:Int, align:Int)
  169. xOffset = 0
  170. Select align
  171. Case ALIGN_CENTER
  172. RenderText(canvas,txt,x-(TextWidth(txt)/2),y)
  173. Case ALIGN_RIGHT
  174. RenderText(canvas,txt,x-TextWidth(txt),y)
  175. Case ALIGN_LEFT
  176. RenderText(canvas,txt,x,y)
  177. End Select
  178. End Method
  179. Method RenderHTML:Void(canvas:Canvas,txt:String, x:Int, y:Int)
  180. Local prevChar:String = ""
  181. xOffset = 0
  182. Local italic:Bool = False
  183. Local bold:Bool = False
  184. Local th:Float=TextHeight(txt)
  185. For Local i:= 0 Until txt.Length
  186. While txt.Mid(i,1) = "<" '[i..i+1] = "<"
  187. Select txt.Mid(i+1,2) '[i+1..i+3]
  188. Case "i>"
  189. italic = True
  190. i += 3
  191. Case "b>"
  192. bold = True
  193. i += 3
  194. Default
  195. Select txt.Mid(i+1,3) '[i+1..i+4]
  196. Case "/i>"
  197. italic = False
  198. i += 4
  199. Case "/b>"
  200. bold = False
  201. i += 4
  202. End
  203. End
  204. If i >= txt.Length
  205. Return
  206. End
  207. Wend
  208. Local asc:Int = txt[i]
  209. Local ac:Char = chars[asc]
  210. Local thisChar:String = String.FromChar(asc)
  211. If ac <> Null
  212. If useKerning
  213. Local key:String = prevChar+"_"+thisChar
  214. If kernPairs.Contains(key)
  215. xOffset += kernPairs.Get(key).amount
  216. Endif
  217. Endif
  218. If italic = False
  219. ac.Render(canvas,image, x+xOffset,y)
  220. If bold
  221. ac.Render(canvas,image, x+xOffset+1,y)
  222. End
  223. Else
  224. canvas.PushMatrix()
  225. 'Transform 1,0,-italicSkew,1, (x+xOffset)+th*italicSkew,y
  226. ac.Render(canvas,image, 0,0)
  227. If bold
  228. ac.Render(canvas,image, 1,0)
  229. Endif
  230. canvas.PopMatrix()
  231. End
  232. xOffset += ac.xAdvance
  233. prevChar = thisChar
  234. Endif
  235. Next
  236. End Method
  237. Method RenderHTML:Void(canvas:Canvas,txt:String, x:Int, y:Int, align:Int)
  238. xOffset = 0
  239. Select align
  240. Case ALIGN_CENTER
  241. RenderHTML(canvas,txt,x-(TextWidth(StripHTML(txt))/2),y)
  242. Case ALIGN_RIGHT
  243. RenderHTML(canvas,txt,x-TextWidth(StripHTML(txt)),y)
  244. Case ALIGN_LEFT
  245. RenderHTML(canvas,txt,x,y)
  246. End Select
  247. End Method
  248. Function StripHTML:String(txt:String)
  249. Local plainText:String = txt.Replace("</","<")
  250. plainText = plainText.Replace("<b>","")
  251. Return plainText.Replace("<i>","")
  252. End
  253. Method TextWidth:Int(txt:String)
  254. Local prevChar:String = ""
  255. Local width:Int = 0
  256. For Local i:= 0 Until txt.Length
  257. Local asc:Int = txt[i]
  258. Local ac:Char = chars[asc]
  259. Local thisChar:String = String.FromChar(asc)
  260. If ac <> Null
  261. If useKerning
  262. Local key:String = prevChar+"_"+thisChar
  263. If kernPairs.Contains(key)
  264. width += kernPairs.Get(key).amount
  265. Endif
  266. Endif
  267. width += ac.xAdvance
  268. prevChar = thisChar
  269. Endif
  270. Next
  271. Return width
  272. End Method
  273. Method TextHeight:Int(txt:String)
  274. Local h:Int = 0
  275. For Local i:= 0 Until txt.Length
  276. Local asc:Int = txt[i]
  277. Local ac:Char = chars[asc]
  278. If ac.height+ac.yOffset > h h = ac.height+ac.yOffset
  279. Next
  280. Return h
  281. End
  282. End Class
  283. Global Text:BitmapText
  284. Class BitmapText
  285. Field chWidth:Int
  286. Field chHeight:Int
  287. Field count:Int
  288. Field image:Image[]
  289. Field upper:Int
  290. Method New(image:Image[],count:Int)
  291. Self.chWidth = image[0].Width
  292. Self.chHeight = image[0].Height
  293. Self.image = image
  294. Self.count = count
  295. End Method
  296. Method CharWidth:Int()
  297. Return chWidth
  298. End Method
  299. Method CharHeight:Int()
  300. Return chHeight
  301. End Method
  302. Method Width:Int(str:String)
  303. Return str.Length * chWidth
  304. End Method
  305. Method Height:Int()
  306. Return chHeight
  307. End Method
  308. Method Draw:Void(canvas:Canvas,str:String,x:Int,y:Int)
  309. Local tx:Int = x
  310. Local ty:Int = y
  311. For Local c:Int = Eachin str
  312. c &= $FF
  313. If c < 91
  314. c -= 32
  315. Else
  316. c -= 64
  317. Endif
  318. canvas.DrawImage(image[c],tx,ty)
  319. tx += chWidth
  320. Next
  321. End Method
  322. End Class
  323. Global LargeText:VaryFont
  324. Class VaryFont
  325. Field fontImg:Image[]
  326. Const COUNT:Int = 94
  327. Global param:Int[][] = New Int[][](New Int[]( 12,355,29,45),New int[]( 41,355,29,30),New Int[]( 70,355,29,47),New Int[](100,355,24,47),New Int[](128,355,29,47),New Int[](157,355,30,47),
  328. New Int[](193,355,15,28),New Int[](222,355,19,48),New Int[](247,355,19,48),New Int[](276,355,22,32),New Int[](302,355,28,39),New Int[](337,355,16,49),
  329. New Int[](363,355,23,34),New Int[](394,355,16,44),New int[](419,355,25,44),New int[](447,355,28,44),New int[](477,355,26,44),New int[](506,355,25,44),
  330. New Int[](536,355,24,44),New int[](563,355,27,44),New int[](593,355,25,44),New int[](622,355,27,44),New int[](651,355,26,44),New int[](679,355,27,44),
  331. New int[](708,355,26,44),New int[](744,355,15,44),New int[](773,355,15,51),New int[](796,355,25,38),New int[](825,355,26,38),New int[](855,355,24,38),
  332. New int[](885,355,23,44),New int[](910,355,30,47),New int[](939,355,31,44),New int[](970,355,27,44),New int[]( 12,403,27,44),New int[]( 42,403,27,44),
  333. New int[]( 72,403,24,44),New int[](100,403,25,44),New int[](128,403,27,44),New int[](158,403,26,44),New int[](189,403,23,44),New int[](216,403,23,44),
  334. New Int[](245,403,29,44),New Int[](275,403,25,44),New Int[](302,403,27,44),New Int[](332,403,27,44),New Int[](360,403,27,44),New Int[](391,403,26,44),
  335. New Int[](417,403,29,46),New Int[](448,403,28,44),New Int[](477,403,25,44),New Int[](505,403,29,44),New Int[](535,403,26,44),New Int[](562,403,30,44),
  336. New Int[](591,403,30,44),New Int[](621,403,29,44),New Int[](650,403,28,44),New Int[](680,403,27,44),New Int[](714,403,20,47),New Int[](739,403,24,44),
  337. New Int[](768,403,19,47),New Int[](794,403,29,26),New Int[](822,426,32,48),New Int[](857,403,18,20),New Int[](883,403,26,44),New Int[](912,403,27,44),
  338. New Int[](940,403,25,44),New Int[](970,403,26,44),New Int[]( 12,449,27,44),New Int[]( 43,449,24,44),New Int[]( 71,449,26,49),New Int[](100,449,26,44),
  339. New Int[](131,449,18,44),New Int[](159,449,20,49),New Int[](187,449,27,44),New Int[](217,449,24,44),New Int[](245,449,28,44),New Int[](274,449,26,44),
  340. New Int[](303,449,27,44),New Int[](332,449,26,49),New Int[](361,449,26,49),New Int[](392,449,24,44),New Int[](421,449,24,44),New Int[](450,449,24,44),
  341. New Int[](479,449,24,44),New Int[](506,449,26,44),New Int[](534,449,29,44),New Int[](563,449,27,44),New Int[](592,449,27,49),New Int[](622,449,25,44),
  342. New Int[](654,449,21,48),New Int[](686,449,13,48),New Int[](711,449,21,48),New Int[](735,449,31,34))
  343. Method New(image:Image)
  344. fontImg = New Image[COUNT]
  345. For Local i:Int = 0 Until COUNT
  346. fontImg[i] = New Image(image,param[i][0],param[i][1],param[i][2],param[i][3])
  347. Next
  348. End Method
  349. Method TextWidth:Int(str:String)
  350. Local l:Int= 0
  351. For Local n:Int = Eachin str
  352. Local i:Int = GetIndex(n)
  353. If i > -1
  354. l += param[i][2]
  355. Else
  356. l += 20
  357. Endif
  358. Next
  359. Return l
  360. End Method
  361. Method TextHeight:Int(str:String)
  362. Local l:Int = 0
  363. If str > 0
  364. l = param[0][3]
  365. Endif
  366. Return l
  367. End Method
  368. Method GetIndex:Int(n:Int)
  369. If n >32 And n < 128 Then Return n-33
  370. Return -1
  371. End Method
  372. Method Draw:Void(canvas:Canvas,str:String,x:Float,y:Float)
  373. If str.Length = 0 Return
  374. For Local n:Int = Eachin str
  375. Local i:Int = GetIndex(n)
  376. If i > -1
  377. canvas.DrawImage(fontImg[i],x,y)
  378. x += param[i][2]
  379. Else
  380. x += 20
  381. Endif
  382. Next
  383. End Method
  384. End Class