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

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