Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/fonts: Store font data for user space with font_data_export()

Add font_data_export() and update consoles to use it.

The helper font_data_export() is based on code in fbcon_get_font().
It extends the size of a single glyph to match the requested vpitch,
which us usually 32 bytes for fonts from user space. Internal fonts
have a pitch according to the glyph's height.

The implementation of font_data_export() differs in several ways from
the original code. The original implementation distinguished between
different pitches of the font data. This is not necessary as the pitch
is a parameter in the copying.

There was also special handling for a font pitch of 3 bytes, which got
expanded to 4 bytes (with trailing bits on each scanline). The logic
originated from long before git history exists even in the historical
tree. So it is not clear why this was implemented. It is not what user
space expects. The setfont utitlity loads font with 3-bytes pitches and
expects to read such fonts with a 3-byte pitch. For any font width, the
font pitch is always the width extended to the next multiple of 8. See
[1] for the user-space font-reading code.

With the changes to handling the font pitches, font_data_export() replaces
the original code's various special cases with a single copying logic.

v3:
- fix typos (Helge)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://github.com/legionus/kbd/blob/v2.9.0/src/libkfont/kdfontop.c#L73 # [1]
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Thomas Zimmermann and committed by
Helge Deller
c37bd7c8 514d0de7

+43 -55
+2 -55
drivers/video/fbdev/core/fbcon.c
··· 2282 2282 2283 2283 static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch) 2284 2284 { 2285 - struct fbcon_display *p = &fb_display[vc->vc_num]; 2286 - font_data_t *fontdata = p->fontdata; 2287 - u8 *data = font->data; 2288 - int i, j; 2285 + const struct fbcon_display *p = &fb_display[vc->vc_num]; 2289 2286 2290 2287 font->width = vc->vc_font.width; 2291 2288 font->height = vc->vc_font.height; 2292 2289 if (font->height > vpitch) 2293 2290 return -ENOSPC; 2294 2291 font->charcount = vc->vc_hi_font_mask ? 512 : 256; 2295 - if (!font->data) 2296 - return 0; 2297 2292 2298 - if (font->width <= 8) { 2299 - j = vc->vc_font.height; 2300 - if (font->charcount * j > font_data_size(fontdata)) 2301 - return -EINVAL; 2302 - 2303 - for (i = 0; i < font->charcount; i++) { 2304 - memcpy(data, fontdata, j); 2305 - memset(data + j, 0, vpitch - j); 2306 - data += vpitch; 2307 - fontdata += j; 2308 - } 2309 - } else if (font->width <= 16) { 2310 - j = vc->vc_font.height * 2; 2311 - if (font->charcount * j > font_data_size(fontdata)) 2312 - return -EINVAL; 2313 - 2314 - for (i = 0; i < font->charcount; i++) { 2315 - memcpy(data, fontdata, j); 2316 - memset(data + j, 0, 2*vpitch - j); 2317 - data += 2*vpitch; 2318 - fontdata += j; 2319 - } 2320 - } else if (font->width <= 24) { 2321 - if (font->charcount * (vc->vc_font.height * sizeof(u32)) > font_data_size(fontdata)) 2322 - return -EINVAL; 2323 - 2324 - for (i = 0; i < font->charcount; i++) { 2325 - for (j = 0; j < vc->vc_font.height; j++) { 2326 - *data++ = fontdata[0]; 2327 - *data++ = fontdata[1]; 2328 - *data++ = fontdata[2]; 2329 - fontdata += sizeof(u32); 2330 - } 2331 - memset(data, 0, 3 * (vpitch - j)); 2332 - data += 3 * (vpitch - j); 2333 - } 2334 - } else { 2335 - j = vc->vc_font.height * 4; 2336 - if (font->charcount * j > font_data_size(fontdata)) 2337 - return -EINVAL; 2338 - 2339 - for (i = 0; i < font->charcount; i++) { 2340 - memcpy(data, fontdata, j); 2341 - memset(data + j, 0, 4 * vpitch - j); 2342 - data += 4 * vpitch; 2343 - fontdata += j; 2344 - } 2345 - } 2346 - return 0; 2293 + return font_data_export(p->fontdata, font, vpitch); 2347 2294 } 2348 2295 2349 2296 /* set/clear vc_hi_font_mask and update vc attrs accordingly */
+1
include/linux/font.h
··· 62 62 bool font_data_put(font_data_t *fd); 63 63 unsigned int font_data_size(font_data_t *fd); 64 64 bool font_data_is_equal(font_data_t *lhs, font_data_t *rhs); 65 + int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch); 65 66 66 67 /* 67 68 * Font description
+40
lib/fonts/fonts.c
··· 198 198 } 199 199 EXPORT_SYMBOL_GPL(font_data_is_equal); 200 200 201 + /** 202 + * font_data_export - Stores font data for user space 203 + * @fd: Font data 204 + * @font: A font for user space 205 + * @vpitch: The size of a single glyph in @font in bytes 206 + * 207 + * Store the font data given in @fd to the font in @font. Values and 208 + * pointers in @font are pre-initialized. This helper mostly checks some 209 + * corner cases and translates glyph sizes according to the value given 210 + * @vpitch. 211 + * 212 + * Returns: 213 + * 0 on success, or a negative errno code otherwise. 214 + */ 215 + int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch) 216 + { 217 + const unsigned char *font_data = font_data_buf(fd); 218 + unsigned char *data = font->data; 219 + unsigned int pitch = console_font_pitch(font); 220 + unsigned int glyphsize, i; 221 + 222 + if (!font->width || !font->height || !font->charcount || !font->data) 223 + return 0; 224 + 225 + glyphsize = font->height * pitch; 226 + 227 + if (font->charcount * glyphsize > font_data_size(fd)) 228 + return -EINVAL; 229 + 230 + for (i = 0; i < font->charcount; i++) { 231 + memcpy(data, font_data, glyphsize); 232 + memset(data + glyphsize, 0, pitch * vpitch - glyphsize); 233 + data += pitch * vpitch; 234 + font_data += glyphsize; 235 + } 236 + 237 + return 0; 238 + } 239 + EXPORT_SYMBOL_GPL(font_data_export); 240 + 201 241 /* 202 242 * Font lookup 203 243 */