ssfn.h 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  1. /*
  2. * ssfn.h
  3. * https://gitlab.com/bztsrc/scalable-font2
  4. *
  5. * Copyright (C) 2020 - 2022 bzt
  6. *
  7. * Permission is hereby granted, free of charge, to any person
  8. * obtaining a copy of this software and associated documentation
  9. * files (the "Software"), to deal in the Software without
  10. * restriction, including without limitation the rights to use, copy,
  11. * modify, merge, publish, distribute, sublicense, and/or sell copies
  12. * of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  22. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  23. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. *
  27. * @brief Scalable Screen Font renderers
  28. *
  29. */
  30. #ifndef _SSFN_H_
  31. #define _SSFN_H_
  32. #define SSFN_VERSION 0x0200
  33. #ifdef __cplusplus
  34. extern "C" {
  35. # ifndef __THROW
  36. # define __THROW throw()
  37. # endif
  38. #else
  39. # ifndef __THROW
  40. # define __THROW
  41. # endif
  42. #endif
  43. /* if stdint.h was not included before us */
  44. #ifndef _STDINT_H
  45. typedef unsigned char uint8_t;
  46. typedef unsigned short int uint16_t;
  47. typedef short int int16_t;
  48. typedef unsigned int uint32_t;
  49. #ifndef _UINT64_T
  50. typedef unsigned long int uint64_t;
  51. #endif
  52. #endif
  53. /***** file format *****/
  54. /* magic bytes */
  55. #define SSFN_MAGIC "SFN2"
  56. #define SSFN_COLLECTION "SFNC"
  57. #define SSFN_ENDMAGIC "2NFS"
  58. /* ligatures area */
  59. #define SSFN_LIG_FIRST 0xF000
  60. #define SSFN_LIG_LAST 0xF8FF
  61. /* font family group in font type byte */
  62. #define SSFN_TYPE_FAMILY(x) ((x)&15)
  63. #define SSFN_FAMILY_SERIF 0
  64. #define SSFN_FAMILY_SANS 1
  65. #define SSFN_FAMILY_DECOR 2
  66. #define SSFN_FAMILY_MONOSPACE 3
  67. #define SSFN_FAMILY_HAND 4
  68. /* font style flags in font type byte */
  69. #define SSFN_TYPE_STYLE(x) (((x)>>4)&15)
  70. #define SSFN_STYLE_REGULAR 0
  71. #define SSFN_STYLE_BOLD 1
  72. #define SSFN_STYLE_ITALIC 2
  73. #define SSFN_STYLE_USRDEF1 4 /* user defined variant 1 */
  74. #define SSFN_STYLE_USRDEF2 8 /* user defined variant 2 */
  75. /* contour commands */
  76. #define SSFN_CONTOUR_MOVE 0
  77. #define SSFN_CONTOUR_LINE 1
  78. #define SSFN_CONTOUR_QUAD 2
  79. #define SSFN_CONTOUR_CUBIC 3
  80. /* glyph fragments, kerning groups and hinting grid info */
  81. #define SSFN_FRAG_CONTOUR 0
  82. #define SSFN_FRAG_BITMAP 1
  83. #define SSFN_FRAG_PIXMAP 2
  84. #define SSFN_FRAG_KERNING 3
  85. #define SSFN_FRAG_HINTING 4
  86. /* main SSFN header, 32 bytes */
  87. #ifndef _MSC_VER
  88. #define _pack __attribute__((packed))
  89. #else
  90. #define _pack
  91. #pragma pack(push)
  92. #pragma pack(1)
  93. #endif
  94. typedef struct {
  95. uint8_t magic[4]; /* SSFN magic bytes */
  96. uint32_t size; /* total size in bytes */
  97. uint8_t type; /* font family and style */
  98. uint8_t features; /* format features and revision */
  99. uint8_t width; /* overall width of the font */
  100. uint8_t height; /* overall height of the font */
  101. uint8_t baseline; /* horizontal baseline in grid pixels */
  102. uint8_t underline; /* position of under line in grid pixels */
  103. uint16_t fragments_offs; /* offset of fragments table */
  104. uint32_t characters_offs; /* characters table offset */
  105. uint32_t ligature_offs; /* ligatures table offset */
  106. uint32_t kerning_offs; /* kerning table offset */
  107. uint32_t cmap_offs; /* color map offset */
  108. } _pack ssfn_font_t;
  109. #ifdef _MSC_VER
  110. #pragma pack(pop)
  111. #endif
  112. /***** renderer API *****/
  113. #define SSFN_FAMILY_ANY 0xff /* select the first loaded font */
  114. #define SSFN_FAMILY_BYNAME 0xfe /* select font by its unique name */
  115. /* additional styles not stored in fonts */
  116. #define SSFN_STYLE_UNDERLINE 16 /* under line glyph */
  117. #define SSFN_STYLE_STHROUGH 32 /* strike through glyph */
  118. #define SSFN_STYLE_NOAA 64 /* no anti-aliasing */
  119. #define SSFN_STYLE_NOKERN 128 /* no kerning */
  120. #define SSFN_STYLE_NODEFGLYPH 256 /* don't draw default glyph */
  121. #define SSFN_STYLE_NOCACHE 512 /* don't cache rasterized glyph */
  122. #define SSFN_STYLE_NOHINTING 1024 /* no auto hinting grid (not used as of now) */
  123. #define SSFN_STYLE_RTL 2048 /* render right-to-left */
  124. #define SSFN_STYLE_ABS_SIZE 4096 /* scale absoulte height */
  125. #define SSFN_STYLE_NOSMOOTH 8192 /* no edge-smoothing for bitmaps */
  126. /* error codes */
  127. #define SSFN_OK 0 /* success */
  128. #define SSFN_ERR_ALLOC -1 /* allocation error */
  129. #define SSFN_ERR_BADFILE -2 /* bad SSFN file format */
  130. #define SSFN_ERR_NOFACE -3 /* no font face selected */
  131. #define SSFN_ERR_INVINP -4 /* invalid input */
  132. #define SSFN_ERR_BADSTYLE -5 /* bad style */
  133. #define SSFN_ERR_BADSIZE -6 /* bad size */
  134. #define SSFN_ERR_NOGLYPH -7 /* glyph (or kerning info) not found */
  135. #define SSFN_SIZE_MAX 192 /* biggest size we can render */
  136. #define SSFN_ITALIC_DIV 4 /* italic angle divisor, glyph top side pushed width / this pixels */
  137. #define SSFN_PREC 4 /* precision in bits */
  138. /* destination frame buffer context */
  139. typedef struct {
  140. uint8_t *ptr; /* pointer to the buffer */
  141. int w; /* width (positive: ARGB, negative: ABGR pixels) */
  142. int h; /* height */
  143. uint16_t p; /* pitch, bytes per line */
  144. int x; /* cursor x */
  145. int y; /* cursor y */
  146. uint32_t fg; /* foreground color */
  147. uint32_t bg; /* background color */
  148. } ssfn_buf_t;
  149. /* cached bitmap struct */
  150. #define SSFN_DATA_MAX 65536
  151. typedef struct {
  152. uint16_t p; /* data buffer pitch, bytes per line */
  153. uint8_t h; /* data buffer height */
  154. uint8_t o; /* overlap of glyph, scaled to size */
  155. uint8_t x; /* advance x, scaled to size */
  156. uint8_t y; /* advance y, scaled to size */
  157. uint8_t a; /* ascender, scaled to size */
  158. uint8_t d; /* descender, scaled to size */
  159. uint8_t data[SSFN_DATA_MAX]; /* data buffer */
  160. } ssfn_glyph_t;
  161. /* character metrics */
  162. typedef struct {
  163. uint8_t t; /* type and overlap */
  164. uint8_t n; /* number of fragments */
  165. uint8_t w; /* width */
  166. uint8_t h; /* height */
  167. uint8_t x; /* advance x */
  168. uint8_t y; /* advance y */
  169. } ssfn_chr_t;
  170. #ifdef SSFN_PROFILING
  171. #include <string.h>
  172. #include <sys/time.h>
  173. #endif
  174. /* renderer context */
  175. typedef struct {
  176. #ifdef SSFN_MAXLINES
  177. const ssfn_font_t *fnt[5][16]; /* static font registry */
  178. #else
  179. const ssfn_font_t **fnt[5]; /* dynamic font registry */
  180. #endif
  181. const ssfn_font_t *s; /* explicitly selected font */
  182. const ssfn_font_t *f; /* font selected by best match */
  183. ssfn_glyph_t ga; /* glyph sketch area */
  184. ssfn_glyph_t *g; /* current glyph pointer */
  185. #ifdef SSFN_MAXLINES
  186. uint16_t p[SSFN_MAXLINES*2];
  187. #else
  188. ssfn_glyph_t ***c[17]; /* glyph cache */
  189. uint16_t *p;
  190. char **bufs; /* allocated extra buffers */
  191. #endif
  192. ssfn_chr_t *rc; /* pointer to current character */
  193. int numbuf, lenbuf, np, ap, ox, oy, ax;
  194. int mx, my, lx, ly; /* move to coordinates, last coordinates */
  195. int len[5]; /* number of fonts in registry */
  196. int family; /* required family */
  197. int style; /* required style */
  198. int size; /* required size */
  199. int line; /* calculate line height */
  200. #ifdef SSFN_PROFILING
  201. uint64_t lookup, raster, blit, kern;/* profiling accumulators */
  202. #endif
  203. } ssfn_t;
  204. /***** API function protoypes *****/
  205. uint32_t ssfn_utf8(char **str); /* decode UTF-8 sequence */
  206. /* normal renderer */
  207. int ssfn_load(ssfn_t *ctx, const void *data); /* add an SSFN to context */
  208. int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size); /* select font to use */
  209. int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str); /* render a glyph to a pixel buffer */
  210. int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top); /* get bounding box */
  211. ssfn_buf_t *ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg); /* renders text to a newly allocated buffer */
  212. int ssfn_mem(ssfn_t *ctx); /* return how much memory is used */
  213. void ssfn_free(ssfn_t *ctx); /* free context */
  214. #define ssfn_error(err) (err<0&&err>=-7?ssfn_errstr[-err]:"Unknown error") /* return string for error code */
  215. extern const char *ssfn_errstr[];
  216. /* simple renderer */
  217. extern ssfn_font_t *ssfn_src; /* font buffer */
  218. extern ssfn_buf_t ssfn_dst; /* destination frame buffer */
  219. int ssfn_putc(uint32_t unicode); /* render console bitmap font */
  220. /***** renderer implementations *****/
  221. /*** these go for both renderers ***/
  222. #if (defined(SSFN_IMPLEMENTATION) || defined(SSFN_CONSOLEBITMAP_PALETTE) || \
  223. defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)) && !defined(SSFN_COMMON)
  224. #define SSFN_COMMON
  225. /**
  226. * Error code strings
  227. */
  228. const char *ssfn_errstr[] = { "",
  229. "Memory allocation error",
  230. "Bad file format",
  231. "No font face found",
  232. "Invalid input value",
  233. "Invalid style",
  234. "Invalid size",
  235. "Glyph not found"
  236. };
  237. /**
  238. * Decode an UTF-8 multibyte, advance string pointer and return UNICODE. Watch out, no input checks
  239. *
  240. * @param **s pointer to an UTF-8 string pointer
  241. * @return unicode, and *s moved to next multibyte sequence
  242. */
  243. uint32_t ssfn_utf8(char **s)
  244. {
  245. uint32_t c = **s;
  246. if((**s & 128) != 0) {
  247. if(!(**s & 32)) { c = ((**s & 0x1F)<<6)|(*(*s+1) & 0x3F); *s += 1; } else
  248. if(!(**s & 16)) { c = ((**s & 0xF)<<12)|((*(*s+1) & 0x3F)<<6)|(*(*s+2) & 0x3F); *s += 2; } else
  249. if(!(**s & 8)) { c = ((**s & 0x7)<<18)|((*(*s+1) & 0x3F)<<12)|((*(*s+2) & 0x3F)<<6)|(*(*s+3) & 0x3F); *s += 3; }
  250. else c = 0;
  251. }
  252. (*s)++;
  253. return c;
  254. }
  255. #endif
  256. #ifdef SSFN_IMPLEMENTATION
  257. /*** normal renderer (ca. 28k, fully featured with error checking) ***/
  258. # ifndef NULL
  259. # define NULL (void*)0
  260. # endif
  261. # ifndef size_t
  262. typedef __SIZE_TYPE__ size_t;
  263. # endif
  264. # ifndef inline
  265. # define inline __inline__
  266. # endif
  267. #ifndef _STRING_H_
  268. extern int memcmp (const void *__s1, const void *__s2, size_t __n) __THROW;
  269. extern void *memset (void *__s, int __c, size_t __n) __THROW;
  270. #endif
  271. /* Clang does not have built-ins */
  272. # ifndef SSFN_memcmp
  273. # ifdef __builtin_memcmp
  274. # define SSFN_memcmp __builtin_memcmp
  275. # else
  276. # ifndef SSFN_MAXLINES
  277. # define SSFN_memcmp memcmp
  278. # else
  279. static int SSFN_memcmp(const void *__s1, const void *__s2, size_t __n)
  280. { unsigned char *a = (unsigned char *)__s1, *b = (unsigned char *)__s2;
  281. if(__n > 0) { while(__n-- > 0) { if(*a != *b) { return *a - *b; } a++; b++; } } return 0; }
  282. # endif
  283. # endif
  284. # endif
  285. # ifndef SSFN_memset
  286. # ifdef __builtin_memset
  287. # define SSFN_memset __builtin_memset
  288. # else
  289. # ifndef SSFN_MAXLINES
  290. # define SSFN_memset memset
  291. # else
  292. static void *SSFN_memset(void *__s, int __c, size_t __n)
  293. { unsigned char *a = __s; if(__n > 0) { while(__n-- > 0) *a++ = __c; } return __s; }
  294. # endif
  295. # endif
  296. # endif
  297. # ifndef SSFN_MAXLINES
  298. # ifndef SSFN_realloc
  299. # ifdef __builtin_realloc
  300. # define SSFN_realloc __builtin_realloc
  301. # else
  302. # define SSFN_realloc realloc
  303. extern void *realloc (void *__ptr, size_t __size) __THROW;
  304. # endif
  305. # endif
  306. # ifndef SSFN_free
  307. # ifdef __builtin_free
  308. # define SSFN_free __builtin_free
  309. # else
  310. # define SSFN_free free
  311. extern void free (void *p) __THROW;
  312. # endif
  313. # endif
  314. # endif /* if !SSFN_MAXLINES */
  315. /*** Private functions ***/
  316. /* parse character table */
  317. static uint8_t *_ssfn_c(const ssfn_font_t *font, const char *str, int *len, uint32_t *unicode)
  318. {
  319. uint32_t i, j, u = -1U;
  320. uint16_t *l;
  321. uint8_t *ptr, *s;
  322. *len = 0; *unicode = 0;
  323. if(!font || !font->characters_offs || !str || !*str) return NULL;
  324. if(font->ligature_offs) {
  325. for(l = (uint16_t*)((uint8_t*)font + font->ligature_offs), i = 0; l[i] && u == -1U; i++) {
  326. for(ptr = (uint8_t*)font + l[i], s = (uint8_t*)str; *ptr && *ptr == *s; ptr++, s++);
  327. if(!*ptr) { u = SSFN_LIG_FIRST + i; break; }
  328. }
  329. }
  330. if(u == -1U) {
  331. /* inline ssfn_utf8 to workaround -O2 bug in gcc 11.1 */
  332. s = (uint8_t*)str; u = *s;
  333. if((*s & 128) != 0) {
  334. if(!(*s & 32)) { u = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); s++; } else
  335. if(!(*s & 16)) { u = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); s += 2; } else
  336. if(!(*s & 8)) { u = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); s += 3; }
  337. else u = 0;
  338. }
  339. s++;
  340. }
  341. *len = (int)(s - (uint8_t*)str);
  342. *unicode = u;
  343. for(ptr = (uint8_t*)font + font->characters_offs, i = 0; i < 0x110000; i++) {
  344. if(ptr[0] == 0xFF) { i += 65535; ptr++; }
  345. else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; }
  346. else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; }
  347. else {
  348. if(i == u) return ptr;
  349. ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5);
  350. }
  351. }
  352. return NULL;
  353. }
  354. /* add a line to contour */
  355. static void _ssfn_l(ssfn_t *ctx, int p, int h, int x, int y)
  356. {
  357. if(x < 0 || y < 0 || x >= p || y >= h || (
  358. ((ctx->lx + (1 << (SSFN_PREC-1))) >> SSFN_PREC) == ((x + (1 << (SSFN_PREC-1))) >> SSFN_PREC) &&
  359. ((ctx->ly + (1 << (SSFN_PREC-1))) >> SSFN_PREC) == ((y + (1 << (SSFN_PREC-1))) >> SSFN_PREC))) return;
  360. #ifdef SSFN_MAXLINES
  361. if(ctx->np >= SSFN_MAXLINES*2-2) return;
  362. #else
  363. if(ctx->ap <= ctx->np) {
  364. ctx->ap = ctx->np + 512;
  365. ctx->p = (uint16_t*)SSFN_realloc(ctx->p, ctx->ap * sizeof(uint16_t));
  366. if(!ctx->p) { ctx->ap = ctx->np = 0; return; }
  367. }
  368. #endif
  369. if(!ctx->np) {
  370. ctx->p[0] = ctx->mx;
  371. ctx->p[1] = ctx->my;
  372. ctx->np += 2;
  373. }
  374. ctx->p[ctx->np+0] = x;
  375. ctx->p[ctx->np+1] = y;
  376. ctx->np += 2;
  377. ctx->lx = x; ctx->ly = y;
  378. }
  379. /* add a Bezier curve to contour */
  380. static void _ssfn_b(ssfn_t *ctx, int p,int h, int x0,int y0, int x1,int y1, int x2,int y2, int x3,int y3, int l)
  381. {
  382. int m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y,m5x, m5y;
  383. if(l<4 && (x0!=x3 || y0!=y3)) {
  384. m0x = ((x1-x0)/2) + x0; m0y = ((y1-y0)/2) + y0;
  385. m1x = ((x2-x1)/2) + x1; m1y = ((y2-y1)/2) + y1;
  386. m2x = ((x3-x2)/2) + x2; m2y = ((y3-y2)/2) + y2;
  387. m3x = ((m1x-m0x)/2) + m0x; m3y = ((m1y-m0y)/2) + m0y;
  388. m4x = ((m2x-m1x)/2) + m1x; m4y = ((m2y-m1y)/2) + m1y;
  389. m5x = ((m4x-m3x)/2) + m3x; m5y = ((m4y-m3y)/2) + m3y;
  390. _ssfn_b(ctx, p,h, x0,y0, m0x,m0y, m3x,m3y, m5x,m5y, l+1);
  391. _ssfn_b(ctx, p,h, m5x,m5y, m4x,m4y, m2x,m2y, x3,y3, l+1);
  392. }
  393. if(l) _ssfn_l(ctx, p,h, x3, y3);
  394. }
  395. #ifndef SSFN_MAXLINES
  396. static void _ssfn_fc(ssfn_t *ctx)
  397. {
  398. int i, j, k;
  399. if(!ctx) return;
  400. for(k = 0; k <= 16; k++)
  401. if(ctx->c[k]) {
  402. for(j = 0; j < 256; j++)
  403. if(ctx->c[k][j]) {
  404. for(i = 0; i < 256; i++)
  405. if(ctx->c[k][j][i]) SSFN_free(ctx->c[k][j][i]);
  406. SSFN_free(ctx->c[k][j]);
  407. }
  408. SSFN_free(ctx->c[k]);
  409. ctx->c[k] = NULL;
  410. }
  411. }
  412. /*
  413. * gzip deflate uncompressor from stb_image.h with minor modifications to reduce dependency
  414. * stb_image - v2.23 - public domain image loader - http://nothings.org/stb_image.h
  415. */
  416. #define SSFN__ZFAST_BITS 9
  417. #define SSFN__ZFAST_MASK ((1 << SSFN__ZFAST_BITS) - 1)
  418. typedef struct
  419. {
  420. uint16_t fast[1 << SSFN__ZFAST_BITS];
  421. uint16_t firstcode[16];
  422. int maxcode[17];
  423. uint16_t firstsymbol[16];
  424. unsigned char size[288];
  425. uint16_t value[288];
  426. } _ssfn__zhuffman;
  427. inline static int _ssfn__bitreverse16(int n)
  428. {
  429. n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
  430. n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
  431. n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
  432. n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
  433. return n;
  434. }
  435. inline static int _ssfn__bit_reverse(int v, int bits)
  436. {
  437. return _ssfn__bitreverse16(v) >> (16-bits);
  438. }
  439. static int _ssfn__zbuild_huffman(_ssfn__zhuffman *z, unsigned char *sizelist, int num)
  440. {
  441. int i,k=0;
  442. int code, next_code[16], sizes[17];
  443. SSFN_memset(sizes, 0, sizeof(sizes));
  444. SSFN_memset(z->fast, 0, sizeof(z->fast));
  445. for (i=0; i < num; ++i)
  446. ++sizes[sizelist[i]];
  447. sizes[0] = 0;
  448. for (i=1; i < 16; ++i)
  449. if (sizes[i] > (1 << i))
  450. return 0;
  451. code = 0;
  452. for (i=1; i < 16; ++i) {
  453. next_code[i] = code;
  454. z->firstcode[i] = (uint16_t) code;
  455. z->firstsymbol[i] = (uint16_t) k;
  456. code = (code + sizes[i]);
  457. if (sizes[i])
  458. if (code-1 >= (1 << i)) return 0;
  459. z->maxcode[i] = code << (16-i);
  460. code <<= 1;
  461. k += sizes[i];
  462. }
  463. z->maxcode[16] = 0x10000;
  464. for (i=0; i < num; ++i) {
  465. int s = sizelist[i];
  466. if (s) {
  467. int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
  468. uint16_t fastv = (uint16_t) ((s << 9) | i);
  469. z->size [c] = (unsigned char) s;
  470. z->value[c] = (uint16_t) i;
  471. if (s <= SSFN__ZFAST_BITS) {
  472. int j = _ssfn__bit_reverse(next_code[s],s);
  473. while (j < (1 << SSFN__ZFAST_BITS)) {
  474. z->fast[j] = fastv;
  475. j += (1 << s);
  476. }
  477. }
  478. ++next_code[s];
  479. }
  480. }
  481. return 1;
  482. }
  483. typedef struct
  484. {
  485. unsigned char *zbuffer;
  486. int num_bits;
  487. uint32_t code_buffer;
  488. char *zout;
  489. char *zout_start;
  490. char *zout_end;
  491. _ssfn__zhuffman z_length, z_distance;
  492. } _ssfn__zbuf;
  493. inline static unsigned char _ssfn__zget8(_ssfn__zbuf *z)
  494. {
  495. return *z->zbuffer++;
  496. }
  497. static void _ssfn__fill_bits(_ssfn__zbuf *z)
  498. {
  499. do {
  500. z->code_buffer |= (unsigned int) _ssfn__zget8(z) << z->num_bits;
  501. z->num_bits += 8;
  502. } while (z->num_bits <= 24);
  503. }
  504. inline static unsigned int _ssfn__zreceive(_ssfn__zbuf *z, int n)
  505. {
  506. unsigned int k;
  507. if (z->num_bits < n) _ssfn__fill_bits(z);
  508. k = z->code_buffer & ((1 << n) - 1);
  509. z->code_buffer >>= n;
  510. z->num_bits -= n;
  511. return k;
  512. }
  513. static int _ssfn__zhuffman_decode_slowpath(_ssfn__zbuf *a, _ssfn__zhuffman *z)
  514. {
  515. int b,s,k;
  516. k = _ssfn__bit_reverse(a->code_buffer, 16);
  517. for (s=SSFN__ZFAST_BITS+1; ; ++s)
  518. if (k < z->maxcode[s])
  519. break;
  520. if (s == 16) return -1;
  521. b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
  522. a->code_buffer >>= s;
  523. a->num_bits -= s;
  524. return z->value[b];
  525. }
  526. inline static int _ssfn__zhuffman_decode(_ssfn__zbuf *a, _ssfn__zhuffman *z)
  527. {
  528. int b,s;
  529. if (a->num_bits < 16) _ssfn__fill_bits(a);
  530. b = z->fast[a->code_buffer & SSFN__ZFAST_MASK];
  531. if (b) {
  532. s = b >> 9;
  533. a->code_buffer >>= s;
  534. a->num_bits -= s;
  535. return b & 511;
  536. }
  537. return _ssfn__zhuffman_decode_slowpath(a, z);
  538. }
  539. static int _ssfn__zexpand(_ssfn__zbuf *z, char *zout)
  540. {
  541. char *q;
  542. unsigned int cur, limit;
  543. #ifdef __GNUC__
  544. #pragma GCC diagnostic push
  545. #pragma GCC diagnostic ignored "-Wuse-after-free"
  546. #endif
  547. z->zout = zout; cur = (unsigned int) (z->zout - z->zout_start); limit = (unsigned int) (z->zout_end - z->zout_start);
  548. if(limit == 8) { if(z->zout_start[0] != 'S' || z->zout_start[1] != 'F' || z->zout_start[2] != 'N') return 0; limit = *((uint32_t*)&z->zout_start[4]); } else return 0;
  549. q = (char *) SSFN_realloc(z->zout_start, limit);
  550. if (q == NULL) return 0;
  551. z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit;
  552. #ifdef __GNUC__
  553. #pragma GCC diagnostic pop
  554. #endif
  555. return 1;
  556. }
  557. static int _ssfn__zlength_base[31]={3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0};
  558. static int _ssfn__zlength_extra[31]={0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0};
  559. static int _ssfn__zdist_base[32]={1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
  560. static int _ssfn__zdist_extra[32]={0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
  561. static int _ssfn__parse_huffman_block(_ssfn__zbuf *a)
  562. {
  563. char *zout = a->zout;
  564. for(;;) {
  565. int z = _ssfn__zhuffman_decode(a, &a->z_length);
  566. if (z < 256) {
  567. if (z < 0) return 0;
  568. if (zout >= a->zout_end) { if (!_ssfn__zexpand(a, zout)) return 0; zout = a->zout; }
  569. *zout++ = (char) z;
  570. } else {
  571. unsigned char *p;
  572. int len,dist;
  573. if (z == 256) { a->zout = zout; return 1; }
  574. z -= 257;
  575. len = _ssfn__zlength_base[z];
  576. if (_ssfn__zlength_extra[z]) len += _ssfn__zreceive(a, _ssfn__zlength_extra[z]);
  577. z = _ssfn__zhuffman_decode(a, &a->z_distance);
  578. if (z < 0) return 0;
  579. dist = _ssfn__zdist_base[z];
  580. if (_ssfn__zdist_extra[z]) dist += _ssfn__zreceive(a, _ssfn__zdist_extra[z]);
  581. if (zout - a->zout_start < dist) return 0;
  582. if (zout + len > a->zout_end) {
  583. if (!_ssfn__zexpand(a, zout)) return 0;
  584. zout = a->zout;
  585. }
  586. p = (unsigned char *) (zout - dist);
  587. if (dist == 1) {unsigned char v = *p;if (len) { do *zout++ = v; while (--len); }
  588. } else { if (len) { do *zout++ = *p++; while (--len); } }
  589. }
  590. }
  591. }
  592. static int _ssfn__compute_huffman_codes(_ssfn__zbuf *a)
  593. {
  594. static unsigned char length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
  595. _ssfn__zhuffman z_codelength;
  596. unsigned char lencodes[286+32+137];
  597. unsigned char codelength_sizes[19];
  598. int i,n;
  599. int hlit = _ssfn__zreceive(a,5) + 257;
  600. int hdist = _ssfn__zreceive(a,5) + 1;
  601. int hclen = _ssfn__zreceive(a,4) + 4;
  602. int ntot = hlit + hdist;
  603. SSFN_memset(codelength_sizes, 0, sizeof(codelength_sizes));
  604. for (i=0; i < hclen; ++i) {
  605. int s = _ssfn__zreceive(a,3);
  606. codelength_sizes[length_dezigzag[i]] = (unsigned char) s;
  607. }
  608. if (!_ssfn__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
  609. n = 0;
  610. while (n < ntot) {
  611. int c = _ssfn__zhuffman_decode(a, &z_codelength);
  612. if (c < 0 || c >= 19) return 0;
  613. if (c < 16)
  614. lencodes[n++] = (unsigned char) c;
  615. else {
  616. unsigned char fill = 0;
  617. if (c == 16) {
  618. c = _ssfn__zreceive(a,2)+3;
  619. if (n == 0) return 0;
  620. fill = lencodes[n-1];
  621. } else
  622. if (c == 17) c = _ssfn__zreceive(a,3)+3;
  623. else { c = _ssfn__zreceive(a,7)+11; }
  624. if (ntot - n < c) return 0;
  625. SSFN_memset(lencodes+n, fill, c);
  626. n += c;
  627. }
  628. }
  629. if (n != ntot) return 0;
  630. if (!_ssfn__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
  631. if (!_ssfn__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
  632. return 1;
  633. }
  634. inline static int _ssfn__parse_uncompressed_block(_ssfn__zbuf *a)
  635. {
  636. unsigned char header[4];
  637. int len,nlen,k;
  638. if (a->num_bits & 7)
  639. _ssfn__zreceive(a, a->num_bits & 7);
  640. k = 0;
  641. while (a->num_bits > 0) {
  642. header[k++] = (unsigned char) (a->code_buffer & 255);
  643. a->code_buffer >>= 8;
  644. a->num_bits -= 8;
  645. }
  646. while (k < 4)
  647. header[k++] = _ssfn__zget8(a);
  648. len = header[1] * 256 + header[0];
  649. nlen = header[3] * 256 + header[2];
  650. if (nlen != (len ^ 0xffff)) return 0;
  651. if (a->zout + len > a->zout_end)
  652. if (!_ssfn__zexpand(a, a->zout)) return 0;
  653. for(k = 0; k < len; k++)
  654. a->zout[k] = a->zbuffer[k];
  655. a->zbuffer += len;
  656. a->zout += len;
  657. return 1;
  658. }
  659. static unsigned char _ssfn__zdefault_length[288], _ssfn__zdefault_distance[32];
  660. static void _ssfn__init_zdefaults(void)
  661. {
  662. int i;
  663. for (i=0; i <= 143; ++i) _ssfn__zdefault_length[i] = 8;
  664. for ( ; i <= 255; ++i) _ssfn__zdefault_length[i] = 9;
  665. for ( ; i <= 279; ++i) _ssfn__zdefault_length[i] = 7;
  666. for ( ; i <= 287; ++i) _ssfn__zdefault_length[i] = 8;
  667. for (i=0; i <= 31; ++i) _ssfn__zdefault_distance[i] = 5;
  668. }
  669. static int _ssfn__parse_zlib(_ssfn__zbuf *a)
  670. {
  671. int fin, type;
  672. a->num_bits = 0;
  673. a->code_buffer = 0;
  674. do {
  675. fin = _ssfn__zreceive(a,1);
  676. type = _ssfn__zreceive(a,2);
  677. if (type == 0) { if (!_ssfn__parse_uncompressed_block(a)) return 0; }
  678. else if (type == 3) { return 0; }
  679. else {
  680. if (type == 1) {
  681. if (!_ssfn__zbuild_huffman(&a->z_length , _ssfn__zdefault_length , 288)) return 0;
  682. if (!_ssfn__zbuild_huffman(&a->z_distance, _ssfn__zdefault_distance, 32)) return 0;
  683. } else {
  684. if (!_ssfn__compute_huffman_codes(a)) return 0;
  685. }
  686. if (!_ssfn__parse_huffman_block(a)) return 0;
  687. }
  688. } while (!fin);
  689. return 1;
  690. }
  691. char *_ssfn_zlib_decode(const char *buffer)
  692. {
  693. _ssfn__zbuf a;
  694. char *p = (char *) SSFN_realloc(NULL, 8);
  695. if (p == NULL) return NULL;
  696. a.zbuffer = (unsigned char *) buffer;
  697. a.zout_start = p; a.zout = p; a.zout_end = p + 8;
  698. _ssfn__init_zdefaults();
  699. if (_ssfn__parse_zlib(&a)) { return a.zout_start; } else { SSFN_free(a.zout_start); return NULL; }
  700. }
  701. #endif /* if !SSFN_MAXLINES */
  702. /*** Public API implementation ***/
  703. /**
  704. * Load a font or font collection into renderer context
  705. *
  706. * @param ctx rendering context
  707. * @param font SSFN font or font collection in memory
  708. * @return error code
  709. */
  710. int ssfn_load(ssfn_t *ctx, const void *data)
  711. {
  712. const ssfn_font_t *font = (const ssfn_font_t *)data;
  713. ssfn_font_t *fnt, *end;
  714. int family;
  715. #ifndef SSFN_MAXLINES
  716. uint8_t c, r, *ptr = (uint8_t *)font;
  717. #endif
  718. if(!ctx || !font)
  719. return SSFN_ERR_INVINP;
  720. if(((uint8_t *)font)[0] == 0x1f && ((uint8_t *)font)[1] == 0x8b) {
  721. #ifdef SSFN_MAXLINES
  722. return SSFN_ERR_BADFILE;
  723. #else
  724. ptr += 2;
  725. if(*ptr++ != 8) return SSFN_ERR_BADFILE;
  726. c = *ptr++; ptr += 6;
  727. if(c & 4) { r = *ptr++; r += (*ptr++ << 8); ptr += r; }
  728. if(c & 8) { while(*ptr++ != 0); }
  729. if(c & 16) { while(*ptr++ != 0); }
  730. font = (ssfn_font_t*)_ssfn_zlib_decode((const char*)ptr);
  731. if(!font) return SSFN_ERR_BADFILE;
  732. ctx->bufs = (char**)SSFN_realloc(ctx->bufs, (ctx->numbuf + 1) * sizeof(char*));
  733. if(!ctx->bufs) { ctx->numbuf = 0; return SSFN_ERR_ALLOC; }
  734. ctx->bufs[ctx->numbuf++] = (char*)font;
  735. ctx->lenbuf += font->size;
  736. #endif
  737. }
  738. if(!SSFN_memcmp(font->magic, SSFN_COLLECTION, 4)) {
  739. end = (ssfn_font_t*)((uint8_t*)font + font->size);
  740. for(fnt = (ssfn_font_t*)((uint8_t*)font + 8); fnt < end && !ssfn_load(ctx, (const void *)fnt);
  741. fnt = (ssfn_font_t*)((uint8_t*)fnt + fnt->size));
  742. } else {
  743. family = SSFN_TYPE_FAMILY(font->type);
  744. if(SSFN_memcmp(font->magic, SSFN_MAGIC, 4) || SSFN_memcmp((uint8_t*)font + font->size - 4, SSFN_ENDMAGIC, 4) ||
  745. family > SSFN_FAMILY_HAND || font->fragments_offs >= font->size || font->characters_offs >= font->size ||
  746. font->ligature_offs >= font->size || font->kerning_offs >= font->size || font->cmap_offs >= font->size ||
  747. font->fragments_offs >= font->characters_offs) {
  748. return SSFN_ERR_BADFILE;
  749. } else {
  750. ctx->len[family]++;
  751. #ifdef SSFN_MAXLINES
  752. if(ctx->len[family] > 15) return SSFN_ERR_ALLOC;
  753. #else
  754. ctx->fnt[family] = (const ssfn_font_t**)SSFN_realloc(ctx->fnt[family], ctx->len[family]*sizeof(void*));
  755. if(!ctx->fnt[family]) {
  756. ctx->len[family] = 0;
  757. return SSFN_ERR_ALLOC;
  758. } else
  759. #endif
  760. ctx->fnt[family][ctx->len[family]-1] = font;
  761. }
  762. #ifndef SSFN_MAXLINES
  763. _ssfn_fc(ctx);
  764. #endif
  765. }
  766. return SSFN_OK;
  767. }
  768. /**
  769. * Free renderer context
  770. *
  771. * @param ctx rendering context
  772. */
  773. void ssfn_free(ssfn_t *ctx)
  774. {
  775. #ifndef SSFN_MAXLINES
  776. int i;
  777. #endif
  778. if(!ctx) return;
  779. #ifndef SSFN_MAXLINES
  780. _ssfn_fc(ctx);
  781. if(ctx->bufs) {
  782. for(i = 0; i < ctx->numbuf; i++)
  783. if(ctx->bufs[i]) SSFN_free(ctx->bufs[i]);
  784. SSFN_free(ctx->bufs);
  785. }
  786. for(i = 0; i < 5; i++)
  787. if(ctx->fnt[i]) SSFN_free(ctx->fnt[i]);
  788. if(ctx->p) SSFN_free(ctx->p);
  789. #endif
  790. SSFN_memset(ctx, 0, sizeof(ssfn_t));
  791. }
  792. /**
  793. * Returns how much memory a context consumes
  794. *
  795. * @param ctx rendering context
  796. * @return total memory used by that context in bytes
  797. */
  798. int ssfn_mem(ssfn_t *ctx)
  799. {
  800. #ifdef SSFN_MAXLINES
  801. return ctx ? sizeof(ssfn_t) : 0;
  802. #else
  803. int i, j, k, ret = sizeof(ssfn_t);
  804. if(!ctx) return 0;
  805. for(i = 0; i < 5; i++) ret += ctx->len[i] * sizeof(ssfn_font_t*);
  806. ret += ctx->lenbuf;
  807. for(k = 0; k <= 16; k++) {
  808. if(ctx->c[k]) {
  809. for(j = 0; j < 256; j++)
  810. if(ctx->c[k][j]) {
  811. for(i = 0; i < 256; i++)
  812. if(ctx->c[k][j][i]) ret += 8 + ctx->c[k][j][i]->p * ctx->c[k][j][i]->h;
  813. ret += 256 * sizeof(void*);
  814. }
  815. ret += 256 * sizeof(void*);
  816. }
  817. }
  818. if(ctx->p) ret += ctx->ap * sizeof(uint16_t);
  819. return ret;
  820. #endif
  821. }
  822. /**
  823. * Set up rendering parameters
  824. *
  825. * @param ctx rendering context
  826. * @param family one of SSFN_FAMILY_*
  827. * @param name NULL or UTF-8 string if family is SSFN_FAMILY_BYNAME
  828. * @param style OR'd values of SSFN_STYLE_*
  829. * @param size how big glyph it should render, 8 - 192
  830. * @return error code
  831. */
  832. int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size)
  833. {
  834. int i, j, l;
  835. if(!ctx) return SSFN_ERR_INVINP;
  836. #ifndef SSFN_MAXLINES
  837. _ssfn_fc(ctx);
  838. #endif
  839. if((style & ~0x5FFF)) return SSFN_ERR_BADSTYLE;
  840. if(size < 8 || size > SSFN_SIZE_MAX) return SSFN_ERR_BADSIZE;
  841. if(family == SSFN_FAMILY_BYNAME) {
  842. if(!name || !name[0]) return SSFN_ERR_INVINP;
  843. for(l=0; name[l]; l++);
  844. for(i=0; i < 5; i++) {
  845. for(j=0; j < ctx->len[i]; j++) {
  846. if(!SSFN_memcmp(name, (uint8_t*)&ctx->fnt[i][j]->magic + sizeof(ssfn_font_t), l)) {
  847. ctx->s = ctx->fnt[i][j];
  848. goto familyfound;
  849. }
  850. }
  851. }
  852. return SSFN_ERR_NOFACE;
  853. } else {
  854. if(family != SSFN_FAMILY_ANY && (family > SSFN_FAMILY_HAND || !ctx->len[family])) return SSFN_ERR_NOFACE;
  855. ctx->s = NULL;
  856. }
  857. familyfound:
  858. ctx->f = NULL;
  859. ctx->family = family;
  860. ctx->style = style;
  861. ctx->size = size;
  862. ctx->line = 0;
  863. return SSFN_OK;
  864. }
  865. /**
  866. * Render a glyph to a pixel buffer
  867. *
  868. * @param ctx rendering context
  869. * @param dst destination buffer
  870. * @param str pointer to an UTF-8 string
  871. * @return number of bytes parsed in str (zero means end of string) or error code
  872. */
  873. int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str)
  874. {
  875. ssfn_font_t **fl;
  876. uint8_t *ptr = NULL, *frg, *end, *tmp, color, ci = 0, cb = 0, cs, dec[65536];
  877. uint16_t r[640];
  878. uint32_t unicode, P, O, *Op, *Ol, sR, sG, sB, sA, bA;
  879. int ret = 0, i, j, k, l, p, m, n, o, s, x, y, w, h, H, a, A, b, B, nr, uix, uax;
  880. int ox, oy, y0, y1, Y0, Y1, x0, x1, X0, X1, X2, xs, ys, yp, pc, fB, fG, fR, fA, bB, bG, bR, dB, dG, dR, dA;
  881. #ifdef SSFN_PROFILING
  882. struct timeval tv0, tv1, tvd;
  883. gettimeofday(&tv0, NULL);
  884. #endif
  885. #define PUTPIXEL O = *Ol;bR = (O >> (16 - cs)) & 0xFF; bG = (O >> 8) & 0xFF; bB = (O >> cs) & 0xFF; bA = (O >> 24) & 0xFF;\
  886. bB += ((fB - bB) * fA) >> 8; bG += ((fG - bG) * fA) >> 8; bR += ((fR - bR) * fA) >> 8; bA += ((fA - bA) * fA) >> 8;\
  887. *Ol = (bA << 24) | (bR << (16 - cs)) | (bG << 8) | (bB << cs);
  888. if(!ctx || !str) return SSFN_ERR_INVINP;
  889. if(!*str) return 0;
  890. if(*str == '\r') { dst->x = 0; return 1; }
  891. if(*str == '\n') { dst->x = 0; dst->y += ctx->line ? ctx->line : ctx->size; return 1; }
  892. if(ctx->s) {
  893. ctx->f = ctx->s;
  894. ptr = _ssfn_c(ctx->f, str, &ret, &unicode);
  895. } else {
  896. /* find best match */
  897. p = ctx->family;
  898. ctx->f = NULL;
  899. again: if(p >= SSFN_FAMILY_BYNAME) { n = 0; m = 4; } else n = m = p;
  900. for(; n <= m; n++) {
  901. fl = (ssfn_font_t **)ctx->fnt[n];
  902. if(ctx->style & 3) {
  903. /* check if we have a specific ctx->f for the requested style and size */
  904. for(i=0;i<ctx->len[n];i++)
  905. if(((fl[i]->type>>4) & 3) == (ctx->style & 3) && fl[i]->height == ctx->size &&
  906. (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
  907. /* if not, check if we have the requested size (for bitmap fonts) */
  908. if(!ptr)
  909. for(i=0;i<ctx->len[n];i++)
  910. if(fl[i]->height == ctx->size && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
  911. /* if neither size+style nor size matched, look for style match */
  912. if(!ptr)
  913. for(i=0;i<ctx->len[n];i++)
  914. if(((fl[i]->type>>4) & 3) == (ctx->style & 3) && (ptr = _ssfn_c(fl[i], str, &ret, &unicode)))
  915. { ctx->f = fl[i]; break; }
  916. /* if bold italic was requested, check if we have at least bold or italic */
  917. if(!ptr && (ctx->style & 3) == 3)
  918. for(i=0;i<ctx->len[n];i++)
  919. if(((fl[i]->type>>4) & 3) && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
  920. }
  921. /* last resort, get the first ctx->f which has a glyph for this multibyte, no matter style */
  922. if(!ptr) {
  923. for(i=0;i<ctx->len[n];i++)
  924. if((ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
  925. }
  926. }
  927. /* if glyph still not found, try any family group */
  928. if(!ptr && p != SSFN_FAMILY_ANY) { p = SSFN_FAMILY_ANY; goto again; }
  929. }
  930. if(!ptr) {
  931. if(ctx->style & SSFN_STYLE_NODEFGLYPH) return SSFN_ERR_NOGLYPH;
  932. else {
  933. unicode = 0;
  934. if(ctx->family >= SSFN_FAMILY_BYNAME) { n = 0; m = 4; } else n = m = ctx->family;
  935. for(; n <= m && !ptr; n++)
  936. if(ctx->len[n] && ctx->fnt[n][0] && !(*((uint8_t*)ctx->fnt[n][0] + ctx->fnt[n][0]->characters_offs) & 0x80))
  937. { ctx->f = ctx->fnt[n][0]; ptr = (uint8_t*)ctx->f + ctx->f->characters_offs; }
  938. }
  939. if(!ptr) return SSFN_ERR_NOGLYPH;
  940. }
  941. if(!ctx->f || !ctx->f->height || !ctx->size) return SSFN_ERR_NOFACE;
  942. if((unicode >> 16) > 0x10) return SSFN_ERR_INVINP;
  943. ctx->rc = (ssfn_chr_t*)ptr; ptr += sizeof(ssfn_chr_t);
  944. H = (ctx->style & SSFN_STYLE_ABS_SIZE) || SSFN_TYPE_FAMILY(ctx->f->type) == SSFN_FAMILY_MONOSPACE || !ctx->f->baseline ?
  945. ctx->size : ctx->size * ctx->f->height / ctx->f->baseline;
  946. #ifdef SSFN_PROFILING
  947. gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  948. if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
  949. ctx->lookup += tvd.tv_sec * 1000000L + tvd.tv_usec;
  950. memcpy(&tv0, &tv1, sizeof(struct timeval));
  951. #endif
  952. /* render glyph into cache */
  953. #ifndef SSFN_MAXLINES
  954. if(!(ctx->style & SSFN_STYLE_NOCACHE) && ctx->c[unicode >> 16] && ctx->c[unicode >> 16][(unicode >> 8) & 0xFF] &&
  955. ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) {
  956. ctx->g = ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF];
  957. } else
  958. #endif
  959. {
  960. h = ctx->style & SSFN_STYLE_NOAA ? H : (ctx->size > ctx->f->height ? (ctx->size + 4) & ~3 : ctx->f->height);
  961. ci = (ctx->style & SSFN_STYLE_ITALIC) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_ITALIC);
  962. cb = (ctx->style & SSFN_STYLE_BOLD) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_BOLD) ? (ctx->f->height+64)>>6 : 0;
  963. w = (ctx->rc->w * h + ctx->f->height - 1) / ctx->f->height;
  964. if(w > SSFN_SIZE_MAX) { h = h * SSFN_SIZE_MAX / w; w = SSFN_SIZE_MAX; }
  965. p = w + (ci ? h / SSFN_ITALIC_DIV : 0) + cb;
  966. /* failsafe, should never happen */
  967. if(p * h >= SSFN_DATA_MAX) return SSFN_ERR_BADSIZE;
  968. #ifndef SSFN_MAXLINES
  969. if(!(ctx->style & SSFN_STYLE_NOCACHE)) {
  970. if(!ctx->c[unicode >> 16]) {
  971. ctx->c[unicode >> 16] = (ssfn_glyph_t***)SSFN_realloc(NULL, 256 * sizeof(void*));
  972. if(!ctx->c[unicode >> 16]) return SSFN_ERR_ALLOC;
  973. SSFN_memset(ctx->c[unicode >> 16], 0, 256 * sizeof(void*));
  974. }
  975. if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF]) {
  976. ctx->c[unicode >> 16][(unicode >> 8) & 0xFF] = (ssfn_glyph_t**)SSFN_realloc(NULL, 256 * sizeof(void*));
  977. if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF]) return SSFN_ERR_ALLOC;
  978. SSFN_memset(ctx->c[unicode >> 16][(unicode >> 8) & 0xFF], 0, 256 * sizeof(void*));
  979. }
  980. ctx->g = ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF] = (ssfn_glyph_t*)SSFN_realloc(NULL, p * h + 8);
  981. if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) return SSFN_ERR_ALLOC;
  982. } else
  983. #endif
  984. ctx->g = &ctx->ga;
  985. x = (ctx->rc->x > 0 && ci ? (ctx->f->height - ctx->f->baseline) * h / SSFN_ITALIC_DIV / ctx->f->height : 0);
  986. ctx->g->p = p;
  987. ctx->g->h = h;
  988. ctx->g->x = (ctx->rc->x + x > 255 ? 255 : ctx->rc->x + x);
  989. ctx->g->y = ctx->rc->y;
  990. ctx->g->o = (ctx->rc->t & 0x3F) + x;
  991. SSFN_memset(&ctx->g->data, 0xFF, p * h);
  992. color = 0xFE; ctx->g->a = ctx->g->d = 0;
  993. for(n = 0; n < ctx->rc->n; n++) {
  994. if(ptr[0] == 255 && ptr[1] == 255) { color = ptr[2]; ptr += ctx->rc->t & 0x40 ? 6 : 5; continue; }
  995. x = ((ptr[0] + cb) << SSFN_PREC) * h / ctx->f->height; y = (ptr[1] << SSFN_PREC) * h / ctx->f->height;
  996. if(ctx->rc->t & 0x40) { m = (ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 6; }
  997. else { m = (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 5; }
  998. frg = (uint8_t*)ctx->f + m;
  999. if(!(frg[0] & 0x80)) {
  1000. /* contour */
  1001. j = (frg[0] & 0x3F);
  1002. if(frg[0] & 0x40) { j <<= 8; j |= frg[1]; frg++; }
  1003. j++; frg++; tmp = frg; frg += (j+3)/4; ctx->np = 0;
  1004. for(i = 0; i < j; i++) {
  1005. k = (frg[0] << SSFN_PREC) * h / ctx->f->height + x; m = (frg[1] << SSFN_PREC) * h / ctx->f->height + y;
  1006. switch((tmp[i >> 2] >> ((i & 3) << 1)) & 3) {
  1007. case SSFN_CONTOUR_MOVE: ctx->mx = ctx->lx = k; ctx->my = ctx->ly = m; frg += 2; break;
  1008. case SSFN_CONTOUR_LINE: _ssfn_l(ctx, p << SSFN_PREC, h << SSFN_PREC, k, m); frg += 2; break;
  1009. case SSFN_CONTOUR_QUAD:
  1010. a = (frg[2] << SSFN_PREC) * h / ctx->f->height + x; A = (frg[3] << SSFN_PREC) * h / ctx->f->height + y;
  1011. _ssfn_b(ctx, p << SSFN_PREC,h << SSFN_PREC, ctx->lx,ctx->ly, ((a-ctx->lx)/2)+ctx->lx,
  1012. ((A-ctx->ly)/2)+ctx->ly, ((k-a)/2)+a,((A-m)/2)+m, k,m, 0);
  1013. frg += 4;
  1014. break;
  1015. case SSFN_CONTOUR_CUBIC:
  1016. a = (frg[2] << SSFN_PREC) * h / ctx->f->height + x; A = (frg[3] << SSFN_PREC) * h / ctx->f->height + y;
  1017. b = (frg[4] << SSFN_PREC) * h / ctx->f->height + x; B = (frg[5] << SSFN_PREC) * h / ctx->f->height + y;
  1018. _ssfn_b(ctx, p << SSFN_PREC,h << SSFN_PREC, ctx->lx,ctx->ly, a,A, b,B, k,m, 0);
  1019. frg += 6;
  1020. break;
  1021. }
  1022. }
  1023. /* close path */
  1024. if(ctx->mx != ctx->lx || ctx->my != ctx->ly) { ctx->p[ctx->np+0] = ctx->mx; ctx->p[ctx->np+1] = ctx->my; ctx->np += 2; }
  1025. /* add rasterized vector layers to cached glyph */
  1026. if(ctx->np > 4) {
  1027. for(b = A = B = o = 0; b < h; b++, B += p) {
  1028. a = b << SSFN_PREC;
  1029. for(nr = 0, i = 0; i < ctx->np - 3; i += 2) {
  1030. if( (ctx->p[i+1] < a && ctx->p[i+3] >= a) ||
  1031. (ctx->p[i+3] < a && ctx->p[i+1] >= a)) {
  1032. if((ctx->p[i+1] >> SSFN_PREC) == (ctx->p[i+3] >> SSFN_PREC))
  1033. x = (((int)ctx->p[i]+(int)ctx->p[i+2])>>1);
  1034. else
  1035. x = ((int)ctx->p[i]) + ((a - (int)ctx->p[i+1])*
  1036. ((int)ctx->p[i+2] - (int)ctx->p[i])/
  1037. ((int)ctx->p[i+3] - (int)ctx->p[i+1]));
  1038. x >>= SSFN_PREC;
  1039. if(ci) x += (h - b) / SSFN_ITALIC_DIV;
  1040. if(cb && !o) {
  1041. if(ctx->g->data[B + x] != color) { o = -cb; A = cb; }
  1042. else { o = cb; A = -cb; }
  1043. }
  1044. for(k = 0; k < nr && x > r[k]; k++);
  1045. for(l = nr; l > k; l--) r[l] = r[l-1];
  1046. r[k] = x;
  1047. nr++;
  1048. }
  1049. }
  1050. if(nr > 1 && nr & 1) { r[nr - 2] = r[nr - 1]; nr--; }
  1051. if(nr) {
  1052. if(ctx->g->d < y + b) ctx->g->d = y + b;
  1053. for(i = 0; i < nr - 1; i += 2) {
  1054. l = r[i] + o; m = r[i + 1] + A;
  1055. if(l < 0) l = 0;
  1056. if(m > p) m = p;
  1057. if(i > 0 && l < r[i - 1] + A) l = r[i - 1] + A;
  1058. for(; l < m; l++)
  1059. ctx->g->data[B + l] = ctx->g->data[B + l] == color ? 0xFF : color;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. } else if((frg[0] & 0x60) == 0x00) {
  1065. /* bitmap */
  1066. B = ((frg[0] & 0x1F) + 1) << 3; A = frg[1] + 1; x >>= SSFN_PREC; y >>= SSFN_PREC;
  1067. b = B * h / ctx->f->height; a = A * h / ctx->f->height;
  1068. if(ctx->g->d < y + a) ctx->g->d = y + a;
  1069. frg += 2;
  1070. for(j = 0; j < a; j++) {
  1071. k = j * A / a;
  1072. l = (y + j) * p + x + (ci ? (h - y - j) / SSFN_ITALIC_DIV : 0);
  1073. for(i = 0; i < b; i++) {
  1074. m = i * B / b;
  1075. if(frg[(k * B + m) >> 3] & (1 << (m & 7))) {
  1076. for(o = 0; o <= cb; o++)
  1077. ctx->g->data[l + i + o] = color;
  1078. }
  1079. }
  1080. }
  1081. if(!(ctx->style & (SSFN_STYLE_NOAA|SSFN_STYLE_NOSMOOTH))) {
  1082. m = color == 0xFD ? 0xFC : 0xFD; o = y * p + p + x;
  1083. for(k = h; k > ctx->f->height + 4; k -= 2*ctx->f->height) {
  1084. for(j = 1, l = o; j < a - 1; j++, l += p)
  1085. for(i = 1; i < b - 1; i++) {
  1086. if(ctx->g->data[l + i] == 0xFF && (ctx->g->data[l + i - p] == color ||
  1087. ctx->g->data[l + i + p] == color) && (ctx->g->data[l + i - 1] == color ||
  1088. ctx->g->data[l + i + 1] == color)) ctx->g->data[l + i] = m;
  1089. }
  1090. for(j = 1, l = o; j < a - 1; j++, l += p)
  1091. for(i = 1; i < b - 1; i++) {
  1092. if(ctx->g->data[l + i] == m) ctx->g->data[l + i] = color;
  1093. }
  1094. }
  1095. }
  1096. } else if((frg[0] & 0x60) == 0x20) {
  1097. /* pixmap */
  1098. k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; B = frg[2] + 1; A = frg[3] + 1; x >>= SSFN_PREC; y >>= SSFN_PREC;
  1099. b = B * h / ctx->f->height; a = A * h / ctx->f->height;
  1100. if(ctx->g->d < y + a) ctx->g->d = y + a;
  1101. frg += 4; end = frg + k; i = 0;
  1102. while(frg < end) {
  1103. l = ((*frg++) & 0x7F) + 1;
  1104. if(frg[-1] & 0x80) {
  1105. while(l--) dec[i++] = *frg;
  1106. frg++;
  1107. } else while(l--) dec[i++] = *frg++;
  1108. }
  1109. for(j = 0; j < a; j++) {
  1110. k = j * A / a * B;
  1111. l = (y + j) * p + x + (ci ? (h - y - j) / SSFN_ITALIC_DIV : 0);
  1112. for(i = 0; i < b; i++) {
  1113. m = dec[k + i * B / b];
  1114. if(m != 0xFF) ctx->g->data[l + i] = m;
  1115. }
  1116. }
  1117. }
  1118. color = 0xFE;
  1119. }
  1120. ctx->g->a = ctx->f->baseline;
  1121. if(ctx->g->d > ctx->g->a + 1) ctx->g->d -= ctx->g->a + 1; else ctx->g->d = 0;
  1122. #ifdef SSFN_DEBUGGLYPH
  1123. printf("\nU+%06X size %d p %d h %d base %d under %d overlap %d ascender %d descender %d advance x %d advance y %d cb %d\n",
  1124. unicode, ctx->size,p,h,ctx->f->baseline,ctx->f->underline,ctx->g->o,ctx->g->a,ctx->g->d,ctx->g->x,ctx->g->y,cb);
  1125. for(j = 0; j < h; j++) { printf("%3d: ", j); for(i = 0; i < p; i++) { if(ctx->g->data[j*p+i] == 0xFF) printf(j == ctx->g->a ? "_" : "."); else printf("%x", ctx->g->data[j*p+i] & 0xF); } printf("\n"); }
  1126. #endif
  1127. #ifdef SSFN_PROFILING
  1128. gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  1129. if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
  1130. ctx->raster += tvd.tv_sec * 1000000L + tvd.tv_usec;
  1131. memcpy(&tv0, &tv1, sizeof(struct timeval));
  1132. #endif
  1133. }
  1134. if(dst) {
  1135. /* blit glyph from cache into buffer */
  1136. h = H;
  1137. if(h > ctx->line) ctx->line = h;
  1138. w = ctx->g->p * h / ctx->g->h;
  1139. s = ((ctx->g->x - ctx->g->o) * h + ctx->f->height - 1) / ctx->f->height;
  1140. n = ctx->size > 16 ? 2 : 1;
  1141. if(w < n) w = n;
  1142. if(s < n) s = n;
  1143. if(ctx->g->x) {
  1144. ctx->ox = ox = ((ctx->g->o * h + ctx->f->height - 1) / ctx->f->height) + (ctx->style & SSFN_STYLE_RTL ? w : 0);
  1145. ctx->oy = oy = (ctx->g->a * h + ctx->f->height - 1) / ctx->f->height;
  1146. } else { ctx->ox = ox = w / 2; ctx->oy = oy = 0; }
  1147. if(dst->ptr) {
  1148. j = dst->w < 0 ? -dst->w : dst->w;
  1149. cs = dst->w < 0 ? 16 : 0;
  1150. cb = (h + 64) >> 6; uix = w > s ? w : s; uax = 0;
  1151. n = (ctx->f->underline * h + ctx->f->height - 1) / ctx->f->height;
  1152. #ifdef SSFN_DEBUGGLYPH
  1153. printf("Scaling to w %d h %d (glyph %d %d, cache %d %d, font %d)\n",
  1154. w,h,ctx->rc->w,ctx->rc->h,ctx->g->p,ctx->g->h,ctx->f->height);
  1155. #endif
  1156. fR = (dst->fg >> 16) & 0xFF; fG = (dst->fg >> 8) & 0xFF; fB = (dst->fg >> 0) & 0xFF; fA = (dst->fg >> 24) & 0xFF;
  1157. bR = (dst->bg >> 16) & 0xFF; bG = (dst->bg >> 8) & 0xFF; bB = (dst->bg >> 0) & 0xFF; O = 0xFF000000;
  1158. Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy) + ((dst->x - ox) << 2));
  1159. for (y = 0; y < h && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) {
  1160. if(dst->y + y - oy < 0) continue;
  1161. y0 = (y << 8) * ctx->g->h / h; Y0 = y0 >> 8; y1 = ((y + 1) << 8) * ctx->g->h / h; Y1 = y1 >> 8; Ol = Op;
  1162. for (x = 0; x < w && dst->x + x - ox < j; x++, Ol++) {
  1163. if(dst->x + x - ox < 0) continue;
  1164. m = 0; sR = sG = sB = sA = bA = 0;
  1165. if(!dst->bg) {
  1166. /* real linear frame buffers should be accessed only as uint32_t on 32 bit boundary */
  1167. O = *Ol;
  1168. bA = (O >> 24) & 0xFF;
  1169. bR = (O >> (16 - cs)) & 0xFF;
  1170. bG = (O >> 8) & 0xFF;
  1171. bB = (O >> cs) & 0xFF;
  1172. }
  1173. x0 = (x << 8) * ctx->g->p / w; X0 = x0 >> 8; x1 = ((x + 1) << 8) * ctx->g->p / w; X1 = x1 >> 8;
  1174. for(ys = y0; ys < y1; ys += 256) {
  1175. if(ys >> 8 == Y0) { yp = 256 - (ys & 0xFF); ys &= ~0xFF; if(yp > y1 - y0) yp = y1 - y0; }
  1176. else if(ys >> 8 == Y1) yp = y1 & 0xFF; else yp = 256;
  1177. X2 = (ys >> 8) * ctx->g->p;
  1178. for(xs = x0; xs < x1; xs += 256) {
  1179. if (xs >> 8 == X0) {
  1180. k = 256 - (xs & 0xFF); xs &= ~0xFF; if(k > x1 - x0) k = x1 - x0; pc = k == 256 ? yp : (k * yp)>>8;
  1181. } else
  1182. if (xs >> 8 == X1) { k = x1 & 0xFF; pc = k == 256 ? yp : (k * yp) >> 8; }
  1183. else pc = yp;
  1184. m += pc;
  1185. k = ctx->g->data[X2 + (xs >> 8)];
  1186. if(k == 0xFF) {
  1187. sB += bB * pc; sG += bG * pc; sR += bR * pc; sA += 255;
  1188. } else {
  1189. if(k == 0xFE || !ctx->f->cmap_offs) {
  1190. dB = fB; dG = fG; dR = fR; dA = fA;
  1191. } else {
  1192. P = *((uint32_t*)((uint8_t*)ctx->f + ctx->f->cmap_offs + (k << 2)));
  1193. dR = (P >> 16) & 0xFF; dG = (P >> 8) & 0xFF; dB = (P >> 0) & 0xFF; dA = (P >> 24) & 0xFF;
  1194. }
  1195. if(dA == 255) {
  1196. sB += dB * pc; sG += dG * pc; sR += dR * pc; sA += dA * pc;
  1197. } else {
  1198. sB += (dB * dA + bB * (255 - dA)) * pc / 255; sG += (dG * dA + bG * (255 - dA)) * pc / 255;
  1199. sR += (dR * dA + bR * (255 - dA)) * pc / 255; sA += dA * pc;
  1200. }
  1201. }
  1202. }
  1203. }
  1204. if(m) { sR /= m; sG /= m; sB /= m; sA /= m; } else { sR >>= 8; sG >>= 8; sB >>= 8; sA >>= 8; }
  1205. if(ctx->style & SSFN_STYLE_NOAA) sA = sA > 127 ? 255 : 0;
  1206. if(sA > 15) {
  1207. *Ol = ((sA > 255 ? 255 : (sA > bA ? sA : bA)) << 24) |
  1208. ((sR > 255 ? 255 : sR) << (16 - cs)) | ((sG > 255 ? 255 : sG) << 8) | ((sB > 255 ? 255 : sB) << cs);
  1209. if(y == n) { if(uix > x) { uix = x; } if(uax < x) { uax = x; } }
  1210. }
  1211. }
  1212. }
  1213. if(ctx->style & SSFN_STYLE_UNDERLINE) {
  1214. uix -= cb + 1; uax += cb + 2;
  1215. if(uax < uix) uax = uix + 1;
  1216. k = (w > s ? w : s);
  1217. Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy + n) + ((dst->x - ox - 1) << 2));
  1218. for (y = n; y < n + cb && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) {
  1219. if(dst->y + y - oy < 0) continue;
  1220. for (Ol = Op, x = 0; x <= k && dst->x + x - ox < j; x++, Ol++) {
  1221. if(dst->x + x - ox < 0 || (x > uix && x < uax)) continue;
  1222. PUTPIXEL;
  1223. }
  1224. }
  1225. }
  1226. if(ctx->style & SSFN_STYLE_STHROUGH) {
  1227. n = (h >> 1); k = (w > s ? w : s) + 1;
  1228. Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy + n) + ((dst->x - ox - 1) << 2));
  1229. for (y = n; y < n + cb && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) {
  1230. if(dst->y + y - oy < 0) continue;
  1231. for (Ol = Op, x = 0; x <= k && dst->x + x - ox < j; x++, Ol++) {
  1232. if(dst->x + x - ox < 0) continue;
  1233. PUTPIXEL;
  1234. }
  1235. }
  1236. }
  1237. #ifdef SSFN_PROFILING
  1238. gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  1239. if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
  1240. ctx->blit += tvd.tv_sec * 1000000L + tvd.tv_usec;
  1241. memcpy(&tv0, &tv1, sizeof(struct timeval));
  1242. #endif
  1243. }
  1244. /* add advance and kerning */
  1245. ctx->ax = (ctx->style & SSFN_STYLE_RTL ? -s : s);
  1246. dst->x += ctx->ax;
  1247. dst->y += (ctx->g->y * h + ctx->f->height - 1) / ctx->f->height;
  1248. ptr = (uint8_t*)str + ret;
  1249. if(!(ctx->style & SSFN_STYLE_NOKERN) && ctx->f->kerning_offs && _ssfn_c(ctx->f, (const char*)ptr, &i, &P) && P > 32) {
  1250. ptr = (uint8_t*)ctx->rc + sizeof(ssfn_chr_t);
  1251. /* check all kerning fragments, because we might have both vertical and horizontal kerning offsets */
  1252. for(n = 0; n < ctx->rc->n; n++) {
  1253. if(ptr[0] == 255 && ptr[1] == 255) { ptr += ctx->rc->t & 0x40 ? 6 : 5; continue; }
  1254. x = ptr[0];
  1255. if(ctx->rc->t & 0x40) { m = (ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 6; }
  1256. else { m = (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 5; }
  1257. frg = (uint8_t*)ctx->f + m;
  1258. if((frg[0] & 0xE0) == 0xC0) {
  1259. k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; frg += 2;
  1260. while(k--) {
  1261. m = ((frg[2] & 0xF) << 16) | (frg[1] << 8) | frg[0];
  1262. if(P >= (uint32_t)m && P <= (uint32_t)(((frg[5] & 0xF) << 16) | (frg[4] << 8) | frg[3])) {
  1263. P -= m;
  1264. m = ctx->f->kerning_offs + ((((frg[2] >> 4) & 0xF) << 24) | (((frg[5] >> 4) & 0xF) << 16) |
  1265. (frg[7] << 8) | frg[6]);
  1266. tmp = (uint8_t*)ctx->f + m;
  1267. while(tmp < (uint8_t*)ctx->f + ctx->f->size - 4) {
  1268. if((tmp[0] & 0x7F) < P) {
  1269. P -= (tmp[0] & 0x7F) + 1;
  1270. tmp += 2 + (tmp[0] & 0x80 ? 0 : tmp[0] & 0x7F);
  1271. } else {
  1272. y = (int)((signed char)tmp[1 + ((tmp[0] & 0x80) ? 0 : P)]) * h / ctx->f->height;
  1273. if(x) dst->x += y; else dst->y += y;
  1274. break;
  1275. }
  1276. }
  1277. break;
  1278. }
  1279. frg += 8;
  1280. }
  1281. }
  1282. }
  1283. #ifdef SSFN_PROFILING
  1284. gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  1285. if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
  1286. ctx->kern += tvd.tv_sec * 1000000L + tvd.tv_usec;
  1287. #endif
  1288. }
  1289. }
  1290. return ret;
  1291. }
  1292. /**
  1293. * Get the bounding box for a string
  1294. * @param ctx rendering context
  1295. * @param str string to measure
  1296. * @param w returned width
  1297. * @param h returned height
  1298. * @param left returned left margin
  1299. * @param top returned ascender
  1300. * @return error code
  1301. */
  1302. int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top)
  1303. {
  1304. ssfn_buf_t buf;
  1305. int ret, f = 1, l = 0, t = 0;
  1306. if(!ctx || !str) return SSFN_ERR_INVINP;
  1307. if(w) {*w = 0;} if(h) {*h = 0;} if(top) {*top = 0;} if(left) {*left = 0;}
  1308. if(!*str) return SSFN_OK;
  1309. SSFN_memset(&buf, 0, sizeof(ssfn_buf_t)); ctx->line = 0;
  1310. while((ret = ssfn_render(ctx, &buf, str))) {
  1311. if(ret < 0 || !ctx->g) return ret;
  1312. if(f) { f = 0; l = ctx->ox; buf.x += l; }
  1313. if(ctx->g->x) {
  1314. if(ctx->oy > t) t = ctx->oy;
  1315. } else {
  1316. if(buf.w < ctx->g->p) buf.w = ctx->g->p;
  1317. buf.h += ctx->g->y ? ctx->g->y : ctx->g->h;
  1318. }
  1319. str += ret;
  1320. }
  1321. if((ctx->style & SSFN_STYLE_ITALIC) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_ITALIC))
  1322. buf.x += ctx->size / SSFN_ITALIC_DIV - l;
  1323. if(ctx->g->x) { if(w) {*w = buf.x;} if(h) {*h = ctx->line;} if(left) {*left = l;} if(top) {*top = t;} }
  1324. else { if(w) {*w = buf.w;} if(h) {*h = buf.y;} if(top) {*top = 0;} if(left) {*left = 0;} }
  1325. return SSFN_OK;
  1326. }
  1327. /**
  1328. * Render text to a newly allocated pixel buffer
  1329. *
  1330. * @param ctx rendering context
  1331. * @param str string to measure
  1332. * @return a newly allocated pixel buffer or NULL
  1333. */
  1334. ssfn_buf_t *ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg)
  1335. {
  1336. #ifndef SSFN_MAXLINES
  1337. ssfn_buf_t *buf;
  1338. int ret;
  1339. if(!ctx || !str) return NULL;
  1340. buf = (ssfn_buf_t*)SSFN_realloc(NULL, sizeof(ssfn_buf_t));
  1341. if(!buf) return NULL;
  1342. SSFN_memset(buf, 0, sizeof(ssfn_buf_t));
  1343. buf->fg = fg;
  1344. if(!*str || ssfn_bbox(ctx, str, (int*)&buf->w, (int*)&buf->h, (int*)&buf->x, (int*)&buf->y) != SSFN_OK)
  1345. return buf;
  1346. buf->p = buf->w * sizeof(uint32_t);
  1347. buf->ptr = (uint8_t*)SSFN_realloc(NULL, buf->p * buf->h);
  1348. SSFN_memset(buf->ptr, 0, buf->p * buf->h);
  1349. while((ret = ssfn_render(ctx, buf, str)) > 0)
  1350. str += ret;
  1351. if(ret != SSFN_OK) { SSFN_free(buf->ptr); SSFN_free(buf); return NULL; }
  1352. return buf;
  1353. #else
  1354. (void)ctx;
  1355. (void)str;
  1356. (void)fg;
  1357. return NULL;
  1358. #endif
  1359. }
  1360. #endif /* SSFN_IMPLEMENTATION */
  1361. #if defined(SSFN_CONSOLEBITMAP_PALETTE) || defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)
  1362. /*** special console bitmap font renderer (ca. 1.5k, no dependencies, no memory allocation and no error checking) ***/
  1363. /**
  1364. * public variables to configure
  1365. */
  1366. ssfn_font_t *ssfn_src; /* font buffer with an inflated bitmap font */
  1367. ssfn_buf_t ssfn_dst; /* destination frame buffer */
  1368. /**
  1369. * Minimal OS kernel console renderer
  1370. *
  1371. * @param unicode character
  1372. * @return error code
  1373. */
  1374. int ssfn_putc(uint32_t unicode)
  1375. {
  1376. # ifdef SSFN_CONSOLEBITMAP_PALETTE
  1377. # define SSFN_PIXEL uint8_t
  1378. # else
  1379. # ifdef SSFN_CONSOLEBITMAP_HICOLOR
  1380. # define SSFN_PIXEL uint16_t
  1381. # else
  1382. # define SSFN_PIXEL uint32_t
  1383. # endif
  1384. # endif
  1385. register SSFN_PIXEL *o, *p;
  1386. register uint8_t *ptr, *chr = NULL, *frg;
  1387. register int i, j, k, l, m, y = 0, w, s = ssfn_dst.p / sizeof(SSFN_PIXEL);
  1388. if(!ssfn_src || ssfn_src->magic[0] != 'S' || ssfn_src->magic[1] != 'F' || ssfn_src->magic[2] != 'N' ||
  1389. ssfn_src->magic[3] != '2' || !ssfn_dst.ptr || !ssfn_dst.p) return SSFN_ERR_INVINP;
  1390. w = ssfn_dst.w < 0 ? -ssfn_dst.w : ssfn_dst.w;
  1391. for(ptr = (uint8_t*)ssfn_src + ssfn_src->characters_offs, i = 0; i < 0x110000; i++) {
  1392. if(ptr[0] == 0xFF) { i += 65535; ptr++; }
  1393. else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; }
  1394. else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; }
  1395. else { if((uint32_t)i == unicode) { chr = ptr; break; } ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5); }
  1396. }
  1397. #ifdef SSFN_CONSOLEBITMAP_CONTROL
  1398. i = ssfn_src->height; j = ssfn_dst.h - i - (ssfn_dst.h % i);
  1399. if(chr && w) {
  1400. if(unicode == '\t') ssfn_dst.x -= ssfn_dst.x % chr[4];
  1401. if(ssfn_dst.x + chr[4] > w) { ssfn_dst.x = 0; ssfn_dst.y += i; }
  1402. }
  1403. if(unicode == '\n') ssfn_dst.y += i;
  1404. if(j > 0 && ssfn_dst.y > j) {
  1405. ssfn_dst.y = j;
  1406. for(k = 0; k < j; k++)
  1407. for(l = 0; l < ssfn_dst.p; l++) ssfn_dst.ptr[k * ssfn_dst.p + l] = ssfn_dst.ptr[(k + i) * ssfn_dst.p + l];
  1408. }
  1409. if(unicode == '\r' || unicode == '\n') { ssfn_dst.x = 0; return SSFN_OK; }
  1410. #endif
  1411. if(!chr) return SSFN_ERR_NOGLYPH;
  1412. ptr = chr + 6; o = (SSFN_PIXEL*)(ssfn_dst.ptr + ssfn_dst.y * ssfn_dst.p + ssfn_dst.x * sizeof(SSFN_PIXEL));
  1413. for(i = 0; i < chr[1]; i++, ptr += chr[0] & 0x40 ? 6 : 5) {
  1414. if(ptr[0] == 255 && ptr[1] == 255) continue;
  1415. frg = (uint8_t*)ssfn_src + (chr[0] & 0x40 ? ((ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) :
  1416. ((ptr[4] << 16) | (ptr[3] << 8) | ptr[2]));
  1417. if((frg[0] & 0xE0) != 0x80) continue;
  1418. if(ssfn_dst.bg) {
  1419. for(; y < ptr[1] && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); y++, o += s) {
  1420. for(p = o, j = 0; j < chr[2] && (!w || ssfn_dst.x + j < w); j++, p++)
  1421. *p = ssfn_dst.bg;
  1422. }
  1423. } else { o += (int)(ptr[1] - y) * s; y = ptr[1]; }
  1424. k = ((frg[0] & 0x1F) + 1) << 3; j = frg[1] + 1; frg += 2;
  1425. for(m = 1; j && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); j--, y++, o += s)
  1426. for(p = o, l = 0; l < k; l++, p++, m <<= 1) {
  1427. if(m > 0x80) { frg++; m = 1; }
  1428. if(ssfn_dst.x + l >= 0 && (!w || ssfn_dst.x + l < w)) {
  1429. if(*frg & m) *p = ssfn_dst.fg; else
  1430. if(ssfn_dst.bg) *p = ssfn_dst.bg;
  1431. }
  1432. }
  1433. }
  1434. if(ssfn_dst.bg)
  1435. for(; y < chr[3] && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); y++, o += s) {
  1436. for(p = o, j = 0; j < chr[2] && (!w || ssfn_dst.x + j < w); j++, p++)
  1437. *p = ssfn_dst.bg;
  1438. }
  1439. ssfn_dst.x += chr[4]; ssfn_dst.y += chr[5];
  1440. return SSFN_OK;
  1441. }
  1442. #endif /* SSFN_CONSOLEBITMAP */
  1443. #ifdef __cplusplus
  1444. }
  1445. /*** SSFN C++ Wrapper Class ***/
  1446. #include <string>
  1447. namespace SSFN {
  1448. #ifndef SSFN_IMPLEMENTATION
  1449. class Font {
  1450. public:
  1451. Font();
  1452. ~Font();
  1453. public:
  1454. int Load(const std::string &data);
  1455. int Load(const void *data, int len);
  1456. int Select(int family, const std::string &name, int style, int size);
  1457. int Select(int family, const char *name, int style, int size);
  1458. int Render(ssfn_buf_t *dst, const std::string &str);
  1459. int Render(ssfn_buf_t *dst, const char *str);
  1460. int BBox(const std::string &str, int *w, int *h, int *left, int *top);
  1461. int BBox(const char *str, int *w, int *h, int *left, int *top);
  1462. ssfn_buf_t *Text(const std::string &str, unsigned int fg);
  1463. ssfn_buf_t *Text(const char *str, unsigned int fg);
  1464. int LineHeight();
  1465. int Mem();
  1466. const std::string ErrorStr(int err);
  1467. };
  1468. #else
  1469. class Font {
  1470. private:
  1471. ssfn_t ctx;
  1472. public:
  1473. Font() { SSFN_memset(&this->ctx, 0, sizeof(ssfn_t)); }
  1474. ~Font() { ssfn_free(&this->ctx); }
  1475. public:
  1476. int Load(const std::string &data) { return ssfn_load(&this->ctx,reinterpret_cast<const void*>(data.data())); }
  1477. int Load(const void *data) { return ssfn_load(&this->ctx, data); }
  1478. int Select(int family, const std::string &name, int style, int size)
  1479. { return ssfn_select(&this->ctx, family, (char*)name.data(), style, size); }
  1480. int Select(int family, char *name, int style, int size) { return ssfn_select(&this->ctx,family,name,style,size); }
  1481. int Render(ssfn_buf_t *dst, const std::string &str) { return ssfn_render(&this->ctx,dst,(const char *)str.data()); }
  1482. int Render(ssfn_buf_t *dst, const char *str) { return ssfn_render(&this->ctx, dst, str); }
  1483. int BBox(const std::string &str, int *w, int *h, int *left, int *top)
  1484. { return ssfn_bbox(&this->ctx, (const char *)str.data(), w, h, left, top); }
  1485. int BBox(const char *str, int *w, int *h, int *left, int *top) { return ssfn_bbox(&this->ctx,str,w,h,left,top); }
  1486. ssfn_buf_t *Text(const std::string &str, unsigned int fg)
  1487. { return ssfn_text(&this->ctx,(const char*)str.data(), fg); }
  1488. ssfn_buf_t *Text(const char *str, unsigned int fg) { return ssfn_text(&this->ctx, str, fg); }
  1489. int LineHeight() { return this->ctx.line ? this->ctx.line : this->ctx.size; }
  1490. int Mem() { return ssfn_mem(&this->ctx); }
  1491. const std::string ErrorStr(int err) { return std::string(ssfn_error(err)); }
  1492. };
  1493. #endif
  1494. }
  1495. #endif
  1496. /* */
  1497. /* */
  1498. #endif /* _SSFN_H_ */