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 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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. struct cucul_font *cucul_load_font(void *data, unsigned int size)
  78. {
  79. struct cucul_font *f;
  80. unsigned int i;
  81. f = malloc(sizeof(struct cucul_font));
  82. f->private = data;
  83. memcpy(&f->header, f->private + 8, sizeof(struct font_header));
  84. f->header.control_size = htonl(f->header.control_size);
  85. f->header.data_size = htonl(f->header.data_size);
  86. f->header.version = htons(f->header.version);
  87. f->header.blocks = htons(f->header.blocks);
  88. f->header.glyphs = htonl(f->header.glyphs);
  89. f->header.bpp = htons(f->header.bpp);
  90. f->header.width = htons(f->header.width);
  91. f->header.height = htons(f->header.height);
  92. f->header.flags = htons(f->header.flags);
  93. f->block_list = malloc(f->header.blocks * sizeof(struct block_info));
  94. memcpy(f->block_list,
  95. f->private + 8 + sizeof(struct font_header),
  96. f->header.blocks * sizeof(struct block_info));
  97. for(i = 0; i < f->header.blocks; i++)
  98. {
  99. f->block_list[i].start = htonl(f->block_list[i].start);
  100. f->block_list[i].stop = htonl(f->block_list[i].stop);
  101. f->block_list[i].index = htonl(f->block_list[i].index);
  102. }
  103. f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info));
  104. memcpy(f->glyph_list,
  105. f->private + 8 + sizeof(struct font_header)
  106. + f->header.blocks * sizeof(struct block_info),
  107. f->header.glyphs * sizeof(struct glyph_info));
  108. for(i = 0; i < f->header.glyphs; i++)
  109. {
  110. f->glyph_list[i].width = htons(f->glyph_list[i].width);
  111. f->glyph_list[i].height = htons(f->glyph_list[i].height);
  112. f->glyph_list[i].data_offset = htonl(f->glyph_list[i].data_offset);
  113. }
  114. f->font_data = f->private + 8 + f->header.control_size;
  115. return f;
  116. }
  117. void cucul_free_font(struct cucul_font *f)
  118. {
  119. free(f->glyph_list);
  120. free(f->block_list);
  121. free(f);
  122. }
  123. void cucul_render_canvas(cucul_t *qq, struct cucul_font *f)
  124. {
  125. uint8_t *buf, *glyph = NULL;
  126. unsigned int x, y;
  127. buf = malloc(4 * qq->width * f->header.width
  128. * qq->height * f->header.height);
  129. if(f->header.bpp != 8)
  130. glyph = malloc(f->header.width * f->header.height);
  131. for(y = 0; y < qq->height; y++)
  132. {
  133. for(x = 0; x < qq->width; x++)
  134. {
  135. uint8_t argb[8];
  136. unsigned int starty = y * f->header.height;
  137. unsigned int startx = x * f->header.width;
  138. uint32_t ch = qq->chars[y * qq->width + x];
  139. uint32_t attr = qq->attr[y * qq->width + x];
  140. unsigned int b, i, j;
  141. struct glyph_info *g;
  142. /* Find the Unicode block where our glyph lies */
  143. for(b = 0; b < f->header.blocks; b++)
  144. {
  145. if(ch < f->block_list[b].start)
  146. {
  147. b = f->header.blocks;
  148. break;
  149. }
  150. if(ch < f->block_list[b].stop)
  151. break;
  152. }
  153. /* Glyph not in font? Skip it. */
  154. if(b == f->header.blocks)
  155. continue;
  156. g = &f->glyph_list[f->block_list[b].index
  157. + ch - f->block_list[b].start];
  158. _cucul_argb32_to_argb4(attr, argb);
  159. /* Step 1: unpack glyph */
  160. switch(f->header.bpp)
  161. {
  162. case 8:
  163. glyph = f->font_data + g->data_offset;
  164. break;
  165. case 4:
  166. unpack_glyph4(glyph, f->font_data + g->data_offset,
  167. g->width * g->height);
  168. break;
  169. case 2:
  170. unpack_glyph2(glyph, f->font_data + g->data_offset,
  171. g->width * g->height);
  172. break;
  173. case 1:
  174. unpack_glyph1(glyph, f->font_data + g->data_offset,
  175. g->width * g->height);
  176. break;
  177. }
  178. /* Step 2: render glyph using true colours */
  179. for(j = 0; j < g->height; j++)
  180. {
  181. uint8_t *line = buf + 4 * ((starty + j) * qq->width
  182. * f->header.width + startx);
  183. for(i = 0; i < g->width; i++)
  184. {
  185. uint8_t *pixel = line + 4 * (startx + i);
  186. uint32_t p, q, t;
  187. p = glyph[j * g->width + i];
  188. q = 0xff - p;
  189. for(t = 0; t < 4; t++)
  190. pixel[t] = (((q * argb[t]) + (p * argb[4 + t])) / 0xf);
  191. }
  192. }
  193. }
  194. }
  195. for(y = 0; y < qq->height * f->header.height; y++)
  196. {
  197. for(x = 0; x < qq->width * f->header.width; x++)
  198. {
  199. printf("%.02x", buf[4 * (y * qq->width * f->header.width + x) + 3]);
  200. }
  201. printf("\n");
  202. }
  203. if(f->header.bpp != 8)
  204. free(glyph);
  205. free(buf);
  206. }
  207. /*
  208. * The libcaca font format, version 1
  209. * ----------------------------------
  210. *
  211. * All types are big endian.
  212. *
  213. * struct
  214. * {
  215. * uint8_t caca_header[4]; // "CACA"
  216. * uint8_t caca_file_type[4]; // "FONT"
  217. *
  218. * font_header:
  219. * uint32_t control_size; // Control size (font_data - font_header)
  220. * uint32_t data_size; // Data size (EOF - font_data)
  221. *
  222. * uint16_t version; // Font format version
  223. * // bit 0: set to 1 if font is compatible
  224. * // with version 1 of the format
  225. * // bits 1-15: unused yet, must be 0
  226. *
  227. * uint16_t blocks; // Number of blocks in the font
  228. * uint32_t glyphs; // Total number of glyphs in the font
  229. *
  230. * uint16_t bpp; // Bits per pixel for glyph data (valid
  231. * // Values are 1, 2, 4 and 8)
  232. * uint16_t width; // Maximum glyph width
  233. * uint16_t height; // Maximum glyph height
  234. *
  235. * uint16_t flags; // Feature flags
  236. * // bit 0: set to 1 if font is fixed width
  237. * // bits 1-15: unused yet, must be 0
  238. *
  239. * block_info:
  240. * struct
  241. * {
  242. * uint32_t start; // Unicode index of the first glyph
  243. * uint32_t stop; // Unicode index of the last glyph + 1
  244. * uint32_t index; // Glyph info index of the first glyph
  245. * }
  246. * block_list[blocks];
  247. *
  248. * glyph_info:
  249. * struct
  250. * {
  251. * uint16_t width; // Glyph width in pixels
  252. * uint16_t height; // Glyph height in pixels
  253. * uint32_t data_offset; // Offset (starting from data) to the data
  254. * // for the first character
  255. * }
  256. * glyph_list[glyphs];
  257. *
  258. * extension_1:
  259. * extension_2:
  260. * ...
  261. * extension_N:
  262. * ... // reserved for future use
  263. *
  264. * font_data:
  265. * uint8_t data[data_size]; // glyph data
  266. * };
  267. */