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.

преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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. #include "font_mono9.h"
  32. #include "font_monobold12.h"
  33. /* Helper structure for font loading */
  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. {
  100. if(!strcasecmp(data, "Monospace 9"))
  101. return cucul_load_font(mono9_data, mono9_size);
  102. if(!strcasecmp(data, "Monospace Bold 12"))
  103. return cucul_load_font(monobold12_data, monobold12_size);
  104. return NULL;
  105. }
  106. f = malloc(sizeof(struct cucul_font));
  107. f->private = (void *)(uintptr_t)data;
  108. memcpy(&f->header, f->private + 8, sizeof(struct font_header));
  109. f->header.control_size = htonl(f->header.control_size);
  110. f->header.data_size = htonl(f->header.data_size);
  111. f->header.version = htons(f->header.version);
  112. f->header.blocks = htons(f->header.blocks);
  113. f->header.glyphs = htonl(f->header.glyphs);
  114. f->header.bpp = htons(f->header.bpp);
  115. f->header.width = htons(f->header.width);
  116. f->header.height = htons(f->header.height);
  117. f->header.flags = htons(f->header.flags);
  118. f->block_list = malloc(f->header.blocks * sizeof(struct block_info));
  119. memcpy(f->block_list,
  120. f->private + 8 + sizeof(struct font_header),
  121. f->header.blocks * sizeof(struct block_info));
  122. for(i = 0; i < f->header.blocks; i++)
  123. {
  124. f->block_list[i].start = htonl(f->block_list[i].start);
  125. f->block_list[i].stop = htonl(f->block_list[i].stop);
  126. f->block_list[i].index = htonl(f->block_list[i].index);
  127. }
  128. f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info));
  129. memcpy(f->glyph_list,
  130. f->private + 8 + sizeof(struct font_header)
  131. + f->header.blocks * sizeof(struct block_info),
  132. f->header.glyphs * sizeof(struct glyph_info));
  133. for(i = 0; i < f->header.glyphs; i++)
  134. {
  135. f->glyph_list[i].width = htons(f->glyph_list[i].width);
  136. f->glyph_list[i].height = htons(f->glyph_list[i].height);
  137. f->glyph_list[i].data_offset = htonl(f->glyph_list[i].data_offset);
  138. }
  139. f->font_data = f->private + 8 + f->header.control_size;
  140. return f;
  141. }
  142. /**
  143. * \brief Get available builtin fonts
  144. *
  145. * Return a list of available builtin fonts. The list is a NULL-terminated
  146. * array of strings.
  147. *
  148. * \return An array of strings.
  149. */
  150. char const * const * cucul_get_font_list(void)
  151. {
  152. static char const * const list[] =
  153. {
  154. "Monospace 9",
  155. "Monospace Bold 12",
  156. NULL
  157. };
  158. return list;
  159. }
  160. /** \brief Get a font's maximum glyph width.
  161. *
  162. * This function returns the maximum value for the current font's glyphs
  163. *
  164. * \param f The font, as returned by \e cucul_load_font()
  165. * \return The maximum glyph width.
  166. */
  167. unsigned int cucul_get_font_width(struct cucul_font *f)
  168. {
  169. return f->header.width;
  170. }
  171. /** \brief Get a font's maximum glyph height.
  172. *
  173. * This function returns the maximum value for the current font's glyphs
  174. *
  175. * \param f The font, as returned by \e cucul_load_font()
  176. * \return The maximum glyph height.
  177. */
  178. unsigned int cucul_get_font_height(struct cucul_font *f)
  179. {
  180. return f->header.height;
  181. }
  182. /** \brief Free a font structure.
  183. *
  184. * This function frees all data allocated by \e cucul_load_font(). The
  185. * font structure is no longer usable by other libcucul functions. Once
  186. * this function has returned, the memory area that was given to
  187. * \e cucul_load_font() can be freed.
  188. *
  189. * \param f The font, as returned by \e cucul_load_font()
  190. */
  191. void cucul_free_font(struct cucul_font *f)
  192. {
  193. free(f->glyph_list);
  194. free(f->block_list);
  195. free(f);
  196. }
  197. /** \brief Render the canvas onto an image buffer.
  198. *
  199. * This function renders the given canvas on an image buffer using a specific
  200. * font. The pixel format is fixed (32-bit ARGB, 8 bits for each component).
  201. *
  202. * The required image width can be computed using \e cucul_get_width(qq) and
  203. * \e cucul_get_font_width(f). The required height can be computed using
  204. * \e cucul_get_height(qq) and \e cucul_get_font_height(f).
  205. *
  206. * Glyphs that do not fit in the image buffer are currently not rendered at
  207. * all. They may be cropped instead in future versions.
  208. *
  209. * \param qq The canvas to render
  210. * \param f The font, as returned by \e cucul_load_font()
  211. * \param buf The image buffer
  212. * \param width The width (in pixels) of the image buffer
  213. * \param height The height (in pixels) of the image buffer
  214. * \param pitch The pitch (in bytes) of an image buffer line.
  215. */
  216. void cucul_render_canvas(cucul_t *qq, struct cucul_font *f,
  217. unsigned char *buf, unsigned int width,
  218. unsigned int height, unsigned int pitch)
  219. {
  220. uint8_t *glyph = NULL;
  221. unsigned int x, y, xmax, ymax;
  222. if(f->header.bpp != 8)
  223. glyph = malloc(f->header.width * f->header.height);
  224. if(width < qq->width * f->header.width)
  225. xmax = width / f->header.width;
  226. else
  227. xmax = qq->width;
  228. if(height < qq->height * f->header.height)
  229. ymax = height / f->header.height;
  230. else
  231. ymax = qq->height;
  232. for(y = 0; y < ymax; y++)
  233. {
  234. for(x = 0; x < xmax; x++)
  235. {
  236. uint8_t argb[8];
  237. unsigned int starty = y * f->header.height;
  238. unsigned int startx = x * f->header.width;
  239. uint32_t ch = qq->chars[y * qq->width + x];
  240. uint32_t attr = qq->attr[y * qq->width + x];
  241. unsigned int b, i, j;
  242. struct glyph_info *g;
  243. /* Find the Unicode block where our glyph lies */
  244. for(b = 0; b < f->header.blocks; b++)
  245. {
  246. if(ch < f->block_list[b].start)
  247. {
  248. b = f->header.blocks;
  249. break;
  250. }
  251. if(ch < f->block_list[b].stop)
  252. break;
  253. }
  254. /* Glyph not in font? Skip it. */
  255. if(b == f->header.blocks)
  256. continue;
  257. g = &f->glyph_list[f->block_list[b].index
  258. + ch - f->block_list[b].start];
  259. _cucul_argb32_to_argb4(attr, argb);
  260. /* Step 1: unpack glyph */
  261. switch(f->header.bpp)
  262. {
  263. case 8:
  264. glyph = f->font_data + g->data_offset;
  265. break;
  266. case 4:
  267. unpack_glyph4(glyph, f->font_data + g->data_offset,
  268. g->width * g->height);
  269. break;
  270. case 2:
  271. unpack_glyph2(glyph, f->font_data + g->data_offset,
  272. g->width * g->height);
  273. break;
  274. case 1:
  275. unpack_glyph1(glyph, f->font_data + g->data_offset,
  276. g->width * g->height);
  277. break;
  278. }
  279. /* Step 2: render glyph using colour attribute */
  280. for(j = 0; j < g->height; j++)
  281. {
  282. uint8_t *line = buf + (starty + j) * pitch + 4 * startx;
  283. for(i = 0; i < g->width; i++)
  284. {
  285. uint8_t *pixel = line + 4 * i;
  286. uint32_t p, q, t;
  287. p = glyph[j * g->width + i];
  288. q = 0xff - p;
  289. for(t = 0; t < 4; t++)
  290. pixel[t] = (((q * argb[t]) + (p * argb[4 + t])) / 0xf);
  291. }
  292. }
  293. }
  294. }
  295. if(f->header.bpp != 8)
  296. free(glyph);
  297. }
  298. /*
  299. * The libcaca font format, version 1
  300. * ----------------------------------
  301. *
  302. * All types are big endian.
  303. *
  304. * struct
  305. * {
  306. * uint8_t caca_header[4]; // "CACA"
  307. * uint8_t caca_file_type[4]; // "FONT"
  308. *
  309. * font_header:
  310. * uint32_t control_size; // Control size (font_data - font_header)
  311. * uint32_t data_size; // Data size (EOF - font_data)
  312. *
  313. * uint16_t version; // Font format version
  314. * // bit 0: set to 1 if font is compatible
  315. * // with version 1 of the format
  316. * // bits 1-15: unused yet, must be 0
  317. *
  318. * uint16_t blocks; // Number of blocks in the font
  319. * uint32_t glyphs; // Total number of glyphs in the font
  320. *
  321. * uint16_t bpp; // Bits per pixel for glyph data (valid
  322. * // Values are 1, 2, 4 and 8)
  323. * uint16_t width; // Maximum glyph width
  324. * uint16_t height; // Maximum glyph height
  325. *
  326. * uint16_t flags; // Feature flags
  327. * // bit 0: set to 1 if font is fixed width
  328. * // bits 1-15: unused yet, must be 0
  329. *
  330. * block_info:
  331. * struct
  332. * {
  333. * uint32_t start; // Unicode index of the first glyph
  334. * uint32_t stop; // Unicode index of the last glyph + 1
  335. * uint32_t index; // Glyph info index of the first glyph
  336. * }
  337. * block_list[blocks];
  338. *
  339. * glyph_info:
  340. * struct
  341. * {
  342. * uint16_t width; // Glyph width in pixels
  343. * uint16_t height; // Glyph height in pixels
  344. * uint32_t data_offset; // Offset (starting from data) to the data
  345. * // for the first character
  346. * }
  347. * glyph_list[glyphs];
  348. *
  349. * extension_1:
  350. * extension_2:
  351. * ...
  352. * extension_N:
  353. * ... // reserved for future use
  354. *
  355. * font_data:
  356. * uint8_t data[data_size]; // glyph data
  357. * };
  358. */