/* mbed GraphicsDisplay Display Library Base Class
 * Copyright (c) 2007-2009 sford
 * Released under the MIT License: http://mbed.org/license/mit
 */

#include "GraphicsDisplay.h"
#include "emscripten.h"

const unsigned char FONT8x8[97][8] = {
{ 0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00 }, // columns, rows, num_bytes_per_char
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // space 0x20
{ 0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00 }, // !
{ 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00 }, // "
{ 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00 }, // #
{ 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00 }, // $
{ 0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00 }, // %
{ 0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00 }, // &
{ 0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00 }, // '
{ 0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00 }, // (
{ 0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00 }, // )
{ 0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00 }, // *
{ 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00 }, // +
{ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30 }, // ,
{ 0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00 }, // -
{ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 }, // .
{ 0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00 }, // / (forward slash)
{ 0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00 }, // 0 0x30
{ 0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00 }, // 1
{ 0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00 }, // 2
{ 0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00 }, // 3
{ 0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00 }, // 4
{ 0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00 }, // 5
{ 0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00 }, // 6
{ 0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00 }, // 7
{ 0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00 }, // 8
{ 0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00 }, // 9
{ 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00 }, // :
{ 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30 }, // ;
{ 0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00 }, // <
{ 0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00 }, // =
{ 0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00 }, // >
{ 0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00 }, // ?
{ 0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00 }, // @ 0x40
{ 0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00 }, // A
{ 0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00 }, // B
{ 0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00 }, // C
{ 0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00 }, // D
{ 0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00 }, // E
{ 0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00 }, // F
{ 0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00 }, // G
{ 0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00 }, // H
{ 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00 }, // I
{ 0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00 }, // J
{ 0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00 }, // K
{ 0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00 }, // L
{ 0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00 }, // M
{ 0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00 }, // N
{ 0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00 }, // O
{ 0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00 }, // P 0x50
{ 0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00 }, // Q
{ 0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00 }, // R
{ 0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00 }, // S
{ 0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00 }, // T
{ 0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00 }, // U
{ 0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00 }, // V
{ 0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00 }, // W
{ 0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00 }, // X
{ 0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00 }, // Y
{ 0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00 }, // Z
{ 0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00 }, // [
{ 0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00 }, // \ (back slash)
{ 0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00 }, // ]
{ 0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00 }, // ^
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF }, // _
{ 0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00 }, // ` 0x60
{ 0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00 }, // a
{ 0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00 }, // b
{ 0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00 }, // c
{ 0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00 }, // d
{ 0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00 }, // e
{ 0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00 }, // f
{ 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C }, // g
{ 0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00 }, // h
{ 0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00 }, // i
{ 0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C }, // j
{ 0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00 }, // k
{ 0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00 }, // l
{ 0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00 }, // m
{ 0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00 }, // n
{ 0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00 }, // o
{ 0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78 }, // p
{ 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F }, // q
{ 0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00 }, // r
{ 0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00 }, // s
{ 0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00 }, // t
{ 0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00 }, // u
{ 0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00 }, // v
{ 0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00 }, // w
{ 0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00 }, // x
{ 0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C }, // y
{ 0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00 }, // z
{ 0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00 }, // {
{ 0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00 }, // |
{ 0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00 }, // }
{ 0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00 }, // ~
{ 0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00 }  // DEL
};

GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
    foreground(0xFFFF);
    background(0x0000);
}

void GraphicsDisplay::character(int column, int row, int value) {
    blitbit(column * 8, row * 8, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));
}

void GraphicsDisplay::window(int x, int y, int w, int h) {
    // current pixel location
    _x = x;
    _y = y;
    // window settings
    _x1 = x;
    _x2 = x + w - 1;
    _y1 = y;
    _y2 = y + h - 1;
}

void GraphicsDisplay::putp(int colour) {
    // put pixel at current pixel location
    pixel(_x, _y, colour);
    // update pixel location based on window settings
    _x++;
    if(_x > _x2) {
        _x = _x1;
        _y++;
        if(_y > _y2) {
            _y = _y1;
        }
    }
}

void GraphicsDisplay::fill(int x, int y, int w, int h, int colour) {
    window(x, y, w, h);
    for(int i=0; i<w*h; i++) {
        putp(colour);
    }
}

void GraphicsDisplay::cls() {
    fill(0, 0, width(), height(), _background);
}

void GraphicsDisplay::blit(int x, int y, int w, int h, const int *colour) {
    window(x, y, w, h);
    for(int i=0; i<w*h; i++) {
        putp(colour[i]);
    }
}

void GraphicsDisplay::blitbit(int x, int y, int w, int h, const char* colour) {
    window(x, y, w, h);
    for(int i = 0; i < w*h; i++) {
        char byte = colour[i >> 3];
        int offset = i & 0x7;
        int c = ((byte << offset) & 0x80) ? _foreground : _background;
        putp(c);
    }
}

int GraphicsDisplay::columns() {
    return width() / 8;
}

int GraphicsDisplay::rows() {
    return height() / 8;
}
