Skip to content

Commit

Permalink
[PATCH] fbcon: Console Rotation - Add support to rotate font bitmap
Browse files Browse the repository at this point in the history
Add support to rotate the font bitmap.  To save on processing time, the entire
fontdata will be rotated on a console switch, then stored in a buffer private
to fbcon.  To further save on processing, the fontdata will only be rotated if
the font has changed or if the angle of rotation has changed.  Only a single
copy of the rotated fontdata will be kept.

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Antonino A. Daplas authored and Linus Torvalds committed Nov 9, 2005
1 parent 9c44e5f commit 6cc50e1
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/video/console/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o
ifeq ($(CONFIG_FB_TILEBLITTING),y)
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o
endif
ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y)
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o
endif

obj-$(CONFIG_FB_STI) += sticore.o font.o

Expand Down
4 changes: 4 additions & 0 deletions drivers/video/console/fbcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ static inline int get_attribute(struct fb_info *info, u16 c)
(void) (&_r == &_v); \
(i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; })

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
extern void fbcon_set_rotate(struct fbcon_ops *ops);
#else
#define fbcon_set_rotate(x) do {} while(0)
#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */

#endif /* _VIDEO_FBCON_H */

105 changes: 105 additions & 0 deletions drivers/video/console/fbcon_rotate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* linux/drivers/video/console/fbcon_rotate.c -- Software Rotation
*
* Copyright (C) 2005 Antonino Daplas <adaplas @pol.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/

#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <asm/types.h>
#include "fbcon.h"
#include "fbcon_rotate.h"

static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc,
struct display *p)
{
struct fbcon_ops *ops = info->fbcon_par;
int len, err = 0;
int s_cellsize, d_cellsize, i;
const u8 *src;
u8 *dst;

if (vc->vc_font.data == ops->fontdata &&
p->con_rotate == ops->cur_rotate)
goto finished;

src = ops->fontdata = vc->vc_font.data;
ops->cur_rotate = p->con_rotate;
len = (!p->userfont) ? 256 : FNTCHARCNT(src);
s_cellsize = ((vc->vc_font.width + 7)/8) *
vc->vc_font.height;
d_cellsize = s_cellsize;

if (ops->rotate == FB_ROTATE_CW ||
ops->rotate == FB_ROTATE_CCW)
d_cellsize = ((vc->vc_font.height + 7)/8) *
vc->vc_font.width;

if (info->fbops->fb_sync)
info->fbops->fb_sync(info);

if (ops->fd_size < d_cellsize * len) {
dst = kmalloc(d_cellsize * len, GFP_KERNEL);

if (dst == NULL) {
err = -ENOMEM;
goto finished;
}

ops->fd_size = d_cellsize * len;
kfree(ops->fontbuffer);
ops->fontbuffer = dst;
}

dst = ops->fontbuffer;
memset(dst, 0, ops->fd_size);

switch (ops->rotate) {
case FB_ROTATE_UD:
for (i = len; i--; ) {
rotate_ud(src, dst, vc->vc_font.width,
vc->vc_font.height);

src += s_cellsize;
dst += d_cellsize;
}
break;
case FB_ROTATE_CW:
for (i = len; i--; ) {
rotate_cw(src, dst, vc->vc_font.width,
vc->vc_font.height);
src += s_cellsize;
dst += d_cellsize;
}
break;
case FB_ROTATE_CCW:
for (i = len; i--; ) {
rotate_ccw(src, dst, vc->vc_font.width,
vc->vc_font.height);
src += s_cellsize;
dst += d_cellsize;
}
break;
}

finished:
return err;
}

void fbcon_set_rotate(struct fbcon_ops *ops)
{
ops->rotate_font = fbcon_rotate_font;
}
EXPORT_SYMBOL(fbcon_set_rotate);

MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
MODULE_DESCRIPTION("Console Rotation Support");
MODULE_LICENSE("GPL");
102 changes: 102 additions & 0 deletions drivers/video/console/fbcon_rotate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* linux/drivers/video/console/fbcon_rotate.h -- Software Display Rotation
*
* Copyright (C) 2005 Antonino Daplas <adaplas@pol.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/

#ifndef _FBCON_ROTATE_H
#define _FBCON_ROTATE_H

#define FNTCHARCNT(fd) (((int *)(fd))[-3])

#define GETVYRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
(i)->var.yres : (i)->var.yres_virtual; })

#define GETVXRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
(i)->var.xres : (i)->var.xres_virtual; })

/*
* The bitmap is always big endian
*/
#if defined(__LITTLE_ENDIAN)
#define FBCON_BIT(b) (7 - (b))
#else
#define FBCON_BIT(b) (b)
#endif

static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat)
{
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;

pat +=index;
return (test_bit(FBCON_BIT(bit), (void *)pat));
}

static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat)
{
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;

pat += index;
set_bit(FBCON_BIT(bit), (void *)pat);
}

static inline void rotate_ud(const char *in, char *out, u32 width, u32 height)
{
int i, j;
int shift = width % 8;

width = (width + 7) & ~7;

for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
if (pattern_test_bit(j, i, width, in))
pattern_set_bit(width - (1 + j + shift),
height - (1 + i),
width, out);
}

}
}

static inline void rotate_cw(const char *in, char *out, u32 width, u32 height)
{
int i, j, h = height, w = width;
int shift = (8 - (height % 8)) & 7;

width = (width + 7) & ~7;
height = (height + 7) & ~7;

for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (pattern_test_bit(j, i, width, in))
pattern_set_bit(height - 1 - i - shift, j,
height, out);

}
}
}

static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height)
{
int i, j, h = height, w = width;
int shift = width % 8;

width = (width + 7) & ~7;
height = (height + 7) & ~7;

for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (pattern_test_bit(j, i, width, in))
pattern_set_bit(i, width - 1 - j - shift,
height, out);
}
}
}

#endif

0 comments on commit 6cc50e1

Please sign in to comment.