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

377 строки
11 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. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file font.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Colour handling
  15. *
  16. * This file contains font handling functions.
  17. */
  18. #include "config.h"
  19. #if !defined(__KERNEL__)
  20. # if defined(HAVE_ENDIAN_H)
  21. # include <endian.h>
  22. # endif
  23. # include <stdio.h>
  24. # include <stdlib.h>
  25. # include <string.h>
  26. # include <arpa/inet.h>
  27. #endif
  28. #include "cucul.h"
  29. #include "cucul_internals.h"
  30. /* Internal fonts */
  31. uint8_t const font_monospace9[] =
  32. #include "font_monospace9.h"
  33. ;
  34. struct font_header
  35. {
  36. uint32_t control_size, data_size;
  37. uint16_t version, blocks;
  38. uint32_t glyphs;
  39. uint16_t bpp, width, height, flags;
  40. };
  41. struct block_info
  42. {
  43. uint32_t start, stop, index;
  44. };
  45. struct glyph_info
  46. {
  47. uint16_t width, height;
  48. uint32_t data_offset;
  49. };
  50. struct cucul_font
  51. {
  52. struct font_header header;
  53. struct block_info *block_list;
  54. struct glyph_info *glyph_list;
  55. uint8_t *font_data;
  56. uint8_t *private;
  57. };
  58. #define DECLARE_UNPACKGLYPH(bpp) \
  59. static inline void \
  60. unpack_glyph ## bpp(uint8_t *glyph, uint8_t *packed_data, \
  61. unsigned int n) \
  62. { \
  63. unsigned int i; \
  64. \
  65. for(i = 0; i < n; i++) \
  66. { \
  67. uint8_t pixel = packed_data[i / (8 / bpp)]; \
  68. pixel >>= bpp * ((8 / bpp) - 1 - (i % (8 / bpp))); \
  69. pixel %= (1 << bpp); \
  70. pixel *= 0xff / ((1 << bpp) - 1); \
  71. *glyph++ = pixel; \
  72. } \
  73. }
  74. DECLARE_UNPACKGLYPH(4)
  75. DECLARE_UNPACKGLYPH(2)
  76. DECLARE_UNPACKGLYPH(1)
  77. /** \brief Load a font from memory for future use.
  78. *
  79. * This function loads a font and returns a handle to its internal
  80. * structure. The handle can then be used with \e cucul_render_canvas()
  81. * for bitmap output.
  82. *
  83. * Internal fonts can also be loaded: if \e size is set to 0, \e data must
  84. * be a string containing the internal font name.
  85. *
  86. * If \e size is non-zero, the \e size bytes of memory at address \e data
  87. * are loaded as a font. This memory are must not be freed by the calling
  88. * program until the font handle has been freed with \e cucul_free_font().
  89. *
  90. * \param data The memory area containing the font or its name.
  91. * \param size The size of the memory area, or 0 if the font name is given.
  92. * \return A font handle or NULL in case of error.
  93. */
  94. struct cucul_font *cucul_load_font(void const *data, unsigned int size)
  95. {
  96. struct cucul_font *f;
  97. unsigned int i;
  98. if(size == 0)
  99. return cucul_load_font(font_monospace9, 150000); /* FIXME */
  100. f = malloc(sizeof(struct cucul_font));
  101. f->private = (void *)(uintptr_t)data;
  102. memcpy(&f->header, f->private + 8, sizeof(struct font_header));
  103. f->header.control_size = htonl(f->header.control_size);
  104. f->header.data_size = htonl(f->header.data_size);
  105. f->header.version = htons(f->header.version);
  106. f->header.blocks = htons(f->header.blocks);
  107. f->header.glyphs = htonl(f->header.glyphs);
  108. f->header.bpp = htons(f->header.bpp);
  109. f->header.width = htons(f->header.width);
  110. f->header.height = htons(f->header.height);
  111. f->header.flags = htons(f->header.flags);
  112. f->block_list = malloc(f->header.blocks * sizeof(struct block_info));
  113. memcpy(f->block_list,
  114. f->private + 8 + sizeof(struct font_header),
  115. f->header.blocks * sizeof(struct block_info));
  116. for(i = 0; i < f->header.blocks; i++)
  117. {
  118. f->block_list[i].start = htonl(f->block_list[i].start);
  119. f->block_list[i].stop = htonl(f->block_list[i].stop);
  120. f->block_list[i].index = htonl(f->block_list[i].index);
  121. }
  122. f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info));
  123. memcpy(f->glyph_list,
  124. f->private + 8 + sizeof(struct font_header)
  125. + f->header.blocks * sizeof(struct block_info),
  126. f->header.glyphs * sizeof(struct glyph_info));
  127. for(i = 0; i < f->header.glyphs; i++)
  128. {
  129. f->glyph_list[i].width = htons(f->glyph_list[i].width);
  130. f->glyph_list[i].height = htons(f->glyph_list[i].height);
  131. f->glyph_list[i].data_offset = htonl(f->glyph_list[i].data_offset);
  132. }
  133. f->font_data = f->private + 8 + f->header.control_size;
  134. return f;
  135. }
  136. /** \brief Get a font's maximum glyph width.
  137. *
  138. * This function returns the maximum value for the current font's glyphs
  139. *
  140. * \param f The font, as returned by \e cucul_load_font()
  141. * \return The maximum glyph width.
  142. */
  143. unsigned int cucul_get_font_width(struct cucul_font *f)
  144. {
  145. return f->header.width;
  146. }
  147. /** \brief Get a font's maximum glyph height.
  148. *
  149. * This function returns the maximum value for the current font's glyphs
  150. *
  151. * \param f The font, as returned by \e cucul_load_font()
  152. * \return The maximum glyph height.
  153. */
  154. unsigned int cucul_get_font_height(struct cucul_font *f)
  155. {
  156. return f->header.height;
  157. }
  158. /** \brief Free a font structure.
  159. *
  160. * This function frees all data allocated by \e cucul_load_font(). The
  161. * font structure is no longer usable by other libcucul functions. Once
  162. * this function has returned, the memory area that was given to
  163. * \e cucul_load_font() can be freed.
  164. *
  165. * \param f The font, as returned by \e cucul_load_font()
  166. */
  167. void cucul_free_font(struct cucul_font *f)
  168. {
  169. free(f->glyph_list);
  170. free(f->block_list);
  171. free(f);
  172. }
  173. /** \brief Render the canvas onto an image buffer.
  174. *
  175. * This function renders the given canvas on an image buffer using a specific
  176. * font. The pixel format is fixed (32-bit ARGB, 8 bits for each component).
  177. *
  178. * The required image width can be computed using \e cucul_get_width(qq) and
  179. * \e cucul_get_font_width(f). The required height can be computed using
  180. * \e cucul_get_height(qq) and \e cucul_get_font_height(f).
  181. *
  182. * Glyphs that do not fit in the image buffer are currently not rendered at
  183. * all. They may be cropped instead in future versions.
  184. *
  185. * \param qq The canvas to render
  186. * \param f The font, as returned by \e cucul_load_font()
  187. * \param buf The image buffer
  188. * \param width The width (in pixels) of the image buffer
  189. * \param height The height (in pixels) of the image buffer
  190. * \param pitch The pitch (in bytes) of an image buffer line.
  191. */
  192. void cucul_render_canvas(cucul_t *qq, struct cucul_font *f,
  193. unsigned char *buf, unsigned int width,
  194. unsigned int height, unsigned int pitch)
  195. {
  196. uint8_t *glyph = NULL;
  197. unsigned int x, y, xmax, ymax;
  198. if(f->header.bpp != 8)
  199. glyph = malloc(f->header.width * f->header.height);
  200. if(width < qq->width * f->header.width)
  201. xmax = width / f->header.width;
  202. else
  203. xmax = qq->width;
  204. if(height < qq->height * f->header.height)
  205. ymax = height / f->header.height;
  206. else
  207. ymax = qq->height;
  208. for(y = 0; y < ymax; y++)
  209. {
  210. for(x = 0; x < xmax; x++)
  211. {
  212. uint8_t argb[8];
  213. unsigned int starty = y * f->header.height;
  214. unsigned int startx = x * f->header.width;
  215. uint32_t ch = qq->chars[y * qq->width + x];
  216. uint32_t attr = qq->attr[y * qq->width + x];
  217. unsigned int b, i, j;
  218. struct glyph_info *g;
  219. /* Find the Unicode block where our glyph lies */
  220. for(b = 0; b < f->header.blocks; b++)
  221. {
  222. if(ch < f->block_list[b].start)
  223. {
  224. b = f->header.blocks;
  225. break;
  226. }
  227. if(ch < f->block_list[b].stop)
  228. break;
  229. }
  230. /* Glyph not in font? Skip it. */
  231. if(b == f->header.blocks)
  232. continue;
  233. g = &f->glyph_list[f->block_list[b].index
  234. + ch - f->block_list[b].start];
  235. _cucul_argb32_to_argb4(attr, argb);
  236. /* Step 1: unpack glyph */
  237. switch(f->header.bpp)
  238. {
  239. case 8:
  240. glyph = f->font_data + g->data_offset;
  241. break;
  242. case 4:
  243. unpack_glyph4(glyph, f->font_data + g->data_offset,
  244. g->width * g->height);
  245. break;
  246. case 2:
  247. unpack_glyph2(glyph, f->font_data + g->data_offset,
  248. g->width * g->height);
  249. break;
  250. case 1:
  251. unpack_glyph1(glyph, f->font_data + g->data_offset,
  252. g->width * g->height);
  253. break;
  254. }
  255. /* Step 2: render glyph using colour attribute */
  256. for(j = 0; j < g->height; j++)
  257. {
  258. uint8_t *line = buf + (starty + j) * pitch + 4 * startx;
  259. for(i = 0; i < g->width; i++)
  260. {
  261. uint8_t *pixel = line + 4 * i;
  262. uint32_t p, q, t;
  263. p = glyph[j * g->width + i];
  264. q = 0xff - p;
  265. for(t = 0; t < 4; t++)
  266. pixel[t] = (((q * argb[t]) + (p * argb[4 + t])) / 0xf);
  267. }
  268. }
  269. }
  270. }
  271. if(f->header.bpp != 8)
  272. free(glyph);
  273. }
  274. /*
  275. * The libcaca font format, version 1
  276. * ----------------------------------
  277. *
  278. * All types are big endian.
  279. *
  280. * struct
  281. * {
  282. * uint8_t caca_header[4]; // "CACA"
  283. * uint8_t caca_file_type[4]; // "FONT"
  284. *
  285. * font_header:
  286. * uint32_t control_size; // Control size (font_data - font_header)
  287. * uint32_t data_size; // Data size (EOF - font_data)
  288. *
  289. * uint16_t version; // Font format version
  290. * // bit 0: set to 1 if font is compatible
  291. * // with version 1 of the format
  292. * // bits 1-15: unused yet, must be 0
  293. *
  294. * uint16_t blocks; // Number of blocks in the font
  295. * uint32_t glyphs; // Total number of glyphs in the font
  296. *
  297. * uint16_t bpp; // Bits per pixel for glyph data (valid
  298. * // Values are 1, 2, 4 and 8)
  299. * uint16_t width; // Maximum glyph width
  300. * uint16_t height; // Maximum glyph height
  301. *
  302. * uint16_t flags; // Feature flags
  303. * // bit 0: set to 1 if font is fixed width
  304. * // bits 1-15: unused yet, must be 0
  305. *
  306. * block_info:
  307. * struct
  308. * {
  309. * uint32_t start; // Unicode index of the first glyph
  310. * uint32_t stop; // Unicode index of the last glyph + 1
  311. * uint32_t index; // Glyph info index of the first glyph
  312. * }
  313. * block_list[blocks];
  314. *
  315. * glyph_info:
  316. * struct
  317. * {
  318. * uint16_t width; // Glyph width in pixels
  319. * uint16_t height; // Glyph height in pixels
  320. * uint32_t data_offset; // Offset (starting from data) to the data
  321. * // for the first character
  322. * }
  323. * glyph_list[glyphs];
  324. *
  325. * extension_1:
  326. * extension_2:
  327. * ...
  328. * extension_N:
  329. * ... // reserved for future use
  330. *
  331. * font_data:
  332. * uint8_t data[data_size]; // glyph data
  333. * };
  334. */