1 local cached_fonts
= {};
8 set_font_file
= function(file
)
10 cached_fonts
= {}; -- Flush cache.
13 local check_codepoint
= function(codepoint
)
14 if type(codepoint
) == "string" then
15 if codepoint
== "nonexistent" then
17 elseif codepoint
== "invalid" then
22 elseif type(codepoint
) == "number" then
23 local planechar
= codepoint
% 65536;
24 local plane
= (codepoint
- planechar
) / 65536;
26 -- Negative codepoints are not valid, planes have 65534 characters
27 -- and there are 17 planes.
28 if codepoint
< 0 or planechar
> 65533 or plane
> 16 then
31 -- Surrogate range not valid.
32 if codepoint
>= xD800
and codepoint
<= xDFFF
then
41 local load_codepoint
= function(codepoint
)
46 if not font_file
or not font_file
.member
then
47 cached_fonts
[codepoint
] = false;
52 file
, err
= font_file
:member(tostring(codepoint
));
54 cached_fonts
[codepoint
] = false;
57 local file2
= file
:four_to_five();
60 local raw
= file2
:read();
66 local w1
= string.byte(raw
, 1);
67 local w2
= string.byte(raw
, 2);
70 metric_w
= (w1
- 128) + 128 * w2
;
76 metric_h
= ((8 * l
) - (8 * l
) % metric_w
) / metric_w
;
81 cached_fonts
[codepoint
] = {bitmap
= bitmap
, metric_w
= metric_w
, metric_h
= metric_h
};
84 local get_character
= function(codepoint
)
85 if not check_codepoint(codepoint
) then
86 codepoint
= "invalid";
88 if cached_fonts
[codepoint
] == nil then
89 load_codepoint(codepoint
);
91 if not cached_fonts
[codepoint
] then
92 -- No such codepoint in font. Fall back.
93 codepoint
= "nonexistent";
95 if cached_fonts
[codepoint
] == nil then
96 load_codepoint(codepoint
);
98 if not cached_fonts
[codepoint
] then
99 -- Fine, doesn't exist and no fallback.
100 return {bitmap
= "", metric_w
= 0, metric_h
= 0};
102 return cached_fonts
[codepoint
];
105 local next_character
= function(str
, index
)
106 local c1
= string.byte(str
, index
);
109 c2
= string.byte(str
, index
);
114 if c1
< xD800
or c1
> xDFFF
then
117 elseif c1
>= xDC00
then
123 elseif c2
< xDC00
or c2
> xDFFF
then
129 point
= 65536 + c1
* 1024 + c2
;
132 if index
+ codelen
<= #str
then
133 return point
, index
+ codelen
;
139 text_metrics
= function(str
, singleline
)
142 local metric_w_curline
= 0;
143 local metric_h_curline
= 0;
149 codepoint
, index
= next_character(str
, index
);
150 if singleline
or (codepoint
~= 10 and codepoint
~= 13) then
151 fontdata
= get_character(codepoint
);
152 if fontdata
.metric_h
> metric_h_curline
then
153 metric_h_curline
= fontdata
.metric_h
;
155 metric_w_curline
= metric_w_curline
+ fontdata
.metric_w
;
157 if metric_w_curline
> metric_w
then
158 metric_w
= metric_w_curline
;
160 metric_h
= metric_h
+ metric_h_curline
;
161 metric_w_curline
= 0;
162 metric_h_curline
= 0;
165 if metric_w_curline
> metric_w
then
166 metric_w
= metric_w_curline
;
168 metric_h
= metric_h
+ metric_h_curline
;
169 metric_w_curline
= 0;
170 metric_h_curline
= 0;
172 return metric_w
, metric_h
;
175 render_text
= function(flags
, x
, y
, str
, singleline
, fgr
, fgg
, fgb
, fga
, bgr
, bgg
, bgb
, bga
)
178 local metric_w_curline
= 0;
179 local metric_h_curline
= 0;
191 codepoint
, index
= next_character(str
, index
);
192 if singleline
or (codepoint
~= 10 and codepoint
~= 13) then
193 fontdata
= get_character(codepoint
);
194 jpcrr
.hud
.bitmap_binary(flags
, x
+ metric_w_curline
, y
+ metric_h
, fontdata
.bitmap
, fgr
, fgg
,
195 fgb
, fga
, bgr
, bgg
, bgb
, bga
);
196 if fontdata
.metric_h
> metric_h_curline
then
197 metric_h_curline
= fontdata
.metric_h
;
199 metric_w_curline
= metric_w_curline
+ fontdata
.metric_w
;
201 if metric_w_curline
> metric_w
then
202 metric_w
= metric_w_curline
;
204 metric_h
= metric_h
+ metric_h_curline
;
205 metric_w_curline
= 0;
206 metric_h_curline
= 0;