39 typedef unsigned char uint8_t;
40 typedef unsigned short int uint16_t;
41 typedef unsigned int uint32_t;
47 #define SSFN_MAGIC "SSFN"
48 #define SSFN_COLLECTION "SFNC"
49 #define SSFN_ENDMAGIC "NFSS"
52 #define SSFN_FAMILY_SERIF 0
53 #define SSFN_FAMILY_SANS 1
54 #define SSFN_FAMILY_DECOR 2
55 #define SSFN_FAMILY_MONOSPACE 3
56 #define SSFN_FAMILY_HAND 4
59 #define SSFN_STYLE_REGULAR 0
60 #define SSFN_STYLE_BOLD 1
61 #define SSFN_STYLE_ITALIC 2
64 #define SSFN_FEAT_HASBMAP 1
65 #define SSFN_FEAT_HASCMAP 2
66 #define SSFN_FEAT_HASHINT 4
67 #define SSFN_FEAT_KBIGLKP 8
68 #define SSFN_FEAT_KBIGCHR 16
69 #define SSFN_FEAT_KBIGCRD 32
70 #define SSFN_FEAT_HBIGCRD 64
73 #define SSFN_CONTOUR_MOVE 0
74 #define SSFN_CONTOUR_LINE 1
75 #define SSFN_CONTOUR_QUAD 2
76 #define SSFN_CONTOUR_CUBIC 3
77 #define SSFN_CONTOUR_COLOR 4
80 #define SSFN_FRAG_BITMAP 0
81 #define SSFN_FRAG_LBITMAP 1
82 #define SSFN_FRAG_PIXMAP 2
83 #define SSFN_FRAG_HINTING 3
86 #define SSFN_VARIANT_DEFAULT 0
87 #define SSFN_VARIANT_LOCAL0 0
88 #define SSFN_VARIANT_INITIAL 1
89 #define SSFN_VARIANT_LOCAL1 1
90 #define SSFN_VARIANT_MEDIAL 2
91 #define SSFN_VARIANT_LOCAL2 2
92 #define SSFN_VARIANT_FINAL 3
93 #define SSFN_VARIANT_LOCAL3 3
94 #define SSFN_VARIANT_LOCAL4 4
95 #define SSFN_VARIANT_LOCAL5 5
96 #define SSFN_VARIANT_LOCAL6 6
97 #define SSFN_NUMVARIANTS 7
115 uint16_t bbox_bottom;
116 uint32_t fragments_offs;
117 uint32_t characters_offs[SSFN_NUMVARIANTS];
118 uint32_t kerning_offs;
122 #define SSFN_FAMILY_ANY 0xff
123 #define SSFN_FAMILY_BYNAME 0xfe
125 #define SSFN_STYLE_UNDERLINE 4
126 #define SSFN_STYLE_STHROUGH 8
127 #define SSFN_STYLE_NOHINTING 0x40
128 #define SSFN_STYLE_ABS_SIZE 0x80
130 #define SSFN_FRAG_CONTOUR 255
134 #define SSFN_ERR_ALLOC 1
135 #define SSFN_ERR_NOFACE 2
136 #define SSFN_ERR_INVINP 3
137 #define SSFN_ERR_BADFILE 4
138 #define SSFN_ERR_BADSTYLE 5
139 #define SSFN_ERR_BADSIZE 6
140 #define SSFN_ERR_BADMODE 7
141 #define SSFN_ERR_NOGLYPH 8
142 #define SSFN_ERR_NOVARIANT 9
145 #define SSFN_MODE_NONE 0
146 #define SSFN_MODE_OUTLINE 1
147 #define SSFN_MODE_BITMAP 2
148 #define SSFN_MODE_ALPHA 3
149 #define SSFN_MODE_CMAP 4
152 #define SSFN_HINTING_THRESHOLD 16
155 #define SSFN_DATA_MAX 65536
165 uint8_t data[SSFN_DATA_MAX];
188 int m, ix, u,uix,uax, lx,ly, mx,my;
195 int ssfn_select(
ssfn_t *ctx,
int family,
char *name,
int style,
int size,
int mode);
196 int ssfn_variant(
ssfn_t *ctx,
int variant);
197 uint32_t ssfn_utf8(
char **str);
199 int ssfn_kern(
ssfn_t *ctx, uint32_t unicode, uint32_t nextunicode,
int *x,
int *y);
200 int ssfn_bbox(
ssfn_t *ctx,
char *str,
int usekern,
int *w,
int *h);
201 int ssfn_mem(
ssfn_t *ctx);
202 void ssfn_free(
ssfn_t *ctx);
203 #define ssfn_lasterr(ctx) ((ssfn_t*)ctx)->err
204 #define ssfn_error(err) (err>=0&&err<=9?ssfn_errstr[err]:"Unknown error")
205 extern const char *ssfn_errstr[];
208 int ssfn_putc(uint32_t unicode);
212 #ifndef SSFN_NOIMPLEMENTATION
216 # define NULL (void*)0
221 # ifndef ssfn_private
230 # ifdef __builtin_memcmp
231 # define SSFN_memcmp __builtin_memcmp
233 # define SSFN_memcmp memcmp
238 # ifdef __builtin_memset
239 # define SSFN_memset __builtin_memset
241 # define SSFN_memset memset
245 # ifndef SSFN_realloc
246 # ifdef __builtin_realloc
247 # define SSFN_realloc __builtin_realloc
249 # define SSFN_realloc realloc
254 # ifdef __builtin_free
255 # define SSFN_free __builtin_free
257 # define SSFN_free free
264 const char *ssfn_errstr[] = {
"",
265 "Memory allocation error",
266 "No font face found",
267 "Invalid input value",
273 "Glyph variant not found"
278 # define _ssfn_i2g(x) ((x)? (((x) << 16) - (1 << 15)) / ctx->m : 0)
279 # define _ssfn_g2o(x) (((x) * ctx->m + (1 << 7)) >> 8)
280 # define _ssfn_g2i(x) (((x) * ctx->m + (1 << 15)) >> 16)
281 # define _ssfn_g2ic(x) (((x) * ctx->m + (1 << 16) - 1) >> 16)
282 # define _ssfn_f2i(x) ((((x) << s) * ctx->m + (1 << 15)) >> 16)
283 # define _ssfn_o2i(x) (((x) + (1 << 7)) >> 8)
284 # define _ssfn_o2ic(x) ((x + (1<<8) - 1) >> 8)
285 # define _ssfn_g2ox(x) ((x)>=(4095 << 4) ? _ssfn_g2o(x) : ctx->h[((x) >> 4)])
286 # define _ssfn_g2ix(x) ((x)>=(4095 << 4) ? _ssfn_g2i(x) : _ssfn_o2i(ctx->h[((x) >> 4)]))
287 # define _ssfn_g2ixc(x) ((x)>=(4095 << 4) ? _ssfn_g2ic(x) : _ssfn_o2ic(ctx->h[((x) >> 4)]))
288 # define _ssfn_g2oy(y) (_ssfn_g2o(y))
289 # define _ssfn_g2iy(y) (_ssfn_g2i(y))
290 # define _ssfn_g2iyc(y) (_ssfn_g2ic(y))
291 # define _ssfn_igg(y) (((4096<<4)-(y)) >> (2))
292 # define _ssfn_igi(y) ((((4096<<4)-(y)) * ctx->m + (1 << (15+3))) >> (16+3))
295 ssfn_private uint8_t *_ssfn_c(
const ssfn_font_t *font, uint32_t unicode,
int v)
300 if(!font->characters_offs[v])
return NULL;
302 ptr = (uint8_t*)font + font->characters_offs[v];
303 l = (font->quality < 5 && font->characters_offs[v] < 65536) ? 4 : (font->characters_offs[v] < 1048576 ? 5 : 6);
305 for(j=i=0;i<0x110000;i++) {
307 if(ptr[0] & 0x40) { i += ptr[1] | ((ptr[0] & 0x3f) << 8); ptr += 2; }
308 else { i += ptr[0] & 0x3f; ptr++; }
310 if(i == unicode)
return ptr;
311 ptr += ptr[0] * l + 10;
319 ssfn_private
void _ssfn_l(
ssfn_t *ctx,
int x,
int y,
int l)
321 if(x > (4096<<4) - 16) x = (4096<<4) - 16;
322 if(y > (4096<<4) - 16) y = (4096<<4) - 16;
323 if(x < -1 || y < -1 || (x == ctx->lx && y == ctx->ly))
return;
325 if(ctx->np+2 >= ctx->mp) {
327 ctx->p = (uint16_t *)SSFN_realloc(ctx->p, ctx->mp*
sizeof(uint16_t));
328 if(!ctx->p) { ctx->err = SSFN_ERR_ALLOC;
return; }
330 if(!ctx->np || !l || _ssfn_g2i(ctx->p[ctx->np-2]) != _ssfn_g2i(x) ||
331 _ssfn_g2i(ctx->p[ctx->np-1]) != _ssfn_g2i(y)) {
332 ctx->p[ctx->np++] = x;
333 ctx->p[ctx->np++] = y;
334 ctx->lx = x; ctx->ly = y;
336 if((ctx->style & 0x200) && x >= 0 && ctx->ix > x) ctx->ix = x;
340 void _ssfn_b(
ssfn_t *ctx,
int x0,
int y0,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int l)
342 int m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y,m5x, m5y;
343 if(l<8 && (x0!=x3 || y0!=y3)) {
344 m0x = ((x1-x0)/2) + x0; m0y = ((y1-y0)/2) + y0;
345 m1x = ((x2-x1)/2) + x1; m1y = ((y2-y1)/2) + y1;
346 m2x = ((x3-x2)/2) + x2; m2y = ((y3-y2)/2) + y2;
347 m3x = ((m1x-m0x)/2) + m0x; m3y = ((m1y-m0y)/2) + m0y;
348 m4x = ((m2x-m1x)/2) + m1x; m4y = ((m2y-m1y)/2) + m1y;
349 m5x = ((m4x-m3x)/2) + m3x; m5y = ((m4y-m3y)/2) + m3y;
350 _ssfn_b(ctx, x0,y0, m0x,m0y, m3x,m3y, m5x,m5y, l+1);
351 _ssfn_b(ctx, m5x,m5y, m4x,m4y, m2x,m2y, x3,y3, l+1);
353 _ssfn_l(ctx, x3, y3, l);
357 ssfn_private
void _ssfn_r(
ssfn_t *ctx)
359 int i, k, l, m, n = 0, x, y, Y, M = 0;
361 uint8_t *pix = ctx->ret->data;
363 for(y = 0; y < ctx->ret->h; y++) {
364 Y = _ssfn_i2g(y); r = ctx->r[y];
365 for(n = 0, i = 0; i < ctx->np - 3; i += 2) {
366 if((ctx->p[i] == 0xffff && ctx->p[i+1] == 0xffff) ||
367 (ctx->p[i+2] == 0xffff && ctx->p[i+3] == 0xffff))
continue;
368 if( (ctx->p[i+1] < Y && ctx->p[i+3] >= Y) ||
369 (ctx->p[i+3] < Y && ctx->p[i+1] >= Y)) {
370 if(_ssfn_g2iy(ctx->p[i+1]) == _ssfn_g2iy(ctx->p[i+3]))
371 x = (((int)ctx->p[i]+(
int)ctx->p[i+2])>>1);
373 x = ((int)ctx->p[i]) + ((Y - (int)ctx->p[i+1])*
374 ((int)ctx->p[i+2] - (
int)ctx->p[i])/
375 ((
int)ctx->p[i+3] - (int)ctx->p[i+1]));
377 if(x < ctx->uix) { ctx->uix = x; }
378 if(x > ctx->uax) { ctx->uax = x; }
380 x = _ssfn_g2ox(x - ctx->ix);
381 for(k=0; k < n && x > r[k]; k++);
382 if(n >= ctx->nr[y]) {
383 ctx->nr[y] = (n < ctx->np) ? ctx->np : (n+1) << 1;
384 ctx->r[y] = (uint16_t *)SSFN_realloc(ctx->r[y], (ctx->nr[y] << 1));
385 if(!ctx->r[y]) { ctx->err = SSFN_ERR_ALLOC;
return; }
388 for(l = n; l > k; l--) r[l] = r[l-1];
393 if(n>1 && n&1) { r[n-2] = r[n-1]; n--; }
397 k = y*ctx->ret->pitch;
398 for(i=0; i < n-1; i += 2) {
399 if(ctx->style & 0x100) {
400 l = (r[i] + r[i + 1]) >> 9;
401 if(ctx->mode == SSFN_MODE_BITMAP ? (pix[k + (l >> 3)] & (1 << (l & 7)) ? 1 : 0) : (pix[k + l] == 0xFF)) {
402 if(r[i] + 256 > r[i + 1]) r[i] = r[i + 1] - 128;
else r[i] += 256;
403 if(r[i + 1] - 256 > r[i]) r[i + 1] -= 256;
405 if(i >= n-2 || r[i + 1] + 256 < r[i + 2]) r[i + 1] += 256;
408 l = ((r[i] + 128) >> 8);
409 m = ((r[i + 1] + 128) >> 8);
410 if(ctx->mode != SSFN_MODE_BITMAP && l + 1 < m) l++;
413 case SSFN_MODE_BITMAP: pix[k + (l >> 3)] ^= 1 << (l & 7);
break;
414 case SSFN_MODE_ALPHA: pix[k + l] ^= 0xFF;
break;
415 case SSFN_MODE_CMAP: pix[k + l] ^= 0x0F;
break;
418 if(l + 1 > ctx->ret->w) ctx->ret->w = l + 1;
423 if(M + 1 == ctx->ret->baseline) { ctx->ret->baseline--; ctx->u--; }
427 ssfn_private
void _ssfn_a(
ssfn_t * ctx)
429 int i, x, y, x0,y0,x1,y1, sx,sy, dx,dy, m, o, p = ctx->ret->pitch;
430 uint8_t *pix = ctx->ret->data, e;
433 if(ctx->mode < SSFN_MODE_ALPHA || !ctx->p || ctx->np < 4)
return;
435 for(y = o = 0; y < ctx->ret->h; y++, o += p) {
436 if(ctx->nr[y] && (r = ctx->r[y])) {
437 for(i = 0; i < ctx->nr[y] - 1; i += 2) {
438 x = (r[i] + 128) >> 8;
439 e = ~((r[i] + 128) & 0xFF);
440 if(e == 127) e = 255;
442 if(x && pix[o + x - 1] > e) e = pix[o + x - 1];
443 if(y && pix[o + x - p] > e) e = pix[o + x - p];
445 if(ctx->mode == SSFN_MODE_CMAP) e = (e >> 4) | 0xF0;
446 if(e > pix[o + x]) pix[o + x] = e;
447 e = ((r[i + 1] + 128) & 0xFF);
448 if(e == 128) e = 255;
449 pix[o + ((r[i + 1] + 128) >> 8)] = ctx->mode == SSFN_MODE_CMAP ? (e >> 4) | 0xF0 : e;
454 for(i = 0; i < ctx->np - 3; i += 2) {
455 if((ctx->p[i] == 0xffff && ctx->p[i+1] == 0xffff) ||
456 (ctx->p[i+2] == 0xffff && ctx->p[i+3] == 0xffff))
continue;
458 x0 = ctx->p[i] - ctx->ix; y0 = ctx->p[i+1]; x1 = ctx->p[i+2] - ctx->ix; y1 = ctx->p[i+3];
459 sx = x1 >= x0? 1 : -1; sy = y1 >= y0? 1 : -1; dx = x1 - x0; dy = y1 - y0;
460 if(sx * dx >= sy * dy && dx) {
461 for(x = x0, m = sx * dx; m > 0; m -= 16, x += sx * 16) {
462 y = _ssfn_g2oy(y0 + ((x - x0) * dy / dx));
463 y += 128; e = ~(y & 0xFF); y >>= 8; e >>= 1;
464 o = y * p + ((_ssfn_g2ox(x) + 128) >> 8);
465 if(ctx->mode == SSFN_MODE_CMAP) e = (e >> 4) | 0xF0;
466 if(e > pix[o]) pix[o] = e;
473 ssfn_private
void _ssfn_g(
ssfn_t *ctx, uint8_t *rg,
int render)
475 int i, j, nf, m, n, o, ox, oy, ol, t, x, y, a, b, c, d, w, h, s;
476 uint8_t *raw, *ra, *re, *pix = ctx->ret->data;
478 ctx->lx = ctx->ly = ctx->mx = ctx->my = -1;
479 ol = (ctx->f->quality < 5 && ctx->f->characters_offs[ctx->variant] < 65536) ? 4 :
480 ((ctx->f->characters_offs[ctx->variant] < 1048576) ? 5 : 6);
485 for(h=0; nf-- && !ctx->err; rg += ol) {
487 case 4: o = ((rg[1] << 8) | rg[0]); ox = rg[2]; oy = rg[3];
break;
488 case 5: o = (((rg[2] & 0xF) << 16) | (rg[1] << 8) | rg[0]);
489 ox = (((rg[2] >> 4) & 3) << 8) | rg[3]; oy = (((rg[2] >> 6) & 3) << 8) | rg[4];
break;
490 default: o = (((rg[3] & 0xF) << 24) | (rg[2] << 16) | (rg[1] << 8) | rg[0]);
491 ox = ((rg[3] & 0xF) << 8) | rg[4]; oy = (((rg[3] >> 4) & 0xF) << 8) | rg[5];
break;
493 ox <<= s; oy <<= s; raw = (uint8_t*)ctx->f + o;
495 t = (raw[0] & 0x60)>>5;
496 if(!render && t != SSFN_FRAG_HINTING)
break;
498 case SSFN_FRAG_LBITMAP:
499 x = ((((raw[0]>>2)&3)<<8)+raw[1])+1;
500 y = (((raw[0]&3)<<8)|raw[2])+1;
504 case SSFN_FRAG_BITMAP:
505 x = (raw[0] & 0x1F)+1;
508 bitmap:
if(ctx->mode == SSFN_MODE_OUTLINE) {
510 outline: ctx->lx = ctx->ly = -1;
512 if(ctx->style & 0x200) {
513 a = (((4096<<4)-(oy)) >> (3));
514 b = (((4096<<4)-(oy + y)) >> (3));
515 if(ctx->ix > ox + a) ctx->ix = ox + a;
517 if(ctx->np) _ssfn_l(ctx, -1, -1, 0);
518 _ssfn_l(ctx, ox+a, oy, 0);
519 _ssfn_l(ctx, ox+x+a, oy, 0);
520 _ssfn_l(ctx, ox+x+b, oy+y, 0);
521 _ssfn_l(ctx, ox+b, oy+y, 0);
522 _ssfn_l(ctx, ox+a, oy, 0);
524 a = x << 3; b = y << s;
527 w = _ssfn_g2i(x << (3+s));
529 if(c + h >= ctx->ret->h) c = ctx->ret->h - h;
530 c = t = c * ctx->ret->pitch;
531 for(j=0; j < h; j++) {
532 o = (((j<<8) * (y<<8) / (h<<8)) >> 8) * x;
533 for(i=0; i < w; i++) {
534 m = ((i<<8) * (a<<8) / (w<<8)) >> 8;
535 if(raw[o + (m >> 3)] & (1 << (m & 7))) {
536 d = n + ((ctx->style & 0x200) ? _ssfn_igi(oy + (j<<s) + 127) : 0) + i;
538 case SSFN_MODE_BITMAP:
539 pix[c + (d >> 3)] |= 1 << (d & 7); d++;
540 if((ctx->style & 0x100) && (d >> 3) < ctx->ret->pitch) {
541 pix[c + (d >> 3)] |= 1 << (d & 7); d++;
542 if(ctx->size > 127 && (d >> 3) < ctx->ret->pitch) {
543 pix[c + (d >> 3)] |= 1 << (d & 7);
548 case SSFN_MODE_ALPHA:
549 pix[c + (d++)] = 0xFF;
550 if((ctx->style & 0x100) && d < ctx->ret->pitch) {
551 pix[c + (d++)] = 0xFF;
552 if(ctx->size > 127 && d < ctx->ret->pitch) {
558 if(d > ctx->ret->w) ctx->ret->w = d;
559 d = ox + _ssfn_i2g(d);
560 if((ctx->style & 0x200) && ctx->ix > d) ctx->ix = d;
561 if(_ssfn_g2i(oy) + j == ctx->u) {
562 if(d < ctx->uix) { ctx->uix = d; }
563 if(d > ctx->uax) { ctx->uax = d; }
567 c += ctx->ret->pitch;
569 if(ctx->mode != SSFN_MODE_BITMAP && h > y && w > 1) {
570 m = (ctx->mode == SSFN_MODE_CMAP) ? 0xF0 : 0;
573 b = ctx->style & 0x100 ? (64 + (128 * a / x)) : (192 * a / x);
574 if(ctx->mode == SSFN_MODE_CMAP) b = (b >> 4) | 0xF0;
575 c = t + ctx->ret->pitch;
576 for(j=1; j < h-1; j++) {
577 for(i=1; i < w-1; i++) {
578 d = n + ((ctx->style & 0x200) ? _ssfn_igi(oy + (j<<s)) : 0) + i;
579 if(pix[c + d] == m &&
580 (pix[c + d - ctx->ret->pitch] > b || pix[c + d + ctx->ret->pitch] > b) &&
581 (pix[c + d - 1] > b || pix[c + d + 1] > b))
584 c += ctx->ret->pitch;
592 case SSFN_FRAG_PIXMAP:
593 x = (((raw[0] & 12) << 6) | raw[1])+1;
594 y = (((raw[0] & 3) << 8) | raw[2])+1;
595 n = ((raw[4]<<8) | raw[3])+1;
597 if(ctx->mode == SSFN_MODE_OUTLINE)
goto outline;
602 if(a >= (ctx->nr[0] << 1)) {
603 ctx->nr[0] = (a+1) >> 1;
604 ctx->r[0] = (uint16_t *)SSFN_realloc(ctx->r[0], (ctx->nr[0] << 1));
605 if(!ctx->r[0]) { ctx->err = SSFN_ERR_ALLOC;
return; }
607 ctx->ret->cmap = (uint32_t*)((uint8_t*)ctx->f + ctx->f->size - 964);
608 for(re = raw+n, ra = (uint8_t*)ctx->r[0], i=0; i < a && raw < re;) {
609 c = (raw[0] & 0x7F)+1;
610 if(raw[0] & 0x80) {
for(j=0; j < c; j++) ra[i++] = raw[1]; raw += 2; }
611 else { raw++;
for(j=0; j < c; j++) ra[i++] = *raw++; }
616 w = _ssfn_g2i(x << s);
618 if(c + h >= ctx->ret->h) c = ctx->ret->h - h;
619 c = t = c * ctx->ret->pitch;
620 for(j=0; j < h; j++) {
621 o = (((j<<8) * (y<<8) / (h<<8)) >> 8) * x;
622 for(i=0; i < w; i++) {
623 m = ((i<<8) * (x<<8) / (w<<8)) >> 8;
624 if(ra[o + m] < 0xF0) {
625 d = n + ((ctx->style & 0x200) ? _ssfn_igi(oy + (j<<s) + 127) : 0) + i;
626 re = (uint8_t*)&ctx->ret->cmap[ra[o + m]];
627 a = (re[0] + re[1] + re[2] + 255) >> 2;
629 case SSFN_MODE_BITMAP:
631 pix[c + (d >> 3)] |= 1 << (d & 7);
634 pix[c + d] = ra[o + m];
636 case SSFN_MODE_ALPHA:
641 if(d > ctx->ret->w) ctx->ret->w = d;
644 c += ctx->ret->pitch;
649 case SSFN_FRAG_HINTING:
650 if(raw[0] & 0x10) { n = ((raw[0]&0xF)<<8) | raw[1]; raw += 2; }
else { n = raw[0] & 0xF; raw++; }
651 if(render || !ox) { raw += n << (ctx->f->features & SSFN_FEAT_HBIGCRD ? 1 : 0);
continue; }
652 y = 4096; x = ((ox >> s) - 1) << (s-4);
654 for(n++;n-- && x < 4096;) {
656 if(ctx->f->features & SSFN_FEAT_HBIGCRD) { x |= (raw[0] << 8); raw++; }
660 if(y < 4096) ctx->h[y++] = 65535;
665 if(!render && h)
break;
666 if(raw[0] & 0x40) { n = ((raw[0] & 0x3F) << 8) | raw[1]; raw += 2; }
else { n = raw[0] & 0x3F; raw++; }
667 if(ctx->f->quality < 5) { x = raw[0]; y = raw[1]; raw += 2; }
668 else { x = ((raw[0] & 3) << 8) | raw[1]; y = ((raw[0] & 0x30) << 4) | raw[2]; raw += 3; }
669 x <<= s; y <<= s; y += oy;
670 x += ox + (ctx->style & 0x200 ? _ssfn_igg(y) : 0);
672 if(ctx->np) { _ssfn_l(ctx, ctx->mx, ctx->my, 0); _ssfn_l(ctx, -1, -1, 0); }
673 _ssfn_l(ctx, x, y, 0);
675 ctx->lx = ctx->mx = x; ctx->ly = ctx->my = y;
677 t = ctx->g < 8 ? (raw[0] >> 7) | ((raw[1] >> 6) & 2) : raw[0] & 3;
678 x = y = a = b = c = d = j = 0;
684 x = raw[0] & 0x7F; y = raw[1] & 0x7F;
686 case 0: raw += raw[0] & 4 ? 5 : 2;
break;
687 case 1: raw += 2;
break;
688 case 2: a = raw[2] & 0x7F; b = raw[3] & 0x7F; raw += 4;
break;
689 case 3: a = raw[2] & 0x7F; b = raw[3] & 0x7F; c = raw[4] & 0x7F; d = raw[5] & 0x7F; raw += 6;
break;
694 x = raw[1]; y = raw[2];
696 case 0: raw += raw[0] & 4 ? 5 : 2;
break;
697 case 1: raw += 3;
break;
698 case 2: a = raw[3]; b = raw[4]; raw += 5;
break;
699 case 3: a = raw[3]; b = raw[4]; c = raw[5]; d = raw[6]; raw += 7;
break;
704 x = ((raw[0] & 4) << 6) | raw[1]; y = ((raw[0] & 8) << 5) | raw[2];
706 case 0: raw += raw[0] & 4 ? 5 : 2;
break;
707 case 1: raw += 3;
break;
708 case 2: a = ((raw[0] & 16) << 4) | raw[3]; b = ((raw[0] & 32) << 3) | raw[4]; raw += 5;
break;
709 case 3: a = ((raw[0] & 16) << 4) | raw[3]; b = ((raw[0] & 32) << 3) | raw[4];
710 c = ((raw[0] & 64) << 2) | raw[5]; d = ((raw[0] & 128) << 1) | raw[6]; raw += 7;
break;
715 x = ((raw[0] & 12) << 6) | raw[1]; y = ((raw[0] & 48) << 4) | raw[2];
717 case 0: raw += raw[0] & 4 ? 5 : 2;
break;
718 case 1: raw += 3;
break;
719 case 2: a = ((raw[3] & 3) << 8) | raw[4]; b = ((raw[3] & 12) << 6) | raw[5]; raw += 6;
break;
720 case 3: a = ((raw[3] & 3) << 8) | raw[4]; b = ((raw[3] & 12) << 6) | raw[5];
721 c = ((raw[3] & 48) << 4) | raw[6]; d = ((raw[3] & 192) << 2) | raw[7]; raw += 8;
break;
725 x <<= s; y <<= s; a <<= s; b <<= s; c <<= s; d <<= s;
726 x += ox; y += oy; a += ox; b += oy; c += ox; d += oy;
727 if(ctx->style & 0x200) {
735 case 1: _ssfn_l(ctx, x, y, 0);
break;
736 case 2: _ssfn_b(ctx, ctx->lx,ctx->ly, ((a-ctx->lx)>>1)+ctx->lx,((b-ctx->ly)>>1)+ctx->ly,
737 ((x-a)>>1)+a,((y-b)>>1)+b, x,y, 0);
break;
738 case 3: _ssfn_b(ctx, ctx->lx,ctx->ly, a,b, c,d, x,y, 0);
break;
740 }
else if(t == 1 && x >= 0 && y >= 0) {
741 a = ((ctx->lx < x) ? x - ctx->lx : ctx->lx - x) >> 4;
742 b = ((ctx->ly < y) ? y - ctx->ly : ctx->ly - y) >> 4;
743 c = (ctx->lx + x) >> 5;
744 if(a < 2) ctx->h[4096 + (!ctx->h[4096 + c] && c && ctx->h[4096 + c - 1]? c - 1 : c)] += b;
746 ctx->lx = x; ctx->ly = y;
752 for(j = m = x = y = 0; j < 4096; j++) {
753 if(ctx->h[4096 + j] >= 4096/SSFN_HINTING_THRESHOLD) {
755 else { ctx->h[4096 + m++] = j - x; x = j; }
758 if(m < 4096) ctx->h[4096 + m] = 65535;
772 #define SSFN_CMAP_TO_ARGB(p,c,fg) (p>=0xF0?(uint32_t)((p<<28)|((p&0xF)<<24)|fg):c[p])
786 if(ctx) ctx->err = SSFN_ERR_INVINP;
787 return SSFN_ERR_INVINP;
790 if(!SSFN_memcmp(font->magic, SSFN_COLLECTION, 4)) {
792 for(ptr = (
ssfn_font_t*)((uint8_t*)font + 8); ptr < end && !ctx->err; ptr = (
ssfn_font_t*)((uint8_t*)ptr + ptr->size))
795 if(SSFN_memcmp(font->magic, SSFN_MAGIC, 4) || SSFN_memcmp((uint8_t*)font + font->size - 4, SSFN_ENDMAGIC, 4) ||
796 font->family > SSFN_FAMILY_HAND || font->fragments_offs > font->size || font->characters_offs[0] > font->size ||
797 font->kerning_offs > font->size || font->fragments_offs >= font->characters_offs[0] || font->quality > 8) {
798 ctx->err = SSFN_ERR_BADFILE;
800 ctx->len[font->family]++;
801 ctx->fnt[font->family] = (
const ssfn_font_t**)SSFN_realloc(ctx->fnt[font->family], ctx->len[font->family]*
sizeof(
void*));
802 if(!ctx->fnt[font->family])
803 ctx->err = SSFN_ERR_ALLOC;
805 ctx->fnt[font->family][ctx->len[font->family]-1] = font;
822 int ssfn_select(
ssfn_t *ctx,
int family,
char *name,
int style,
int size,
int mode)
826 if(!ctx)
return SSFN_ERR_INVINP;
827 if((style & ~0xCF))
return (ctx->err = SSFN_ERR_BADSTYLE);
828 if(size < 8 || size > 255)
return (ctx->err = SSFN_ERR_BADSIZE);
829 if(mode > SSFN_MODE_CMAP)
return (ctx->err = SSFN_ERR_BADMODE);
831 if(family == SSFN_FAMILY_BYNAME) {
832 if(!name || !name[0]) {
833 invinp:
return (ctx->err = SSFN_ERR_INVINP);
835 for(l=0; name[l]; l++);
836 for(i=0; i < 5; i++) {
837 for(j=0; j < ctx->len[i]; j++) {
838 if(!SSFN_memcmp(name, (uint8_t*)&ctx->fnt[i][j]->magic +
sizeof(
ssfn_font_t), l)) {
839 ctx->s = ctx->fnt[i][j];
844 noface:
return (ctx->err = SSFN_ERR_NOFACE);
846 if(family != SSFN_FAMILY_ANY) {
847 if(family > SSFN_FAMILY_HAND)
goto invinp;
848 if(!ctx->len[family])
goto noface;
853 ctx->np = ctx->mp = 0;
859 ctx->family = family;
864 return (ctx->err = SSFN_OK);
874 int ssfn_variant(
ssfn_t *ctx,
int variant)
876 if(!ctx)
return SSFN_ERR_INVINP;
877 if(variant < 0 || variant > SSFN_NUMVARIANTS-1)
return (ctx->err = SSFN_ERR_INVINP);
878 ctx->variant = variant;
879 return (ctx->err = SSFN_OK);
892 int i, j, s, h, p, m, n, bt, bl;
894 uint8_t *rg = NULL, c, d;
896 if(!ctx)
return NULL;
897 if(ctx->size < 8) { ctx->err = SSFN_ERR_NOFACE;
return NULL; }
901 rg = _ssfn_c(ctx->f, unicode, ctx->variant);
902 if(!rg) rg = _ssfn_c(ctx->f, unicode, 0);
906 again:
if(p == SSFN_FAMILY_ANY) { n = 0; m = 4; }
else n = m = p;
911 for(i=0;i<ctx->len[n];i++)
912 if((fl[i]->style & 3) == (ctx->style & 3) && (rg = _ssfn_c(fl[i], unicode, k))) { ctx->f = fl[i];
break; }
914 if(!rg && (ctx->style & 3) == 3)
915 for(i=0;i<ctx->len[n];i++)
916 if((fl[i]->style & 3) && (rg = _ssfn_c(fl[i], unicode, k))) { ctx->f = fl[i];
break; }
920 for(i=0;i<ctx->len[n];i++)
921 if((rg = _ssfn_c(fl[i], unicode, k))) { ctx->f = fl[i];
break; }
926 if(p != SSFN_FAMILY_ANY) { p = SSFN_FAMILY_ANY;
goto again; }
927 if(k) { k = 0;
goto again; }
930 if(!rg) { ctx->err = ctx->variant ? SSFN_ERR_NOVARIANT : SSFN_ERR_NOGLYPH;
return NULL; }
933 if((ctx->style & 1) && !(ctx->f->style & 1)) ctx->style |= 0x100;
934 if((ctx->style & 2) && !(ctx->f->style & 2)) ctx->style |= 0x200;
935 if(ctx->f->family == SSFN_FAMILY_MONOSPACE) ctx->style |= SSFN_STYLE_ABS_SIZE;
937 ctx->g = 4 + ctx->f->quality;
941 if(ctx->mode == SSFN_MODE_OUTLINE) {
945 if(!(((rg[2] & 0x0F) << 8) | rg[6]) || ctx->style & SSFN_STYLE_ABS_SIZE)
948 h = (4096 << 4) * ctx->size / ((ctx->f->baseline - ctx->f->bbox_top) << s);
949 p = (h + (ctx->style & 0x100? 2 : 0) + (ctx->style & 0x200 ? h>>2 : 0));
952 if(ctx->style & 0x100) h -= 2;
953 if(ctx->style & 0x200) h = h*4/5;
955 if(ctx->mode == SSFN_MODE_BITMAP) p = (p + 7) >> 3;
959 if(!ctx->h) ctx->h = (uint16_t*)SSFN_realloc(NULL, 4096*2*
sizeof(uint16_t));
960 if(!ctx->h)
goto erralloc;
962 if(!(ctx->style & SSFN_STYLE_NOHINTING)) {
963 SSFN_memset(&ctx->h[4096], 0, 4096*
sizeof(uint16_t));
965 }
else ctx->h[4096] = 65535;
968 for(i = j = k = x = y = m = 0; i < 4096 && j < 4095; i++) {
969 y = ctx->h[4096 + i] == 65535 ? 4095 - j : ctx->h[4096 + i];
972 ctx->h[j] = (((j<<4) * h + (1<<15)) >> 16) << 8;
977 if((i&1) || y < 256) {
continue; }
980 for(l = 0; l + x <= j; l++)
981 ctx->h[x + l] = n + ((m-n)*l / (j-x));
985 ctx->uix = _ssfn_g2ixc((((rg[2] & 0x0F) << 8) | rg[6]) << s);
986 ctx->uax = _ssfn_g2iyc((((rg[2] & 0xF0) << 4) | rg[7]) << s);
987 if(ctx->mode == SSFN_MODE_NONE)
return NULL;
989 bl = ((((rg[3] & 0x0F) << 8) | rg[8])) << s;
990 bt = ((((rg[3] & 0xF0) << 4) | rg[9])) << s;
992 ctx->ret = (
ssfn_glyph_t*)SSFN_realloc(NULL, i + 8 +
sizeof(uint8_t*));
995 ctx->err = SSFN_ERR_ALLOC;
998 SSFN_memset(&ctx->ret->data, ctx->mode == SSFN_MODE_CMAP ? 0xF0 : 0, i);
999 ctx->ret->cmap = NULL;
1000 ctx->ret->mode = ctx->mode;
1001 ctx->ret->pitch = p;
1004 ctx->ret->baseline = (((ctx->f->baseline << s) - bt) * h + (1<<16) - 1) >> 16;
1005 ctx->u = ctx->ret->baseline + ((((ctx->f->underline - ctx->f->baseline) << s) * h) >> 16);
1007 ctx->ret->adv_x = ctx->uix;
1008 ctx->ret->adv_y = ctx->uax;
1010 ctx->ix = ctx->uix = 4096 << 4; ctx->uax = 0;
1011 _ssfn_g(ctx, rg, 1);
1014 if(!(ctx->style & 0x200) || ctx->ix == 4096 << 4) ctx->ix = 0;
1015 if(ctx->mode == SSFN_MODE_OUTLINE) {
1016 if(ctx->np > p * h) {
1017 ctx->ret = (
ssfn_glyph_t*)SSFN_realloc(ctx->ret, ctx->np + 8 +
sizeof(uint8_t*));
1018 if(!ctx->ret)
goto erralloc;
1020 for(s=i=0; i < ctx->np; i += 2) {
1021 c = ctx->p[i+0] == 0xffff ? 0xff : _ssfn_g2ix(ctx->p[i+0] + bl);
1022 d = ctx->p[i+1] == 0xffff ? 0xff : _ssfn_g2iy(ctx->p[i+1] + bt);
1023 if(s<2 || ctx->ret->data[s-2] != c || ctx->ret->data[s-1] != d) {
1024 ctx->ret->data[s++] = c;
1025 ctx->ret->data[s++] = d;
1028 ctx->ret->pitch = s;
1029 ctx->ret = (
ssfn_glyph_t*)SSFN_realloc(ctx->ret, s + 8 +
sizeof(uint8_t*));
1030 if(!ctx->ret)
goto erralloc;
1033 if(ctx->mode != SSFN_MODE_BITMAP) _ssfn_a(ctx);
1034 if(ctx->style & SSFN_STYLE_STHROUGH) {
1035 if(ctx->ret->w < ctx->ret->adv_x) ctx->ret->w = ctx->ret->adv_x;
1036 SSFN_memset(&ctx->ret->data[(ctx->ret->baseline - (ctx->size >> 2)) * p], 0xFF, (ctx->size/64 + 2) * p);
1038 if(ctx->style & SSFN_STYLE_UNDERLINE) {
1039 if(ctx->ret->w < ctx->ret->adv_x) ctx->ret->w = ctx->ret->adv_x;
1040 if(ctx->uax > ctx->ix) ctx->uax = _ssfn_g2i(ctx->uax - ctx->ix);
1041 if(ctx->uix != 4096<<4) ctx->uix = _ssfn_g2i(ctx->uix - ctx->ix);
1042 else ctx->uix = ctx->ret->w + 3;
1044 n = ctx->size > 127 ? 2 : 1;
1048 if(ctx->mode == SSFN_MODE_BITMAP)
1049 for(i=0; i < j; i++) ctx->ret->data[m + (i >> 3)] |= 1 << (i & 7);
1051 SSFN_memset(&ctx->ret->data[m], 0xFF, j);
1055 if(ctx->mode == SSFN_MODE_BITMAP)
1056 for(i=j; i < ctx->ret->w; i++) ctx->ret->data[m + (i >> 3)] |= 1 << (i & 7);
1058 SSFN_memset(&ctx->ret->data[m + j], 0xFF, p - j);
1065 ctx->ret->baseline = ctx->ret->w >> 1;
1066 }
else if(ctx->ret) {
1067 SSFN_free(ctx->ret);
1083 int ssfn_kern(
ssfn_t *ctx, uint32_t unicode, uint32_t nextunicode,
int *x,
int *y)
1086 uint32_t i, j, k, l, a, b, c;
1090 if(!ctx || !x || !y)
return SSFN_ERR_INVINP;
1091 if(!ctx->f && !ctx->s)
return (ctx->err = SSFN_ERR_NOFACE);
1092 font = ctx->s ? ctx->s : ctx->f;
1093 if(unicode && nextunicode && font->kerning_offs) {
1094 ptr = (uint8_t*)font + font->kerning_offs;
1095 a = font->features & SSFN_FEAT_KBIGLKP ? 4 : 3;
1096 b = font->features & SSFN_FEAT_KBIGCHR;
1097 c = font->features & SSFN_FEAT_KBIGCRD;
1098 for(i=0;i<0x110000;i++) {
1100 if(ptr[0] & 0x40) { i += ptr[1] | ((ptr[0] & 0x3f) << 8); ptr += 2; }
1101 else { i += ptr[0] & 0x3f; ptr++; }
1104 if(unicode >= i && unicode <= i+m) {
1105 ptr = (uint8_t*)font + font->kerning_offs + ((a==4?(ptr[3]<<16):0)|(ptr[2]<<8)|ptr[1]);
1106 if(ptr[0] & 0x80) { k = ptr[1] | ((ptr[0] & 0x7f) << 8); ptr += 2; }
1107 else { k = ptr[0] & 0x7F; ptr++; }
1108 for(m=0,a=SSFN_ERR_NOGLYPH,i=j=0;i<=k && j<=nextunicode;i++) {
1109 if(b) { j = ptr[0] | (ptr[1] << 8) | ((ptr[2] & 0x7F) << 16); l = ptr[2] & 0x80; ptr += 3; }
1110 else { j = ptr[0] | ((ptr[1] & 0x7F) << 8); l = ptr[1] & 0x80; ptr += 2; }
1111 if(c) { m = (short)(ptr[0] | (ptr[1] << 8)); ptr += 2; }
else { m = (
signed char)ptr[0]; ptr++; }
1112 if(j == nextunicode) {
1113 a = SSFN_OK; m = (((m) << (16 - ctx->g)) * ctx->m + (1 << 16) - 1) >> 16;
1114 if(l) *y += m;
else *x += m;
1117 return (ctx->err = a);
1124 return (ctx->err = SSFN_ERR_NOGLYPH);
1137 int ssfn_bbox(
ssfn_t *ctx,
char *str,
int usekern,
int *w,
int *h)
1142 if(!ctx)
return SSFN_ERR_INVINP;
1143 if(!str || !w || !h)
return (ctx->err = SSFN_ERR_INVINP);
1145 m = ctx->mode; ctx->mode = SSFN_MODE_NONE; ctx->m = 0;
1146 for(s = str, u = ssfn_utf8(&s); u;) {
1147 ssfn_render(ctx, u);
1148 if(ctx->err == SSFN_OK) {
1153 if(usekern) ssfn_kern(ctx, u, v, w, h);
1156 if(!*w) *w = ctx->m;
1157 if(!*h) *h = ctx->m;
1168 int ssfn_mem(
ssfn_t *ctx)
1170 int i, ret =
sizeof(
ssfn_t);
1174 for(i=0; i<5; i++) ret += ctx->len[i] *
sizeof(
ssfn_font_t*);
1175 if(ctx->p) ret += ctx->mp *
sizeof(uint16_t);
1176 for(i=0; i<256; i++)
1177 if(ctx->r[i]) ret += ctx->nr[i] *
sizeof(uint16_t);
1178 if(ctx->h) ret += 8192 *
sizeof(uint16_t);
1187 void ssfn_free(
ssfn_t *ctx)
1194 if(ctx->fnt[i]) SSFN_free(ctx->fnt[i]);
1195 if(ctx->p) SSFN_free(ctx->p);
1196 for(i=0; i<256; i++)
1197 if(ctx->r[i]) SSFN_free(ctx->r[i]);
1198 if(ctx->h) SSFN_free(ctx->h);
1199 SSFN_memset(ctx, 0,
sizeof(
ssfn_t));
1205 #if !defined(SSFN_NOIMPLEMENTATION) || defined(SSFN_CONSOLEBITMAP_PALETTE) || \
1206 defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)
1213 uint32_t ssfn_utf8(
char **s)
1217 if((**s & 128) != 0) {
1218 if(!(**s & 32)) { c = ((**s & 0x1F)<<6)|(*(*s+1) & 0x3F); *s += 1; }
else
1219 if(!(**s & 16)) { c = ((**s & 0xF)<<12)|((*(*s+1) & 0x3F)<<6)|(*(*s+2) & 0x3F); *s += 2; }
else
1220 if(!(**s & 8)) { c = ((**s & 0x7)<<18)|((*(*s+1) & 0x3F)<<12)|((*(*s+2) & 0x3F)<<6)|(*(*s+3) & 0x3F); *s += 3; }
1228 #if defined(SSFN_CONSOLEBITMAP_PALETTE) || defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)
1235 uint8_t *ssfn_dst_ptr;
1236 uint32_t ssfn_dst_pitch;
1237 uint32_t ssfn_dst_w = 0;
1238 uint32_t ssfn_dst_h = 0;
1240 #ifdef SSFN_CONSOLEBITMAP_CLEARBG
1245 uint32_t ssfn_adv_x;
1246 uint32_t ssfn_adv_y;
1254 int ssfn_putc(uint32_t unicode)
1256 uint32_t i, j, a, b, m, p, t;
1257 uint8_t *rg, *o, *g, *s, *r, y, n;
1258 #ifdef SSFN_CONSOLEBITMAP_CLEARBG
1262 t = (ssfn_font->quality < 5 && ssfn_font->characters_offs[0] < 65536) ? 4 : (ssfn_font->characters_offs[0] < 1048576 ? 5 : 6);
1263 rg = (uint8_t*)ssfn_font + ssfn_font->characters_offs[0];
1264 ssfn_adv_x = ssfn_adv_y = 0;
1266 for(j=i=0;i<0x110000;i++) {
1269 if(rg[0] & 0x40) { i += rg[1] | (n << 8); rg++; }
else { i += n; }
1274 #ifdef SSFN_CONSOLEBITMAP_CLEARBG
1276 if(ssfn_dst_w && (ssfn_x + w >= ssfn_dst_w)) w = ssfn_dst_w - ssfn_x;
1277 s = ssfn_dst_ptr + (ssfn_y)*ssfn_dst_pitch;
1278 # ifdef SSFN_CONSOLEBITMAP_PALETTE
1281 # ifdef SSFN_CONSOLEBITMAP_HICOLOR
1288 if((ssfn_dst_w && (ssfn_x > ssfn_dst_w)) || (ssfn_dst_h && (ssfn_y + ssfn_font->bbox_bottom >= ssfn_dst_h)))
1289 return SSFN_ERR_INVINP;
1290 n = rg[0]; ssfn_adv_x = rg[6]; ssfn_adv_y = rg[7]; rg += 10;
1292 #ifndef SSFN_CONSOLEBITMAP_CLEARBG
1293 s = ssfn_dst_ptr + (ssfn_y + y + rg[t-1])*ssfn_dst_pitch;
1294 # ifdef SSFN_CONSOLEBITMAP_PALETTE
1297 # ifdef SSFN_CONSOLEBITMAP_HICOLOR
1304 o = (uint8_t*)ssfn_font; a = ((rg[1] << 8) | rg[0]);
1306 case 4: o += a;
break;
1307 case 5: o += ((rg[2] & 0xF) << 16) | a;
break;
1308 default: o += ((rg[3] & 0xF) << 24) | (rg[2] << 16) | a;
break;
1310 p = ((o[0] & 0xF)+1); a = p << 3; b = o[1]+1; o += 2;
1311 if(ssfn_dst_w && (ssfn_x + a >= ssfn_dst_w)) a = ssfn_dst_w - ssfn_x;
1312 #ifdef SSFN_CONSOLEBITMAP_CLEARBG
1313 for(;j<y+rg[t-1];j++,s+=ssfn_dst_pitch)
1314 for(r=s,i=0;i<w;i++) {
1315 # ifdef SSFN_CONSOLEBITMAP_PALETTE
1316 *((uint8_t*)r) = (uint8_t)ssfn_bg;
1319 # ifdef SSFN_CONSOLEBITMAP_HICOLOR
1320 *((uint16_t*)r) = (uint16_t)ssfn_bg;
1323 *((uint32_t*)r) = (uint32_t)ssfn_bg;
1332 for(;j<b;j++,s+=ssfn_dst_pitch,o+=p) {
1333 for(g=o,r=s,m=1,i=0;i<a;i++,m<<=1) {
1334 if(m > 0x80) { g++; m = 1; }
1335 #ifndef SSFN_CONSOLEBITMAP_CLEARBG
1338 #ifdef SSFN_CONSOLEBITMAP_PALETTE
1339 *((uint8_t*)r) = (uint8_t)(
1340 # ifdef SSFN_CONSOLEBITMAP_CLEARBG
1341 *g & m ? ssfn_fg : ssfn_bg
1348 # ifdef SSFN_CONSOLEBITMAP_HICOLOR
1349 *((uint16_t*)r) = (uint16_t)(
1350 # ifdef SSFN_CONSOLEBITMAP_CLEARBG
1351 *g & m ? ssfn_fg : ssfn_bg
1358 *((uint32_t*)r) = (uint32_t)(
1359 # ifdef SSFN_CONSOLEBITMAP_CLEARBG
1360 *g & m ? ssfn_fg : ssfn_bg
1372 #ifdef SSFN_CONSOLEBITMAP_CLEARBG
1373 for(;j<=ssfn_font->bbox_bottom;j++,s+=ssfn_dst_pitch)
1374 for(r=s,i=0;i<w;i++) {
1375 # ifdef SSFN_CONSOLEBITMAP_PALETTE
1376 *((uint8_t*)r) = (uint8_t)ssfn_bg;
1379 # ifdef SSFN_CONSOLEBITMAP_HICOLOR
1380 *((uint16_t*)r) = (uint16_t)ssfn_bg;
1383 *((uint32_t*)r) = (uint32_t)ssfn_bg;
1389 ssfn_x += ssfn_adv_x; ssfn_y += ssfn_adv_y;
1392 rg += rg[0] * t + 10;
1396 return SSFN_ERR_NOGLYPH;