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.
 
 
 
 
 
 

308 lines
8.7 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. 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. */