int main(int argc, char *argv[]) { caca_canvas_t *cv; int tests = 0, passed = 0; cv = caca_create_canvas(0, 0); caca_put_char(cv, 0, 0, 'x'); TEST(caca_get_char(cv, 0, 0) != 'x'); caca_rotate_180(cv); caca_set_canvas_size(cv, 1, 1); TEST(caca_get_char(cv, 0, 0) != 'x'); TEST(caca_get_char(cv, 0, 0) == ' '); caca_put_char(cv, 0, 0, 'y'); TEST(caca_get_char(cv, 0, 0) == 'y'); caca_set_canvas_size(cv, 1000, 1000); TEST(caca_get_canvas_width(cv) == 1000); caca_put_char(cv, 999, 999, 'z'); TEST(caca_get_char(cv, 999, 999) == 'z'); caca_free_canvas(cv); fprintf(stderr, "%i tests, %i errors\n", tests, tests - passed); return 0; }
static int conio_init_graphics(caca_display_t *dp) { dp->drv.p = malloc(sizeof(struct driver_private)); _wscroll = 0; _setcursortype(_NOCURSOR); clrscr(); gettextinfo(&dp->drv.p->ti); dp->drv.p->screen = malloc(2 * dp->drv.p->ti.screenwidth * dp->drv.p->ti.screenheight * sizeof(char)); if(dp->drv.p->screen == NULL) return -1; # if defined(SCREENUPDATE_IN_PC_H) ScreenRetrieve(dp->drv.p->screen); # else /* FIXME */ # endif dp->resize.allow = 1; caca_set_canvas_size(dp->cv, dp->drv.p->ti.screenwidth, dp->drv.p->ti.screenheight); dp->resize.allow = 0; return 0; }
static int vga_init_graphics(caca_display_t *dp) { int i; uint8_t tmp; /* Blank screen */ memset(VGA_SCREEN, 0, 80 * 25 * 2); /* Fill VGA palette */ for(i = 0; i < 16; i++) { outb(vga_colors[i][0], 0x3c8); outb(vga_colors[i][1], 0x3c9); outb(vga_colors[i][2], 0x3c9); outb(vga_colors[i][3], 0x3c9); } /* Hide cursor */ outb(0x0a, 0x3d4); tmp = inb(0x3d5); tmp |= 0x20; outb(0x0a, 0x3d4); outb(tmp, 0x3d5); caca_add_dirty_rect(dp->cv, 0, 0, dp->cv->width, dp->cv->height); dp->resize.allow = 1; caca_set_canvas_size(dp->cv, 80, 25); /* We don't have much choice */ dp->resize.allow = 0; return 0; }
/** \brief flush the figlet context */ int caca_flush_figlet(caca_canvas_t *cv) { caca_charfont_t *ff = cv->ff; int x, y; if (!ff) return -1; //ff->torender = cv; //caca_set_canvas_size(ff->torender, ff->w, ff->h); caca_set_canvas_size(cv, ff->w, ff->h); /* FIXME: do this somewhere else, or record hardblank positions */ for(y = 0; y < ff->h; y++) for(x = 0; x < ff->w; x++) if(caca_get_char(cv, x, y) == 0xa0) { uint32_t attr = caca_get_attr(cv, x, y); caca_put_char(cv, x, y, ' '); caca_put_attr(cv, x, y, attr); } ff->x = ff->y = 0; ff->w = ff->h = 0; //cv = caca_create_canvas(1, 1); /* XXX */ /* from render.c */ ff->lines += caca_get_canvas_height(cv); return 0; }
static int flush_tiny(context_t *cx) { cx->torender = cx->cv; caca_set_canvas_size(cx->torender, cx->w, cx->h); cx->ew = 16; cx->eh = 2; cx->x = cx->y = 0; cx->w = cx->h = 0; cx->cv = caca_create_canvas(cx->ew, cx->eh); return 0; }
void _caca_handle_resize(caca_display_t *dp) { dp->drv.handle_resize(dp); /* Tell libcaca we changed size */ if(dp->resize.w != caca_get_canvas_width(dp->cv) || dp->resize.h != caca_get_canvas_height(dp->cv)) { dp->resize.allow = 1; caca_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h); dp->resize.allow = 0; } }
static int feed_tiny(context_t *cx, uint32_t ch, uint32_t attr) { switch(ch) { case (uint32_t)'\r': return 0; case (uint32_t)'\n': cx->x = 0; cx->y++; return 0; case (uint32_t)'\t': cx->x = (cx->x & ~7) + 8; return 0; } /* Check whether we reached the end of the screen */ if(cx->x && cx->x + 1 > cx->term_width) { cx->x = 0; cx->y++; } /* Check whether the current canvas is large enough */ if(cx->x + 1 > cx->w) { cx->w = cx->x + 1 < cx->term_width ? cx->x + 1 : cx->term_width; if(cx->w > cx->ew) cx->ew = cx->ew + cx->ew / 2; } if(cx->y + 1 > cx->h) { cx->h = cx->y + 1; if(cx->h > cx->eh) cx->eh = cx->eh + cx->eh / 2; } caca_set_attr(cx->cv, attr); caca_set_canvas_size(cx->cv, cx->ew, cx->eh); caca_put_char(cx->cv, cx->x, cx->y, ch); cx->x++; return 0; }
/** \brief load a figfont and attach it to a canvas */ int caca_canvas_set_figfont(caca_canvas_t *cv, char const *path) { caca_charfont_t *ff = NULL; if (path) { ff = open_charfont(path); if (!ff) return -1; } if (cv->ff) { caca_free_canvas(cv->ff->charcv); free(cv->ff->left); free(cv->ff->right); free_charfont(cv->ff); } cv->ff = ff; if (!path) return 0; /* from TOIlet’s main.c -- can be overriden by user */ ff->term_width = 80; ff->hmode = H_DEFAULT; /* from TOIlet’s render.c */ ff->x = ff->y = 0; ff->w = ff->h = 0; ff->lines = 0; caca_set_canvas_size(cv, 0, 0); /* XXX */ cv->ff = ff; update_figfont_settings(cv); return 0; }
int main(int argc, char *argv[]) { caca_canvas_t *cv; caca_display_t *dp; caca_font_t *f; caca_dither_t *d; uint8_t *buf; unsigned int w, h; char const * const * fonts; /* Create a canvas */ cv = caca_create_canvas(8, 2); if(cv == NULL) { printf("Can't create canvas\n"); return -1; } /* Draw stuff on our canvas */ caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK); caca_put_str(cv, 0, 0, "ABcde"); caca_set_color_ansi(cv, CACA_LIGHTRED, CACA_BLACK); caca_put_str(cv, 5, 0, "\\o/"); caca_set_color_ansi(cv, CACA_WHITE, CACA_BLUE); caca_put_str(cv, 0, 1, "&$âøÿØ?!"); /* Load a libcaca internal font */ fonts = caca_get_font_list(); if(fonts[0] == NULL) { fprintf(stderr, "error: libcaca was compiled without any fonts\n"); return -1; } f = caca_load_font(fonts[0], 0); if(f == NULL) { fprintf(stderr, "error: could not load font \"%s\"\n", fonts[0]); return -1; } /* Create our bitmap buffer (32-bit ARGB) */ w = caca_get_canvas_width(cv) * caca_get_font_width(f); h = caca_get_canvas_height(cv) * caca_get_font_height(f); buf = malloc(4 * w * h); /* Render the canvas onto our image buffer */ caca_render_canvas(cv, f, buf, w, h, 4 * w); /* Just for fun, render the image using libcaca */ caca_set_canvas_size(cv, 80, 32); dp = caca_create_display(cv); { #if defined(HAVE_ENDIAN_H) if(__BYTE_ORDER == __BIG_ENDIAN) #else /* This is compile-time optimised with at least -O1 or -Os */ uint32_t const tmp = 0x12345678; if(*(uint8_t const *)&tmp == 0x12) #endif d = caca_create_dither(32, w, h, 4 * w, 0xff0000, 0xff00, 0xff, 0xff000000); else d = caca_create_dither(32, w, h, 4 * w, 0xff00, 0xff0000, 0xff000000, 0xff); } caca_dither_bitmap(cv, 0, 0, caca_get_canvas_width(cv), caca_get_canvas_height(cv), d, buf); caca_refresh_display(dp); caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, -1); /* Free everything */ caca_free_display(dp); free(buf); caca_free_dither(d); caca_free_font(f); caca_free_canvas(cv); return 0; }
static int ncurses_init_graphics(caca_display_t *dp) { static int curses_colors[] = { /* Standard curses colours */ COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, /* Extra values for xterm-16color */ COLOR_BLACK + 8, COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8, COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8 }; mmask_t newmask; int fg, bg, max; dp->drv.p = malloc(sizeof(struct driver_private)); #if defined HAVE_GETENV && defined HAVE_PUTENV ncurses_install_terminal(dp); #endif #if defined HAVE_SIGNAL sigwinch_d = dp; signal(SIGWINCH, sigwinch_handler); #endif #if defined HAVE_LOCALE_H setlocale(LC_ALL, ""); #endif _caca_set_term_title("caca for ncurses"); initscr(); keypad(stdscr, TRUE); nonl(); raw(); noecho(); nodelay(stdscr, TRUE); curs_set(0); /* Activate mouse */ newmask = REPORT_MOUSE_POSITION | ALL_MOUSE_EVENTS; mousemask(newmask, &dp->drv.p->oldmask); mouseinterval(-1); /* No click emulation */ /* Set the escape delay to a ridiculously low value */ ESCDELAY = 10; /* Activate colour */ start_color(); /* If COLORS == 16, it means the terminal supports full bright colours * using setab and setaf (will use \e[90m \e[91m etc. for colours >= 8), * we can build 16*16 colour pairs. * If COLORS == 8, it means the terminal does not know about bright * colours and we need to get them through A_BOLD and A_BLINK (\e[1m * and \e[5m). We can only build 8*8 colour pairs. */ max = COLORS >= 16 ? 16 : 8; for(bg = 0; bg < max; bg++) for(fg = 0; fg < max; fg++) { /* Use ((max + 7 - fg) % max) instead of fg so that colour 0 * is light gray on black. Some terminals don't like this * colour pair to be redefined. */ int col = ((max + 7 - fg) % max) + max * bg; init_pair(col, curses_colors[fg], curses_colors[bg]); dp->drv.p->attr[fg + 16 * bg] = COLOR_PAIR(col); if(max == 8) { /* Bright fg on simple bg */ dp->drv.p->attr[fg + 8 + 16 * bg] = A_BOLD | COLOR_PAIR(col); /* Simple fg on bright bg */ dp->drv.p->attr[fg + 16 * (bg + 8)] = A_BLINK | COLOR_PAIR(col); /* Bright fg on bright bg */ dp->drv.p->attr[fg + 8 + 16 * (bg + 8)] = A_BLINK | A_BOLD | COLOR_PAIR(col); } } caca_add_dirty_rect(dp->cv, 0, 0, dp->cv->width, dp->cv->height); dp->resize.allow = 1; caca_set_canvas_size(dp->cv, COLS, LINES); dp->resize.allow = 0; return 0; }
static int win32_init_graphics(caca_display_t *dp) { int width = caca_get_canvas_width(dp->cv); int height = caca_get_canvas_height(dp->cv); CONSOLE_SCREEN_BUFFER_INFO csbi; SMALL_RECT rect; COORD size; dp->drv.p = malloc(sizeof(struct driver_private)); /* This call is allowed to fail in case we already have a console */ AllocConsole(); dp->drv.p->hin = GetStdHandle(STD_INPUT_HANDLE); dp->drv.p->hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(dp->drv.p->hout == INVALID_HANDLE_VALUE) return -1; GetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci); dp->drv.p->cci.bVisible = FALSE; SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci); SetConsoleMode(dp->drv.p->hout, ENABLE_MOUSE_INPUT); dp->drv.p->screen = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); if(!dp->drv.p->screen || dp->drv.p->screen == INVALID_HANDLE_VALUE) return -1; /* Set the new console size */ size.X = width ? width : 80; size.Y = height ? height : 25; SetConsoleScreenBufferSize(dp->drv.p->screen, size); rect.Left = rect.Top = 0; rect.Right = size.X - 1; rect.Bottom = size.Y - 1; SetConsoleWindowInfo(dp->drv.p->screen, TRUE, &rect); /* Report our new size to libcaca */ if(!GetConsoleScreenBufferInfo(dp->drv.p->screen, &csbi)) return -1; dp->resize.allow = 1; caca_set_canvas_size(dp->cv, csbi.srWindow.Right - csbi.srWindow.Left + 1, csbi.srWindow.Bottom - csbi.srWindow.Top + 1); width = caca_get_canvas_width(dp->cv); height = caca_get_canvas_height(dp->cv); dp->resize.allow = 0; SetConsoleMode(dp->drv.p->screen, 0); GetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci); dp->drv.p->cci.dwSize = 0; dp->drv.p->cci.bVisible = FALSE; SetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci); SetConsoleActiveScreenBuffer(dp->drv.p->screen); dp->drv.p->buffer = malloc(width * height * sizeof(CHAR_INFO)); if(dp->drv.p->buffer == NULL) return -1; return 0; }
static int slang_init_graphics(caca_display_t *dp) { dp->drv.p = malloc(sizeof(struct driver_private)); dp->drv.p->sigint_event = 0; #if defined(HAVE_GETENV) && defined(HAVE_PUTENV) slang_install_terminal(dp); #endif #if defined(HAVE_SIGNAL) sigwinch_d = dp; signal(SIGWINCH, sigwinch_handler); #endif _caca_set_term_title("caca for S-Lang"); /* Initialise slang library */ SLsig_block_signals(); /* Disable SLang's own SIGINT on ctrl-c */ SLang_set_abort_signal(default_sigint); SLtt_get_terminfo(); if(SLkp_init() == -1) { SLsig_unblock_signals(); return -1; } SLang_init_tty(-1, 0, 1); if(SLsmg_init_smg() == -1) { SLsig_unblock_signals(); return -1; } SLsmg_cls(); SLtt_set_cursor_visibility(0); SLkp_define_keysym("\e[M", 1001); SLtt_set_mouse_mode(1, 0); SLsmg_refresh(); /* Disable scrolling so that hashmap scrolling optimization code * does not cause ugly refreshes due to slow terminals */ SLtt_Term_Cannot_Scroll = 1; slang_init_palette(); #if defined(VMS) || defined(REAL_UNIX_SYSTEM) /* Disable alt charset support so that we get a chance to have all * 256 colour pairs */ SLtt_Has_Alt_Charset = 0; #endif #ifdef HAVE_SLSMG_UTF8_ENABLE SLsmg_utf8_enable(1); /* 1 == force, 0 == disable, -1 == autodetect */ SLtt_utf8_enable(1); #endif caca_add_dirty_rect(dp->cv, 0, 0, dp->cv->width, dp->cv->height); dp->resize.allow = 1; caca_set_canvas_size(dp->cv, SLtt_Screen_Cols, SLtt_Screen_Rows); dp->resize.allow = 0; SLsig_unblock_signals(); return 0; }
int main(int argc, char **argv) { static caca_display_t *dp; static caca_canvas_t *frontcv, *backcv, *mask; int demo, next = -1, paused = 0, next_transition = DEMO_FRAMES; unsigned int i; int tmode = caca_rand(0, TRANSITION_COUNT); /* Set up two canvases, a mask, and attach a display to the front one */ frontcv = caca_create_canvas(0, 0); backcv = caca_create_canvas(0, 0); mask = caca_create_canvas(0, 0); dp = caca_create_display(frontcv); if(!dp) return 1; caca_set_canvas_size(backcv, caca_get_canvas_width(frontcv), caca_get_canvas_height(frontcv)); caca_set_canvas_size(mask, caca_get_canvas_width(frontcv), caca_get_canvas_height(frontcv)); caca_set_display_time(dp, 20000); /* Initialise all demos' lookup tables */ for(i = 0; i < DEMOS; i++) fn[i](PREPARE, frontcv); /* Choose a demo at random */ demo = caca_rand(0, DEMOS); fn[demo](INIT, frontcv); for(;;) { /* Handle events */ caca_event_t ev; while(caca_get_event(dp, CACA_EVENT_KEY_PRESS | CACA_EVENT_QUIT, &ev, 0)) { if(caca_get_event_type(&ev) == CACA_EVENT_QUIT) goto end; switch(caca_get_event_key_ch(&ev)) { case CACA_KEY_ESCAPE: case CACA_KEY_CTRL_C: case CACA_KEY_CTRL_Z: goto end; case ' ': paused = !paused; break; case '\r': if(next == -1) next_transition = frame; break; } } /* Resize the spare canvas, just in case the main one changed */ caca_set_canvas_size(backcv, caca_get_canvas_width(frontcv), caca_get_canvas_height(frontcv)); caca_set_canvas_size(mask, caca_get_canvas_width(frontcv), caca_get_canvas_height(frontcv)); if(paused) goto _paused; /* Update demo's data */ fn[demo](UPDATE, frontcv); /* Handle transitions */ if(frame == next_transition) { next = caca_rand(0, DEMOS); if(next == demo) next = (next + 1) % DEMOS; fn[next](INIT, backcv); } else if(frame == next_transition + TRANSITION_FRAMES) { fn[demo](FREE, frontcv); demo = next; next = -1; next_transition = frame + DEMO_FRAMES; tmode = caca_rand(0, TRANSITION_COUNT); } if(next != -1) fn[next](UPDATE, backcv); frame++; _paused: /* Render main demo's canvas */ fn[demo](RENDER, frontcv); /* If a transition is on its way, render it */ if(next != -1) { fn[next](RENDER, backcv); caca_set_color_ansi(mask, CACA_LIGHTGRAY, CACA_BLACK); caca_clear_canvas(mask); caca_set_color_ansi(mask, CACA_WHITE, CACA_WHITE); transition(mask, tmode, 100 * (frame - next_transition) / TRANSITION_FRAMES); caca_blit(frontcv, 0, 0, backcv, mask); } caca_set_color_ansi(frontcv, CACA_WHITE, CACA_BLUE); if(frame < 100) caca_put_str(frontcv, caca_get_canvas_width(frontcv) - 30, caca_get_canvas_height(frontcv) - 2, " -=[ Powered by libcaca ]=- "); caca_refresh_display(dp); } end: if(next != -1) fn[next](FREE, frontcv); fn[demo](FREE, frontcv); caca_free_display(dp); caca_free_canvas(mask); caca_free_canvas(backcv); caca_free_canvas(frontcv); return 0; }
/** \brief paste a character using the current figfont */ int caca_put_figchar(caca_canvas_t *cv, uint32_t ch) { caca_charfont_t *ff = cv->ff; int c, w, h, x, y, overlap, extra, xleft, xright; if (!ff) return -1; switch(ch) { case (uint32_t)'\r': return 0; case (uint32_t)'\n': ff->x = 0; ff->y += ff->height; return 0; /* FIXME: handle '\t' */ } /* Look whether our glyph is available */ for(c = 0; c < ff->glyphs; c++) if(ff->lookup[c * 2] == ch) break; if(c == ff->glyphs) return 0; w = ff->lookup[c * 2 + 1]; h = ff->height; caca_set_canvas_handle(ff->fontcv, 0, c * ff->height); caca_blit(ff->charcv, 0, 0, ff->fontcv, NULL); /* Check whether we reached the end of the screen */ if(ff->x && ff->x + w > ff->term_width) { ff->x = 0; ff->y += h; } /* Compute how much the next character will overlap */ switch(ff->hmode) { case H_SMUSH: case H_KERN: case H_OVERLAP: extra = (ff->hmode == H_OVERLAP); overlap = w; for(y = 0; y < h; y++) { /* Compute how much spaces we can eat from the new glyph */ for(xright = 0; xright < overlap; xright++) if(caca_get_char(ff->charcv, xright, y) != ' ') break; /* Compute how much spaces we can eat from the previous glyph */ for(xleft = 0; xright + xleft < overlap && xleft < ff->x; xleft++) if(caca_get_char(cv, ff->x - 1 - xleft, ff->y + y) != ' ') break; /* Handle overlapping */ if(ff->hmode == H_OVERLAP && xleft < ff->x) xleft++; /* Handle smushing */ if(ff->hmode == H_SMUSH) { if(xleft < ff->x && hsmush(caca_get_char(cv, ff->x - 1 - xleft, ff->y + y), caca_get_char(ff->charcv, xright, y), ff->hsmushrule)) xleft++; } if(xleft + xright < overlap) overlap = xleft + xright; } break; case H_NONE: overlap = 0; break; default: return -1; } /* Check whether the current canvas is large enough */ if(ff->x + w - overlap > ff->w) ff->w = ff->x + w - overlap < ff->term_width ? ff->x + w - overlap : ff->term_width; if(ff->y + h > ff->h) ff->h = ff->y + h; #if 0 /* deactivated for libcaca insertion */ if(attr) caca_set_attr(cv, attr); #endif caca_set_canvas_size(cv, ff->w, ff->h); /* Render our char (FIXME: create a rect-aware caca_blit_canvas?) */ for(y = 0; y < h; y++) for(x = 0; x < w; x++) { uint32_t ch1, ch2; uint32_t tmpat = caca_get_attr(ff->fontcv, x, y + c * ff->height); ch2 = caca_get_char(ff->charcv, x, y); if(ch2 == ' ') continue; ch1 = caca_get_char(cv, ff->x + x - overlap, ff->y + y); if(ch1 == ' ' || ff->hmode != H_SMUSH) caca_put_char(cv, ff->x + x - overlap, ff->y + y, ch2); else caca_put_char(cv, ff->x + x - overlap, ff->y + y, hsmush(ch1, ch2, ff->hsmushrule)); caca_put_attr(cv, ff->x + x, ff->y + y, tmpat); } /* Advance cursor */ ff->x += w - overlap; return 0; }
JNIEXPORT void JNICALL Java_org_zoy_caca_Canvas_setCanvasSize(JNIEnv *env, jclass cls, jlong ptr, jint w, jint h) { caca_set_canvas_size((caca_canvas_t *)ptr, w, h); }