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

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