Browse Source

=?utf-8?q?=20=20*=20Implement=20cucul=5Fput=5Ffigchar()=20to=20paste=20FIGlet/TOIlet=20characters=20in

=20=20=20=20=20=20=20=20=20=20=E2=96=8C=20=E2=96=8C=20=20=20=E2=96=9C=E2=96=9C=20=20=20=20=C2=A0=E2=96=8C=20=E2=96=8C=20=20=20=20=20=20=E2=96=9C=20=20=20=E2=96=8C=E2=96=90
=20=20=20=20=20=20=20=20=20=20=E2=96=99=E2=96=84=E2=96=8C=E2=96=9E=E2=96=80=E2=96=96=E2=96=90=E2=96=90=20=E2=96=9E=E2=96=80=E2=96=96=C2=A0=E2=96=8C=E2=96=96=E2=96=8C=E2=96=9E=E2=96=80=E2=96=96=E2=96=99=E2=96=80=E2=96=96=E2=96=90=20=E2=96=9E=E2=96=80=E2=96=8C=E2=96=90
=20=20=20=20=20=20=20=20=20=20=E2=96=8C=20=E2=96=8C=E2=96=9B=E2=96=80=20=E2=96=90=E2=96=90=20=E2=96=8C=20=E2=96=8C=C2=A0=E2=96=99=E2=96=9A=E2=96=8C=E2=96=8C=20=E2=96=8C=E2=96=8C=20=C2=A0=E2=96=90=20=E2=96=8C=20=E2=96=8C=E2=96=9D
=20=20=20=20=20=20=20=20=20=20=E2=96=98=20=E2=96=98=E2=96=9D=E2=96=80=E2=96=98=20=E2=96=98=E2=96=98=E2=96=9D=E2=96=80=20=C2=A0=E2=96=98=20=E2=96=98=E2=96=9D=E2=96=80=20=E2=96=98=20=20=20=E2=96=98=E2=96=9D=E2=96=80=E2=96=98=E2=96=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
tags/v0.99.beta14
Sam Hocevar sam 17 years ago
parent
commit
d06bf76c96
5 changed files with 310 additions and 13 deletions
  1. +1
    -2
      cucul/cucul.c
  2. +1
    -0
      cucul/cucul.h
  3. +0
    -4
      cucul/cucul_internals.h
  4. +293
    -6
      cucul/figfont.c
  5. +15
    -1
      examples/figfont.c

+ 1
- 2
cucul/cucul.c View File

@@ -308,8 +308,7 @@ int cucul_free_canvas(cucul_canvas_t *cv)
free(cv->frames[f].name);
}

if(cv->ff)
_cucul_free_figfont(cv->ff);
cucul_canvas_set_figfont(cv, NULL);

free(cv->frames);
free(cv);


+ 1
- 0
cucul/cucul.h View File

@@ -286,6 +286,7 @@ __extern int cucul_free_font(cucul_font_t *);
*
* @{ */
__extern int cucul_canvas_set_figfont(cucul_canvas_t *, char const *);
__extern int cucul_put_figchar(cucul_canvas_t *, unsigned long int);
/* @} */

/** \defgroup cucul_importexport libcucul importers/exporters from/to various


+ 0
- 4
cucul/cucul_internals.h View File

@@ -85,8 +85,4 @@ extern int _cucul_file_close(cucul_file_t *);
extern int _cucul_file_eof(cucul_file_t *);
extern char *_cucul_file_gets(char *, int, cucul_file_t *);

/* FIGfont functions */
extern cucul_figfont_t * _cucul_open_figfont(char const *);
extern int _cucul_free_figfont(cucul_figfont_t *);

#endif /* __CUCUL_INTERNALS_H__ */

+ 293
- 6
cucul/figfont.c View File

@@ -16,6 +16,10 @@
* This file contains FIGlet and TOIlet font handling functions.
*/

/*
* FIXME: this file needs huge cleanup to be usable
*/

#include "config.h"
#include "common.h"

@@ -30,39 +34,257 @@

struct cucul_figfont
{
/* Used by the FIGlet driver */
unsigned int term_width;
int x, y, w, h, lines;

enum { H_DEFAULT, H_KERN, H_SMUSH, H_NONE, H_OVERLAP } hmode;
unsigned int hsmushrule;
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 *fontcv;
cucul_canvas_t *fontcv, *charcv;
int *left, *right; /* Unused yet */
unsigned int *lookup;
};

static uint32_t hsmush(uint32_t ch1, uint32_t ch2, unsigned int rule);
static cucul_figfont_t * open_figfont(char const *);
static int free_figfont(cucul_figfont_t *);

int cucul_canvas_set_figfont(cucul_canvas_t *cv, char const *path)
{
cucul_figfont_t *ff = NULL;

if(path)
{
ff = _cucul_open_figfont(path);
ff = open_figfont(path);
if(!ff)
return -1;
}

if(cv->ff)
_cucul_free_figfont(cv->ff);
{
cucul_free_canvas(cv->ff->charcv);
free(cv->ff->left);
free(cv->ff->right);
free_figfont(cv->ff);
}

cv->ff = ff;

if(!path)
return 0;

/* from TOIlet’s main.c */
ff->term_width = 80;
ff->hmode = H_DEFAULT;

/* from TOIlet’s render.c */
ff->x = ff->y = 0;
ff->w = ff->h = 0;
ff->lines = 0;
cucul_set_canvas_size(cv, 0, 0); /* XXX */

/* from TOIlet’s figlet.c */
if(ff->full_layout & 0x3f)
ff->hsmushrule = ff->full_layout & 0x3f;
else if(ff->old_layout > 0)
ff->hsmushrule = ff->old_layout;

switch(ff->hmode)
{
case H_DEFAULT:
if(ff->old_layout == -1)
ff->hmode = H_NONE;
else if(ff->old_layout == 0 && (ff->full_layout & 0xc0) == 0x40)
ff->hmode = H_KERN;
else if((ff->old_layout & 0x3f) && (ff->full_layout & 0x3f)
&& (ff->full_layout & 0x80))
{
ff->hmode = H_SMUSH;
ff->hsmushrule = ff->full_layout & 0x3f;
}
else if(ff->old_layout == 0 && (ff->full_layout & 0xbf) == 0x80)
{
ff->hmode = H_SMUSH;
ff->hsmushrule = 0x3f;
}
else
ff->hmode = H_OVERLAP;
break;
default:
break;
}

ff->charcv = cucul_create_canvas(ff->max_length - 2, ff->height);

ff->left = malloc(ff->height * sizeof(int));
ff->right = malloc(ff->height * sizeof(int));

cv->ff = ff;

return 0;
}

int cucul_put_figchar(cucul_canvas_t *cv, unsigned long int ch)
{
cucul_figfont_t *ff = cv->ff;
unsigned int c, w, h, x, y, overlap, extra, xleft, xright;

switch(ch)
{
case (uint32_t)'\r':
return 0;
case (uint32_t)'\n':
ff->x = 0;
ff->y += ff->height;
return 0;
/* FIXME: handle '\t' */
}

/* Look whether our glyph is available */
for(c = 0; c < ff->glyphs; c++)
if(ff->lookup[c * 2] == ch)
break;

if(c == ff->glyphs)
return 0;

w = ff->lookup[c * 2 + 1];
h = ff->height;

cucul_set_canvas_handle(ff->fontcv, 0, c * ff->height);
cucul_blit(ff->charcv, 0, 0, ff->fontcv, NULL);

/* Check whether we reached the end of the screen */
if(ff->x && ff->x + w > ff->term_width)
{
ff->x = 0;
ff->y += h;
}

/* Compute how much the next character will overlap */
switch(ff->hmode)
{
case H_SMUSH:
case H_KERN:
case H_OVERLAP:
extra = (ff->hmode == H_OVERLAP);
overlap = w;
for(y = 0; y < h; y++)
{
/* Compute how much spaces we can eat from the new glyph */
for(xright = 0; xright < overlap; xright++)
if(cucul_get_char(ff->charcv, xright, y) != ' ')
break;

/* Compute how much spaces we can eat from the previous glyph */
for(xleft = 0; xright + xleft < overlap && xleft < ff->x; xleft++)
if(cucul_get_char(cv, ff->x - 1 - xleft, ff->y + y) != ' ')
break;

/* Handle overlapping */
if(ff->hmode == H_OVERLAP && xleft < ff->x)
xleft++;

/* Handle smushing */
if(ff->hmode == H_SMUSH)
{
if(xleft < ff->x &&
hsmush(cucul_get_char(cv, ff->x - 1 - xleft, ff->y + y),
cucul_get_char(ff->charcv, xright, y),
ff->hsmushrule))
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 */
if(ff->x + w - overlap > ff->w)
ff->w = ff->x + w - overlap < ff->term_width
? ff->x + w - overlap : ff->term_width;

if(ff->y + h > ff->h)
ff->h = ff->y + h;

#if 0 /* deactivated for libcaca insertion */
if(attr)
cucul_set_attr(cv, attr);
#endif
cucul_set_canvas_size(cv, ff->w, ff->h);

/* Render our char (FIXME: create a rect-aware cucul_blit_canvas?) */
for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
{
uint32_t ch1, ch2;
//uint32_t tmpat = cucul_get_attr(ff->fontcv, x, y + c * ff->height);
ch2 = cucul_get_char(ff->charcv, x, y);
if(ch2 == ' ')
continue;
ch1 = cucul_get_char(cv, ff->x + x - overlap, ff->y + y);
/* FIXME: this could be changed to cucul_put_attr() when the
* function is fixed in libcucul */
//cucul_set_attr(cv, tmpat);
if(ch1 == ' ' || ff->hmode != H_SMUSH)
cucul_put_char(cv, ff->x + x - overlap, ff->y + y, ch2);
else
cucul_put_char(cv, ff->x + x - overlap, ff->y + y,
hsmush(ch1, ch2, ff->hsmushrule));
//cucul_put_attr(cv, ff->x + x, ff->y + y, tmpat);
}

/* Advance cursor */
ff->x += w - overlap;

return 0;
}

static int flush_figlet(cucul_canvas_t *cv)
{
cucul_figfont_t *ff = cv->ff;
unsigned int x, y;

//ff->torender = cv;
//cucul_set_canvas_size(ff->torender, ff->w, ff->h);
cucul_set_canvas_size(cv, ff->w, ff->h);

/* FIXME: do this somewhere else, or record hardblank positions */
for(y = 0; y < ff->h; y++)
for(x = 0; x < ff->w; x++)
if(cucul_get_char(cv, x, y) == 0xa0)
{
uint32_t attr = cucul_get_attr(cv, x, y);
cucul_put_char(cv, x, y, ' ');
cucul_put_attr(cv, x, y, attr);
}

ff->x = ff->y = 0;
ff->w = ff->h = 0;

//cv = cucul_create_canvas(1, 1); /* XXX */

/* from render.c */
ff->lines += cucul_get_canvas_height(cv);

return 0;
}

#define STD_GLYPHS (127 - 32)
#define EXT_GLYPHS (STD_GLYPHS + 7)

cucul_figfont_t * _cucul_open_figfont(char const *path)
cucul_figfont_t * open_figfont(char const *path)
{
char altpath[2048];
char buf[2048];
@@ -250,7 +472,7 @@ cucul_figfont_t * _cucul_open_figfont(char const *path)
return ff;
}

int _cucul_free_figfont(cucul_figfont_t *ff)
int free_figfont(cucul_figfont_t *ff)
{
cucul_free_canvas(ff->fontcv);
free(ff->lookup);
@@ -259,3 +481,68 @@ int _cucul_free_figfont(cucul_figfont_t *ff)
return 0;
}

static uint32_t hsmush(uint32_t ch1, uint32_t ch2, unsigned int rule)
{
/* Rule 1 */
if((rule & 0x01) && ch1 == ch2 && ch1 != 0xa0)
return ch2;

if(ch1 < 0x80 && ch2 < 0x80)
{
char const charlist[] = "|/\\[]{}()<>";
char *tmp1, *tmp2;

/* Rule 2 */
if(rule & 0x02)
{
if(ch1 == '_' && strchr(charlist, ch2))
return ch2;

if(ch2 == '_' && strchr(charlist, ch1))
return ch1;
}

/* Rule 3 */
if((rule & 0x04) &&
(tmp1 = strchr(charlist, ch1)) && (tmp2 = strchr(charlist, ch2)))
{
int cl1 = (tmp1 + 1 - charlist) / 2;
int cl2 = (tmp2 + 1 - charlist) / 2;

if(cl1 < cl2)
return ch2;
if(cl1 > cl2)
return ch1;
}

/* Rule 4 */
if(rule & 0x08)
{
uint16_t s = ch1 + ch2;
uint16_t p = ch1 * ch2;

if(p == 15375 /* '{' * '}' */
|| p == 8463 /* '[' * ']' */
|| (p == 1640 && s == 81)) /* '(' *|+ ')' */
return '|';
}

/* Rule 5 */
if(rule & 0x10)
{
switch((ch1 << 8) | ch2)
{
case 0x2f5c: return '|'; /* /\ */
case 0x5c2f: return 'Y'; /* \/ */
case 0x3e3c: return 'X'; /* >< */
}
}

/* Rule 6 */
if((rule & 0x20) && ch1 == ch2 && ch1 == 0xa0)
return 0xa0;
}

return 0;
}


+ 15
- 1
examples/figfont.c View File

@@ -17,6 +17,7 @@

#if !defined(__KERNEL__)
# include <stdio.h>
# include <stdlib.h>
#endif

#include "cucul.h"
@@ -24,8 +25,11 @@
int main(int argc, char *argv[])
{
cucul_canvas_t *cv;
void *buffer;
unsigned long int len;
uint8_t color = 0;

if(argc < 2)
if(argc < 3)
{
fprintf(stderr, "Too few arguments\n");
return -1;
@@ -38,6 +42,16 @@ int main(int argc, char *argv[])
return -1;
}

while(argv[2][0])
{
cucul_set_color_ansi(cv, 1 + ((color += 4) % 15), CUCUL_TRANSPARENT);
cucul_put_figchar(cv, argv[2]++[0]);
}

buffer = cucul_export_memory(cv, "utf8", &len);
fwrite(buffer, len, 1, stdout);
free(buffer);

cucul_free_canvas(cv);

return 0;


Loading…
Cancel
Save