}
PSplashFB*
-psplash_fb_new (void)
+psplash_fb_new (int angle)
{
struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;
fb_var.bits_per_pixel);
}
- fb->width = fb_var.xres;
- fb->height = fb_var.yres;
+ fb->real_width = fb->width = fb_var.xres;
+ fb->real_height = fb->height = fb_var.yres;
fb->bpp = fb_var.bits_per_pixel;
fb->stride = fb_fix.line_length;
fb->type = fb_fix.type;
DBG("width: %i, height: %i, bpp: %i, stride: %i",
fb->width, fb->height, fb->bpp, fb->stride);
-
fb->base = (char *) mmap ((caddr_t) NULL,
/*fb_fix.smem_len */
fb->stride * fb->height,
status = 2;
#endif
+ fb->angle = angle;
+
+ switch (fb->angle)
+ {
+ case 270:
+ case 90:
+ fb->width = fb->real_height;
+ fb->height = fb->real_width;
+ break;
+ case 180:
+ case 0:
+ default:
+ break;
+ }
+
return fb;
fail:
return NULL;
}
-void
+#define OFFSET(fb,x,y) (((y) * (fb)->stride) + ((x) * ((fb)->bpp >> 3)))
+
+inline void
psplash_fb_plot_pixel (PSplashFB *fb,
int x,
int y,
if (x < 0 || x > fb->width-1 || y < 0 || y > fb->height-1)
return;
- off = (y * fb->stride) + (x * (fb->bpp >> 3));
+ switch (fb->angle)
+ {
+ case 270:
+ off = OFFSET (fb, fb->real_height - y - 1, x);
+ break;
+ case 180:
+ off = OFFSET (fb, fb->real_width - x - 1, fb->real_height - y - 1);
+ break;
+ case 90:
+ off = OFFSET (fb, y, fb->real_width - x - 1);
+ break;
+ case 0:
+ default:
+ off = OFFSET (fb, x, y);
+ break;
+ }
/* FIXME: handle no RGB orderings */
switch (fb->bpp)
for (dy=0; dy < height; dy++)
for (dx=0; dx < width; dx++)
- {
- /* FIXME: inline this call */
psplash_fb_plot_pixel (fb, x+dx, y+dy, red, green, blue);
- }
}
void
int img_bytes_per_pixel,
uint8 *rle_data)
{
- uint8 *p = rle_data;
- int dx = 0, dy = 0, total_len;
+ uint8 *p = rle_data;
+ int dx = 0, dy = 0, total_len;
unsigned int len;
-#if 0
- for (dy=0; dy < img_height; dy++)
- for (dx=0; dx < img_width; dx++)
- {
- psplash_fb_plot_pixel (fb, x+dx, y+dy, *p, *(p+1), *(p+2));
- p += img_bytes_per_pixel;
- }
-#endif
-
total_len = img_width * img_height * img_bytes_per_pixel;
/* FIXME: Optimise, check for over runs ... */
}
}
}
+
+/* Font rendering code based on BOGL by Ben Pfaff */
+
+static int
+psplash_font_glyph (const PSplashFont *font, wchar_t wc, u_int32_t **bitmap)
+{
+ int mask = font->index_mask;
+ int i;
+
+ for (;;)
+ {
+ for (i = font->offset[wc & mask]; font->index[i]; i += 2)
+ {
+ if ((font->index[i] & ~mask) == (wc & ~mask))
+ {
+ if (bitmap != NULL)
+ *bitmap = &font->content[font->index[i+1]];
+ return font->index[i] & mask;
+ }
+ }
+ }
+ return 0;
+}
+
+void
+psplash_fb_text_size (PSplashFB *fb,
+ int *width,
+ int *height,
+ const PSplashFont *font,
+ const char *text)
+{
+ char *c = (char*)text;
+ wchar_t wc;
+ int k, n, w, h, mw;
+
+ n = strlen (text);
+ mw = h = w = 0;
+
+ mbtowc (0, 0, 0);
+ for (; (k = mbtowc (&wc, c, n)) > 0; c += k, n -= k)
+ {
+ if (*c == '\n')
+ {
+ if (w > mw)
+ mw = 0;
+ h += font->height;
+ continue;
+ }
+
+ w += psplash_font_glyph (font, wc, NULL);
+ }
+
+ *width = (w > mw) ? w : mw;
+ *height = (h == 0) ? font->height : h;
+}
+
+void
+psplash_fb_draw_text (PSplashFB *fb,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue,
+ const PSplashFont *font,
+ const char *text)
+{
+ int h, w, k, n, cx, cy, dx, dy;
+ char *c = (char*)text;
+ wchar_t wc;
+
+ n = strlen (text);
+ h = font->height;
+ dx = dy = 0;
+
+ mbtowc (0, 0, 0);
+ for (; (k = mbtowc (&wc, c, n)) > 0; c += k, n -= k)
+ {
+ u_int32_t *glyph = NULL;
+
+ if (*c == '\n')
+ {
+ dy += h;
+ dx = 0;
+ continue;
+ }
+
+ w = psplash_font_glyph (font, wc, &glyph);
+
+ if (glyph == NULL)
+ continue;
+
+ for (cy = 0; cy < h; cy++)
+ {
+ u_int32_t g = *glyph++;
+
+ for (cx = 0; cx < w; cx++)
+ {
+ if (g & 0x80000000)
+ psplash_fb_plot_pixel (fb, x+dx+cx, y+dy+cy,
+ red, green, blue);
+ g <<= 1;
+ }
+ }
+
+ dx += w;
+ }
+}
+