hackthelobby/libcaca/caca/caca0.c

294 lines
7.6 KiB
C

/*
* libcaca Colour ASCII-Art library
* Copyright (c) 2002-2012 Sam Hocevar <sam@hocevar.net>
* All Rights Reserved
*
* This library is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What the Fuck You Want
* to Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details.
*/
/*
* This file contains glue code for applications using the pre-1.0
* libcaca API.
*/
#include "config.h"
#if !defined(__KERNEL__)
# include <stdlib.h>
#endif
#include "caca0.h"
/* These variables are needed to emulate old non-thread safe behaviour */
caca_canvas_t *__caca0_cv = NULL;
caca_display_t *__caca0_dp = NULL;
unsigned char __caca0_fg = CACA_LIGHTGRAY;
unsigned char __caca0_bg = CACA_BLACK;
char __caca0_utf8[2] = " ";
/* These functions are needed, too */
int __caca0_init(void);
void __caca0_end(void);
unsigned int __caca0_get_event(unsigned int, int);
unsigned int __caca0_sqrt(unsigned int);
int __caca0_get_feature(int);
void __caca0_set_feature(int);
char const *__caca0_get_feature_name(int);
caca_canvas_t *__caca0_load_sprite(char const *);
caca_dither_t *__caca0_create_bitmap(unsigned int, unsigned int,
unsigned int, unsigned int, unsigned long int, unsigned long int,
unsigned long int, unsigned long int);
void __caca0_free_bitmap(caca_dither_t *);
extern char const *__caca0_get_color_name(unsigned char);
/* Emulation functions */
int __caca0_init(void)
{
__caca0_cv = caca_create_canvas(0, 0);
if(!__caca0_cv)
return -1;
__caca0_dp = caca_create_display(__caca0_cv);
if(!__caca0_dp)
{
caca_free_canvas(__caca0_cv);
__caca0_cv = NULL;
return -1;
}
__caca0_fg = CACA_LIGHTGRAY;
__caca0_bg = CACA_BLACK;
return 0;
}
void __caca0_end(void)
{
caca_free_display(__caca0_dp);
__caca0_dp = NULL;
caca_free_canvas(__caca0_cv);
__caca0_cv = NULL;
}
unsigned int __caca0_get_event(unsigned int m, int t)
{
caca_event_t ev;
int ret;
ret = caca_get_event(__caca0_dp, (m >> 24) & 0x7f, &ev, t);
if(!ret)
return 0x00000000;
switch(caca_get_event_type(&ev))
{
case CACA_EVENT_KEY_PRESS:
return 0x01000000 | caca_get_event_key_ch(&ev);
case CACA_EVENT_KEY_RELEASE:
return 0x02000000 | caca_get_event_key_ch(&ev);
case CACA_EVENT_MOUSE_PRESS:
return 0x04000000 | caca_get_event_mouse_button(&ev);
case CACA_EVENT_MOUSE_RELEASE:
return 0x08000000 | caca_get_event_mouse_button(&ev);
case CACA_EVENT_MOUSE_MOTION:
return 0x10000000 | ((caca_get_event_mouse_x(&ev) & 0xfff) << 12)
| (caca_get_event_mouse_y(&ev) & 0xfff);
case CACA_EVENT_RESIZE:
return 0x20000000;
default:
break;
}
return 0x00000000;
}
unsigned int __caca0_sqrt(unsigned int a)
{
if(a == 0)
return 0;
if(a < 1000000000)
{
unsigned int x = a < 10 ? 1
: a < 1000 ? 10
: a < 100000 ? 100
: a < 10000000 ? 1000
: 10000;
/* Newton's method. Three iterations would be more than enough. */
x = (x * x + a) / x / 2;
x = (x * x + a) / x / 2;
x = (x * x + a) / x / 2;
x = (x * x + a) / x / 2;
return x;
}
return 2 * __caca0_sqrt(a / 4);
}
static char const *features[] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "16", "full16", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "none", "prefilter", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "none", "ordered2", "ordered4", "ordered8", "random"
};
static caca_dither_t **bitmaps = NULL;
static unsigned int nbitmaps = 0;
static int background = 0x12;
static int antialiasing = 0x22;
static int dithering = 0x33;
int __caca0_get_feature(int feature)
{
if(feature == 0x10)
return background;
if(feature == 0x20)
return antialiasing;
if(feature == 0x30)
return dithering;
return 0xffff; /* CACA_FEATURE_UNKNOWN */
}
void __caca0_set_feature(int feature)
{
unsigned int i;
switch(feature)
{
case 0x10: feature = 0x12; /* CACA_BACKGROUND_SOLID */
case 0x11: case 0x12:
background = feature;
for(i = 0; i < nbitmaps; i++)
caca_set_dither_color(bitmaps[i], features[feature]);
break;
case 0x20: feature = 0x22; /* CACA_ANTIALIASING_PREFILTER */
case 0x21: case 0x22:
antialiasing = feature;
for(i = 0; i < nbitmaps; i++)
caca_set_dither_antialias(bitmaps[i], features[feature]);
break;
case 0x30: feature = 0x33; /* CACA_DITHERING_ORDERED4 */
case 0x31: case 0x32: case 0x33: case 0x34: case 0x35:
dithering = feature;
for(i = 0; i < nbitmaps; i++)
caca_set_dither_algorithm(bitmaps[i], features[feature]);
break;
}
}
char const *__caca0_get_feature_name(int feature)
{
switch(feature)
{
case 0x11: return "black background";
case 0x12: return "solid background";
case 0x21: return "no antialiasing";
case 0x22: return "prefilter antialiasing";
case 0x31: return "no dithering";
case 0x32: return "2x2 ordered dithering";
case 0x33: return "4x4 ordered dithering";
case 0x34: return "8x8 ordered dithering";
case 0x35: return "random dithering";
default: return "unknown";
}
}
caca_canvas_t *__caca0_load_sprite(char const *file)
{
caca_canvas_t *cv;
cv = caca_create_canvas(0, 0);;
if(caca_import_canvas_from_file(cv, file, "") < 0)
{
caca_free_canvas(cv);
return NULL;
}
return cv;
}
caca_dither_t *__caca0_create_bitmap(unsigned int bpp, unsigned int w,
unsigned int h, unsigned int pitch,
unsigned long int r, unsigned long int g,
unsigned long int b, unsigned long int a)
{
caca_dither_t *d;
d = caca_create_dither(bpp, w, h, pitch, r, g, b, a);
if(!d)
return NULL;
caca_set_dither_color(d, features[background]);
caca_set_dither_antialias(d, features[antialiasing]);
caca_set_dither_algorithm(d, features[dithering]);
/* Store bitmap in our list */
nbitmaps++;
bitmaps = realloc(bitmaps, nbitmaps * (sizeof(caca_dither_t *)));
bitmaps[nbitmaps - 1] = d;
return d;
}
void __caca0_free_bitmap(caca_dither_t *d)
{
unsigned int i, found = 0;
caca_free_dither(d);
/* Remove bitmap from our list */
for(i = 0; i + 1 < nbitmaps; i++)
{
if(bitmaps[i] == d)
found = 1;
if(found)
bitmaps[i] = bitmaps[i + 1];
}
nbitmaps--;
}
char const *__caca0_get_color_name(unsigned char color)
{
static char const *color_names[] =
{
"black",
"blue",
"green",
"cyan",
"red",
"magenta",
"brown",
"light gray",
"dark gray",
"light blue",
"light green",
"light cyan",
"light red",
"light magenta",
"yellow",
"white",
};
if(color > 15)
return "unknown";
return color_names[(unsigned int)color];
}