source: libcaca/trunk/cucul/export.c @ 568

Last change on this file since 568 was 568, checked in by Sam Hocevar, 15 years ago
  • Added glue code to compile libcaca without a libc and build applications as multiboot kernels.
  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1/*
2 *  libcucul      Unicode canvas library
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
12/** \file export.c
13 *  \version \$Id: export.c 568 2006-03-09 12:47:37Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
15 *  \author Jean-Yves Lamoureux <jylam@lnxscene.org>
16 *  \brief Export function
17 *
18 *  This file contains export functions for various file formats such
19 *  as HTML or IRC.
20 */
21
22#include "config.h"
23
24#if !defined(__KERNEL__)
25#   include <stdlib.h>
26#   include <stdio.h>
27#   include <string.h>
28#endif
29
30#include "cucul.h"
31#include "cucul_internals.h"
32
33/* HTML */
34
35/** \brief Generate HTML representation of current image.
36 *
37 *  This function generates and returns the HTML representation of
38 *  the current image.
39 */
40char* cucul_get_html(cucul_t *qq, int *size)
41{
42    static int const palette[] =
43    {
44        0x000, 0x008, 0x080, 0x088, 0x800, 0x808, 0x880, 0x888,
45        0x444, 0x44f, 0x4f4, 0x4ff, 0xf44, 0xf4f, 0xff4, 0xfff,
46    };
47    char *buffer, *cur;
48    unsigned int x, y, len;
49
50    /* 13000 -> css palette
51     * 40 -> max size used for a pixel (plus 10, never know)*/
52    /* FIXME: Check this value */
53    buffer = malloc((13000 + ((qq->width*qq->height) * 40)) * sizeof(char));
54    cur = buffer;
55
56    /* HTML header */
57    cur += sprintf(cur, "<html>\n<head>\n<title>Generated by libcaca %s</title>\n", VERSION);
58
59    /* CSS */
60    cur += sprintf(cur, "<style>\n");
61    cur += sprintf(cur, ".caca { font-family: monospace, fixed; font-weight: bold; }");
62    for(x = 0; x < 0x100; x++)
63    {
64        cur += sprintf(cur, ".b%02x { color:#%03x; background-color:#%03x; }\n",
65                       x, palette[x & 0xf ], palette[x >> 4]);
66    }
67    cur += sprintf(cur, "</style>\n</head>\n<body>\n");
68
69    cur += sprintf(cur, "<div cellpadding='0' cellspacing='0' style='%s'>\n",
70                        "font-family: monospace, fixed; font-weight: bold;");
71
72    for(y = 0; y < qq->height; y++)
73    {
74        uint8_t *lineattr = qq->attr + y * qq->width;
75        uint32_t *linechar = qq->chars + y * qq->width;
76
77        for(x = 0; x < qq->width; x += len)
78        {
79            cur += sprintf(cur, "<span class='b%02x'>", lineattr[x]);
80
81            for(len = 0;
82                x + len < qq->width && lineattr[x + len] == lineattr[x];
83                len++)
84            {
85                if(linechar[x + len] == (uint32_t)' ')
86                    cur += sprintf(cur, "&nbsp;");
87                else
88                    cur += sprintf(cur, "%c", linechar[x + len] & 0x7f);
89            }
90            cur += sprintf(cur, "</span>");
91        }
92        /* New line */
93        cur += sprintf(cur, "<br />\n");
94    }
95
96    cur += sprintf(cur, "</div></body></html>\n");
97
98    /* Crop to really used size */
99    *size = (strlen(buffer) + 1) * sizeof(char);
100    buffer = realloc(buffer, *size);
101
102    return buffer;
103}
104
105/** \brief Generate HTML3 representation of current image.
106 *
107 *  This function generates and returns the HTML3 representation of
108 *  the current image. It is way bigger than cucul_get_html(), but
109 *  permits viewing in old browsers (or limited ones such as links)
110 *  Won't work under gecko (mozilla rendering engine) unless you set
111 *  a correct header.
112 */
113char* cucul_get_html3(cucul_t *qq, int *size)
114{
115    static int const palette[] =
116    {
117        0x000000, 0x000088, 0x008800, 0x008888,
118        0x880000, 0x880088, 0x888800, 0x888888,
119        0x444444, 0x4444ff, 0x44ff44, 0x44ffff,
120        0xff4444, 0xff44ff, 0xffff44, 0xffffff,
121    };
122    char *buffer, *cur;
123    unsigned int x, y, len;
124
125    /* 13000 -> css palette
126     * 40 -> max size used for a pixel (plus 10, never know) */
127    buffer = malloc((13000 + ((qq->width*qq->height)*40))*sizeof(char));
128    cur = buffer;
129
130    /* Table */
131    cur += sprintf(cur, "<table cols='%d' cellpadding='0' cellspacing='0'>\n",
132                        qq->height);
133
134    for(y = 0; y < qq->height; y++)
135    {
136        uint8_t *lineattr = qq->attr + y * qq->width;
137        uint32_t *linechar = qq->chars + y * qq->width;
138
139        cur += sprintf(cur, "<tr>");
140
141        for(x = 0; x < qq->width; x += len)
142        {
143            unsigned int i;
144
145            /* Use colspan option to factorize cells with same attributes
146             * (see below) */
147            len = 1;
148            while(x + len < qq->width && lineattr[x + len] == lineattr[x])
149                len++;
150
151            cur += sprintf(cur, "<td bgcolor=#%06x", palette[lineattr[x] >> 4]);
152
153            if(len > 1)
154                cur += sprintf(cur, " colspan=%d", len);
155
156            cur += sprintf(cur, "><font color=#%06x>",
157                                palette[lineattr[x] & 0x0f]);
158
159            for(i = 0; i < len; i++)
160            {
161                if(linechar[x + i] == (uint32_t)' ')
162                    cur += sprintf(cur, "&nbsp;");
163                else
164                    cur += sprintf(cur, "%c", linechar[x + i] & 0x7f);
165            }
166
167            cur += sprintf(cur, "</font></td>");
168        }
169        cur += sprintf(cur, "</tr>\n");
170    }
171
172    /* Footer */
173    cur += sprintf(cur, "</table>\n");
174
175    /* Crop to really used size */
176    *size = (strlen(buffer) + 1) * sizeof(char);
177    buffer = realloc(buffer, *size);
178   
179    return buffer;
180}
181
182/** \brief Generate IRC representation of current image.
183 *
184 *  This function generates and returns an IRC representation of
185 *  the current image.
186 */
187char* cucul_get_irc(cucul_t *qq, int *size)
188{
189    static int const palette[] =
190    {
191        1, 2, 3, 10, 5, 6, 7, 15, /* Dark */
192        14, 12, 9, 11, 4, 13, 8, 0, /* Light */
193    };
194
195    char *buffer, *cur;
196    unsigned int x, y;
197
198    /* 11 bytes assumed for max length per pixel. Worst case scenario:
199     * ^Cxx,yy   6 bytes
200     * ^B^B      2 bytes
201     * c         1 byte
202     * \r\n      2 bytes
203     * In real life, the average bytes per pixel value will be around 5.
204     */
205    buffer = malloc((2 + (qq->width * qq->height * 11)) * sizeof(char));
206    cur = buffer;
207
208    *cur++ = '\x0f';
209
210    for(y = 0; y < qq->height; y++)
211    {
212        uint8_t *lineattr = qq->attr + y * qq->width;
213        uint32_t *linechar = qq->chars + y * qq->width;
214
215        uint8_t prevfg = -1;
216        uint8_t prevbg = -1;
217
218        for(x = 0; x < qq->width; x++)
219        {
220            uint8_t fg = palette[lineattr[x] & 0x0f];
221            uint8_t bg = palette[lineattr[x] >> 4];
222            uint32_t c = linechar[x];
223
224            if(bg == prevbg)
225            {
226                if(fg == prevfg)
227                    ; /* Same fg/bg, do nothing */
228                else if(c == (uint32_t)' ')
229                    fg = prevfg; /* Hackety hack */
230                else
231                {
232                    cur += sprintf(cur, "\x03%d", fg);
233                    if(c >= (uint32_t)'0' && c <= (uint32_t)'9')
234                        cur += sprintf(cur, "\x02\x02");
235                }
236            }
237            else
238            {
239                if(fg == prevfg)
240                    cur += sprintf(cur, "\x03,%d", bg);
241                else
242                    cur += sprintf(cur, "\x03%d,%d", fg, bg);
243
244                if(c >= (uint32_t)'0' && c <= (uint32_t)'9')
245                    cur += sprintf(cur, "\x02\x02");
246            }
247            *cur++ = c & 0x7f;
248            prevfg = fg;
249            prevbg = bg;
250        }
251        *cur++ = '\r';
252        *cur++ = '\n';
253    }
254
255    *cur++ = '\x0f';
256
257    /* Crop to really used size */
258    *size = (strlen(buffer) + 1) * sizeof(char);
259    buffer = realloc(buffer, *size);
260
261    return buffer;
262}
263
264/** \brief Generate ANSI representation of current image.
265 *
266 *  This function generates and returns an ANSI representation of
267 *  the current image.
268 *  \param trailing if 0, raw ANSI will be generated. Otherwise, you'll be
269 *                  able to cut/paste the result to a function like printf
270 *  \return buffer containing generated ANSI codes as a big string
271 */
272char * cucul_get_ansi(cucul_t *qq, int trailing, int *size)
273{
274    static int const palette[] =
275    {
276        30, 34, 32, 36, 31, 35, 33, 37, /* Both lines (light and dark) are the same, */
277        30, 34, 32, 36, 31, 35, 33, 37, /* light colors handling is done later */
278    };
279
280    char *cur;
281    unsigned int x, y;
282
283    /* 20 bytes assumed for max length per pixel.
284     * Add height*9 to that (zeroes color at the end and jump to next line) */
285    if(qq->ansi_buffer)
286        free(qq->ansi_buffer);
287    qq->ansi_buffer = malloc(((qq->height*9) + (qq->width * qq->height * 20)) * sizeof(char));
288    cur = qq->ansi_buffer;
289
290    // *cur++ = '';
291
292    for(y = 0; y < qq->height; y++)
293    {
294        uint8_t *lineattr = qq->attr + y * qq->width;
295        uint32_t *linechar = qq->chars + y * qq->width;
296
297        uint8_t prevfg = -1;
298        uint8_t prevbg = -1;
299
300        for(x = 0; x < qq->width; x++)
301        {
302            uint8_t fg = palette[lineattr[x] & 0x0f];
303            uint8_t bg = (palette[lineattr[x] >> 4])+10;
304            uint32_t c = linechar[x];
305
306            if(!trailing)
307                cur += sprintf(cur, "\033[");
308            else
309                cur += sprintf(cur, "\\033[");
310
311            if(fg > 7)
312                cur += sprintf(cur, "1;%d;%dm",fg,bg);
313            else
314                cur += sprintf(cur, "0;%d;%dm",fg,bg);
315            *cur++ = c & 0x7f;
316            if((c == '%') && trailing)
317                *cur++ = c & 0x7f;
318            prevfg = fg;
319            prevbg = bg;
320        }
321        if(!trailing)
322            cur += sprintf(cur, "\033[0m\n\r");
323        else
324            cur += sprintf(cur, "\\033[0m\\n\n");
325    }
326
327    /* Crop to really used size */
328    *size = (strlen(qq->ansi_buffer) + 1)* sizeof(char);
329    qq->ansi_buffer = realloc(qq->ansi_buffer, *size);
330
331    return qq->ansi_buffer;
332}
333
Note: See TracBrowser for help on using the repository browser.