lib/tileset: intro `TileSetFont::text_height`
[nit.git] / lib / mnit / tileset.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Manage images that are tileset or glyphset (for bitmap fonts)
16 module tileset
17
18 import mnit_display
19
20 # Efficienly retrieve tiles in a big image
21 class TileSet
22 # The image containing the tileset
23 var image: Image
24
25 # The witdh of a tile
26 var width: Int
27
28 # The height of a tile
29 var height: Int
30
31 init
32 do
33 self.nb_cols = image.width / width
34 self.nb_rows = image.height / height
35
36 for j in [0..nb_rows[ do
37 for i in [0..nb_cols[ do
38 subimages.add image.subimage(i*width,j*height,width,height)
39 end
40 end
41 end
42
43 # The number of columns of tiles in the image
44 var nb_cols: Int is noinit
45
46 # The number of rows of tiles in the image
47 var nb_rows: Int is noinit
48
49 # Cache for images of tiles
50 var subimages = new Array[Image]
51
52 # The subimage of given tile
53 # Aborts if x or y are out of bound
54 fun [](x,y: Int): Image
55 do
56 assert x >= 0 and x < nb_cols and y >= 0 and y <= nb_rows else print "{x}x{y}<?{nb_cols}x{nb_rows}"
57 var idx = x + y * nb_cols
58 return subimages[idx]
59 end
60 end
61
62 # A monospace bitmap font where glyphs are stored in a tileset
63 class TileSetFont
64 super TileSet
65
66 # Each caracter in the image
67 # in left->right, then top->bottom order
68 # Use space (' ') for holes in the tileset
69 var chars: String
70
71 # Additional space to insert horizontally between characters
72 # A negave value will display tile overlaped
73 var hspace: Numeric = 0.0 is writable
74
75 # Additional space to insert vertically between characters
76 # A negave value will display tile overlaped
77 var vspace: Numeric = 0.0 is writable
78
79 # The glyph (tile) associated to the caracter `c` according to `chars`
80 # Returns null if `c` is not in `chars`
81 fun char(c: Char): nullable Image
82 do
83 var i = chars.index_of(c)
84 if i == -1 then return null
85 return subimages[i]
86 end
87
88 # Distance between the beginning of a letter tile and the beginning of the next letter tile
89 fun advance: Numeric do return width.add(hspace)
90
91 # Distance between the top of the first line to the bottom of the last line in `text`
92 fun text_height(text: Text): Numeric
93 do
94 if text.is_empty then return 0
95
96 var n_lines = text.chars.count('\n')
97 return (n_lines+1).mul(height.add(vspace)).sub(vspace)
98 end
99 end
100
101 redef class Display
102 # Blit the text using a monospace bitmap font
103 # '\n' are rendered as carriage return
104 fun text(text: String, font: TileSetFont, x, y: Numeric)
105 do
106 x = x.to_f
107 var cx = x
108 var cy = y.to_f
109 var sw = font.width.to_f + font.hspace.to_f
110 var sh = font.height.to_f + font.vspace.to_f
111 for c in text.chars do
112 if c == '\n' then
113 cx = x
114 cy += sh
115 continue
116 end
117 if c == ' ' then
118 cx += sw
119 continue
120 end
121 var image = font.char(c)
122 if image != null then
123 blit(image, cx, cy)
124 end
125 cx += sw
126 end
127 end
128 end