bitmap.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. /*
  2. * libsfn/bitmap.c
  3. *
  4. * Copyright (C) 2020 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * @brief File functions for bitmap and pixmap fonts
  27. *
  28. */
  29. #ifndef USE_NOFOREIGN
  30. #include <stdint.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #ifdef HAS_QUANT
  35. #include "libimagequant.h"
  36. #endif
  37. #define STBI_IMPLEMENTATION
  38. #include "stb_png.h"
  39. #include <ssfn.h>
  40. #include "libsfn.h"
  41. #include "bitmap.h"
  42. /* DOS 437 codepage to UNICODE (needed by BMF importer) */
  43. static int doscp[256] = {
  44. 0x0000,0x263A,0x263B,0x2665,0x2666,0x2663,0x2660,0x2022,0x25D8,0x25CB,0x25D9,0x2642,0x2640,0x266A,0x266B,0x263C,
  45. 0x25BA,0x25C4,0x2195,0x203C,0x00B6,0x00A7,0x25AC,0x21A8,0x2191,0x2193,0x2192,0x2190,0x221F,0x2194,0x25B2,0x25BC,
  46. 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
  47. 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
  48. 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
  49. 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
  50. 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
  51. 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
  52. 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
  53. 0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
  54. 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
  55. 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
  56. 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
  57. 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
  58. 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
  59. 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
  60. };
  61. typedef struct {
  62. uint32_t magic;
  63. uint8_t version;
  64. uint8_t lineHeight;
  65. int8_t sizeOver;
  66. int8_t sizeUnder;
  67. int8_t addSpace;
  68. int8_t sizeInner;
  69. uint8_t usedColors;
  70. uint8_t highestColor;
  71. uint8_t alphaBits;
  72. uint8_t extraPalettes;
  73. uint16_t reserved;
  74. uint8_t numColors;
  75. } __attribute__((packed)) bmf_t;
  76. typedef struct {
  77. unsigned int magic;
  78. unsigned int version;
  79. unsigned int headersize;
  80. unsigned int flags;
  81. unsigned int numglyph;
  82. unsigned int bytesperglyph;
  83. unsigned int height;
  84. unsigned int width;
  85. unsigned char glyphs;
  86. } __attribute__((packed)) psf_t;
  87. /****************************** file format parsers ******************************/
  88. /**
  89. * Parse PSF2 font (binary)
  90. */
  91. void psf(unsigned char *ptr, int size)
  92. {
  93. psf_t *psf = (psf_t*)ptr;
  94. uint16_t *utbl = NULL;
  95. uint32_t c, g=0, unicode, nc = 0, numchars = psf->numglyph;
  96. unsigned char *s, *e, *glyph, *bitmap;
  97. int i, j, k, l, n;
  98. s=(unsigned char*)(ptr + psf->headersize + psf->numglyph*psf->bytesperglyph);
  99. e=ptr + size;
  100. /* try to fix bad fonts */
  101. if(s > e) {
  102. for(s = e; s + 1 > ptr + psf->headersize && (s[-1] || s[0] == 0xFF); s--);
  103. psf->numglyph = ((int)(s - ptr) - psf->headersize) / psf->bytesperglyph;
  104. }
  105. if(s < e) {
  106. numchars = 0;
  107. utbl = (uint16_t*)malloc(0x110000*sizeof(uint16_t));
  108. if(!utbl) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  109. memset(utbl, 0, 0x110000*sizeof(uint16_t));
  110. while(s<e && g<psf->numglyph) {
  111. c = (uint16_t)((uint8_t)s[0]);
  112. if(c == 0xFF) { g++; } else {
  113. if((c & 128) != 0) {
  114. if((c & 32) == 0 ) { c=((s[0] & 0x1F)<<6)+(s[1] & 0x3F); s++; } else
  115. if((c & 16) == 0 ) { c=((((s[0] & 0xF)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F); s+=2; } else
  116. if((c & 8) == 0 ) { c=((((((s[0] & 0x7)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F))<<6)+(s[3] & 0x3F); s+=3;}
  117. else c=0;
  118. }
  119. if(c<0x110000) {
  120. utbl[c] = g;
  121. numchars++;
  122. }
  123. }
  124. s++;
  125. }
  126. }
  127. if((psf->flags >> 24) && !ctx.baseline) ctx.baseline = (psf->flags >> 24);
  128. if(psf->width < 1) psf->width = 1;
  129. if(psf->height < 1) psf->height = 1;
  130. l = ((psf->width + 7) & ~7) * (psf->height + 1);
  131. bitmap = (unsigned char*)malloc(l);
  132. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  133. for(unicode=rs;unicode<=(uint32_t)re;unicode++) {
  134. g = utbl? utbl[unicode] : unicode;
  135. if((!g && unicode && !iswhitespace(unicode)) || g >= psf->numglyph) continue;
  136. glyph = ptr + psf->headersize + g*psf->bytesperglyph;
  137. memset(bitmap, 0, l);
  138. for(i=k=0;i<(int)psf->bytesperglyph;) {
  139. for(n = 0; n < (int)psf->width; i++)
  140. for(j=0x80;j && n < (int)psf->width;j>>=1,n++)
  141. bitmap[k+n] = (glyph[i] & j) ? 0xFE : 0xFF;
  142. k += psf->width;
  143. }
  144. if(sfn_charadd(unicode, psf->width, psf->height, 0, 0, 0))
  145. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, psf->width, psf->height, 0xFE, bitmap);
  146. if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
  147. }
  148. free(bitmap);
  149. free(utbl);
  150. }
  151. /**
  152. * Parse GRUB's PFF2 font (binary)
  153. * yet another messy, resource wasteful, extremely badly documented format...
  154. */
  155. void pff(unsigned char *ptr, int size)
  156. {
  157. uint32_t len = 0, unicode, nc = 0, numchars = 0;
  158. int16_t w = 0, h = 0, p, n, a /*, x, y, mix, miy, max, may*/;
  159. int i, j, k, m;
  160. unsigned char *end = ptr + size, *section, *data = ptr, *bitmap;
  161. ptr += 12;
  162. while(ptr < end && len < (uint32_t)size) {
  163. len = (ptr[4] << 24) | (ptr[5] << 16) | (ptr[6] << 8) | ptr[7];
  164. section = ptr + 8;
  165. if(!memcmp(ptr, "NAME", 4)) sfn_setstr(&ctx.name, (char*)section, len); else
  166. if(!memcmp(ptr, "FAMI", 4)) sfn_setstr(&ctx.familyname, (char*)section, len); else
  167. if(!memcmp(ptr, "WEIG", 4) && section[0]=='b') ctx.style |= SSFN_STYLE_BOLD; else
  168. if(!memcmp(ptr, "SLAN", 4) && section[0]=='i') ctx.style |= SSFN_STYLE_ITALIC; else
  169. if(!memcmp(ptr, "MAXW", 4)) w = (section[0] << 8) | section[1]; else
  170. if(!memcmp(ptr, "MAXH", 4)) h = (section[0] << 8) | section[1]; else
  171. if(!memcmp(ptr, "ASCE", 4)) ctx.baseline = (section[0] << 8) | section[1]; else
  172. if(!memcmp(ptr, "CHIX", 4)) {
  173. /*mix = miy = max = may = 0;*/
  174. for(end = section + len, ptr = section; ptr < end; ptr += 9) {
  175. if(!ptr[4]) {
  176. n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 0] << 8) |
  177. data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 1];
  178. if(n > w) w = n;
  179. n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 2] << 8) |
  180. data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 3];
  181. if(n > h) h = n;
  182. /*
  183. n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 4] << 8) |
  184. data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 5];
  185. if(n < mix) { mix = n; } if(n > max) max = n;
  186. n = (data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 6] << 8) |
  187. data[((ptr[5] << 24) | (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]) + 7];
  188. if(n < miy) { miy = n; } if(n > may) may = n;
  189. */
  190. numchars++;
  191. }
  192. }
  193. ctx.width = w/* - mix + max*/;
  194. ctx.height = h/* - miy + may*/;
  195. /* ctx.baseline -= miy; */
  196. printf("\r Name '%s' num_glyphs: %d, ascender: %d, width: %d, height: %d\n", ctx.name, numchars, ctx.baseline,
  197. ctx.width, ctx.height);
  198. n = ctx.width * ctx.height;
  199. bitmap = (unsigned char*)malloc(n);
  200. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  201. for(end = section + len; section < end; section += 9) {
  202. /* undocumented: section[4] supposed to indicate compression of some sort? grub-mkfont.c always writes 0 */
  203. if(!section[4]) {
  204. /* undocumented: section[0] holds left and right joins (or both), not sure what to do with those */
  205. unicode = (section[1] << 16) | (section[2] << 8) | section[3];
  206. ptr = data + ((section[5] << 24) | (section[6] << 16) | (section[7] << 8) | section[8]);
  207. memset(bitmap, 0xFF, n);
  208. w = (ptr[0] << 8) | ptr[1]; h = (ptr[2] << 8) | ptr[3];
  209. /* x = (ptr[4] << 8) | ptr[5]; y = (ptr[6] << 8) | ptr[7];*/
  210. a = (ptr[8] << 8) | ptr[9];
  211. p = w; /* + (x < 0 ? 0 : x); h -= y;*/
  212. ptr += 10; /*k = (y - miy) * p;*/
  213. for(j = k = 0, m = 0x80; j < h; j++, k += p)
  214. for(i = 0; i < w; i++, m >>= 1) {
  215. if(!m) { m = 0x80; ptr++; }
  216. if(ptr[0] & m) bitmap[k + i/* + (x < 0 ? 0 : x)*/] = 0xFE;
  217. }
  218. if(sfn_charadd(unicode, p, h, a, 0, /*x < 0 ? -x :*/ 0))
  219. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, p, h, 0xFE, bitmap);
  220. if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
  221. }
  222. }
  223. free(bitmap);
  224. break;
  225. }
  226. ptr += 8 + len;
  227. }
  228. }
  229. /**
  230. * Parse fucked up Windows Console Font (binary)
  231. */
  232. void fnt(unsigned char *ptr, int size)
  233. {
  234. int i, j, k, l, m, w, h, p, mn, mx, defchar;
  235. unsigned char *data = ptr, *bit, map[8192], *bitmap = NULL, ver, charset;
  236. /* skip over executable header... */
  237. if(ptr[0] == 'M' && ptr[1] == 'Z') {
  238. ptr += ((ptr[0x3D] << 8) | ptr[0x3C]); if(ptr[0] != 'N' || ptr[1] != 'E') return;
  239. ptr += ((ptr[37] << 8) | ptr[36]); j = ((ptr[1] << 8) | ptr[0]); ptr += 2; if(j > 16) return;
  240. for(i = 0; i < 16 && (ptr[0] || ptr[1]); i++) {
  241. if(ptr[0] == 0x08 && ptr[1] == 0x80) {
  242. if(((ptr[3] << 8) | ptr[2]) < 1) { return; } ptr += 8; ptr = data + (((ptr[1] << 8) | ptr[0]) << j); break;
  243. } else ptr += ((ptr[3] << 8) | ptr[2]) * 12 + 8;
  244. }
  245. }
  246. /* parse Windows resource file */
  247. if(ptr[0] || (ptr[1] != 2 && ptr[1] != 3) || ((ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) > size ||
  248. (ptr[66] & 1)) return;
  249. sfn_setstr(&ctx.name, (char*)(ptr + ((ptr[107] << 16) | (ptr[106] << 8) | ptr[105])), 0);
  250. sfn_setstr(&ctx.license, (char*)(ptr + 6), 0);
  251. h = ((ptr[89] << 8) | ptr[88]); charset = ptr[85];
  252. mn = ptr[95]; mx = ptr[96]; defchar = ptr[97] + mn; ctx.baseline = ((ptr[75] << 8) | ptr[74]);
  253. if(ptr[80]) ctx.style |= SSFN_STYLE_ITALIC;
  254. if(((ptr[84] << 8) | ptr[83]) > 400) ctx.style |= SSFN_STYLE_BOLD;
  255. switch(ptr[90] >> 4) {
  256. case 2: ctx.family = SSFN_FAMILY_SANS; break;
  257. case 3: ctx.family = SSFN_FAMILY_MONOSPACE; break;
  258. case 4: ctx.family = SSFN_FAMILY_HAND; break;
  259. case 5: ctx.family = SSFN_FAMILY_DECOR; break;
  260. default: ctx.family = SSFN_FAMILY_SERIF; break;
  261. }
  262. printf("\r Name '%s' num_glyphs: %d, ascender: %d, height: %d\n", ctx.name, mx - mn + 1, ctx.baseline, h);
  263. if(!h || mn >= mx) return;
  264. ver = ptr[1]; data = ptr; ptr += (ptr[1] == 3 ? 148 : 118);
  265. /* get bitmaps */
  266. for(unicode = mn; unicode <= mx; unicode++, ptr += ver == 3 ? 6 : 4) {
  267. w = ptr[0]; bit = data + ((ver == 3 ? (ptr[4] << 16) : 0) | (ptr[3] << 8) | ptr[2]);
  268. p = ((w - 1) >> 3) + 1;
  269. if(p * h > (int)sizeof(map)) continue;
  270. bitmap = realloc(bitmap, w * h);
  271. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  272. /* 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 */
  273. for(j = 0; j < p; j++)
  274. for(k = 0; k < h; k++)
  275. map[k * p + j] = *bit++;
  276. for(i = k = l = 0; k < h; k++)
  277. for(j = 0, l = k * p, m = 0x80; j < w; j++, m >>= 1) {
  278. if(!m) { m = 0x80; l++; }
  279. bitmap[i++] = map[l] & m ? 0xFE : 0xFF;
  280. }
  281. if(sfn_charadd(charset ? unicode : doscp[unicode], w, h, 0, 0, 0))
  282. sfn_layeradd(charset ? unicode : doscp[unicode], SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
  283. if(unicode == defchar) {
  284. sfn_chardel(0);
  285. if(sfn_charadd(0, w, h, 0, 0, 0))
  286. sfn_layeradd(0, SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
  287. }
  288. }
  289. free(bitmap);
  290. }
  291. /**
  292. * Parse GNU unifont hex format (text)
  293. */
  294. void hex(char *ptr, int size)
  295. {
  296. uint32_t i, j, c, unicode, nc = 0, numchars;
  297. int w;
  298. char *end = ptr + size;
  299. unsigned char bitmap[256];
  300. numchars = 0;
  301. for(numchars=0;ptr < end && *ptr;ptr++) if(*ptr=='\n') numchars++;
  302. ptr = end - size;
  303. while(ptr < end && *ptr) {
  304. unicode = gethex(ptr, 6);
  305. while(*ptr && *ptr!=':') ptr++;
  306. if(!*ptr) return;
  307. ptr++;
  308. while(*ptr && (*ptr==' '||*ptr=='\t')) ptr++;
  309. if(!*ptr) return;
  310. memset(bitmap, 0, 256);
  311. for(i = 0;i<256 && *ptr && *ptr!='\n' && *ptr!='\r';ptr += 2) {
  312. c = gethex(ptr, 2);
  313. for(j=0x80;j;j>>=1) bitmap[i++] = (c & j) ? 0xFE : 0xFF;
  314. }
  315. while(*ptr && *ptr!='\n' && *ptr!='\r') ptr++;
  316. while(*ptr && (*ptr=='\n' || *ptr=='\r')) ptr++;
  317. w = i > 128 ? 16 : 8;
  318. if(sfn_charadd(unicode, w, 16, 0, 0, 0))
  319. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, w, 16, 0xFE, bitmap);
  320. if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
  321. }
  322. }
  323. /**
  324. * Parse X11 BDF font format and FontForge's SplineFontDB with bitmaps (text)
  325. */
  326. void bdf(char *ptr, int size)
  327. {
  328. uint32_t c;
  329. 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;
  330. char *end = ptr + size, *face, *name = NULL, *style = NULL, *manu = NULL;
  331. unsigned char *bitmap = NULL, sfd = 0, dec[4];
  332. for(face = ptr; face + 12 < end && *face; face++) {
  333. if(!memcmp(face, "ENCODING ", 9)) numchars++;
  334. if(!memcmp(face, "BDFChar:", 8)) { numchars++; sfd = 1; }
  335. if(!memcmp(face, "BitmapFont: ", 12)) {
  336. ptr += 12; while(*ptr == ' ') ptr++;
  337. ps = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  338. while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  339. b = atoi(ptr); if(!ctx.baseline) ctx.baseline = b;
  340. sfd = 1;
  341. }
  342. }
  343. face = NULL;
  344. while(ptr < end && *ptr) {
  345. if(!memcmp(ptr, "FACE_NAME ", 10) && !face) {
  346. ptr += 10; while(*ptr==' ') { ptr++; } if(*ptr=='\"') { ptr++; } face = ptr;
  347. }
  348. if(!memcmp(ptr, "FONT_NAME ", 10) && !face) {
  349. ptr += 10; while(*ptr==' ') { ptr++; } if(*ptr=='\"') { ptr++; } face = ptr;
  350. }
  351. if(!memcmp(ptr, "FONT_VERSION ", 13) && !ctx.revision) {
  352. ptr += 13; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  353. sfn_setstr(&ctx.revision, ptr, 0);
  354. }
  355. if(!memcmp(ptr, "ADD_STYLE_NAME ", 15) && !ctx.name && !style) {
  356. ptr += 15; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  357. style = ptr;
  358. }
  359. if(!memcmp(ptr, "FOUNDRY ", 8) && !ctx.manufacturer) {
  360. ptr += 8; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  361. manu = ptr;
  362. }
  363. if(!memcmp(ptr, "HOMEPAGE ", 9) && !ctx.manufacturer && !manu) {
  364. ptr += 9; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  365. manu = ptr;
  366. }
  367. if(!memcmp(ptr, "FAMILY_NAME ", 12) && !ctx.familyname) {
  368. ptr += 12; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  369. sfn_setstr(&ctx.familyname, ptr, 0);
  370. }
  371. if(!memcmp(ptr, "WEIGHT_NAME ", 12) && !ctx.subname) {
  372. ptr += 12; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  373. sfn_setstr(&ctx.subname, ptr, 0);
  374. }
  375. if(!memcmp(ptr, "COPYRIGHT ", 10) && !ctx.license) {
  376. ptr += 10; while(*ptr==' ') { ptr++; } if(*ptr=='\"') ptr++;
  377. sfn_setstr(&ctx.license, ptr, 0);
  378. }
  379. if(!memcmp(ptr, "FONT_ASCENT ", 12)) {
  380. ptr += 12; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
  381. b = atoi(ptr); if(!ctx.baseline) ctx.baseline = b; }
  382. if(!memcmp(ptr, "UNDERLINE_POSITION ", 19)) {
  383. ptr += 19; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
  384. relul = atoi(ptr); if(relul < 0) relul = -relul; }
  385. if(!memcmp(ptr, "DEFAULT_CHAR ", 13)) {
  386. ptr += 13; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
  387. defchar = atoi(ptr); }
  388. if(!memcmp(ptr, "PIXEL_SIZE ", 11) && !ps) {
  389. ptr += 11; if(sfd) { while(*ptr && *ptr != ' ') ptr++; } while(*ptr == ' ') ptr++;
  390. ps = atoi(ptr); }
  391. if(!memcmp(ptr, "ENDPROPERTIES", 13) || !memcmp(ptr, "BDFEndProperties", 16)) break;
  392. while(*ptr && *ptr!='\n') ptr++;
  393. while(*ptr=='\r' || *ptr=='\n') ptr++;
  394. }
  395. if(!ctx.name) {
  396. if(!face) face = ctx.familyname;
  397. if(face && style && style[0]) {
  398. for(i = 0; face[i] && face[i] != '\"' && face[i] != '\r' && face[i] != '\n'; i++);
  399. for(j = 0; style[j] && style[i] != '\"' && style[i] != '\r' && style[i] != '\n'; j++);
  400. name = malloc(i + j + 2);
  401. if(!name) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  402. memcpy(name, face, i);
  403. name[i] = ' ';
  404. memcpy(name + i + 1, style, j);
  405. name[i + j + 1] = 0;
  406. sfn_setstr(&ctx.name, name, 0);
  407. free(name);
  408. } else
  409. sfn_setstr(&ctx.name, ctx.familyname, 0);
  410. }
  411. if(!ctx.manufacturer && manu)
  412. sfn_setstr(&ctx.manufacturer, manu, 0);
  413. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, b, b + relul, ps);
  414. while(ptr < end && *ptr) {
  415. if(!sfd) {
  416. if(!memcmp(ptr, "ENCODING ", 9)) { ptr += 9; unicode = atoi(ptr); }
  417. if(!memcmp(ptr, "BBX ", 4)) {
  418. ptr += 4; w = atoi(ptr);
  419. while(*ptr && *ptr!=' ') ptr++;
  420. ptr++; h = atoi(ptr);
  421. while(*ptr && *ptr!=' ') ptr++;
  422. ptr++; l = atoi(ptr);
  423. while(*ptr && *ptr!=' ') ptr++;
  424. ptr++; t = atoi(ptr);
  425. }
  426. if(!memcmp(ptr, "BITMAP", 6)) {
  427. ptr += 6; while(*ptr && *ptr!='\n') ptr++;
  428. ptr++;
  429. if(skipcode && uniname(unicode) == UNICODE_NUMNAMES && !memcmp(ptr,"0000\n7FFE", 9) &&
  430. !memcmp(ptr + 35,"7FFE\n7FFE", 9)) ptr += 16*5;
  431. else if(w > 0 && h > 0 && w * h <= 65536) {
  432. bitmap = realloc(bitmap, ((w + 7) & ~7) * (h + 1));
  433. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); }
  434. else {
  435. for(i = 0;i < w * h && *ptr; ptr += 2) {
  436. while(*ptr=='\n' || *ptr=='\r') ptr++;
  437. c = gethex(ptr, 2);
  438. for(j=0x80,k=0;j && k < w && i < w * h;k++,j>>=1) bitmap[i++] = c & j ? 0xFE : 0xFF;
  439. }
  440. while(i < ((w + 7) & ~7) * (h + 1)) bitmap[i++] = 0xFF;
  441. if(!skipcode && unicode == defchar) { sfn_chardel(0); unicode = 0; }
  442. if(sfn_charadd(unicode, w, h, 0, 0, 0))
  443. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, l, ctx.baseline - t - h, w, h, 0xFE, bitmap);
  444. }
  445. }
  446. if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
  447. w = h = l = t = 0;
  448. }
  449. } else
  450. if(!memcmp(ptr, "BDFChar:", 8)) {
  451. ptr += 8; while(*ptr == ' ') ptr++;
  452. while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  453. unicode = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  454. w = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  455. mx = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  456. xx = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  457. my = atoi(ptr); while(*ptr && *ptr != ' ') { ptr++; } while(*ptr == ' ') ptr++;
  458. xy = atoi(ptr); while(*ptr && *ptr != ' ' && *ptr != '\n') { ptr++; } while(*ptr == ' ') ptr++;
  459. if(*ptr != '\n') a = atoi(ptr); else a = w;
  460. while(*ptr && *ptr != '\n') { ptr++; } while(*ptr == '\r' || *ptr == '\n') ptr++;
  461. h = ps; xx -= mx - 1; xy -= my - 1;
  462. xx = (xx + 7) & ~7;
  463. if(xx * xy < 65536) {
  464. bitmap = realloc(bitmap, xx * xy);
  465. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  466. for(i = 0, k = 4; i < xx * xy;) {
  467. if(k > 3) {
  468. if(!*ptr || *ptr == '\r' || *ptr == '\n') break;
  469. k = 0;
  470. if(*ptr == 'z') { dec[0] = dec[1] = dec[2] = dec[3] = 0; ptr++; }
  471. else {
  472. c = ((((ptr[0]-'!')*85 + ptr[1]-'!')*85 + ptr[2]-'!')*85 + ptr[3]-'!')*85 + ptr[4]-'!';
  473. dec[0] = (c >> 24) & 0xFF; dec[1] = (c >> 16) & 0xFF; dec[2] = (c >> 8) & 0xFF; dec[3] = c & 0xFF;
  474. ptr += 5;
  475. }
  476. }
  477. c = dec[k++];
  478. for(j = 0x80; j; j >>= 1) bitmap[i++] = c & j ? 0xFE : 0xFF;
  479. }
  480. while(i < xx * xy) bitmap[i++] = 0xFF;
  481. if(!skipcode && unicode == defchar) { sfn_chardel(0); unicode = 0; }
  482. if(sfn_charadd(unicode, w, h, a, 0, mx < 0 ? -mx : 0))
  483. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, xx, xy, 0xFE, bitmap);
  484. }
  485. if(pbar) (*pbar)(0, 0, ++nc, numchars, PBAR_BITMAP);
  486. }
  487. while(*ptr && *ptr!='\n') ptr++;
  488. while(*ptr=='\r' || *ptr=='\n') ptr++;
  489. }
  490. if(bitmap) free(bitmap);
  491. }
  492. /**
  493. * Parse X11 PCF font format (binary)
  494. */
  495. void pcf(unsigned char *ptr, int size)
  496. {
  497. 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;
  498. uint32_t boffs = 0, bitmaps = 0, metrics = 0, encodings = 0;
  499. unsigned char *bitmap = NULL, *bm;
  500. char *face = NULL, *name = NULL, *style = NULL, *manu = NULL;
  501. char *str, *s, *v;
  502. int x, y, o, a, b = 0, k, w, h = 0, p = 1, r, sx = 1, m, defchar = 0;
  503. #define pcf32(f,o) (f&(1<<2)? (ptr[o+0]<<24)|(ptr[o+1]<<16)|(ptr[o+2]<<8)|ptr[o+3] : \
  504. (ptr[o+3]<<24)|(ptr[o+2]<<16)|(ptr[o+1]<<8)|ptr[o+0])
  505. #define pcf16(f,o) (f&(1<<2)? (ptr[o+0]<<8)|ptr[o+1] : (ptr[o+1]<<8)|ptr[o+0])
  506. /* parse tables */
  507. for(i = 0; i < iptr[1]; i++) {
  508. fmt = iptr[i*4+3]; offs = iptr[i*4+5];
  509. if(offs + iptr[i*4+4] >= (uint32_t)size) continue;
  510. switch(iptr[i*4+2]) {
  511. case (1<<0): /* PCF_PROPERTIES */
  512. n = pcf32(fmt,offs+4); str = (char*)ptr + offs + ((n * 9 + 3)/4 + 3)*4;
  513. for(j = 0; j < n; j++) {
  514. s = str + pcf32(fmt,offs + 8 + j * 9); v = str + pcf32(fmt,offs + 13 + j * 9);
  515. if(!strcmp(s, "FACE_NAME") && !face) face = v; else
  516. if(!strcmp(s, "FONT_NAME") && !face) face = v; else
  517. if(!strcmp(s, "FONT_VERSION") && !ctx.revision) sfn_setstr(&ctx.revision, v, 0); else
  518. if(!strcmp(s, "ADD_STYLE_NAME") && !ctx.name && !style) style = v; else
  519. if(!strcmp(s, "FOUNDRY") && !ctx.manufacturer) manu = v; else
  520. if(!strcmp(s, "HOMEPAGE") && !ctx.manufacturer && !manu) manu = v; else
  521. if(!strcmp(s, "FAMILY_NAME") && !ctx.familyname) sfn_setstr(&ctx.subname, v, 0); else
  522. if(!strcmp(s, "WEIGHT_NAME") && !ctx.subname) sfn_setstr(&ctx.subname, v, 0); else
  523. if(!strcmp(s, "COPYRIGHT") && !ctx.license) sfn_setstr(&ctx.license, v, 0); else
  524. if(!strcmp(s, "PIXEL_SIZE")) { k = pcf32(fmt,offs + 13 + j * 9); if(k > h) h = k; } else
  525. if(!strcmp(s, "UNDERLINE_POSITION")) {
  526. relul = (int)pcf32(fmt,offs + 13 + j * 9); if(relul < 0) relul = -relul;
  527. }
  528. }
  529. break;
  530. case (1<<2): /* PCF_METRICS */
  531. metrics = offs; mf = fmt; b = 0;
  532. if(fmt & 0x100) {
  533. n = pcf16(fmt,offs + 4);
  534. for(j=0; j<n; j++) { k = (int)ptr[offs+3+6+j*5]-0x80; if(k > b) b = k; }
  535. for(j=0; j<n; j++) { k = (int)ptr[offs+4+6+j*5]-0x80 + b; if(k > h) h = k; }
  536. } else {
  537. n = pcf32(fmt,offs + 4);
  538. for(j = 0; j < n; j++) { k = pcf16(fmt,offs+6+8+j*12); if(k > b) b = k; }
  539. for(j = 0; j < n; j++) { k = pcf16(fmt,offs+8+8+j*12) + b; if(k > h) h = k; }
  540. }
  541. if(!mn && !mx && n) mx = n - 1;
  542. if(!mg || n < mg) mg = n;
  543. break;
  544. case (1<<3): /* PCF_BITMAPS */
  545. boffs = offs + 8; bf = fmt; n = pcf32(fmt,offs+4);
  546. bitmaps = boffs + n * 4 + 16; bs = iptr[i*4+4] + offs - bitmaps;
  547. p = 1 << (fmt & 3); sx = fmt & (1 << 2) ? 1 : -1;
  548. if(!mg || n < mg) mg = n;
  549. break;
  550. case (1<<5): /* PCF_BDF_ENCODINGS */
  551. encodings = offs + 14; ef = fmt;
  552. mn = (pcf16(fmt, offs + 8)<<8) | pcf16(fmt, offs + 4);
  553. mx = (pcf16(fmt, offs + 10)<<8) | pcf16(fmt, offs + 6);
  554. defchar = pcf16(fmt, offs + 12);
  555. break;
  556. }
  557. }
  558. if(!ctx.name) {
  559. if(!face) face = ctx.familyname;
  560. if(face && style && style[0]) {
  561. i = strlen(face); j = strlen(style);
  562. name = malloc(i + j + 2);
  563. if(!name) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  564. memcpy(name, face, i);
  565. name[i] = ' ';
  566. memcpy(name + i + 1, style, j);
  567. name[i + j + 1] = 0;
  568. sfn_setstr(&ctx.name, name, 0);
  569. free(name);
  570. } else
  571. sfn_setstr(&ctx.name, ctx.familyname, 0);
  572. }
  573. if(!ctx.manufacturer && manu)
  574. sfn_setstr(&ctx.manufacturer, manu, 0);
  575. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", face, mg, b, b + relul, h);
  576. if(!b || !h || !mg || !mx || !bitmaps) return;
  577. if(mg > 65534) mg = 65534;
  578. ctx.baseline = b;
  579. ctx.underline = b + relul;
  580. ctx.height = h;
  581. /* parse bitmaps and add glyphs. Encoding table must be handled as optional */
  582. for(unicode = mn; (uint32_t)unicode <= mx; unicode++) {
  583. if(pbar) (*pbar)(0, 0, unicode, mx - mn + 1, PBAR_BITMAP);
  584. i = encodings ? pcf16(ef, encodings + unicode * 2) : unicode;
  585. if(i >= mg) continue;
  586. offs = pcf32(bf, boffs + i * 4); siz = (i >= mg - 1 ? bs : (uint32_t)pcf32(bf, boffs + i * 4 + 4)) - offs;
  587. if(mf & 0x100) {
  588. x = (int)ptr[metrics+6+i*5]-0x80; a = (int)ptr[metrics+3+6+i*5]-0x80;
  589. w = (int)ptr[metrics+2+6+i*5]-0x80; r = (int)ptr[metrics+1+6+i*5]-0x80;
  590. } else {
  591. x = (int16_t)pcf16(mf,metrics+8+i*12); a = pcf16(mf,metrics+6+8+i*12);
  592. w = pcf16(mf,metrics+4+8+i*12); r = pcf16(mf,metrics+2+8+i*12);
  593. }
  594. /* do some heuristics and validation because PCF fonts are *usually* buggy... */
  595. if(x < 0) { o = -x; x = 0; } else o = 0;
  596. if(w < r) r = w;
  597. if(p < 1) p = 1;
  598. n = (siz / p); y = b - a;
  599. if(n > (uint32_t)h) n = h;
  600. if(y < 0) y = 0;
  601. if(y + n > (uint32_t)h) y = h - n;
  602. k = n * r; if(k < 1 || k > 65536) continue;
  603. bitmap = realloc(bitmap, k);
  604. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  605. memset(bitmap, 0xFF, k);
  606. if(siz > n * p) siz = n * p;
  607. for(j = 0; siz; siz -= p, offs += p) {
  608. /* seriously, who have thought even for a moment that messing with both byte and bit endianess is sane? */
  609. bm = ptr + bitmaps + offs + (sx < 0 ? p - 1 : 0); m = bf & (1 << 3) ? 1 << 7 : 1;
  610. for(k = 0; k < r; k++) {
  611. bitmap[j++] = bm[0] & m ? 0xFE : 0xFF;
  612. if(bf & (1 << 3)) { m >>= 1; if(!m) { m = 1 << 7; bm += sx; } }
  613. else { m <<= 1; if(m > 0x80) { m = 1; bm += sx; } }
  614. }
  615. }
  616. if(unicode == defchar) {
  617. sfn_chardel(0);
  618. j = 0;
  619. } else j = unicode;
  620. if(sfn_charadd(j, w, h, x+r, 0, o))
  621. sfn_layeradd(j, SSFN_FRAG_BITMAP, x, y, r, n, 0xFE, bitmap);
  622. }
  623. if(bitmap) free(bitmap);
  624. }
  625. /**
  626. * Parse BMF font format (binary)
  627. */
  628. void bmf(unsigned char *ptr, int size)
  629. {
  630. bmf_t *bmf = (bmf_t*)ptr;
  631. uint8_t *end = ptr + size, pal[256];
  632. int i, n, unicode, numchars, w, h, a, x, y;
  633. if(!ctx.baseline) ctx.baseline = -bmf->sizeOver;
  634. if(ctx.height < bmf->lineHeight) ctx.height = bmf->lineHeight;
  635. memset(pal, 0, sizeof(pal)); pal[0] = 0xFF;
  636. ptr += sizeof(bmf_t);
  637. for(i = 0; i < (int)bmf->numColors; i++, ptr += 3)
  638. pal[i + 1] = sfn_cpaladd(ptr[0] << 2, ptr[1] << 2, ptr[2] << 2, 255);
  639. i = *ptr++; sfn_setstr(&ctx.name, (char*)ptr, i); ptr += i;
  640. numchars = (ptr[1] << 8) | ptr[0]; ptr += 2;
  641. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars,
  642. -bmf->sizeOver, -bmf->sizeOver, bmf->lineHeight);
  643. for(n = 0; n < numchars && ptr + 6 < end; n++) {
  644. if(pbar) (*pbar)(0, 0, n, numchars, PBAR_BITMAP);
  645. unicode = doscp[*ptr++]; w = *ptr++; h = *ptr++; x = (int8_t)*ptr++; y = (int8_t)*ptr++; a = bmf->addSpace + (int8_t)*ptr++;
  646. if(sfn_charadd(unicode, (x < 0 ? 0 : x) + w, (y < 0 ? 0 : y) + h, a, 0, (x < 0 ? -x : 0))) {
  647. for(i = 0; i < w * h && ptr + i < end; i++) ptr[i] = pal[ptr[i]];
  648. sfn_layeradd(unicode, SSFN_FRAG_PIXMAP, (x < 0 ? 0 : x), (y < 0 ? 0 : y), w, h, 0xFE, ptr);
  649. }
  650. ptr += w * h;
  651. }
  652. }
  653. /**
  654. * Parse YAFF font format (text)
  655. */
  656. void yaff(char *ptr, int size)
  657. {
  658. 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;
  659. char *end = ptr + size, *s = ptr, *e, *n, *v, hack = 0;
  660. unsigned char bitmap[65536];
  661. /* this is REALLY bad format which cannot be parsed reliably line by line... expect parsing errors! */
  662. while(s < end) {
  663. while(s < end && *s && (*s == '\r' || *s == '\n')) s++;
  664. if(!*s) break;
  665. for(e = s; e < end && *e && *e != '\r' && *e != '\n'; e++);
  666. for(v = s; v < e && *v != ':'; v++);
  667. if(v < e && *v == ':') {
  668. for(v++; v < e && *v && (*v == ' ' || *v == '\t'); v++);
  669. if(v >= e || *v == '\r' || *v == '\n') v = NULL;
  670. } else v = NULL;
  671. /* s: first character in line, e: end of line, v: first character of value */
  672. if(*s == ' ' || *s == '\t') {
  673. while(s < end && *s && (*s == ' ' || *s == '\t')) s++;
  674. if(!*s) break;
  675. if(unicode == -1 && c != -1) unicode = c;
  676. if(unicode == -1) { s = e; continue; }
  677. if(last != unicode) {
  678. /* add character */
  679. if(w > 0 && h > 0 && last != -1) {
  680. if(o < 0) w += o;
  681. if(w > 0) {
  682. for(i = 0; i < h; i++)
  683. memcpy(bitmap + i * w, bitmap + i * 256 - (o < 0 ? o : 0), w);
  684. if(sfn_charadd(last, w, h, x && !y ? x : w, !x && y ? y : 0, o < 0 ? 0 : o))
  685. sfn_layeradd(last, SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
  686. }
  687. numchars++;
  688. }
  689. w = h = o = x = y = 0; memset(bitmap, 0, sizeof(bitmap));
  690. last = unicode; hack = 0;
  691. }
  692. if(*s == '.' || *s == '@') {
  693. /* add a row */
  694. for(i = 0; i < 255 && s < e && (*s == '.' || *s == '@'); s++, i++)
  695. bitmap[h * 256 + i] = *s == '@' ? 0xFE : 0xFF;
  696. h++;
  697. if(i > w) w = i;
  698. if(w > W) W = w;
  699. if(h > H) H = h;
  700. /* ugly hack */
  701. hack = 0;
  702. } else
  703. if(!memcmp(s, "advance-width:", 14) && v) x = atoi(v); else
  704. if(!memcmp(s, "advance-height:", 15) && v) y = atoi(v); else
  705. if(!memcmp(s, "left-bearing:", 13) && v) { o = atoi(v); }
  706. } else {
  707. if(*s == '#' || *s == '\'' || *s == '\"') { s = e; continue; }
  708. /* codepoint */
  709. n = s; u = (int)ssfn_utf8(&n);
  710. if(*s >= '0' && *s <= '9') {
  711. if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) c = gethex(s + 2, 6);
  712. else c = atoi(s);
  713. if(!hack) unicode = c;
  714. } else
  715. if((s[0] == 'u' || s[0] == 'U') && s[1] == '+') { unicode = gethex(s + 2, 6); c = -1; hack = 1; } else
  716. if(*n == ':') { unicode = u; c = -1; } else
  717. if(!memcmp(s, "weight:", 7) && v && (*v == 'b' || *v == 'B')) ctx.style |= SSFN_STYLE_BOLD; else
  718. if(!memcmp(s, "slant:", 7) && v && (*v == 'i' || *v == 'I' || *v == 'o' || *v == 'O')) ctx.style |= SSFN_STYLE_ITALIC; else
  719. if(!memcmp(s, "name:", 5) && !ctx.name && v) sfn_setstr(&ctx.name, v, e - v); else
  720. if(!memcmp(s, "family:", 7) && !ctx.familyname && v) sfn_setstr(&ctx.familyname, v, e - v); else
  721. if(!memcmp(s, "subfamily:", 10) && !ctx.subname && v) sfn_setstr(&ctx.subname, v, e - v); else
  722. if(!memcmp(s, "revision:", 9) && !ctx.revision && v) sfn_setstr(&ctx.revision, v, e - v); else
  723. if(!memcmp(s, "foundry:", 8) && !ctx.manufacturer && v) sfn_setstr(&ctx.manufacturer, v, e - v); else
  724. if(!memcmp(s, "copyright:", 10) && !ctx.license && v) sfn_setstr(&ctx.license, v, e - v); else
  725. if(!memcmp(s, "line-height:", 12) && v) H = atoi(v); else
  726. if(!memcmp(s, "ascent:", 7) && !b && v) b = atoi(v); else
  727. if(!memcmp(s, "baseline:", 9) && v) b = atoi(v); else
  728. if(!memcmp(s, "shift-up:", 9) && b && v) { b -= atoi(v); if(b < 0) b = 0; } else
  729. if(!memcmp(s, "underline-descent:", 18) && v) relul = atoi(v);
  730. }
  731. s = e;
  732. }
  733. /* add the last character too */
  734. if(unicode == -1 && c != -1) unicode = c;
  735. if(w > 0 && h > 0 && unicode != -1) {
  736. if(o < 0) w += o;
  737. if(w > 0) {
  738. for(i = 0; i < h; i++)
  739. memcpy(bitmap + i * w, bitmap + i * 256 - (o < 0 ? o : 0), w);
  740. if(sfn_charadd(unicode, w, h, x && !y ? x : w, !x && y ? y : 0, o < 0 ? 0 : o))
  741. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
  742. }
  743. numchars++;
  744. }
  745. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, b, b + relul, H);
  746. if(b > ctx.baseline) ctx.baseline = b;
  747. ctx.underline = ctx.baseline + relul;
  748. if(ctx.underline < ctx.baseline) ctx.underline = ctx.baseline;
  749. if(W > ctx.width) ctx.width = W;
  750. if(H > ctx.height) ctx.height = H;
  751. ctx.family = SSFN_FAMILY_MONOSPACE;
  752. }
  753. /**
  754. * Parse name chunk
  755. */
  756. void kbits_name(char **strings)
  757. {
  758. /* unique font name */
  759. if(!ctx.name) {
  760. if(strings[4]) sfn_setstr(&ctx.name, strings[4], 0); else
  761. if(strings[3]) sfn_setstr(&ctx.name, strings[3], 0); else
  762. if(strings[6]) sfn_setstr(&ctx.name, strings[6], 0); else
  763. if(strings[20]) sfn_setstr(&ctx.name, strings[20], 0); else
  764. if(strings[18]) sfn_setstr(&ctx.name, strings[18], 0); else
  765. /* fallback */
  766. if(strings[16]) sfn_setstr(&ctx.name, strings[16], 0);
  767. }
  768. /* family name */
  769. if(!ctx.familyname) {
  770. if(strings[1]) sfn_setstr(&ctx.familyname, strings[1], 0); else
  771. if(strings[16]) sfn_setstr(&ctx.familyname, strings[16], 0);
  772. }
  773. /* subfamily name */
  774. if(!ctx.subname) {
  775. if(strings[2]) sfn_setstr(&ctx.subname, strings[2], 0); else
  776. if(strings[17]) sfn_setstr(&ctx.subname, strings[17], 0);
  777. }
  778. /* version / revision */
  779. if(!ctx.revision && strings[5]) sfn_setstr(&ctx.revision, strings[5], 0);
  780. /* manufacturer */
  781. if(!ctx.manufacturer) {
  782. if(strings[8]) sfn_setstr(&ctx.manufacturer, strings[8], 0); else
  783. if(strings[9]) sfn_setstr(&ctx.manufacturer, strings[9], 0);
  784. }
  785. /* copyright */
  786. if(!ctx.license) {
  787. if(strings[13]) sfn_setstr(&ctx.license, strings[13], 0); else
  788. if(strings[0]) sfn_setstr(&ctx.license, strings[0], 0); else
  789. if(strings[7]) sfn_setstr(&ctx.license, strings[7], 0);
  790. }
  791. }
  792. /**
  793. * Parse Bits'N'Picas font format (binary)
  794. */
  795. void kbits(unsigned char *ptr, int size)
  796. {
  797. uint8_t *end = ptr + size, *s, *save;
  798. unsigned char *bitmap = NULL;
  799. char *strings[32] = { 0 };
  800. int i, j, k, numchars = 0, a, x, y, w, h;
  801. ctx.height = ptr[0x17]; /* lineAscent */
  802. ctx.baseline = ctx.underline = 0;
  803. ptr += 0x24;
  804. while(ptr < end && (!memcmp(ptr, "name", 4) || !memcmp(ptr, "\0ame", 4))) {
  805. if(ptr[11] < 32) strings[(int)ptr[11]] = (char*)ptr + 14;
  806. ptr += 14 + ((ptr[12] << 8) | ptr[13]); *ptr = 0;
  807. }
  808. kbits_name(strings);
  809. save = ptr;
  810. while(ptr < end && (!memcmp(ptr, "char", 4) || !memcmp(ptr, "\0har", 4))) {
  811. if(ctx.baseline < ptr[0x17]) ctx.baseline = ptr[0x17];
  812. if(ctx.height < ptr[0x1b]) ctx.height = ptr[0x1b];
  813. for(i = ptr[0x1b], ptr += 0x1c; i > 0; i--, ptr += 4 + ptr[3]);
  814. numchars++;
  815. }
  816. if(ctx.underline < ctx.baseline) ctx.underline = ctx.baseline;
  817. ptr = save;
  818. while(ptr < end && (!memcmp(ptr, "char", 4) || !memcmp(ptr, "\0har", 4))) {
  819. s = ptr;
  820. x = (char)ptr[0x13]; y = ctx.baseline - (char)ptr[0x17]; h = ptr[0x1b];
  821. if(y < 0 || y > ctx.height || h < 1) y = 0;
  822. if(x < 0 || x >= 255) x = 0;
  823. for(w = 0, i = ptr[0x1b], ptr += 0x1c; i > 0; i--, ptr += 4 + ptr[3]) if(ptr[3] > w) w = ptr[3];
  824. if(x + w > ctx.width) ctx.width = x + w;
  825. if(y + h > ctx.height) ctx.height = y + h;
  826. }
  827. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, ctx.baseline,
  828. ctx.underline, ctx.height);
  829. ptr = save;
  830. while(ptr < end && (!memcmp(ptr, "char", 4) || !memcmp(ptr, "\0har", 4))) {
  831. s = ptr;
  832. a = ptr[0xf]; x = (char)ptr[0x13]; y = ctx.baseline - ptr[0x17]; h = ptr[0x1b];
  833. if(y < 0 || y > ctx.height || h < 1) y = 0;
  834. unicode = (ptr[8] << 24) | (ptr[9] << 16) | (ptr[10] << 8) | ptr[11];
  835. for(w = 0, i = s[0x1b], s += 0x1c; i > 0; i--, s += 4 + s[3]) if(s[3] > w) w = s[3];
  836. bitmap = realloc(bitmap, w * h + 1);
  837. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  838. memset(bitmap, 0xFF, w * h + 1);
  839. for(i = h, ptr += 0x1c, k = 0; i > 0; i--, ptr += 4 + ptr[3], k += w)
  840. for(j = 0; j < ptr[3]; j++) bitmap[k + j] = ptr[4 + j] > 127 ? 0xFE : 0xFF;
  841. if(y + h > ctx.height) h = ctx.height - y;
  842. if(sfn_charadd(unicode, (x < 0 ? 0 : x) + w, y + h, a, 0, (x < 0 ? -x : 0)))
  843. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, (x < 0 ? 0 : x), y, w, h, 0xFE, bitmap);
  844. }
  845. if(bitmap) free(bitmap);
  846. }
  847. /**
  848. * Parse Bits'N'Picas font format (text)
  849. */
  850. void kbitx(char *ptr, int size)
  851. {
  852. unsigned char *bitmap = NULL, *buf = NULL, *buf2;
  853. char *strings[32] = { 0 }, *s, *e, *save, *end = ptr + size;
  854. int i, j, l, numchars = 0, a, x, y, w, h;
  855. int repeatCount = 0, repeatData = -1, data;
  856. while(ptr < end && *ptr && memcmp(ptr, "<g ", 3) && memcmp(ptr, "</kbits", 7)) {
  857. if(!memcmp(ptr, "<name ", 6)) {
  858. for(i = -1, e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
  859. if(!memcmp(s, "id=\"", 4)) { s += 4; i = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  860. if(!memcmp(s, "value=\"", 7)) { s += 7; e = s; while(*s && *s != '\n' && *s != '\"') s++; }
  861. }
  862. if(i >= 0 && i < 32 && e) strings[i] = e;
  863. }
  864. while(*ptr && *ptr!='\n') ptr++;
  865. while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
  866. }
  867. ctx.height = ctx.baseline = ctx.underline = 0;
  868. kbits_name(strings);
  869. save = ptr;
  870. while(ptr < end && *ptr && !memcmp(ptr, "<g ", 3)) {
  871. y = 0;
  872. for(e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
  873. if(!memcmp(s, "y=\"", 3)) { s += 3; y = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; }
  874. }
  875. if(y > ctx.baseline) ctx.baseline = y;
  876. while(*ptr && *ptr!='\n') ptr++;
  877. while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
  878. numchars++;
  879. }
  880. if(ctx.underline < ctx.baseline) ctx.underline = ctx.baseline;
  881. ptr = save;
  882. while(ptr < end && *ptr && !memcmp(ptr, "<g ", 3)) {
  883. x = y = w = h = 0;
  884. for(e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
  885. if(!memcmp(s, "x=\"", 3)) { s += 3; x = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  886. if(!memcmp(s, "y=\"", 3)) { s += 3; y = ctx.baseline - atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  887. if(!memcmp(s, "d=\"", 3)) { s += 3; e = s; while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; }
  888. }
  889. if(y < 0 || y > ctx.height || h < 1) y = 0;
  890. if(x < 0 || x >= 255) x = 0;
  891. while(*ptr && *ptr!='\n') ptr++;
  892. while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
  893. if(e) {
  894. buf2 = buf = realloc(buf, ptr - e + 256);
  895. if(!buf2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  896. memset(buf, 0, ptr - e + 256);
  897. if(base64_decode(e, buf) > 2) {
  898. buf2 = getleb(buf2, (unsigned int*)&h);
  899. buf2 = getleb(buf2, (unsigned int*)&w);
  900. };
  901. };
  902. if(x + w > ctx.width) ctx.width = x + w;
  903. if(y + h > ctx.height) ctx.height = y + h;
  904. }
  905. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", ctx.name, numchars, ctx.baseline,
  906. ctx.underline, ctx.height);
  907. ptr = save;
  908. while(ptr < end && *ptr && !memcmp(ptr, "<g ", 3)) {
  909. a = x = y = w = h = 0;
  910. for(e = NULL, s = ptr; *s && *s != '\n' && *s != '>'; s++) {
  911. if(!memcmp(s, "u=\"", 3)) { s += 3; unicode = (uint32_t)atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  912. if(!memcmp(s, "x=\"", 3)) { s += 3; x = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  913. if(!memcmp(s, "y=\"", 3)) { s += 3; y = ctx.baseline - atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  914. /* this isn't width, this is actually advance x */
  915. if(!memcmp(s, "w=\"", 3)) { s += 3; a = atoi(s); while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; } else
  916. if(!memcmp(s, "d=\"", 3)) { s += 3; e = s; while(*s && *s != '>' && *s != '\n' && *s != '\"') s++; }
  917. }
  918. while(*ptr && *ptr!='\n') ptr++;
  919. while(*ptr=='\r' || *ptr=='\n' || *ptr == ' ') ptr++;
  920. if(e) {
  921. buf2 = buf = realloc(buf, ptr - e + 256);
  922. if(!buf2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  923. memset(buf, 0, ptr - e + 256);
  924. if((l = base64_decode(e, buf)) > 2) {
  925. buf2 = getleb(buf2, (unsigned int*)&h);
  926. buf2 = getleb(buf2, (unsigned int*)&w);
  927. bitmap = realloc(bitmap, w * h + 1);
  928. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  929. memset(bitmap, 0xFF, w * h + 1);
  930. for(j = repeatCount = 0, repeatData = -1; j < w * h && buf2 <= buf + l; ) {
  931. if(repeatCount > 0) {
  932. repeatCount--;
  933. if(repeatData == -1) {
  934. bitmap[j++] = buf2 == buf + l || *buf2++ > 127 ? 0xFE : 0xFF;
  935. continue;
  936. } else {
  937. bitmap[j++] = repeatData > 127 ? 0xFE : 0xFF;
  938. continue;
  939. }
  940. }
  941. if(buf2 == buf + l) { bitmap[j++] = 0xFE; break; }
  942. data = *buf2++;
  943. repeatCount = data & 0x1F;
  944. if((data & 0x20) != 0) repeatCount <<= 5;
  945. switch(data & 0xC0) {
  946. case 0x00: repeatData = 0x00; break;
  947. case 0x40: repeatData = 0xFF; break;
  948. case 0x80:
  949. if(buf2 == buf + l) { bitmap[j++] = 0xFE; buf2++; break; }
  950. repeatData = *buf2++;
  951. break;
  952. case 0xC0: repeatData = -1; break;
  953. }
  954. }
  955. } else x = w = 0;
  956. } else x = w = 0;
  957. if(sfn_charadd(unicode, (x < 0 ? 0 : x) + w, y + h, a, 0, (x < 0 ? -x : 0)))
  958. sfn_layeradd(unicode, SSFN_FRAG_BITMAP, (x < 0 ? 0 : x), y, w, h, 0xFE, bitmap);
  959. }
  960. if(bitmap) free(bitmap);
  961. if(buf) free(buf);
  962. }
  963. /**
  964. * Raw ROM image (binary)
  965. */
  966. void raw(unsigned char *ptr, int size, int h)
  967. {
  968. unsigned char *bitmap;
  969. int w = (size / h / 256) << 3, unicode, i, j, k, l, p, m;
  970. if(size < 2048 || !w) return;
  971. bitmap = (unsigned char*)malloc(w * h);
  972. if(!bitmap) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  973. printf("\r Name '%s' num_glyphs: %d, ascender: %d, underline: %d, height: %d\n", "", 256, h, h, h);
  974. m = (w >> 3) * h;
  975. for(unicode = 0; unicode < 256; unicode++) {
  976. for(k = l = 0; k < h; k++)
  977. for(p = unicode * m + (w >> 3) * k, j = 0x80, i = 0; i < w; i++, j >>= 1) {
  978. if(!j) { j = 0x80; p++; }
  979. bitmap[l++] = (ptr[p] & j) ? 0xFE : 0xFF;
  980. }
  981. if(sfn_charadd(doscp[unicode], w, h, w + 1, 0, 0))
  982. sfn_layeradd(doscp[unicode], SSFN_FRAG_BITMAP, 0, 0, w, h, 0xFE, bitmap);
  983. }
  984. free(bitmap);
  985. ctx.width = w;
  986. ctx.height = h;
  987. if(!ctx.baseline) ctx.baseline = ctx.underline = h;
  988. ctx.family = SSFN_FAMILY_MONOSPACE;
  989. }
  990. /**
  991. * Parse a pixel map in memory
  992. */
  993. void pixmap_parse(unsigned char *data, int w, int h)
  994. {
  995. unsigned char *data2, l = 0xFE;
  996. unsigned int i, j, k, x, y, m, o, pw = 0, ph = 0, X, Y;
  997. int unicode, s;
  998. if(rs==0 && re==0x10FFFF) {
  999. /* try to detect square images with 16 x 16 glyphs. Use -X and -Y explicitly on command line to override */
  1000. if(!px && !py && w >= 128 && h >= 128 && (w == h || w * 2 == h)) { pw = w / 16; ph = h / 16; re = 255; }
  1001. if(px > 0 && py > 0) { pw = px; ph = py; }
  1002. /* if we have exact glyph dimensions */
  1003. if(pw >= 8 && ph >= 8) {
  1004. data2 = (unsigned char*)malloc(pw*ph);
  1005. if(!data2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  1006. for(unicode = rs, Y = 0; Y < (unsigned int)h; Y += ph)
  1007. for(X = 0; unicode <= re && X < (unsigned int)w; X += pw, unicode++) {
  1008. for(y=o=k=0,s=-1,l=0xFE;y<ph;y++) {
  1009. i = (Y+y)*w + X;
  1010. for(x=0;x<pw;x++) {
  1011. if(data[i] < 0xFF){
  1012. if(k < x) k = x;
  1013. if(s == -1) { l = data[i]; s = 1; }
  1014. if(s && data[i] != l) s = 0;
  1015. }
  1016. data2[o++] = data[i++];
  1017. }
  1018. }
  1019. if(s) for(i=0;i<pw*ph;i++)if(data2[i] != 0xFF) data2[i] = 0xFE;
  1020. if(sfn_charadd(unicode, pw, ph, k+1, 0, 0))
  1021. sfn_layeradd(unicode, s ? SSFN_FRAG_BITMAP : SSFN_FRAG_PIXMAP, 0, 0, pw, ph, l, data2);
  1022. if(pbar) (*pbar)(0, 0, unicode, re - rs, PBAR_SQRPIX);
  1023. }
  1024. free(data2);
  1025. return;
  1026. } else
  1027. re = h > w ? h / w : w / h;
  1028. }
  1029. if(h > w) {
  1030. m = h / (re - rs + 1);
  1031. if(m < 8 || w < 8) { fprintf(stderr, "libsfn: unable to determine glyph size\n"); return; }
  1032. for(unicode=rs, i=0; unicode<=re; unicode++, i += w*m) {
  1033. for(y=k=0,s=-1,l=0xFE;y<m;y++)
  1034. for(j=w-1;j>k;j--)
  1035. if(data[i+y*w+j] < 0xFF) k=j;
  1036. if(sfn_charadd(unicode, w, m, k+1, 0, 0))
  1037. sfn_layeradd(unicode, SSFN_FRAG_PIXMAP, 0, 0, w, m, 0xFE, data + i);
  1038. if(pbar) (*pbar)(0, 0, unicode, re - rs, PBAR_TALLPIX);
  1039. }
  1040. } else {
  1041. m = w / (re - rs + 1);
  1042. if(m < 8 || h < 8) { fprintf(stderr, "libsfn: unable to determine glyph size\n"); return; }
  1043. data2 = (unsigned char*)malloc(m*h);
  1044. if(!data2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  1045. for(unicode=rs; unicode<=re; unicode++) {
  1046. for(y=o=k=0;y<(unsigned int)h;y++) {
  1047. i = y*w + (unicode-rs)*m;
  1048. for(x=0;x<m;x++) {
  1049. if(data[i] < 0xFF && k < x) k = x;
  1050. data2[o++] = data[i++];
  1051. }
  1052. }
  1053. if(sfn_charadd(unicode, m, h, k+1, 0, 0))
  1054. sfn_layeradd(unicode, SSFN_FRAG_PIXMAP, 0, 0, m, h, 0xFE, data2);
  1055. if(pbar) (*pbar)(0, 0, unicode, re - rs, PBAR_WIDEPIX);
  1056. }
  1057. free(data2);
  1058. }
  1059. }
  1060. /**
  1061. * Parse PNG format for pixel fonts (binary)
  1062. */
  1063. void png(unsigned char *ptr, int size)
  1064. {
  1065. unsigned char *data, *data2;
  1066. unsigned int i, w, h, f;
  1067. stbi__context s;
  1068. stbi__result_info ri;
  1069. #ifdef HAS_QUANT
  1070. liq_attr *handle = NULL;
  1071. liq_image *input_image = NULL;
  1072. liq_result *quantization_result;
  1073. const liq_palette *liqpalette;
  1074. unsigned char pal[256];
  1075. #endif
  1076. s.read_from_callbacks = 0;
  1077. s.img_buffer = s.img_buffer_original = ptr;
  1078. s.img_buffer_end = s.img_buffer_original_end = ptr+size;
  1079. w = h = size = 0;
  1080. ri.bits_per_channel = 8;
  1081. data = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&f, 0, &ri);
  1082. if(!data || (f != STBI_rgb_alpha && f != STBI_rgb) || w < 1 || h < 1)
  1083. { fprintf(stderr,"libsfn: unsupported PNG format\n"); return; }
  1084. data2 = (unsigned char*)malloc(w * h);
  1085. if(!data2) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  1086. #ifdef HAS_QUANT
  1087. handle = liq_attr_create();
  1088. liq_set_max_colors(handle, 254);
  1089. if(f == STBI_rgb_alpha)
  1090. input_image = liq_image_create_rgba(handle, data, w, h, 0);
  1091. if(pbar) (*pbar)(0, 0, 0, 1, PBAR_QUANT);
  1092. if (f == STBI_rgb_alpha && liq_image_quantize(input_image, handle, &quantization_result) == LIQ_OK) {
  1093. liq_set_dithering_level(quantization_result, 1.0);
  1094. liqpalette = liq_get_palette(quantization_result);
  1095. liq_write_remapped_image(quantization_result, input_image, data, w * h);
  1096. for(i = 0; i < liqpalette->count && i < 254; i++) {
  1097. pal[i] = sfn_cpaladd(liqpalette->entries[i].r, liqpalette->entries[i].g,
  1098. liqpalette->entries[i].b, liqpalette->entries[i].a);
  1099. }
  1100. for(i = 0; i < w * h; i++)
  1101. data2[i] = pal[data[i]];
  1102. liq_result_destroy(quantization_result);
  1103. } else
  1104. #endif
  1105. {
  1106. if(f == STBI_rgb_alpha)
  1107. for(i = 0; i < w * h; i++) {
  1108. if(pbar) (*pbar)(0, 0, i, w * h, PBAR_QUANT);
  1109. data2[i] = sfn_cpaladd(data[i*4], data[i*4+1], data[i*4+2], data[i*4+3]);
  1110. }
  1111. else
  1112. for(i = 0; i < w * h; i++) {
  1113. if(pbar) (*pbar)(0, 0, i, w * h, PBAR_QUANT);
  1114. data2[i] = sfn_cpaladd(data[i*3], data[i*3+1], data[i*3+2], 255);
  1115. }
  1116. }
  1117. #ifdef HAS_QUANT
  1118. if(input_image) liq_image_destroy(input_image);
  1119. liq_attr_destroy(handle);
  1120. #endif
  1121. free(data);
  1122. pixmap_parse(data2, w, h);
  1123. free(data2);
  1124. }
  1125. /**
  1126. * Parse TGA format for pixel fonts (binary)
  1127. */
  1128. void tga(unsigned char *ptr, int size)
  1129. {
  1130. unsigned char *data;
  1131. int i, j, k, x, y, w, h, o, m;
  1132. o = (ptr[11] << 8) + ptr[10];
  1133. w = (ptr[13] << 8) + ptr[12];
  1134. h = (ptr[15] << 8) + ptr[14];
  1135. if(w<1 || h<1) {
  1136. tgaerr: fprintf(stderr,"libsfn: unsupported TGA file format\n");
  1137. return;
  1138. }
  1139. m = ((ptr[1]? (ptr[7]>>3)*ptr[5] : 0) + 18);
  1140. data = (unsigned char*)malloc(w*h);
  1141. if(!data) { fprintf(stderr,"libsfn: memory allocation error\n"); return; }
  1142. switch(ptr[2]) {
  1143. case 1:
  1144. if(ptr[6]!=0 || ptr[4]!=0 || ptr[3]!=0 || (ptr[7]!=24 && ptr[7]!=32)) goto tgaerr;
  1145. for(y=i=0; y<h; y++) {
  1146. k = ((!o?h-y-1:y)*w);
  1147. for(x=0; x<w; x++) {
  1148. j = ptr[m + k++]*(ptr[7]>>3) + 18;
  1149. data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[7]==32?ptr[j+3]:0xFF);
  1150. }
  1151. }
  1152. break;
  1153. case 2:
  1154. if(ptr[5]!=0 || ptr[6]!=0 || ptr[1]!=0 || (ptr[16]!=24 && ptr[16]!=32)) goto tgaerr;
  1155. for(y=i=0; y<h; y++) {
  1156. j = m+((!o?h-y-1:y)*w*(ptr[16]>>3));
  1157. for(x=0; x<w; x++) {
  1158. data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[16]==32?ptr[j+3]:0xFF);
  1159. j += ptr[16]>>3;
  1160. }
  1161. }
  1162. break;
  1163. case 9:
  1164. if(ptr[6]!=0 || ptr[4]!=0 || ptr[3]!=0 || (ptr[7]!=24 && ptr[7]!=32)) goto tgaerr;
  1165. y = i = 0;
  1166. for(x=0; x<w*h && m<size;) {
  1167. k = ptr[m++];
  1168. if(k > 127) {
  1169. k -= 127; x += k;
  1170. j = ptr[m++]*(ptr[7]>>3) + 18;
  1171. while(k--) {
  1172. if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
  1173. data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[7]==32?ptr[j+3]:0xFF);
  1174. }
  1175. } else {
  1176. k++; x += k;
  1177. while(k--) {
  1178. j = ptr[m++]*(ptr[7]>>3) + 18;
  1179. if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
  1180. data[i++] = sfn_cpaladd(ptr[j+2], ptr[j+1], ptr[j], ptr[7]==32?ptr[j+3]:0xFF);
  1181. }
  1182. }
  1183. }
  1184. break;
  1185. case 10:
  1186. if(ptr[5]!=0 || ptr[6]!=0 || ptr[1]!=0 || (ptr[16]!=24 && ptr[16]!=32)) goto tgaerr;
  1187. y = i = 0;
  1188. for(x=0; x<w*h && m<size;) {
  1189. k = ptr[m++];
  1190. if(k > 127) {
  1191. k -= 127; x += k;
  1192. while(k--) {
  1193. if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
  1194. data[i++] = sfn_cpaladd(ptr[m+2], ptr[m+1], ptr[m], ptr[16]==32?ptr[m+3]:0xFF);
  1195. }
  1196. m += ptr[16]>>3;
  1197. } else {
  1198. k++; x += k;
  1199. while(k--) {
  1200. if(!(i%w)) { i=((!o?h-y-1:y)*w); y++; }
  1201. data[i++] = sfn_cpaladd(ptr[m+2], ptr[m+1], ptr[m], ptr[16]==32?ptr[m+3]:0xFF);
  1202. m += ptr[16]>>3;
  1203. }
  1204. }
  1205. }
  1206. break;
  1207. }
  1208. pixmap_parse(data, w, h);
  1209. free(data);
  1210. }
  1211. #endif