sfndemo.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. * sfndemo.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 testing Scalable Screen Font renderer features demo
  27. *
  28. */
  29. #include <stdio.h>
  30. #include <stdint.h>
  31. #define SSFN_IMPLEMENTATION
  32. #define SSFN_PROFILING
  33. #define SSFN_CONSOLEBITMAP_TRUECOLOR
  34. /*#define SSFN_MAXLINES 4096*/
  35. #include "../ssfn.h"
  36. #if HAS_ZLIB
  37. #include <zlib.h>
  38. #endif
  39. #include <SDL.h>
  40. long int loadtim = 0;
  41. /**
  42. * Load a file
  43. */
  44. ssfn_font_t *load_file(char *filename, int *size)
  45. {
  46. char *fontdata = NULL;
  47. FILE *f;
  48. #if HAS_ZLIB
  49. unsigned char hdr[2];
  50. gzFile g;
  51. #endif
  52. #ifdef SSFN_PROFILING
  53. struct timeval tv0, tv1, tvd;
  54. gettimeofday(&tv0, NULL);
  55. #endif
  56. f = fopen(filename, "rb");
  57. if(!f) { fprintf(stderr,"unable to load %s\n", filename); exit(3); }
  58. *size = 0;
  59. #if HAS_ZLIB
  60. fread(&hdr, 2, 1, f);
  61. if(hdr[0]==0x1f && hdr[1]==0x8b) {
  62. fseek(f, -4L, SEEK_END);
  63. fread(size, 4, 1, f);
  64. } else {
  65. fseek(f, 0, SEEK_END);
  66. *size = (int)ftell(f);
  67. }
  68. fclose(f);
  69. g = gzopen(filename,"r");
  70. #else
  71. fseek(f, 0, SEEK_END);
  72. *size = (int)ftell(f);
  73. fseek(f, 0, SEEK_SET);
  74. #endif
  75. if(!*size) { fprintf(stderr,"unable to load %s\n", filename); exit(3); }
  76. fontdata = (char*)malloc(*size);
  77. if(!fontdata) { fprintf(stderr,"memory allocation error\n"); exit(2); }
  78. #if HAS_ZLIB
  79. gzread(g, fontdata, *size);
  80. gzclose(g);
  81. #else
  82. fread(fontdata, *size, 1, f);
  83. fclose(f);
  84. #endif
  85. #ifdef SSFN_PROFILING
  86. gettimeofday(&tv1, NULL);
  87. tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
  88. tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
  89. if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
  90. loadtim += (long int)(tvd.tv_sec * 1000000L + tvd.tv_usec);
  91. #endif
  92. return (ssfn_font_t*)fontdata;
  93. }
  94. /**
  95. * testing the SSFN library (normal renderer)
  96. */
  97. void do_test(SDL_Surface *screen, char *fontfn)
  98. {
  99. char *s;
  100. char *title="Scalable Screen Font 2.0 (SSFN2) Feature Demo";
  101. char *str0="Simple renderer आइऊईऋऌ 丕世丽乇 Многоязычный with GNU unifont (unscaled bitmap fonts only)";
  102. char *str1="Normal renderer आइऊईऋऌ 丕世丽乇 Многоязычный with GNU unifont (scaled to 1:1)";
  103. char *str2="Using UNICODE VGA but switching to GNU unifont आइऊईऋऌ for uncovered glyphs automatically";
  104. char *str3="Scaling bitmap fonts without antialiasing to black and white";
  105. char *str4="Scaling bitmap fonts with antialiasing and edge smoothing";
  106. char *str5="Vector based fonts are also supported of course";
  107. char *str6="%Applying #different @styles to !vector bitmap fonts";
  108. char *str7="%Applying #different @styles to !bitmap vector fonts";
  109. char *str8="Rendering vector font without antialiasing";
  110. char *str9="Rendering vector font with antialiasing";
  111. char *strA="#;$L Rendering vector font without kerning";
  112. char *strB="#;$L Rendering vector font with kerning";
  113. char *strC="FreeSerif #Italic #font and %Bold";
  114. char *strD="FreeSans #Italic #font and %Bold";
  115. char *strE="BitStream Vera #Italic and %Bold and !Bold+Italic";
  116. char *strF="(generated)";
  117. char *str10="(font provided)";
  118. char *str11="The compressed 😀 SSFN format supports bitmap based glyphs, vector based glyphs, and...";
  119. char *str12="->@-COLORFUL-PIXMAP-GLYPHS-=-ALSO>AVAILABLE-BY:->\n->THE-----------<SSFN>FORMAT-AND>RENDERER-;->=@->";
  120. char *str13="Vertical, left-to-right and right-to-left rendering (with flag, no BiDi state machine):";
  121. char *str14="אבגדהוזחט";
  122. char strM[128];
  123. int sintbl[] = { 0, 1, 5, 9, 14, 21, 28, 36, 56, 67, 78, 67, 56, 46, 36, 28, 21, 14, 9, 5, 1 };
  124. int ret, size, i;
  125. ssfn_t ctx;
  126. /* initialize the normal renderer */
  127. memset(&ctx, 0, sizeof(ssfn_t));
  128. /* set up destination buffer */
  129. ssfn_dst.ptr = (uint8_t*)screen->pixels;
  130. ssfn_dst.p = screen->pitch;
  131. ssfn_dst.w = screen->w;
  132. ssfn_dst.h = screen->h;
  133. ssfn_dst.fg = 0xFF202020;
  134. ssfn_dst.bg = 0;
  135. /*ssfn_dst.bg = 0xFF20FF20;*/
  136. /* load and select a font */
  137. ssfn_src = load_file("../fonts/unifont.sfn.gz", &size);
  138. ret = ssfn_load(&ctx, ssfn_src);
  139. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: unifont.sfn.gz err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  140. ret = ssfn_load(&ctx, load_file(fontfn ? fontfn : "../fonts/FreeSerif.sfn", &size));
  141. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSerif.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  142. ret = ssfn_load(&ctx, load_file("../fonts/FreeSans.sfn", &size));
  143. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSans.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  144. /* title */
  145. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 32);
  146. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  147. s = title;
  148. ssfn_dst.x = 55;
  149. ssfn_dst.y = 32;
  150. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  151. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  152. /* testing simple renderer with unscaled bitmap fonts */
  153. s = str0;
  154. ssfn_dst.x = 8;
  155. ssfn_dst.y = 48;
  156. ret = SSFN_OK;
  157. while(*s && ret == SSFN_OK)
  158. ssfn_putc(ssfn_utf8(&s));
  159. if(ret != SSFN_OK) { fprintf(stderr, "ssfn putc error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  160. /* testing normal renderer with unscaled bitmap fonts */
  161. ret = ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  162. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  163. s = str1;
  164. ssfn_dst.x = 8;
  165. ssfn_dst.y = 80;
  166. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  167. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  168. ssfn_free(&ctx);
  169. /* load uvga first, then unifont */
  170. ret = ssfn_load(&ctx, load_file("../fonts/u_vga16.sfn.gz", &size));
  171. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: u_vga16.sfn.gz err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  172. ret = ssfn_load(&ctx, ssfn_src);
  173. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  174. ret = ssfn_load(&ctx, load_file("../fonts/FreeSerif.sfn", &size));
  175. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSerif.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  176. ret = ssfn_load(&ctx, load_file("../fonts/FreeSans.sfn", &size));
  177. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSans.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  178. ret = ssfn_load(&ctx, load_file("../fonts/VeraR.sfn", &size));
  179. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: VeraR.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  180. ret = ssfn_load(&ctx, load_file("../fonts/emoji.sfn", &size));
  181. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: emoji.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  182. /* testing switching to other fonts when glyph not found */
  183. ret = ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  184. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  185. s = str2;
  186. ssfn_dst.x = 8;
  187. ssfn_dst.y = 100;
  188. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  189. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  190. /* scaling demos */
  191. s = str3;
  192. ssfn_dst.x = 8;
  193. ssfn_dst.y = 135;
  194. i = 0;
  195. do {
  196. ret = ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE | SSFN_STYLE_NOAA,
  197. 10 + sintbl[(i+1)%(sizeof(sintbl)/sizeof(sintbl[0]))]/2);
  198. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  199. i++;
  200. ret = ssfn_render(&ctx, &ssfn_dst, s);
  201. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  202. s += ret;
  203. } while(ret);
  204. s = str4;
  205. ssfn_dst.x = 8;
  206. ssfn_dst.y = 170;
  207. i = 0;
  208. do {
  209. ret = ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE,
  210. 10 + sintbl[(i+1)%(sizeof(sintbl)/sizeof(sintbl[0]))]/2);
  211. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  212. i++;
  213. ret = ssfn_render(&ctx, &ssfn_dst, s);
  214. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  215. s += ret;
  216. } while(ret);
  217. s = str5;
  218. ssfn_dst.x = 8;
  219. ssfn_dst.y = 232;
  220. i = 0;
  221. do {
  222. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE,
  223. 10 + 2*sintbl[i%(sizeof(sintbl)/sizeof(sintbl[0]))]/2);
  224. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  225. i++;
  226. ret = ssfn_render(&ctx, &ssfn_dst, s);
  227. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  228. s += ret;
  229. } while(ret);
  230. /* bitmap style tests */
  231. s = str6;
  232. ssfn_dst.x = 8;
  233. ssfn_dst.y = 270;
  234. while(*s) {
  235. if(*s=='@') { s++; ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_UNDERLINE | SSFN_STYLE_NOCACHE, 16); continue; }
  236. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 16); continue; }
  237. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 16); continue; }
  238. if(*s=='!') { s++; ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_STHROUGH | SSFN_STYLE_NOCACHE, 16); continue; }
  239. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_MONOSPACE, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16); }
  240. ret = ssfn_render(&ctx, &ssfn_dst, s);
  241. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  242. s += ret;
  243. };
  244. s = str7;
  245. ssfn_dst.x = 420;
  246. ssfn_dst.y = 270;
  247. while(*s) {
  248. if(*s=='@') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_UNDERLINE | SSFN_STYLE_NOCACHE, 16); continue; }
  249. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 16); continue; }
  250. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 16); continue; }
  251. if(*s=='!') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_STHROUGH | SSFN_STYLE_NOCACHE, 16); continue; }
  252. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16); }
  253. ret = ssfn_render(&ctx, &ssfn_dst, s);
  254. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  255. s += ret;
  256. };
  257. /* without and with antialias */
  258. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOAA | SSFN_STYLE_NOCACHE, 16);
  259. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  260. s = str8;
  261. ssfn_dst.x = 8;
  262. ssfn_dst.y = 290;
  263. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  264. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  265. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  266. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  267. s = str9;
  268. ssfn_dst.x = 8;
  269. ssfn_dst.y = 310;
  270. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  271. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  272. /* without and with kerning */
  273. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOKERN | SSFN_STYLE_NOCACHE, 16);
  274. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  275. s = strA;
  276. ssfn_dst.x = 420;
  277. ssfn_dst.y = 290;
  278. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  279. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  280. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  281. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  282. s = strB;
  283. ssfn_dst.x = 420;
  284. ssfn_dst.y = 310;
  285. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  286. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  287. /* italic and bold in bigger */
  288. s = strC;
  289. ssfn_dst.x = 8;
  290. ssfn_dst.y = 340;
  291. ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27);
  292. while(*s) {
  293. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 27); continue; }
  294. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 27); continue; }
  295. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27); }
  296. ret = ssfn_render(&ctx, &ssfn_dst, s);
  297. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  298. s += ret;
  299. };
  300. s = strD;
  301. ssfn_dst.x = 400;
  302. ssfn_dst.y = 340;
  303. ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27);
  304. while(*s) {
  305. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 27); continue; }
  306. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 27); continue; }
  307. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27); }
  308. ret = ssfn_render(&ctx, &ssfn_dst, s);
  309. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  310. s += ret;
  311. };
  312. s = strF;
  313. ssfn_dst.x = 680;
  314. ssfn_dst.y = 361;
  315. ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  316. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  317. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  318. s = strE;
  319. ssfn_dst.x = 10;
  320. ssfn_dst.y = 365;
  321. ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 20);
  322. while(*s) {
  323. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 20); continue; }
  324. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 20); continue; }
  325. if(*s=='!') { s++; ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_BOLD | SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 20); continue; }
  326. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 20); }
  327. ret = ssfn_render(&ctx, &ssfn_dst, s);
  328. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  329. s += ret;
  330. };
  331. ret = ssfn_load(&ctx, load_file("../fonts/FreeSerifI.sfn", &size));
  332. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSerifI.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  333. ret = ssfn_load(&ctx, load_file("../fonts/FreeSerifB.sfn", &size));
  334. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSerifB.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  335. ret = ssfn_load(&ctx, load_file("../fonts/FreeSansI.sfn", &size));
  336. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSansI.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  337. ret = ssfn_load(&ctx, load_file("../fonts/FreeSansB.sfn", &size));
  338. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: FreeSansB.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  339. ret = ssfn_load(&ctx, load_file("../fonts/VeraB.sfn", &size));
  340. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: VeraB.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  341. ret = ssfn_load(&ctx, load_file("../fonts/VeraI.sfn", &size));
  342. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: VeraI.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  343. ret = ssfn_load(&ctx, load_file("../fonts/VeraBI.sfn", &size));
  344. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: VeraBI.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  345. ret = ssfn_load(&ctx, load_file("../fonts/stoneage.sfn", &size));
  346. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: stoneage.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  347. ret = ssfn_load(&ctx, load_file("../fonts/chrome.sfn", &size));
  348. if(ret != SSFN_OK) { fprintf(stderr, "ssfn load error: chrome.sfn err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  349. s = strC;
  350. ssfn_dst.x = 8;
  351. ssfn_dst.y = 400;
  352. ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27);
  353. while(*s) {
  354. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 27); continue; }
  355. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 27); continue; }
  356. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27); }
  357. ret = ssfn_render(&ctx, &ssfn_dst, s);
  358. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  359. s += ret;
  360. };
  361. s = strD;
  362. ssfn_dst.x = 400;
  363. ssfn_dst.y = 400;
  364. ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27);
  365. while(*s) {
  366. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_ITALIC | SSFN_STYLE_NOCACHE, 27); continue; }
  367. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 27); continue; }
  368. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 27); }
  369. ret = ssfn_render(&ctx, &ssfn_dst, s);
  370. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  371. s += ret;
  372. };
  373. s = str10;
  374. ssfn_dst.x = 680;
  375. ssfn_dst.y = 421;
  376. ssfn_select(&ctx, SSFN_FAMILY_SANS, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  377. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  378. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  379. s = strE;
  380. ssfn_dst.x = 10;
  381. ssfn_dst.y = 425;
  382. ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 20);
  383. while(*s) {
  384. if(*s=='#') { s++; ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans Oblique", SSFN_STYLE_NOCACHE, 20); continue; }
  385. if(*s=='%') { s++; ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans Bold", SSFN_STYLE_NOCACHE, 20); continue; }
  386. if(*s=='!') { s++; ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans Bold Oblique", SSFN_STYLE_NOCACHE, 20); continue; }
  387. if(*s==' ') { ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Bitstream Vera Sans", SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 20); }
  388. ret = ssfn_render(&ctx, &ssfn_dst, s);
  389. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  390. s += ret;
  391. };
  392. /* pixel map fonts features */
  393. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  394. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  395. s = str11;
  396. ssfn_dst.x = 8;
  397. ssfn_dst.y = 460;
  398. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  399. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  400. s = str12;
  401. ssfn_dst.x = 8;
  402. ssfn_dst.y = 485;
  403. ret = ssfn_select(&ctx, SSFN_FAMILY_DECOR, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_ABS_SIZE | SSFN_STYLE_NOCACHE, 16);
  404. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  405. while(*s) {
  406. if(*s=='>') { ssfn_select(&ctx, SSFN_FAMILY_DECOR, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_ABS_SIZE | SSFN_STYLE_NOCACHE, 16); }
  407. if(*s=='<') { ssfn_select(&ctx, SSFN_FAMILY_BYNAME, "Retro Chrome", SSFN_STYLE_REGULAR | SSFN_STYLE_ABS_SIZE | SSFN_STYLE_NOCACHE, 24); ssfn_dst.x -= 164; s++; continue; }
  408. if(*s=='\n') { s++; ssfn_dst.x = 48; ssfn_dst.y += 28; continue; }
  409. ret = ssfn_render(&ctx, &ssfn_dst, s);
  410. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  411. s += ret;
  412. };
  413. /* writing directions */
  414. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  415. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  416. s = str13;
  417. ssfn_dst.x = 8;
  418. ssfn_dst.y = 550;
  419. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  420. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  421. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_RTL | SSFN_STYLE_NOCACHE, 28);
  422. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  423. s = str14;
  424. ssfn_dst.x = screen->w - 8;
  425. ssfn_dst.y = 550;
  426. while((ret = ssfn_render(&ctx, &ssfn_dst, s)) > 0) s += ret;
  427. if(ret != SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  428. /* free resources */
  429. sprintf(strM, "Memory "
  430. #ifdef SSFN_MAXLINES
  431. "required"
  432. #else
  433. "allocated"
  434. #endif
  435. ": @%d bytes. All of this from a 30k of code in a single ANSI C header!",
  436. ssfn_mem(&ctx));
  437. ret = ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16);
  438. if(ret != SSFN_OK) { fprintf(stderr, "ssfn select error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  439. s = strM;
  440. ssfn_dst.x = 32;
  441. ssfn_dst.y = 585;
  442. while(*s) {
  443. if(*s=='@') { s++; ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_BOLD | SSFN_STYLE_NOCACHE, 16); continue; }
  444. if(*s=='.') { ssfn_select(&ctx, SSFN_FAMILY_SERIF, NULL, SSFN_STYLE_REGULAR | SSFN_STYLE_NOCACHE, 16); }
  445. ret = ssfn_render(&ctx, &ssfn_dst, s);
  446. if(ret < SSFN_OK) { fprintf(stderr, "ssfn render error: err=%d %s\n", ret, ssfn_error(ret)); exit(2); }
  447. s += ret;
  448. };
  449. printf("Memory allocated: %d, sizeof(ssfn_t) = %d\n\n", ssfn_mem(&ctx), (int)sizeof(ssfn_t));
  450. printf("File load time: %3ld.%06ld sec\n", loadtim / 1000000L, loadtim % 1000000L);
  451. printf("Character lookup: %3ld.%06ld sec\n", ctx.lookup / 1000000L, ctx.lookup % 1000000L);
  452. printf("Rasterization: %3ld.%06ld sec\n", ctx.raster / 1000000L, ctx.raster % 1000000L);
  453. printf("Blitting: %3ld.%06ld sec\n", ctx.blit / 1000000L, ctx.blit % 1000000L);
  454. printf("Kerning: %3ld.%06ld sec\n", ctx.kern / 1000000L, ctx.kern % 1000000L);
  455. loadtim = ctx.blit - ctx.raster;
  456. if(loadtim < 0) { i = '-'; loadtim = -loadtim; } else i = ' ';
  457. printf("Raster/blit diff: %c%3ld.%06ld sec\n", i, loadtim / 1000000L, loadtim % 1000000L);
  458. ssfn_free(&ctx);
  459. free(ssfn_src);
  460. }
  461. /**
  462. * Main procedure
  463. */
  464. int main(int argc __attribute__((unused)), char **argv)
  465. {
  466. SDL_Window *window;
  467. SDL_Surface *screen;
  468. SDL_Event event;
  469. if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTS)) {
  470. fprintf(stderr,"SDL error %s\n", SDL_GetError());
  471. return 2;
  472. }
  473. window = SDL_CreateWindow("SSFN normal renderer bitmap font test",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,800,600,0);
  474. screen = SDL_GetWindowSurface(window);
  475. memset(screen->pixels, 0xF8, screen->pitch*screen->h);
  476. do_test(screen, argv[1]);
  477. do{ SDL_UpdateWindowSurface(window); SDL_Delay(10); } while(SDL_WaitEvent(&event) && event.type != SDL_QUIT &&
  478. event.type != SDL_MOUSEBUTTONDOWN && event.type != SDL_KEYDOWN);
  479. SDL_DestroyWindow(window);
  480. SDL_Quit();
  481. return 0;
  482. }