You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. * libcucul Canvas for ultrafast compositing of Unicode letters
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. /*
  14. * This file contains font handling functions.
  15. */
  16. #include "config.h"
  17. #include "common.h"
  18. #if !defined(__KERNEL__)
  19. # if defined(HAVE_ENDIAN_H)
  20. # include <endian.h>
  21. # endif
  22. # if defined(HAVE_ARPA_INET_H)
  23. # include <arpa/inet.h>
  24. # elif defined(HAVE_NETINET_IN_H)
  25. # include <netinet/in.h>
  26. # endif
  27. # if defined(HAVE_ERRNO_H)
  28. # include <errno.h>
  29. # endif
  30. # include <stdio.h>
  31. # include <stdlib.h>
  32. # include <string.h>
  33. #endif
  34. #include "cucul.h"
  35. #include "cucul_internals.h"
  36. /* Internal fonts */
  37. #include "font_mono9.h"
  38. #include "font_monobold12.h"
  39. /* Helper structures for font loading */
  40. #if !defined(_DOXYGEN_SKIP_ME)
  41. struct font_header
  42. {
  43. uint32_t control_size, data_size;
  44. uint16_t version, blocks;
  45. uint32_t glyphs;
  46. uint16_t bpp, width, height, flags;
  47. };
  48. struct block_info
  49. {
  50. uint32_t start, stop, index;
  51. };
  52. struct glyph_info
  53. {
  54. uint16_t width, height;
  55. uint32_t data_offset;
  56. };
  57. struct cucul_font
  58. {
  59. struct font_header header;
  60. struct block_info *block_list;
  61. struct glyph_info *glyph_list;
  62. uint8_t *font_data;
  63. uint8_t *private;
  64. };
  65. #endif
  66. #define DECLARE_UNPACKGLYPH(bpp) \
  67. static inline void \
  68. unpack_glyph ## bpp(uint8_t *glyph, uint8_t *packed_data, \
  69. unsigned int n) \
  70. { \
  71. unsigned int i; \
  72. \
  73. for(i = 0; i < n; i++) \
  74. { \
  75. uint8_t pixel = packed_data[i / (8 / bpp)]; \
  76. pixel >>= bpp * ((8 / bpp) - 1 - (i % (8 / bpp))); \
  77. pixel %= (1 << bpp); \
  78. pixel *= 0xff / ((1 << bpp) - 1); \
  79. *glyph++ = pixel; \
  80. } \
  81. }
  82. DECLARE_UNPACKGLYPH(4)
  83. DECLARE_UNPACKGLYPH(2)
  84. DECLARE_UNPACKGLYPH(1)
  85. /** \brief Load a font from memory for future use.
  86. *
  87. * This function loads a font and returns a handle to its internal
  88. * structure. The handle can then be used with cucul_render_canvas()
  89. * for bitmap output.
  90. *
  91. * Internal fonts can also be loaded: if \c size is set to 0, \c data must
  92. * be a string containing the internal font name.
  93. *
  94. * If \c size is non-zero, the \c size bytes of memory at address \c data
  95. * are loaded as a font. This memory are must not be freed by the calling
  96. * program until the font handle has been freed with cucul_free_font().
  97. *
  98. * If an error occurs, NULL is returned and \b errno is set accordingly:
  99. * - \c ENOENT Requested built-in font does not exist.
  100. * - \c EINVAL Invalid font data in memory area.
  101. * - \c ENOMEM Not enough memory to allocate font structure.
  102. *
  103. * \param data The memory area containing the font or its name.
  104. * \param size The size of the memory area, or 0 if the font name is given.
  105. * \return A font handle or NULL in case of error.
  106. */
  107. cucul_font_t *cucul_load_font(void const *data, unsigned int size)
  108. {
  109. cucul_font_t *f;
  110. unsigned int i;
  111. if(size == 0)
  112. {
  113. if(!strcasecmp(data, "Monospace 9"))
  114. return cucul_load_font((char *)&mono9_data, mono9_size);
  115. if(!strcasecmp(data, "Monospace Bold 12"))
  116. return cucul_load_font((char *)&monobold12_data, monobold12_size);
  117. #if defined(HAVE_ERRNO_H)
  118. errno = ENOENT;
  119. #endif
  120. return NULL;
  121. }
  122. if(size < sizeof(struct font_header))
  123. {
  124. #if defined(HAVE_ERRNO_H)
  125. errno = EINVAL;
  126. #endif
  127. return NULL;
  128. }
  129. f = malloc(sizeof(cucul_font_t));
  130. if(!f)
  131. {
  132. #if defined(HAVE_ERRNO_H)
  133. errno = ENOMEM;
  134. #endif
  135. return NULL;
  136. }
  137. f->private = (void *)(uintptr_t)data;
  138. memcpy(&f->header, f->private + 8, sizeof(struct font_header));
  139. f->header.control_size = hton32(f->header.control_size);
  140. f->header.data_size = hton32(f->header.data_size);
  141. f->header.version = hton16(f->header.version);
  142. f->header.blocks = hton16(f->header.blocks);
  143. f->header.glyphs = hton32(f->header.glyphs);
  144. f->header.bpp = hton16(f->header.bpp);
  145. f->header.width = hton16(f->header.width);
  146. f->header.height = hton16(f->header.height);
  147. f->header.flags = hton16(f->header.flags);
  148. if(size != 8 + f->header.control_size + f->header.data_size
  149. || (f->header.bpp != 8 && f->header.bpp != 4 &&
  150. f->header.bpp != 2 && f->header.bpp != 1)
  151. || (f->header.flags & 1) == 0)
  152. {
  153. free(f);
  154. #if defined(HAVE_ERRNO_H)
  155. errno = EINVAL;
  156. #endif
  157. return NULL;
  158. }
  159. f->block_list = malloc(f->header.blocks * sizeof(struct block_info));
  160. if(!f->block_list)
  161. {
  162. free(f);
  163. #if defined(HAVE_ERRNO_H)
  164. errno = ENOMEM;
  165. #endif
  166. return NULL;
  167. }
  168. memcpy(f->block_list,
  169. f->private + 8 + sizeof(struct font_header),
  170. f->header.blocks * sizeof(struct block_info));
  171. for(i = 0; i < f->header.blocks; i++)
  172. {
  173. f->block_list[i].start = hton32(f->block_list[i].start);
  174. f->block_list[i].stop = hton32(f->block_list[i].stop);
  175. f->block_list[i].index = hton32(f->block_list[i].index);
  176. if(f->block_list[i].start > f->block_list[i].stop
  177. || (i > 0 && f->block_list[i].start < f->block_list[i - 1].stop)
  178. || f->block_list[i].index >= f->header.glyphs)
  179. {
  180. free(f->block_list);
  181. free(f);
  182. #if defined(HAVE_ERRNO_H)
  183. errno = EINVAL;
  184. #endif
  185. return NULL;
  186. }
  187. }
  188. f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info));
  189. if(!f->glyph_list)
  190. {
  191. free(f->block_list);
  192. free(f);
  193. #if defined(HAVE_ERRNO_H)
  194. errno = ENOMEM;
  195. #endif
  196. return NULL;
  197. }
  198. memcpy(f->glyph_list,
  199. f->private + 8 + sizeof(struct font_header)
  200. + f->header.blocks * sizeof(struct block_info),
  201. f->header.glyphs * sizeof(struct glyph_info));
  202. for(i = 0; i < f->header.glyphs; i++)
  203. {
  204. f->glyph_list[i].width = hton16(f->glyph_list[i].width);
  205. f->glyph_list[i].height = hton16(f->glyph_list[i].height);
  206. f->glyph_list[i].data_offset = hton32(f->glyph_list[i].data_offset);
  207. if(f->glyph_list[i].data_offset >= f->header.data_size
  208. || f->glyph_list[i].data_offset
  209. + (f->glyph_list[i].width * f->glyph_list[i].height *
  210. f->header.bpp + 7) / 8 > f->header.data_size)
  211. {
  212. free(f->glyph_list);
  213. free(f->block_list);
  214. free(f);
  215. #if defined(HAVE_ERRNO_H)
  216. errno = EINVAL;
  217. #endif
  218. return NULL;
  219. }
  220. }
  221. f->font_data = f->private + 8 + f->header.control_size;
  222. return f;
  223. }
  224. /** \brief Get available builtin fonts
  225. *
  226. * Return a list of available builtin fonts. The list is a NULL-terminated
  227. * array of strings.
  228. *
  229. * This function never fails.
  230. *
  231. * \return An array of strings.
  232. */
  233. char const * const * cucul_get_font_list(void)
  234. {
  235. static char const * const list[] =
  236. {
  237. "Monospace 9",
  238. "Monospace Bold 12",
  239. NULL
  240. };
  241. return list;
  242. }
  243. /** \brief Get a font's maximum glyph width.
  244. *
  245. * This function returns the maximum value for the current font's glyphs
  246. *
  247. * This function never fails.
  248. *
  249. * \param f The font, as returned by cucul_load_font()
  250. * \return The maximum glyph width.
  251. */
  252. unsigned int cucul_get_font_width(cucul_font_t *f)
  253. {
  254. return f->header.width;
  255. }
  256. /** \brief Get a font's maximum glyph height.
  257. *
  258. * This function returns the maximum value for the current font's glyphs
  259. *
  260. * This function never fails.
  261. *
  262. * \param f The font, as returned by cucul_load_font()
  263. * \return The maximum glyph height.
  264. */
  265. unsigned int cucul_get_font_height(cucul_font_t *f)
  266. {
  267. return f->header.height;
  268. }
  269. /** \brief Free a font structure.
  270. *
  271. * This function frees all data allocated by cucul_load_font(). The
  272. * font structure is no longer usable by other libcucul functions. Once
  273. * this function has returned, the memory area that was given to
  274. * cucul_load_font() can be freed.
  275. *
  276. * This function never fails.
  277. *
  278. * \param f The font, as returned by cucul_load_font()
  279. * \return This function always returns 0.
  280. */
  281. int cucul_free_font(cucul_font_t *f)
  282. {
  283. free(f->glyph_list);
  284. free(f->block_list);
  285. free(f);
  286. return 0;
  287. }
  288. /** \brief Render the canvas onto an image buffer.
  289. *
  290. * This function renders the given canvas on an image buffer using a specific
  291. * font. The pixel format is fixed (32-bit ARGB, 8 bits for each component).
  292. *
  293. * The required image width can be computed using
  294. * cucul_get_canvas_width() and cucul_get_font_width(). The required
  295. * height can be computed using cucul_get_canvas_height() and
  296. * cucul_get_font_height().
  297. *
  298. * Glyphs that do not fit in the image buffer are currently not rendered at
  299. * all. They may be cropped instead in future versions.
  300. *
  301. * This function never fails.
  302. *
  303. * \param cv The canvas to render
  304. * \param f The font, as returned by cucul_load_font()
  305. * \param buf The image buffer
  306. * \param width The width (in pixels) of the image buffer
  307. * \param height The height (in pixels) of the image buffer
  308. * \param pitch The pitch (in bytes) of an image buffer line.
  309. * \return This function always returns 0.
  310. */
  311. int cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f,
  312. void *buf, unsigned int width,
  313. unsigned int height, unsigned int pitch)
  314. {
  315. uint8_t *glyph = NULL;
  316. unsigned int x, y, xmax, ymax;
  317. if(f->header.bpp != 8)
  318. glyph = malloc(f->header.width * f->header.height);
  319. if(width < cv->width * f->header.width)
  320. xmax = width / f->header.width;
  321. else
  322. xmax = cv->width;
  323. if(height < cv->height * f->header.height)
  324. ymax = height / f->header.height;
  325. else
  326. ymax = cv->height;
  327. for(y = 0; y < ymax; y++)
  328. {
  329. for(x = 0; x < xmax; x++)
  330. {
  331. uint8_t argb[8];
  332. unsigned int starty = y * f->header.height;
  333. unsigned int startx = x * f->header.width;
  334. uint32_t ch = cv->chars[y * cv->width + x];
  335. uint32_t attr = cv->attr[y * cv->width + x];
  336. unsigned int b, i, j;
  337. struct glyph_info *g;
  338. /* Find the Unicode block where our glyph lies */
  339. for(b = 0; b < f->header.blocks; b++)
  340. {
  341. if(ch < f->block_list[b].start)
  342. {
  343. b = f->header.blocks;
  344. break;
  345. }
  346. if(ch < f->block_list[b].stop)
  347. break;
  348. }
  349. /* Glyph not in font? Skip it. */
  350. if(b == f->header.blocks)
  351. continue;
  352. g = &f->glyph_list[f->block_list[b].index
  353. + ch - f->block_list[b].start];
  354. _cucul_argb32_to_argb4(attr, argb);
  355. /* Step 1: unpack glyph */
  356. switch(f->header.bpp)
  357. {
  358. case 8:
  359. glyph = f->font_data + g->data_offset;
  360. break;
  361. case 4:
  362. unpack_glyph4(glyph, f->font_data + g->data_offset,
  363. g->width * g->height);
  364. break;
  365. case 2:
  366. unpack_glyph2(glyph, f->font_data + g->data_offset,
  367. g->width * g->height);
  368. break;
  369. case 1:
  370. unpack_glyph1(glyph, f->font_data + g->data_offset,
  371. g->width * g->height);
  372. break;
  373. }
  374. /* Step 2: render glyph using colour attribute */
  375. for(j = 0; j < g->height; j++)
  376. {
  377. uint8_t *line = buf;
  378. line += (starty + j) * pitch + 4 * startx;
  379. for(i = 0; i < g->width; i++)
  380. {
  381. uint8_t *pixel = line + 4 * i;
  382. uint32_t p, q, t;
  383. p = glyph[j * g->width + i];
  384. q = 0xff - p;
  385. for(t = 0; t < 4; t++)
  386. pixel[t] = (((q * argb[t]) + (p * argb[4 + t])) / 0xf);
  387. }
  388. }
  389. }
  390. }
  391. if(f->header.bpp != 8)
  392. free(glyph);
  393. return 0;
  394. }
  395. /** \brief Render the given character onto given buffer
  396. *
  397. * This function renders the given character on an image buffer using a specific
  398. * font. The pixel format is fixed (8 bits per pixel).
  399. *
  400. * The required buffer width can be computed using
  401. * cucul_get_canvas_width() and cucul_get_font_width(). The required
  402. * height can be computed using cucul_get_canvas_height() and
  403. * cucul_get_font_height().
  404. *
  405. * Glyphs that do not fit in the image buffer are currently not rendered at
  406. * all. They may be cropped instead in future versions.
  407. *
  408. * This function never fails.
  409. *
  410. * \param f The font, as returned by cucul_load_font()
  411. * \param ch The character to render
  412. * \param buf The image buffer
  413. * \param width The width (in pixels) of the image buffer
  414. * \param height The height (in pixels) of the image buffer
  415. * \return This function return 1 if glyph is succesfully renderer, 0 otherwise
  416. */
  417. int cucul_render_glyph(cucul_font_t *f, unsigned int ch, void *buffer,
  418. unsigned int width, unsigned int height)
  419. {
  420. unsigned int b;
  421. struct glyph_info *g;
  422. uint8_t *glyph = buffer;
  423. /* Find the Unicode block where our glyph lies */
  424. for(b = 0; b < f->header.blocks; b++)
  425. {
  426. if(ch < f->block_list[b].start)
  427. {
  428. b = f->header.blocks;
  429. break;
  430. }
  431. if(ch < f->block_list[b].stop) {
  432. break;
  433. }
  434. }
  435. /* Glyph not in font? Skip it. */
  436. if(b == f->header.blocks)
  437. return 0;
  438. g = &f->glyph_list[f->block_list[b].index
  439. + ch - f->block_list[b].start];
  440. /* Step 1: unpack glyph */
  441. switch(f->header.bpp)
  442. {
  443. case 8:
  444. glyph = f->font_data + g->data_offset;
  445. break;
  446. case 4:
  447. unpack_glyph4(glyph, f->font_data + g->data_offset,
  448. g->width * g->height);
  449. break;
  450. case 2:
  451. unpack_glyph2(glyph, f->font_data + g->data_offset,
  452. g->width * g->height);
  453. break;
  454. case 1:
  455. unpack_glyph1(glyph, f->font_data + g->data_offset,
  456. g->width * g->height);
  457. break;
  458. }
  459. return 1;
  460. }
  461. /*
  462. * The libcaca font format, version 1
  463. * ----------------------------------
  464. *
  465. * All types are big endian.
  466. *
  467. * struct
  468. * {
  469. * uint8_t caca_header[4]; // "CACA"
  470. * uint8_t caca_file_type[4]; // "FONT"
  471. *
  472. * font_header:
  473. * uint32_t control_size; // Control size (font_data - font_header)
  474. * uint32_t data_size; // Data size (EOF - font_data)
  475. *
  476. * uint16_t version; // Font format version
  477. * // bit 0: set to 1 if font is compatible
  478. * // with version 1 of the format
  479. * // bits 1-15: unused yet, must be 0
  480. *
  481. * uint16_t blocks; // Number of blocks in the font
  482. * uint32_t glyphs; // Total number of glyphs in the font
  483. *
  484. * uint16_t bpp; // Bits per pixel for glyph data (valid
  485. * // Values are 1, 2, 4 and 8)
  486. * uint16_t width; // Maximum glyph width
  487. * uint16_t height; // Maximum glyph height
  488. *
  489. * uint16_t flags; // Feature flags
  490. * // bit 0: set to 1 if font is fixed width
  491. * // bits 1-15: unused yet, must be 0
  492. *
  493. * block_info:
  494. * struct
  495. * {
  496. * uint32_t start; // Unicode index of the first glyph
  497. * uint32_t stop; // Unicode index of the last glyph + 1
  498. * uint32_t index; // Glyph info index of the first glyph
  499. * }
  500. * block_list[blocks];
  501. *
  502. * glyph_info:
  503. * struct
  504. * {
  505. * uint16_t width; // Glyph width in pixels
  506. * uint16_t height; // Glyph height in pixels
  507. * uint32_t data_offset; // Offset (starting from data) to the data
  508. * // for the first character
  509. * }
  510. * glyph_list[glyphs];
  511. *
  512. * extension_1:
  513. * extension_2:
  514. * ...
  515. * extension_N:
  516. * ... // reserved for future use
  517. *
  518. * font_data:
  519. * uint8_t data[data_size]; // glyph data
  520. * };
  521. */