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.
 
 
 
 
 
 

560 lines
16 KiB

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