2016-09-22 19:18:50 +01:00
|
|
|
/**
|
2014-06-13 21:01:19 +01:00
|
|
|
* Copyright (c) 2014 rxi
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or modify it
|
|
|
|
|
* under the terms of the MIT license. See LICENSE for details.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "lib/dmt/dmt.h"
|
|
|
|
|
#include "font.h"
|
|
|
|
|
#include "luaobj.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *font_init(font_t *self, const char *filename) {
|
|
|
|
|
memset(self, 0, sizeof(*self));
|
2016-09-22 19:18:50 +01:00
|
|
|
const char *err = image_init(&self->image, filename);
|
2014-06-13 21:01:19 +01:00
|
|
|
if (err) return err;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-06-14 14:14:09 +01:00
|
|
|
const char *font_initEmbedded(font_t *self) {
|
|
|
|
|
#include "font_embedded.c"
|
|
|
|
|
memset(self, 0, sizeof(*self));
|
|
|
|
|
image_initBlank(&self->image, font_width, font_height);
|
|
|
|
|
int i, j;
|
|
|
|
|
char *p = font_data;
|
|
|
|
|
for (i = 0; i < font_width * font_height; i += 8) {
|
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
|
int res = (*p >> j) & 1;
|
|
|
|
|
self->image.data[i + j] = res ? 0xf : 0x00;
|
|
|
|
|
self->image.mask[i + j] = res ? 0x0 : 0xff;
|
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-06-13 21:01:19 +01:00
|
|
|
void font_deinit(font_t *self) {
|
|
|
|
|
image_deinit(&self->image);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern int image_blendMode;
|
2014-06-15 11:50:04 +01:00
|
|
|
extern int image_flip;
|
2014-06-13 21:01:19 +01:00
|
|
|
|
|
|
|
|
void font_blit(font_t *self, pixel_t *buf, int bufw, int bufh,
|
|
|
|
|
const char *str, int dx, int dy
|
|
|
|
|
) {
|
|
|
|
|
int cw = self->image.width / 16;
|
|
|
|
|
int ch = self->image.height / 16;
|
|
|
|
|
int cws = (cw + self->charSpacing);
|
|
|
|
|
int chs = (ch + self->lineSpacing);
|
|
|
|
|
|
|
|
|
|
const char *p = str;
|
|
|
|
|
int x = dx;
|
|
|
|
|
int y = dy;
|
2014-06-15 11:50:04 +01:00
|
|
|
|
2014-06-13 21:01:19 +01:00
|
|
|
int oldBlendMode = image_blendMode;
|
2014-06-15 11:50:04 +01:00
|
|
|
int oldFlip = image_flip;
|
2014-06-13 21:01:19 +01:00
|
|
|
image_blendMode = IMAGE_COLOR;
|
2014-06-15 11:50:04 +01:00
|
|
|
image_flip = 0;
|
2014-06-13 21:01:19 +01:00
|
|
|
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == '\n') {
|
|
|
|
|
x = dx;
|
|
|
|
|
y += chs;
|
|
|
|
|
} else {
|
2016-09-22 19:18:50 +01:00
|
|
|
if (*p != ' ') {
|
2014-06-13 21:01:19 +01:00
|
|
|
image_blit(&self->image, buf, bufw, bufh,
|
|
|
|
|
x, y, cw * (*p % 16), ch * (*p / 16), cw, ch);
|
|
|
|
|
}
|
|
|
|
|
x += cws;
|
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_blendMode = oldBlendMode;
|
2014-06-15 11:50:04 +01:00
|
|
|
image_flip = oldFlip;
|
2014-06-13 21:01:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CLASS_TYPE LUAOBJ_TYPE_FONT
|
|
|
|
|
#define CLASS_NAME "Font"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_new(lua_State *L) {
|
2014-06-14 14:20:04 +01:00
|
|
|
const char *filename = lua_isnoneornil(L, 1) ? NULL : luaL_checkstring(L, 1);
|
2014-06-13 21:01:19 +01:00
|
|
|
font_t *self = luaobj_newudata(L, sizeof(*self));
|
|
|
|
|
luaobj_setclass(L, CLASS_TYPE, CLASS_NAME);
|
2014-06-14 14:20:04 +01:00
|
|
|
if (filename) {
|
|
|
|
|
const char *err = font_init(self, filename);
|
|
|
|
|
if (err) luaL_error(L, err);
|
|
|
|
|
} else {
|
|
|
|
|
font_initEmbedded(self);
|
|
|
|
|
}
|
2014-06-13 21:01:19 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_gc(lua_State *L) {
|
|
|
|
|
font_t *self = luaobj_checkudata(L, 1, CLASS_TYPE);
|
|
|
|
|
font_deinit(self);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_getDimensions(lua_State *L) {
|
|
|
|
|
font_t *self = luaobj_checkudata(L, 1, CLASS_TYPE);
|
|
|
|
|
int charWidth = (self->image.width / 16) + self->charSpacing;
|
|
|
|
|
int charHeight = (self->image.height / 16) + self->lineSpacing;
|
|
|
|
|
int count = 0, max = 0, lines = 1;
|
|
|
|
|
const char *p = luaL_checkstring(L, 2);
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == '\n') {
|
|
|
|
|
max = count > max ? count : max;
|
|
|
|
|
count = 0;
|
|
|
|
|
lines++;
|
|
|
|
|
} else {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
max = count > max ? count : max;
|
|
|
|
|
lua_pushinteger(L, max * charWidth);
|
|
|
|
|
lua_pushinteger(L, lines * charHeight);
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_getWidth(lua_State *L) {
|
|
|
|
|
font_t *self = luaobj_checkudata(L, 1, CLASS_TYPE);
|
|
|
|
|
int charWidth = (self->image.width / 16) + self->charSpacing;
|
|
|
|
|
if (lua_isnoneornil(L, 2)) {
|
|
|
|
|
lua_pushinteger(L, charWidth);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
int count = 0, max = 0;
|
|
|
|
|
const char *p = luaL_checkstring(L, 2);
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == '\n') {
|
|
|
|
|
max = count > max ? count : max;
|
|
|
|
|
count = 0;
|
|
|
|
|
} else {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
max = count > max ? count : max;
|
|
|
|
|
lua_pushinteger(L, max * charWidth);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_getHeight(lua_State *L) {
|
|
|
|
|
font_t *self = luaobj_checkudata(L, 1, CLASS_TYPE);
|
|
|
|
|
int charHeight = (self->image.height / 16) + self->lineSpacing;
|
|
|
|
|
if (lua_isnoneornil(L, 2)) {
|
|
|
|
|
lua_pushinteger(L, charHeight);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
const char *p = luaL_checkstring(L, 2);
|
|
|
|
|
int lines = 1;
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == '\n') {
|
|
|
|
|
lines++;
|
|
|
|
|
}
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
lua_pushinteger(L, lines * charHeight);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_setLineSpacing(lua_State *L) {
|
|
|
|
|
font_t *self = luaobj_checkudata(L, 1, CLASS_TYPE);
|
|
|
|
|
int x = luaL_checkinteger(L, 2);
|
|
|
|
|
self->lineSpacing = x;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int l_font_setCharSpacing(lua_State *L) {
|
|
|
|
|
font_t *self = luaobj_checkudata(L, 1, CLASS_TYPE);
|
|
|
|
|
int x = luaL_checkinteger(L, 2);
|
|
|
|
|
self->charSpacing = x;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int luaopen_font(lua_State *L) {
|
|
|
|
|
luaL_Reg reg[] = {
|
|
|
|
|
{ "new", l_font_new },
|
|
|
|
|
{ "__gc", l_font_gc },
|
|
|
|
|
{ "getDimensions", l_font_getDimensions },
|
|
|
|
|
{ "getWidth", l_font_getWidth },
|
|
|
|
|
{ "getHeight", l_font_getHeight },
|
|
|
|
|
{ "setLineSpacing", l_font_setLineSpacing },
|
|
|
|
|
{ "setCharSpacing", l_font_setCharSpacing },
|
|
|
|
|
{ 0, 0 },
|
|
|
|
|
};
|
|
|
|
|
luaobj_newclass(L, CLASS_NAME, NULL, l_font_new, reg);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|