1 local cached_fonts
= {};
3 local use_chargen
= true;
9 set_font_file
= function(file
)
12 cached_fonts
= {}; -- Flush cache.
15 local check_codepoint
= function(codepoint
)
16 if type(codepoint
) == "string" then
17 if codepoint
== "nonexistent" then
19 elseif codepoint
== "invalid" then
24 elseif type(codepoint
) == "number" then
25 local planechar
= codepoint
% 65536;
26 local plane
= (codepoint
- planechar
) / 65536;
28 -- Negative codepoints are not valid, planes have 65534 characters
29 -- and there are 17 planes.
30 if codepoint
< 0 or planechar
> 65533 or plane
> 16 then
33 -- Surrogate range not valid.
34 if codepoint
>= xD800
and codepoint
<= xDFFF
then
43 local load_codepoint
= function(codepoint
)
48 if not font_file
or not font_file
.member
then
49 cached_fonts
[codepoint
] = false;
54 file
, err
= font_file
:member(tostring(codepoint
));
56 cached_fonts
[codepoint
] = false;
59 local file2
= file
:four_to_five();
62 local raw
= file2
:read();
68 local w1
= string.byte(raw
, 1);
69 local w2
= string.byte(raw
, 2);
72 metric_w
= (w1
- 128) + 128 * w2
;
78 metric_h
= ((8 * l
) - (8 * l
) % metric_w
) / metric_w
;
83 cached_fonts
[codepoint
] = {bitmap
= bitmap
, metric_w
= metric_w
, metric_h
= metric_h
};
86 local get_character
= function(codepoint
)
87 if not check_codepoint(codepoint
) then
88 codepoint
= "invalid";
90 if cached_fonts
[codepoint
] == nil then
91 load_codepoint(codepoint
);
93 if not cached_fonts
[codepoint
] then
94 -- No such codepoint in font. Fall back.
95 codepoint
= "nonexistent";
97 if cached_fonts
[codepoint
] == nil then
98 load_codepoint(codepoint
);
100 if not cached_fonts
[codepoint
] then
101 -- Fine, doesn't exist and no fallback.
102 return {bitmap
= "", metric_w
= 0, metric_h
= 0};
104 return cached_fonts
[codepoint
];
107 local next_character
= function(str
, index
)
108 local c1
= string.byte(str
, index
);
111 c2
= string.byte(str
, index
);
116 if c1
< xD800
or c1
> xDFFF
then
119 elseif c1
>= xDC00
then
125 elseif c2
< xDC00
or c2
> xDFFF
then
131 point
= 65536 + c1
* 1024 + c2
;
134 if index
+ codelen
<= #str
then
135 return point
, index
+ codelen
;
141 text_metrics
= function(str
, singleline
)
144 local metric_w_curline
= 0;
145 local metric_h_curline
= 0;
151 codepoint
, index
= next_character(str
, index
);
152 if singleline
or (codepoint
~= 10 and codepoint
~= 13) then
154 fontdata
= get_character(codepoint
);
155 if fontdata
.metric_h
> metric_h_curline
then
156 metric_h_curline
= fontdata
.metric_h
;
158 metric_w_curline
= metric_w_curline
+ fontdata
.metric_w
;
160 metric_h_curline
= 16;
161 metric_w_curline
= metric_w_curline
+ 8;
164 if metric_w_curline
> metric_w
then
165 metric_w
= metric_w_curline
;
167 metric_h
= metric_h
+ metric_h_curline
;
168 metric_w_curline
= 0;
169 metric_h_curline
= 0;
172 if metric_w_curline
> metric_w
then
173 metric_w
= metric_w_curline
;
175 metric_h
= metric_h
+ metric_h_curline
;
176 metric_w_curline
= 0;
177 metric_h_curline
= 0;
179 return metric_w
, metric_h
;
182 render_text
= function(flags
, x
, y
, str
, singleline
, fgr
, fgg
, fgb
, fga
, bgr
, bgg
, bgb
, bga
)
185 local metric_w_curline
= 0;
186 local metric_h_curline
= 0;
196 jpcrr
.hud
.chargen(flags
, x
, y
, str
, not singleline
, fgr
, fgg
, fgb
, fga
, bgr
, bgg
, bgb
, bga
);
203 codepoint
, index
= next_character(str
, index
);
204 if singleline
or (codepoint
~= 10 and codepoint
~= 13) then
205 fontdata
= get_character(codepoint
);
206 jpcrr
.hud
.bitmap_binary(flags
, x
+ metric_w_curline
, y
+ metric_h
, fontdata
.bitmap
, fgr
, fgg
,
207 fgb
, fga
, bgr
, bgg
, bgb
, bga
);
208 if fontdata
.metric_h
> metric_h_curline
then
209 metric_h_curline
= fontdata
.metric_h
;
211 metric_w_curline
= metric_w_curline
+ fontdata
.metric_w
;
213 if metric_w_curline
> metric_w
then
214 metric_w
= metric_w_curline
;
216 metric_h
= metric_h
+ metric_h_curline
;
217 metric_w_curline
= 0;
218 metric_h_curline
= 0;