Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

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