#include #include #include "language/ada.h" #include "language/assembly.h" #include "language/c.h" #include "language/c++.h" #include "language/eaxhla.h" #include "language/flat.h" #include "language/fortran.h" #include "language/xofya.h" static struct { void (* highlighter) (void); char * option_short; char * option_long; } const language [] = { { highlight_ada, "-A", "--ada" }, { highlight_assembly, "-S", "--assembly" }, { highlight_c, "-C", "--c" }, { highlight_cpp, "-P", "--c++" }, { highlight_eaxhla, "-E", "--eaxhla" }, { highlight_flat, "-T", "--flat" }, { highlight_fortran, "-F", "--fortran" }, { highlight_xofya, "-X", "--xofya" } }; static int background = 0xff181818; static int tab_width = 8; static int render_border = 10; static int * render_image = null; static int render_width = 0; static int render_height = 0; static int * font_source = null; static int font_width = 0; static int font_height = 0; static int line_number = 0; static int line_digits = 0; static void import_png_as_glyphmap (const char * path) { png_image image = { 0 }; image.version = PNG_IMAGE_VERSION; png_image_begin_read_from_file (& image, path); image.format = PNG_FORMAT_RGBA; font_width = image.width / 16; font_height = image.height / 6; font_source = allocate (image.width * image.height * (int) sizeof (* font_source)); png_image_finish_read (& image, null, font_source, 0, null); png_image_free (& image); } static void export_render_as_png (const char * path) { png_image image = { 0 }; image.version = PNG_IMAGE_VERSION; image.format = PNG_FORMAT_RGBA; image.width = (unsigned int) render_width; image.height = (unsigned int) render_height; png_image_write_to_file (& image, path, 0, render_image, 0, null); png_image_free (& image); } static int fetch_width (const char * data) { int image_width = 0; int count = 0; do { if (* data == '\t') { count += tab_width; } else if (* data == '\n') { image_width = (++count > image_width) ? count : image_width; count = 0; } else { ++count; } } while (* (++data) != '\0'); return (image_width - 1); } static int fetch_height (const char * data) { int image_height = 0; int count = 0; do { if (* data == '\n') { ++image_height; } } while (* (++data) != '\0'); count = image_height + 1; do { ++line_digits; count /= 10; } while (count > 0); return (image_height + 1); } static int interpolate_pixel (int pixel, int colour) { int r, g, b, a; a = (pixel >> 24) & 0xff; if (a == 0x00) { return (background); } else if (a == 0xff) { return (colour); } else { r = (((background >> 0) & 0xff) * (0xff - a) + ((colour >> 0) & 0xff) * a) / 0xff; g = (((background >> 8) & 0xff) * (0xff - a) + ((colour >> 8) & 0xff) * a) / 0xff; b = (((background >> 16) & 0xff) * (0xff - a) + ((colour >> 16) & 0xff) * a) / 0xff; return ((r << 0) | (g << 8) | (b << 16) | 0xff000000); } } static void render_character (char character, int * x, int * y, int colour) { int offset_x = 0; int offset_y = 0; int offset_u = (character - ' ') % 16; int offset_v = (character - ' ') / 16; for (offset_y = 0; offset_y < font_height; ++offset_y) { for (offset_x = 0; offset_x < font_width; ++offset_x) { int destination = (* y + offset_y) * render_width + (* x + offset_x); int source = (offset_v * font_height + offset_y) * font_width * 16 + (offset_u * font_width + offset_x); render_image [destination] = interpolate_pixel (font_source [source], colour); } } * x += font_width; } static void render_string (char * string, int length, int * x, int * y, int colour) { int offset; for (offset = 0; offset < length; ++offset) { if (string [offset] == '\t') { * x += font_width * tab_width; } else if (string [offset] == '\n') { * y += font_height; * x = render_border; render_string (format_to_string (++line_number, false, 10, line_digits, ' '), line_digits, x, y, (int) 0xffeeeeee); * x += font_width; } else { render_character (string [offset], x, y, colour); } } } int main (int argc, char * * argv) { int offset = 0; int select = 0; int length = 0; int x = render_border; int y = render_border; char * buffer = null; if (argc != 1) { if (string_compare (argv [1], "-v") || string_compare (argv [1], "--version")) { echo ("xarbon: Source code renderer (version 144)\n"); exit (log_success); } else if (string_compare (argv [1], "-l") || string_compare (argv [1], "--license")) { echo ("xarbon: Source code renderer (GNU/GPLv3)\n"); exit (log_success); } else if (string_compare (argv [1], "-a") || string_compare (argv [1], "--author")) { echo ("xarbon: Source code renderer (Ognjen 'xolatile' Milan Robovic)\n"); exit (log_success); } else if (string_compare (argv [1], "-h") || string_compare (argv [1], "--help")) { echo ("xarbon: Source code renderer:\n"); echo ("Example usage:\n"); echo ("\t$ cat file.ext | xarbon [flag] -- You need to pass language flag in this case.\n"); echo ("\t$ xarbon [flag] < file.ext -- You need to pass language flag in this case.\n"); echo ("\t$ xarbon file.ext -- Language is automatically detected in this case.\n"); echo ("Supported languages:\n"); echo ("\t -C --c -- C syntax\n"); echo ("\t -A --ada -- Ada syntax\n"); echo ("\t -P --cpp -- C++ syntax \n"); echo ("\t -S --assembly -- General assembly syntax\n"); echo ("\t -T --flat -- Flat assembly syntax\n"); echo ("\t -F --fortran -- Fortran syntax\n"); echo ("\t -X --xofya -- Xofya syntax\n"); exit (log_success); } else { int index; for (index = 0; index < (int) (sizeof (language) / sizeof (* language)); ++index) { if ((string_compare (argv [1], language [index].option_short) == true) || (string_compare (argv [1], language [index].option_long) == true)) { language [index].highlighter (); break; } } if (syntax_active == false) { select = file_type (argv [1]); buffer = file_import (argv [1]); } } } if (buffer == null) { buffer = record (); } if (syntax_active == false) { if ((select == file_type_c_source) || (select == file_type_c_header)) { highlight_c (); } else if ((select == file_type_ada_body) || (select == file_type_ada_specification)) { highlight_ada (); } else if ((select == file_type_cpp_source) || (select == file_type_cpp_header)) { highlight_cpp (); } else if (select == file_type_common_assembly) { highlight_assembly (); } else if (select == file_type_flat_assembly) { highlight_flat (); } else if (select == file_type_fortran_90) { highlight_fortran (); /*} else if (select == file_type_xofya) { highlight_xofya ();*/ } } import_png_as_glyphmap ("/usr/local/bin/xarbon_font.png"); render_width = fetch_width (buffer) * font_width + 2 * render_border; render_height = fetch_height (buffer) * font_height + 2 * render_border; render_width += (line_digits + 1) * font_width; render_image = allocate (render_width * render_height * (int) sizeof (* render_image)); for (offset = 0; offset < render_width * render_height; ++offset) { render_image [offset] = background; } render_string (format_to_string (++line_number, false, 10, line_digits, ' '), line_digits, & x, & y, (int) 0xffeeeeee); x += font_width; for (offset = 0; buffer [offset] != '\0'; offset += length) { select = syntax_select (& buffer [offset], & length); render_string (& buffer [offset], length, & x, & y, (select >= syntax_count) ? (int) background : syntax_colour [select]); } export_render_as_png ("./xarbon.png"); render_image = deallocate (render_image); font_source = deallocate (font_source); buffer = deallocate (buffer); return (log_success); }