34#define SSFN_VERSION 0x0200
39# define __THROW throw()
47#if !defined(_STDINT) && !defined(_STDINT_H)
60#define SSFN_MAGIC "SFN2"
61#define SSFN_COLLECTION "SFNC"
62#define SSFN_ENDMAGIC "2NFS"
65#define SSFN_LIG_FIRST 0xF000
66#define SSFN_LIG_LAST 0xF8FF
69#define SSFN_TYPE_FAMILY(x) ((x)&15)
70#define SSFN_FAMILY_SERIF 0
71#define SSFN_FAMILY_SANS 1
72#define SSFN_FAMILY_DECOR 2
73#define SSFN_FAMILY_MONOSPACE 3
74#define SSFN_FAMILY_HAND 4
77#define SSFN_TYPE_STYLE(x) (((x)>>4)&15)
78#define SSFN_STYLE_REGULAR 0
79#define SSFN_STYLE_BOLD 1
80#define SSFN_STYLE_ITALIC 2
81#define SSFN_STYLE_USRDEF1 4
82#define SSFN_STYLE_USRDEF2 8
85#define SSFN_CONTOUR_MOVE 0
86#define SSFN_CONTOUR_LINE 1
87#define SSFN_CONTOUR_QUAD 2
88#define SSFN_CONTOUR_CUBIC 3
91#define SSFN_FRAG_CONTOUR 0
92#define SSFN_FRAG_BITMAP 1
93#define SSFN_FRAG_PIXMAP 2
94#define SSFN_FRAG_KERNING 3
95#define SSFN_FRAG_HINTING 4
99#define _pack __attribute__((packed))
125#define SSFN_FAMILY_ANY 0xff
126#define SSFN_FAMILY_BYNAME 0xfe
129#define SSFN_STYLE_UNDERLINE 16
130#define SSFN_STYLE_STHROUGH 32
131#define SSFN_STYLE_NOAA 64
132#define SSFN_STYLE_NOKERN 128
133#define SSFN_STYLE_NODEFGLYPH 256
134#define SSFN_STYLE_NOCACHE 512
135#define SSFN_STYLE_NOHINTING 1024
136#define SSFN_STYLE_RTL 2048
137#define SSFN_STYLE_ABS_SIZE 4096
138#define SSFN_STYLE_NOSMOOTH 8192
142#define SSFN_ERR_ALLOC -1
143#define SSFN_ERR_BADFILE -2
144#define SSFN_ERR_NOFACE -3
145#define SSFN_ERR_INVINP -4
146#define SSFN_ERR_BADSTYLE -5
147#define SSFN_ERR_BADSIZE -6
148#define SSFN_ERR_NOGLYPH -7
150#define SSFN_SIZE_MAX 192
151#define SSFN_ITALIC_DIV 4
167#define SSFN_DATA_MAX 65536
197 const ssfn_font_t *
fnt[5][16];
199 const ssfn_font_t **
fnt[5];
201 const ssfn_font_t *
s;
202 const ssfn_font_t *
f;
221 uint64_t lookup, raster, blit, kern;
238#define ssfn_error(err) (err<0&&err>=-7?ssfn_errstr[-err]:"Unknown error")
249#if (defined(SSFN_IMPLEMENTATION) || defined(SSFN_CONSOLEBITMAP_PALETTE) || \
250 defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)) && !defined(SSFN_COMMON)
252#define le32(a) (uint32_t)(((uint8_t*)&(a))[0]|(((uint8_t*)&(a))[1]<<8)|(((uint8_t*)&(a))[2]<<16)|(((uint8_t*)&(a))[3]<<24))
258 "Memory allocation error",
260 "No font face found",
261 "Invalid input value",
277 if((**s & 128) != 0) {
278 if(!(**s & 32)) { c = ((**s & 0x1F)<<6)|(*(*s+1) & 0x3F); *s += 1; }
else
279 if(!(**s & 16)) { c = ((**s & 0xF)<<12)|((*(*s+1) & 0x3F)<<6)|(*(*s+2) & 0x3F); *s += 2; }
else
280 if(!(**s & 8)) { c = ((**s & 0x7)<<18)|((*(*s+1) & 0x3F)<<12)|((*(*s+2) & 0x3F)<<6)|(*(*s+3) & 0x3F); *s += 3; }
288#ifdef SSFN_IMPLEMENTATION
292# define NULL (void*)0
295# ifndef __SIZE_TYPE__
296# define __SIZE_TYPE__ uint32_t
298 typedef __SIZE_TYPE__
size_t;
302# define inline __inline
304# define inline __inline__
309extern int memcmp (
const void *__s1,
const void *__s2,
size_t __n)
__THROW;
315# ifdef __builtin_memcmp
316# define SSFN_memcmp __builtin_memcmp
318# ifndef SSFN_MAXLINES
319# define SSFN_memcmp memcmp
321static int SSFN_memcmp(
const void *__s1,
const void *__s2,
size_t __n)
322{
unsigned char *
a = (
unsigned char *)__s1, *b = (
unsigned char *)__s2;
323 if(__n > 0) {
while(__n-- > 0) {
if(*
a != *b) {
return *
a - *b; }
a++; b++; } }
return 0; }
329# ifdef __builtin_memset
330# define SSFN_memset __builtin_memset
332# ifndef SSFN_MAXLINES
333# define SSFN_memset memset
335static void *
SSFN_memset(
void *__s,
int __c,
size_t __n)
336{
unsigned char *
a = __s;
if(__n > 0) {
while(__n-- > 0) *
a++ = __c; }
return __s; }
341# ifndef SSFN_MAXLINES
344# ifdef __builtin_realloc
345# define SSFN_realloc __builtin_realloc
347# define SSFN_realloc realloc
348 extern void *realloc (
void *__ptr,
size_t __size)
__THROW;
353# ifdef __builtin_free
354# define SSFN_free __builtin_free
356# define SSFN_free free
357 extern void free (
void *p)
__THROW;
372 *
len = 0; *unicode = 0;
373 if(!font || !font->characters_offs || !
str || !*
str)
return NULL;
375 if(font->ligature_offs) {
376 for(l = (
uint16_t*)((
uint8_t*)font + le32(font->ligature_offs)), i = 0; l[i] && u == -1U; i++) {
384 if((*s & 128) != 0) {
385 if(!(*s & 32)) { u = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); s++; }
else
386 if(!(*s & 16)) { u = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); s += 2; }
else
387 if(!(*s & 8)) { u = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); s += 3; }
394 for(
ptr = (
uint8_t*)font + le32(font->characters_offs), i = 0; i < 0x110000; i++) {
395 if(
ptr[0] == 0xFF) { i += 65535;
ptr++; }
396 else if((
ptr[0] & 0xC0) == 0xC0) { j = (((
ptr[0] & 0x3F) << 8) |
ptr[1]); i += j;
ptr += 2; }
397 else if((
ptr[0] & 0xC0) == 0x80) { j = (
ptr[0] & 0x3F); i += j;
ptr++; }
399 if(i == u)
return ptr;
400 ptr += 6 +
ptr[1] * (
ptr[0] & 0x40 ? 6 : 5);
407static void _ssfn_l(
ssfn_t *ctx,
int p,
int h,
int x,
int y)
413 if(ctx->
np >= SSFN_MAXLINES*2-2)
return;
415 if(ctx->
ap <= ctx->
np) {
416 ctx->
ap = ctx->
np + 512;
418 if(!ctx->
p) { ctx->
ap = ctx->
np = 0;
return; }
426 ctx->
p[ctx->
np+0] =
x;
427 ctx->
p[ctx->
np+1] =
y;
433static void _ssfn_b(
ssfn_t *ctx,
int p,
int h,
int x0,
int y0,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int l)
435 int m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y,m5x, m5y;
436 if(l<4 && (x0!=x3 || y0!=y3)) {
437 m0x = ((x1-x0)/2) + x0; m0y = ((y1-y0)/2) + y0;
438 m1x = ((x2-x1)/2) + x1; m1y = ((y2-y1)/2) + y1;
439 m2x = ((x3-x2)/2) + x2; m2y = ((y3-y2)/2) + y2;
440 m3x = ((m1x-m0x)/2) + m0x; m3y = ((m1y-m0y)/2) + m0y;
441 m4x = ((m2x-m1x)/2) + m1x; m4y = ((m2y-m1y)/2) + m1y;
442 m5x = ((m4x-m3x)/2) + m3x; m5y = ((m4y-m3y)/2) + m3y;
443 _ssfn_b(ctx, p,
h, x0,y0, m0x,m0y, m3x,m3y, m5x,m5y, l+1);
444 _ssfn_b(ctx, p,
h, m5x,m5y, m4x,m4y, m2x,m2y, x3,y3, l+1);
446 if(l) _ssfn_l(ctx, p,
h, x3, y3);
450static void _ssfn_fc(
ssfn_t *ctx)
454 for(k = 0; k <= 16; k++)
456 for(j = 0; j < 256; j++)
458 for(i = 0; i < 256; i++)
471#define SSFN__ZFAST_BITS 9
472#define SSFN__ZFAST_MASK ((1 << SSFN__ZFAST_BITS) - 1)
476 uint16_t fast[1 << SSFN__ZFAST_BITS];
480 unsigned char size[288];
484inline static int _ssfn__bitreverse16(
int n)
486 n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
487 n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
488 n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
489 n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
493inline static int _ssfn__bit_reverse(
int v,
int bits)
495 return _ssfn__bitreverse16(v) >> (16-bits);
498static int _ssfn__zbuild_huffman(_ssfn__zhuffman *z,
unsigned char *sizelist,
int num)
501 int code, next_code[16], sizes[17];
505 for(i=0; i < num; ++i)
506 ++sizes[sizelist[i]];
508 for(i=1; i < 16; ++i)
509 if(sizes[i] > (1 << i))
512 for(i=1; i < 16; ++i) {
518 if(
code-1 >= (1 << i))
return 0;
519 z->maxcode[i] =
code << (16-i);
523 z->maxcode[16] = 0x10000;
524 for(i=0; i < num; ++i) {
527 int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
529 z->size [c] = (
unsigned char) s;
531 if(s <= SSFN__ZFAST_BITS) {
532 int j = _ssfn__bit_reverse(next_code[s],s);
533 while(j < (1 << SSFN__ZFAST_BITS)) {
554 _ssfn__zhuffman z_length, z_distance;
557inline static unsigned char _ssfn__zget8(_ssfn__zbuf *z)
559 return *z->zbuffer++;
562static void _ssfn__fill_bits(_ssfn__zbuf *z)
565 z->code_buffer |= (
unsigned int) _ssfn__zget8(z) << z->num_bits;
567 }
while (z->num_bits <= 24);
570inline static unsigned int _ssfn__zreceive(_ssfn__zbuf *z,
int n)
573 if(z->num_bits < n) _ssfn__fill_bits(z);
574 k = z->code_buffer & ((1 << n) - 1);
575 z->code_buffer >>= n;
580static int _ssfn__zhuffman_decode_slowpath(_ssfn__zbuf *
a, _ssfn__zhuffman *z)
583 k = _ssfn__bit_reverse(
a->code_buffer, 16);
584 for(s=SSFN__ZFAST_BITS+1; ; ++s)
585 if(k < z->maxcode[s])
break;
586 if(s == 16)
return -1;
587 b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
588 if(b >= 288 || z->size[b] != s)
return -1;
589 a->code_buffer >>= s;
594inline static int _ssfn__zhuffman_decode(_ssfn__zbuf *
a, _ssfn__zhuffman *z)
597 if(
a->num_bits < 16) _ssfn__fill_bits(
a);
598 b = z->fast[
a->code_buffer & SSFN__ZFAST_MASK];
601 a->code_buffer >>= s;
605 return _ssfn__zhuffman_decode_slowpath(
a, z);
608static int _ssfn__zexpand(_ssfn__zbuf *z,
char *zout)
611 unsigned int cur, limit;
613#pragma GCC diagnostic push
614#pragma GCC diagnostic ignored "-Wuse-after-free"
616 z->zout = zout; cur = (
unsigned int) (z->zout - z->zout_start); limit = (
unsigned int) (z->zout_end - z->zout_start);
617 if(limit == 16) {
if(z->zout_start[0] !=
'S' || z->zout_start[1] !=
'F' || z->zout_start[2] !=
'N')
return 0; limit = le32(z->zout_start[4]); }
else return 0;
619 if (q ==
NULL)
return 0;
620 z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit;
622#pragma GCC diagnostic pop
627static int _ssfn__zlength_base[31]={3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0};
628static int _ssfn__zlength_extra[31]={0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0};
629static int _ssfn__zdist_base[32]={1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
630static int _ssfn__zdist_extra[32]={0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
632static int _ssfn__parse_huffman_block(_ssfn__zbuf *
a)
634 char *zout =
a->zout;
636 int z = _ssfn__zhuffman_decode(
a, &
a->z_length);
639 if(zout >=
a->zout_end) {
if(!_ssfn__zexpand(
a, zout))
return 0; zout =
a->zout; }
644 if(z == 256) {
a->zout = zout;
return 1; }
645 if(z >= 286)
return 0;
647 len = _ssfn__zlength_base[z];
648 if(_ssfn__zlength_extra[z])
len += _ssfn__zreceive(
a, _ssfn__zlength_extra[z]);
649 z = _ssfn__zhuffman_decode(
a, &
a->z_distance);
650 if(z < 0 || z >= 30)
return 0;
651 dist = _ssfn__zdist_base[z];
652 if(_ssfn__zdist_extra[z]) dist += _ssfn__zreceive(
a, _ssfn__zdist_extra[z]);
653 if(zout -
a->zout_start < dist)
return 0;
654 if(zout +
len >
a->zout_end) {
655 if(!_ssfn__zexpand(
a, zout))
return 0;
659 if(dist == 1) {
uint8_t v = *p;
if(
len) {
do *zout++ = v;
while(--
len); }}
660 else {
if(
len) {
do *zout++ = *p++;
while(--
len); } }
665static int _ssfn__compute_huffman_codes(_ssfn__zbuf *
a)
667 static uint8_t length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
668 _ssfn__zhuffman z_codelength;
672 int hlit = _ssfn__zreceive(
a,5) + 257;
673 int hdist = _ssfn__zreceive(
a,5) + 1;
674 int hclen = _ssfn__zreceive(
a,4) + 4;
675 int ntot = hlit + hdist;
677 SSFN_memset(codelength_sizes, 0,
sizeof(codelength_sizes));
678 for(i=0; i < hclen; ++i) {
679 n = _ssfn__zreceive(
a,3);
680 codelength_sizes[length_dezigzag[i]] = (
uint8_t)n;
682 if(!_ssfn__zbuild_huffman(&z_codelength, codelength_sizes, 19))
return 0;
686 int c = _ssfn__zhuffman_decode(
a, &z_codelength);
687 if(c < 0 || c >= 19)
return 0;
688 if(c < 16) lencodes[n++] = (
uint8_t)c;
692 c = _ssfn__zreceive(
a,2)+3;
694 fill = lencodes[n-1];
696 if(c == 17) c = _ssfn__zreceive(
a,3)+3;
else
697 if(c == 18){ c = _ssfn__zreceive(
a,7)+11; }
else return 0;
698 if(ntot - n < c)
return 0;
703 if(n != ntot || !_ssfn__zbuild_huffman(&
a->z_length, lencodes, hlit) || !_ssfn__zbuild_huffman(&
a->z_distance, lencodes+hlit, hdist))
708inline static int _ssfn__parse_uncompressed_block(_ssfn__zbuf *
a)
712 if(
a->num_bits & 7) _ssfn__zreceive(
a,
a->num_bits & 7);
714 while(
a->num_bits > 0) {
716 a->code_buffer >>= 8;
719 if(
a->num_bits < 0)
return 0;
720 while(k < 4)
header[k++] = _ssfn__zget8(
a);
723 if(nlen != (
len ^ 0xffff))
return 0;
724 if(
a->zout +
len >
a->zout_end && !_ssfn__zexpand(
a,
a->zout))
return 0;
725 for(k = 0; k <
len; k++)
a->zout[k] =
a->zbuffer[k];
731static uint8_t _ssfn__zdefault_length[288], _ssfn__zdefault_distance[32];
732static void _ssfn__init_zdefaults(
void)
735 for(i=0; i <= 143; ++i) _ssfn__zdefault_length[i] = 8;
736 for( ; i <= 255; ++i) _ssfn__zdefault_length[i] = 9;
737 for( ; i <= 279; ++i) _ssfn__zdefault_length[i] = 7;
738 for( ; i <= 287; ++i) _ssfn__zdefault_length[i] = 8;
739 for(i=0; i <= 31; ++i) _ssfn__zdefault_distance[i] = 5;
742static int _ssfn__parse_zlib(_ssfn__zbuf *
a)
745 a->num_bits =
a->code_buffer = 0;
747 fin = _ssfn__zreceive(
a,1);
748 type = _ssfn__zreceive(
a,2);
749 if(
type == 0) {
if(!_ssfn__parse_uncompressed_block(
a))
return 0; }
750 else if(
type == 3) {
return 0; }
753 if(!_ssfn__zbuild_huffman(&
a->z_length , _ssfn__zdefault_length , 288))
return 0;
754 if(!_ssfn__zbuild_huffman(&
a->z_distance, _ssfn__zdefault_distance, 32))
return 0;
756 if(!_ssfn__compute_huffman_codes(
a))
return 0;
758 if(!_ssfn__parse_huffman_block(
a))
return 0;
764char *_ssfn_zlib_decode(
const char *
buffer)
770 a.zout_start = p;
a.zout = p;
a.zout_end = p + 16;
771 _ssfn__init_zdefaults();
772 if (_ssfn__parse_zlib(&
a)) {
return a.zout_start; }
else {
SSFN_free(
a.zout_start);
return NULL; }
787 const ssfn_font_t *font = (
const ssfn_font_t *)
data;
788 ssfn_font_t *fnt, *end;
796 if(((
uint8_t *)font)[0] == 0x1f && ((
uint8_t *)font)[1] == 0x8b) {
803 if(c & 4) { r = *
ptr++; r += (*
ptr++ << 8);
ptr += r; }
804 if(c & 8) {
while(*
ptr++ != 0); }
805 if(c & 16) {
while(*
ptr++ != 0); }
806 font = (ssfn_font_t*)_ssfn_zlib_decode((
const char*)
ptr);
811 ctx->
lenbuf += le32(font->size);
815 end = (ssfn_font_t*)((
uint8_t*)font + le32(font->size));
816 for(fnt = (ssfn_font_t*)((
uint8_t*)font + 8); fnt < end && !
ssfn_load(ctx, (
const void *)fnt);
817 fnt = (ssfn_font_t*)((
uint8_t*)fnt + le32(fnt->size)));
820 s = le32(font->size);
822 fam >
SSFN_FAMILY_HAND || le32(font->characters_offs) >= s || le32(font->ligature_offs) >= s ||
823 le32(font->kerning_offs) >= s || le32(font->cmap_offs) >= s) {
837 ctx->
fnt[fam][ctx->
len[fam]-1] = font;
860 for(i = 0; i < ctx->
numbuf; i++)
864 for(i = 0; i < 5; i++)
880 return ctx ?
sizeof(
ssfn_t) : 0;
882 int i, j, k, ret =
sizeof(
ssfn_t);
885 for(i = 0; i < 5; i++) ret += ctx->
len[i] *
sizeof(ssfn_font_t*);
887 for(k = 0; k <= 16; k++) {
889 for(j = 0; j < 256; j++)
891 for(i = 0; i < 256; i++)
892 if(ctx->
c[k][j][i]) ret += 8 + ctx->
c[k][j][i]->
p * ctx->
c[k][j][i]->
h;
893 ret += 256 *
sizeof(
void*);
895 ret += 256 *
sizeof(
void*);
926 for(l=0;
name[l]; l++);
927 for(i=0; i < 5; i++) {
928 for(j=0; j < ctx->
len[i]; j++) {
930 ctx->
s = ctx->
fnt[i][j];
961 uint8_t *
ptr =
NULL, *frg, *end, *tmp, color, ci = 0, cb = 0, cs, dec[65536];
963 uint32_t unicode, P, O, *Op, *Ol, sR, sG, sB, sA, bA;
964 int ret = 0, i, j, k, l, p, m, n, o, s,
x,
y, w,
h, H,
a, A, b, B, nr, uix, uax;
965 int ox, oy, y0, y1, Y0, Y1, x0, x1, X0, X1, X2, xs, ys, yp, pc, fB, fG, fR, fA, bB, bG, bR, dB, dG, dR, dA;
967 struct timeval tv0, tv1, tvd;
968 gettimeofday(&tv0,
NULL);
970#define PUTPIXEL O = *Ol;bR = (O >> 16) & 0xFF;bG = (O >> 8) & 0xFF;bB = O & 0xFF;bA = (O >> 24) & 0xFF;\
971 bB += ((fB - bB) * fA) >> 8;bG += ((fG - bG) * fA) >> 8;bR += ((fR - bR) * fA) >> 8;bA += ((fA - bA) * fA) >> 8;\
972 *Ol = (bA << 24) | (bR << 16) | (bG << 8) | bB;
976 if(*
str ==
'\r') {
dst->x = 0;
return 1; }
981 ptr = _ssfn_c(ctx->
f,
str, &ret, &unicode);
988 fl = (ssfn_font_t **)ctx->
fnt[n];
991 for(i=0;i<ctx->
len[n];i++)
992 if(((fl[i]->
type>>4) & 3) == (ctx->
style & 3) && fl[i]->height == ctx->
size &&
993 (
ptr = _ssfn_c(fl[i],
str, &ret, &unicode))) { ctx->
f = fl[i];
break; }
996 for(i=0;i<ctx->
len[n];i++)
997 if(fl[i]->
height == ctx->
size && (
ptr = _ssfn_c(fl[i],
str, &ret, &unicode))) { ctx->
f = fl[i];
break; }
1000 for(i=0;i<ctx->
len[n];i++)
1001 if(((fl[i]->
type>>4) & 3) == (ctx->
style & 3) && (
ptr = _ssfn_c(fl[i],
str, &ret, &unicode)))
1002 { ctx->
f = fl[i];
break; }
1005 for(i=0;i<ctx->
len[n];i++)
1006 if(((fl[i]->
type>>4) & 3) && (
ptr = _ssfn_c(fl[i],
str, &ret, &unicode))) { ctx->
f = fl[i];
break; }
1010 for(i=0;i<ctx->
len[n];i++)
1011 if((
ptr = _ssfn_c(fl[i],
str, &ret, &unicode))) { ctx->
f = fl[i];
break; }
1022 for(; n <= m && !
ptr; n++)
1023 if(ctx->
len[n] && ctx->
fnt[n][0] && !(*((
uint8_t*)ctx->
fnt[n][0] + le32(ctx->
fnt[n][0]->characters_offs)) & 0x80))
1024 { ctx->
f = ctx->
fnt[n][0];
ptr = (
uint8_t*)ctx->
f + le32(ctx->
f->characters_offs); }
1032 ctx->
size : ctx->
size * ctx->
f->height / ctx->
f->baseline;
1034#ifdef SSFN_PROFILING
1035 gettimeofday(&tv1,
NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
1036 if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
1037 ctx->lookup += tvd.tv_sec * 1000000L + tvd.tv_usec;
1038 memcpy(&tv0, &tv1,
sizeof(
struct timeval));
1041#ifndef SSFN_MAXLINES
1043 ctx->
c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) {
1044 ctx->
g = ctx->
c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF];
1051 w = (ctx->
rc->
w *
h + ctx->
f->height - 1) / ctx->
f->height;
1056#ifndef SSFN_MAXLINES
1058 if(!ctx->
c[unicode >> 16]) {
1061 SSFN_memset(ctx->
c[unicode >> 16], 0, 256 *
sizeof(
void*));
1063 if(!ctx->
c[unicode >> 16][(unicode >> 8) & 0xFF]) {
1065 if(!ctx->
c[unicode >> 16][(unicode >> 8) & 0xFF])
return SSFN_ERR_ALLOC;
1066 SSFN_memset(ctx->
c[unicode >> 16][(unicode >> 8) & 0xFF], 0, 256 *
sizeof(
void*));
1069 if(!ctx->
c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF])
return SSFN_ERR_ALLOC;
1076 ctx->
g->
x = (ctx->
rc->
x +
x > 255 ? 255 : ctx->
rc->
x +
x);
1077 ctx->
g->
y = ctx->
rc->
y;
1078 ctx->
g->
o = (ctx->
rc->
t & 0x3F) +
x;
1080 color = 0xFE; ctx->
g->
a = ctx->
g->
d = 0;
1081 for(n = 0; n < ctx->
rc->
n; n++) {
1082 if(
ptr[0] == 255 &&
ptr[1] == 255) { color =
ptr[2];
ptr += ctx->
rc->
t & 0x40 ? 6 : 5;
continue; }
1084 if(ctx->
rc->
t & 0x40) { m = (
ptr[5] << 24) | (
ptr[4] << 16) | (
ptr[3] << 8) |
ptr[2];
ptr += 6; }
1085 else { m = (
ptr[4] << 16) | (
ptr[3] << 8) |
ptr[2];
ptr += 5; }
1087 if(!(frg[0] & 0x80)) {
1089 j = (frg[0] & 0x3F);
1090 if(frg[0] & 0x40) { j <<= 8; j |= frg[1]; frg++; }
1091 j++; frg++; tmp = frg; frg += (j+3)/4; ctx->
np = 0;
1092 for(i = 0; i < j; i++) {
1094 switch((tmp[i >> 2] >> ((i & 3) << 1)) & 3) {
1100 ((A-ctx->
ly)/2)+ctx->
ly, ((k-
a)/2)+
a,((A-m)/2)+m, k,m, 0);
1106 _ssfn_b(ctx, p <<
SSFN_PREC,
h <<
SSFN_PREC, ctx->
lx,ctx->
ly,
a,A, b,B, k,m, 0);
1112 if(ctx->
mx != ctx->
lx || ctx->
my != ctx->
ly) { ctx->
p[ctx->
np+0] = ctx->
mx; ctx->
p[ctx->
np+1] = ctx->
my; ctx->
np += 2; }
1115 for(b = A = B = o = 0; b <
h; b++, B += p) {
1117 for(nr = 0, i = 0; i < ctx->
np - 3; i += 2) {
1118 if( (ctx->
p[i+1] <
a && ctx->
p[i+3] >=
a) ||
1119 (ctx->
p[i+3] <
a && ctx->
p[i+1] >=
a)) {
1121 x = (((int)ctx->
p[i]+(int)ctx->
p[i+2])>>1);
1123 x = ((int)ctx->
p[i]) + ((
a - (
int)ctx->
p[i+1])*
1124 ((
int)ctx->
p[i+2] - (
int)ctx->
p[i])/
1125 ((
int)ctx->
p[i+3] - (
int)ctx->
p[i+1]));
1129 if(ctx->
g->
data[B +
x] != color) { o = -cb; A = cb; }
1130 else { o = cb; A = -cb; }
1132 for(k = 0; k < nr && x > r[k]; k++);
1133 for(l = nr; l > k; l--) r[l] = r[l-1];
1138 if(nr > 1 && nr & 1) { r[nr - 2] = r[nr - 1]; nr--; }
1140 if(ctx->
g->
d <
y + b) ctx->
g->
d =
y + b;
1141 for(i = 0; i < nr - 1; i += 2) {
1142 l = r[i] + o; m = r[i + 1] + A;
1145 if(i > 0 && l < r[i - 1] + A) l = r[i - 1] + A;
1147 ctx->
g->
data[B + l] = ctx->
g->
data[B + l] == color ? 0xFF : color;
1152 }
else if((frg[0] & 0x60) == 0x00) {
1155 b = B *
h / ctx->
f->height;
a = A *
h / ctx->
f->height;
1156 if(ctx->
g->
d <
y +
a) ctx->
g->
d =
y +
a;
1158 for(j = 0; j <
a; j++) {
1161 for(i = 0; i < b; i++) {
1163 if(frg[(k * B + m) >> 3] & (1 << (m & 7))) {
1164 for(o = 0; o <= cb; o++)
1165 ctx->
g->
data[l + i + o] = color;
1170 m = color == 0xFD ? 0xFC : 0xFD; o =
y * p + p +
x;
1171 for(k =
h; k > ctx->
f->height + 4; k -= 2*ctx->
f->height) {
1172 for(j = 1, l = o; j <
a - 1; j++, l += p)
1173 for(i = 1; i < b - 1; i++) {
1174 if(ctx->
g->
data[l + i] == 0xFF && (ctx->
g->
data[l + i - p] == color ||
1175 ctx->
g->
data[l + i + p] == color) && (ctx->
g->
data[l + i - 1] == color ||
1176 ctx->
g->
data[l + i + 1] == color)) ctx->
g->
data[l + i] = m;
1178 for(j = 1, l = o; j <
a - 1; j++, l += p)
1179 for(i = 1; i < b - 1; i++) {
1180 if(ctx->
g->
data[l + i] == m) ctx->
g->
data[l + i] = color;
1184 }
else if((frg[0] & 0x60) == 0x20) {
1186 k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; B = frg[2] + 1; A = frg[3] + 1;
x >>=
SSFN_PREC;
y >>=
SSFN_PREC;
1187 b = B *
h / ctx->
f->height;
a = A *
h / ctx->
f->height;
1188 if(ctx->
g->
d <
y +
a) ctx->
g->
d =
y +
a;
1189 frg += 4; end = frg + k; i = 0;
1191 l = ((*frg++) & 0x7F) + 1;
1192 if(frg[-1] & 0x80) {
1193 while(l--) dec[i++] = *frg;
1195 }
else while(l--) dec[i++] = *frg++;
1197 for(j = 0; j <
a; j++) {
1200 for(i = 0; i < b; i++) {
1201 m = dec[k + i * B / b];
1202 if(m != 0xFF) ctx->
g->
data[l + i] = m;
1208 ctx->
g->
a = ctx->
f->baseline;
1209 if(ctx->
g->
d > ctx->
g->
a + 1) ctx->
g->
d -= ctx->
g->
a + 1;
else ctx->
g->
d = 0;
1210#ifdef SSFN_DEBUGGLYPH
1211 printf(
"\nU+%06X size %d p %d h %d base %d under %d overlap %d ascender %d descender %d advance x %d advance y %d cb %d\n",
1212 unicode, ctx->
size,p,
h,ctx->
f->baseline,ctx->
f->underline,ctx->
g->
o,ctx->
g->
a,ctx->
g->
d,ctx->
g->
x,ctx->
g->
y,cb);
1213 for(j = 0; j <
h; j++) { printf(
"%3d: ", j);
for(i = 0; i < p; i++) {
if(ctx->
g->
data[j*p+i] == 0xFF) printf(j == ctx->
g->
a ?
"_" :
".");
else printf(
"%x", ctx->
g->
data[j*p+i] & 0xF); } printf(
"\n"); }
1215#ifdef SSFN_PROFILING
1216 gettimeofday(&tv1,
NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
1217 if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
1218 ctx->raster += tvd.tv_sec * 1000000L + tvd.tv_usec;
1219 memcpy(&tv0, &tv1,
sizeof(
struct timeval));
1226 w = ctx->
g->
p *
h / ctx->
g->
h;
1227 s = ((ctx->
g->
x - ctx->
g->
o) *
h + ctx->
f->height - 1) / ctx->
f->height;
1228 n = ctx->
size > 16 ? 2 : 1;
1233 ctx->
oy = oy = (ctx->
g->
a *
h + ctx->
f->height - 1) / ctx->
f->height;
1234 }
else { ctx->
ox = ox = w / 2; ctx->
oy = oy = 0; }
1237 cs =
dst->w < 0 ? 16 : 0;
1238 cb = (
h + 64) >> 6; uix = w > s ? w : s; uax = 0;
1239 n = (ctx->
f->underline *
h + ctx->
f->height - 1) / ctx->
f->height;
1240#ifdef SSFN_DEBUGGLYPH
1241 printf(
"Scaling to w %d h %d (glyph %d %d, cache %d %d, font %d)\n",w,
h,ctx->
rc->
w,ctx->
rc->
h,ctx->
g->
p,ctx->
g->
h,ctx->
f->height);
1243 fR = (
dst->fg >> 16) & 0xFF; fG = (
dst->fg >> 8) & 0xFF; fB = (
dst->fg >> 0) & 0xFF; fA = (
dst->fg >> 24) & 0xFF;
1244 bR = (
dst->bg >> 16) & 0xFF; bG = (
dst->bg >> 8) & 0xFF; bB = (
dst->bg >> 0) & 0xFF; O = 0xFF000000;
1246 for (
y = 0;
y <
h &&
dst->y +
y - oy <
dst->h;
y++, Op +=
dst->p >> 2) {
1247 if(
dst->y +
y - oy < 0)
continue;
1248 y0 = (
y << 8) * ctx->
g->
h /
h; Y0 = y0 >> 8; y1 = ((
y + 1) << 8) * ctx->
g->
h /
h; Y1 = y1 >> 8; Ol = Op;
1249 for (
x = 0;
x < w &&
dst->x +
x - ox < j;
x++, Ol++) {
1250 if(
dst->x +
x - ox < 0)
continue;
1251 m = 0; sR = sG = sB = sA = bA = 0;
1255 bA = (O >> 24) & 0xFF;
1256 bR = (O >> (16 - cs)) & 0xFF;
1257 bG = (O >> 8) & 0xFF;
1258 bB = (O >> cs) & 0xFF;
1260 x0 = (
x << 8) * ctx->
g->
p / w; X0 = x0 >> 8; x1 = ((
x + 1) << 8) * ctx->
g->
p / w; X1 = x1 >> 8;
1261 for(ys = y0; ys < y1; ys += 256) {
1262 if(ys >> 8 == Y0) { yp = 256 - (ys & 0xFF); ys &= ~0xFF;
if(yp > y1 - y0) yp = y1 - y0; }
1263 else if(ys >> 8 == Y1) yp = y1 & 0xFF;
else yp = 256;
1264 X2 = (ys >> 8) * ctx->
g->
p;
1265 for(xs = x0; xs < x1; xs += 256) {
1266 if (xs >> 8 == X0) {
1267 k = 256 - (xs & 0xFF); xs &= ~0xFF;
if(k > x1 - x0) k = x1 - x0; pc = k == 256 ? yp : (k * yp)>>8;
1269 if (xs >> 8 == X1) { k = x1 & 0xFF; pc = k == 256 ? yp : (k * yp) >> 8; }
1272 k = ctx->
g->
data[X2 + (xs >> 8)];
1274 sB += bB * pc; sG += bG * pc; sR += bR * pc; sA += 255;
1276 if(k == 0xFE || !ctx->
f->cmap_offs) {
1277 dB = fB; dG = fG; dR = fR; dA = fA;
1280 dR = (P >> 16) & 0xFF; dG = (P >> 8) & 0xFF; dB = (P >> 0) & 0xFF; dA = (P >> 24) & 0xFF;
1283 sB += dB * pc; sG += dG * pc; sR += dR * pc; sA += dA * pc;
1286 sB += ((dB * dA + bB *
a) * pc + 255)>>8; sG += ((dG * dA + bG *
a) * pc + 255)>>8;
1287 sR += ((dR * dA + bR *
a) * pc + 255)>>8; sA += dA * pc;
1292 if(m) { sR /= m; sG /= m; sB /= m; sA /= m; }
else { sR >>= 8; sG >>= 8; sB >>= 8; sA >>= 8; }
1295 *Ol = ((sA > 255 ? 255 : (sA > bA ? sA : bA)) << 24) |
1296 ((sR > 255 ? 255 : sR) << (16 - cs)) | ((sG > 255 ? 255 : sG) << 8) | ((sB > 255 ? 255 : sB) << cs);
1297 if(
y == n) {
if(uix >
x) { uix =
x; }
if(uax <
x) { uax =
x; } }
1302 uix -= cb + 1; uax += cb + 2;
1303 if(uax < uix) uax = uix + 1;
1304 k = (w > s ? w : s);
1306 for (
y = n;
y < n + cb &&
dst->y +
y - oy <
dst->h;
y++, Op +=
dst->p >> 2) {
1307 if(
dst->y +
y - oy < 0)
continue;
1308 for (Ol = Op,
x = 0;
x <= k &&
dst->x +
x - ox < j;
x++, Ol++) {
1309 if(
dst->x +
x - ox < 0 || (
x > uix &&
x < uax))
continue;
1315 n = (
h >> 1); k = (w > s ? w : s) + 1;
1317 for (
y = n;
y < n + cb &&
dst->y +
y - oy <
dst->h;
y++, Op +=
dst->p >> 2) {
1318 if(
dst->y +
y - oy < 0)
continue;
1319 for (Ol = Op,
x = 0;
x <= k &&
dst->x +
x - ox < j;
x++, Ol++) {
1320 if(
dst->x +
x - ox < 0)
continue;
1325#ifdef SSFN_PROFILING
1326 gettimeofday(&tv1,
NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
1327 if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
1328 ctx->blit += tvd.tv_sec * 1000000L + tvd.tv_usec;
1329 memcpy(&tv0, &tv1,
sizeof(
struct timeval));
1335 dst->y += (ctx->
g->
y *
h + ctx->
f->height - 1) / ctx->
f->height;
1340 for(n = 0; n < ctx->
rc->
n; n++) {
1341 if(
ptr[0] == 255 &&
ptr[1] == 255) {
ptr += ctx->
rc->
t & 0x40 ? 6 : 5;
continue; }
1343 if(ctx->
rc->
t & 0x40) { m = (
ptr[5] << 24) | (
ptr[4] << 16) | (
ptr[3] << 8) |
ptr[2];
ptr += 6; }
1344 else { m = (
ptr[4] << 16) | (
ptr[3] << 8) |
ptr[2];
ptr += 5; }
1346 if((frg[0] & 0xE0) == 0xC0) {
1347 k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; frg += 2;
1349 m = ((frg[2] & 0xF) << 16) | (frg[1] << 8) | frg[0];
1350 if(P >= (
uint32_t)m && P <= (
uint32_t)(((frg[5] & 0xF) << 16) | (frg[4] << 8) | frg[3])) {
1352 m = le32(ctx->
f->kerning_offs) + ((((frg[2] >> 4) & 0xF) << 24) | (((frg[5] >> 4) & 0xF) << 16) | (frg[7] << 8) | frg[6]);
1354 while(tmp < (
uint8_t*)ctx->
f + ctx->
f->size - 4) {
1355 if((tmp[0] & 0x7F) < P) {
1356 P -= (tmp[0] & 0x7F) + 1;
1357 tmp += 2 + (tmp[0] & 0x80 ? 0 : tmp[0] & 0x7F);
1359 y = (int)((
signed char)tmp[1 + ((tmp[0] & 0x80) ? 0 : P)]) *
h / ctx->
f->height;
1370#ifdef SSFN_PROFILING
1371 gettimeofday(&tv1,
NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
1372 if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
1373 ctx->kern += tvd.tv_sec * 1000000L + tvd.tv_usec;
1391int ssfn_bbox2(
ssfn_t *ctx,
const char *
str,
const char *end,
int *w,
int *
h,
int *left,
int *top)
1394 int ret, f = 1, l = 0, t = 0;
1397 if(w) {*w = 0;}
if(
h) {*
h = 0;}
if(top) {*top = 0;}
if(left) {*left = 0;}
1401 if(ret < 0 || !ctx->g)
return ret;
1402 if(f) { f = 0; l = ctx->
ox; buf.
x += l; }
1404 if(ctx->
oy > t) t = ctx->
oy;
1406 if(buf.
w < ctx->
g->
p) buf.
w = ctx->
g->
p;
1407 buf.
h += ctx->
g->
y ? ctx->
g->
y : ctx->
g->
h;
1413 if(ctx->
g->
x) {
if(w) {*w = buf.
x;}
if(
h) {*
h = ctx->
line;}
if(left) {*left = l;}
if(top) {*top = t;} }
1414 else {
if(w) {*w = buf.
w;}
if(
h) {*
h = buf.
y;}
if(top) {*top = 0;}
if(left) {*left = 0;} }
1417int ssfn_bbox(
ssfn_t *ctx,
const char *
str,
int *w,
int *
h,
int *left,
int *top) {
return ssfn_bbox2(ctx,
str,
NULL,w,
h,left,top); }
1428#ifndef SSFN_MAXLINES
1434 if(!buf)
return NULL;
1447 (void)ctx; (void)
str; (void)fg;
1454#if defined(SSFN_CONSOLEBITMAP_PALETTE) || defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)
1471# ifdef SSFN_CONSOLEBITMAP_PALETTE
1472# define SSFN_PIXEL uint8_t
1474# ifdef SSFN_CONSOLEBITMAP_HICOLOR
1475# define SSFN_PIXEL uint16_t
1477# define SSFN_PIXEL uint32_t
1480 register SSFN_PIXEL *o, *p;
1482 register int i, j, k, l, m,
y = 0, w, s =
ssfn_dst.p /
sizeof(SSFN_PIXEL);
1488 if(
ptr[0] == 0xFF) { i += 65535;
ptr++; }
1489 else if((
ptr[0] & 0xC0) == 0xC0) { j = (((
ptr[0] & 0x3F) << 8) |
ptr[1]); i += j;
ptr += 2; }
1490 else if((
ptr[0] & 0xC0) == 0x80) { j = (
ptr[0] & 0x3F); i += j;
ptr++; }
1491 else {
if((
uint32_t)i == unicode) { chr =
ptr;
break; }
ptr += 6 +
ptr[1] * (
ptr[0] & 0x40 ? 6 : 5); }
1493#ifdef SSFN_CONSOLEBITMAP_CONTROL
1499 if(unicode ==
'\n')
ssfn_dst.y += i;
1502 for(k = 0; k < j; k++)
1505 if(unicode ==
'\r' || unicode ==
'\n') {
ssfn_dst.x = 0;
return SSFN_OK; }
1509 for(i = 0; i < chr[1]; i++,
ptr += chr[0] & 0x40 ? 6 : 5) {
1510 if(
ptr[0] == 255 &&
ptr[1] == 255)
continue;
1512 ((
ptr[4] << 16) | (
ptr[3] << 8) |
ptr[2]));
1513 if((frg[0] & 0xE0) != 0x80)
continue;
1516 for(p = o, j = 0; j < chr[2] && (!w ||
ssfn_dst.x + j < w); j++, p++) *p =
ssfn_dst.bg;
1518 }
else { o += (int)(
ptr[1] -
y) * s;
y =
ptr[1]; }
1519 k = ((frg[0] & 0x1F) + 1) << 3; j = frg[1] + 1; frg += 2;
1521 for(p = o, l = 0; l < k; l++, p++, m <<= 1) {
1522 if(m > 0x80) { frg++; m = 1; }
1524 if(*frg & m) *p =
ssfn_dst.fg;
else
1531 for(p = o, j = 0; j < chr[2] && (!w ||
ssfn_dst.x + j < w); j++, p++) *p =
ssfn_dst.bg;
1542#ifndef SSFN_NO_CPP_STD_STRING
1547#ifndef SSFN_IMPLEMENTATION
1554 int Load(
const void *
data,
int len);
1555 int Select(
int family,
const char *
name,
int style,
int size);
1556 int Render(ssfn_buf_t *
dst,
const char *
str);
1557 int BBox(
const char *
str,
int *w,
int *
h,
int *left,
int *top);
1558 int BBox(
const char *
str,
const char *end,
int *w,
int *
h,
int *left,
int *top);
1559 ssfn_buf_t *Text(
const char *
str,
unsigned int fg);
1562#ifndef SSFN_NO_CPP_STD_STRING
1563 int Load(
const std::string &
data);
1564 int Select(
int family,
const std::string &
name,
int style,
int size);
1565 int Render(ssfn_buf_t *
dst,
const std::string &
str);
1566 int BBox(
const std::string &
str,
int *w,
int *
h,
int *left,
int *top);
1567 ssfn_buf_t *Text(
const std::string &
str,
unsigned int fg);
1568 const std::string ErrorStr(
int err);
1577 Font() {
SSFN_memset(&this->ctx, 0,
sizeof(ssfn_t)); }
1584 int BBox(
const char *
str,
int *w,
int *
h,
int *left,
int *top) {
return ssfn_bbox(&this->ctx,
str,w,
h,left,top); }
1585 int BBox(
const char *
str,
const char *end,
int *w,
int *
h,
int *left,
int *top) {
return ssfn_bbox2(&this->ctx,
str,end,w,
h,left,top); }
1586 ssfn_buf_t *Text(
const char *
str,
unsigned int fg) {
return ssfn_text(&this->ctx,
str, fg); }
1587 int LineHeight() {
return this->ctx.
line ? this->ctx.
line : this->ctx.
size; }
1588 int Mem() {
return ssfn_mem(&this->ctx); }
1589#ifndef SSFN_NO_CPP_STD_STRING
1590 int Load(
const std::string &
data) {
return ssfn_load(&this->ctx,
reinterpret_cast<const void*
>(
data.data())); }
1591 int Select(
int family,
const std::string &
name,
int style,
int size) {
return ssfn_select(&this->ctx, family, (
char*)
name.data(), style,
size); }
1592 int Render(ssfn_buf_t *
dst,
const std::string &
str) {
return ssfn_render(&this->ctx,
dst,(
const char *)
str.data()); }
1593 int BBox(
const std::string &
str,
int *w,
int *
h,
int *left,
int *top) {
return ssfn_bbox(&this->ctx, (
const char *)
str.data(), w,
h, left, top); }
1594 ssfn_buf_t *Text(
const std::string &
str,
unsigned int fg) {
return ssfn_text(&this->ctx,(
const char*)
str.data(), fg); }
1595 const std::string ErrorStr(
int err) {
return std::string(
ssfn_error(err)); }
volatile uint32_t buffer[5]
#define SSFN_FAMILY_BYNAME
ssfn_buf_t * ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg)
#define SSFN_TYPE_FAMILY(x)
int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size)
#define SSFN_CONTOUR_MOVE
int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str)
#define SSFN_STYLE_STHROUGH
#define SSFN_STYLE_ITALIC
int ssfn_putc(uint32_t unicode)
int ssfn_mem(ssfn_t *ctx)
#define SSFN_STYLE_NOCACHE
#define SSFN_TYPE_STYLE(x)
#define SSFN_CONTOUR_CUBIC
#define SSFN_CONTOUR_QUAD
void ssfn_free(ssfn_t *ctx)
#define SSFN_STYLE_UNDERLINE
unsigned long int uint64_t
#define SSFN_STYLE_NOKERN
#define SSFN_STYLE_NOSMOOTH
#define SSFN_ERR_BADSTYLE
int ssfn_bbox2(ssfn_t *ctx, const char *str, const char *end, int *w, int *h, int *left, int *top)
#define SSFN_FAMILY_MONOSPACE
int ssfn_load(ssfn_t *ctx, const void *data)
#define SSFN_STYLE_ABS_SIZE
#define SSFN_STYLE_NODEFGLYPH
#define SSFN_CONTOUR_LINE
uint32_t ssfn_utf8(char **str)
const char * ssfn_errstr[]
unsigned short int uint16_t
int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top)
int memcmp(const void *s1, const void *s2, size_t n)
void memset(void *ptr, int value, size_t num)
kstring str(const char *str)
const ssfn_font_t ** fnt[5]