Ignore:
Timestamp:
Nov 12, 2006, 11:42:14 AM (13 years ago)
Author:
Sam Hocevar
Message:
  • Documentation updates. Moved the canvas and font format definitions to the Doxygen documentation.
Location:
libcaca/trunk/doc
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/doc/Makefile.am

    r1328 r1357  
    33EXTRA_DIST = doxygen.cfg.in footer.html header.html $(man_MANS) $(doxygen_DOX)
    44
    5 doxygen_DOX = libcaca.dox user.dox migrating.dox tutorial.dox style.dox
     5doxygen_DOX = libcaca.dox user.dox migrating.dox tutorial.dox canvas.dox font.dox style.dox
    66man_MANS = caca-config.1 cacafire.1 cacaview.1 cacaserver.1 img2irc.1 cacaplay.1
    77
  • libcaca/trunk/doc/canvas.dox

    r1354 r1357  
    1 /*
    2  *  libcucul      Canvas for ultrafast compositing of Unicode letters
    3  *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
    4  *                2006 Jean-Yves Lamoureux <jylam@lnxscene.org>
    5  *                All Rights Reserved
    6  *
    7  *  $Id$
    8  *
    9  *  This library is free software; you can redistribute it and/or
    10  *  modify it under the terms of the Do What The Fuck You Want To
    11  *  Public License, Version 2, as published by Sam Hocevar. See
    12  *  http://sam.zoy.org/wtfpl/COPYING for more details.
    13  */
     1/* $Id$ */
    142
    15 /*
    16  *  This file contains various export functions
    17  */
     3/** \page canvas The libcaca canvas format (version 1)
    184
    19 #include "config.h"
    20 #include "common.h"
     5 All types are big endian.
    216
    22 #if !defined(__KERNEL__)
    23 #   if defined(HAVE_ERRNO_H)
    24 #       include <errno.h>
    25 #   endif
    26 #   include <stdlib.h>
    27 #   include <stdio.h>
    28 #   include <string.h>
    29 #endif
     7 \code
     8struct
     9{
     10magic:
     11   uint8_t caca_header[2];    // "\xCA\xCA"
     12   uint8_t caca_file_type[2]; // "CV"
    3013
    31 #include "cucul.h"
    32 #include "cucul_internals.h"
     14canvas_header:
     15   uint32_t control_size;     // Control size (canvas_data - canvas_header)
     16   uint32_t data_size;        // Data size (EOF - canvas_data)
    3317
    34 static inline int sprintu32(char *s, uint32_t x)
    35 {
    36     s[0] = (uint8_t)(x >> 24);
    37     s[1] = (uint8_t)(x >> 16) & 0xff;
    38     s[2] = (uint8_t)(x >>  8) & 0xff;
    39     s[3] = (uint8_t)(x      ) & 0xff;
    40     return 4;
    41 }
     18   uint16_t version;          // Canvas format version
     19                              //  bit 0: set to 1 if canvas is compatible
     20                              //         with version 1 of the format
     21                              //  bits 1-15: unused yet, must be 0
    4222
    43 static inline int sprintu16(char *s, uint16_t x)
    44 {
    45     s[0] = (uint8_t)(x >>  8) & 0xff;
    46     s[1] = (uint8_t)(x      ) & 0xff;
    47     return 2;
    48 }
     23   uint32_t frames;           // Frame count
    4924
    50 static void *export_caca(cucul_canvas_t *, unsigned long int *);
    51 static void *export_ansi(cucul_canvas_t *, unsigned long int *);
    52 static void *export_utf8(cucul_canvas_t *, unsigned long int *, int);
    53 static void *export_html(cucul_canvas_t *, unsigned long int *);
    54 static void *export_html3(cucul_canvas_t *, unsigned long int *);
    55 static void *export_irc(cucul_canvas_t *, unsigned long int *);
    56 static void *export_ps(cucul_canvas_t *, unsigned long int *);
    57 static void *export_svg(cucul_canvas_t *, unsigned long int *);
    58 static void *export_tga(cucul_canvas_t *, unsigned long int *);
     25   uint16_t flags;            // Feature flags
     26                              //  bits 0-15: unused yet, must be 0
    5927
    60 /** \brief Export a canvas into a foreign format.
    61  *
    62  *  This function exports a libcucul canvas into various foreign formats such
    63  *  as ANSI art, HTML, IRC colours, etc. The returned pointer should be passed
    64  *  to free() to release the allocated storage when it is no longer needed.
    65  *
    66  *  Valid values for \c format are:
    67  *  - \c "caca": export native libcaca files.
    68  *  - \c "ansi": export ANSI art (CP437 charset with ANSI colour codes).
    69  *  - \c "html": export an HTML page with CSS information.
    70  *  - \c "html3": export an HTML table that should be compatible with
    71  *    most navigators, including textmode ones.
    72  *  - \c "irc": export UTF-8 text with mIRC colour codes.
    73  *  - \c "ps": export a PostScript document.
    74  *  - \c "svg": export an SVG vector image.
    75  *  - \c "tga": export a TGA image.
    76  *
    77  *  If an error occurs, NULL is returned and \b errno is set accordingly:
    78  *  - \c EINVAL Unsupported format requested.
    79  *  - \c ENOMEM Not enough memory to allocate output buffer.
    80  *
    81  *  \param cv A libcucul canvas
    82  *  \param format A string describing the requested output format.
    83  *  \param bytes A pointer to an unsigned long integer where the number of
    84  *         allocated bytes will be written.
    85  *  \return A pointer to the exported memory area, or NULL in case of error.
    86  */
    87 void *cucul_export_memory(cucul_canvas_t *cv, char const *format,
    88                           unsigned long int *bytes)
    89 {
    90     if(!strcasecmp("caca", format))
    91         return export_caca(cv, bytes);
     28frame_info:
     29   struct
     30   {
     31      uint32_t width;         // Frame width
     32      uint32_t height;        // Frame height
     33      uint32_t duration;      // Frame duration in milliseconds, 0 to
     34                              // not specify a duration
     35      uint32_t attr;          // Graphics context attribute
     36      int32_t cursor_x;       // Cursor X coordinate
     37      int32_t cursor_y;       // Cursor Y coordinate
     38      int32_t handle_x;       // Handle X coordinate
     39      int32_t handle_y;       // Handle Y coordinate
     40   }
     41   frame_list[frames];
    9242
    93     if(!strcasecmp("ansi", format))
    94         return export_ansi(cv, bytes);
     43control_extension_1:
     44control_extension_2:
     45   ...
     46control_extension_N:
     47   ...                        // reserved for future use
    9548
    96     if(!strcasecmp("utf8", format))
    97         return export_utf8(cv, bytes, 0);
     49canvas_data:
     50   uint8_t data[data_size];   // canvas data
    9851
    99     if(!strcasecmp("utf8cr", format))
    100         return export_utf8(cv, bytes, 1);
     52data_extension_1:
     53data_extension_2:
     54   ...
     55data_extension_N:
     56   ...                        // reserved for future use
     57};
     58 \endcode
    10159
    102     if(!strcasecmp("html", format))
    103         return export_html(cv, bytes);
    104 
    105     if(!strcasecmp("html3", format))
    106         return export_html3(cv, bytes);
    107 
    108     if(!strcasecmp("irc", format))
    109         return export_irc(cv, bytes);
    110 
    111     if(!strcasecmp("ps", format))
    112         return export_ps(cv, bytes);
    113 
    114     if(!strcasecmp("svg", format))
    115         return export_svg(cv, bytes);
    116 
    117     if(!strcasecmp("tga", format))
    118         return export_tga(cv, bytes);
    119 
    120 #if defined(HAVE_ERRNO_H)
    121     errno = EINVAL;
    122 #endif
    123     return NULL;
    124 }
    125 
    126 /** \brief Get available export formats
    127  *
    128  *  Return a list of available export formats. The list is a NULL-terminated
    129  *  array of strings, interleaving a string containing the internal value for
    130  *  the export format, to be used with cucul_export_memory(), and a string
    131  *  containing the natural language description for that export format.
    132  *
    133  *  This function never fails.
    134  *
    135  *  \return An array of strings.
    136  */
    137 char const * const * cucul_get_export_list(void)
    138 {
    139     static char const * const list[] =
    140     {
    141         "caca", "native libcaca format",
    142         "ansi", "ANSI",
    143         "utf8", "UTF-8 with ANSI escape codes",
    144         "utf8cr", "UTF-8 with ANSI escape codes and MS-DOS \\r",
    145         "html", "HTML",
    146         "html3", "backwards-compatible HTML",
    147         "irc", "IRC with mIRC colours",
    148         "ps", "PostScript document",
    149         "svg", "SVG vector image",
    150         "tga", "TGA image",
    151         NULL, NULL
    152     };
    153 
    154     return list;
    155 }
    156 
    157 /*
    158  * XXX: the following functions are local.
    159  */
    160 
    161 /* Generate a native libcaca canvas file. */
    162 static void *export_caca(cucul_canvas_t *cv, unsigned long int *bytes)
    163 {
    164     uint32_t *attrs = cv->attrs;
    165     uint32_t *chars = cv->chars;
    166     char *data, *cur;
    167     unsigned int n;
    168 
    169     /* 52 bytes for the header:
    170      *  - 4 bytes for "\xCA\xCA" + "CV"
    171      *  - 16 bytes for the canvas header
    172      *  - 32 bytes for the frame info
    173      * 8 bytes for each character cell */
    174     *bytes = 52 + 8 * cv->width * cv->height;
    175     cur = data = malloc(*bytes);
    176 
    177     /* magic */
    178     cur += sprintf(cur, "%s", "\xCA\xCA" "CV");
    179 
    180     /* canvas_header */
    181     cur += sprintu32(cur, 16 + 32 * 1);
    182     cur += sprintu32(cur, cv->width * cv->height * 8);
    183     cur += sprintu16(cur, 0x0001);
    184     cur += sprintu32(cur, 1);
    185     cur += sprintu16(cur, 0x0000);
    186 
    187     /* frame_info */
    188     cur += sprintu32(cur, cv->width);
    189     cur += sprintu32(cur, cv->height);
    190     cur += sprintu32(cur, 0);
    191     cur += sprintu32(cur, cv->curattr);
    192     cur += sprintu32(cur, cv->frames[0].x);
    193     cur += sprintu32(cur, cv->frames[0].y);
    194     cur += sprintu32(cur, cv->frames[0].handlex);
    195     cur += sprintu32(cur, cv->frames[0].handley);
    196 
    197     /* canvas_data */
    198     for(n = cv->height * cv->width; n--; )
    199     {
    200         cur += sprintu32(cur, *chars++);
    201         cur += sprintu32(cur, *attrs++);
    202     }
    203 
    204     return data;
    205 }
    206 
    207 /*
    208  * The libcaca canvas format, version 1
    209  * ------------------------------------
    210  *
    211  * All types are big endian.
    212  *
    213  * struct
    214  * {
    215  * magic:
    216  *    uint8_t caca_header[2];    // "\xCA\xCA"
    217  *    uint8_t caca_file_type[2]; // "CV"
    218  *
    219  * canvas_header:
    220  *    uint32_t control_size;     // Control size (canvas_data - canvas_header)
    221  *    uint32_t data_size;        // Data size (EOF - canvas_data)
    222  *
    223  *    uint16_t version;          // Canvas format version
    224  *                               //  bit 0: set to 1 if canvas is compatible
    225  *                               //         with version 1 of the format
    226  *                               //  bits 1-15: unused yet, must be 0
    227  *
    228  *    uint32_t frames;           // Frame count
    229  *
    230  *    uint16_t flags;            // Feature flags
    231  *                               //  bits 0-15: unused yet, must be 0
    232  *
    233  * frame_info:
    234  *    struct
    235  *    {
    236  *       uint32_t width;         // Frame width
    237  *       uint32_t height;        // Frame height
    238  *       uint32_t duration;      // Frame duration in milliseconds, 0 to
    239  *                               // not specify a duration
    240  *       uint32_t attr;          // Graphics context attribute
    241  *       int32_t cursor_x;       // Cursor X coordinate
    242  *       int32_t cursor_y;       // Cursor Y coordinate
    243  *       int32_t handle_x;       // Handle X coordinate
    244  *       int32_t handle_y;       // Handle Y coordinate
    245  *    }
    246  *    frame_list[frames];
    247  *
    248  * control_extension_1:
    249  * control_extension_2:
    250  *    ...
    251  * control_extension_N:
    252  *    ...                        // reserved for future use
    253  *
    254  * canvas_data:
    255  *    uint8_t data[data_size];   // canvas data
    256  *
    257  * data_extension_1:
    258  * data_extension_2:
    259  *    ...
    260  * data_extension_N:
    261  *    ...                        // reserved for future use
    262  * };
    263  */
    264 
    265 /* Generate UTF-8 representation of current canvas. */
    266 static void *export_utf8(cucul_canvas_t *cv, unsigned long int *bytes, int cr)
    267 {
    268     static uint8_t const palette[] =
    269     {
    270         0,  4,  2,  6, 1,  5,  3,  7,
    271         8, 12, 10, 14, 9, 13, 11, 15
    272     };
    273 
    274     char *data, *cur;
    275     unsigned int x, y;
    276 
    277     /* 23 bytes assumed for max length per pixel ('\e[5;1;3x;4y;9x;10ym' plus
    278      * 4 max bytes for a UTF-8 character).
    279      * Add height*9 to that (zeroes color at the end and jump to next line) */
    280     *bytes = (cv->height * 9) + (cv->width * cv->height * 23);
    281     cur = data = malloc(*bytes);
    282 
    283     for(y = 0; y < cv->height; y++)
    284     {
    285         uint32_t *lineattr = cv->attrs + y * cv->width;
    286         uint32_t *linechar = cv->chars + y * cv->width;
    287 
    288         uint8_t prevfg = 0x10;
    289         uint8_t prevbg = 0x10;
    290 
    291         for(x = 0; x < cv->width; x++)
    292         {
    293             uint32_t attr = lineattr[x];
    294             uint32_t ch = linechar[x];
    295             uint8_t ansifg, ansibg, fg, bg;
    296 
    297             if(ch == CUCUL_MAGIC_FULLWIDTH)
    298                 continue;
    299 
    300             ansifg = cucul_attr_to_ansi_fg(attr);
    301             ansibg = cucul_attr_to_ansi_bg(attr);
    302 
    303             fg = ansifg < 0x10 ? palette[ansifg] : 0x10;
    304             bg = ansibg < 0x10 ? palette[ansibg] : 0x10;
    305 
    306             /* TODO: the [0 could be omitted in some cases */
    307             if(fg != prevfg || bg != prevbg)
    308             {
    309                 cur += sprintf(cur, "\033[0");
    310 
    311                 if(fg < 8)
    312                     cur += sprintf(cur, ";3%d", fg);
    313                 else if(fg < 16)
    314                     cur += sprintf(cur, ";1;3%d;9%d", fg - 8, fg - 8);
    315 
    316                 if(bg < 8)
    317                     cur += sprintf(cur, ";4%d", bg);
    318                 else if(bg < 16)
    319                     cur += sprintf(cur, ";5;4%d;10%d", bg - 8, bg - 8);
    320 
    321                 cur += sprintf(cur, "m");
    322             }
    323 
    324             cur += cucul_utf32_to_utf8(cur, ch);
    325 
    326             prevfg = fg;
    327             prevbg = bg;
    328         }
    329 
    330         if(prevfg != 0x10 || prevbg != 0x10)
    331             cur += sprintf(cur, "\033[0m");
    332 
    333         cur += sprintf(cur, cr ? "\r\n" : "\n");
    334     }
    335 
    336     /* Crop to really used size */
    337     *bytes = (uintptr_t)(cur - data);
    338     data = realloc(data, *bytes);
    339 
    340     return data;
    341 }
    342 
    343 /* Generate ANSI representation of current canvas. */
    344 static void *export_ansi(cucul_canvas_t *cv, unsigned long int *bytes)
    345 {
    346     static uint8_t const palette[] =
    347     {
    348         0,  4,  2,  6, 1,  5,  3,  7,
    349         8, 12, 10, 14, 9, 13, 11, 15
    350     };
    351 
    352     char *data, *cur;
    353     unsigned int x, y;
    354 
    355     uint8_t prevfg = -1;
    356     uint8_t prevbg = -1;
    357 
    358     /* 16 bytes assumed for max length per pixel ('\e[5;1;3x;4ym' plus
    359      * 1 byte for a CP437 character).
    360      * Add height*9 to that (zeroes color at the end and jump to next line) */
    361     *bytes = (cv->height * 9) + (cv->width * cv->height * 16);
    362     cur = data = malloc(*bytes);
    363 
    364     for(y = 0; y < cv->height; y++)
    365     {
    366         uint32_t *lineattr = cv->attrs + y * cv->width;
    367         uint32_t *linechar = cv->chars + y * cv->width;
    368 
    369         for(x = 0; x < cv->width; x++)
    370         {
    371             uint8_t ansifg = cucul_attr_to_ansi_fg(lineattr[x]);
    372             uint8_t ansibg = cucul_attr_to_ansi_bg(lineattr[x]);
    373             uint8_t fg = ansifg < 0x10 ? palette[ansifg] : CUCUL_LIGHTGRAY;
    374             uint8_t bg = ansibg < 0x10 ? palette[ansibg] : CUCUL_BLACK;
    375             uint32_t ch = linechar[x];
    376 
    377             if(ch == CUCUL_MAGIC_FULLWIDTH)
    378                 ch = '?';
    379 
    380             if(fg != prevfg || bg != prevbg)
    381             {
    382                 cur += sprintf(cur, "\033[0;");
    383 
    384                 if(fg < 8)
    385                     if(bg < 8)
    386                         cur += sprintf(cur, "3%d;4%dm", fg, bg);
    387                     else
    388                         cur += sprintf(cur, "5;3%d;4%dm", fg, bg - 8);
    389                 else
    390                     if(bg < 8)
    391                         cur += sprintf(cur, "1;3%d;4%dm", fg - 8, bg);
    392                     else
    393                         cur += sprintf(cur, "5;1;3%d;4%dm", fg - 8, bg - 8);
    394             }
    395 
    396             *cur++ = cucul_utf32_to_cp437(ch);
    397 
    398             prevfg = fg;
    399             prevbg = bg;
    400         }
    401 
    402         if(cv->width == 80)
    403         {
    404             cur += sprintf(cur, "\033[s\n\033[u");
    405         }
    406         else
    407         {
    408             cur += sprintf(cur, "\033[0m\r\n");
    409             prevfg = -1;
    410             prevbg = -1;
    411         }
    412     }
    413 
    414     /* Crop to really used size */
    415     *bytes = (uintptr_t)(cur - data);
    416     data = realloc(data, *bytes);
    417 
    418     return data;
    419 }
    420 
    421 /* Generate HTML representation of current canvas. */
    422 static void *export_html(cucul_canvas_t *cv, unsigned long int *bytes)
    423 {
    424     char *data, *cur;
    425     unsigned int x, y, len;
    426 
    427     /* The HTML header: less than 1000 bytes
    428      * A line: 7 chars for "<br />\n"
    429      * A glyph: 47 chars for "<span style="color:#xxx;background-color:#xxx">"
    430      *          83 chars for ";font-weight..."
    431      *          up to 9 chars for "&#xxxxxx;", far less for pure ASCII
    432      *          7 chars for "</span>" */
    433     *bytes = 1000 + cv->height * (7 + cv->width * (47 + 83 + 9 + 7));
    434     cur = data = malloc(*bytes);
    435 
    436     /* HTML header */
    437     cur += sprintf(cur, "<html><head>\n");
    438     cur += sprintf(cur, "<title>Generated by libcaca %s</title>\n", VERSION);
    439     cur += sprintf(cur, "</head><body>\n");
    440 
    441     cur += sprintf(cur, "<div cellpadding='0' cellspacing='0' style='%s'>\n",
    442                         "font-family: monospace, fixed; font-weight: bold;");
    443 
    444     for(y = 0; y < cv->height; y++)
    445     {
    446         uint32_t *lineattr = cv->attrs + y * cv->width;
    447         uint32_t *linechar = cv->chars + y * cv->width;
    448 
    449         for(x = 0; x < cv->width; x += len)
    450         {
    451             cur += sprintf(cur, "<span style=\"color:#%.03x;"
    452                                 "background-color:#%.03x",
    453                                 _cucul_attr_to_rgb12fg(lineattr[x]),
    454                                 _cucul_attr_to_rgb12bg(lineattr[x]));
    455             if(lineattr[x] & CUCUL_BOLD)
    456                 cur += sprintf(cur, ";font-weight:bold");
    457             if(lineattr[x] & CUCUL_ITALICS)
    458                 cur += sprintf(cur, ";font-style:italic");
    459             if(lineattr[x] & CUCUL_UNDERLINE)
    460                 cur += sprintf(cur, ";text-decoration:underline");
    461             if(lineattr[x] & CUCUL_BLINK)
    462                 cur += sprintf(cur, ";text-decoration:blink");
    463             cur += sprintf(cur, "\">");
    464 
    465             for(len = 0;
    466                 x + len < cv->width && lineattr[x + len] == lineattr[x];
    467                 len++)
    468             {
    469                 if(linechar[x + len] == CUCUL_MAGIC_FULLWIDTH)
    470                     ;
    471                 else if(linechar[x + len] <= 0x00000020)
    472                     cur += sprintf(cur, "&nbsp;");
    473                 else if(linechar[x + len] < 0x00000080)
    474                     cur += sprintf(cur, "%c",
    475                                    (unsigned char)linechar[x + len]);
    476                 else
    477                     cur += sprintf(cur, "&#%i;",
    478                                    (unsigned int)linechar[x + len]);
    479             }
    480             cur += sprintf(cur, "</span>");
    481         }
    482         /* New line */
    483         cur += sprintf(cur, "<br />\n");
    484     }
    485 
    486     cur += sprintf(cur, "</div></body></html>\n");
    487 
    488     /* Crop to really used size */
    489     *bytes = (uintptr_t)(cur - data);
    490     data = realloc(data, *bytes);
    491 
    492     return data;
    493 }
    494 
    495 /* Export an HTML3 document. This function is way bigger than export_html(),
    496  * but permits viewing in old browsers (or limited ones such as links). It
    497  * will not work under gecko (mozilla rendering engine) unless you set a
    498  * correct header. */
    499 static void *export_html3(cucul_canvas_t *cv, unsigned long int *bytes)
    500 {
    501     char *data, *cur;
    502     unsigned int x, y, len;
    503 
    504     /* The HTML table markup: less than 1000 bytes
    505      * A line: 10 chars for "<tr></tr>\n"
    506      * A glyph: 40 chars for "<td bgcolor=#xxxxxx><font color=#xxxxxx>"
    507      *          up to 36 chars for "<b><i><u><blink></blink></u></i></b>"
    508      *          up to 9 chars for "&#xxxxxx;", far less for pure ASCII
    509      *          12 chars for "</font></td>" */
    510     *bytes = 1000 + cv->height * (10 + cv->width * (40 + 36 + 9 + 12));
    511     cur = data = malloc(*bytes);
    512 
    513     /* Table */
    514     cur += sprintf(cur, "<table cols='%d' cellpadding='0' cellspacing='0'>\n",
    515                         cv->height);
    516 
    517     for(y = 0; y < cv->height; y++)
    518     {
    519         uint32_t *lineattr = cv->attrs + y * cv->width;
    520         uint32_t *linechar = cv->chars + y * cv->width;
    521 
    522         cur += sprintf(cur, "<tr>");
    523 
    524         for(x = 0; x < cv->width; x += len)
    525         {
    526             unsigned int i;
    527 
    528             /* Use colspan option to factor cells with same attributes
    529              * (see below) */
    530             len = 1;
    531             while(x + len < cv->width && lineattr[x + len] == lineattr[x])
    532                 len++;
    533 
    534             cur += sprintf(cur, "<td bgcolor=#%.06lx", (unsigned long int)
    535                            _cucul_attr_to_rgb24bg(lineattr[x]));
    536 
    537             if(len > 1)
    538                 cur += sprintf(cur, " colspan=%d", len);
    539 
    540             cur += sprintf(cur, "><font color=#%.06lx>", (unsigned long int)
    541                            _cucul_attr_to_rgb24fg(lineattr[x]));
    542 
    543             if(lineattr[x] & CUCUL_BOLD)
    544                 cur += sprintf(cur, "<b>");
    545             if(lineattr[x] & CUCUL_ITALICS)
    546                 cur += sprintf(cur, "<i>");
    547             if(lineattr[x] & CUCUL_UNDERLINE)
    548                 cur += sprintf(cur, "<u>");
    549             if(lineattr[x] & CUCUL_BLINK)
    550                 cur += sprintf(cur, "<blink>");
    551 
    552             for(i = 0; i < len; i++)
    553             {
    554                 if(linechar[x + i] == CUCUL_MAGIC_FULLWIDTH)
    555                     ;
    556                 else if(linechar[x + i] <= 0x00000020)
    557                     cur += sprintf(cur, "&nbsp;");
    558                 else if(linechar[x + i] < 0x00000080)
    559                     cur += sprintf(cur, "%c", (unsigned char)linechar[x + i]);
    560                 else
    561                     cur += sprintf(cur, "&#%i;", (unsigned int)linechar[x + i]);
    562             }
    563 
    564             if(lineattr[x] & CUCUL_BLINK)
    565                 cur += sprintf(cur, "</blink>");
    566             if(lineattr[x] & CUCUL_UNDERLINE)
    567                 cur += sprintf(cur, "</u>");
    568             if(lineattr[x] & CUCUL_ITALICS)
    569                 cur += sprintf(cur, "</i>");
    570             if(lineattr[x] & CUCUL_BOLD)
    571                 cur += sprintf(cur, "</b>");
    572 
    573             cur += sprintf(cur, "</font></td>");
    574         }
    575         cur += sprintf(cur, "</tr>\n");
    576     }
    577 
    578     /* Footer */
    579     cur += sprintf(cur, "</table>\n");
    580 
    581     /* Crop to really used size */
    582     *bytes = (uintptr_t)(cur - data);
    583     data = realloc(data, *bytes);
    584 
    585     return data;
    586 }
    587 
    588 /* Export a text file with IRC colours */
    589 static void *export_irc(cucul_canvas_t *cv, unsigned long int *bytes)
    590 {
    591     static uint8_t const palette[] =
    592     {
    593         1, 2, 3, 10, 5, 6, 7, 15, /* Dark */
    594         14, 12, 9, 11, 4, 13, 8, 0, /* Light */
    595     };
    596 
    597     char *data, *cur;
    598     unsigned int x, y;
    599 
    600     /* 14 bytes assumed for max length per pixel. Worst case scenario:
    601      * ^Cxx,yy   6 bytes
    602      * ^B^B      2 bytes
    603      * ch        6 bytes
    604      * 3 bytes for max length per line. Worst case scenario:
    605      * <spc>     1 byte (for empty lines)
    606      * \r\n      2 bytes
    607      * In real life, the average bytes per pixel value will be around 5.
    608      */
    609 
    610     *bytes = 2 + cv->height * (3 + cv->width * 14);
    611     cur = data = malloc(*bytes);
    612 
    613     for(y = 0; y < cv->height; y++)
    614     {
    615         uint32_t *lineattr = cv->attrs + y * cv->width;
    616         uint32_t *linechar = cv->chars + y * cv->width;
    617 
    618         uint8_t prevfg = 0x10;
    619         uint8_t prevbg = 0x10;
    620 
    621         for(x = 0; x < cv->width; x++)
    622         {
    623             uint32_t attr = lineattr[x];
    624             uint32_t ch = linechar[x];
    625             uint8_t ansifg, ansibg, fg, bg;
    626 
    627             if(ch == CUCUL_MAGIC_FULLWIDTH)
    628                 continue;
    629 
    630             ansifg = cucul_attr_to_ansi_fg(attr);
    631             ansibg = cucul_attr_to_ansi_bg(attr);
    632 
    633             fg = ansifg < 0x10 ? palette[ansifg] : 0x10;
    634             bg = ansibg < 0x10 ? palette[ansibg] : 0x10;
    635 
    636             /* TODO: optimise series of same fg / same bg
    637              *       don't change fg value if ch == ' '
    638              *       make sure the \x03,%d trick works everywhere */
    639             if(bg != prevbg || fg != prevfg)
    640             {
    641                 int need_escape = 0;
    642 
    643                 if(bg == 0x10)
    644                 {
    645                     if(fg == 0x10)
    646                         cur += sprintf(cur, "\x0f");
    647                     else
    648                     {
    649                         if(prevbg == 0x10)
    650                             cur += sprintf(cur, "\x03%d", fg);
    651                         else
    652                             cur += sprintf(cur, "\x0f\x03%d", fg);
    653 
    654                         if(ch == (uint32_t)',')
    655                             need_escape = 1;
    656                     }
    657                 }
    658                 else
    659                 {
    660                     if(fg == 0x10)
    661                         cur += sprintf(cur, "\x0f\x03,%d", bg);
    662                     else
    663                         cur += sprintf(cur, "\x03%d,%d", fg, bg);
    664                 }
    665 
    666                 if(ch >= (uint32_t)'0' && ch <= (uint32_t)'9')
    667                     need_escape = 1;
    668 
    669                 if(need_escape)
    670                     cur += sprintf(cur, "\x02\x02");
    671             }
    672 
    673             cur += cucul_utf32_to_utf8(cur, ch);
    674             prevfg = fg;
    675             prevbg = bg;
    676         }
    677 
    678         /* TODO: do the same the day we optimise whole lines above */
    679         if(!cv->width)
    680             *cur++ = ' ';
    681 
    682         *cur++ = '\r';
    683         *cur++ = '\n';
    684     }
    685 
    686     /* Crop to really used size */
    687     *bytes = (uintptr_t)(cur - data);
    688     data = realloc(data, *bytes);
    689 
    690     return data;
    691 }
    692 
    693 /* Export a PostScript document. */
    694 static void *export_ps(cucul_canvas_t *cv, unsigned long int *bytes)
    695 {
    696     static char const *ps_header =
    697         "%!\n"
    698         "%% libcaca PDF export\n"
    699         "%%LanguageLevel: 2\n"
    700         "%%Pages: 1\n"
    701         "%%DocumentData: Clean7Bit\n"
    702         "/csquare {\n"
    703         "  newpath\n"
    704         "  0 0 moveto\n"
    705         "  0 1 rlineto\n"
    706         "  1 0 rlineto\n"
    707         "  0 -1 rlineto\n"
    708         "  closepath\n"
    709         "  setrgbcolor\n"
    710         "  fill\n"
    711         "} def\n"
    712         "/S {\n"
    713         "  Show\n"
    714         "} bind def\n"
    715         "/Courier-Bold findfont\n"
    716         "8 scalefont\n"
    717         "setfont\n"
    718         "gsave\n"
    719         "6 10 scale\n";
    720 
    721     char *data, *cur;
    722     unsigned int x, y;
    723 
    724     /* 200 is arbitrary but should be ok */
    725     *bytes = strlen(ps_header) + 100 + cv->height * (32 + cv->width * 200);
    726     cur = data = malloc(*bytes);
    727 
    728     /* Header */
    729     cur += sprintf(cur, "%s", ps_header);
    730     cur += sprintf(cur, "0 %d translate\n", cv->height);
    731 
    732     /* Background, drawn using csquare macro defined in header */
    733     for(y = cv->height; y--; )
    734     {
    735         uint32_t *lineattr = cv->attrs + y * cv->width;
    736 
    737         for(x = 0; x < cv->width; x++)
    738         {
    739             uint8_t argb[8];
    740             _cucul_attr_to_argb4(*lineattr++, argb);
    741             cur += sprintf(cur, "1 0 translate\n %f %f %f csquare\n",
    742                            (float)argb[1] * (1.0 / 0xf),
    743                            (float)argb[2] * (1.0 / 0xf),
    744                            (float)argb[3] * (1.0 / 0xf));
    745         }
    746 
    747         /* Return to beginning of the line, and jump to the next one */
    748         cur += sprintf(cur, "-%d 1 translate\n", cv->width);
    749     }
    750 
    751     cur += sprintf(cur, "grestore\n"); /* Restore transformation matrix */
    752     cur += sprintf(cur, "0 %d translate\n", cv->height*10);
    753 
    754     for(y = cv->height; y--; )
    755     {
    756         uint32_t *lineattr = cv->attrs + (cv->height - y - 1) * cv->width;
    757         uint32_t *linechar = cv->chars + (cv->height - y - 1) * cv->width;
    758 
    759         for(x = 0; x < cv->width; x++)
    760         {
    761             uint8_t argb[8];
    762             uint32_t ch = *linechar++;
    763 
    764             _cucul_attr_to_argb4(*lineattr++, argb);
    765 
    766             cur += sprintf(cur, "newpath\n");
    767             cur += sprintf(cur, "%d %d moveto\n", (x + 1) * 6, y * 10 + 2);
    768             cur += sprintf(cur, "%f %f %f setrgbcolor\n",
    769                            (float)argb[5] * (1.0 / 0xf),
    770                            (float)argb[6] * (1.0 / 0xf),
    771                            (float)argb[7] * (1.0 / 0xf));
    772 
    773             if(ch < 0x00000020)
    774                 cur += sprintf(cur, "(?) show\n");
    775             else if(ch >= 0x00000080)
    776                 cur += sprintf(cur, "(?) show\n");
    777             else switch((uint8_t)(ch & 0x7f))
    778             {
    779                 case '\\':
    780                 case '(':
    781                 case ')':
    782                     cur += sprintf(cur, "(\\%c) show\n", (unsigned char)ch);
    783                     break;
    784                 default:
    785                     cur += sprintf(cur, "(%c) show\n", (unsigned char)ch);
    786                     break;
    787             }
    788         }
    789     }
    790 
    791     cur += sprintf(cur, "showpage\n");
    792 
    793     /* Crop to really used size */
    794     *bytes = (uintptr_t)(cur - data);
    795     data = realloc(data, *bytes);
    796 
    797     return data;
    798 }
    799 
    800 /* Export an SVG vector image */
    801 static void *export_svg(cucul_canvas_t *cv, unsigned long int *bytes)
    802 {
    803     static char const svg_header[] =
    804         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    805         "<svg width=\"%d\" height=\"%d\" viewBox=\"0 0 %d %d\""
    806         " xmlns=\"http://www.w3.org/2000/svg\""
    807         " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
    808         " xml:space=\"preserve\" version=\"1.1\"  baseProfile=\"full\">\n";
    809 
    810     char *data, *cur;
    811     unsigned int x, y;
    812 
    813     /* 200 is arbitrary but should be ok */
    814     *bytes = strlen(svg_header) + 128 + cv->width * cv->height * 200;
    815     cur = data = malloc(*bytes);
    816 
    817     /* Header */
    818     cur += sprintf(cur, svg_header, cv->width * 6, cv->height * 10,
    819                                     cv->width * 6, cv->height * 10);
    820 
    821     cur += sprintf(cur, " <g id=\"mainlayer\" font-size=\"10\""
    822                         " style=\"font-family: monospace\">\n");
    823 
    824     /* Background */
    825     for(y = 0; y < cv->height; y++)
    826     {
    827         uint32_t *lineattr = cv->attrs + y * cv->width;
    828 
    829         for(x = 0; x < cv->width; x++)
    830         {
    831             cur += sprintf(cur, "<rect style=\"fill:#%.03x\" x=\"%d\" y=\"%d\""
    832                                 " width=\"6\" height=\"10\"/>\n",
    833                                 _cucul_attr_to_rgb12bg(*lineattr++),
    834                                 x * 6, y * 10);
    835         }
    836     }
    837 
    838     /* Text */
    839     for(y = 0; y < cv->height; y++)
    840     {
    841         uint32_t *lineattr = cv->attrs + y * cv->width;
    842         uint32_t *linechar = cv->chars + y * cv->width;
    843 
    844         for(x = 0; x < cv->width; x++)
    845         {
    846             uint32_t ch = *linechar++;
    847 
    848             if(ch == ' ' || ch == CUCUL_MAGIC_FULLWIDTH)
    849             {
    850                 lineattr++;
    851                 continue;
    852             }
    853 
    854             cur += sprintf(cur, "<text style=\"fill:#%.03x\" "
    855                                 "x=\"%d\" y=\"%d\">",
    856                                 _cucul_attr_to_rgb12fg(*lineattr++),
    857                                 x * 6, (y * 10) + 8);
    858 
    859             if(ch < 0x00000020)
    860                 *cur++ = '?';
    861             else if(ch > 0x0000007f)
    862                 cur += cucul_utf32_to_utf8(cur, ch);
    863             else switch((uint8_t)ch)
    864             {
    865                 case '>': cur += sprintf(cur, "&gt;"); break;
    866                 case '<': cur += sprintf(cur, "&lt;"); break;
    867                 case '&': cur += sprintf(cur, "&amp;"); break;
    868                 default: *cur++ = ch; break;
    869             }
    870             cur += sprintf(cur, "</text>\n");
    871         }
    872     }
    873 
    874     cur += sprintf(cur, " </g>\n");
    875     cur += sprintf(cur, "</svg>\n");
    876 
    877     /* Crop to really used size */
    878     *bytes = (uintptr_t)(cur - data);
    879     data = realloc(data, *bytes);
    880 
    881     return data;
    882 }
    883 
    884 /* Export a TGA image */
    885 static void *export_tga(cucul_canvas_t *cv, unsigned long int *bytes)
    886 {
    887     char const * const *fontlist;
    888     char *data, *cur;
    889     cucul_font_t *f;
    890     unsigned int i, w, h;
    891 
    892     fontlist = cucul_get_font_list();
    893     if(!fontlist[0])
    894     {
    895 #if defined(HAVE_ERRNO_H)
    896         errno = EINVAL;
    897 #endif
    898         return NULL;
    899     }
    900 
    901     f = cucul_load_font(fontlist[0], 0);
    902 
    903     w = cucul_get_canvas_width(cv) * cucul_get_font_width(f);
    904     h = cucul_get_canvas_height(cv) * cucul_get_font_height(f);
    905 
    906     *bytes = w * h * 4 + 18; /* 32 bpp + 18 bytes for the header */
    907     cur = data = malloc(*bytes);
    908 
    909     /* ID Length */
    910     cur += sprintf(cur, "%c", 0);
    911     /* Color Map Type: no colormap */
    912     cur += sprintf(cur, "%c", 0);
    913     /* Image Type: uncompressed truecolor */
    914     cur += sprintf(cur, "%c", 2);
    915     /* Color Map Specification: no color map */
    916     memset(cur, 0, 5); cur += 5;
    917 
    918     /* Image Specification */
    919     cur += sprintf(cur, "%c%c", 0, 0); /* X Origin */
    920     cur += sprintf(cur, "%c%c", 0, 0); /* Y Origin */
    921     cur += sprintf(cur, "%c%c", w & 0xff, w >> 8); /* Width */
    922     cur += sprintf(cur, "%c%c", h & 0xff, h >> 8); /* Height */
    923     cur += sprintf(cur, "%c", 32); /* Pixel Depth */
    924     cur += sprintf(cur, "%c", 40); /* Image Descriptor */
    925 
    926     /* Image ID: no ID */
    927     /* Color Map Data: no colormap */
    928 
    929     /* Image Data */
    930     cucul_render_canvas(cv, f, cur, w, h, 4 * w);
    931 
    932     /* Swap bytes. What a waste of time. */
    933     for(i = 0; i < w * h * 4; i += 4)
    934     {
    935         char w;
    936         w = cur[i]; cur[i] = cur[i + 3]; cur[i + 3] = w;
    937         w = cur[i + 1]; cur[i + 1] = cur[i + 2]; cur[i + 2] = w;
    938     }
    939 
    940     cucul_free_font(f);
    941 
    942     return data;
    943 }
    944 
     60*/
  • libcaca/trunk/doc/font.dox

    r1349 r1357  
    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  *  $Id$
    7  *
    8  *  This library is free software; you can redistribute it and/or
    9  *  modify it under the terms of the Do What The Fuck You Want To
    10  *  Public License, Version 2, as published by Sam Hocevar. See
    11  *  http://sam.zoy.org/wtfpl/COPYING for more details.
    12  */
     1/* $Id$ */
    132
    14 /*
    15  *  This file contains font handling functions.
    16  */
     3/** \page font The libcaca font format (version 1)
    174
    18 #include "config.h"
    19 #include "common.h"
     5 All types are big endian.
    206
    21 #if !defined(__KERNEL__)
    22 #   if defined(HAVE_ENDIAN_H)
    23 #       include <endian.h>
    24 #   endif
    25 #   if defined(HAVE_ERRNO_H)
    26 #       include <errno.h>
    27 #   endif
    28 #   include <stdio.h>
    29 #   include <stdlib.h>
    30 #   include <string.h>
    31 #endif
     7 \code
     8struct
     9{
     10magic:
     11   uint8_t caca_header[2];    // "\xCA\xCA"
     12   uint8_t caca_file_type[2]; // "FT"
    3213
    33 #include "cucul.h"
    34 #include "cucul_internals.h"
     14font_header:
     15   uint32_t control_size;     // Control size (font_data - font_header)
     16   uint32_t data_size;        // Data size (EOF - font_data)
    3517
    36 /* Internal fonts */
    37 #include "font_mono9.h"
    38 #include "font_monobold12.h"
     18   uint16_t version;          // Font format version
     19                              //  bit 0: set to 1 if font is compatible
     20                              //         with version 1 of the format
     21                              //  bits 1-15: unused yet, must be 0
    3922
    40 /* Helper structures for font loading */
    41 #if !defined(_DOXYGEN_SKIP_ME)
    42 struct font_header
    43 {
    44     uint32_t control_size, data_size;
    45     uint16_t version, blocks;
    46     uint32_t glyphs;
    47     uint16_t bpp, width, height, flags;
     23   uint16_t blocks;           // Number of blocks in the font
     24   uint32_t glyphs;           // Total number of glyphs in the font
     25
     26   uint16_t bpp;              // Bits per pixel for glyph data (valid
     27                              // Values are 1, 2, 4 and 8)
     28   uint16_t width;            // Maximum glyph width
     29   uint16_t height;           // Maximum glyph height
     30
     31   uint16_t flags;            // Feature flags
     32                              //  bit 0: set to 1 if font is fixed width
     33                              //  bits 1-15: unused yet, must be 0
     34
     35block_info:
     36   struct
     37   {
     38      uint32_t start;         // Unicode index of the first glyph
     39      uint32_t stop;          // Unicode index of the last glyph + 1
     40      uint32_t index;         // Glyph info index of the first glyph
     41   }
     42   block_list[blocks];
     43
     44glyph_info:
     45   struct
     46   {
     47      uint16_t width;         // Glyph width in pixels
     48      uint16_t height;        // Glyph height in pixels
     49      uint32_t data_offset;   // Offset (starting from data) to the data
     50                              // for the first character
     51   }
     52   glyph_list[glyphs];
     53
     54control_extension_1:
     55control_extension_2:
     56   ...
     57control_extension_N:
     58   ...                        // reserved for future use
     59
     60font_data:
     61   uint8_t data[data_size];   // glyph data
     62
     63data_extension_1:
     64data_extension_2:
     65   ...
     66data_extension_N:
     67   ...                        // reserved for future use
    4868};
     69\endcode
    4970
    50 struct block_info
    51 {
    52     uint32_t start, stop, index;
    53 };
    54 
    55 struct glyph_info
    56 {
    57     uint16_t width, height;
    58     uint32_t data_offset;
    59 };
    60 
    61 struct cucul_font
    62 {
    63     struct font_header header;
    64 
    65     struct block_info *block_list;
    66     unsigned long int *user_block_list;
    67     struct glyph_info *glyph_list;
    68     uint8_t *font_data;
    69 
    70     uint8_t *private;
    71 };
    72 #endif
    73 
    74 #define DECLARE_UNPACKGLYPH(bpp) \
    75     static inline void \
    76       unpack_glyph ## bpp(uint8_t *glyph, uint8_t *packed_data, \
    77                           unsigned int n) \
    78 { \
    79     unsigned int i; \
    80     \
    81     for(i = 0; i < n; i++) \
    82     { \
    83         uint8_t pixel = packed_data[i / (8 / bpp)]; \
    84         pixel >>= bpp * ((8 / bpp) - 1 - (i % (8 / bpp))); \
    85         pixel %= (1 << bpp); \
    86         pixel *= 0xff / ((1 << bpp) - 1); \
    87         *glyph++ = pixel; \
    88     } \
    89 }
    90 
    91 DECLARE_UNPACKGLYPH(4)
    92 DECLARE_UNPACKGLYPH(2)
    93 DECLARE_UNPACKGLYPH(1)
    94 
    95 /** \brief Load a font from memory for future use.
    96  *
    97  *  This function loads a font and returns a handle to its internal
    98  *  structure. The handle can then be used with cucul_render_canvas()
    99  *  for bitmap output.
    100  *
    101  *  Internal fonts can also be loaded: if \c size is set to 0, \c data must
    102  *  be a string containing the internal font name.
    103  *
    104  *  If \c size is non-zero, the \c size bytes of memory at address \c data
    105  *  are loaded as a font. This memory are must not be freed by the calling
    106  *  program until the font handle has been freed with cucul_free_font().
    107  *
    108  *  If an error occurs, NULL is returned and \b errno is set accordingly:
    109  *  - \c ENOENT Requested built-in font does not exist.
    110  *  - \c EINVAL Invalid font data in memory area.
    111  *  - \c ENOMEM Not enough memory to allocate font structure.
    112  *
    113  *  \param data The memory area containing the font or its name.
    114  *  \param size The size of the memory area, or 0 if the font name is given.
    115  *  \return A font handle or NULL in case of error.
    116  */
    117 cucul_font_t *cucul_load_font(void const *data, unsigned int size)
    118 {
    119     cucul_font_t *f;
    120     unsigned int i;
    121 
    122     if(size == 0)
    123     {
    124         if(!strcasecmp(data, "Monospace 9"))
    125             return cucul_load_font((char *)&mono9_data, mono9_size);
    126         if(!strcasecmp(data, "Monospace Bold 12"))
    127             return cucul_load_font((char *)&monobold12_data, monobold12_size);
    128 
    129 #if defined(HAVE_ERRNO_H)
    130         errno = ENOENT;
    131 #endif
    132         return NULL;
    133     }
    134 
    135     if(size < sizeof(struct font_header))
    136     {
    137 #if defined(HAVE_ERRNO_H)
    138         errno = EINVAL;
    139 #endif
    140         return NULL;
    141     }
    142 
    143     f = malloc(sizeof(cucul_font_t));
    144     if(!f)
    145     {
    146 #if defined(HAVE_ERRNO_H)
    147         errno = ENOMEM;
    148 #endif
    149         return NULL;
    150     }
    151 
    152     f->private = (void *)(uintptr_t)data;
    153 
    154     memcpy(&f->header, f->private + 4, sizeof(struct font_header));
    155     f->header.control_size = hton32(f->header.control_size);
    156     f->header.data_size = hton32(f->header.data_size);
    157     f->header.version = hton16(f->header.version);
    158     f->header.blocks = hton16(f->header.blocks);
    159     f->header.glyphs = hton32(f->header.glyphs);
    160     f->header.bpp = hton16(f->header.bpp);
    161     f->header.width = hton16(f->header.width);
    162     f->header.height = hton16(f->header.height);
    163     f->header.flags = hton16(f->header.flags);
    164 
    165     if(size != 4 + f->header.control_size + f->header.data_size
    166         || (f->header.bpp != 8 && f->header.bpp != 4 &&
    167             f->header.bpp != 2 && f->header.bpp != 1)
    168         || (f->header.flags & 1) == 0)
    169     {
    170         free(f);
    171 #if defined(HAVE_ERRNO_H)
    172         errno = EINVAL;
    173 #endif
    174         return NULL;
    175     }
    176 
    177     f->block_list = malloc(f->header.blocks * sizeof(struct block_info));
    178     if(!f->block_list)
    179     {
    180         free(f);
    181 #if defined(HAVE_ERRNO_H)
    182         errno = ENOMEM;
    183 #endif
    184         return NULL;
    185     }
    186 
    187     f->user_block_list = malloc((f->header.blocks + 1)
    188                                   * 2 * sizeof(unsigned long int));
    189     if(!f->user_block_list)
    190     {
    191         free(f->block_list);
    192         free(f);
    193 #if defined(HAVE_ERRNO_H)
    194         errno = ENOMEM;
    195 #endif
    196         return NULL;
    197     }
    198 
    199     memcpy(f->block_list,
    200            f->private + 4 + sizeof(struct font_header),
    201            f->header.blocks * sizeof(struct block_info));
    202     for(i = 0; i < f->header.blocks; i++)
    203     {
    204         f->block_list[i].start = hton32(f->block_list[i].start);
    205         f->block_list[i].stop = hton32(f->block_list[i].stop);
    206         f->block_list[i].index = hton32(f->block_list[i].index);
    207 
    208         if(f->block_list[i].start > f->block_list[i].stop
    209             || (i > 0 && f->block_list[i].start < f->block_list[i - 1].stop)
    210             || f->block_list[i].index >= f->header.glyphs)
    211         {
    212             free(f->user_block_list);
    213             free(f->block_list);
    214             free(f);
    215 #if defined(HAVE_ERRNO_H)
    216             errno = EINVAL;
    217 #endif
    218             return NULL;
    219         }
    220 
    221         f->user_block_list[i * 2] = f->block_list[i].start;
    222         f->user_block_list[i * 2 + 1] = f->block_list[i].stop;
    223     }
    224 
    225     f->user_block_list[i * 2] = 0;
    226     f->user_block_list[i * 2 + 1] = 0;
    227 
    228     f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info));
    229     if(!f->glyph_list)
    230     {
    231         free(f->user_block_list);
    232         free(f->block_list);
    233         free(f);
    234 #if defined(HAVE_ERRNO_H)
    235         errno = ENOMEM;
    236 #endif
    237         return NULL;
    238     }
    239 
    240     memcpy(f->glyph_list,
    241            f->private + 4 + sizeof(struct font_header)
    242                 + f->header.blocks * sizeof(struct block_info),
    243            f->header.glyphs * sizeof(struct glyph_info));
    244     for(i = 0; i < f->header.glyphs; i++)
    245     {
    246         f->glyph_list[i].width = hton16(f->glyph_list[i].width);
    247         f->glyph_list[i].height = hton16(f->glyph_list[i].height);
    248         f->glyph_list[i].data_offset = hton32(f->glyph_list[i].data_offset);
    249 
    250         if(f->glyph_list[i].data_offset >= f->header.data_size
    251             || f->glyph_list[i].data_offset
    252                 + (f->glyph_list[i].width * f->glyph_list[i].height *
    253                    f->header.bpp + 7) / 8 > f->header.data_size)
    254         {
    255             free(f->glyph_list);
    256             free(f->user_block_list);
    257             free(f->block_list);
    258             free(f);
    259 #if defined(HAVE_ERRNO_H)
    260             errno = EINVAL;
    261 #endif
    262             return NULL;
    263         }
    264     }
    265 
    266     f->font_data = f->private + 4 + f->header.control_size;
    267 
    268     return f;
    269 }
    270 
    271 /** \brief Get available builtin fonts
    272  *
    273  *  Return a list of available builtin fonts. The list is a NULL-terminated
    274  *  array of strings.
    275  *
    276  *  This function never fails.
    277  *
    278  *  \return An array of strings.
    279  */
    280 char const * const * cucul_get_font_list(void)
    281 {
    282     static char const * const list[] =
    283     {
    284         "Monospace 9",
    285         "Monospace Bold 12",
    286         NULL
    287     };
    288 
    289     return list;
    290 }
    291 
    292 /** \brief Get a font's maximum glyph width.
    293  *
    294  *  This function returns the maximum value for the current font's glyphs
    295  *
    296  *  This function never fails.
    297  *
    298  *  \param f The font, as returned by cucul_load_font()
    299  *  \return The maximum glyph width.
    300  */
    301 unsigned int cucul_get_font_width(cucul_font_t *f)
    302 {
    303     return f->header.width;
    304 }
    305 
    306 /** \brief Get a font's maximum glyph height.
    307  *
    308  *  This function returns the maximum value for the current font's glyphs
    309  *
    310  *  This function never fails.
    311  *
    312  *  \param f The font, as returned by cucul_load_font()
    313  *  \return The maximum glyph height.
    314  */
    315 unsigned int cucul_get_font_height(cucul_font_t *f)
    316 {
    317     return f->header.height;
    318 }
    319 
    320 /** \brief Get a font's list of supported glyphs.
    321  *
    322  *  This function returns the list of Unicode blocks supported by the
    323  *  given font. The list is a zero-terminated list of indices. Here is
    324  *  an example:
    325  *
    326  *  \code
    327  *  {
    328  *       0x0,  0x80,   // Basic latin: A, B, C, a, b, c
    329  *      0x80, 0x100,   // Latin-1 supplement: "A, 'e, ^u
    330  *     0x530, 0x590,   // Armenian
    331  *       0x0,   0x0,   // END
    332  *  };
    333  *  \endcode
    334  *
    335  *  This function never fails.
    336  *
    337  *  \param f The font, as returned by cucul_load_font()
    338  *  \return The list of Unicode blocks supported by the font.
    339  */
    340 unsigned long int const *cucul_get_font_blocks(cucul_font_t *f)
    341 {
    342     return (unsigned long int const *)f->user_block_list;
    343 }
    344 
    345 /** \brief Free a font structure.
    346  *
    347  *  This function frees all data allocated by cucul_load_font(). The
    348  *  font structure is no longer usable by other libcucul functions. Once
    349  *  this function has returned, the memory area that was given to
    350  *  cucul_load_font() can be freed.
    351  *
    352  *  This function never fails.
    353  *
    354  *  \param f The font, as returned by cucul_load_font()
    355  *  \return This function always returns 0.
    356  */
    357 int cucul_free_font(cucul_font_t *f)
    358 {
    359     free(f->glyph_list);
    360     free(f->user_block_list);
    361     free(f->block_list);
    362     free(f);
    363 
    364     return 0;
    365 }
    366 
    367 /** \brief Render the canvas onto an image buffer.
    368  *
    369  *  This function renders the given canvas on an image buffer using a specific
    370  *  font. The pixel format is fixed (32-bit ARGB, 8 bits for each component).
    371  *
    372  *  The required image width can be computed using
    373  *  cucul_get_canvas_width() and cucul_get_font_width(). The required
    374  *  height can be computed using cucul_get_canvas_height() and
    375  *  cucul_get_font_height().
    376  *
    377  *  Glyphs that do not fit in the image buffer are currently not rendered at
    378  *  all. They may be cropped instead in future versions.
    379  *
    380  *  This function never fails.
    381  *
    382  *  \param cv The canvas to render
    383  *  \param f The font, as returned by cucul_load_font()
    384  *  \param buf The image buffer
    385  *  \param width The width (in pixels) of the image buffer
    386  *  \param height The height (in pixels) of the image buffer
    387  *  \param pitch The pitch (in bytes) of an image buffer line.
    388  *  \return This function always returns 0.
    389  */
    390 int cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f,
    391                         void *buf, unsigned int width,
    392                         unsigned int height, unsigned int pitch)
    393 {
    394     uint8_t *glyph = NULL;
    395     unsigned int x, y, xmax, ymax;
    396 
    397     if(f->header.bpp != 8)
    398         glyph = malloc(f->header.width * f->header.height);
    399 
    400     if(width < cv->width * f->header.width)
    401         xmax = width / f->header.width;
    402     else
    403         xmax = cv->width;
    404 
    405     if(height < cv->height * f->header.height)
    406         ymax = height / f->header.height;
    407     else
    408         ymax = cv->height;
    409 
    410     for(y = 0; y < ymax; y++)
    411     {
    412         for(x = 0; x < xmax; x++)
    413         {
    414             uint8_t argb[8];
    415             unsigned int starty = y * f->header.height;
    416             unsigned int startx = x * f->header.width;
    417             uint32_t ch = cv->chars[y * cv->width + x];
    418             uint32_t attr = cv->attrs[y * cv->width + x];
    419             unsigned int b, i, j;
    420             struct glyph_info *g;
    421 
    422             /* Find the Unicode block where our glyph lies */
    423             for(b = 0; b < f->header.blocks; b++)
    424             {
    425                 if(ch < f->block_list[b].start)
    426                 {
    427                     b = f->header.blocks;
    428                     break;
    429                 }
    430 
    431                 if(ch < f->block_list[b].stop)
    432                     break;
    433             }
    434 
    435             /* Glyph not in font? Skip it. */
    436             if(b == f->header.blocks)
    437                 continue;
    438 
    439             g = &f->glyph_list[f->block_list[b].index
    440                                 + ch - f->block_list[b].start];
    441 
    442             _cucul_attr_to_argb4(attr, argb);
    443 
    444             /* Step 1: unpack glyph */
    445             switch(f->header.bpp)
    446             {
    447             case 8:
    448                 glyph = f->font_data + g->data_offset;
    449                 break;
    450             case 4:
    451                 unpack_glyph4(glyph, f->font_data + g->data_offset,
    452                               g->width * g->height);
    453                 break;
    454             case 2:
    455                 unpack_glyph2(glyph, f->font_data + g->data_offset,
    456                               g->width * g->height);
    457                 break;
    458             case 1:
    459                 unpack_glyph1(glyph, f->font_data + g->data_offset,
    460                               g->width * g->height);
    461                 break;
    462             }
    463 
    464             /* Step 2: render glyph using colour attribute */
    465             for(j = 0; j < g->height; j++)
    466             {
    467                 uint8_t *line = buf;
    468                 line += (starty + j) * pitch + 4 * startx;
    469 
    470                 for(i = 0; i < g->width; i++)
    471                 {
    472                     uint8_t *pixel = line + 4 * i;
    473                     uint32_t p, q, t;
    474 
    475                     p = glyph[j * g->width + i];
    476                     q = 0xff - p;
    477 
    478                     for(t = 0; t < 4; t++)
    479                        pixel[t] = (((q * argb[t]) + (p * argb[4 + t])) / 0xf);
    480                 }
    481             }
    482         }
    483     }
    484 
    485     if(f->header.bpp != 8)
    486         free(glyph);
    487 
    488     return 0;
    489 }
    490 
    491 /*
    492  * The libcaca font format, version 1
    493  * ----------------------------------
    494  *
    495  * All types are big endian.
    496  *
    497  * struct
    498  * {
    499  * magic:
    500  *    uint8_t caca_header[2];    // "\xCA\xCA"
    501  *    uint8_t caca_file_type[2]; // "FT"
    502  *
    503  * font_header:
    504  *    uint32_t control_size;     // Control size (font_data - font_header)
    505  *    uint32_t data_size;        // Data size (EOF - font_data)
    506  *
    507  *    uint16_t version;          // Font format version
    508  *                               //  bit 0: set to 1 if font is compatible
    509  *                               //         with version 1 of the format
    510  *                               //  bits 1-15: unused yet, must be 0
    511  *
    512  *    uint16_t blocks;           // Number of blocks in the font
    513  *    uint32_t glyphs;           // Total number of glyphs in the font
    514  *
    515  *    uint16_t bpp;              // Bits per pixel for glyph data (valid
    516  *                               // Values are 1, 2, 4 and 8)
    517  *    uint16_t width;            // Maximum glyph width
    518  *    uint16_t height;           // Maximum glyph height
    519  *
    520  *    uint16_t flags;            // Feature flags
    521  *                               //  bit 0: set to 1 if font is fixed width
    522  *                               //  bits 1-15: unused yet, must be 0
    523  *
    524  * block_info:
    525  *    struct
    526  *    {
    527  *       uint32_t start;         // Unicode index of the first glyph
    528  *       uint32_t stop;          // Unicode index of the last glyph + 1
    529  *       uint32_t index;         // Glyph info index of the first glyph
    530  *    }
    531  *    block_list[blocks];
    532  *
    533  * glyph_info:
    534  *    struct
    535  *    {
    536  *       uint16_t width;         // Glyph width in pixels
    537  *       uint16_t height;        // Glyph height in pixels
    538  *       uint32_t data_offset;   // Offset (starting from data) to the data
    539  *                               // for the first character
    540  *    }
    541  *    glyph_list[glyphs];
    542  *
    543  * control_extension_1:
    544  * control_extension_2:
    545  *    ...
    546  * control_extension_N:
    547  *    ...                        // reserved for future use
    548  *
    549  * font_data:
    550  *    uint8_t data[data_size];   // glyph data
    551  *
    552  * data_extension_1:
    553  * data_extension_2:
    554  *    ...
    555  * data_extension_N:
    556  *    ...                        // reserved for future use
    557  * };
    558  */
    559 
     71*/
  • libcaca/trunk/doc/libcaca.dox

    r1214 r1357  
    4141 There is also information specially targeted at \e libcaca developers:
    4242
     43 - \subpage font
     44 - \subpage canvas
    4345 - \subpage style
    4446
Note: See TracChangeset for help on using the changeset viewer.