* Smushing support. Yeah baby.
This commit is contained in:
parent
2427741182
commit
aefd454432
3 changed files with 144 additions and 27 deletions
135
src/figlet.c
135
src/figlet.c
|
@ -37,12 +37,19 @@ static int flush_figlet(context_t *);
|
|||
static int end_figlet(context_t *);
|
||||
|
||||
static int open_font(context_t *cx);
|
||||
static uint32_t smush(uint32_t, uint32_t, unsigned int);
|
||||
|
||||
int init_figlet(context_t *cx)
|
||||
{
|
||||
if(open_font(cx))
|
||||
return -1;
|
||||
|
||||
/* FIXME: read the font's contents */
|
||||
if(cx->hlayout == H_DEFAULT)
|
||||
cx->hlayout = H_SMUSH;
|
||||
|
||||
cx->charcv = cucul_create_canvas(cx->max_length - 2, cx->height);
|
||||
|
||||
cx->left = malloc(cx->height * sizeof(int));
|
||||
cx->right = malloc(cx->height * sizeof(int));
|
||||
|
||||
|
@ -55,7 +62,7 @@ int init_figlet(context_t *cx)
|
|||
|
||||
static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr)
|
||||
{
|
||||
unsigned int c, w, h, x, y, overlap, mx;
|
||||
unsigned int c, w, h, x, y, overlap, extra, xleft, xright;
|
||||
|
||||
switch(ch)
|
||||
{
|
||||
|
@ -79,6 +86,9 @@ static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr)
|
|||
w = cx->lookup[c * 2 + 1];
|
||||
h = cx->height;
|
||||
|
||||
cucul_set_canvas_handle(cx->fontcv, 0, c * cx->height);
|
||||
cucul_blit(cx->charcv, 0, 0, cx->fontcv, NULL);
|
||||
|
||||
/* Check whether we reached the end of the screen */
|
||||
if(cx->x && cx->x + w > cx->term_width)
|
||||
{
|
||||
|
@ -87,21 +97,48 @@ static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr)
|
|||
}
|
||||
|
||||
/* Compute how much the next character will overlap */
|
||||
switch(cx->hlayout)
|
||||
{
|
||||
case H_SMUSH:
|
||||
case H_KERN:
|
||||
case H_OVERLAP:
|
||||
extra = (cx->hlayout == H_OVERLAP);
|
||||
overlap = w;
|
||||
for(y = 0; y < h; y++)
|
||||
{
|
||||
/* Compute how much spaces we can eat from the new glyph */
|
||||
for(x = 0; x < overlap; x++)
|
||||
if(cucul_get_char(cx->image, x, y + c * cx->height) != ' ')
|
||||
for(xright = 0; xright < overlap; xright++)
|
||||
if(cucul_get_char(cx->charcv, xright, y) != ' ')
|
||||
break;
|
||||
|
||||
/* Compute how much spaces we can eat from the previous glyph */
|
||||
for(mx = 0; x + mx < overlap && mx < cx->x; mx++)
|
||||
if(cucul_get_char(cx->cv, cx->x - 1 - mx, cx->y + y) != ' ')
|
||||
for(xleft = 0; xright + xleft < overlap && xleft < cx->x; xleft++)
|
||||
if(cucul_get_char(cx->cv, cx->x - 1 - xleft, cx->y + y) != ' ')
|
||||
break;
|
||||
|
||||
if(x + mx < overlap)
|
||||
overlap = x + mx;
|
||||
/* Handle overlapping */
|
||||
if(cx->hlayout == H_OVERLAP && xleft < cx->x)
|
||||
xleft++;
|
||||
|
||||
/* Handle smushing */
|
||||
if(cx->hlayout == H_SMUSH)
|
||||
{
|
||||
if(xleft < cx->x &&
|
||||
smush(cucul_get_char(cx->charcv, xright, y),
|
||||
cucul_get_char(cx->cv, cx->x - 1 - xleft, cx->y + y),
|
||||
0))
|
||||
xleft++;
|
||||
}
|
||||
|
||||
if(xleft + xright < overlap)
|
||||
overlap = xleft + xright;
|
||||
}
|
||||
break;
|
||||
case H_NONE:
|
||||
overlap = 0;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check whether the current canvas is large enough */
|
||||
|
@ -120,14 +157,20 @@ static int feed_figlet(context_t *cx, uint32_t ch, uint32_t attr)
|
|||
for(y = 0; y < h; y++)
|
||||
for(x = 0; x < w; x++)
|
||||
{
|
||||
uint32_t tmpch = cucul_get_char(cx->image, x, y + c * cx->height);
|
||||
//uint32_t tmpat = cucul_get_attr(cx->image, x, y + c * cx->height);
|
||||
if(tmpch == ' ')
|
||||
uint32_t ch1, ch2;
|
||||
//uint32_t tmpat = cucul_get_attr(cx->fontcv, x, y + c * cx->height);
|
||||
ch2 = cucul_get_char(cx->charcv, x, y);
|
||||
if(ch2 == ' ')
|
||||
continue;
|
||||
ch1 = cucul_get_char(cx->cv, cx->x + x - overlap, cx->y + y);
|
||||
/* FIXME: this could be changed to cucul_put_attr() when the
|
||||
* function is fixed in libcucul */
|
||||
//cucul_set_attr(cx->cv, tmpat);
|
||||
cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y, tmpch);
|
||||
if(ch1 == ' ' || cx->hlayout != H_SMUSH)
|
||||
cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y, ch2);
|
||||
else
|
||||
cucul_put_char(cx->cv, cx->x + x - overlap, cx->y + y,
|
||||
smush(ch1, ch2, 0));
|
||||
//cucul_put_attr(cx->cv, cx->x + x, cx->y + y, tmpat);
|
||||
}
|
||||
|
||||
|
@ -165,7 +208,8 @@ static int end_figlet(context_t *cx)
|
|||
{
|
||||
free(cx->left);
|
||||
free(cx->right);
|
||||
cucul_free_canvas(cx->image);
|
||||
cucul_free_canvas(cx->charcv);
|
||||
cucul_free_canvas(cx->fontcv);
|
||||
free(cx->lookup);
|
||||
|
||||
return 0;
|
||||
|
@ -293,8 +337,8 @@ static int open_font(context_t *cx)
|
|||
}
|
||||
|
||||
/* Import buffer into canvas */
|
||||
cx->image = cucul_create_canvas(0, 0);
|
||||
cucul_import_memory(cx->image, data, i, "utf8");
|
||||
cx->fontcv = cucul_create_canvas(0, 0);
|
||||
cucul_import_memory(cx->fontcv, data, i, "utf8");
|
||||
free(data);
|
||||
|
||||
/* Remove EOL characters. For now we ignore hardblanks, don’t do any
|
||||
|
@ -305,11 +349,11 @@ static int open_font(context_t *cx)
|
|||
|
||||
for(i = cx->max_length; i--;)
|
||||
{
|
||||
ch = cucul_get_char(cx->image, i, j);
|
||||
ch = cucul_get_char(cx->fontcv, i, j);
|
||||
|
||||
/* Replace hardblanks with U+00A0 NO-BREAK SPACE */
|
||||
if(ch == cx->hardblank)
|
||||
cucul_put_char(cx->image, i, j, ch = 0xa0);
|
||||
cucul_put_char(cx->fontcv, i, j, ch = 0xa0);
|
||||
|
||||
if(oldch && ch != oldch)
|
||||
{
|
||||
|
@ -317,11 +361,11 @@ static int open_font(context_t *cx)
|
|||
cx->lookup[j / cx->height * 2 + 1] = i + 1;
|
||||
}
|
||||
else if(oldch && ch == oldch)
|
||||
cucul_put_char(cx->image, i, j, ' ');
|
||||
cucul_put_char(cx->fontcv, i, j, ' ');
|
||||
else if(ch != ' ')
|
||||
{
|
||||
oldch = ch;
|
||||
cucul_put_char(cx->image, i, j, ' ');
|
||||
cucul_put_char(cx->fontcv, i, j, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,3 +373,58 @@ static int open_font(context_t *cx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t smush(uint32_t ch1, uint32_t ch2, unsigned int mode)
|
||||
{
|
||||
|
||||
/* Rule 1 */
|
||||
if(ch1 == ch2 && ch1 != 0xa0)
|
||||
return ch2;
|
||||
|
||||
if(ch1 < 0x80 && ch2 < 0x80)
|
||||
{
|
||||
char const rule2[] = "|/\\[]{}()<>";
|
||||
char const rule3[] = "||/\\[]{}()<>";
|
||||
char *tmp1, *tmp2;
|
||||
uint16_t s, p;
|
||||
|
||||
/* Rule 2 */
|
||||
if(ch1 == '_' && strchr(rule2, ch2))
|
||||
return ch2;
|
||||
|
||||
/* Rule 3 */
|
||||
if((tmp1 = strchr(rule3, ch1)) && (tmp2 = strchr(rule3, ch2)))
|
||||
{
|
||||
int cl1 = (tmp1 - rule3) / 2;
|
||||
int cl2 = (tmp2 - rule3) / 2;
|
||||
|
||||
if(cl1 < cl2)
|
||||
return ch2;
|
||||
if(cl1 > cl2)
|
||||
return ch1;
|
||||
}
|
||||
|
||||
/* Rule 4 */
|
||||
s = ch1 + ch2;
|
||||
p = ch1 * ch2;
|
||||
|
||||
if(p == 15375 /* '{' * '}' */
|
||||
|| p == 8463 /* '[' * ']' */
|
||||
|| (p == 1640 && s == 81)) /* '(' *|+ ')' */
|
||||
return '|';
|
||||
|
||||
/* Rule 5 */
|
||||
switch((ch1 << 8) | ch2)
|
||||
{
|
||||
case 0x2f5c: return '|'; /* /\ */
|
||||
case 0x5c2f: return 'Y'; /* \/ */
|
||||
case 0x3e3c: return 'X'; /* >< */
|
||||
}
|
||||
|
||||
/* Rule 6 */
|
||||
if(ch1 == ch2 && ch1 == 0xa0)
|
||||
return 0xa0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
21
src/main.c
21
src/main.c
|
@ -54,6 +54,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
cx->term_width = 80;
|
||||
|
||||
cx->hlayout = H_DEFAULT;
|
||||
|
||||
cx->filters = NULL;
|
||||
cx->nfilters = 0;
|
||||
|
||||
|
@ -82,11 +84,11 @@ int main(int argc, char *argv[])
|
|||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int c = getopt_long(argc, argv, "f:d:w:tF:E:hI:v",
|
||||
int c = getopt_long(argc, argv, "f:d:w:tsSkWoF:E:hI:v",
|
||||
long_options, &option_index);
|
||||
# else
|
||||
# define MOREINFO "Try `%s -h' for more information.\n"
|
||||
int c = getopt(argc, argv, "f:d:w:tF:E:hI:v");
|
||||
int c = getopt(argc, argv, "f:d:w:tsSkWoF:E:hI:v");
|
||||
# endif
|
||||
if(c == -1)
|
||||
break;
|
||||
|
@ -135,6 +137,21 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
cx->hlayout = H_DEFAULT;
|
||||
break;
|
||||
case 'S':
|
||||
cx->hlayout = H_SMUSH;
|
||||
break;
|
||||
case 'k':
|
||||
cx->hlayout = H_KERN;
|
||||
break;
|
||||
case 'W':
|
||||
cx->hlayout = H_NONE;
|
||||
break;
|
||||
case 'o':
|
||||
cx->hlayout = H_OVERLAP;
|
||||
break;
|
||||
case 'E': /* --export */
|
||||
if(!strcmp(optarg, "list"))
|
||||
return export_list();
|
||||
|
|
|
@ -33,12 +33,13 @@ struct toilet_context
|
|||
int (*end)(struct toilet_context *);
|
||||
|
||||
/* Used by the FIGlet driver */
|
||||
enum { H_DEFAULT, H_KERN, H_SMUSH, H_NONE, H_OVERLAP } hlayout;
|
||||
unsigned long int hardblank;
|
||||
unsigned int height, baseline, max_length;
|
||||
int old_layout;
|
||||
unsigned int print_direction, full_layout, codetag_count;
|
||||
unsigned int glyphs;
|
||||
cucul_canvas_t *image;
|
||||
cucul_canvas_t *fontcv, *charcv;
|
||||
int *left, *right; /* Unused yet */
|
||||
unsigned int *lookup;
|
||||
|
||||
|
|
Loading…
Reference in a new issue