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: Implement font rotation

Move the core of fbcon's font-rotation code to the font library as
the new helper font_data_rotate(). The code can rotate in steps of
90°. For completeness, it also copies the glyph data for multiples
of 360°.

Bring back the memset optimization. A memset to 0 again clears the
whole glyph output buffer. Then use the internal rotation helpers on
the cleared output. Fbcon's original implementation worked like this,
but lost it during refactoring.

Replace fbcon's font-rotation code with the new implementations.
All that's left to do for fbcon is to maintain its internal fbcon
state.

v2:
- fix typos

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Thomas Zimmermann and committed by
Helge Deller
cfa72955 a30e9e6b

+126 -60
+1 -1
drivers/video/fbdev/core/fbcon.h
··· 86 86 const u8 *fontdata; 87 87 u8 *cursor_src; 88 88 u32 cursor_size; 89 - u32 fd_size; 89 + size_t fd_size; 90 90 91 91 const struct fbcon_bitops *bitops; 92 92 };
+19 -59
drivers/video/fbdev/core/fbcon_rotate.c
··· 8 8 * more details. 9 9 */ 10 10 11 - #include <linux/module.h> 12 - #include <linux/slab.h> 13 - #include <linux/string.h> 11 + #include <linux/errno.h> 14 12 #include <linux/fb.h> 15 13 #include <linux/font.h> 16 - #include <linux/vt_kern.h> 17 - #include <linux/console.h> 18 - #include <asm/types.h> 14 + 19 15 #include "fbcon.h" 20 16 #include "fbcon_rotate.h" 21 17 22 18 int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) 23 19 { 24 20 struct fbcon_par *par = info->fbcon_par; 25 - int len, err = 0; 26 - int s_cellsize, d_cellsize, i; 27 - const u8 *src; 28 - u8 *dst; 21 + unsigned char *fontbuffer; 22 + int ret; 29 23 30 24 if (vc->vc_font.data == par->fontdata && 31 25 par->p->con_rotate == par->cur_rotate) 32 - goto finished; 26 + return 0; 33 27 34 - src = par->fontdata = vc->vc_font.data; 28 + par->fontdata = vc->vc_font.data; 35 29 par->cur_rotate = par->p->con_rotate; 36 - len = vc->vc_font.charcount; 37 - s_cellsize = font_glyph_size(vc->vc_font.width, vc->vc_font.height); 38 - d_cellsize = s_cellsize; 39 - 40 - if (par->rotate == FB_ROTATE_CW || 41 - par->rotate == FB_ROTATE_CCW) 42 - d_cellsize = font_glyph_size(vc->vc_font.height, vc->vc_font.width); 43 30 44 31 if (info->fbops->fb_sync) 45 32 info->fbops->fb_sync(info); 46 33 47 - if (par->fd_size < d_cellsize * len) { 48 - kfree(par->fontbuffer); 49 - par->fontbuffer = NULL; 50 - par->fd_size = 0; 51 - 52 - dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); 53 - 54 - if (dst == NULL) { 55 - err = -ENOMEM; 56 - goto finished; 57 - } 58 - 59 - par->fd_size = d_cellsize * len; 60 - par->fontbuffer = dst; 34 + fontbuffer = font_data_rotate(par->p->fontdata, vc->vc_font.width, 35 + vc->vc_font.height, vc->vc_font.charcount, 36 + par->rotate, par->fontbuffer, &par->fd_size); 37 + if (IS_ERR(fontbuffer)) { 38 + ret = PTR_ERR(fontbuffer); 39 + goto err_kfree; 61 40 } 62 41 63 - dst = par->fontbuffer; 42 + par->fontbuffer = fontbuffer; 64 43 65 - switch (par->rotate) { 66 - case FB_ROTATE_UD: 67 - for (i = len; i--; ) { 68 - font_glyph_rotate_180(src, vc->vc_font.width, vc->vc_font.height, dst); 69 - src += s_cellsize; 70 - dst += d_cellsize; 71 - } 72 - break; 73 - case FB_ROTATE_CW: 74 - for (i = len; i--; ) { 75 - font_glyph_rotate_90(src, vc->vc_font.width, vc->vc_font.height, dst); 76 - src += s_cellsize; 77 - dst += d_cellsize; 78 - } 79 - break; 80 - case FB_ROTATE_CCW: 81 - for (i = len; i--; ) { 82 - font_glyph_rotate_270(src, vc->vc_font.width, vc->vc_font.height, dst); 83 - src += s_cellsize; 84 - dst += d_cellsize; 85 - } 86 - break; 87 - } 44 + return 0; 88 45 89 - finished: 90 - return err; 46 + err_kfree: 47 + kfree(par->fontbuffer); 48 + par->fontbuffer = NULL; /* clear here to avoid output */ 49 + 50 + return ret; 91 51 }
+3
include/linux/font.h
··· 111 111 unsigned char *out); 112 112 void font_glyph_rotate_270(const unsigned char *glyph, unsigned int width, unsigned int height, 113 113 unsigned char *out); 114 + unsigned char *font_data_rotate(font_data_t *fd, unsigned int width, unsigned int height, 115 + unsigned int charcount, unsigned int steps, 116 + unsigned char *buf, size_t *bufsize); 114 117 115 118 /* 116 119 * Font description
+103
lib/fonts/font_rotate.c
··· 9 9 * more details. 10 10 */ 11 11 12 + #include <linux/errno.h> 12 13 #include <linux/export.h> 13 14 #include <linux/math.h> 15 + #include <linux/overflow.h> 16 + #include <linux/slab.h> 14 17 #include <linux/string.h> 15 18 16 19 #include "font.h" ··· 173 170 __font_glyph_rotate_270(glyph, width, height, out); 174 171 } 175 172 EXPORT_SYMBOL_GPL(font_glyph_rotate_270); 173 + 174 + /** 175 + * font_data_rotate - Rotate font data by multiples of 90° 176 + * @fd: The font data to rotate 177 + * @width: The glyph width in bits per scanline 178 + * @height: The number of scanlines in the glyph 179 + * @charcount: The number of glyphs in the font 180 + * @steps: Number of rotation steps of 90° 181 + * @buf: Preallocated output buffer; can be NULL 182 + * @bufsize: The size of @buf in bytes; can be NULL 183 + * 184 + * The parameters @width and @height refer to the visible number of pixels 185 + * and scanlines in a single glyph. The number of glyphs is given in @charcount. 186 + * Rotation happens in steps of 90°. The @steps parameter can have any value, 187 + * but only 0 to 3 produce distinct results. With 4 or higher, a full rotation 188 + * has been performed. You can pass any value for @steps and the helper will 189 + * perform the appropriate rotation. Note that the returned buffer is not 190 + * compatible with font_data_t. It only contains glyph data in the same format 191 + * as returned by font_data_buf(). Callers are responsible to free the returned 192 + * buffer with kfree(). Font rotation typically happens when displays get 193 + * re-oriented. To avoid unnecessary re-allocation of the memory buffer, the 194 + * caller can pass in an earlier result buffer in @buf for reuse. The old and 195 + * new buffer sizes are given and retrieved by the caller in @bufsize. The 196 + * allocation semantics are compatible with krealloc(). 197 + * 198 + * Returns: 199 + * A buffer with rotated glyphs on success, or an error pointer otherwise 200 + */ 201 + unsigned char *font_data_rotate(font_data_t *fd, unsigned int width, unsigned int height, 202 + unsigned int charcount, unsigned int steps, 203 + unsigned char *buf, size_t *bufsize) 204 + { 205 + const unsigned char *src = font_data_buf(fd); 206 + unsigned int s_cellsize = font_glyph_size(width, height); 207 + unsigned int d_cellsize, i; 208 + unsigned char *dst; 209 + size_t size; 210 + 211 + steps %= 4; 212 + 213 + switch (steps) { 214 + case 0: 215 + case 2: 216 + d_cellsize = s_cellsize; 217 + break; 218 + case 1: 219 + case 3: 220 + d_cellsize = font_glyph_size(height, width); /* flip width/height */ 221 + break; 222 + } 223 + 224 + if (check_mul_overflow(charcount, d_cellsize, &size)) 225 + return ERR_PTR(-EINVAL); 226 + 227 + if (!buf || !bufsize || size > *bufsize) { 228 + dst = kmalloc_array(charcount, d_cellsize, GFP_KERNEL); 229 + if (!dst) 230 + return ERR_PTR(-ENOMEM); 231 + 232 + kfree(buf); 233 + buf = dst; 234 + if (bufsize) 235 + *bufsize = size; 236 + } else { 237 + dst = buf; 238 + } 239 + 240 + switch (steps) { 241 + case 0: 242 + memcpy(dst, src, size); 243 + break; 244 + case 1: 245 + memset(dst, 0, size); 246 + for (i = 0; i < charcount; ++i) { 247 + __font_glyph_rotate_90(src, width, height, dst); 248 + src += s_cellsize; 249 + dst += d_cellsize; 250 + } 251 + break; 252 + case 2: 253 + memset(dst, 0, size); 254 + for (i = 0; i < charcount; ++i) { 255 + __font_glyph_rotate_180(src, width, height, dst); 256 + src += s_cellsize; 257 + dst += d_cellsize; 258 + } 259 + break; 260 + case 3: 261 + memset(dst, 0, size); 262 + for (i = 0; i < charcount; ++i) { 263 + __font_glyph_rotate_270(src, width, height, dst); 264 + src += s_cellsize; 265 + dst += d_cellsize; 266 + } 267 + break; 268 + } 269 + 270 + return buf; 271 + } 272 + EXPORT_SYMBOL_GPL(font_data_rotate);