erythros/System/Libraries/Graphics2D.HC

1845 lines
63 KiB
HolyC

JsonObject* Fonts = Json.CreateObject(adam_task);
#define C2D_MAGIC 0xDEDEDEDEDEDEDEDE
class @context2d
{
I64 width;
I64 height;
U32* fb;
I64 opacity;
};
class @callable_context2d : @context2d
{
@callable_context2d* (*blot)(I64 x, I64 y, @callable_context2d* src);
@callable_context2d* (*blur)(I64 radius);
@callable_context2d* (*copy_rect)(I64 x, I64 y, @callable_context2d* rect);
@callable_context2d* (*fill)(U32 color = 0);
@callable_context2d* (*fill_rect)(I64 x, I64 y, I64 w, I64 h, U32 color);
U32 (*peek)(I64 x, I64 y);
@callable_context2d* (*plot)(I64 x, I64 y, U32 color);
@callable_context2d* (*line)(I64 x1, I64 y1, I64 x2, I64 y2, U32 color);
@callable_context2d* (*text)(U64 font, I64 x, I64 y, I64 size, U32 color, U8* text);
@callable_context2d* (*clipped)();
@callable_context2d* (*rotated)(F64 angle);
@callable_context2d* (*scaled)(F64 scale_x, F64 scale_y);
};
extern @callable_context2d* @create_callable_context2d(@context2d* ctx);
#define Context2D @callable_context2d
class Bounds2D {
I64 x1;
I64 y1;
I64 x2;
I64 y2;
};
U32 Color(I64 r, I64 g, I64 b, I64 a = 255)
{
U32 c;
c.u8[0] = b;
c.u8[1] = g;
c.u8[2] = r;
c.u8[3] = a;
return c;
}
U32 ColorHSVToRGB(I64 hue, I64 saturation, I64 value)
{
if (!(0 <= hue < 360))
hue = 0;
if (!(0 <= saturation <= 100))
saturation = 100;
if (!(0 <= value <= 100))
value = 100;
F64 s = saturation / 100.0;
F64 v = value / 100.0;
F64 c = v * s;
F64 x = c * (1 - Abs(((hue / 60.0) % 2) - 1));
F64 m = v - c;
F64 r, g, b;
switch (hue) {
case 0...59:
r = c;
g = x;
b = 0;
break;
case 60...119:
r = x;
g = c;
b = 0;
break;
case 120...179:
r = 0;
g = c;
b = x;
break;
case 180...239:
r = 0;
g = x;
b = c;
break;
case 240...299:
r = x;
g = 0;
b = c;
break;
case 300...359:
r = c;
g = 0;
b = x;
break;
}
return Color(ToI64((r + m) * 255), ToI64((g + m) * 255), ToI64((b + m) * 255));
}
U0 ColorRGBToHSV(U32 color, I64* hue, I64* saturation, I64* value)
{
if (!hue || !saturation || !value)
return;
F64 r = color.u8[2] / 255.0;
F64 g = color.u8[1] / 255.0;
F64 b = color.u8[0] / 255.0;
F64 cMax = Max(r, Max(g, b));
F64 cMin = Min(r, Min(g, b));
F64 delta = cMax - cMin;
if (delta == 0)
*hue = 0;
else if (cMax == r)
*hue = 60 * (((g - b) / delta) % 6);
else if (cMax == g)
*hue = 60 * (((b - r) / delta) + 2);
else
*hue = 60 * (((r - g) / delta) + 4);
if (cMax != 0)
*saturation = (delta / cMax) * 100;
else
*saturation = 0;
*value = cMax * 100;
}
/*
* ISO Latin-1 Font
*
* Copyright (c) 2000
* Ka-Ping Yee <ping@lfw.org>
*
* This font may be freely used for any purpose.
*/
/*
* adjusted 'A' 'V' to improve their dense appearance (ie. lightened)
* adjusted 'i' 'l' to improve their flow within a word (ie. widened)
* adjusted 'E' 'F' '#'
*/
U8 console_font[256 * 16] = {
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 11 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 21 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 22 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 23 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 24 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 25 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 26 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 29 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 31 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 32 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 33 */ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 34 */ 0x00, 0x00, 0x6c, 0x6c, 0x36, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 35 */ 0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x36,
0x7f, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 36 */ 0x00, 0x08, 0x08, 0x3e, 0x6b, 0x0b, 0x0b, 0x3e,
0x68, 0x68, 0x6b, 0x3e, 0x08, 0x08, 0x00, 0x00,
/* 37 */ 0x00, 0x00, 0x00, 0x33, 0x13, 0x18, 0x08, 0x0c,
0x04, 0x06, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00,
/* 38 */ 0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x6c, 0x3e,
0x33, 0x33, 0x7b, 0xce, 0x00, 0x00, 0x00, 0x00,
/* 39 */ 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 40 */ 0x00, 0x00, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
/* 41 */ 0x00, 0x00, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x30,
0x30, 0x30, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
/* 42 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x1c, 0x7f,
0x1c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 43 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 44 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
/* 45 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 46 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 47 */ 0x00, 0x00, 0x60, 0x20, 0x30, 0x10, 0x18, 0x08,
0x0c, 0x04, 0x06, 0x02, 0x03, 0x00, 0x00, 0x00,
/* 48 */ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x6b, 0x6b,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 49 */ 0x00, 0x00, 0x18, 0x1e, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 50 */ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x30, 0x18,
0x0c, 0x06, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 51 */ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x3c, 0x60,
0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 52 */ 0x00, 0x00, 0x30, 0x38, 0x3c, 0x36, 0x33, 0x7f,
0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
/* 53 */ 0x00, 0x00, 0x7f, 0x03, 0x03, 0x3f, 0x60, 0x60,
0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 54 */ 0x00, 0x00, 0x3c, 0x06, 0x03, 0x03, 0x3f, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 55 */ 0x00, 0x00, 0x7f, 0x60, 0x30, 0x30, 0x18, 0x18,
0x18, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
/* 56 */ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 57 */ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x7e, 0x60,
0x60, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00,
/* 58 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 59 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
/* 60 */ 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06,
0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
/* 61 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 62 */ 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60,
0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
/* 63 */ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x30, 0x30, 0x18,
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 64 */ 0x00, 0x00, 0x3c, 0x66, 0x73, 0x7b, 0x6b, 0x6b,
0x7b, 0x33, 0x06, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 65 */ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 66 */ 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x3f, 0x63,
0x63, 0x63, 0x63, 0x3f, 0x00, 0x00, 0x00, 0x00,
/* 67 */ 0x00, 0x00, 0x3c, 0x66, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 68 */ 0x00, 0x00, 0x1f, 0x33, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x33, 0x1f, 0x00, 0x00, 0x00, 0x00,
/* 69 */ 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x03,
0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 70 */ 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x03,
0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
/* 71 */ 0x00, 0x00, 0x3c, 0x66, 0x03, 0x03, 0x03, 0x73,
0x63, 0x63, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
/* 72 */ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 73 */ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 74 */ 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
/* 75 */ 0x00, 0x00, 0x63, 0x33, 0x1b, 0x0f, 0x07, 0x07,
0x0f, 0x1b, 0x33, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 76 */ 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 77 */ 0x00, 0x00, 0x63, 0x63, 0x77, 0x7f, 0x7f, 0x6b,
0x6b, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 78 */ 0x00, 0x00, 0x63, 0x63, 0x67, 0x6f, 0x6f, 0x7b,
0x7b, 0x73, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 79 */ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 80 */ 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3f,
0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
/* 81 */ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x6f, 0x7b, 0x3e, 0x30, 0x60, 0x00, 0x00,
/* 82 */ 0x00, 0x00, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3f,
0x1b, 0x33, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 83 */ 0x00, 0x00, 0x3e, 0x63, 0x03, 0x03, 0x0e, 0x38,
0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 84 */ 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 85 */ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 86 */ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36,
0x36, 0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00,
/* 87 */ 0x00, 0x00, 0x63, 0x63, 0x6b, 0x6b, 0x6b, 0x6b,
0x7f, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
/* 88 */ 0x00, 0x00, 0x63, 0x63, 0x36, 0x36, 0x1c, 0x1c,
0x36, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 89 */ 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x66, 0x3c, 0x3c,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 90 */ 0x00, 0x00, 0x7f, 0x30, 0x30, 0x18, 0x18, 0x0c,
0x0c, 0x06, 0x06, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 91 */ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 92 */ 0x00, 0x00, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08,
0x18, 0x10, 0x30, 0x20, 0x60, 0x00, 0x00, 0x00,
/* 93 */ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 94 */ 0x00, 0x08, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
/* 96 */ 0x00, 0x00, 0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 98 */ 0x00, 0x00, 0x03, 0x03, 0x03, 0x3b, 0x67, 0x63,
0x63, 0x63, 0x67, 0x3b, 0x00, 0x00, 0x00, 0x00,
/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03,
0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 100 */ 0x00, 0x00, 0x60, 0x60, 0x60, 0x6e, 0x73, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 101 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63,
0x7f, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 102 */ 0x00, 0x00, 0x3c, 0x66, 0x06, 0x1f, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
/* 103 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x60, 0x63, 0x3e, 0x00,
/* 104 */ 0x00, 0x00, 0x03, 0x03, 0x03, 0x3b, 0x67, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 105 */ 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 106 */ 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x00,
/* 107 */ 0x00, 0x00, 0x03, 0x03, 0x03, 0x63, 0x33, 0x1b,
0x0f, 0x1f, 0x33, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 108 */ 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 109 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x6b, 0x6b,
0x6b, 0x6b, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00,
/* 110 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x67, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 111 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x67, 0x63,
0x63, 0x63, 0x67, 0x3b, 0x03, 0x03, 0x03, 0x00,
/* 113 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x60, 0xe0, 0x60, 0x00,
/* 114 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x67, 0x03,
0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
/* 115 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x0e,
0x38, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 116 */ 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3e, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 117 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 118 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x36,
0x36, 0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00,
/* 119 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x6b,
0x6b, 0x3e, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x36, 0x1c,
0x1c, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 121 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x36,
0x36, 0x1c, 0x1c, 0x0c, 0x0c, 0x06, 0x03, 0x00,
/* 122 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x30,
0x18, 0x0c, 0x06, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 123 */ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
/* 124 */ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
/* 125 */ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70,
0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
/* 126 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 127 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 129 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 130 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 131 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 132 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 133 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 134 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 135 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 137 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 138 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 139 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 140 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 141 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 142 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 143 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 145 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 146 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 147 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 148 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 149 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 150 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 151 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 153 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 154 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 155 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 156 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 157 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 158 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 159 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 161 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
/* 162 */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x6b, 0x0b,
0x0b, 0x0b, 0x6b, 0x3e, 0x08, 0x08, 0x00, 0x00,
/* 163 */ 0x00, 0x00, 0x1c, 0x36, 0x06, 0x06, 0x1f, 0x06,
0x06, 0x07, 0x6f, 0x3b, 0x00, 0x00, 0x00, 0x00,
/* 164 */ 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x66, 0x66,
0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 165 */ 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x66, 0x3c, 0x7e,
0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 166 */ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 167 */ 0x00, 0x3c, 0x66, 0x0c, 0x1e, 0x33, 0x63, 0x66,
0x3c, 0x18, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
/* 168 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 169 */ 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0x85, 0xa5,
0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 170 */ 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x3b, 0x36, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 171 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x1b,
0x1b, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 172 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60,
0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 173 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 174 */ 0x00, 0x00, 0x3c, 0x42, 0x9d, 0xa5, 0x9d, 0xa5,
0xa5, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 175 */ 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 176 */ 0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 177 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 178 */ 0x00, 0x1e, 0x33, 0x18, 0x0c, 0x06, 0x3f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 179 */ 0x00, 0x1e, 0x33, 0x18, 0x30, 0x33, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 180 */ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 181 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
0x66, 0x66, 0x76, 0x6e, 0x06, 0x06, 0x03, 0x00,
/* 182 */ 0x00, 0x00, 0x7e, 0x2f, 0x2f, 0x2f, 0x2e, 0x28,
0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00,
/* 183 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1e, 0x00,
/* 185 */ 0x00, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 186 */ 0x00, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1e, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 187 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c,
0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 188 */ 0x00, 0x10, 0x1c, 0x18, 0x18, 0x18, 0x00, 0x7f,
0x00, 0x18, 0x1c, 0x1a, 0x3e, 0x18, 0x00, 0x00,
/* 189 */ 0x00, 0x10, 0x1c, 0x18, 0x18, 0x18, 0x00, 0x7f,
0x00, 0x1c, 0x36, 0x18, 0x0c, 0x3e, 0x00, 0x00,
/* 190 */ 0x00, 0x1c, 0x36, 0x18, 0x36, 0x1c, 0x00, 0x7f,
0x00, 0x18, 0x1c, 0x1a, 0x3e, 0x18, 0x00, 0x00,
/* 191 */ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c,
0x0c, 0x06, 0x06, 0x03, 0x63, 0x3e, 0x00, 0x00,
/* 192 */ 0x0c, 0x18, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 193 */ 0x18, 0x0c, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 194 */ 0x08, 0x14, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 195 */ 0x6e, 0x3b, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 196 */ 0x36, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 197 */ 0x1c, 0x36, 0x3e, 0x63, 0x63, 0x63, 0x7f, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 198 */ 0x00, 0x00, 0xfe, 0x33, 0x33, 0x33, 0xff, 0x33,
0x33, 0x33, 0x33, 0xf3, 0x00, 0x00, 0x00, 0x00,
/* 199 */ 0x00, 0x00, 0x3c, 0x66, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x66, 0x3c, 0x18, 0x30, 0x1e, 0x00,
/* 200 */ 0x0c, 0x18, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x03,
0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 201 */ 0x18, 0x0c, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x03,
0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 202 */ 0x08, 0x14, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x03,
0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 203 */ 0x36, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x03,
0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00,
/* 204 */ 0x0c, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 205 */ 0x30, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 206 */ 0x18, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 207 */ 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 208 */ 0x00, 0x00, 0x1e, 0x36, 0x66, 0x66, 0x6f, 0x66,
0x66, 0x66, 0x36, 0x1e, 0x00, 0x00, 0x00, 0x00,
/* 209 */ 0x6e, 0x3b, 0x63, 0x63, 0x67, 0x6f, 0x6f, 0x7b,
0x7b, 0x73, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 210 */ 0x06, 0x0c, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 211 */ 0x30, 0x18, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 212 */ 0x08, 0x14, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 213 */ 0x6e, 0x3b, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 214 */ 0x36, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 215 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18,
0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 216 */ 0x00, 0x20, 0x3e, 0x73, 0x73, 0x6b, 0x6b, 0x6b,
0x6b, 0x67, 0x67, 0x3e, 0x02, 0x00, 0x00, 0x00,
/* 217 */ 0x0c, 0x18, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 218 */ 0x18, 0x0c, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 219 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 220 */ 0x36, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 221 */ 0x30, 0x18, 0xc3, 0xc3, 0x66, 0x66, 0x3c, 0x3c,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 222 */ 0x00, 0x00, 0x0f, 0x06, 0x3e, 0x66, 0x66, 0x66,
0x66, 0x3e, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
/* 223 */ 0x00, 0x00, 0x1e, 0x33, 0x33, 0x1b, 0x33, 0x63,
0x63, 0x63, 0x63, 0x3b, 0x00, 0x00, 0x00, 0x00,
/* 224 */ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 225 */ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 226 */ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 227 */ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 228 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 229 */ 0x00, 0x1c, 0x36, 0x1c, 0x00, 0x3e, 0x60, 0x7e,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 230 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xdb, 0xd8,
0xfe, 0x1b, 0xdb, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 231 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03,
0x03, 0x03, 0x63, 0x3e, 0x18, 0x30, 0x1e, 0x00,
/* 232 */ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x3e, 0x63, 0x63,
0x7f, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 233 */ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x3e, 0x63, 0x63,
0x7f, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 234 */ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63,
0x7f, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 235 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x3e, 0x63, 0x63,
0x7f, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 236 */ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 237 */ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 238 */ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 239 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 240 */ 0x00, 0x00, 0x2c, 0x18, 0x34, 0x60, 0x7c, 0x66,
0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
/* 241 */ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x3b, 0x67, 0x63,
0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
/* 242 */ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 243 */ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x3e, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 244 */ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 245 */ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x3e, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 246 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x3e, 0x63, 0x63,
0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
/* 247 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e,
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 248 */ 0x00, 0x00, 0x00, 0x00, 0x20, 0x3e, 0x73, 0x6b,
0x6b, 0x6b, 0x67, 0x3e, 0x02, 0x00, 0x00, 0x00,
/* 249 */ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x63, 0x63, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 250 */ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x63, 0x63, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 251 */ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x63, 0x63, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 252 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x63, 0x63, 0x63,
0x63, 0x63, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,
/* 253 */ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x63, 0x63, 0x36,
0x36, 0x1c, 0x1c, 0x0c, 0x0c, 0x06, 0x03, 0x00,
/* 254 */ 0x00, 0x00, 0x0f, 0x06, 0x06, 0x3e, 0x66, 0x66,
0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x0f, 0x00,
/* 255 */ 0x00, 0x00, 0x36, 0x36, 0x00, 0x63, 0x63, 0x36,
0x36, 0x1c, 0x1c, 0x0c, 0x0c, 0x06, 0x03, 0x00
};
Context2D* NewContext2D(I64 width, I64 height,
I64 bpp = 32)
{ // Create new Context2D.
switch (bpp) {
case 32:
break;
default:
return NULL;
break;
}
Context2D* ctx = CAlloc(sizeof(Context2D));
ctx->width = width;
ctx->height = height;
ctx->fb = CAlloc((width * height) * bpp / 8);
ctx->opacity = -1;
return @create_callable_context2d(ctx);
}
U0 DelContext2D(Context2D* ctx)
{
if (!ctx) {
return;
}
if (ctx->fb)
Free(ctx->fb);
if (ctx->blot)
Free(ctx->blot);
Free(ctx);
}
U0 Fill2D(Context2D* ctx, U32 color = 0)
{ // Fill a Context2D with color.
MemSetU32(ctx->fb, color, ctx->width * ctx->height);
return;
}
U32 Peek2D(Context2D* ctx, I64 x, I64 y)
{ // Return RGBA value for pixel.
if (x < 0 || x > ctx->width - 1 || y < 0 || y > ctx->height - 1)
return Color(255, 255, 255);
return ctx->fb[(ctx->width * y) + x];
}
U0 Plot2D(Context2D* ctx, I64 x, I64 y,
U32 color)
{ // Plot a pixel with clipping.
if (x < 0 || x > ctx->width - 1 || y < 0 || y > ctx->height - 1)
return;
ctx->fb[(ctx->width * y) + x] = color;
}
U0 VLine2D(Context2D* ctx, I64 x, I64 y, I64 y2,
U32 color)
{ // Draw a vertical line.
if (y2 < y)
return;
while (y < y2 + 1) {
Plot2D(ctx, x, y, color);
y++;
}
}
U0 HLine2D(Context2D* ctx, I64 x, I64 y, I64 x2,
U32 color)
{ // Draw a horizontal line.
if (x2 < x)
return;
if (y < 0 || y > ctx->height - 1)
return;
if (x > ctx->width - 1)
return;
if (x2 < 0)
return;
I64 min_x = MaxI64(0, x);
I64 max_x = MinI64(ctx->width - 1, x2);
I64 width = (max_x - min_x) + 1;
if (width == 1) {
Plot2D(ctx, x, y, color);
} else {
MemSetU32(ctx->fb + (y * ctx->width) + min_x, color, width);
}
}
U0 Line2D(Context2D* ctx, I64 x1, I64 y1, I64 x2, I64 y2,
U32 color)
{ // Draw an arbitrary line using Bresenham's algorithm.
if (x1 == x2) {
VLine2D(ctx, x1, y1, y2, color);
return;
}
if (y1 == y2) {
HLine2D(ctx, x1, y1, x2, color);
return;
}
I64 dx, sx, dy, sy;
I64 err, e2;
dx = Abs(x2 - x1);
sx = T(x1 < x2, 1, -1);
dy = -Abs(y2 - y1);
sy = T(y1 < y2, 1, -1);
err = dx + dy;
while (1) {
Plot2D(ctx, x1, y1, color);
if (x2 == x1 && y2 == y1)
break;
e2 = 2 * err;
if (e2 >= dy) {
err += dy;
x1 += sx;
}
if (e2 <= dx) {
err += dx;
y1 += sy;
}
}
}
Context2D* MirroredHorz2D(Context2D* src)
{
if (!src)
return NULL;
Context2D* dst = NewContext2D(src->width, src->height);
I64 x, y;
for (y = 0; y < src->height; y++)
for (x = src->width - 1; x > -1; x--)
Plot2D(dst, (src->width - 1) - x, y, Peek2D(src, x, y));
return dst;
}
Context2D* MirroredVert2D(Context2D* src)
{
if (!src)
return NULL;
Context2D* dst = NewContext2D(src->width, src->height);
I64 x, y;
for (x = 0; x < src->width; x++)
for (y = src->height - 1; y > -1; y--)
Plot2D(dst, x, (src->height - 1) - y, Peek2D(src, x, y));
return dst;
}
I64 Blend2D(F64 alpha, F64 value1, F64 value2)
{
return ToI64((1 - alpha) * value1 + alpha * value2);
}
U0 Blot2D(Context2D* dst, I64 x, I64 y, Context2D* src)
{
if (!src || !dst)
return;
I64 xx, yy;
I64 src_col, dst_col;
F64 alpha;
I64 plot_col;
for (yy = 0; yy < src->height; yy++) {
for (xx = 0; xx < src->width; xx++) {
src_col = Peek2D(src, xx, yy);
dst_col = Peek2D(dst, x + xx, y + yy);
alpha = src_col.u8[3] / 128; // FIXME: Alpha blending not working correctly.
plot_col = Blend2D(alpha, dst_col, src_col);
if (src->opacity > -1) {
plot_col.u8[3] = src->opacity;
}
Plot2D(dst, x + xx, y + yy, plot_col);
}
}
}
U0 @patch_blend_rect_2d(U64 addr_start, I64 size, U64 jmp_offset,
U64 table_offset)
{
U8* patch_ptr = addr_start;
I64 i;
for (i = 0; (addr_start + table_offset - i) % 16; i++) {
patch_ptr[jmp_offset]--;
}
if (i)
MemCpy(addr_start + table_offset - i, addr_start + table_offset,
size - table_offset);
}
U0 BlendRect2D(Context2D* rect, Context2D* ctx)
{
U64 reg R10 d = ctx->fb;
U64 reg R11 s1 = rect->fb;
U64 reg R14 s2 = ctx->fb;
I64 reg RSI w = ctx->width;
I64 reg RDI h = ctx->height;
no_warn d, s1, s2, w, h;
asm {
MOV RAX, R10
MOV RDX, R11
MOV RCX, R14
DU8
0x0f, 0xaf, 0xf7, 0xc1, 0xfe, 0x02, 0xeb, 0x7f,
0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0x1f, 0x40, 0x00, 0x90,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x03,
0x80, 0x03, 0x80, 0x07, 0x80, 0x07, 0x80, 0x0b,
0x80, 0x0b, 0x80, 0x0f, 0x80, 0x0f, 0x80, 0x00,
0x80, 0x02, 0x80, 0x04, 0x80, 0x06, 0x80, 0x08,
0x80, 0x0a, 0x80, 0x0c, 0x80, 0x0e, 0x80, 0x01,
0x80, 0x03, 0x80, 0x05, 0x80, 0x07, 0x80, 0x09,
0x80, 0x0b, 0x80, 0x0d, 0x80, 0x0f, 0x80, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0f,
0x10, 0x0a, 0x0f, 0x10, 0x11, 0x66, 0x0f, 0x6f,
0xd9, 0x66, 0x0f, 0x38, 0x00, 0x1d, 0x8d, 0xff,
0xff, 0xff, 0x66, 0x0f, 0x6f, 0xe3, 0x66, 0x0f,
0xef, 0x25, 0xb1, 0xff, 0xff, 0xff, 0x66, 0x0f,
0x6f, 0xe9, 0x66, 0x0f, 0x6f, 0xf2, 0x66, 0x0f,
0x38, 0x00, 0x0d, 0x80, 0xff, 0xff, 0xff, 0x66,
0x0f, 0xd5, 0xcb, 0x66, 0x0f, 0x38, 0x00, 0x15,
0x73, 0xff, 0xff, 0xff, 0x66, 0x0f, 0xd5, 0xd4,
0x66, 0x0f, 0x38, 0x00, 0x2d, 0x76, 0xff, 0xff,
0xff, 0x66, 0x0f, 0xd5, 0xeb, 0x66, 0x0f, 0xfd,
0xd1, 0x66, 0x0f, 0xe4, 0x15, 0x86, 0xff, 0xff,
0xff, 0x66, 0x0f, 0x38, 0x00, 0x35, 0x5d, 0xff,
0xff, 0xff, 0x66, 0x0f, 0xd5, 0xf4, 0x66, 0x0f,
0xfd, 0xf5, 0x66, 0x0f, 0xe4, 0x35, 0x6d, 0xff,
0xff, 0xff, 0x66, 0x0f, 0x71, 0xf6, 0x08, 0x66,
0x0f, 0xeb, 0xd6, 0x66, 0x0f, 0xeb, 0x15, 0x6c,
0xff, 0xff, 0xff, 0x0f, 0x11, 0x10, 0x48, 0x83,
0xc2, 0x10, 0x48, 0x83, 0xc1, 0x10, 0x48, 0x83,
0xc0, 0x10, 0xff, 0xce, 0x0f, 0x85, 0x65, 0xff,
0xff, 0xff, 0x90;
}
}
@patch_blend_rect_2d(&BlendRect2D, sizeof(BlendRect2D), 0x3D, 0x5D);
U0 CopyRect2D(Context2D* ctx, I64 x, I64 y,
Context2D* rect)
{ // Copy rect with clipping.
if (x > ctx->width - 1 || y > ctx->height - 1)
return;
U8* ctx_pos = ctx->fb;
U8* rect_pos = rect->fb;
I64 rect_row = 0;
I64 rect_y_ofs = 0;
I64 rect_x_ofs = 0;
I64 clip_y = 0;
U8* rect_line;
I64 bpp = 32 / 8;
// Handle horizontal clipping left
while (x < 0) {
rect_x_ofs++;
x++;
}
// Handle vertical clipping top
while (y < 0) {
rect_pos += (rect->width) * bpp;
rect_y_ofs++;
y++;
}
// default, clip line to copy as width-left off screen
rect_line = rect->width - rect_x_ofs;
if (-rect_x_ofs + x + rect->width >= ctx->width) {
rect_line -= ((-rect_x_ofs + x + rect->width) - ctx->width);
}
rect_pos += (rect_x_ofs)*bpp;
clip_y = y;
while (rect_row < (rect->height - rect_y_ofs) && clip_y < ctx->height) {
MemCpyU32(ctx_pos + (y * ((ctx->width) * bpp)) + (x * bpp), rect_pos,
(rect_line));
ctx_pos += (ctx->width) * bpp;
rect_pos += (rect->width) * bpp;
clip_y++;
rect_row++;
}
}
U0 @graphics2d_get_gradient_steps(U32 start, U32 end, U32* gradient)
{
I64 a2 = start.u8[3];
I64 r2 = start.u8[2];
I64 g2 = start.u8[1];
I64 b2 = start.u8[0];
I64 a1 = end.u8[3];
I64 r1 = end.u8[2];
I64 g1 = end.u8[1];
I64 b1 = end.u8[0];
I64 i;
F64 c = 1.0;
for (i = 0; i < 256; i++) {
gradient[i] = Color(r1 / 255.0 * c + r2 / 255.0 * (255 - c),
g1 / 255.0 * c + g2 / 255.0 * (255 - c),
b1 / 255.0 * c + b2 / 255.0 * (255 - c),
a1 / 255.0 * c + a2 / 255.0 * (255 - c));
c += 1.0;
}
}
U0 HGradientRect2D(Context2D* ctx, I64 x, I64 y, I64 w, I64 h, U32 from,
U32 to)
{
U32 gradient[256];
F64 gradient_index;
I64 xx;
@graphics2d_get_gradient_steps(from, to, &gradient);
for (xx = 0; xx < w; xx++) {
gradient_index = ToF64(256.0 / ToF64(w)) * ToF64(xx);
Line2D(ctx, x + xx, y, x + xx, y + h - 1, gradient[ToI64(gradient_index)]);
}
}
U0 Rect2D(Context2D* ctx, I64 x, I64 y, I64 w, I64 h,
U32 color)
{ // Draw a rectangle fill.
I64 i;
for (i = y; i < y + h; i++) {
HLine2D(ctx, x, i, x + w - 1, color);
}
}
U0 ConsolePrint2D(Context2D* ctx, I64 x, I64 y,
U32 color = Color(255, 255, 255), U32 colorbg = 0, U8* fmt,
...)
{ // Print formatted string using console font.
Bool skip;
U8* buf = StrPrintJoin(NULL, fmt, argc, argv);
U8* str = buf;
I64 orig_x = x;
I64 xx, yy;
U64* chr = console_font;
while (*str) {
skip = FALSE;
if (*str == '\n') {
skip = TRUE;
y += 16;
x = orig_x - 8;
}
for (yy = 0; yy < 16; yy++) {
for (xx = 0; xx < 8; xx++) {
if (chr[(*str) * 2].u8[yy] & 1 << xx == 1 << xx && !skip)
Plot2D(ctx, x + xx, y + yy, color);
else
Plot2D(ctx, x + xx, y + yy, colorbg);
}
}
x += 8;
str++;
}
Free(buf);
}
U0 PutChar2D(Context2D* ctx, BitmapFont* font, I64 x, I64 y,
U32 color = Color(0, 0, 0), I64 char)
{
if (!ctx)
return;
I64 xx;
I64 yy;
I64 char_index = 0;
while (char != font->char_map[char_index])
char_index++;
for (yy = 0; yy < 16; yy++) {
for (xx = 0; xx < 16; xx++) {
if (font->bitmap[(char_index * 16) + yy] & 0x8000 >> xx == 0x8000 >> xx && char != ' ') {
Plot2D(ctx, x + xx, y + yy, color);
}
}
}
}
I64 PutS2D(Context2D* ctx, BitmapFont* font, I64 x, I64 y,
U32 color = Color(0, 0, 0), I64 max_width = -1, U8* buf)
{
U8* str = buf;
I64 origin_x;
I64 origin_y;
I64 xx, yy;
Bool char_space;
I64 char_index;
I64 insert_space;
I64 pass;
origin_x = x;
origin_y = y;
if (max_width > -1)
max_width = Min(ctx->width, max_width);
for (pass = 0; pass < 2; pass++) {
x = origin_x;
y = origin_y;
str = buf;
while (*str) {
char_space = FALSE;
switch (*str) {
case '\n':
x = origin_x;
if (font->line_height)
y += Min(16, font->line_height);
else
y += 16;
goto @print2d_next_char;
break;
case ' ':
char_space = TRUE;
break;
default:
break;
}
char_index = 0;
while (*str != font->char_map[char_index])
char_index++;
insert_space = 0;
for (yy = 0; yy < 16; yy++) {
for (xx = 0; xx < 16; xx++) {
if (font->bitmap[(char_index * 16) + yy] & 0x8000 >> xx == 0x8000 >> xx && !char_space) {
insert_space = Max(xx, insert_space);
if (pass && ctx)
Plot2D(ctx, x + xx, y + yy, color);
}
}
}
if (char_space)
insert_space = 4;
@print2d_next_char : str++;
if (str > buf && str[-1] != '\n') {
if (*str) {
x += insert_space + 2;
} else {
x += insert_space;
}
}
if (max_width == -1) {
} else if (x > max_width) {
StrCpy(&str[-4], "...");
break;
}
}
}
return x;
}
I64 Print2D(Context2D* ctx, BitmapFont* font, I64 x, I64 y,
U32 color = Color(0, 0, 0), I64 max_width = -1, U8* fmt,
...)
{ // Print formatted string using BitmapFont.
U8* buf;
if (argc)
buf = StrPrintJoin(NULL, fmt, argc, argv);
else
buf = StrNew(fmt);
I64 retval = PutS2D(ctx, font, x, y, color, max_width, buf);
Free(buf);
return retval;
}
I64 X1Pos(CDC* src)
{
I64 x = 0;
I64 y = 0;
I64 color;
while (x < src->width) {
y = 0;
while (y < src->height) {
color = GrPeek(src, x, y);
if (color)
return x;
y++;
}
x++;
}
return -1;
}
I64 X2Pos(CDC* src)
{
I64 x = src->width - 1;
I64 y = src->height - 1;
I64 color;
while (x > -1) {
y = src->height - 1;
while (y > -1) {
color = GrPeek(src, x, y);
if (color)
return x;
y--;
}
x--;
}
return -1;
}
I64 Y2Pos(CDC* src)
{
I64 x = src->width - 1;
I64 y = src->height - 1;
I64 color;
while (y > -1) {
x = src->width - 1;
while (x > -1) {
color = GrPeek(src, x, y);
if (color)
return y;
x--;
}
y--;
}
return -1;
}
I64 @get_truetype_text_width(U8* font_name, I64 size, I32* text, I32* advance = NULL)
{
I64 line_height = ToI64(size * 1.2);
stbtt_fontinfo* font = Fonts->@(font_name);
if (!font || !line_height || !text) {
return 0;
}
return @stbtt_GetTextWidth(font, line_height, text, advance);
}
I64 @get_truetype_baseline(U8* font_name, I64 size)
{
stbtt_fontinfo* font = Fonts->@(font_name);
if (!font) {
return 0;
}
I64 res = 0;
CDC* dc = DCNew(Display.Width() / 2, (size * 2));
Free(dc->body);
I32 i32char[16];
MemSet(&i32char, NULL, 16);
i32char[0] = 'o';
dc->body = @stbtt_RenderText(font, dc->width_internal, dc->height, ToI64(size * 1.2), &i32char);
dc->width -= 16;
dc->height -= size / 4;
res = Y2Pos(dc);
Free(dc);
return res;
}
U0 Text2D(Context2D* ctx, U8* font_name, I64 x, I64 y, I64 size, U32 color, U8* text)
{
stbtt_fontinfo* font = Fonts->@(font_name);
if (!ctx || !ctx->width || !ctx->height || !font || !size || !text || !StrLen(text)) {
return;
}
Context2D* text_ctx = NewContext2D(ctx->width, ctx->height);
CDC* dc = DCNew(ctx->width, ctx->height);
Free(dc->body);
dc->body = @stbtt_RenderText(font, dc->width_internal, dc->height, ToI64(size * 1.2), text);
I64 text_x, text_y, text_c;
for (text_y = 0; text_y < dc->height; text_y++) {
for (text_x = 0; text_x < dc->width; text_x++) {
text_c = GrPeek(dc, text_x, text_y);
if (text_c) {
color.u8[3] = text_c;
text_ctx->plot(x + text_x, y + text_y, color);
}
}
}
BlendRect2D(text_ctx, ctx);
DelContext2D(text_ctx);
Free(dc);
}
Context2D* FastBoxBlur2D(Context2D* img, I64 radius)
{
/*
Algorithm by Wojciech Jarosz, Implementation by Ferris Ateniese
http://elynxsdk.free.fr/ext-docs/Blur/Fast_box_blur.pdf
https://gist.github.com/LionRoar/12d625bee5882abb339dc7102ad6fe32#file-fastboxblur-cs
*/
I64 kSize = radius;
I64 c, i, j, x, y;
I64 bpp = 32;
no_warn bpp;
U32 tmpColor, tmp_nColor, tmp_pColor, plot_color;
F64 hSum[4];
F64 tSum[4];
F64 iAvg[4];
if (kSize % 2 == 0)
kSize++;
Context2D* Hblur = NewContext2D(img->width, img->height);
MemCpyU32(Hblur->fb, img->fb, img->width * img->height);
F64 Avg = 1.0 / kSize;
for (j = 0; j < img->height; j++) {
for (c = 0; c < 4; c++) {
hSum[c] = 0.0;
iAvg[c] = 0.0;
}
for (x = 0; x < kSize; x++) {
tmpColor = Peek2D(img, x, j);
hSum[3] += tmpColor.u8[3];
hSum[2] += tmpColor.u8[2];
hSum[1] += tmpColor.u8[1];
hSum[0] += tmpColor.u8[0];
}
iAvg[3] = hSum[3] * Avg;
iAvg[2] = hSum[2] * Avg;
iAvg[1] = hSum[1] * Avg;
iAvg[0] = hSum[0] * Avg;
for (i = 0; i < img->width; i++) {
if (i - kSize / 2 >= 0 && i + 1 + kSize / 2 < img->width) {
tmp_pColor = Peek2D(img, i - kSize / 2, j);
hSum[3] -= tmp_pColor.u8[3];
hSum[2] -= tmp_pColor.u8[2];
hSum[1] -= tmp_pColor.u8[1];
hSum[0] -= tmp_pColor.u8[0];
tmp_nColor = Peek2D(img, i + 1 + kSize / 2, j);
hSum[3] += tmp_nColor.u8[3];
hSum[2] += tmp_nColor.u8[2];
hSum[1] += tmp_nColor.u8[1];
hSum[0] += tmp_nColor.u8[0];
iAvg[3] = hSum[3] * Avg;
iAvg[2] = hSum[2] * Avg;
iAvg[1] = hSum[1] * Avg;
iAvg[0] = hSum[0] * Avg;
}
plot_color.u8[3] = ToI64(iAvg[3]);
plot_color.u8[2] = ToI64(iAvg[2]);
plot_color.u8[1] = ToI64(iAvg[1]);
plot_color.u8[0] = ToI64(iAvg[0]);
Plot2D(Hblur, i, j, plot_color);
}
}
Context2D* total = NewContext2D(Hblur->width, Hblur->height);
MemCpyU32(total->fb, Hblur->fb, Hblur->width * Hblur->height);
for (i = 0; i < Hblur->width; i++) {
for (c = 0; c < 4; c++) {
tSum[c] = 0.0;
iAvg[c] = 0.0;
}
for (y = 0; y < kSize; y++) {
tmpColor = Peek2D(Hblur, i, y);
tSum[3] += tmpColor.u8[3];
tSum[2] += tmpColor.u8[2];
tSum[1] += tmpColor.u8[1];
tSum[0] += tmpColor.u8[0];
}
iAvg[3] = tSum[3] * Avg;
iAvg[2] = tSum[2] * Avg;
iAvg[1] = tSum[1] * Avg;
iAvg[0] = tSum[0] * Avg;
for (j = 0; j < Hblur->height; j++) {
if (j - kSize / 2 >= 0 && j + 1 + kSize / 2 < Hblur->height) {
tmp_pColor = Peek2D(Hblur, i, j - kSize / 2);
tSum[3] -= tmp_pColor.u8[3];
tSum[2] -= tmp_pColor.u8[2];
tSum[1] -= tmp_pColor.u8[1];
tSum[0] -= tmp_pColor.u8[0];
tmp_nColor = Peek2D(Hblur, i, j + 1 + kSize / 2);
tSum[3] += tmp_nColor.u8[3];
tSum[2] += tmp_nColor.u8[2];
tSum[1] += tmp_nColor.u8[1];
tSum[0] += tmp_nColor.u8[0];
iAvg[3] = tSum[3] * Avg;
iAvg[2] = tSum[2] * Avg;
iAvg[1] = tSum[1] * Avg;
iAvg[0] = tSum[0] * Avg;
}
plot_color.u8[3] = ToI64(iAvg[3]);
plot_color.u8[2] = ToI64(iAvg[2]);
plot_color.u8[1] = ToI64(iAvg[1]);
plot_color.u8[0] = ToI64(iAvg[0]);
Plot2D(total, i, j, plot_color);
}
}
DelContext2D(Hblur);
return total;
}
U0 BlurInPlace(Context2D* img, I64 radius)
{
Context2D* blurred = FastBoxBlur2D(img, radius);
CopyRect2D(img, 0, 0, blurred);
DelContext2D(blurred);
}
U8 @scale2d_get_byte(I64 value, I64 n) { return (value >> (n * 8) & 0xFF); }
U32 @scale2d_get_pixel(Context2D* img, I64 x, I64 y)
{
return img->fb[(y * img->width) + x];
}
F64 @scale2d_lerp(F64 s, F64 e, F64 t) { return s + (e - s) * t; }
F64 @scale2d_blerp(F64 c00, F64 c10, F64 c01, F64 c11, F64 tx, F64 ty)
{
return @scale2d_lerp(@scale2d_lerp(c00, c10, tx), @scale2d_lerp(c01, c11, tx),
ty);
}
U0 @scale2d_put_pixel(Context2D* img, I64 x, I64 y, U32 color)
{
img->fb[(y * img->width) + x] = color;
}
I64 X1Pos2D(Context2D* src)
{
I64 x = 0;
I64 y = 0;
U32 color;
while (x < src->width) {
y = 0;
while (y < src->height) {
color = Peek2D(src, x, y);
if (color.u8[3])
return x;
y++;
}
x++;
}
return -1;
}
I64 Y1Pos2D(Context2D* src)
{
I64 x = 0;
I64 y = 0;
U32 color;
while (y < src->height) {
x = 0;
while (x < src->width) {
color = Peek2D(src, x, y);
if (color.u8[3])
return y;
x++;
}
y++;
}
return -1;
}
I64 X2Pos2D(Context2D* src)
{
I64 x = src->width - 1;
I64 y = src->height - 1;
U32 color;
while (x > -1) {
y = src->height - 1;
while (y > -1) {
color = Peek2D(src, x, y);
if (color.u8[3])
return x;
y--;
}
x--;
}
return -1;
}
I64 Y2Pos2D(Context2D* src)
{
I64 x = src->width - 1;
I64 y = src->height - 1;
U32 color;
while (y > -1) {
x = src->width - 1;
while (x > -1) {
color = Peek2D(src, x, y);
if (color.u8[3])
return y;
x--;
}
y--;
}
return -1;
}
Context2D* ClipToRect2D(Context2D* src)
{
I64 x1, y1, x2, y2;
x1 = X1Pos2D(src);
y1 = Y1Pos2D(src);
x2 = X2Pos2D(src);
y2 = Y2Pos2D(src);
Context2D* dst = NewContext2D(x2 - x1, y2 - y1);
CopyRect2D(dst, -x1, -y1, src);
return dst;
}
Context2D* Scale2D(Context2D* src, F64 scale_x, F64 scale_y)
{
I64 newWidth = ToI64(src->width * scale_x);
I64 newHeight = ToI64(src->height * scale_y);
Context2D* dst = NewContext2D(newWidth, newHeight);
I64 x, y;
F64 fw, fh;
F64 gx;
F64 gy;
I64 gxi;
I64 gyi;
U32 result;
U32 c00;
U32 c10;
U32 c01;
U32 c11;
U64 i;
fw = ToF64(newWidth);
fh = ToF64(newHeight);
for (x = 0, y = 0; y < newHeight; x++) {
if (x > newWidth) {
x = 0;
y++;
}
gx = x / fw * (src->width - 1);
gy = y / fh * (src->height - 1);
gxi = ToI64(gx);
gyi = ToI64(gy);
result = 0;
c00 = @scale2d_get_pixel(src, gxi, gyi);
c10 = @scale2d_get_pixel(src, gxi + 1, gyi);
c01 = @scale2d_get_pixel(src, gxi, gyi + 1);
c11 = @scale2d_get_pixel(src, gxi + 1, gyi + 1);
for (i = 0; i < 4; i++) {
result.u8[i] = ToI64(
@scale2d_blerp(@scale2d_get_byte(c00, i), @scale2d_get_byte(c10, i),
@scale2d_get_byte(c01, i), @scale2d_get_byte(c11, i),
gx - gxi, gy - gyi)
<< (8 * i));
}
@scale2d_put_pixel(dst, x, y, result);
}
return dst;
}
Context2D* Rotate2D(Context2D* src, F64 angle)
{ // FIXME: This is just awful...
Context2D* dst = NewContext2D(src->width * 4, src->height * 4);
Fill2D(dst, 0);
CDC* dc[4];
CSprite* s[4];
I64 i, x, y;
U32 color;
for (i = 0; i < 4; i++) {
dc[i] = DCNew(src->width * 4, src->height * 4);
}
for (y = 0; y < src->height; y++) {
for (x = 0; x < src->width; x++) {
color = Peek2D(src, x, y);
for (i = 0; i < 4; i++) {
dc[i]->color = Min(color.u8[i], 254);
GrPlot(dc[i], x, y);
}
}
}
for (i = 0; i < 4; i++) {
s[i] = DC2Sprite(dc[i]);
DCFill(dc[i], 0);
Sprite3ZB(dc[i], src->width * 2, src->height * 2, 0, s[i],
angle * 0.017499999999);
}
for (y = 0; y < src->height * 4; y++) {
for (x = 0; x < src->width * 4; x++) {
for (i = 0; i < 4; i++) {
color.u8[i] = GrPeek(dc[i], x, y);
}
Plot2D(dst, x, y, color);
}
}
for (i = 0; i < 4; i++) {
DCDel(dc[i]);
Free(s[i]);
}
Context2D* dst2 = ClipToRect2D(dst);
DelContext2D(dst);
return dst2;
}
class @graphics2d
{
Context2D* fb;
Context2D* (*FrameBufferContext2D)();
U0 (*Init)();
U0 (*Flip)(Context2D* ctx);
I64 qwords;
};
@graphics2d Graphics2D;
U0 @graphics2d_init()
{
Graphics2D.fb = CAlloc(sizeof(Context2D));
Graphics2D.fb->width = Display.width;
Graphics2D.fb->height = Display.height;
Graphics2D.fb->fb = Display.fb;
Graphics2D.fb->opacity = -1;
Graphics2D.qwords = (Display.width * Display.height) / 2;
Fill2D(Graphics2D.fb, 0x0);
}
U0 @graphics2d_flip(Context2D* ctx)
{
MemCpyU64(Graphics2D.fb->fb, ctx->fb, Graphics2D.qwords);
}
Context2D @graphics2d_get_framebuffer_context2d() { return Graphics2D.fb; }
Graphics2D.FrameBufferContext2D = &@graphics2d_get_framebuffer_context2d;
Graphics2D.Init = &@graphics2d_init;
Graphics2D.Flip = &@graphics2d_flip;
@callable_context2d* @c2d_blot_wrapper_function(I64 x, I64 y, @callable_context2d* src)
{
Context2D* dst = C2D_MAGIC;
Blot2D(dst, x, y, src);
return dst;
}
@callable_context2d* @c2d_blur_wrapper_function(I64 radius)
{
Context2D* img = C2D_MAGIC;
BlurInPlace(img, radius);
return img;
}
@callable_context2d* @c2d_copy_rect_wrapper_function(I64 x, I64 y, @callable_context2d* rect)
{
Context2D* ctx = C2D_MAGIC;
CopyRect2D(ctx, x, y, rect);
return ctx;
}
@callable_context2d* @c2d_fill_wrapper_function(U32 color = 0)
{
Context2D* ctx = C2D_MAGIC;
Fill2D(ctx, color);
return ctx;
}
@callable_context2d* @c2d_fill_rect_wrapper_function(I64 x, I64 y, I64 w, I64 h, U32 color)
{
Context2D* ctx = C2D_MAGIC;
Rect2D(ctx, x, y, w, h, color);
return ctx;
}
U32 @c2d_peek_wrapper_function(I64 x, I64 y)
{
Context2D* ctx = C2D_MAGIC;
return Peek2D(ctx, x, y);
}
@callable_context2d* @c2d_plot_wrapper_function(I64 x, I64 y, U32 color)
{
Context2D* ctx = C2D_MAGIC;
Plot2D(ctx, x, y, color);
return ctx;
}
@callable_context2d* @c2d_line_wrapper_function(I64 x1, I64 y1, I64 x2, I64 y2, U32 color)
{
Context2D* ctx = C2D_MAGIC;
Line2D(ctx, x1, y1, x2, y2, color);
return ctx;
}
@callable_context2d* @c2d_text_wrapper_function(U64 font, I64 x, I64 y, I64 size, U32 color, U8* text)
{
Context2D* ctx = C2D_MAGIC;
Text2D(ctx, font, x, y, size, color, text);
return ctx;
}
@callable_context2d* @c2d_clipped_wrapper_function()
{
Context2D* ctx = C2D_MAGIC;
return ClipToRect2D(ctx);
}
@callable_context2d* @c2d_rotated_wrapper_function(F64 angle)
{
Context2D* src = C2D_MAGIC;
return Rotate2D(src, angle);
}
@callable_context2d* @c2d_scaled_wrapper_function(F64 scale_x, F64 scale_y)
{
Context2D* src = C2D_MAGIC;
return Scale2D(src, scale_x, scale_y);
}
@callable_context2d* @create_callable_context2d(@context2d* ctx)
{
@callable_context2d* res = CAlloc(sizeof(@callable_context2d));
MemCpy(res, ctx, sizeof(@context2d));
Free(ctx);
U64 a;
I64 buffer_size = (MSize(&@c2d_blot_wrapper_function) + MSize(&@c2d_blur_wrapper_function) + MSize(&@c2d_copy_rect_wrapper_function) + MSize(&@c2d_fill_wrapper_function) + MSize(&@c2d_fill_rect_wrapper_function) + MSize(&@c2d_peek_wrapper_function) + MSize(&@c2d_plot_wrapper_function) + MSize(&@c2d_line_wrapper_function) + MSize(&@c2d_text_wrapper_function) + MSize(&@c2d_clipped_wrapper_function) + MSize(&@c2d_rotated_wrapper_function) + MSize(&@c2d_scaled_wrapper_function));
buffer_size += buffer_size % 16;
U64 code_ptr = CAlloc(buffer_size, adam_task->code_heap);
I64 code_size = 0;
// blot
code_size = MSize(&@c2d_blot_wrapper_function);
res->blot = code_ptr;
MemCpy(res->blot, &@c2d_blot_wrapper_function, code_size);
code_ptr += code_size;
a = res->blot;
a += 0x1c;
MemSetI64(a, res, 1);
a = res->blot;
a += 0x2a;
@patch_call_rel32(a, &Blot2D);
// blur
code_size = MSize(&@c2d_blur_wrapper_function);
res->blur = code_ptr;
MemCpy(res->blur, &@c2d_blur_wrapper_function, code_size);
code_ptr += code_size;
a = res->blur;
a += 0x10;
MemSetI64(a, res, 1);
a = res->blur;
a += 0x1a;
@patch_call_rel32(a, &BlurInPlace);
// copy_rect
code_size = MSize(&@c2d_copy_rect_wrapper_function);
res->copy_rect = code_ptr;
MemCpy(res->copy_rect, &@c2d_copy_rect_wrapper_function, code_size);
code_ptr += code_size;
a = res->copy_rect;
a += 0x1c;
MemSetI64(a, res, 1);
a = res->copy_rect;
a += 0x2a;
@patch_call_rel32(a, &CopyRect2D);
// fill
code_size = MSize(&@c2d_fill_wrapper_function);
res->fill = code_ptr;
MemCpy(res->fill, &@c2d_fill_wrapper_function, code_size);
code_ptr += code_size;
a = res->fill;
a += 0x0f;
MemSetI64(a, res, 1);
a = res->fill;
a += 0x19;
@patch_call_rel32(a, &Fill2D);
// fill_rect
code_size = MSize(&@c2d_fill_rect_wrapper_function);
res->fill_rect = code_ptr;
MemCpy(res->fill_rect, &@c2d_fill_rect_wrapper_function, code_size);
code_ptr += code_size;
a = res->fill_rect;
a += 0x28;
MemSetI64(a, res, 1);
a = res->fill_rect;
a += 0x3a;
@patch_call_rel32(a, &Rect2D);
// peek
code_size = MSize(&@c2d_peek_wrapper_function);
res->peek = code_ptr;
MemCpy(res->peek, &@c2d_peek_wrapper_function, code_size);
code_ptr += code_size;
a = res->peek;
a += 0x16;
MemSetI64(a, res, 1);
a = res->peek;
a += 0x22;
@patch_call_rel32(a, &Peek2D);
// plot
code_size = MSize(&@c2d_plot_wrapper_function);
res->plot = code_ptr;
MemCpy(res->plot, &@c2d_plot_wrapper_function, code_size);
code_ptr += code_size;
a = res->plot;
a += 0x1b;
MemSetI64(a, res, 1);
a = res->plot;
a += 0x29;
@patch_call_rel32(a, &Plot2D);
// line
code_size = MSize(&@c2d_line_wrapper_function);
res->line = code_ptr;
MemCpy(res->line, &@c2d_line_wrapper_function, code_size);
code_ptr += code_size;
a = res->line;
a += 0x28;
MemSetI64(a, res, 1);
a = res->line;
a += 0x3a;
@patch_call_rel32(a, &Line2D);
// text
code_size = MSize(&@c2d_text_wrapper_function);
res->text = code_ptr;
MemCpy(res->text, &@c2d_text_wrapper_function, code_size);
code_ptr += code_size;
a = res->text;
a += 0x2e;
MemSetI64(a, res, 1);
a = res->text;
a += 0x42;
@patch_call_rel32(a, &Text2D);
// clipped
code_size = MSize(&@c2d_clipped_wrapper_function);
res->clipped = code_ptr;
MemCpy(res->clipped, &@c2d_clipped_wrapper_function, code_size);
code_ptr += code_size;
a = res->clipped;
a += 0x0b;
MemSetI64(a, res, 1);
a = res->clipped;
a += 0x14;
@patch_call_rel32(a, &ClipToRect2D);
// rotated
code_size = MSize(&@c2d_rotated_wrapper_function);
res->rotated = code_ptr;
MemCpy(res->rotated, &@c2d_rotated_wrapper_function, code_size);
code_ptr += code_size;
a = res->rotated;
a += 0x0b;
MemSetI64(a, res, 1);
a = res->rotated;
a += 0x18;
@patch_call_rel32(a, &Rotate2D);
// scaled
code_size = MSize(&@c2d_scaled_wrapper_function);
res->scaled = code_ptr;
MemCpy(res->scaled, &@c2d_scaled_wrapper_function, code_size);
code_ptr += code_size;
a = res->scaled;
a += 0x0b;
MemSetI64(a, res, 1);
a = res->scaled;
a += 0x1c;
@patch_call_rel32(a, &Scale2D);
return res;
}
"graphics2d ";