render text with background and foreground 'color'

pull/2/merge
chrox 11 years ago
parent 1f01537751
commit 26e2435fc6

@ -329,6 +329,7 @@ static int addblitToBuffer(lua_State *L) {
int yoffs = luaL_checkint(L, 6); int yoffs = luaL_checkint(L, 6);
int w = luaL_checkint(L, 7); int w = luaL_checkint(L, 7);
int h = luaL_checkint(L, 8); int h = luaL_checkint(L, 8);
double p = luaL_checknumber(L, 9);
int x, y; int x, y;
uint8_t *dstptr; uint8_t *dstptr;
@ -349,7 +350,7 @@ static int addblitToBuffer(lua_State *L) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint8_t v = (*dstptr & 0x0F) + (*srcptr & 0x0F); uint8_t v = (int)((*dstptr & 0x0F)*(1-p) + (*srcptr & 0x0F)*p);
*dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F); *dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F);
dstptr += dst->pitch; dstptr += dst->pitch;
srcptr += src->pitch; srcptr += src->pitch;
@ -358,7 +359,7 @@ static int addblitToBuffer(lua_State *L) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint8_t v = (*dstptr & 0x0F) + (*srcptr >> 4); uint8_t v = (int)((*dstptr & 0x0F)*(1-p) + (*srcptr >> 4)*p);
*dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F); *dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F);
dstptr += dst->pitch; dstptr += dst->pitch;
srcptr += src->pitch; srcptr += src->pitch;
@ -381,14 +382,14 @@ static int addblitToBuffer(lua_State *L) {
for(x = 0; x < (w / 2); x++) { for(x = 0; x < (w / 2); x++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4); uint16_t v1 = (int)((dstptr[x] & 0xF0)*(1-p) + ((srcptr[x] & 0x0F) << 4)*p);
uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x+1] >> 4); uint8_t v2 = (int)((dstptr[x] & 0x0F)*(1-p) + (srcptr[x+1] >> 4)*p);
dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F); dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
} }
if(w & 1) { if(w & 1) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4); uint16_t v1 = (int)((dstptr[x] & 0xF0)*(1-p) + ((srcptr[x] & 0x0F) << 4)*p);
dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0); dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
} }
dstptr += dst->pitch; dstptr += dst->pitch;
@ -399,14 +400,14 @@ static int addblitToBuffer(lua_State *L) {
for(x = 0; x < (w / 2); x++) { for(x = 0; x < (w / 2); x++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0); uint16_t v1 = (int)((dstptr[x] & 0xF0)*(1-p) + (srcptr[x] & 0xF0)*p);
uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x] & 0x0F); uint8_t v2 = (int)((dstptr[x] & 0x0F)*(1-p) + (srcptr[x] & 0x0F)*p);
dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F); dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
} }
if(w & 1) { if(w & 1) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr); ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr); ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0); uint16_t v1 = (int)((dstptr[x] & 0xF0)*(1-p) + (srcptr[x] & 0xF0)*p);
dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0); dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
} }
dstptr += dst->pitch; dstptr += dst->pitch;

@ -4,14 +4,16 @@ require "cache"
TODO: all these functions should probably be methods on Face objects TODO: all these functions should probably be methods on Face objects
]]-- ]]--
function getGlyph(face, charcode) function getGlyph(face, charcode, bgcolor, fgcolor)
local hash = "glyph|"..face.hash.."|"..charcode if bgcolor == nil then bgcolor = 0.0 end
if fgcolor == nil then fgcolor = 1.0 end
local hash = "glyph|"..face.hash.."|"..charcode.."|"..bgcolor.."|"..fgcolor
local glyph = Cache:check(hash) local glyph = Cache:check(hash)
if glyph then if glyph then
-- cache hit -- cache hit
return glyph[1] return glyph[1]
end end
local rendered_glyph = face.ftface:renderGlyph(charcode) local rendered_glyph = face.ftface:renderGlyph(charcode, bgcolor, fgcolor)
if not rendered_glyph then if not rendered_glyph then
DEBUG("error rendering glyph (charcode=", charcode, ") for face", face) DEBUG("error rendering glyph (charcode=", charcode, ") for face", face)
return return
@ -75,7 +77,7 @@ function sizeUtf8Text(x, width, face, text, kerning)
return { x = pen_x, y_top = pen_y_top, y_bottom = pen_y_bottom} return { x = pen_x, y_top = pen_y_top, y_bottom = pen_y_bottom}
end end
function renderUtf8Text(buffer, x, y, face, text, kerning) function renderUtf8Text(buffer, x, y, face, text, kerning, bgcolor, fgcolor)
if not text then if not text then
DEBUG("renderUtf8Text called without text"); DEBUG("renderUtf8Text called without text");
return 0 return 0
@ -89,7 +91,7 @@ function renderUtf8Text(buffer, x, y, face, text, kerning)
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
if pen_x < buffer_width then if pen_x < buffer_width then
local charcode = util.utf8charcode(uchar) local charcode = util.utf8charcode(uchar)
local glyph = getGlyph(face, charcode) local glyph = getGlyph(face, charcode, bgcolor, fgcolor)
if kerning and (prevcharcode ~= 0) then if kerning and (prevcharcode ~= 0) then
pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode) pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode)
end end
@ -97,7 +99,7 @@ function renderUtf8Text(buffer, x, y, face, text, kerning)
glyph.bb, glyph.bb,
x + pen_x + glyph.l, y - glyph.t, x + pen_x + glyph.l, y - glyph.t,
0, 0, 0, 0,
glyph.bb:getWidth(), glyph.bb:getHeight()) glyph.bb:getWidth(), glyph.bb:getHeight(), 1)
pen_x = pen_x + glyph.ax pen_x = pen_x + glyph.ax
prevcharcode = charcode prevcharcode = charcode
end -- if pen_x < buffer_width end -- if pen_x < buffer_width

@ -67,6 +67,8 @@ static int newFace(lua_State *L) {
static int renderGlyph(lua_State *L) { static int renderGlyph(lua_State *L) {
KPVFace *face = (KPVFace*) luaL_checkudata(L, 1, "ft_face"); KPVFace *face = (KPVFace*) luaL_checkudata(L, 1, "ft_face");
int ch = luaL_checkint(L, 2); int ch = luaL_checkint(L, 2);
double bg = luaL_checknumber(L, 3);
double fg = luaL_checknumber(L, 4);
FT_Error error = FT_Load_Char(face->face, ch, FT_LOAD_RENDER); FT_Error error = FT_Load_Char(face->face, ch, FT_LOAD_RENDER);
if(error) { if(error) {
return luaL_error(L, "freetype error"); return luaL_error(L, "freetype error");
@ -91,12 +93,13 @@ static int renderGlyph(lua_State *L) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
uint8_t *src = face->face->glyph->bitmap.buffer + y * face->face->glyph->bitmap.pitch; uint8_t *src = face->face->glyph->bitmap.buffer + y * face->face->glyph->bitmap.pitch;
for(x = 0; x < (w/2); x++) { for(x = 0; x < (w/2); x++) {
*dst = (src[0] & 0xF0) | (src[1] >> 4); *dst = (int)(0xFF * bg - src[0] * (bg - fg)) & 0xF0 |
(int)(0xFF * bg - src[1] * (bg - fg)) >> 4;
src+=2; src+=2;
dst++; dst++;
} }
if(w & 1) { if(w & 1) {
*dst = *src & 0xF0; *dst = (int)(0xFF * bg - *src * (bg - fg)) & 0xF0;
dst++; dst++;
} }
} }

Loading…
Cancel
Save