moved blitting over to blitbuffer API

the framebuffer "object" now has a "member" that exposes the blitbuffer
API for the framebuffer pixmap. This allows to reuse blitting & Co for
blitbuffer-to-blitbuffer operations
pull/2/merge
HW 13 years ago
parent dfbdad5cbf
commit f739baff5f

@ -16,17 +16,26 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h>
#include <string.h>
#include "blitbuffer.h" #include "blitbuffer.h"
static int newBlitBuffer(lua_State *L) { static int newBlitBuffer(lua_State *L) {
int w = luaL_checkint(L, 1); int w = luaL_checkint(L, 1);
int h = luaL_checkint(L, 2); int h = luaL_checkint(L, 2);
BlitBuffer *bb = (BlitBuffer*) lua_newuserdata(L, sizeof(BlitBuffer) + (w * h / 2) - 1); BlitBuffer *bb = (BlitBuffer*) lua_newuserdata(L, sizeof(BlitBuffer));
luaL_getmetatable(L, "blitbuffer"); luaL_getmetatable(L, "blitbuffer");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
bb->w = w; bb->w = w;
bb->pitch = (w + 1) / 2;
bb->h = h; bb->h = h;
bb->data = malloc(bb->pitch * h);
if(bb->data == NULL) {
return luaL_error(L, "cannot allocate memory for blitbuffer");
}
memset(bb->data, 0, bb->pitch * h);
bb->allocated = 1;
return 1; return 1;
} }
@ -45,7 +54,275 @@ static int getHeight(lua_State *L) {
static int freeBlitBuffer(lua_State *L) { static int freeBlitBuffer(lua_State *L) {
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer"); BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer");
// lua will free the memory for the buffer itself if(bb->allocated && bb->data != NULL) {
free(bb->data);
bb->data = NULL;
}
return 0;
}
static int blitFullToBuffer(lua_State *L) {
BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer");
BlitBuffer *src = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
if(src->w != dst->w || src->h != dst->h) {
return luaL_error(L, "blitbuffer size must be framebuffer size!");
}
memcpy(dst->data, src->data, src->pitch * src->h);
return 0;
}
static int blitToBuffer(lua_State *L) {
BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer");
BlitBuffer *src = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
int xdest = luaL_checkint(L, 3);
int ydest = luaL_checkint(L, 4);
int xoffs = luaL_checkint(L, 5);
int yoffs = luaL_checkint(L, 6);
int w = luaL_checkint(L, 7);
int h = luaL_checkint(L, 8);
int x, y;
// check bounds
if(yoffs >= src->h) {
return 0;
} else if(yoffs + h > src->h) {
h = src->h - yoffs;
}
if(ydest >= dst->h) {
return 0;
} else if(ydest + h > dst->h) {
h = dst->h - ydest;
}
if(xoffs >= src->w) {
return 0;
} else if(xoffs + w > src->w) {
w = src->w - xoffs;
}
if(xdest >= dst->w) {
return 0;
} else if(xdest + w > dst->w) {
w = dst->w - xdest;
}
uint8_t *dstptr;
uint8_t *srcptr;
if(xdest & 1) {
/* this will render the leftmost column */
dstptr = (uint8_t*)(dst->data +
ydest * dst->pitch +
xdest / 2);
srcptr = (uint8_t*)(src->data +
yoffs * src->pitch +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
*dstptr &= 0xF0;
*dstptr |= *srcptr & 0x0F;
dstptr += dst->pitch;
srcptr += src->pitch;
}
} else {
for(y = 0; y < h; y++) {
*dstptr &= 0xF0;
*dstptr |= *srcptr >> 4;
dstptr += dst->pitch;
srcptr += src->pitch;
}
}
xdest++;
xoffs++;
w--;
}
dstptr = (uint8_t*)(dst->data +
ydest * dst->pitch +
xdest / 2);
srcptr = (uint8_t*)(src->data +
yoffs * src->pitch +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
dstptr[x] = (srcptr[x] << 4) | (srcptr[x+1] >> 4);
}
if(w & 1) {
dstptr[x] &= 0x0F;
dstptr[x] |= srcptr[x] << 4;
}
dstptr += dst->pitch;
srcptr += src->pitch;
}
} else {
for(y = 0; y < h; y++) {
memcpy(dstptr, srcptr, w / 2);
if(w & 1) {
dstptr[w/2] &= 0x0F;
dstptr[w/2] |= (srcptr[w/2] & 0xF0);
}
dstptr += dst->pitch;
srcptr += src->pitch;
}
}
return 0;
}
static int addblitToBuffer(lua_State *L) {
BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer");
BlitBuffer *src = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
int xdest = luaL_checkint(L, 3);
int ydest = luaL_checkint(L, 4);
int xoffs = luaL_checkint(L, 5);
int yoffs = luaL_checkint(L, 6);
int w = luaL_checkint(L, 7);
int h = luaL_checkint(L, 8);
int x, y;
// check bounds
if(yoffs >= src->h) {
return 0;
} else if(yoffs + h > src->h) {
h = src->h - yoffs;
}
if(ydest >= dst->h) {
return 0;
} else if(ydest + h > dst->h) {
h = dst->h - ydest;
}
if(xoffs >= src->w) {
return 0;
} else if(xoffs + w > src->w) {
w = src->w - xoffs;
}
if(xdest >= dst->w) {
return 0;
} else if(xdest + w > dst->w) {
w = dst->w - xdest;
}
uint8_t *dstptr;
uint8_t *srcptr;
if(xdest & 1) {
/* this will render the leftmost column */
dstptr = (uint8_t*)(dst->data +
ydest * dst->pitch +
xdest / 2);
srcptr = (uint8_t*)(src->data +
yoffs * src->pitch +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
uint8_t v = (*dstptr & 0x0F) + (*srcptr & 0x0F);
*dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F);
dstptr += dst->pitch;
srcptr += src->pitch;
}
} else {
for(y = 0; y < h; y++) {
uint8_t v = (*dstptr & 0x0F) + (*srcptr >> 4);
*dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F);
dstptr += dst->pitch;
srcptr += src->pitch;
}
}
xdest++;
xoffs++;
w--;
}
dstptr = (uint8_t*)(dst->data +
ydest * dst->pitch +
xdest / 2);
srcptr = (uint8_t*)(src->data +
yoffs * src->pitch +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4);
uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x+1] >> 4);
dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
}
if(w & 1) {
uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4);
dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
}
dstptr += dst->pitch;
srcptr += src->pitch;
}
} else {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0);
uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x] & 0x0F);
dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
}
if(w & 1) {
uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0);
dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
}
dstptr += dst->pitch;
srcptr += src->pitch;
}
}
return 0;
}
static int paintRect(lua_State *L) {
BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer");
int x = luaL_checkint(L, 2);
int y = luaL_checkint(L, 3);
int w = luaL_checkint(L, 4);
int h = luaL_checkint(L, 5);
int c = luaL_checkint(L, 6);
uint8_t *dstptr;
int cy;
if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) {
return 0;
}
if(x + w > dst->w) {
w = dst->w - x;
}
if(y + h > dst->h) {
h = dst->h - y;
}
if(x & 1) {
/* this will render the leftmost column */
dstptr = (uint8_t*)(dst->data +
y * dst->pitch +
x / 2);
for(cy = 0; cy < h; cy++) {
*dstptr &= 0xF0;
*dstptr |= c;
dstptr += dst->pitch;
}
x++;
w--;
}
dstptr = (uint8_t*)(dst->data +
y * dst->pitch +
x / 2);
for(cy = 0; cy < h; cy++) {
memset(dstptr, c | (c << 4), w / 2);
}
if(w & 1) {
dstptr = (uint8_t*)(dst->data +
y * dst->pitch +
(x + w + 1) / 2);
for(cy = 0; cy < h; cy++) {
*dstptr &= 0x0F;
*dstptr |= (c << 4);
dstptr += dst->pitch;
}
}
return 0; return 0;
} }
@ -57,7 +334,12 @@ static const struct luaL_reg blitbuffer_func[] = {
static const struct luaL_reg blitbuffer_meth[] = { static const struct luaL_reg blitbuffer_meth[] = {
{"getWidth", getWidth}, {"getWidth", getWidth},
{"getHeight", getHeight}, {"getHeight", getHeight},
{"blitFrom", blitToBuffer},
{"addblitFrom", addblitToBuffer},
{"blitFullFrom", blitFullToBuffer},
{"paintRect", paintRect},
{"free", freeBlitBuffer}, {"free", freeBlitBuffer},
{"__gc", freeBlitBuffer},
{NULL, NULL} {NULL, NULL}
}; };

@ -26,7 +26,9 @@
typedef struct BlitBuffer { typedef struct BlitBuffer {
int w; int w;
int h; int h;
uint8_t data[1]; int pitch;
uint8_t *data;
uint8_t allocated;
} BlitBuffer; } BlitBuffer;
int luaopen_blitbuffer(lua_State *L); int luaopen_blitbuffer(lua_State *L);

@ -20,7 +20,6 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <fcntl.h> #include <fcntl.h>
//#include <stdio.h> //#include <stdio.h>
#include "blitbuffer.h"
#include "einkfb.h" #include "einkfb.h"
@ -29,6 +28,13 @@ static int openFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) lua_newuserdata(L, sizeof(FBInfo)); FBInfo *fb = (FBInfo*) lua_newuserdata(L, sizeof(FBInfo));
luaL_getmetatable(L, "einkfb"); luaL_getmetatable(L, "einkfb");
fb->buf = (BlitBuffer*) lua_newuserdata(L, sizeof(BlitBuffer));
luaL_getmetatable(L, "blitbuffer");
lua_setmetatable(L, -2);
lua_setfield(L, -2, "bb");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
#ifndef EMULATE_READER #ifndef EMULATE_READER
@ -72,9 +78,9 @@ static int openFrameBuffer(lua_State *L) {
} }
/* mmap the framebuffer */ /* mmap the framebuffer */
fb->data = mmap(0, fb->finfo.smem_len, fb->buf.data = mmap(0, fb->finfo.smem_len,
PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0); PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
if(fb->data == MAP_FAILED) { if(fb->buf.data == MAP_FAILED) {
return luaL_error(L, "cannot mmap framebuffer"); return luaL_error(L, "cannot mmap framebuffer");
} }
#else #else
@ -91,12 +97,19 @@ static int openFrameBuffer(lua_State *L) {
fb->vinfo.yres = EMULATE_READER_H; fb->vinfo.yres = EMULATE_READER_H;
fb->vinfo.grayscale = 1; fb->vinfo.grayscale = 1;
fb->vinfo.bits_per_pixel = 4; fb->vinfo.bits_per_pixel = 4;
fb->finfo.smem_len = EMULATE_READER_W * EMULATE_READER_H / 2; fb->finfo.smem_len = ((EMULATE_READER_W + 1) / 2) * EMULATE_READER_H;
fb->finfo.line_length = EMULATE_READER_W / 2; fb->finfo.line_length = (EMULATE_READER_W + 1) / 2;
fb->finfo.type = FB_TYPE_PACKED_PIXELS; fb->finfo.type = FB_TYPE_PACKED_PIXELS;
fb->data = malloc(fb->finfo.smem_len); fb->buf->data = malloc(fb->finfo.smem_len);
if(fb->buf->data == NULL) {
return luaL_error(L, "cannot get framebuffer emu memory");
}
#endif #endif
memset(fb->data, 0, fb->finfo.smem_len); memset(fb->buf->data, 0, fb->finfo.smem_len);
fb->buf->w = fb->vinfo.xres;
fb->buf->h = fb->vinfo.yres;
fb->buf->pitch = fb->finfo.line_length;
fb->buf->allocated = 0;
return 1; return 1;
} }
@ -110,232 +123,18 @@ static int getSize(lua_State *L) {
static int closeFrameBuffer(lua_State *L) { static int closeFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb"); FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
if(fb->buf != NULL && fb->buf->data != NULL) {
#ifndef EMULATE_READER #ifndef EMULATE_READER
munmap(fb->data, fb->finfo.smem_len); munmap(fb->buf->data, fb->finfo.smem_len);
close(fb->fd); close(fb->fd);
#else #else
free(fb->data); free(fb->buf->data);
#endif #endif
return 0; fb->buf->data = NULL;
}
static int blitFullToFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
if(bb->w != fb->vinfo.xres || bb->h != fb->vinfo.yres) {
return luaL_error(L, "blitbuffer size must be framebuffer size!");
}
memcpy(fb->data, bb->data, bb->w * bb->h / 2);
return 0;
}
static int blitToFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
int xdest = luaL_checkint(L, 3);
int ydest = luaL_checkint(L, 4);
int xoffs = luaL_checkint(L, 5);
int yoffs = luaL_checkint(L, 6);
int w = luaL_checkint(L, 7);
int h = luaL_checkint(L, 8);
int x, y;
// check bounds
if(yoffs >= bb->h) {
return 0;
} else if(yoffs + h > bb->h) {
h = bb->h - yoffs;
}
if(ydest >= fb->vinfo.yres) {
return 0;
} else if(ydest + h > fb->vinfo.yres) {
h = fb->vinfo.yres - ydest;
}
if(xoffs >= bb->w) {
return 0;
} else if(xoffs + w > bb->w) {
w = bb->w - xoffs;
}
if(xdest >= fb->vinfo.xres) {
return 0;
} else if(xdest + w > fb->vinfo.xres) {
w = fb->vinfo.xres - xdest;
}
uint8_t *fbptr;
uint8_t *bbptr;
if(xdest & 1) {
/* this will render the leftmost column */
fbptr = (uint8_t*)(fb->data +
ydest * fb->finfo.line_length +
xdest / 2);
bbptr = (uint8_t*)(bb->data +
yoffs * bb->w / 2 +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
*fbptr &= 0xF0;
*fbptr |= *bbptr & 0x0F;
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
} else {
for(y = 0; y < h; y++) {
*fbptr &= 0xF0;
*fbptr |= *bbptr >> 4;
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
}
xdest++;
xoffs++;
w--;
}
fbptr = (uint8_t*)(fb->data +
ydest * fb->finfo.line_length +
xdest / 2);
bbptr = (uint8_t*)(bb->data +
yoffs * bb->w / 2 +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
fbptr[x] = (bbptr[x] << 4) | (bbptr[x+1] >> 4);
}
if(w & 1) {
fbptr[x] &= 0x0F;
fbptr[x] |= bbptr[x] << 4;
}
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
} else {
for(y = 0; y < h; y++) {
memcpy(fbptr, bbptr, w / 2);
if(w & 1) {
fbptr[w/2 + 1] &= 0x0F;
fbptr[w/2 + 1] |= bbptr[w/2 + 1] << 4;
}
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
}
return 0;
}
static int addblitToFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
int xdest = luaL_checkint(L, 3);
int ydest = luaL_checkint(L, 4);
int xoffs = luaL_checkint(L, 5);
int yoffs = luaL_checkint(L, 6);
int w = luaL_checkint(L, 7);
int h = luaL_checkint(L, 8);
int x, y;
// check bounds
if(yoffs >= bb->h) {
return 0;
} else if(yoffs + h > bb->h) {
h = bb->h - yoffs;
}
if(ydest >= fb->vinfo.yres) {
return 0;
} else if(ydest + h > fb->vinfo.yres) {
h = fb->vinfo.yres - ydest;
}
if(xoffs >= bb->w) {
return 0;
} else if(xoffs + w > bb->w) {
w = bb->w - xoffs;
}
if(xdest >= fb->vinfo.xres) {
return 0;
} else if(xdest + w > fb->vinfo.xres) {
w = fb->vinfo.xres - xdest;
}
uint8_t *fbptr;
uint8_t *bbptr;
if(xdest & 1) {
/* this will render the leftmost column */
fbptr = (uint8_t*)(fb->data +
ydest * fb->finfo.line_length +
xdest / 2);
bbptr = (uint8_t*)(bb->data +
yoffs * bb->w / 2 +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
uint8_t v = (*fbptr & 0x0F) + (*bbptr & 0x0F);
*fbptr = (*fbptr & 0xF0) | (v < 0x0F ? v : 0x0F);
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
} else {
for(y = 0; y < h; y++) {
uint8_t v = (*fbptr & 0x0F) + (*bbptr >> 4);
*fbptr = (*fbptr & 0xF0) | (v < 0x0F ? v : 0x0F);
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
}
xdest++;
xoffs++;
w--;
}
fbptr = (uint8_t*)(fb->data +
ydest * fb->finfo.line_length +
xdest / 2);
bbptr = (uint8_t*)(bb->data +
yoffs * bb->w / 2 +
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
uint16_t v1 = (fbptr[x] & 0xF0) + ((bbptr[x] & 0x0F) << 4);
uint8_t v2 = (fbptr[x] & 0x0F) + (bbptr[x+1] >> 4);
fbptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
}
if(w & 1) {
uint16_t v1 = (fbptr[x] & 0xF0) + ((bbptr[x] & 0x0F) << 4);
fbptr[x] = (fbptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
}
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
} else {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
uint16_t v1 = (fbptr[x] & 0xF0) + (bbptr[x] & 0xF0);
uint8_t v2 = (fbptr[x] & 0x0F) + (bbptr[x] & 0x0F);
fbptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
}
if(w & 1) {
uint16_t v1 = (fbptr[x] & 0xF0) + (bbptr[x] & 0xF0);
fbptr[x] = (fbptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
}
fbptr += fb->finfo.line_length;
bbptr += (bb->w / 2);
}
} }
return 0; return 0;
} }
static int paintRect(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
}
static int einkUpdate(lua_State *L) { static int einkUpdate(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb"); FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
// for Kindle e-ink display // for Kindle e-ink display
@ -355,7 +154,7 @@ static int einkUpdate(lua_State *L) {
return luaL_error(L, "can't lock surface."); return luaL_error(L, "can't lock surface.");
} }
uint32_t *sfptr = (uint32_t*)fb->screen->pixels; uint32_t *sfptr = (uint32_t*)fb->screen->pixels;
uint8_t *fbptr = (uint8_t*)fb->data; uint8_t *fbptr = (uint8_t*)fb->buf->data;
int c = fb->finfo.smem_len; int c = fb->finfo.smem_len;
@ -385,11 +184,9 @@ static const struct luaL_reg einkfb_func[] = {
static const struct luaL_reg einkfb_meth[] = { static const struct luaL_reg einkfb_meth[] = {
{"close", closeFrameBuffer}, {"close", closeFrameBuffer},
{"__gc", closeFrameBuffer},
{"refresh", einkUpdate}, {"refresh", einkUpdate},
{"getSize", getSize}, {"getSize", getSize},
{"blitFrom", blitToFrameBuffer},
{"addblitFrom", addblitToFrameBuffer},
{"blitFullFrom", blitFullToFrameBuffer},
{NULL, NULL} {NULL, NULL}
}; };

@ -29,9 +29,11 @@
#include <lualib.h> #include <lualib.h>
#include <lauxlib.h> #include <lauxlib.h>
#include "blitbuffer.h"
typedef struct FBInfo { typedef struct FBInfo {
int fd; int fd;
void *data; BlitBuffer *buf;
struct fb_fix_screeninfo finfo; struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo;
#ifdef EMULATE_READER #ifdef EMULATE_READER

24
ft.c

@ -107,15 +107,24 @@ static int renderGlyph(lua_State *L) {
return luaL_error(L, "freetype error"); return luaL_error(L, "freetype error");
} }
int w = ((*face)->glyph->bitmap.width + 1) & -2; // 2px steps int w = (*face)->glyph->bitmap.width; // 2px steps
int h = (*face)->glyph->bitmap.rows; int h = (*face)->glyph->bitmap.rows;
lua_newtable(L); lua_newtable(L);
BlitBuffer *bb = (BlitBuffer*) lua_newuserdata(L, sizeof(BlitBuffer) + (w * h / 2) - 1); BlitBuffer *bb = (BlitBuffer*) lua_newuserdata(L, sizeof(BlitBuffer));
luaL_getmetatable(L, "blitbuffer"); luaL_getmetatable(L, "blitbuffer");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
bb->w = w;
bb->pitch = (w + 1) / 2;
bb->h = h;
bb->data = malloc(bb->pitch * h);
if(bb->data == NULL) {
return luaL_error(L, "cannot allocate memory for blitbuffer");
}
bb->allocated = 1;
lua_setfield(L, -2, "bb"); lua_setfield(L, -2, "bb");
bb->w = w; bb->w = w;
@ -128,14 +137,13 @@ static int renderGlyph(lua_State *L) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
uint8_t *src = (*face)->glyph->bitmap.buffer + y * (*face)->glyph->bitmap.pitch; uint8_t *src = (*face)->glyph->bitmap.buffer + y * (*face)->glyph->bitmap.pitch;
for(x = 0; x < w; x+=2) { for(x = 0; x < w; x+=2) {
*dst = *src & 0xF0; *dst = (src[0] & 0xF0) | (src[1] >> 4);
src++; src+=2;
if(x+1 < w) {
*dst |= (*src & 0xF0) >> 4;
src++;
}
dst++; dst++;
} }
if(w & 1) {
*dst = (*src & 0xF0) >> 4;
}
} }
lua_pushinteger(L, (*face)->glyph->bitmap_left); lua_pushinteger(L, (*face)->glyph->bitmap_left);

@ -192,7 +192,7 @@ function show(no)
else else
slot = draworcache(no,globalzoom,offset_x,offset_y,width,height,globalgamma) slot = draworcache(no,globalzoom,offset_x,offset_y,width,height,globalgamma)
end end
fb:blitFullFrom(cache[slot].bb) fb.bb:blitFullFrom(cache[slot].bb)
if rcount == rcountmax then if rcount == rcountmax then
print("full refresh") print("full refresh")
rcount = 1 rcount = 1

@ -43,7 +43,7 @@ function clearglyphcache()
glyphcache = {} glyphcache = {}
end end
function renderUtf8Text(x, y, face, facehash, text, kerning) function renderUtf8Text(buffer, x, y, face, facehash, text, kerning)
-- may still need more adaptive pen placement when kerning, -- may still need more adaptive pen placement when kerning,
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html -- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
local pen_x = 0 local pen_x = 0
@ -54,9 +54,9 @@ function renderUtf8Text(x, y, face, facehash, text, kerning)
if kerning and prevcharcode then if kerning and prevcharcode then
local kern = face:getKerning(prevcharcode, charcode) local kern = face:getKerning(prevcharcode, charcode)
pen_x = pen_x + kern pen_x = pen_x + kern
fb:addblitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight()) buffer:addblitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
else else
fb:blitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight()) buffer:blitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
end end
pen_x = pen_x + glyph.ax pen_x = pen_x + glyph.ax
prevcharcode = charcode prevcharcode = charcode

@ -5,16 +5,16 @@ width, height = fb:getSize()
print("open") print("open")
-- face = freetype.newBuiltinFace("Helvetica", 64) face = freetype.newBuiltinFace("sans", 64)
face = freetype.newFace("test.ttf", 64) --face = freetype.newFace("test.ttf", 64)
print("got face") print("got face")
if face:hasKerning() then if face:hasKerning() then
print("has kerning") print("has kerning")
end end
renderUtf8Text(100,100,face,"h","AV T.T: gxyt!",true) renderUtf8Text(fb.bb, 100, 100, face, "h", "AV T.T: gxyt!", true)
renderUtf8Text(100,200,face,"h","AV T.T: gxyt!",false) renderUtf8Text(fb.bb, 100, 200, face, "h", "AV T.T: gxyt!", false)
fb:refresh() fb:refresh()

Loading…
Cancel
Save