diff --git a/blitbuffer.c b/blitbuffer.c
index 5e0458867..a5b156487 100644
--- a/blitbuffer.c
+++ b/blitbuffer.c
@@ -16,17 +16,26 @@
along with this program. If not, see .
*/
+#include
+#include
#include "blitbuffer.h"
static int newBlitBuffer(lua_State *L) {
int w = luaL_checkint(L, 1);
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");
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");
+ }
+ memset(bb->data, 0, bb->pitch * h);
+ bb->allocated = 1;
return 1;
}
@@ -45,7 +54,275 @@ static int getHeight(lua_State *L) {
static int freeBlitBuffer(lua_State *L) {
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;
}
@@ -57,7 +334,12 @@ static const struct luaL_reg blitbuffer_func[] = {
static const struct luaL_reg blitbuffer_meth[] = {
{"getWidth", getWidth},
{"getHeight", getHeight},
+ {"blitFrom", blitToBuffer},
+ {"addblitFrom", addblitToBuffer},
+ {"blitFullFrom", blitFullToBuffer},
+ {"paintRect", paintRect},
{"free", freeBlitBuffer},
+ {"__gc", freeBlitBuffer},
{NULL, NULL}
};
diff --git a/blitbuffer.h b/blitbuffer.h
index 36e8f159a..6b1774938 100644
--- a/blitbuffer.h
+++ b/blitbuffer.h
@@ -26,7 +26,9 @@
typedef struct BlitBuffer {
int w;
int h;
- uint8_t data[1];
+ int pitch;
+ uint8_t *data;
+ uint8_t allocated;
} BlitBuffer;
int luaopen_blitbuffer(lua_State *L);
diff --git a/einkfb.c b/einkfb.c
index 181fb3024..215ad71d0 100644
--- a/einkfb.c
+++ b/einkfb.c
@@ -20,7 +20,6 @@
#include
#include
//#include
-#include "blitbuffer.h"
#include "einkfb.h"
@@ -29,6 +28,13 @@ static int openFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) lua_newuserdata(L, sizeof(FBInfo));
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);
#ifndef EMULATE_READER
@@ -72,9 +78,9 @@ static int openFrameBuffer(lua_State *L) {
}
/* 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);
- if(fb->data == MAP_FAILED) {
+ if(fb->buf.data == MAP_FAILED) {
return luaL_error(L, "cannot mmap framebuffer");
}
#else
@@ -91,12 +97,19 @@ static int openFrameBuffer(lua_State *L) {
fb->vinfo.yres = EMULATE_READER_H;
fb->vinfo.grayscale = 1;
fb->vinfo.bits_per_pixel = 4;
- fb->finfo.smem_len = EMULATE_READER_W * EMULATE_READER_H / 2;
- fb->finfo.line_length = EMULATE_READER_W / 2;
+ fb->finfo.smem_len = ((EMULATE_READER_W + 1) / 2) * EMULATE_READER_H;
+ fb->finfo.line_length = (EMULATE_READER_W + 1) / 2;
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
- 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;
}
@@ -110,232 +123,18 @@ static int getSize(lua_State *L) {
static int closeFrameBuffer(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
+ if(fb->buf != NULL && fb->buf->data != NULL) {
#ifndef EMULATE_READER
- munmap(fb->data, fb->finfo.smem_len);
- close(fb->fd);
+ munmap(fb->buf->data, fb->finfo.smem_len);
+ close(fb->fd);
#else
- free(fb->data);
+ free(fb->buf->data);
#endif
- return 0;
-}
-
-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);
- }
+ fb->buf->data = NULL;
}
return 0;
}
-static int paintRect(lua_State *L) {
- FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
-}
-
static int einkUpdate(lua_State *L) {
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
// for Kindle e-ink display
@@ -355,7 +154,7 @@ static int einkUpdate(lua_State *L) {
return luaL_error(L, "can't lock surface.");
}
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;
@@ -385,11 +184,9 @@ static const struct luaL_reg einkfb_func[] = {
static const struct luaL_reg einkfb_meth[] = {
{"close", closeFrameBuffer},
+ {"__gc", closeFrameBuffer},
{"refresh", einkUpdate},
{"getSize", getSize},
- {"blitFrom", blitToFrameBuffer},
- {"addblitFrom", addblitToFrameBuffer},
- {"blitFullFrom", blitFullToFrameBuffer},
{NULL, NULL}
};
diff --git a/einkfb.h b/einkfb.h
index cf760d037..883619021 100644
--- a/einkfb.h
+++ b/einkfb.h
@@ -29,9 +29,11 @@
#include
#include
+#include "blitbuffer.h"
+
typedef struct FBInfo {
int fd;
- void *data;
+ BlitBuffer *buf;
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
#ifdef EMULATE_READER
diff --git a/ft.c b/ft.c
index 3370b0ff5..312de3fe9 100644
--- a/ft.c
+++ b/ft.c
@@ -107,15 +107,24 @@ static int renderGlyph(lua_State *L) {
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;
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");
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");
bb->w = w;
@@ -128,14 +137,13 @@ static int renderGlyph(lua_State *L) {
for(y = 0; y < h; y++) {
uint8_t *src = (*face)->glyph->bitmap.buffer + y * (*face)->glyph->bitmap.pitch;
for(x = 0; x < w; x+=2) {
- *dst = *src & 0xF0;
- src++;
- if(x+1 < w) {
- *dst |= (*src & 0xF0) >> 4;
- src++;
- }
+ *dst = (src[0] & 0xF0) | (src[1] >> 4);
+ src+=2;
dst++;
}
+ if(w & 1) {
+ *dst = (*src & 0xF0) >> 4;
+ }
}
lua_pushinteger(L, (*face)->glyph->bitmap_left);
diff --git a/reader.lua b/reader.lua
index ee9628d3f..8df84b4b9 100755
--- a/reader.lua
+++ b/reader.lua
@@ -192,7 +192,7 @@ function show(no)
else
slot = draworcache(no,globalzoom,offset_x,offset_y,width,height,globalgamma)
end
- fb:blitFullFrom(cache[slot].bb)
+ fb.bb:blitFullFrom(cache[slot].bb)
if rcount == rcountmax then
print("full refresh")
rcount = 1
diff --git a/rendertext.lua b/rendertext.lua
index 9a5b62a3f..045361407 100644
--- a/rendertext.lua
+++ b/rendertext.lua
@@ -43,7 +43,7 @@ function clearglyphcache()
glyphcache = {}
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,
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
local pen_x = 0
@@ -54,9 +54,9 @@ function renderUtf8Text(x, y, face, facehash, text, kerning)
if kerning and prevcharcode then
local kern = face:getKerning(prevcharcode, charcode)
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
- 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
pen_x = pen_x + glyph.ax
prevcharcode = charcode
diff --git a/rendertext_example.lua b/rendertext_example.lua
index b8b7d1c5e..70e8c9472 100644
--- a/rendertext_example.lua
+++ b/rendertext_example.lua
@@ -5,16 +5,16 @@ width, height = fb:getSize()
print("open")
--- face = freetype.newBuiltinFace("Helvetica", 64)
-face = freetype.newFace("test.ttf", 64)
+face = freetype.newBuiltinFace("sans", 64)
+--face = freetype.newFace("test.ttf", 64)
print("got face")
if face:hasKerning() then
print("has kerning")
end
-renderUtf8Text(100,100,face,"h","AV T.T: gxyt!",true)
-renderUtf8Text(100,200,face,"h","AV T.T: gxyt!",false)
+renderUtf8Text(fb.bb, 100, 100, face, "h", "AV T.T: gxyt!", true)
+renderUtf8Text(fb.bb, 100, 200, face, "h", "AV T.T: gxyt!", false)
fb:refresh()