123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269 |
- /*
- * libsfn/bitmap.c
- *
- * Copyright (C) 2020 bzt (bztsrc@gitlab)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * @brief File functions for bitmap and pixmap fonts
- *
- */
- #ifndef USE_NOFOREIGN
- #include <stdint.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #ifdef HAS_QUANT
- #include "libimagequant.h"
- #endif
- #define STBI_IMPLEMENTATION
- #include "stb_png.h"
- #include <ssfn.h>
- #include "libsfn.h"
- #include "bitmap.h"
- /* DOS 437 codepage to UNICODE (needed by BMF importer) */
- static int doscp[256] = {
- 0x0000,0x263A,0x263B,0x2665,0x2666,0x2663,0x2660,0x2022,0x25D8,0x25CB,0x25D9,0x2642,0x2640,0x266A,0x266B,0x263C,
- 0x25BA,0x25C4,0x2195,0x203C,0x00B6,0x00A7,0x25AC,0x21A8,0x2191,0x2193,0x2192,0x2190,0x221F,0x2194,0x25B2,0x25BC,
- 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
- 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
- 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
- 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
- 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
- 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
- 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
- 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
- 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
- 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
- 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
- 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
- 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
- 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
- };
- typedef struct {
- uint32_t magic;
- uint8_t version;
- uint8_t lineHeight;
- int8_t sizeOver;
- int8_t sizeUnder;
- int8_t addSpace;
- int8_t sizeInner;
- uint8_t usedColors;
- uint8_t highestColor;
- uint8_t alphaBits;
- uint8_t extraPalettes;
- uint16_t reserved;
- uint8_t numColors;
- } __attribute__((packed)) bmf_t;
- typedef struct {
- unsigned int magic;
- unsigned int version;
- unsigned int headersize;
- unsigned int flags;
- unsigned int numglyph;
- unsigned int bytesperglyph;
- unsigned int height;
- unsigned int width;
- unsigned char glyphs;
- } __attribute__((packed)) psf_t;
- /****************************** file format parsers ******************************/
- /**
- * Parse PSF2 font (binary)
- */
- void psf(unsigned char *ptr, int size)
- {
- psf_t *psf = (psf_t*)ptr;
- uint16_t *utbl = NULL;
- uint32_t c, g=0, unicode, nc = 0, numchars = psf->numglyph;
- unsigned char *s, *e, *glyph, *bitmap;
- int i, j, k, l, n;
- s=(unsigned char*)(ptr + psf->headersize + psf->numglyph*psf->bytesperglyph);
- e=ptr + size;
- /* try to fix bad fonts */
- if(s > e) {
- for(s = e; s + 1 > ptr + psf->headersize && (s[-1] || s[0] == 0xFF); s--);
- psf->numglyph = ((int)(s - ptr) - psf->headersize) / psf->bytesperglyph;
- }
- if(s < e) {
- numchars = 0;
- utbl = (uint16_t*)malloc(0x110000*sizeof(uint16_t));
- if(!utbl) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memset(utbl, 0, 0x110000*sizeof(uint16_t));
- while(s<e && g<psf->numglyph) {
- c = (uint16_t)((uint8_t)s[0]);
- if(c == 0xFF) { g++; } else {
- if((c & 128) != 0) {
- if((c & 32) == 0 ) { c=((s[0] & 0x1F)<<6)+(s[1] & 0x3F); s++; } else
- if((c & 16) == 0 ) { c=((((s[0] & 0xF)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F); s+=2; } else
- if((c & 8) == 0 ) { c=((((((s[0] & 0x7)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F))<<6)+(s[3] & 0x3F); s+=3;}
- else c=0;
- }
- if(c<0x110000) {
- utbl[c] = g;
- numchars++;
- }
- }
- s++;
- }
- }
- if((psf->flags >> 24) && !ctx.baseline) ctx.baseline = (psf->flags >> 24);
- if(psf->width < 1) psf->width = 1;
- if(psf->height < 1) psf->height = 1;
- l = ((psf->width + 7) & ~7) * (psf->height + 1);
- bitmap = (unsigned char*)malloc(l);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- for(unicode=rs;unicode<=(uint32_t)re;unicode++) {
- g = utbl? utbl[unicode] : unicode;
- if((!g && unicode && !iswhitespace(unicode)) || g >= psf->numglyph) continue;
- glyph = ptr + psf->headersize + g*psf->bytesperglyph;
- memset(bitmap, 0, l);
- for(i=k=0;i<(int)psf->bytesperglyph;) {
- for(n = 0; n < (int)psf->width; i++)
- for(j=0x80;j && n < (int)psf->width;j>>=1,n++)
- bitmap[k+n] = (glyph[i] & j) ? 0xFE : 0xFF;
- k += psf->width;
- }
- if(sfn_charadd(unicode, psf->width, psf->height, 0, 0, 0))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, psf->width, psf->height, 0xFE, bitmap);
- if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
- }
- free(bitmap);
- free(utbl);
- }
- /**
- * Parse GRUB's PFF2 font (binary)
- * yet another messy, resource wasteful, extremely badly documented format...
- */
- void pff(unsigned char *ptr, int size)
- {
- uint32_t len = 0, unicode, nc = 0, numchars = 0;
- int16_t w = 0, h = 0, p, n, a /*, x, y, mix, miy, max, may*/;
- int i, j, k, m;
- unsigned char *end = ptr + size, *section, *data = ptr, *bitmap;
- ptr += 12;
- while(ptr < end && len < (uint32_t)size) {
- len = (ptr[4] << 24) | (ptr[5] << 16) | (ptr[6] << 8) | ptr[7];
- section = ptr + 8;
- if(!memcmp(ptr, "NAME", 4)) sfn_setstr(&ctx.name, (char*)section, len); else
- if(!memcmp(ptr, "FAMI", 4)) sfn_setstr(&ctx.familyname, (char*)section, len); else
- if(!memcmp(ptr, "WEIG", 4) && section[0]=='b') ctx.style |= SSFN_STYLE_BOLD; else
- if(!memcmp(ptr, "SLAN", 4) && section[0]=='i') ctx.style |= SSFN_STYLE_ITALIC; else
- if(!memcmp(ptr, "MAXW", 4)) w = (section[0] << 8) | section[1]; else
- if(!memcmp(ptr, "MAXH", 4)) h = (section[0] << 8) | section[1]; else
- if(!memcmp(ptr, "ASCE", 4)) ctx.baseline = (section[0] << 8) | section[1]; else
- if(!memcmp(ptr, "CHIX", 4)) {
- /*mix = miy = max = may = 0;*/
- for(end = section + len, ptr = section; ptr < end; ptr += 9) {
- if(!ptr[4]) {
- n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 0] << 8) |
- data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 1];
- if(n > w) w = n;
- n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 2] << 8) |
- data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 3];
- if(n > h) h = n;
- /*
- n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 4] << 8) |
- data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 5];
- if(n < mix) { mix = n; } if(n > max) max = n;
- n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 6] << 8) |
- data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 7];
- if(n < miy) { miy = n; } if(n > may) may = n;
- */
- numchars++;
- }
- }
- ctx.width = w/* - mix + max*/;
- ctx.height = h/* - miy + may*/;
- /* ctx.baseline -= miy; */
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, width: %d, height: %d\n", ctx.name, numchars, ctx.baseline,
- ctx.width, ctx.height);
- n = ctx.width * ctx.height;
- bitmap = (unsigned char*)malloc(n);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- for(end = section + len; section < end; section += 9) {
- /* undocumented: section[4] supposed to indicate compression of some sort? grub-mkfont.c always writes 0 */
- if(!section[4]) {
- /* undocumented: section[0] holds left and right joins (or both), not sure what to do with those */
- unicode = (section[1] << 16) | (section[2] << 8) | section[3];
- ptr = data + ((section[5] << 24) | (section[6] << 16) | (section[7] << 8) | section[8]);
- memset(bitmap, 0xFF, n);
- w = (ptr[0] << 8) | ptr[1]; h = (ptr[2] << 8) | ptr[3];
- /* x = (ptr[4] << 8) | ptr[5]; y = (ptr[6] << 8) | ptr[7];*/
- a = (ptr[8] << 8) | ptr[9];
- p = w; /* + (x < 0 ? 0 : x); h -= y;*/
- ptr += 10; /*k = (y - miy) * p;*/
- for(j = k = 0, m = 0x80; j < h; j++, k += p)
- for(i = 0; i < w; i++, m >>= 1) {
- if(!m) { m = 0x80; ptr++; }
- if(ptr[0] & m) bitmap[k + i/* + (x < 0 ? 0 : x)*/] = 0xFE;
- }
- if(sfn_charadd(unicode, p, h, a, 0, /*x < 0 ? -x :*/ 0))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, p, h, 0xFE, bitmap);
- if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
- }
- }
- free(bitmap);
- break;
- }
- ptr += 8 + len;
- }
- }
- /**
- * Parse fucked up Windows Console Font (binary)
- */
- void fnt(unsigned char *ptr, int size)
- {
- int i, j, k, l, m, w, h, p, mn, mx, defchar;
- unsigned char *data = ptr, *bit, map[8192], *bitmap = NULL, ver, charset;
- /* skip over executable header... */
- if(ptr[0] == 'M' && ptr[1] == 'Z') {
- ptr += ((ptr[0x3D] << 8) | ptr[0x3C]); if(ptr[0] != 'N' || ptr[1] != 'E') return;
- ptr += ((ptr[37] << 8) | ptr[36]); j = ((ptr[1] << 8) | ptr[0]); ptr += 2; if(j > 16) return;
- for(i = 0; i < 16 && (ptr[0] || ptr[1]); i++) {
- if(ptr[0] == 0x08 && ptr[1] == 0x80) {
- if(((ptr[3] << 8) | ptr[2]) < 1) { return; } ptr += 8; ptr = data + (((ptr[1] << 8) | ptr[0]) << j); break;
- } else ptr += ((ptr[3] << 8) | ptr[2]) * 12 + 8;
- }
- }
- /* parse Windows resource file */
- if(ptr[0] || (ptr[1] != 2 && ptr[1] != 3) || ((ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) > size ||
- (ptr[66] & 1)) return;
- sfn_setstr(&ctx.name, (char*)(ptr + ((ptr[107] << 16) | (ptr[106] << 8) | ptr[105])), 0);
- sfn_setstr(&ctx.license, (char*)(ptr + 6), 0);
- h = ((ptr[89] << 8) | ptr[88]); charset = ptr[85];
- mn = ptr[95]; mx = ptr[96]; defchar = ptr[97] + mn; ctx.baseline = ((ptr[75] << 8) | ptr[74]);
- if(ptr[80]) ctx.style |= SSFN_STYLE_ITALIC;
- if(((ptr[84] << 8) | ptr[83]) > 400) ctx.style |= SSFN_STYLE_BOLD;
- switch(ptr[90] >> 4) {
- case 2: ctx.family = SSFN_FAMILY_SANS; break;
- case 3: ctx.family = SSFN_FAMILY_MONOSPACE; break;
- case 4: ctx.family = SSFN_FAMILY_HAND; break;
- case 5: ctx.family = SSFN_FAMILY_DECOR; break;
- default: ctx.family = SSFN_FAMILY_SERIF; break;
- }
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, height: %d\n", ctx.name, mx - mn + 1, ctx.baseline, h);
- if(!h || mn >= mx) return;
- ver = ptr[1]; data = ptr; ptr += (ptr[1] == 3 ? 148 : 118);
- /* get bitmaps */
- for(unicode = mn; unicode <= mx; unicode++, ptr += ver == 3 ? 6 : 4) {
- w = ptr[0]; bit = data + ((ver == 3 ? (ptr[4] << 16) : 0) | (ptr[3] << 8) | ptr[2]);
- p = ((w - 1) >> 3) + 1;
- if(p * h > (int)sizeof(map)) continue;
- bitmap = realloc(bitmap, w * h);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- /* I'm fed up. I can't properly get the bytes, so lets copy them into correct order before I get crazy. Ugly, but works */
- for(j = 0; j < p; j++)
- for(k = 0; k < h; k++)
- map[k * p + j] = *bit++;
- for(i = k = l = 0; k < h; k++)
- for(j = 0, l = k * p, m = 0x80; j < w; j++, m >>= 1) {
- if(!m) { m = 0x80; l++; }
- bitmap[i++] = map[l] & m ? 0xFE : 0xFF;
- }
- if(sfn_charadd(charset ? unicode : doscp[unicode], w, h, 0, 0, 0))
- sfn_layeradd(charset ? unicode : doscp[unicode], SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
- if(unicode == defchar) {
- sfn_chardel(0);
- if(sfn_charadd(0, w, h, 0, 0, 0))
- sfn_layeradd(0, SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
- }
- }
- free(bitmap);
- }
- /**
- * Parse GNU unifont hex format (text)
- */
- void hex(char *ptr, int size)
- {
- uint32_t i, j, c, unicode, nc = 0, numchars;
- int w;
- char *end = ptr + size;
- unsigned char bitmap[256];
- numchars = 0;
- for(numchars=0;ptr < end && *ptr;ptr++) if(*ptr=='\n') numchars++;
- ptr = end - size;
- while(ptr < end && *ptr) {
- unicode = gethex(ptr, 6);
- while(*ptr && *ptr!=':') ptr++;
- if(!*ptr) return;
- ptr++;
- while(*ptr && (*ptr==' '||*ptr=='\t')) ptr++;
- if(!*ptr) return;
- memset(bitmap, 0, 256);
- for(i = 0;i<256 && *ptr && *ptr!='\n' && *ptr!='\r';ptr += 2) {
- c = gethex(ptr, 2);
- for(j=0x80;j;j>>=1) bitmap[i++] = (c & j) ? 0xFE : 0xFF;
- }
- while(*ptr && *ptr!='\n' && *ptr!='\r') ptr++;
- while(*ptr && (*ptr=='\n' || *ptr=='\r')) ptr++;
- w = i > 128 ? 16 : 8;
- if(sfn_charadd(unicode, w, 16, 0, 0, 0))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, w, 16, 0xFE, bitmap);
- if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
- }
- }
- /**
- * Parse X11 BDF font format and FontForge's SplineFontDB with bitmaps (text)
- */
- void bdf(char *ptr, int size)
- {
- uint32_t c;
- int w = 0, h = 0, l = 0, t = 0, i, j, a, b = 0, unicode = 0, nc = 0, numchars = 0, defchar = 0, ps = 0, mx, xx, my, xy, k;
- char *end = ptr + size, *face, *name = NULL, *style = NULL, *manu = NULL;
- unsigned char *bitmap = NULL, sfd = 0, dec[4];
- for(face = ptr; face + 12 < end && *face; face++) {
- if(!memcmp(face, "ENCODING ", 9)) numchars++;
- if(!memcmp(face, "BDFChar:", 8)) { numchars++; sfd = 1; }
- if(!memcmp(face, "BitmapFont: ", 12)) {
- ptr += 12; while(*ptr == ' ') ptr++;
- ps = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- b = atoi(ptr); if(!ctx.baseline) ctx.baseline = b;
- sfd = 1;
- }
- }
- face = NULL;
- while(ptr < end && *ptr) {
- if(!memcmp(ptr, "FACE_NAME ", 10) && !face) {
- ptr += 10; while(*ptr==' ') { ptr++; } if(*ptr=='\"') { ptr++; } face = ptr;
- }
- if(!memcmp(ptr, "FONT_NAME ", 10) && !face) {
- ptr += 10; while(*ptr==' ') { ptr++; } if(*ptr=='\"') { ptr++; } face = ptr;
- }
- if(!memcmp(ptr, "FONT_VERSION ", 13) && !ctx.revision) {
- ptr += 13; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- sfn_setstr(&ctx.revision, ptr, 0);
- }
- if(!memcmp(ptr, "ADD_STYLE_NAME ", 15) && !ctx.name && !style) {
- ptr += 15; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- style = ptr;
- }
- if(!memcmp(ptr, "FOUNDRY ", 8) && !ctx.manufacturer) {
- ptr += 8; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- manu = ptr;
- }
- if(!memcmp(ptr, "HOMEPAGE ", 9) && !ctx.manufacturer && !manu) {
- ptr += 9; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- manu = ptr;
- }
- if(!memcmp(ptr, "FAMILY_NAME ", 12) && !ctx.familyname) {
- ptr += 12; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- sfn_setstr(&ctx.familyname, ptr, 0);
- }
- if(!memcmp(ptr, "WEIGHT_NAME ", 12) && !ctx.subname) {
- ptr += 12; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- sfn_setstr(&ctx.subname, ptr, 0);
- }
- if(!memcmp(ptr, "COPYRIGHT ", 10) && !ctx.license) {
- ptr += 10; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
- sfn_setstr(&ctx.license, ptr, 0);
- }
- if(!memcmp(ptr, "FONT_ASCENT ", 12)) {
- ptr += 12; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
- b = atoi(ptr); if(!ctx.baseline) ctx.baseline = b; }
- if(!memcmp(ptr, "UNDERLINE_POSITION ", 19)) {
- ptr += 19; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
- relul = atoi(ptr); if(relul < 0) relul = -relul; }
- if(!memcmp(ptr, "DEFAULT_CHAR ", 13)) {
- ptr += 13; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
- defchar = atoi(ptr); }
- if(!memcmp(ptr, "PIXEL_SIZE ", 11) && !ps) {
- ptr += 11; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
- ps = atoi(ptr); }
- if(!memcmp(ptr, "ENDPROPERTIES", 13) || !memcmp(ptr, "BDFEndProperties", 16)) break;
- while(*ptr && *ptr!='\n') ptr++;
- while(*ptr=='\r' || *ptr=='\n') ptr++;
- }
- if(!ctx.name) {
- if(!face) face = ctx.familyname;
- if(face && style && style[0]) {
- for(i = 0; face[i] && face[i] != '\"' && face[i] != '\r' && face[i] != '\n'; i++);
- for(j = 0; style[j] && style[i] != '\"' && style[i] != '\r' && style[i] != '\n'; j++);
- name = malloc(i + j + 2);
- if(!name) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memcpy(name, face, i);
- name[i] = ' ';
- memcpy(name + i + 1, style, j);
- name[i + j + 1] = 0;
- sfn_setstr(&ctx.name, name, 0);
- free(name);
- } else
- sfn_setstr(&ctx.name, ctx.familyname, 0);
- }
- if(!ctx.manufacturer && manu)
- sfn_setstr(&ctx.manufacturer, manu, 0);
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, b, b + relul, ps);
- while(ptr < end && *ptr) {
- if(!sfd) {
- if(!memcmp(ptr, "ENCODING ", 9)) { ptr += 9; unicode = atoi(ptr); }
- if(!memcmp(ptr, "BBX ", 4)) {
- ptr += 4; w = atoi(ptr);
- while(*ptr && *ptr!=' ') ptr++;
- ptr++; h = atoi(ptr);
- while(*ptr && *ptr!=' ') ptr++;
- ptr++; l = atoi(ptr);
- while(*ptr && *ptr!=' ') ptr++;
- ptr++; t = atoi(ptr);
- }
- if(!memcmp(ptr, "BITMAP", 6)) {
- ptr += 6; while(*ptr && *ptr!='\n') ptr++;
- ptr++;
- if(skipcode && uniname(unicode) == UNICODE_NUMNAMES && !memcmp(ptr,"0000\n7FFE", 9) &&
- !memcmp(ptr + 35,"7FFE\n7FFE", 9)) ptr += 16*5;
- else if(w > 0 && h > 0 && w * h <= 65536) {
- bitmap = realloc(bitmap, ((w + 7) & ~7) * (h + 1));
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); }
- else {
- for(i = 0;i < w * h && *ptr; ptr += 2) {
- while(*ptr=='\n' || *ptr=='\r') ptr++;
- c = gethex(ptr, 2);
- for(j=0x80,k=0;j && k < w && i < w * h;k++,j>>=1) bitmap[i++] = c & j ? 0xFE : 0xFF;
- }
- while(i < ((w + 7) & ~7) * (h + 1)) bitmap[i++] = 0xFF;
- if(!skipcode && unicode == defchar) { sfn_chardel(0); unicode = 0; }
- if(sfn_charadd(unicode, w, h, 0, 0, 0))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, l, ctx.baseline - t - h, w, h, 0xFE, bitmap);
- }
- }
- if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
- w = h = l = t = 0;
- }
- } else
- if(!memcmp(ptr, "BDFChar:", 8)) {
- ptr += 8; while(*ptr == ' ') ptr++;
- while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- unicode = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- w = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- mx = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- xx = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- my = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
- xy = atoi(ptr); while(*ptr && *ptr != ' ' && *ptr != '\n') { ptr++; } while(*ptr == ' ') ptr++;
- if(*ptr != '\n') a = atoi(ptr); else a = w;
- while(*ptr && *ptr != '\n') { ptr++; } while(*ptr == '\r' || *ptr == '\n') ptr++;
- h = ps; xx -= mx - 1; xy -= my - 1;
- xx = (xx + 7) & ~7;
- if(xx * xy < 65536) {
- bitmap = realloc(bitmap, xx * xy);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- for(i = 0, k = 4; i < xx * xy;) {
- if(k > 3) {
- if(!*ptr || *ptr == '\r' || *ptr == '\n') break;
- k = 0;
- if(*ptr == 'z') { dec[0] = dec[1] = dec[2] = dec[3] = 0; ptr++; }
- else {
- c = ((((ptr[0]-'!')*85 + ptr[1]-'!')*85 + ptr[2]-'!')*85 + ptr[3]-'!')*85 + ptr[4]-'!';
- dec[0] = (c >> 24) & 0xFF; dec[1] = (c >> 16) & 0xFF; dec[2] = (c >> 8) & 0xFF; dec[3] = c & 0xFF;
- ptr += 5;
- }
- }
- c = dec[k++];
- for(j = 0x80; j; j >>= 1) bitmap[i++] = c & j ? 0xFE : 0xFF;
- }
- while(i < xx * xy) bitmap[i++] = 0xFF;
- if(!skipcode && unicode == defchar) { sfn_chardel(0); unicode = 0; }
- if(sfn_charadd(unicode, w, h, a, 0, mx < 0 ? -mx : 0))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, xx, xy, 0xFE, bitmap);
- }
- if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
- }
- while(*ptr && *ptr!='\n') ptr++;
- while(*ptr=='\r' || *ptr=='\n') ptr++;
- }
- if(bitmap) free(bitmap);
- }
- /**
- * Parse X11 PCF font format (binary)
- */
- void pcf(unsigned char *ptr, int size)
- {
- uint32_t i, j, n, *iptr=(uint32_t*)ptr, fmt, mf=0, bf=0, bs=0, ef=0, offs, mn=0, mx=0, mg=0, siz;
- uint32_t boffs = 0, bitmaps = 0, metrics = 0, encodings = 0;
- unsigned char *bitmap = NULL, *bm;
- char *face = NULL, *name = NULL, *style = NULL, *manu = NULL;
- char *str, *s, *v;
- int x, y, o, a, b = 0, k, w, h = 0, p = 1, r, sx = 1, m, defchar = 0;
- #define pcf32(f,o) (f&(1<<2)? (ptr[o+0]<<24)|(ptr[o+1]<<16)|(ptr[o+2]<<8)|ptr[o+3] : \
- (ptr[o+3]<<24)|(ptr[o+2]<<16)|(ptr[o+1]<<8)|ptr[o+0])
- #define pcf16(f,o) (f&(1<<2)? (ptr[o+0]<<8)|ptr[o+1] : (ptr[o+1]<<8)|ptr[o+0])
- /* parse tables */
- for(i = 0; i < iptr[1]; i++) {
- fmt = iptr[i*4+3]; offs = iptr[i*4+5];
- if(offs + iptr[i*4+4] >= (uint32_t)size) continue;
- switch(iptr[i*4+2]) {
- case (1<<0): /* PCF_PROPERTIES */
- n = pcf32(fmt,offs+4); str = (char*)ptr + offs + ((n * 9 + 3)/4 + 3)*4;
- for(j = 0; j < n; j++) {
- s = str + pcf32(fmt,offs + 8 + j * 9); v = str + pcf32(fmt,offs + 13 + j * 9);
- if(!strcmp(s, "FACE_NAME") && !face) face = v; else
- if(!strcmp(s, "FONT_NAME") && !face) face = v; else
- if(!strcmp(s, "FONT_VERSION") && !ctx.revision) sfn_setstr(&ctx.revision, v, 0); else
- if(!strcmp(s, "ADD_STYLE_NAME") && !ctx.name && !style) style = v; else
- if(!strcmp(s, "FOUNDRY") && !ctx.manufacturer) manu = v; else
- if(!strcmp(s, "HOMEPAGE") && !ctx.manufacturer && !manu) manu = v; else
- if(!strcmp(s, "FAMILY_NAME") && !ctx.familyname) sfn_setstr(&ctx.subname, v, 0); else
- if(!strcmp(s, "WEIGHT_NAME") && !ctx.subname) sfn_setstr(&ctx.subname, v, 0); else
- if(!strcmp(s, "COPYRIGHT") && !ctx.license) sfn_setstr(&ctx.license, v, 0); else
- if(!strcmp(s, "PIXEL_SIZE")) { k = pcf32(fmt,offs + 13 + j * 9); if(k > h) h = k; } else
- if(!strcmp(s, "UNDERLINE_POSITION")) {
- relul = (int)pcf32(fmt,offs + 13 + j * 9); if(relul < 0) relul = -relul;
- }
- }
- break;
- case (1<<2): /* PCF_METRICS */
- metrics = offs; mf = fmt; b = 0;
- if(fmt & 0x100) {
- n = pcf16(fmt,offs + 4);
- for(j=0; j<n; j++) { k = (int)ptr[offs+3+6+j*5]-0x80; if(k > b) b = k; }
- for(j=0; j<n; j++) { k = (int)ptr[offs+4+6+j*5]-0x80 + b; if(k > h) h = k; }
- } else {
- n = pcf32(fmt,offs + 4);
- for(j = 0; j < n; j++) { k = pcf16(fmt,offs+6+8+j*12); if(k > b) b = k; }
- for(j = 0; j < n; j++) { k = pcf16(fmt,offs+8+8+j*12) + b; if(k > h) h = k; }
- }
- if(!mn && !mx && n) mx = n - 1;
- if(!mg || n < mg) mg = n;
- break;
- case (1<<3): /* PCF_BITMAPS */
- boffs = offs + 8; bf = fmt; n = pcf32(fmt,offs+4);
- bitmaps = boffs + n * 4 + 16; bs = iptr[i*4+4] + offs - bitmaps;
- p = 1 << (fmt & 3); sx = fmt & (1 << 2) ? 1 : -1;
- if(!mg || n < mg) mg = n;
- break;
- case (1<<5): /* PCF_BDF_ENCODINGS */
- encodings = offs + 14; ef = fmt;
- mn = (pcf16(fmt, offs + 8)<<8) | pcf16(fmt, offs + 4);
- mx = (pcf16(fmt, offs + 10)<<8) | pcf16(fmt, offs + 6);
- defchar = pcf16(fmt, offs + 12);
- break;
- }
- }
- if(!ctx.name) {
- if(!face) face = ctx.familyname;
- if(face && style && style[0]) {
- i = strlen(face); j = strlen(style);
- name = malloc(i + j + 2);
- if(!name) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memcpy(name, face, i);
- name[i] = ' ';
- memcpy(name + i + 1, style, j);
- name[i + j + 1] = 0;
- sfn_setstr(&ctx.name, name, 0);
- free(name);
- } else
- sfn_setstr(&ctx.name, ctx.familyname, 0);
- }
- if(!ctx.manufacturer && manu)
- sfn_setstr(&ctx.manufacturer, manu, 0);
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", face, mg, b, b + relul, h);
- if(!b || !h || !mg || !mx || !bitmaps) return;
- if(mg > 65534) mg = 65534;
- ctx.baseline = b;
- ctx.underline = b + relul;
- ctx.height = h;
- /* parse bitmaps and add glyphs. Encoding table must be handled as optional */
- for(unicode = mn; (uint32_t)unicode <= mx; unicode++) {
- if(pbar) (*pbar)(0, 0, unicode, mx - mn + 1, PBAR_BITMAP);
- i = encodings ? pcf16(ef, encodings + unicode * 2) : unicode;
- if(i >= mg) continue;
- offs = pcf32(bf, boffs + i * 4); siz = (i >= mg - 1 ? bs : (uint32_t)pcf32(bf, boffs + i * 4 + 4)) - offs;
- if(mf & 0x100) {
- x = (int)ptr[metrics+6+i*5]-0x80; a = (int)ptr[metrics+3+6+i*5]-0x80;
- w = (int)ptr[metrics+2+6+i*5]-0x80; r = (int)ptr[metrics+1+6+i*5]-0x80;
- } else {
- x = (int16_t)pcf16(mf,metrics+8+i*12); a = pcf16(mf,metrics+6+8+i*12);
- w = pcf16(mf,metrics+4+8+i*12); r = pcf16(mf,metrics+2+8+i*12);
- }
- /* do some heuristics and validation because PCF fonts are *usually* buggy... */
- if(x < 0) { o = -x; x = 0; } else o = 0;
- if(w < r) r = w;
- if(p < 1) p = 1;
- n = (siz / p); y = b - a;
- if(n > (uint32_t)h) n = h;
- if(y < 0) y = 0;
- if(y + n > (uint32_t)h) y = h - n;
- k = n * r; if(k < 1 || k > 65536) continue;
- bitmap = realloc(bitmap, k);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memset(bitmap, 0xFF, k);
- if(siz > n * p) siz = n * p;
- for(j = 0; siz; siz -= p, offs += p) {
- /* seriously, who have thought even for a moment that messing with both byte and bit endianess is sane? */
- bm = ptr + bitmaps + offs + (sx < 0 ? p - 1 : 0); m = bf & (1 << 3) ? 1 << 7 : 1;
- for(k = 0; k < r; k++) {
- bitmap[j++] = bm[0] & m ? 0xFE : 0xFF;
- if(bf & (1 << 3)) { m >>= 1; if(!m) { m = 1 << 7; bm += sx; } }
- else { m <<= 1; if(m > 0x80) { m = 1; bm += sx; } }
- }
- }
- if(unicode == defchar) {
- sfn_chardel(0);
- j = 0;
- } else j = unicode;
- if(sfn_charadd(j, w, h, x+r, 0, o))
- sfn_layeradd(j, SSFN_FRAG_BITMAP, x, y, r, n, 0xFE, bitmap);
- }
- if(bitmap) free(bitmap);
- }
- /**
- * Parse BMF font format (binary)
- */
- void bmf(unsigned char *ptr, int size)
- {
- bmf_t *bmf = (bmf_t*)ptr;
- uint8_t *end = ptr + size, pal[256];
- int i, n, unicode, numchars, w, h, a, x, y;
- if(!ctx.baseline) ctx.baseline = -bmf->sizeOver;
- if(ctx.height < bmf->lineHeight) ctx.height = bmf->lineHeight;
- memset(pal, 0, sizeof(pal)); pal[0] = 0xFF;
- ptr += sizeof(bmf_t);
- for(i = 0; i < (int)bmf->numColors; i++, ptr += 3)
- pal[i + 1] = sfn_cpaladd(ptr[0] << 2, ptr[1] << 2, ptr[2] << 2, 255);
- i = *ptr++; sfn_setstr(&ctx.name, (char*)ptr, i); ptr += i;
- numchars = (ptr[1] << 8) | ptr[0]; ptr += 2;
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars,
- -bmf->sizeOver, -bmf->sizeOver, bmf->lineHeight);
- for(n = 0; n < numchars && ptr + 6 < end; n++) {
- if(pbar) (*pbar)(0, 0, n, numchars, PBAR_BITMAP);
- unicode = doscp[*ptr++]; w = *ptr++; h = *ptr++; x = (int8_t)*ptr++; y = (int8_t)*ptr++; a = bmf->addSpace + (int8_t)*ptr++;
- if(sfn_charadd(unicode, (x < 0 ? 0 : x) + w, (y < 0 ? 0 : y) + h, a, 0, (x < 0 ? -x : 0))) {
- for(i = 0; i < w * h && ptr + i < end; i++) ptr[i] = pal[ptr[i]];
- sfn_layeradd(unicode, SSFN_FRAG_PIXMAP, (x < 0 ? 0 : x), (y < 0 ? 0 : y), w, h, 0xFE, ptr);
- }
- ptr += w * h;
- }
- }
- /**
- * Parse YAFF font format (text)
- */
- void yaff(char *ptr, int size)
- {
- int i, w = 0, h = 0, x = 0, y = 0, o = 0, unicode = -1, c = -1, last = -1, u, b = 0, relul = 0, W = 0, H = 0, numchars = 0;
- char *end = ptr + size, *s = ptr, *e, *n, *v, hack = 0;
- unsigned char bitmap[65536];
- /* this is REALLY bad format which cannot be parsed reliably line by line... expect parsing errors! */
- while(s < end) {
- while(s < end && *s && (*s == '\r' || *s == '\n')) s++;
- if(!*s) break;
- for(e = s; e < end && *e && *e != '\r' && *e != '\n'; e++);
- for(v = s; v < e && *v != ':'; v++);
- if(v < e && *v == ':') {
- for(v++; v < e && *v && (*v == ' ' || *v == '\t'); v++);
- if(v >= e || *v == '\r' || *v == '\n') v = NULL;
- } else v = NULL;
- /* s: first character in line, e: end of line, v: first character of value */
- if(*s == ' ' || *s == '\t') {
- while(s < end && *s && (*s == ' ' || *s == '\t')) s++;
- if(!*s) break;
- if(unicode == -1 && c != -1) unicode = c;
- if(unicode == -1) { s = e; continue; }
- if(last != unicode) {
- /* add character */
- if(w > 0 && h > 0 && last != -1) {
- if(o < 0) w += o;
- if(w > 0) {
- for(i = 0; i < h; i++)
- memcpy(bitmap + i * w, bitmap + i * 256 - (o < 0 ? o : 0), w);
- if(sfn_charadd(last, w, h, x && !y ? x : w, !x && y ? y : 0, o < 0 ? 0 : o))
- sfn_layeradd(last, SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
- }
- numchars++;
- }
- w = h = o = x = y = 0; memset(bitmap, 0, sizeof(bitmap));
- last = unicode; hack = 0;
- }
- if(*s == '.' || *s == '@') {
- /* add a row */
- for(i = 0; i < 255 && s < e && (*s == '.' || *s == '@'); s++, i++)
- bitmap[h * 256 + i] = *s == '@' ? 0xFE : 0xFF;
- h++;
- if(i > w) w = i;
- if(w > W) W = w;
- if(h > H) H = h;
- /* ugly hack */
- hack = 0;
- } else
- if(!memcmp(s, "advance-width:", 14) && v) x = atoi(v); else
- if(!memcmp(s, "advance-height:", 15) && v) y = atoi(v); else
- if(!memcmp(s, "left-bearing:", 13) && v) { o = atoi(v); }
- } else {
- if(*s == '#' || *s == '\'' || *s == '\"') { s = e; continue; }
- /* codepoint */
- n = s; u = (int)ssfn_utf8(&n);
- if(*s >= '0' && *s <= '9') {
- if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) c = gethex(s + 2, 6);
- else c = atoi(s);
- if(!hack) unicode = c;
- } else
- if((s[0] == 'u' || s[0] == 'U') && s[1] == '+') { unicode = gethex(s + 2, 6); c = -1; hack = 1; } else
- if(*n == ':') { unicode = u; c = -1; } else
- if(!memcmp(s, "weight:", 7) && v && (*v == 'b' || *v == 'B')) ctx.style |= SSFN_STYLE_BOLD; else
- if(!memcmp(s, "slant:", 7) && v && (*v == 'i' || *v == 'I' || *v == 'o' || *v == 'O')) ctx.style |= SSFN_STYLE_ITALIC; else
- if(!memcmp(s, "name:", 5) && !ctx.name && v) sfn_setstr(&ctx.name, v, e - v); else
- if(!memcmp(s, "family:", 7) && !ctx.familyname && v) sfn_setstr(&ctx.familyname, v, e - v); else
- if(!memcmp(s, "subfamily:", 10) && !ctx.subname && v) sfn_setstr(&ctx.subname, v, e - v); else
- if(!memcmp(s, "revision:", 9) && !ctx.revision && v) sfn_setstr(&ctx.revision, v, e - v); else
- if(!memcmp(s, "foundry:", 8) && !ctx.manufacturer && v) sfn_setstr(&ctx.manufacturer, v, e - v); else
- if(!memcmp(s, "copyright:", 10) && !ctx.license && v) sfn_setstr(&ctx.license, v, e - v); else
- if(!memcmp(s, "line-height:", 12) && v) H = atoi(v); else
- if(!memcmp(s, "ascent:", 7) && !b && v) b = atoi(v); else
- if(!memcmp(s, "baseline:", 9) && v) b = atoi(v); else
- if(!memcmp(s, "shift-up:", 9) && b && v) { b -= atoi(v); if(b < 0) b = 0; } else
- if(!memcmp(s, "underline-descent:", 18) && v) relul = atoi(v);
- }
- s = e;
- }
- /* add the last character too */
- if(unicode == -1 && c != -1) unicode = c;
- if(w > 0 && h > 0 && unicode != -1) {
- if(o < 0) w += o;
- if(w > 0) {
- for(i = 0; i < h; i++)
- memcpy(bitmap + i * w, bitmap + i * 256 - (o < 0 ? o : 0), w);
- if(sfn_charadd(unicode, w, h, x && !y ? x : w, !x && y ? y : 0, o < 0 ? 0 : o))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
- }
- numchars++;
- }
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, b, b + relul, H);
- if(b > ctx.baseline) ctx.baseline = b;
- ctx.underline = ctx.baseline + relul;
- if(ctx.underline < ctx.baseline) ctx.underline = ctx.baseline;
- if(W > ctx.width) ctx.width = W;
- if(H > ctx.height) ctx.height = H;
- ctx.family = SSFN_FAMILY_MONOSPACE;
- }
- /**
- * Parse name chunk
- */
- void kbits_name(char **strings)
- {
- /* unique font name */
- if(!ctx.name) {
- if(strings[4]) sfn_setstr(&ctx.name, strings[4], 0); else
- if(strings[3]) sfn_setstr(&ctx.name, strings[3], 0); else
- if(strings[6]) sfn_setstr(&ctx.name, strings[6], 0); else
- if(strings[20]) sfn_setstr(&ctx.name, strings[20], 0); else
- if(strings[18]) sfn_setstr(&ctx.name, strings[18], 0); else
- /* fallback */
- if(strings[16]) sfn_setstr(&ctx.name, strings[16], 0);
- }
- /* family name */
- if(!ctx.familyname) {
- if(strings[1]) sfn_setstr(&ctx.familyname, strings[1], 0); else
- if(strings[16]) sfn_setstr(&ctx.familyname, strings[16], 0);
- }
- /* subfamily name */
- if(!ctx.subname) {
- if(strings[2]) sfn_setstr(&ctx.subname, strings[2], 0); else
- if(strings[17]) sfn_setstr(&ctx.subname, strings[17], 0);
- }
- /* version / revision */
- if(!ctx.revision && strings[5]) sfn_setstr(&ctx.revision, strings[5], 0);
- /* manufacturer */
- if(!ctx.manufacturer) {
- if(strings[8]) sfn_setstr(&ctx.manufacturer, strings[8], 0); else
- if(strings[9]) sfn_setstr(&ctx.manufacturer, strings[9], 0);
- }
- /* copyright */
- if(!ctx.license) {
- if(strings[13]) sfn_setstr(&ctx.license, strings[13], 0); else
- if(strings[0]) sfn_setstr(&ctx.license, strings[0], 0); else
- if(strings[7]) sfn_setstr(&ctx.license, strings[7], 0);
- }
- }
- /**
- * Parse Bits'N'Picas font format (binary)
- */
- void kbits(unsigned char *ptr, int size)
- {
- uint8_t *end = ptr + size, *s, *save;
- unsigned char *bitmap = NULL;
- char *strings[32] = { 0 };
- int i, j, k, numchars = 0, a, x, y, w, h;
- ctx.height = ptr[0x17]; /* lineAscent */
- ctx.baseline = ctx.underline = 0;
- ptr += 0x24;
- while(ptr < end && (!memcmp(ptr, "name", 4) || !memcmp(ptr, "\0ame", 4))) {
- if(ptr[11] < 32) strings[(int)ptr[11]] = (char*)ptr + 14;
- ptr += 14 + ((ptr[12] << 8) | ptr[13]); *ptr = 0;
- }
- kbits_name(strings);
- save = ptr;
- while(ptr < end && (!memcmp(ptr, "char", 4) || !memcmp(ptr, "\0har", 4))) {
- if(ctx.baseline < ptr[0x17]) ctx.baseline = ptr[0x17];
- if(ctx.height < ptr[0x1b]) ctx.height = ptr[0x1b];
- for(i = ptr[0x1b], ptr += 0x1c; i > 0; i--, ptr += 4 + ptr[3]);
- numchars++;
- }
- if(ctx.underline < ctx.baseline) ctx.underline = ctx.baseline;
- ptr = save;
- while(ptr < end && (!memcmp(ptr, "char", 4) || !memcmp(ptr, "\0har", 4))) {
- s = ptr;
- x = (char)ptr[0x13]; y = ctx.baseline - (char)ptr[0x17]; h = ptr[0x1b];
- if(y < 0 || y > ctx.height || h < 1) y = 0;
- if(x < 0 || x >= 255) x = 0;
- for(w = 0, i = ptr[0x1b], ptr += 0x1c; i > 0; i--, ptr += 4 + ptr[3]) if(ptr[3] > w) w = ptr[3];
- if(x + w > ctx.width) ctx.width = x + w;
- if(y + h > ctx.height) ctx.height = y + h;
- }
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, ctx.baseline,
- ctx.underline, ctx.height);
- ptr = save;
- while(ptr < end && (!memcmp(ptr, "char", 4) || !memcmp(ptr, "\0har", 4))) {
- s = ptr;
- a = ptr[0xf]; x = (char)ptr[0x13]; y = ctx.baseline - ptr[0x17]; h = ptr[0x1b];
- if(y < 0 || y > ctx.height || h < 1) y = 0;
- unicode = (ptr[8] << 24) | (ptr[9] << 16) | (ptr[10] << 8) | ptr[11];
- for(w = 0, i = s[0x1b], s += 0x1c; i > 0; i--, s += 4 + s[3]) if(s[3] > w) w = s[3];
- bitmap = realloc(bitmap, w * h + 1);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memset(bitmap, 0xFF, w * h + 1);
- for(i = h, ptr += 0x1c, k = 0; i > 0; i--, ptr += 4 + ptr[3], k += w)
- for(j = 0; j < ptr[3]; j++) bitmap[k + j] = ptr[4 + j] > 127 ? 0xFE : 0xFF;
- if(y + h > ctx.height) h = ctx.height - y;
- if(sfn_charadd(unicode, (x < 0 ? 0 : x) + w, y + h, a, 0, (x < 0 ? -x : 0)))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, (x < 0 ? 0 : x), y, w, h, 0xFE, bitmap);
- }
- if(bitmap) free(bitmap);
- }
- /**
- * Parse Bits'N'Picas font format (text)
- */
- void kbitx(char *ptr, int size)
- {
- unsigned char *bitmap = NULL, *buf = NULL, *buf2;
- char *strings[32] = { 0 }, *s, *e, *save, *end = ptr + size;
- int i, j, l, numchars = 0, a, x, y, w, h;
- int repeatCount = 0, repeatData = -1, data;
- while(ptr < end && *ptr && memcmp(ptr, "<g ", 3) && memcmp(ptr, "</kbits", 7)) {
- if(!memcmp(ptr, "<name ", 6)) {
- for(i = -1, e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
- if(!memcmp(s, "id=\"", 4)) { s += 4; i = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- if(!memcmp(s, "value=\"", 7)) { s += 7; e = s; while(*s && *s != '\n' && *s != '\"') s++; }
- }
- if(i >= 0 && i < 32 && e) strings[i] = e;
- }
- while(*ptr && *ptr!='\n') ptr++;
- while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
- }
- ctx.height = ctx.baseline = ctx.underline = 0;
- kbits_name(strings);
- save = ptr;
- while(ptr < end && *ptr && !memcmp(ptr, "<g ", 3)) {
- y = 0;
- for(e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
- if(!memcmp(s, "y=\"", 3)) { s += 3; y = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; }
- }
- if(y > ctx.baseline) ctx.baseline = y;
- while(*ptr && *ptr!='\n') ptr++;
- while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
- numchars++;
- }
- if(ctx.underline < ctx.baseline) ctx.underline = ctx.baseline;
- ptr = save;
- while(ptr < end && *ptr && !memcmp(ptr, "<g ", 3)) {
- x = y = w = h = 0;
- for(e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
- if(!memcmp(s, "x=\"", 3)) { s += 3; x = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- if(!memcmp(s, "y=\"", 3)) { s += 3; y = ctx.baseline - atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- if(!memcmp(s, "d=\"", 3)) { s += 3; e = s; while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; }
- }
- if(y < 0 || y > ctx.height || h < 1) y = 0;
- if(x < 0 || x >= 255) x = 0;
- while(*ptr && *ptr!='\n') ptr++;
- while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
- if(e) {
- buf2 = buf = realloc(buf, ptr - e + 256);
- if(!buf2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memset(buf, 0, ptr - e + 256);
- if(base64_decode(e, buf) > 2) {
- buf2 = getleb(buf2, (unsigned int*)&h);
- buf2 = getleb(buf2, (unsigned int*)&w);
- };
- };
- if(x + w > ctx.width) ctx.width = x + w;
- if(y + h > ctx.height) ctx.height = y + h;
- }
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, ctx.baseline,
- ctx.underline, ctx.height);
- ptr = save;
- while(ptr < end && *ptr && !memcmp(ptr, "<g ", 3)) {
- a = x = y = w = h = 0;
- for(e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
- if(!memcmp(s, "u=\"", 3)) { s += 3; unicode = (uint32_t)atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- if(!memcmp(s, "x=\"", 3)) { s += 3; x = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- if(!memcmp(s, "y=\"", 3)) { s += 3; y = ctx.baseline - atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- /* this isn't width, this is actually advance x */
- if(!memcmp(s, "w=\"", 3)) { s += 3; a = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
- if(!memcmp(s, "d=\"", 3)) { s += 3; e = s; while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; }
- }
- while(*ptr && *ptr!='\n') ptr++;
- while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
- if(e) {
- buf2 = buf = realloc(buf, ptr - e + 256);
- if(!buf2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memset(buf, 0, ptr - e + 256);
- if((l = base64_decode(e, buf)) > 2) {
- buf2 = getleb(buf2, (unsigned int*)&h);
- buf2 = getleb(buf2, (unsigned int*)&w);
- bitmap = realloc(bitmap, w * h + 1);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- memset(bitmap, 0xFF, w * h + 1);
- for(j = repeatCount = 0, repeatData = -1; j < w * h && buf2 <= buf + l; ) {
- if(repeatCount > 0) {
- repeatCount--;
- if(repeatData == -1) {
- bitmap[j++] = buf2 == buf + l || *buf2++ > 127 ? 0xFE : 0xFF;
- continue;
- } else {
- bitmap[j++] = repeatData > 127 ? 0xFE : 0xFF;
- continue;
- }
- }
- if(buf2 == buf + l) { bitmap[j++] = 0xFE; break; }
- data = *buf2++;
- repeatCount = data & 0x1F;
- if((data & 0x20) != 0) repeatCount <<= 5;
- switch(data & 0xC0) {
- case 0x00: repeatData = 0x00; break;
- case 0x40: repeatData = 0xFF; break;
- case 0x80:
- if(buf2 == buf + l) { bitmap[j++] = 0xFE; buf2++; break; }
- repeatData = *buf2++;
- break;
- case 0xC0: repeatData = -1; break;
- }
- }
- } else x = w = 0;
- } else x = w = 0;
- if(sfn_charadd(unicode, (x < 0 ? 0 : x) + w, y + h, a, 0, (x < 0 ? -x : 0)))
- sfn_layeradd(unicode, SSFN_FRAG_BITMAP, (x < 0 ? 0 : x), y, w, h, 0xFE, bitmap);
- }
- if(bitmap) free(bitmap);
- if(buf) free(buf);
- }
- /**
- * Raw ROM image (binary)
- */
- void raw(unsigned char *ptr, int size, int h)
- {
- unsigned char *bitmap;
- int w = (size / h / 256) << 3, unicode, i, j, k, l, p, m;
- if(size < 2048 || !w) return;
- bitmap = (unsigned char*)malloc(w * h);
- if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", "", 256, h, h, h);
- m = (w >> 3) * h;
- for(unicode = 0; unicode < 256; unicode++) {
- for(k = l = 0; k < h; k++)
- for(p = unicode * m + (w >> 3) * k, j = 0x80, i = 0; i < w; i++, j >>= 1) {
- if(!j) { j = 0x80; p++; }
- bitmap[l++] = (ptr[p] & j) ? 0xFE : 0xFF;
- }
- if(sfn_charadd(doscp[unicode], w, h, w + 1, 0, 0))
- sfn_layeradd(doscp[unicode], SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
- }
- free(bitmap);
- ctx.width = w;
- ctx.height = h;
- if(!ctx.baseline) ctx.baseline = ctx.underline = h;
- ctx.family = SSFN_FAMILY_MONOSPACE;
- }
- /**
- * Parse a pixel map in memory
- */
- void pixmap_parse(unsigned char *data, int w, int h)
- {
- unsigned char *data2, l = 0xFE;
- unsigned int i, j, k, x, y, m, o, pw = 0, ph = 0, X, Y;
- int unicode, s;
- if(rs==0 && re==0x10FFFF) {
- /* try to detect square images with 16 x 16 glyphs. Use -X and -Y explicitly on command line to override */
- if(!px && !py && w >= 128 && h >= 128 && (w == h || w * 2 == h)) { pw = w / 16; ph = h / 16; re = 255; }
- if(px > 0 && py > 0) { pw = px; ph = py; }
- /* if we have exact glyph dimensions */
- if(pw >= 8 && ph >= 8) {
- data2 = (unsigned char*)malloc(pw*ph);
- if(!data2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- for(unicode = rs, Y = 0; Y < (unsigned int)h; Y += ph)
- for(X = 0; unicode <= re && X < (unsigned int)w; X += pw, unicode++) {
- for(y=o=k=0,s=-1,l=0xFE;y<ph;y++) {
- i = (Y+y)*w + X;
- for(x=0;x<pw;x++) {
- if(data[i] < 0xFF){
- if(k < x) k = x;
- if(s == -1) { l = data[i]; s = 1; }
- if(s && data[i] != l) s = 0;
- }
- data2[o++] = data[i++];
- }
- }
- if(s) for(i=0;i<pw*ph;i++)if(data2[i] != 0xFF) data2[i] = 0xFE;
- if(sfn_charadd(unicode, pw, ph, k+1, 0, 0))
- sfn_layeradd(unicode, s ? SSFN_FRAG_BITMAP : SSFN_FRAG_PIXMAP, 0, 0, pw, ph, l, data2);
- if(pbar) (*pbar)(0, 0, unicode, re - rs, PBAR_SQRPIX);
- }
- free(data2);
- return;
- } else
- re = h > w ? h / w : w / h;
- }
- if(h > w) {
- m = h / (re - rs + 1);
- if(m < 8 || w < 8) { fprintf(stderr, "libsfn: unable to determine glyph size\n"); return; }
- for(unicode=rs, i=0; unicode<=re; unicode++, i += w*m) {
- for(y=k=0,s=-1,l=0xFE;y<m;y++)
- for(j=w-1;j>k;j--)
- if(data[i+y*w+j] < 0xFF) k=j;
- if(sfn_charadd(unicode, w, m, k+1, 0, 0))
- sfn_layeradd(unicode, SSFN_FRAG_PIXMAP, 0, 0, w, m, 0xFE, data + i);
- if(pbar) (*pbar)(0, 0, unicode, re - rs, PBAR_TALLPIX);
- }
- } else {
- m = w / (re - rs + 1);
- if(m < 8 || h < 8) { fprintf(stderr, "libsfn: unable to determine glyph size\n"); return; }
- data2 = (unsigned char*)malloc(m*h);
- if(!data2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- for(unicode=rs; unicode<=re; unicode++) {
- for(y=o=k=0;y<(unsigned int)h;y++) {
- i = y*w + (unicode-rs)*m;
- for(x=0;x<m;x++) {
- if(data[i] < 0xFF && k < x) k = x;
- data2[o++] = data[i++];
- }
- }
- if(sfn_charadd(unicode, m, h, k+1, 0, 0))
- sfn_layeradd(unicode, SSFN_FRAG_PIXMAP, 0, 0, m, h, 0xFE, data2);
- if(pbar) (*pbar)(0, 0, unicode, re - rs, PBAR_WIDEPIX);
- }
- free(data2);
- }
- }
- /**
- * Parse PNG format for pixel fonts (binary)
- */
- void png(unsigned char *ptr, int size)
- {
- unsigned char *data, *data2;
- unsigned int i, w, h, f;
- stbi__context s;
- stbi__result_info ri;
- #ifdef HAS_QUANT
- liq_attr *handle = NULL;
- liq_image *input_image = NULL;
- liq_result *quantization_result;
- const liq_palette *liqpalette;
- unsigned char pal[256];
- #endif
- s.read_from_callbacks = 0;
- s.img_buffer = s.img_buffer_original = ptr;
- s.img_buffer_end = s.img_buffer_original_end = ptr+size;
- w = h = size = 0;
- ri.bits_per_channel = 8;
- data = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&f, 0, &ri);
- if(!data || (f != STBI_rgb_alpha && f != STBI_rgb) || w < 1 || h < 1)
- { fprintf(stderr,"libsfn: unsupported PNG format\n"); return; }
- data2 = (unsigned char*)malloc(w * h);
- if(!data2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- #ifdef HAS_QUANT
- handle = liq_attr_create();
- liq_set_max_colors(handle, 254);
- if(f == STBI_rgb_alpha)
- input_image = liq_image_create_rgba(handle, data, w, h, 0);
- if(pbar) (*pbar)(0, 0, 0, 1, PBAR_QUANT);
- if (f == STBI_rgb_alpha && liq_image_quantize(input_image, handle, &quantization_result) == LIQ_OK) {
- liq_set_dithering_level(quantization_result, 1.0);
- liqpalette = liq_get_palette(quantization_result);
- liq_write_remapped_image(quantization_result, input_image, data, w * h);
- for(i = 0; i < liqpalette->count && i < 254; i++) {
- pal[i] = sfn_cpaladd(liqpalette->entries[i].r, liqpalette->entries[i].g,
- liqpalette->entries[i].b, liqpalette->entries[i].a);
- }
- for(i = 0; i < w * h; i++)
- data2[i] = pal[data[i]];
- liq_result_destroy(quantization_result);
- } else
- #endif
- {
- if(f == STBI_rgb_alpha)
- for(i = 0; i < w * h; i++) {
- if(pbar) (*pbar)(0, 0, i, w * h, PBAR_QUANT);
- data2[i] = sfn_cpaladd(data[i*4], data[i*4+1], data[i*4+2], data[i*4+3]);
- }
- else
- for(i = 0; i < w * h; i++) {
- if(pbar) (*pbar)(0, 0, i, w * h, PBAR_QUANT);
- data2[i] = sfn_cpaladd(data[i*3], data[i*3+1], data[i*3+2], 255);
- }
- }
- #ifdef HAS_QUANT
- if(input_image) liq_image_destroy(input_image);
- liq_attr_destroy(handle);
- #endif
- free(data);
- pixmap_parse(data2, w, h);
- free(data2);
- }
- /**
- * Parse TGA format for pixel fonts (binary)
- */
- void tga(unsigned char *ptr, int size)
- {
- unsigned char *data;
- int i, j, k, x, y, w, h, o, m;
- o = (ptr[11] << 8) + ptr[10];
- w = (ptr[13] << 8) + ptr[12];
- h = (ptr[15] << 8) + ptr[14];
- if(w<1 || h<1) {
- tgaerr: fprintf(stderr,"libsfn: unsupported TGA file format\n");
- return;
- }
- m = ((ptr[1]? (ptr[7]>>3)*ptr[5] : 0) + 18);
- data = (unsigned char*)malloc(w*h);
- if(!data) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
- switch(ptr[2]) {
- case 1:
- if(ptr[6]!=0 || ptr[4]!=0 || ptr[3]!=0 || (ptr[7]!=24 && ptr[7]!=32)) goto tgaerr;
- for(y=i=0; y<h; y++) {
- k = ((!o?h-y-1:y)*w);
- for(x=0; x<w; x++) {
- j = ptr[m + k++]*(ptr[7]>>3) + 18;
- data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[7]==32?ptr[j+3]:0xFF);
- }
- }
- break;
- case 2:
- if(ptr[5]!=0 || ptr[6]!=0 || ptr[1]!=0 || (ptr[16]!=24 && ptr[16]!=32)) goto tgaerr;
- for(y=i=0; y<h; y++) {
- j = m+((!o?h-y-1:y)*w*(ptr[16]>>3));
- for(x=0; x<w; x++) {
- data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[16]==32?ptr[j+3]:0xFF);
- j += ptr[16]>>3;
- }
- }
- break;
- case 9:
- if(ptr[6]!=0 || ptr[4]!=0 || ptr[3]!=0 || (ptr[7]!=24 && ptr[7]!=32)) goto tgaerr;
- y = i = 0;
- for(x=0; x<w*h && m<size;) {
- k = ptr[m++];
- if(k > 127) {
- k -= 127; x += k;
- j = ptr[m++]*(ptr[7]>>3) + 18;
- while(k--) {
- if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
- data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[7]==32?ptr[j+3]:0xFF);
- }
- } else {
- k++; x += k;
- while(k--) {
- j = ptr[m++]*(ptr[7]>>3) + 18;
- if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
- data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[7]==32?ptr[j+3]:0xFF);
- }
- }
- }
- break;
- case 10:
- if(ptr[5]!=0 || ptr[6]!=0 || ptr[1]!=0 || (ptr[16]!=24 && ptr[16]!=32)) goto tgaerr;
- y = i = 0;
- for(x=0; x<w*h && m<size;) {
- k = ptr[m++];
- if(k > 127) {
- k -= 127; x += k;
- while(k--) {
- if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
- data[i++] = sfn_cpaladd(ptr[m+2], ptr[m+1], ptr[m], ptr[16]==32?ptr[m+3]:0xFF);
- }
- m += ptr[16]>>3;
- } else {
- k++; x += k;
- while(k--) {
- if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
- data[i++] = sfn_cpaladd(ptr[m+2], ptr[m+1], ptr[m], ptr[16]==32?ptr[m+3]:0xFF);
- m += ptr[16]>>3;
- }
- }
- }
- break;
- }
- pixmap_parse(data, w, h);
- free(data);
- }
- #endif
|