Compare commits

..

No commits in common. "d" and "master" have entirely different histories.
d ... master

117 changed files with 9601 additions and 3556 deletions

1
.gitignore vendored
View File

@ -3,4 +3,3 @@
/test/tmp/
/coverage/
/jes
/jestest

13
.gitmodules vendored
View File

@ -1,15 +1,6 @@
[submodule "libs/googletest"]
path = libs/googletest
url = https://github.com/google/googletest
url = git://github.com/google/googletest
[submodule "libs/glcxx"]
path = libs/glcxx
url = https://github.com/holtrop/glcxx.git
[submodule "libs/DerelictGL3"]
path = libs/DerelictGL3
url = https://github.com/DerelictOrg/DerelictGL3
[submodule "libs/DerelictGLFW3"]
path = libs/DerelictGLFW3
url = https://github.com/DerelictOrg/DerelictGLFW3
[submodule "libs/DerelictUtil"]
path = libs/DerelictUtil
url = https://github.com/DerelictOrg/DerelictUtil
url = git://github.com/holtrop/glcxx.git

View File

@ -5,12 +5,3 @@ all:
.PHONY: clean
clean:
./rscons clean
.PHONY: test
test:
./rscons build
./jestest
.PHONY: icon
icon:
./scripts/icon.rb

View File

@ -1,20 +1,39 @@
project_name "jes"
configure do
check_c_compiler
check_cxx_compiler
check_d_compiler
check_lib "X11"
check_lib "GLX"
check_c_header "getopt.h"
check_c_header "X11/Xlib.h"
check_cfg package: "freetype2"
check_program "convert"
check_lib "GL"
check_lib "dl"
check_lib "X11"
end
main_env = env do |env|
env["sources"] = glob("src/**/*.{c,d}", "libs/Derelict*/**/*.d")
env["CCFLAGS"] += %w[-Wall]
env["D_IMPORT_PATH"] += glob("src", "libs/Derelict*/source")
env["DFLAGS"] += %w[-Wall]
env["LIBS"] += %w[X11 GLX]
env.Program("jes", "${sources}")
build do
Environment.new do |env|
env["CPPDEFINES"] += %w[
APPNAME="jes"
VERSION="0.0.1"
GLCXX_GL_INCLUDE="gl3w.h"
PLATFORM_LINUX
JTK_X
]
env["CPPPATH"] += glob("src/**", "libs/glcxx/include")
env["CCFLAGS"] += %w[
-Wall
-O2
-Wno-switch
]
env["CXXFLAGS"] += %w[
-std=gnu++14
]
sources = glob("src/**/*.{c,cc,cxx}", "libs/glcxx/src/glcxx/*")
env.Program("jes", sources)
env.InstallDirectory("${prefix}/bin")
env.Install("${prefix}/bin", "jes")
env.Install("${prefix}/share", "share")
end
main_env.clone do |env|
env["DFLAGS"] += %w[-g -funittest]
env.Program("jestest", "${sources}")
end

@ -1 +0,0 @@
Subproject commit e1197a6c5f644a8c4a2f132de03d5c979490690c

@ -1 +0,0 @@
Subproject commit 09b9680cc8b40e20a48b2c008907cc749254aced

@ -1 +0,0 @@
Subproject commit 8dda33953e05e228a8a0459954023de2c0b375b5

33
rscons

File diff suppressed because one or more lines are too long

View File

@ -1,20 +0,0 @@
#!/usr/bin/env ruby
require "fileutils"
ICON = "share/jes/icons/jes-32x32.png"
OUTFILE = "src/jes/gui/icon.d"
system(*%W[convert #{ICON} bgra:icon.bgra])
icon_bgra = File.binread("icon.bgra")
FileUtils.rm_f("icon.bgra")
File.open(OUTFILE, "wb") do |fh|
fh.puts "module jes.gui.icon;"
fh.puts
fh.puts "const ubyte[] icon_32x32_bgra = ["
icon_bgra.bytes.each_slice(8) do |bytes|
fh.puts " #{bytes.map {|b| sprintf("0x%02xu,", b)}.join(" ")}"
end
fh.puts "];"
end

View File

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 565 B

View File

@ -0,0 +1,16 @@
#ifndef CHANGEOPERATION_H
#define CHANGEOPERATION_H
#include "ChangeUnit.h"
#include <list>
#include <stdlib.h>
class ChangeOperation
{
public:
size_t parent;
std::list<ChangeUnit> changes;
std::list<size_t> children;
};
#endif

15
src/core/ChangeUnit.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef CHANGEUNIT_H
#define CHANGEUNIT_H
#include <stdlib.h>
class ChangeUnit
{
public:
size_t change_buffer_offset;
size_t length;
size_t buffer_position;
bool insert;
};
#endif

244
src/core/Encoding.cc Normal file
View File

@ -0,0 +1,244 @@
#include "Encoding.h"
static inline bool
check_continuation_bytes(const uint8_t ** buffer,
uint8_t continuation_bytes_to_check)
{
for (uint8_t i = 0; i < continuation_bytes_to_check; i++)
{
if ((**buffer & 0xC0u) != 0x80u)
return false;
(*buffer)++;
}
return true;
}
Encoding::Type Encoding::detect_encoding(const uint8_t * buffer, size_t length)
{
for (size_t i = 0u; i < length; i++)
{
const uint8_t c = *buffer;
uint8_t continuation_bytes_to_check;
if ((c & 0x80u) == 0u)
{
buffer++;
continue;
}
else if ((c & 0xE0u) == 0xC0u)
{
continuation_bytes_to_check = 1u;
}
else if ((c & 0xF0u) == 0xE0u)
{
continuation_bytes_to_check = 2u;
}
else if ((c & 0xF8u) == 0xF0u)
{
continuation_bytes_to_check = 3u;
}
else if ((c & 0xFCu) == 0xF8u)
{
continuation_bytes_to_check = 4u;
}
else if ((c & 0xFEu) == 0xFCu)
{
continuation_bytes_to_check = 5u;
}
else
{
return CP_1252;
}
buffer++;
if (((i + continuation_bytes_to_check) < length) &&
check_continuation_bytes(&buffer, continuation_bytes_to_check))
{
i += continuation_bytes_to_check;
continue;
}
return CP_1252;
}
return UTF_8;
}
uint8_t Encoding::num_bytes_in_code_point(Type type, const uint8_t * encoded)
{
switch (type)
{
case UTF_8:
{
if ((*encoded & 0x80u) == 0u)
return 1u;
encoded++;
uint8_t n = 1u;
while ((*encoded++ & 0xC0u) == 0x80u)
n++;
return n;
}
break;
case CP_1252:
return 1u;
}
return 0u;
}
const uint8_t * Encoding::beginning_of_code_point(Type type, const uint8_t * encoded)
{
switch (type)
{
case UTF_8:
while ((*encoded & 0xC0u) == 0x80u)
encoded--;
return encoded;
case CP_1252:
return encoded;
}
return nullptr;
}
uint32_t Encoding::decode(Type type, const uint8_t * encoded, uint8_t * encoded_size)
{
uint32_t result = 0u;
uint8_t size = 0u;
switch (type)
{
case UTF_8:
{
const uint_fast8_t c = *encoded;
if ((c & 0x80u) == 0u)
{
result = c;
size = 1u;
}
else
{
uint_fast8_t following_bytes = 0u;
if ((c & 0xE0u) == 0xC0u)
{
result = c & 0x1Fu;
following_bytes = 1u;
}
else if ((c & 0xF0u) == 0xE0u)
{
result = c & 0x0Fu;
following_bytes = 2u;
}
else if ((c & 0xF8u) == 0xF0u)
{
result = c & 0x07u;
following_bytes = 3u;
}
else if ((c & 0xFCu) == 0xF8u)
{
result = c & 0x03u;
following_bytes = 4u;
}
else if ((c & 0xFEu) == 0xFCu)
{
result = c & 0x01u;
following_bytes = 5u;
}
size = following_bytes + 1u;
while (following_bytes-- > 0u)
{
encoded++;
result <<= 6u;
result |= *encoded & 0x3Fu;
}
}
}
break;
case CP_1252:
/* TODO: map byte to code point */
result = *encoded;
size = 1u;
break;
}
if (encoded_size != nullptr)
{
*encoded_size = size;
}
return result;
}
uint8_t Encoding::num_bytes_to_encode_code_point(uint32_t code_point, Type type)
{
switch (type)
{
case UTF_8:
if (code_point <= 0x7Fu)
{
return 1u;
}
else if (code_point <= 0x7FFu)
{
return 2u;
}
else if (code_point <= 0xFFFFu)
{
return 3u;
}
else if (code_point <= 0x1FFFFFu)
{
return 4u;
}
else if (code_point <= 0x3FFFFFFu)
{
return 5u;
}
else
{
return 6u;
}
break;
case CP_1252:
if (code_point <= 0xFFu)
{
return 1u;
}
else
{
return 0u;
}
break;
}
return 0u;
}
uint8_t Encoding::encode(uint32_t code_point, Type type, uint8_t * buffer)
{
switch (type)
{
case UTF_8:
{
uint8_t size = num_bytes_to_encode_code_point(code_point, type);
if (size == 1u)
{
*buffer = code_point;
}
else if (size > 1u)
{
*buffer = (0xFFu << (8u - size)) | (code_point >> (6u * (size - 1u)));
for (uint8_t i = 0u, end = size - 1u; i < end; i++)
{
buffer[end - i] = 0x80u | (code_point >> (6u * i) & 0x3Fu);
}
}
return size;
}
break;
case CP_1252:
if (code_point <= 0xFFu)
{
*buffer = code_point;
return 1u;
}
break;
}
return 0u;
}

29
src/core/Encoding.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef ENCODING_H
#define ENCODING_H
#include <stdint.h>
#include <stdlib.h>
class Encoding
{
public:
enum Type
{
UTF_8,
CP_1252,
};
enum : uint32_t
{
MAX_CODE_POINT_SIZE = 8u,
};
static Type detect_encoding(const uint8_t * buffer, size_t length);
static uint8_t num_bytes_in_code_point(Type type, const uint8_t * encoded);
static const uint8_t * beginning_of_code_point(Type type, const uint8_t * encoded);
static uint32_t decode(Type type, const uint8_t * encoded, uint8_t * encoded_size = nullptr);
static uint8_t num_bytes_to_encode_code_point(uint32_t code_point, Type type);
static uint8_t encode(uint32_t code_point, Type type, uint8_t * buffer);
};
#endif

123
src/core/File.cc Normal file
View File

@ -0,0 +1,123 @@
#include "File.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef _WIN32
#define JES_O_BINARY O_BINARY
#else
#define JES_O_BINARY 0
#endif
/**
* Open a file.
*
* @param[in] filename The filename.
* @param[in] writing Whether to open for writing.
*/
bool File::open(const char * filename, bool writing)
{
int fd;
if (writing)
{
/* TODO: handle mode */
fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC | JES_O_BINARY, 0644);
}
else
{
fd = ::open(filename, O_RDONLY | JES_O_BINARY);
}
if (fd < 0)
{
return false;
}
m_fd = fd;
return true;
}
/**
* Close the file.
*/
void File::close()
{
if (m_fd >= 0)
{
::close(m_fd);
m_fd = -1;
}
}
/**
* Get the file's size.
*
* This function will reset the file position to the beginning of the file.
*
* @return The file's size, or -1 on error.
*/
size_t File::get_size()
{
if (m_fd >= 0)
{
off_t o = lseek(m_fd, 0, SEEK_END);
lseek(m_fd, 0, SEEK_SET);
return o;
}
return -1;
}
/**
* Read from the file.
*
* @param[in] buf Memory buffer to read into. Must be large enough to hold
* size bytes.
* @param[in] size Number of bytes to read.
*
* @retval false The file failed to read.
* @retval true The file was read successfully.
*/
bool File::read(uint8_t * buf, size_t size)
{
size_t n_bytes_read = 0u;
for (;;)
{
off_t rd_size = ::read(m_fd, &buf[n_bytes_read], size - n_bytes_read);
if (rd_size <= 0)
break;
n_bytes_read += (size_t)rd_size;
if (n_bytes_read >= size)
break;
}
if (n_bytes_read != size)
{
return false;
}
return true;
}
bool File::write(const uint8_t * buf, size_t size)
{
if (size <= 0)
return true;
size_t n_bytes_written = 0u;
for (;;)
{
off_t write_size = ::write(m_fd, &buf[n_bytes_written], size - n_bytes_written);
if (write_size <= 0)
break;
n_bytes_written += (size_t)write_size;
if (n_bytes_written >= size)
break;
}
if (n_bytes_written != size)
{
return false;
}
return true;
}

27
src/core/File.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef FILE_H
#define FILE_H
#include <stdint.h>
#include <stdlib.h>
#include "Span.h"
class File
{
public:
File() : m_fd(-1) {}
~File() { close(); }
bool open(const char * filename, bool writing = false);
void close();
size_t get_size();
bool read(uint8_t * buf, size_t size);
bool write(const uint8_t * buf, size_t size);
bool write(const Span & span)
{
return write(span.start, span.length);
}
protected:
int m_fd;
};
#endif

129
src/core/GapBuffer.cc Normal file
View File

@ -0,0 +1,129 @@
#include "GapBuffer.h"
#include "System.h"
#include <string.h>
GapBuffer::GapBuffer()
{
int num_pages = (64u * 1024u + System::page_size - 1u) >> System::page_size_log;
m_buffer = (uint8_t *)System::alloc_pages(num_pages);
m_buffer_size = System::page_size;
m_size = 0u;
m_gap_position = 0u;
}
GapBuffer::GapBuffer(uint8_t * buffer, size_t buffer_size, size_t size)
{
m_buffer = buffer;
m_buffer_size = buffer_size;
m_size = size;
m_gap_position = size;
}
GapBuffer::~GapBuffer()
{
System::free_pages(m_buffer, m_buffer_size >> System::page_size_log);
}
void GapBuffer::insert(size_t position, const uint8_t * data, size_t length)
{
ensure_free(length);
move_gap(position);
memcpy(&m_buffer[m_gap_position], data, length);
m_gap_position += length;
m_size += length;
}
void GapBuffer::erase(size_t position, size_t length)
{
if ((position < m_size) && ((position + length) <= m_size))
{
if ((position + length) == m_gap_position)
{
m_gap_position -= length;
m_size -= length;
}
else
{
move_gap(position);
m_size -= length;
}
}
}
void GapBuffer::clear()
{
m_size = 0u;
m_gap_position = 0u;
}
#ifdef ENABLE_TESTING
std::string GapBuffer::get_string()
{
compact();
return std::string((char *)m_buffer, m_size);
}
void GapBuffer::set_string(const std::string & s)
{
clear();
insert(0u, (const uint8_t *)s.c_str(), s.size());
}
#endif
void GapBuffer::ensure_free(size_t length)
{
if (gap_size() < length)
{
/* We're out of space. Allocate more and move data. */
size_t new_size = (m_buffer_size + (128u * 1024u)) & System::page_base_mask;
size_t new_num_pages = new_size >> System::page_size_log;
uint8_t * new_buffer = (uint8_t *)System::alloc_pages(new_num_pages);
memcpy(new_buffer, m_buffer, m_gap_position);
memcpy(&new_buffer[m_gap_position], &m_buffer[m_gap_position + gap_size()], m_size - m_gap_position);
/* Free the old buffer */
System::free_pages(m_buffer, m_buffer_size >> System::page_size_log);
m_buffer = new_buffer;
m_buffer_size = new_size;
m_gap_position = m_size;
}
}
void GapBuffer::move_gap(size_t position)
{
if (position != m_gap_position)
{
if (position < m_gap_position)
{
memmove(&m_buffer[position + gap_size()], &m_buffer[position], m_gap_position - position);
}
else
{
memmove(&m_buffer[m_gap_position], &m_buffer[m_gap_position + gap_size()], position - m_gap_position);
}
m_gap_position = position;
}
}
void GapBuffer::copy_to(size_t source_position, size_t length, GapBuffer & other, size_t destination_position)
{
if ((source_position < m_size) &&
(length > 0u) &&
((source_position + length) <= m_size))
{
if ((m_gap_position <= source_position) ||
(m_gap_position >= (source_position + length)))
{
/* The gap is before or after the range of data to copy. */
other.insert(destination_position, address(source_position), length);
}
else
{
/* The gap is in the middle of the range of data to copy. */
size_t pre_gap_size = m_gap_position - source_position;
other.insert(destination_position, address(source_position), pre_gap_size);
other.insert(destination_position + pre_gap_size, address(source_position + pre_gap_size), length - pre_gap_size);
}
}
}

169
src/core/GapBuffer.h Normal file
View File

@ -0,0 +1,169 @@
#ifndef GAPBUFFER_H
#define GAPBUFFER_H
#include <stdint.h>
#include <stdlib.h>
#ifdef ENABLE_TESTING
#include <string>
#endif
class GapBuffer
{
public:
/**
* Create a new GapBuffer object.
*
* The GapBuffer will allocate its own memory.
*/
GapBuffer();
/**
* Create a GapBuffer object that points to preallocated memory.
*
* The GapBuffer object will take over ownership of the allocated memory.
*
* @param buffer
* Pointer to buffer allocated by System::alloc_pages().
* @param buffer_size
* Size of the buffer allocated by System::alloc_pages().
* @param size
* Size of the data in the buffer.
*/
GapBuffer(uint8_t * buffer, size_t buffer_size, size_t size);
/**
* Destroy the GapBuffer object and free its memory.
*/
~GapBuffer();
/**
* Insert data into the gap buffer at the given position.
*
* @param position
* Position in the gap buffer to insert the code point at.
* @param data
* Pointer to the data to insert.
* @param length
* Length of the data to insert.
*/
void insert(size_t position, const uint8_t * data, size_t length);
/**
* Erase data from the gap buffer.
*
* @param position
* Position in the gap buffer to erase data from.
* @param length
* Length of the data to erase.
*/
void erase(size_t position, size_t length);
/**
* Erase all data from the gap buffer.
*/
void clear();
/**
* Get the size of the data stored within the buffer.
*/
size_t size() const
{
return m_size;
}
/**
* Get the memory address of a buffer location.
*
* @param offset
* The index into the gap buffer data.
*/
uint8_t * address(size_t offset) const
{
if (offset < m_gap_position)
{
return &m_buffer[offset];
}
else
{
return &m_buffer[offset + gap_size()];
}
}
/**
* Move buffer gap to the end of the buffer so the contents are congruent
* at the beginning of the buffer.
*/
void compact()
{
move_gap(m_size);
}
/**
* Copy a range of data from this GapBuffer to another.
*
* @param source_position
* Position in the gap buffer containing the data to copy.
* @param length
* Length of the data to copy.
* @param other
* Destination GapBuffer to copy the data into.
* @param destination_position
* Position in the destination GapBuffer to copy the data to.
*/
void copy_to(size_t source_position, size_t length, GapBuffer & other, size_t destination_position);
#ifdef ENABLE_TESTING
/**
* Get the contents of the gap buffer as a string.
*
* This makes a copy of the entire buffer in a std::string. This method is
* intended for use by unit tests.
*/
std::string get_string();
/**
* Replace the buffer contents with a string.
*/
void set_string(const std::string & s);
#endif
protected:
/** Address of the allocated memory buffer. */
uint8_t * m_buffer;
/** Size of the allocated memory buffer. */
size_t m_buffer_size;
/** Size of the data stored in the buffer. */
size_t m_size;
/** Index of the gap in the memory buffer. */
size_t m_gap_position;
/**
* Get the gap size.
*/
size_t gap_size() const
{
return m_buffer_size - m_size;
}
/**
* Verify that there is enough free space in the gap, and if not, grow the
* gap and move data.
*
* @param length
* The number of bytes that must be free.
*/
void ensure_free(size_t length);
/**
* Move the gap buffer gap position to the requested position.
*
* @param position
* New gap position. Must be <= m_size.
*/
void move_gap(size_t position);
};
#endif

11
src/core/LineEndings.cc Normal file
View File

@ -0,0 +1,11 @@
#include "LineEndings.h"
static uint8_t lf[] = "\n";
static uint8_t crlf[] = "\r\n";
static uint8_t cr[] = "\r";
const Span LineEndings::spans[] = {
Span(lf, 1u),
Span(crlf, 2u),
Span(cr, 1u),
};

20
src/core/LineEndings.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef LINEENDINGS_H
#define LINEENDINGS_H
#include "Span.h"
class LineEndings
{
public:
enum Type
{
LF,
CRLF,
CR,
COUNT,
};
static const Span spans[COUNT];
};
#endif

72
src/core/PagedBuffer.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef PAGEDBUFFER_H
#define PAGEDBUFFER_H
#include "System.h"
#include <vector>
#include <stdint.h>
#include <stdlib.h>
template <typename T>
class PagedBuffer
{
public:
/**
* Create a PagedBuffer.
*/
PagedBuffer<T>()
{
m_n_per_page = System::page_size / sizeof(T);
m_size = 0u;
}
~PagedBuffer<T>()
{
for (auto it : m_pages)
{
System::free_pages(it, 1);
}
}
const T & operator[](unsigned int index) const
{
while (index >= (m_pages.size() * m_n_per_page))
{
grow();
}
return m_pages[page_index(index)][index_in_page(index)];
}
T & operator[](unsigned int index)
{
while (index >= (m_pages.size() * m_n_per_page))
{
grow();
}
return m_pages[page_index(index)][index_in_page(index)];
}
size_t size() { return m_size; }
protected:
unsigned int page_index(unsigned int index)
{
return index / m_n_per_page;
}
unsigned int index_in_page(unsigned int index)
{
return index % m_n_per_page;
}
void grow()
{
m_pages.push_back((T *)System::alloc_pages(1));
m_size += m_n_per_page;
}
std::vector<T *> m_pages;
unsigned long m_size;
unsigned int m_n_per_page;
};
#endif

32
src/core/Timer.cc Normal file
View File

@ -0,0 +1,32 @@
#include "Timer.h"
#include <sys/time.h>
#include <stdio.h>
static long get_usec()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000 + tv.tv_usec;
}
Timer::Timer()
{
m_start_time = 0;
m_elapsed = 0;
start();
}
void Timer::start()
{
m_start_time = get_usec();
}
void Timer::stop()
{
m_elapsed = get_usec() - m_start_time;
}
void Timer::print()
{
printf("Elapsed: %ldus\n", m_elapsed);
}

19
src/core/Timer.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef TIMER_H
#define TIMER_H
class Timer
{
public:
Timer();
void start();
void stop();
void print();
long get_elapsed() { return m_elapsed; }
protected:
long m_start_time;
long m_elapsed;
};
#endif

View File

@ -1,32 +0,0 @@
module gltk.array;
import derelict.opengl;
class Array
{
private GLuint m_id;
this()
{
m_id = 0u;
glGenVertexArrays(1, &m_id);
if (m_id == 0u)
{
throw new Exception("Failed to allocate an OpenGL array");
}
}
~this()
{
glDeleteVertexArrays(1, &m_id);
}
void bind()
{
glBindVertexArray(m_id);
}
@property GLuint id()
{
return m_id;
}
}

View File

@ -1,47 +0,0 @@
module gltk.buffer;
import derelict.opengl;
class Buffer
{
private GLuint m_id;
private GLenum m_target;
this(GLenum target)
{
m_id = 0u;
glGenBuffers(1, &m_id);
if (m_id == 0u)
{
throw new Exception("Failed to allocate an OpenGL buffer");
}
m_target = target;
}
~this()
{
glDeleteBuffers(1, &m_id);
}
void bind()
{
glBindBuffer(m_target, m_id);
}
@property GLuint id()
{
return m_id;
}
void set_buffer_data(GLenum usage, const void * ptr, size_t size)
{
bind();
glBufferData(m_target, size, ptr, usage);
}
void set_buffer_data(T)(GLenum usage, T[] arr)
{
bind();
glBufferData(m_target, arr.length * arr[0].sizeof, arr.ptr, usage);
}
}

View File

@ -1,7 +0,0 @@
module gltk;
public import gltk.array;
public import gltk.buffer;
public import gltk.program;
public import gltk.shader;
public import gltk.texture;

View File

@ -1,181 +0,0 @@
module gltk.program;
import gltk.shader;
import derelict.opengl;
import std.string;
class Program(uniforms...)
{
/* The number of template parameters must be a multiple of 2. */
static assert((uniforms.length % 2) == 0);
private GLuint m_id;
static foreach (i, v; uniforms)
{
static if ((i % 2) == 0)
{
mixin("private GLint m_uniform_" ~ v ~ ";");
}
}
this(Args...)(Args args)
{
m_id = glCreateProgram();
if (m_id == 0u)
{
throw new Exception("Failed to allocate an OpenGL program");
}
static if (args.length > 0u)
{
build(args);
}
}
~this()
{
glDeleteProgram(m_id);
}
void attach_shader(Shader shader) const
{
glAttachShader(m_id, shader.id);
}
void bind_attrib_location(string name, uint index) const
{
glBindAttribLocation(m_id, index, name.toStringz());
}
void link()
{
glLinkProgram(m_id);
GLint link_status;
glGetProgramiv(m_id, GL_LINK_STATUS, &link_status);
if (link_status != GL_TRUE)
{
string message = "Failed to link program";
GLint log_length = 0;
glGetProgramiv(m_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char[] log = new char[log_length];
glGetProgramInfoLog(m_id, log_length, &log_length, log.ptr);
message ~= "\n";
message ~= log;
message ~= "\n";
}
throw new Exception(message);
}
static foreach(i, v; uniforms)
{
static if ((i % 2) == 0)
{
mixin("m_uniform_" ~ v ~ " = glGetUniformLocation(m_id, \"" ~ v ~ "\");");
}
}
}
GLint get_uniform_location(string uniform_name) const
{
return glGetUniformLocation(m_id, uniform_name.toStringz());
}
void get_uniform_locations(Args...)(string uniform_name, GLint * uniform_location, Args args) const
{
*uniform_location = get_uniform_location(uniform_name);
static if (args.length > 0u)
{
get_uniform_locations(args);
}
}
@property GLuint id() const
{
return m_id;
}
void use() const
{
glUseProgram(m_id);
}
private static string uniform_param_decl_list(string spec)
{
int count = spec[0] - '0';
string type;
if (spec[1] == 'i')
{
type = "GLint";
}
else if (spec[1..2] == "ui")
{
type = "GLuint";
}
else if (spec[1] == 'f')
{
type = "GLfloat";
}
assert(type != "");
if (spec[$ - 1] == 'v')
{
return "uint count, const " ~ type ~ " * v";
}
else
{
string[] decls;
for (int i = 0; i < count; i++)
{
decls ~= type ~ " v" ~ cast(char)('0' + i);
}
return decls.join(", ");
}
}
private static string uniform_param_list(string spec)
{
int count = spec[0] - '0';
if (spec[$ - 1] == 'v')
{
return "count, v";
}
else
{
string[] vees;
for (int i = 0; i < count; i++)
{
vees ~= "v" ~ cast(char)('0' + i);
}
return vees.join(", ");
}
}
static foreach (i, v; uniforms)
{
static if ((i % 2) == 0)
{
mixin("void set_" ~ v ~ "(" ~ uniform_param_decl_list(uniforms[i + 1]) ~ ")" ~
"{" ~
" glUniform" ~ uniforms[i + 1] ~ "(m_uniform_" ~ v ~ ", " ~ uniform_param_list(uniforms[i + 1]) ~ ");" ~
"}");
}
}
private void build(Args...)(Shader s, Args args)
{
attach_shader(s);
build(args);
}
private void build(Args...)(string attrib_name, uint index, Args args)
{
bind_attrib_location(attrib_name, index);
build(args);
}
private void build()
{
link();
}
}

View File

@ -1,80 +0,0 @@
module gltk.shader;
import derelict.opengl;
static import std.file;
class Shader
{
private GLuint m_id;
private GLenum m_shader_type;
this(GLenum shader_type)
{
m_shader_type = shader_type;
m_id = glCreateShader(shader_type);
if (m_id == 0u)
{
throw new Exception("Failed to allocate an OpenGL shader");
}
}
~this()
{
glDeleteShader(m_id);
}
void set_source(const char * source, int length = -1)
{
GLint status;
GLint gllength = length;
glShaderSource(m_id, 1, &source, &gllength);
glCompileShader(m_id);
glGetShaderiv(m_id, GL_COMPILE_STATUS, &status);
if (status == GL_TRUE)
{
return;
}
string message = "Error compiling ";
switch (m_shader_type)
{
case GL_VERTEX_SHADER:
message ~= "vertex";
break;
case GL_FRAGMENT_SHADER:
message ~= "fragment";
break;
default:
message ~= "unknown";
break;
}
message ~= " shader";
GLint log_length;
glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char[] log = new char[log_length];
glGetShaderInfoLog(m_id, log_length, &log_length, log.ptr);
message ~= "\nShader Log:\n";
message ~= log;
message ~= "\n";
}
glDeleteShader(m_id);
throw new Exception(message);
}
void set_source_from_file(string filename)
{
const(char)[] file_data = cast(const(char)[])std.file.read(filename);
set_source(file_data.ptr, cast(int)file_data.length);
}
@property GLuint id()
{
return m_id;
}
}

View File

@ -1,44 +0,0 @@
module gltk.texture;
import derelict.opengl;
class Texture
{
private GLuint m_id;
this()
{
m_id = 0u;
glGenTextures(1, &m_id);
if (m_id == 0u)
{
throw new Exception("Failed to allocate an OpenGL texture");
}
}
~this()
{
glDeleteTextures(1, &m_id);
}
void bind(GLenum target) const
{
glBindTexture(target, m_id);
}
@property GLuint id()
{
return m_id;
}
static uint next_power_of_2(uint n)
{
n--;
n |= n >> 1u;
n |= n >> 2u;
n |= n >> 4u;
n |= n >> 8u;
n |= n >> 16u;
n++;
return n;
}
};

91
src/gui/Font.cc Normal file
View File

@ -0,0 +1,91 @@
#include "Font.h"
#define round_up_26_6(val) (((val) + 63) >> 6u)
static FT_Library ft_library_handle;
static bool ft_initialized;
bool Initialize_FreeType()
{
if (ft_initialized)
{
return true;
}
if (FT_Init_FreeType(&ft_library_handle) != 0)
{
return false;
}
ft_initialized = true;
return true;
}
bool Font::load(const char * fname, int size)
{
if (!Initialize_FreeType())
{
return false;
}
if (FT_New_Face(ft_library_handle, fname, 0, &m_face) != 0)
{
return false;
}
FT_Set_Pixel_Sizes(m_face, 0, size);
return preload_glyphs();
}
bool Font::preload_glyphs()
{
static const char preload_glyph_list[] = "HMgjqxy_|^";
int max_top = -9999;
int min_bottom = 9999;
m_advance = 0;
for (size_t i = 0u; i < sizeof(preload_glyph_list) - 1u; i++)
{
std::shared_ptr<Glyph> g = get_glyph(preload_glyph_list[i]);
if (g == NULL)
{
return false;
}
if (m_face->glyph->bitmap_top > max_top)
{
max_top = m_face->glyph->bitmap_top;
}
int bitmap_bottom = m_face->glyph->bitmap_top - m_face->glyph->bitmap.rows;
if (bitmap_bottom < min_bottom)
{
min_bottom = bitmap_bottom;
}
if (g->get_advance() > m_advance)
{
m_advance = g->get_advance();
}
}
m_line_height = round_up_26_6(m_face->size->metrics.height);
m_baseline_offset = (m_line_height - (max_top - min_bottom)) / 2 - min_bottom;
return true;
}
std::shared_ptr<Glyph> Font::get_glyph(FT_ULong character)
{
auto it = m_glyphs.find(character);
if (it != m_glyphs.end())
{
return it->second;
}
std::shared_ptr<Glyph> glyph = std::make_shared<Glyph>();
if (!glyph->load(m_face, character))
{
glyph = nullptr;
}
m_glyphs[character] = glyph;
return glyph;
}

27
src/gui/Font.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef FONT_H
#define FONT_H
#include <unordered_map>
#include <memory>
#include "Glyph.h"
class Font
{
public:
bool load(const char * fname, int size);
std::shared_ptr<Glyph> get_glyph(FT_ULong character);
int get_advance() { return m_advance; }
int get_line_height() { return m_line_height; }
int get_baseline_offset() { return m_baseline_offset; }
protected:
bool preload_glyphs();
FT_Face m_face;
std::unordered_map<FT_ULong, std::shared_ptr<Glyph>> m_glyphs;
int m_advance;
int m_line_height;
int m_baseline_offset;
};
#endif

52
src/gui/Glyph.cc Normal file
View File

@ -0,0 +1,52 @@
#include "Glyph.h"
#define round_up_26_6(val) (((val) + 63) >> 6u)
bool Glyph::load(FT_Face face, FT_ULong char_code)
{
if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0)
return false;
m_texture = glcxx::Texture::create();
m_texture->bind(GL_TEXTURE_2D);
int width = face->glyph->bitmap.width;
int rounded_width = glcxx::Texture::next_power_of_2(width);
int height = face->glyph->bitmap.rows;
int rounded_height = glcxx::Texture::next_power_of_2(height);
m_advance = round_up_26_6(face->glyph->advance.x);
uint8_t * texture = new uint8_t[rounded_width * rounded_height];
memset(texture, 0, rounded_width * rounded_height);
for (int i = 0; i < height; i++)
{
memcpy(&texture[rounded_width * i],
&face->glyph->bitmap.buffer[width * (height - i - 1)],
width);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, rounded_width, rounded_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture);
delete[] texture;
m_array = glcxx::Array::create();
m_array->bind();
int left = face->glyph->bitmap_left;
int top = face->glyph->bitmap_top;
float s_max = width / (float)rounded_width;
float t_max = height / (float)rounded_height;
m_buffer = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, {
(GLfloat)left, (GLfloat)(top - height), 0.0, 0.0,
(GLfloat)(left + width), (GLfloat)(top - height), s_max, 0.0,
(GLfloat)left, (GLfloat)top, 0.0, t_max,
(GLfloat)(left + width), (GLfloat)top, s_max, t_max,
});
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
return true;
}

27
src/gui/Glyph.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef GLYPH_H
#define GLYPH_H
#include <ft2build.h>
#include FT_FREETYPE_H
#include "glcxx.hpp"
class Glyph
{
public:
bool load(FT_Face face, FT_ULong char_code);
int get_advance() { return m_advance; }
void render()
{
m_array->bind();
m_texture->bind(GL_TEXTURE_2D);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
protected:
int m_advance;
std::shared_ptr<glcxx::Texture> m_texture;
std::shared_ptr<glcxx::Buffer> m_buffer;
std::shared_ptr<glcxx::Array> m_array;
};
#endif

44
src/gui/Pane.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef PANE_H
#define PANE_H
class Pane
{
public:
Pane()
{
m_x = 0;
m_y = 0;
m_width = 0;
m_height = 0;
}
virtual void move(int x, int y)
{
m_x = x;
m_y = y;
}
virtual void resize(int width, int height)
{
m_width = width;
m_height = height;
}
int win_x(int offset)
{
return m_x + offset;
}
int win_y(int offset)
{
return m_y + offset;
}
protected:
int m_x;
int m_y;
int m_width;
int m_height;
};
#endif

17
src/gui/gl/FlatShader.cc Normal file
View File

@ -0,0 +1,17 @@
#include "FlatShader.h"
#include "Runtime.h"
FlatShader::FlatShader()
{
std::string v_path = Runtime::find(Runtime::SHADER, "flat.v");
std::string f_path = Runtime::find(Runtime::SHADER, "flat.f");
m_program = glcxx::Program::create(
glcxx::Shader::create_from_file(GL_VERTEX_SHADER, v_path.c_str()),
glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, f_path.c_str()),
"coords", 0);
m_uniforms.viewport_size = m_program->get_uniform_location("viewport_size");
m_uniforms.position = m_program->get_uniform_location("position");
m_uniforms.color = m_program->get_uniform_location("color");
}

40
src/gui/gl/FlatShader.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef FLATSHADER_H
#define FLATSHADER_H
#include "glcxx.hpp"
#include <memory>
class FlatShader
{
public:
FlatShader();
void use() { m_program->use(); }
void set_viewport_size(int width, int height)
{
glUniform2i(m_uniforms.viewport_size, width, height);
}
void set_color(float r, float g, float b, float a)
{
glUniform4f(m_uniforms.color, r, g, b, a);
}
void set_position(int x, int y)
{
glUniform2i(m_uniforms.position, x, y);
}
protected:
std::shared_ptr<glcxx::Program> m_program;
struct
{
GLint viewport_size;
GLint color;
GLint position;
} m_uniforms;
};
#endif

51
src/gui/gl/GL.cc Normal file
View File

@ -0,0 +1,51 @@
#include "GL.h"
GL::GL()
{
m_shaders.text = std::make_shared<TextShader>();
m_shaders.text->use();
m_shaders.text->set_texture(0);
m_shaders.text->set_color(1.0, 1.0, 1.0, 1.0);
m_shaders.rect = std::make_shared<RectShader>();
GLint rect_coords[] = {
0, 0,
1, 0,
1, 1,
0, 1};
m_rect_array = glcxx::Array::create();
m_rect_array->bind();
m_rect_buffer = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW,
rect_coords, sizeof(rect_coords));
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, 0);
}
void GL::draw_rect(int x, int y, int width, int height,
float r, float g, float b, float a)
{
m_rect_array->bind();
m_shaders.rect->use();
m_shaders.rect->set_color(r, g, b, a);
m_shaders.rect->set_position(x, y);
m_shaders.rect->set_size(width, height);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void GL::draw_character(int x, int y, uint32_t character, Font & font,
float r, float g, float b, float a)
{
m_shaders.text->use();
m_shaders.text->set_color(r, g, b, a);
m_shaders.text->set_position(x, y + font.get_baseline_offset());
font.get_glyph(character)->render();
}
void GL::resize(int width, int height)
{
m_shaders.text->use();
m_shaders.text->set_viewport_size(width, height);
m_shaders.rect->use();
m_shaders.rect->set_viewport_size(width, height);
}

34
src/gui/gl/GL.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef GL_H
#define GL_H
#include "glcxx.hpp"
#include "TextShader.h"
#include "FlatShader.h"
#include "RectShader.h"
#include "Font.h"
#include <memory>
class GL
{
public:
GL();
void draw_rect(int x, int y, int width, int height,
float r, float g, float b, float a);
void draw_character(int x, int y, uint32_t character, Font & font,
float r, float g, float b, float a);
void resize(int width, int height);
protected:
struct
{
std::shared_ptr<TextShader> text;
std::shared_ptr<FlatShader> flat;
std::shared_ptr<RectShader> rect;
} m_shaders;
std::shared_ptr<glcxx::Array> m_rect_array;
std::shared_ptr<glcxx::Buffer> m_rect_buffer;
};
#endif

18
src/gui/gl/RectShader.cc Normal file
View File

@ -0,0 +1,18 @@
#include "RectShader.h"
#include "Runtime.h"
RectShader::RectShader()
{
std::string v_path = Runtime::find(Runtime::SHADER, "rect.v");
std::string f_path = Runtime::find(Runtime::SHADER, "rect.f");
m_program = glcxx::Program::create(
glcxx::Shader::create_from_file(GL_VERTEX_SHADER, v_path.c_str()),
glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, f_path.c_str()),
"coords", 0);
m_uniforms.viewport_size = m_program->get_uniform_location("viewport_size");
m_uniforms.color = m_program->get_uniform_location("color");
m_uniforms.position = m_program->get_uniform_location("position");
m_uniforms.size = m_program->get_uniform_location("size");
}

46
src/gui/gl/RectShader.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef RECTSHADER_H
#define RECTSHADER_H
#include "glcxx.hpp"
#include <memory>
class RectShader
{
public:
RectShader();
void use() { m_program->use(); }
void set_viewport_size(int width, int height)
{
glUniform2i(m_uniforms.viewport_size, width, height);
}
void set_color(float r, float g, float b, float a)
{
glUniform4f(m_uniforms.color, r, g, b, a);
}
void set_position(int x, int y)
{
glUniform2i(m_uniforms.position, x, y);
}
void set_size(int x, int y)
{
glUniform2i(m_uniforms.size, x, y);
}
protected:
std::shared_ptr<glcxx::Program> m_program;
struct
{
GLint viewport_size;
GLint color;
GLint position;
GLint size;
} m_uniforms;
};
#endif

18
src/gui/gl/TextShader.cc Normal file
View File

@ -0,0 +1,18 @@
#include "TextShader.h"
#include "Runtime.h"
TextShader::TextShader()
{
std::string v_path = Runtime::find(Runtime::SHADER, "text.v");
std::string f_path = Runtime::find(Runtime::SHADER, "text.f");
m_program = glcxx::Program::create(
glcxx::Shader::create_from_file(GL_VERTEX_SHADER, v_path.c_str()),
glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, f_path.c_str()),
"coords", 0);
m_uniforms.viewport_size = m_program->get_uniform_location("viewport_size");
m_uniforms.texture = m_program->get_uniform_location("texture");
m_uniforms.color = m_program->get_uniform_location("color");
m_uniforms.position = m_program->get_uniform_location("position");
}

46
src/gui/gl/TextShader.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef TEXTSHADER_H
#define TEXTSHADER_H
#include "glcxx.hpp"
#include <memory>
class TextShader
{
public:
TextShader();
void use() { m_program->use(); }
void set_viewport_size(int width, int height)
{
glUniform2i(m_uniforms.viewport_size, width, height);
}
void set_texture(int texture)
{
glUniform1i(m_uniforms.texture, texture);
}
void set_color(float r, float g, float b, float a)
{
glUniform4f(m_uniforms.color, r, g, b, a);
}
void set_position(int x, int y)
{
glUniform2i(m_uniforms.position, x, y);
}
protected:
std::shared_ptr<glcxx::Program> m_program;
struct
{
GLint viewport_size;
GLint texture;
GLint color;
GLint position;
} m_uniforms;
};
#endif

1339
src/gui/gl3w/gl3w.c Normal file

File diff suppressed because it is too large Load Diff

1235
src/gui/gl3w/gl3w.h Normal file

File diff suppressed because it is too large Load Diff

4544
src/gui/gl3w/glcorearb.h Normal file

File diff suppressed because it is too large Load Diff

99
src/gui/jes_icon-32x32.c Normal file
View File

@ -0,0 +1,99 @@
#include "jes_icon-32x32.h"
/* GIMP RGB C-Source image dump (jes_icon-32x32.c) */
const uint8_t jes_icon_32x32[] = {
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\310\310\310\377\377\377"
"\377\377\377\377\377\377\040\040\040\000\000\000\000\000\000\000\000\000***\261\261\261\361\361"
"\361\365\365\365\265\265\265\"\"\"\000\000\000\000\000\000\000\000\000\000\000\000;;;\300\300\300"
"\360\360\360\347\347\347\240\240\240\033\033\033\000\000\000\000\000\000\377\063\377\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000"
"\000&&&\360\360\360\252\252\252\035\035\035\030\030\030\247\247\247\334\334\334\005"
"\005\005\000\000\000\000\000\000\022\022\022\360\360\360\221\221\221\022\022\022\025\025\025[[[\177"
"\177\177\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"PPP\377\377\377\040\040\040\000\000\000\000\000\000\252\252\252\344\344\344\010\010\010\000\000"
"\000\000\000\000\017\017\017\366\366\366```\000\000\000\000\000\000@@@\377\377\377\064\064\064\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000\000\357\357\357\236\236\236"
"\000\000\000\000\000\000\000\000\000\000\000\000\320\320\320\222\222\222\000\000\000\000\000\000\034\034\034\372"
"\372\372\277\277\277JJJ\017\017\017\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000\000"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\255\255\255\000\000\000\000\000\000\000\000\000LLL\310\310\310\375\375\375\376"
"\376\376\307\307\307\061\061\061\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000\000\360\360\360\211"
"\211\211\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\013\013\013RRR\342\342\342\334\334\334\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000\000\255\255"
"\255\312\312\312\001\001\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000vvv\372\372\372\003\003\003\000\000\000\377\063\377\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040\000\000\000\000\000\000***\363"
"\363\363\232\232\232\"\"\"\013\013\013\065\065\065\230\230\230TTT\000\000\000\000\000\000M"
"MM\227\227\227\063\063\063\012\012\012)))\320\320\320\266\266\266\000\000\000\000\000\000\377"
"\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PPP\377\377\377\040\040\040"
"\000\000\000\000\000\000\000\000\000+++\255\255\255\355\355\355\365\365\365\312\312\312iii"
"\007\007\007\000\000\000\000\000\000\006\006\006hhh\314\314\314\365\365\365\343\343\343\230\230\230"
"\023\023\023\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000^^^\377\377\377\016\016\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\016\016\274\274"
"\274\316\316\316\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\214\214\214\377\377\377\371\371\371"
"\306\306\306+++\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\063\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
};

8
src/gui/jes_icon-32x32.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef JES_ICON_32X32_H
#define JES_ICON_32X32_H
#include <stdint.h>
extern const uint8_t jes_icon_32x32[];
#endif

59
src/gui/jtk/Jtk.cc Normal file
View File

@ -0,0 +1,59 @@
#include "Jtk.h"
#ifdef JTK_X
#include <GL/glx.h>
#include <stdio.h>
Display * g_display;
XVisualInfo * g_vi;
XSetWindowAttributes g_swa;
GLXContext g_context;
/**
* Initialize the Jtk subsystem.
*
* @return true on success, false on failure
*/
bool Jtk_Init()
{
static int glx_attribute_list[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
None,
};
g_display = XOpenDisplay(NULL);
if (g_display == NULL)
{
fprintf(stderr, "XOpenDisplay() failure\n");
return false;
}
g_vi = glXChooseVisual(g_display, DefaultScreen(g_display),
glx_attribute_list);
if (g_vi == NULL)
{
fprintf(stderr, "glXChooseVisual() failure\n");
return false;
}
g_context = glXCreateContext(g_display, g_vi, NULL, True);
if (g_context == NULL)
{
fprintf(stderr, "glXCreateContext() failure\n");
return false;
}
Colormap colormap = XCreateColormap(g_display,
RootWindow(g_display, g_vi->screen), g_vi->visual, AllocNone);
g_swa.colormap = colormap;
g_swa.border_pixel = 0;
g_swa.event_mask = StructureNotifyMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask;
return true;
}
#endif

12
src/gui/jtk/Jtk.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef JTK_H
#define JTK_H
#include "Jtk_event.h"
#include "keys.h"
#include "Jtk_time.h"
#include "Jtk_timer.h"
#include "Jtk_window.h"
bool Jtk_Init();
#endif

482
src/gui/jtk/Jtk_event.cc Normal file
View File

@ -0,0 +1,482 @@
#include "Jtk.h"
#ifdef JTK_X
#include <GL/glx.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include "Jtk_internal.h"
#include <unordered_map>
/** Do not wait longer than 100ms */
#define MAX_WAIT_TIME 100000u
static std::unordered_map<unsigned int, size_t> g_repeating_keys;
static std::unordered_map<size_t, unsigned int> g_key_repeat_timers;
#if 0
static void StopKeyRepeat(unsigned int x_keycode)
{
auto it = g_repeating_keys.find(x_keycode);
if (it != g_repeating_keys.end())
{
size_t timer_id = it->second;
Jtk_RemoveTimer(timer_id);
g_repeating_keys.erase(x_keycode);
g_key_repeat_timers.erase(timer_id);
}
}
#endif
#if 0
static unsigned int GetXState()
{
Window win;
int i;
unsigned int state;
XQueryPointer(g_display, RootWindow(g_display, DefaultScreen(g_display)), &win, &win, &i, &i, &i, &i, &state);
return state;
}
#endif
static uint32_t XStateToJtkKeyMods(unsigned int x_state)
{
uint32_t mods = 0u;
/* OR in the modifier states */
if (x_state & ShiftMask)
{
mods |= JES_KEY_MODS_SHIFT;
}
if (x_state & LockMask)
{
mods |= JES_KEY_MODS_LOCK;
}
if (x_state & ControlMask)
{
mods |= JES_KEY_MODS_CTRL;
}
return mods;
}
static uint32_t XKeyToJtkKey(unsigned int x_keycode, unsigned int x_state)
{
XKeyEvent x_key_event;
x_key_event.type = KeyPress;
x_key_event.display = g_display;
/* Turn off the ControlMask bit for looking up keys. We'll handle control
* keys ourselves. */
x_key_event.state = x_state & ~ControlMask;
x_key_event.keycode = x_keycode;
char buffer;
KeySym keysym;
uint32_t key = JES_KEY_UNKNOWN;
if (XLookupString(&x_key_event, &buffer, 1, &keysym, nullptr) > 0)
{
if (buffer == '\r')
{
key = '\n';
}
else
{
key = buffer;
}
}
else
{
switch (keysym)
{
case XK_F1: key = JES_KEY_F1; break;
case XK_F2: key = JES_KEY_F2; break;
case XK_F3: key = JES_KEY_F3; break;
case XK_F4: key = JES_KEY_F4; break;
case XK_F5: key = JES_KEY_F5; break;
case XK_F6: key = JES_KEY_F6; break;
case XK_F7: key = JES_KEY_F7; break;
case XK_F8: key = JES_KEY_F8; break;
case XK_F9: key = JES_KEY_F9; break;
case XK_F10: key = JES_KEY_F10; break;
case XK_F11: key = JES_KEY_F11; break;
case XK_F12: key = JES_KEY_F12; break;
case XK_F13: key = JES_KEY_F13; break;
case XK_F14: key = JES_KEY_F14; break;
case XK_F15: key = JES_KEY_F15; break;
case XK_F16: key = JES_KEY_F16; break;
case XK_F17: key = JES_KEY_F17; break;
case XK_F18: key = JES_KEY_F18; break;
case XK_F19: key = JES_KEY_F19; break;
case XK_F20: key = JES_KEY_F20; break;
case XK_F21: key = JES_KEY_F21; break;
case XK_F22: key = JES_KEY_F22; break;
case XK_F23: key = JES_KEY_F23; break;
case XK_F24: key = JES_KEY_F24; break;
case XK_F25: key = JES_KEY_F25; break;
case XK_F26: key = JES_KEY_F26; break;
case XK_F27: key = JES_KEY_F27; break;
case XK_F28: key = JES_KEY_F28; break;
case XK_F29: key = JES_KEY_F29; break;
case XK_F30: key = JES_KEY_F30; break;
case XK_F31: key = JES_KEY_F31; break;
case XK_Shift_L: key = JES_KEY_SHIFT_L; break;
case XK_Shift_R: key = JES_KEY_SHIFT_R; break;
case XK_Control_L: key = JES_KEY_CTRL_L; break;
case XK_Control_R: key = JES_KEY_CTRL_R; break;
case XK_Caps_Lock: key = JES_KEY_CAPS_LOCK; break;
case XK_Shift_Lock: key = JES_KEY_SHIFT_LOCK;break;
case XK_Meta_L: key = JES_KEY_META_L; break;
case XK_Meta_R: key = JES_KEY_META_R; break;
case XK_Alt_L: key = JES_KEY_ALT_L; break;
case XK_Alt_R: key = JES_KEY_ALT_R; break;
case XK_Super_L: key = JES_KEY_SUPER_L; break;
case XK_Super_R: key = JES_KEY_SUPER_R; break;
case XK_Home: key = JES_KEY_HOME; break;
case XK_Left: key = JES_KEY_LEFT; break;
case XK_Up: key = JES_KEY_UP; break;
case XK_Right: key = JES_KEY_RIGHT; break;
case XK_Down: key = JES_KEY_DOWN; break;
case XK_Page_Up: key = JES_KEY_PAGE_UP; break;
case XK_Page_Down: key = JES_KEY_PAGE_DOWN; break;
case XK_End: key = JES_KEY_END; break;
case XK_Begin: key = JES_KEY_BEGIN; break;
case XK_Select: key = JES_KEY_SELECT; break;
case XK_Print: key = JES_KEY_PRINT; break;
case XK_Execute: key = JES_KEY_EXECUTE; break;
case XK_Insert: key = JES_KEY_INSERT; break;
case XK_Undo: key = JES_KEY_UNDO; break;
case XK_Redo: key = JES_KEY_REDO; break;
case XK_Menu: key = JES_KEY_MENU; break;
case XK_Find: key = JES_KEY_FIND; break;
case XK_Cancel: key = JES_KEY_CANCEL; break;
case XK_Help: key = JES_KEY_HELP; break;
case XK_Break: key = JES_KEY_BREAK; break;
case XK_Num_Lock: key = JES_KEY_NUM_LOCK; break;
case XK_KP_Space: key = JES_KEY_KP_SPACE; break;
case XK_KP_Tab: key = JES_KEY_KP_TAB; break;
case XK_KP_Enter: key = JES_KEY_KP_ENTER; break;
case XK_KP_F1: key = JES_KEY_KP_F1; break;
case XK_KP_F2: key = JES_KEY_KP_F2; break;
case XK_KP_F3: key = JES_KEY_KP_F3; break;
case XK_KP_F4: key = JES_KEY_KP_F4; break;
case XK_KP_Home: key = JES_KEY_KP_HOME; break;
case XK_KP_Left: key = JES_KEY_KP_LEFT; break;
case XK_KP_Up: key = JES_KEY_KP_UP; break;
case XK_KP_Right: key = JES_KEY_KP_RIGHT; break;
case XK_KP_Down: key = JES_KEY_KP_DOWN; break;
case XK_KP_Page_Up: key = JES_KEY_KP_PAGE_UP; break;
case XK_KP_Page_Down: key = JES_KEY_KP_PAGE_DOWN; break;
case XK_KP_End: key = JES_KEY_KP_END; break;
case XK_KP_Begin: key = JES_KEY_KP_BEGIN; break;
case XK_KP_Insert: key = JES_KEY_KP_INSERT; break;
case XK_KP_Delete: key = JES_KEY_KP_DELETE; break;
case XK_KP_Equal: key = JES_KEY_KP_EQUAL; break;
case XK_KP_Multiply: key = JES_KEY_KP_MULTIPLY; break;
case XK_KP_Add: key = JES_KEY_KP_ADD; break;
case XK_KP_Separator: key = JES_KEY_KP_SEPARATOR; break;
case XK_KP_Subtract: key = JES_KEY_KP_SUBTRACT; break;
case XK_KP_Decimal: key = JES_KEY_KP_DECIMAL; break;
case XK_KP_Divide: key = JES_KEY_KP_DIVIDE; break;
case XK_KP_0: key = JES_KEY_KP_0; break;
case XK_KP_1: key = JES_KEY_KP_1; break;
case XK_KP_2: key = JES_KEY_KP_2; break;
case XK_KP_3: key = JES_KEY_KP_3; break;
case XK_KP_4: key = JES_KEY_KP_4; break;
case XK_KP_5: key = JES_KEY_KP_5; break;
case XK_KP_6: key = JES_KEY_KP_6; break;
case XK_KP_7: key = JES_KEY_KP_7; break;
case XK_KP_8: key = JES_KEY_KP_8; break;
case XK_KP_9: key = JES_KEY_KP_9; break;
}
}
/* OR in the modifier states */
key |= XStateToJtkKeyMods(x_state);
return key;
}
#if 0
static Bool KeyRepeatCheckIfEvent(Display * display, XEvent * chkev,
XPointer arg)
{
XEvent * release_event = (XEvent *)arg;
if (chkev->type == KeyPress &&
chkev->xkey.keycode == release_event->xkey.keycode &&
chkev->xkey.time - release_event->xkey.time < 2)
return True;
return False;
}
/**
* Check to see if this is a repeated key.
*/
static bool IsRepeatKey(Display * display, XEvent * event)
{
XEvent dummyev;
if (XPending(display))
{
if (XCheckIfEvent(display, &dummyev, KeyRepeatCheckIfEvent,
(XPointer)event) == True)
{
return true;
}
}
return false;
}
#endif
static Bool MatchKeyPress(Display * display, XEvent * event, XPointer arg)
{
XEvent * match_event = (XEvent *)arg;
return (event->type == match_event->type) &&
(event->xkey.window == match_event->xkey.window) &&
(event->xkey.state == match_event->xkey.state) &&
(event->xkey.keycode == match_event->xkey.keycode);
}
/**
* Process an X key press event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessXKeyPressEvent(XEvent * x_event, Jtk_Event * event)
{
unsigned int x_keycode = x_event->xkey.keycode;
event->type = JTK_EVENT_KEY_PRESS;
event->key.repeat = false;
event->key.key = XKeyToJtkKey(x_keycode, x_event->xkey.state);
event->key.x_keycode = x_keycode;
/* Remove any following keypress events for the same keycode from the X
* queue. */
XEvent remove_event;
while (XCheckIfEvent(g_display, &remove_event, MatchKeyPress, (XPointer)x_event) == True)
{
}
return true;
}
/**
* Process an X key release event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessXKeyReleaseEvent(XEvent * x_event, Jtk_Event * event)
{
#if 0
if (IsRepeatKey(g_display, x_event))
{
return false;
}
StopKeyRepeat(x_event->xkey.keycode);
#endif
return false;
}
static Bool MatchButtonPress(Display * display, XEvent * event, XPointer arg)
{
XEvent * match_event = (XEvent *)arg;
return (event->type == match_event->type) &&
(event->xbutton.window == match_event->xbutton.window) &&
(event->xbutton.state == match_event->xbutton.state) &&
(event->xbutton.button == match_event->xbutton.button);
}
/**
* Process an X button press event.
*/
static bool ProcessXButtonPressEvent(XEvent * x_event, Jtk_Event * event)
{
event->type = JTK_EVENT_BUTTON_PRESS;
event->button.mods = XStateToJtkKeyMods(x_event->xbutton.state);
event->button.button = x_event->xbutton.button;
/* If this is a mouse wheel scroll event, remove any following scroll
* events. */
if ((event->button.button == 4) || (event->button.button == 5))
{
XEvent remove_event;
while (XCheckIfEvent(g_display, &remove_event, MatchButtonPress, (XPointer)x_event) == True)
{
}
}
return true;
}
/**
* Process an X configure event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessConfigureEvent(XEvent * x_event, Jtk_Event * event)
{
event->type = JTK_EVENT_WINDOW_RESIZE;
event->resize.width = x_event->xconfigure.width;
event->resize.height = x_event->xconfigure.height;
return true;
}
/**
* Process an X ClientMessage event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*/
static bool ProcessXClientMessageEvent(XEvent * x_event, Jtk_Event * event)
{
Atom wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", False);
if (x_event->xclient.data.l[0] == (long)wm_delete_window_atom)
{
event->type = JTK_EVENT_WINDOW_CLOSE;
return true;
}
return false;
}
/**
* Process an X event.
*
* @param x_event
* Pointer to the X event.
* @param event
* Pointer to the Jtk event.
*
* @retval true
* The event should be passed to the user and event has been filled in.
* @retval false
* The event should not be passed to the user.
*/
static bool ProcessXEvent(XEvent * x_event, Jtk_Event * event)
{
switch (x_event->type)
{
case KeyPress:
return ProcessXKeyPressEvent(x_event, event);
case KeyRelease:
return ProcessXKeyReleaseEvent(x_event, event);
case ButtonPress:
return ProcessXButtonPressEvent(x_event, event);
case ButtonRelease:
break;
case Expose:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true;
case GraphicsExpose:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true;
case MapNotify:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true;
case ConfigureNotify:
return ProcessConfigureEvent(x_event, event);
case ClientMessage:
return ProcessXClientMessageEvent(x_event, event);
case MappingNotify:
XRefreshKeyboardMapping(&x_event->xmapping);
return false;
}
return false;
}
bool Jtk_CheckEvent(Jtk_Event * event)
{
/* First check for an X event. */
while (XPending(g_display) > 0)
{
XEvent x_event;
XNextEvent(g_display, &x_event);
if (ProcessXEvent(&x_event, event))
return true;
}
/* Next check if any timer has expired. */
size_t timer_id = Jtk_GetExpiredTimer();
if (timer_id != (size_t)-1)
{
#if 0
auto it = g_key_repeat_timers.find(timer_id);
if (it != g_key_repeat_timers.end())
{
event->type = JTK_EVENT_KEY_PRESS;
event->key.repeat = true;
event->key.key = XKeyToJtkKey(it->second);
event->key.x_keycode = it->second;
}
else
{
#endif
event->type = JTK_EVENT_TIMER;
event->timer.timer_id = timer_id;
event->timer.user1 = Jtk_GetTimerUserData(timer_id, 0u);
event->timer.user2 = Jtk_GetTimerUserData(timer_id, 1u);
#if 0
}
#endif
Jtk_ServiceTimer(timer_id);
return true;
}
return false;
}
void Jtk_WaitEvent(Jtk_Event * event)
{
for (;;)
{
if (Jtk_CheckEvent(event))
return;
/* Wait for something to happen. */
uint64_t time_to_wait = Jtk_TimeToNextTimerExpiration();
if (time_to_wait > MAX_WAIT_TIME)
{
time_to_wait = MAX_WAIT_TIME;
}
int x_fd = ConnectionNumber(g_display);
fd_set fds;
FD_ZERO(&fds);
FD_SET(x_fd, &fds);
struct timeval tv;
tv.tv_sec = time_to_wait / 1000000u;
tv.tv_usec = time_to_wait % 1000000u;
select(x_fd + 1, &fds, nullptr, nullptr, &tv);
}
}
#if 0
void Jtk_BeginKeyRepeat(Jtk_KeyEvent * key_event, uint32_t delay, uint32_t interval)
{
StopKeyRepeat(key_event->x_keycode);
size_t timer_id = Jtk_AddTimer(delay, interval, nullptr, nullptr);
g_repeating_keys[key_event->x_keycode] = timer_id;
g_key_repeat_timers[timer_id] = key_event->x_keycode;
}
#endif
#endif

62
src/gui/jtk/Jtk_event.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef JTK_EVENT_H
#define JTK_EVENT_H
#include <stdint.h>
#include <stdlib.h>
#define JTK_EVENT_WINDOW_CLOSE 1u
#define JTK_EVENT_WINDOW_EXPOSE 2u
#define JTK_EVENT_KEY_PRESS 3u
#define JTK_EVENT_KEY_RELEASE 4u
#define JTK_EVENT_BUTTON_PRESS 5u
#define JTK_EVENT_BUTTON_RELEASE 6u
#define JTK_EVENT_TIMER 7u
#define JTK_EVENT_WINDOW_RESIZE 8u
typedef struct
{
bool repeat;
uint32_t key;
#ifdef JTK_X
unsigned int x_keycode;
#endif
} Jtk_KeyEvent;
typedef struct
{
uint32_t mods;
uint8_t button;
} Jtk_ButtonEvent;
typedef struct
{
size_t timer_id;
void * user1;
void * user2;
} Jtk_TimerEvent;
typedef struct
{
size_t width;
size_t height;
} Jtk_WindowResizeEvent;
typedef struct
{
uint8_t type;
union
{
Jtk_KeyEvent key;
Jtk_ButtonEvent button;
Jtk_TimerEvent timer;
Jtk_WindowResizeEvent resize;
};
} Jtk_Event;
bool Jtk_CheckEvent(Jtk_Event * event);
void Jtk_WaitEvent(Jtk_Event * event);
#if 0
void Jtk_BeginKeyRepeat(Jtk_KeyEvent * key_event, uint32_t delay, uint32_t interval);
#endif
#endif

View File

@ -0,0 +1,9 @@
#ifndef JTK_INTERNAL_H
#define JTK_INTERNAL_H
extern Display * g_display;
extern XVisualInfo * g_vi;
extern XSetWindowAttributes g_swa;
extern GLXContext g_context;
#endif

9
src/gui/jtk/Jtk_time.cc Normal file
View File

@ -0,0 +1,9 @@
#include "Jtk.h"
#include <sys/time.h>
uint64_t Jtk_UsTime()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
return (uint64_t)tv.tv_sec * 1000000u + (uint64_t)tv.tv_usec;
}

9
src/gui/jtk/Jtk_time.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef JTK_TIME_H
#define JTK_TIME_H
#include "Jtk_timer.h"
bool Jtk_Init();
uint64_t Jtk_UsTime();
#endif

157
src/gui/jtk/Jtk_timer.cc Normal file
View File

@ -0,0 +1,157 @@
#include "Jtk.h"
#include <vector>
#include <memory>
#include <list>
typedef struct
{
uint64_t next; /**< Time the timer next expires (us). */
uint64_t interval; /**< Timer interval (us). */
size_t id; /**< Timer ID. */
void * user[2]; /**< User data pointers. */
} Timer;
/** Vector used to allocate timer IDs. */
static std::vector<std::shared_ptr<Timer>> g_timers;
/** Linked list used to traverse all active timers. */
static std::list<std::shared_ptr<Timer>> g_active_timers;
static size_t AllocateTimerID()
{
for (size_t i = 0; i < g_timers.size(); i++)
{
if (!g_timers[i])
{
return i;
}
}
g_timers.push_back(nullptr);
return g_timers.size() - 1u;
}
/**
* Add a timer.
*
* @param delay
* Delay time in milliseconds.
* @param interval
* Interval time in milliseconds. A value of 0 indicates that the timer
* is not periodic.
* @param user1
* User data pointer 1. This value is not used by Jtk but can be retrieved by
* the user when a timer expires.
* @param user2
* User data pointer 2. This value is not used by Jtk but can be retrieved by
* the user when a timer expires.
*
* @return
* Timer ID.
*/
size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2)
{
uint64_t current_system_time = Jtk_UsTime();
size_t timer_id = AllocateTimerID();
auto timer = std::make_shared<Timer>();
timer->next = current_system_time + (delay * 1000u);
timer->interval = interval * 1000u;
timer->id = timer_id;
timer->user[0] = user1;
timer->user[1] = user2;
g_timers[timer_id] = timer;
g_active_timers.push_back(timer);
return timer_id;
}
/**
* Remove a timer.
*
* @param timer_id
* The ID of the timer to remove.
*/
void Jtk_RemoveTimer(size_t timer_id)
{
if (timer_id < g_timers.size())
{
auto timer = g_timers[timer_id];
g_active_timers.remove(timer);
g_timers[timer_id] = nullptr;
}
}
/**
* Determine the amount of time until the next timer expires (in us).
*
* @return
* Time (in us) until the next timer expires. This will be 0 if an active
* timer has already expired, and will be (uint64_t)-1 if there are no
* active timers.
*/
uint64_t Jtk_TimeToNextTimerExpiration()
{
uint64_t time = (uint64_t)-1;
uint64_t current_system_time = Jtk_UsTime();
for (auto & timer : g_active_timers)
{
if (timer->next <= current_system_time)
{
return 0;
}
uint64_t time_until_this_timer = timer->next - current_system_time;
if (time_until_this_timer < time)
{
time = time_until_this_timer;
}
}
return time;
}
/**
* Service a timer.
*
* This will increment the timer's next activation time by its interval, or
* for a timer with an interval of 0, will remove the timer.
*
* @param timer_id
* The ID of the timer to service.
*/
void Jtk_ServiceTimer(size_t timer_id)
{
auto timer = g_timers[timer_id];
if (timer->interval == 0u)
{
Jtk_RemoveTimer(timer_id);
}
else
{
timer->next += timer->interval;
}
}
/**
* Return the ID of an expired timer.
*
* @return
* The ID of an expired timer, or (size_t)-1 if no timer is expired.
*/
size_t Jtk_GetExpiredTimer()
{
uint64_t current_system_time = Jtk_UsTime();
for (auto & timer : g_active_timers)
{
if (timer->next <= current_system_time)
{
return timer->id;
}
}
return (size_t)-1;
}
void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index)
{
if (timer_id < g_timers.size())
{
return g_timers[timer_id]->user[index];
}
return nullptr;
}

14
src/gui/jtk/Jtk_timer.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef JTK_TIMER_H
#define JTK_TIMER_H
#include <stdint.h>
#include <stdlib.h>
size_t Jtk_AddTimer(uint32_t delay, uint32_t interval, void * user1, void * user2);
void Jtk_RemoveTimer(size_t timer_id);
uint64_t Jtk_TimeToNextTimerExpiration();
void Jtk_ServiceTimer(size_t timer_id);
size_t Jtk_GetExpiredTimer();
void * Jtk_GetTimerUserData(size_t timer_id, uint8_t index);
#endif

95
src/gui/jtk/Jtk_window.cc Normal file
View File

@ -0,0 +1,95 @@
#include "Jtk.h"
#ifdef JTK_X
#include <GL/glx.h>
#include "Jtk_internal.h"
#include <stdio.h>
#include <X11/Xatom.h>
#include <cstring>
static Bool WaitForNotify(Display * display, XEvent * event, XPointer arg)
{
return (event->type == MapNotify) && (event->xmap.window == (Window)arg);
}
void * Jtk_CreateWindow()
{
XEvent event;
Window window = XCreateWindow(g_display,
RootWindow(g_display, g_vi->screen),
0, 0, 800, 800, 0, g_vi->depth, InputOutput, g_vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &g_swa);
XMapWindow(g_display, window);
XIfEvent(g_display, &event, WaitForNotify, (XPointer)window);
if (glXMakeCurrent(g_display, window, g_context) == False)
{
fprintf(stderr, "glXMakeCurrent() failure\n");
XDestroyWindow(g_display, window);
return nullptr;
}
/* Disable the window close button. */
Atom wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(g_display, window, &wm_delete_window_atom, 1);
return (void *)window;
}
void Jtk_SwapBuffers(void * window)
{
glXSwapBuffers(g_display, (Window)window);
}
void Jtk_CloseWindow(void * window)
{
XDestroyWindow(g_display, (Window)window);
}
void Jtk_SetWindowTitle(void * window, const char * title)
{
XTextProperty title_property;
if (XStringListToTextProperty((char **)&title, 1, &title_property) != 0)
{
XSetTextProperty(g_display, (Window)window, &title_property, XA_WM_NAME);
XFree(title_property.value);
}
}
/**
* Set the window icon.
*
* @param window
* The window to operate on.
* @param data
* The format of data must be 32 bits per pixel in BGRA format (e.g. data[0]
* is blue value, data[3] is alpha value of first pixel).
* @param width
* Icon width.
* @param height
* Icon height.
*/
void Jtk_SetWindowIcon(void * window, const uint8_t * data,
size_t width, size_t height)
{
Atom net_wm_icon_atom = XInternAtom(g_display, "_NET_WM_ICON", False);
size_t property_size = (2u + width * height) * sizeof(long);
unsigned long * property_data = (unsigned long *)malloc(property_size);
property_data[0] = width;
property_data[1] = height;
unsigned long * dest = &property_data[2];
const uint32_t * src = (const uint32_t *)data;
for (size_t row = 0u; row < height; row++)
{
for (size_t col = 0u; col < width; col++)
{
*dest++ = *src++;
}
}
XChangeProperty(g_display, (Window)window, net_wm_icon_atom, XA_CARDINAL,
32, PropModeReplace, (uint8_t *)property_data, property_size);
XFlush(g_display);
free(property_data);
}
#endif

11
src/gui/jtk/Jtk_window.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef JTK_WINDOW_H
#define JTK_WINDOW_H
void * Jtk_CreateWindow();
void Jtk_SwapBuffers(void * window);
void Jtk_CloseWindow(void * window);
void Jtk_SetWindowTitle(void * window, const char * title);
void Jtk_SetWindowIcon(void * window, const uint8_t * data,
size_t width, size_t height);
#endif

View File

@ -1,178 +0,0 @@
module jes.core.databuffer;
import core.stdc.string;
import core.stdc.stdlib;
class DataBuffer
{
/** Number of bytes to initially allocate for an empty data buffer. */
enum size_t INITIAL_CAPACITY = 8u;
/** Number of extra bytes to allocate when growing. */
enum size_t GROWTH_CAPACITY = 2000u;
/** Size of data. */
private size_t m_size;
/** Underlying capacity in memory. */
private size_t m_capacity;
/** Data. */
private ubyte * m_data;
/**
* Construct a DataBuffer object that is initially empty.
*
* @param capacity The number of bytes to initially allocate.
*/
this(size_t capacity = INITIAL_CAPACITY)
{
m_data = cast(ubyte *)malloc(capacity);
}
/**
* Destructor for a DataBuffer object.
*/
~this()
{
free(m_data);
}
/**
* Get the address of a byte in the data buffer.
*
* @param offset Byte offset into the data buffer.
*/
ubyte * address(size_t offset)
{
return &m_data[offset];
}
/**
* Get the address of a byte in the data buffer.
*
* @param offset Byte offset into the data buffer.
*/
const(ubyte) * address(size_t offset) const
{
return &m_data[offset];
}
/**
* Erase data from the data buffer.
*
* @param position The index of the data to remove.
* @param n The number of bytes to remove.
*/
void erase(size_t position, size_t n)
{
if ((position < m_size) && (position + n <= m_size))
{
memmove(&m_data[position], &m_data[position + n], m_size - (position + n));
m_size -= n;
}
}
/**
* Insert data into the data buffer.
*
* @param position The index at which to insert the data.
* @param data The data to insert.
* @param n The number of bytes to insert.
*/
void insert(size_t position, const ubyte * data, size_t n)
{
if (position <= m_size)
{
ensure_free(n);
memmove(&m_data[position + n], &m_data[position], m_size - position);
memcpy(&m_data[position], data, n);
m_size += n;
}
}
/**
* Get the size of the data in the data buffer.
*/
@property size_t size() const
{
return m_size;
}
/**
* Ensure that there are at least n free.
*
* @param n The number of bytes that must be free.
*/
private void ensure_free(size_t n)
{
if ((m_capacity - m_size) < n)
{
/* Grow the data buffer. */
m_capacity = m_size + n + GROWTH_CAPACITY;
ubyte * new_data = cast(ubyte *)malloc(m_capacity);
memcpy(new_data, m_data, m_size);
free(m_data);
m_data = new_data;
}
}
version(unittest) invariant
{
assert(m_data !is null);
assert(m_size <= m_capacity);
}
unittest
{
DataBuffer tb = new DataBuffer();
assert(tb.size == 0u);
ubyte[20] dat = 5u;
tb.insert(0u, dat.ptr, dat.length);
ubyte * first_address = tb.address(5u);
assert(tb.size() == 20u);
for (size_t i = 0u; i < 20u; i++)
{
assert(*tb.address(i) == 5u);
}
dat[] = 10u;
tb.insert(5u, dat.ptr, dat.length);
assert(tb.size() == 40u);
for (size_t i = 0u; i < 40u; i++)
{
if (i < 5u)
{
assert(*tb.address(i) == 5u);
}
else if (i < 25u)
{
assert(*tb.address(i) == 10u);
}
else
{
assert(*tb.address(i) == 5u);
}
}
tb.erase(15u, 15u);
assert(tb.size() == 25u);
for (size_t i = 0u; i < 25u; i++)
{
if (i < 5u)
{
assert(*tb.address(i) == 5u);
}
else if (i < 15u)
{
assert(*tb.address(i) == 10u);
}
else
{
assert(*tb.address(i) == 5u);
}
}
assert((tb.address(24u) - tb.address(0u)) == 24u);
tb.insert(30u, dat.ptr, dat.length);
assert(tb.size == 25u);
assert(first_address == tb.address(5u));
}
}

View File

@ -1,346 +0,0 @@
module jes.core.encoding;
struct Encoding
{
enum : ubyte
{
UTF8,
CP1252,
UTF16_LE,
UTF16_BE,
}
ubyte type;
alias type this;
this(ubyte type)
{
this.type = type;
}
uint decode(const(ubyte) * data, size_t * encoded_size)
{
uint result;
size_t size;
ubyte following_bytes;
ubyte c;
switch (type)
{
case UTF8:
c = *data;
if ((c & 0x80u) == 0u)
{
result = c;
size = 1u;
}
else
{
if ((c & 0xE0u) == 0xC0u)
{
result = c & 0x1Fu;
following_bytes = 1u;
}
else if ((c & 0xF0u) == 0xE0u)
{
result = c & 0x0Fu;
following_bytes = 2u;
}
else if ((c & 0xF8u) == 0xF0u)
{
result = c & 0x07u;
following_bytes = 3u;
}
else if ((c & 0xFCu) == 0xF8u)
{
result = c & 0x03u;
following_bytes = 4u;
}
else if ((c & 0xFEu) == 0xFCu)
{
result = c & 0x01u;
following_bytes = 5u;
}
size = following_bytes + 1u;
while (following_bytes-- > 0u)
{
data++;
result <<= 6u;
result |= *data & 0x3Fu;
}
}
break;
case CP1252:
/* TODO */
break;
case UTF16_LE:
result = data[0] | (data[1] << 8u);
size = 2u;
break;
case UTF16_BE:
result = (data[0] << 8u) | data[1];
size = 2u;
break;
default:
break;
}
if (encoded_size != null)
{
*encoded_size = size;
}
return result;
}
ubyte num_bytes_to_encode_code_point(uint code_point)
{
switch (type)
{
case UTF8:
if (code_point <= 0x7Fu)
{
return 1u;
}
else if (code_point <= 0x7FFu)
{
return 2u;
}
else if (code_point <= 0xFFFFu)
{
return 3u;
}
else if (code_point <= 0x1FFFFFu)
{
return 4u;
}
else if (code_point <= 0x3FFFFFFu)
{
return 5u;
}
else
{
return 6u;
}
case CP1252:
/* TODO */
break;
case UTF16_LE:
case UTF16_BE:
return 2u;
default:
break;
}
return 0u;
}
ubyte encode(uint code_point, ubyte * buffer)
{
ubyte size;
switch (type)
{
case UTF8:
size = num_bytes_to_encode_code_point(code_point);
if (size == 1u)
{
*buffer = cast(ubyte)code_point;
}
else if (size > 1u)
{
*buffer = cast(ubyte)((0xFFu << (8u - size)) | (code_point >> (6u * (size - 1u))));
const ubyte end = cast(ubyte)(size - 1u);
for (ubyte i = 0u; i < end; i++)
{
buffer[end - i] = 0x80u | (code_point >> (6u * i) & 0x3Fu);
}
}
return size;
case CP1252:
/* TODO */
break;
case UTF16_LE:
buffer[0] = cast(ubyte)code_point;
buffer[1] = cast(ubyte)(code_point >> 8u);
return 2u;
case UTF16_BE:
buffer[0] = cast(ubyte)(code_point >> 8u);
buffer[1] = cast(ubyte)code_point;
return 2u;
default:
break;
}
return 0u;
}
static Encoding detect_encoding(const ubyte * data, size_t n, size_t * bom_size)
{
*bom_size = 0u;
/* First check for BOM presence. */
if ((n >= 3) &&
(data[0..3] == [0xEFu, 0xBBu, 0xBFu]) &&
validate_utf8(&data[3], n - 3u))
{
*bom_size = 3u;
return Encoding(UTF8);
}
if ((n >= 2) &&
(data[0..2] == [0xFEu, 0xFFu]) &&
((n & 1u) == 0u))
{
*bom_size = 2u;
return Encoding(UTF16_BE);
}
if ((n >= 2) &&
(data[0..2] == [0xFFu, 0xFEu]) &&
((n & 1u) == 0u))
{
*bom_size = 2u;
return Encoding(UTF16_LE);
}
/* No BOM found. Check heuristically. */
if (check_utf16(data, n, true))
{
return Encoding(UTF16_LE);
}
if (check_utf16(data, n, false))
{
return Encoding(UTF16_BE);
}
if (validate_utf8(data, n))
{
return Encoding(UTF8);
}
return Encoding(CP1252);
}
private static bool check_utf8_continuation_bytes(const ubyte * data, size_t n)
{
for (size_t i = 0u; i < n; i++)
{
if ((data[i] & 0xC0u) != 0x80u)
return false;
}
return true;
}
private static bool validate_utf8(const ubyte * data, size_t n)
{
for (size_t i = 0u; i < n; i++)
{
const ubyte c = data[i];
size_t n_continuation_bytes;
if ((c & 0x80u) != 0u)
{
if ((c & 0xE0u) == 0xC0u)
{
n_continuation_bytes = 1u;
}
else if ((c & 0xF0u) == 0xE0u)
{
n_continuation_bytes = 2u;
}
else if ((c & 0xF8u) == 0xF0u)
{
n_continuation_bytes = 3u;
}
else if ((c & 0xFCu) == 0xF8u)
{
n_continuation_bytes = 4u;
}
else if ((c & 0xFEu) == 0xFCu)
{
n_continuation_bytes = 5u;
}
else
{
return false;
}
if (((i + n_continuation_bytes) < n) &&
check_utf8_continuation_bytes(&data[i + 1], n_continuation_bytes))
{
i += n_continuation_bytes;
}
else
{
return false;
}
}
}
return true;
}
private static bool check_utf16(const ubyte * data, size_t n, bool le)
{
size_t n_high_zeros;
if ((n == 0u) || ((n & 1u) != 0u))
{
return false;
}
ubyte off = le ? 1u : 0u;
for (size_t i = 0u; i < n; i += 2u)
{
if (data[i + off] == 0u)
{
n_high_zeros++;
}
}
/* 20% threshold of high zeroes required. */
return (40u * n_high_zeros / n) != 0u;
}
unittest
{
import std.stdio;
import std.file;
const(ubyte)[] dat;
Encoding e;
size_t bom_size = 54321;
e = Encoding.detect_encoding(null, 0, &bom_size);
assert(e == Encoding.UTF8);
assert(bom_size == 0u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/utf-8.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.UTF8);
assert(bom_size == 0u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/utf-8-bom.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.UTF8);
assert(bom_size == 3u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/utf-16le.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.UTF16_LE);
assert(bom_size == 2u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/utf-16le-nobom.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.UTF16_LE);
assert(bom_size == 0u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/utf-16be.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.UTF16_BE);
assert(bom_size == 2u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/utf-16be-nobom.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.UTF16_BE);
assert(bom_size == 0u);
dat = cast(const(ubyte)[])std.file.read("test/files/encodings/cp-1252.txt");
e = Encoding.detect_encoding(dat.ptr, dat.length, &bom_size);
assert(e == Encoding.CP1252);
assert(bom_size == 0u);
}
};

View File

@ -1,76 +0,0 @@
module jes.core.lineendings;
struct LineEndings
{
enum : ubyte
{
LF,
CRLF,
}
ubyte type;
alias type this;
this(ubyte type)
{
this.type = type;
}
@property string text() const
{
if (type == LF)
{
return "\n";
}
else
{
return "\r\n";
}
}
static LineEndings detect_line_endings(const ubyte * data, size_t n)
{
size_t lf_count = 0u;
for (size_t i = 0u; i < n; i++)
{
if (data[i] == '\n')
{
lf_count++;
/* Every LF must be preceded by a CR for the content to have
* CRLF line endings. */
if ((i == 0u) || (data[i - 1u] != '\r'))
{
return LineEndings(LF);
}
}
}
if (lf_count > 0u)
{
return LineEndings(CRLF);
}
return LineEndings(LF);
}
unittest
{
import std.stdio;
import std.file;
const(ubyte)[] dat;
LineEndings le;
dat = cast(const(ubyte)[])std.file.read("test/files/line_endings/crlf_format.txt");
le = LineEndings.detect_line_endings(dat.ptr, dat.length);
assert(le == LineEndings.CRLF);
assert(le.text == "\r\n");
dat = cast(const(ubyte)[])std.file.read("test/files/empty.txt");
le = LineEndings.detect_line_endings(dat.ptr, 0u);
assert(le == LineEndings.LF);
assert(le.text == "\n");
dat = cast(const(ubyte)[])std.file.read("test/files/line_endings/lf_format.txt");
le = LineEndings.detect_line_endings(dat.ptr, dat.length);
assert(le == LineEndings.LF);
assert(le.text == "\n");
}
}

View File

@ -1,331 +0,0 @@
module jes.core.undobuffer;
import jes.core.databuffer;
class UndoBuffer
{
/**
* An UndoUnit represents a single contiguous chunk of inserted or deleted
* data.
*/
class UndoUnit
{
/** Index where operation took place in target buffer. */
size_t target_index;
/** Index of data stored in undo buffer. */
size_t undo_buffer_index;
/** Length of the unit. */
size_t length;
/** Whether the unit represents an insertion or deletion. */
bool insert;
this(size_t target_index, size_t undo_buffer_index, size_t length, bool insert)
{
this.target_index = target_index;
this.undo_buffer_index = undo_buffer_index;
this.length = length;
this.insert = insert;
}
}
/**
* An UndoOperation is a collection of one or more UndoUnits.
*
* All units in an operation are applied together when undoing/redoing the
* full operation.
*/
class UndoOperation
{
/** ID of parent operation. */
size_t parent;
/** Units in this operation. */
UndoUnit[] units;
/** ID(s) of child operation(s). */
size_t[] children;
this(size_t parent, UndoUnit unit)
{
this.parent = parent;
this.units ~= unit;
}
}
/** List of all undo operations in the buffer. */
private UndoOperation[] m_operations;
/** Buffer storing the inserted/deleted data. */
private DataBuffer m_data_buffer;
/** Operation level, nonzero means wait to commit the operation. */
private size_t m_operation_level;
/** Reference to the operation currently being built. */
private UndoOperation m_current_operation;
/** ID of the operation representing the current buffer state. */
private size_t m_current_id;
this()
{
m_data_buffer = new DataBuffer();
m_operations ~= null;
}
/**
* Increase the operation level.
*
* The operation will not be committed until the level returns to 0.
*/
void push_operation()
{
m_operation_level++;
}
/**
* Check if the operation should be committed and commit it if so.
*/
private void check_commit()
{
if (m_operation_level == 0u)
{
m_current_operation = null;
}
}
/**
* Decrease operation level.
*
* All undo units will be collected in one operation until the operation
* level returns to 0.
*/
void pop_operation()
{
m_operation_level--;
check_commit();
}
private bool augment_current_unit(const(ubyte) * data, size_t length, size_t target_index, bool insert)
{
/* Nothing to augment if no operation yet in progress. */
if (m_current_operation is null)
{
return false;
}
/* Current undo unit is the last undo unit in the current operation. */
UndoUnit cuu = m_current_operation.units[$ - 1];
size_t cuu_target_end_index = cuu.target_index + cuu.length;
if (cuu.insert)
{
if (insert)
{
/* Case 1: current unit is an insert, new unit is an insert,
* and the inserted data can be combined with the current unit
* data. */
if ((cuu.target_index <= target_index) &&
(target_index <= cuu_target_end_index))
{
m_data_buffer.insert(cuu.undo_buffer_index + target_index - cuu.target_index, data, length);
cuu.length += length;
return true;
}
}
else
{
/* Case 2: current unit is an insert, new unit is a delete, and
* the data to be deleted is part of the inserted data. */
if ((cuu.target_index <= target_index) &&
((target_index + length) <= cuu_target_end_index))
{
m_data_buffer.erase(cuu.undo_buffer_index + target_index - cuu.target_index, length);
cuu.length -= length;
return true;
}
}
}
else
{
/* Case 3: current unit is a delete, new unit is a delete, and the
* new delete range is congruent to the current unit delete range. */
if (!insert)
{
if (cuu.target_index == target_index)
{
m_data_buffer.insert(cuu.undo_buffer_index + cuu.length, data, length);
}
else if ((target_index + length) == cuu.target_index)
{
m_data_buffer.insert(cuu.undo_buffer_index, data, length);
cuu.target_index = target_index;
}
else
{
return false;
}
cuu.length += length;
return true;
}
}
return false;
}
private void record_new_unit(UndoUnit uu)
{
if (m_current_operation is null)
{
UndoOperation uo = new UndoOperation(m_current_id, uu);
size_t new_id = m_operations.length;
m_operations ~= uo;
m_current_operation = uo;
if (m_current_id > 0u)
{
m_operations[m_current_id].children ~= new_id;
}
}
else
{
m_current_operation.units ~= uu;
}
}
/**
* Record a unit of undoable activity.
*
* @param data The data being inserted/deleted.
* @param length Length of the data.
* @param target_index Position in the target buffer where the unit takes place.
* @param insert Whether this unit is an insertion or a deletion.
*/
void record_unit(const(ubyte) * data, size_t length, size_t target_index, bool insert)
{
if (!augment_current_unit(data, length, target_index, insert))
{
size_t undo_buffer_index = m_data_buffer.size;
m_data_buffer.insert(undo_buffer_index, data, length);
UndoUnit uu = new UndoUnit(target_index, undo_buffer_index, length, insert);
record_new_unit(uu);
}
check_commit();
}
version(unittest) invariant
{
assert(m_operations !is null);
assert(m_operations.length > 0u);
}
version(unittest) private @property size_t n_operations() const
{
return m_operations.length - 1u;
}
version(unittest) private @property size_t n_units() const
{
size_t n;
foreach (operation; m_operations)
{
if (operation !is null)
{
n += operation.units.length;
}
}
return n;
}
version(unittest) void record_unit(string data, size_t length, size_t target_index, bool insert)
{
return record_unit(cast(const(ubyte) *)data.ptr, length, target_index, insert);
}
version(unittest) string uu_string(UndoUnit uu) const
{
return (cast(immutable(char) *)m_data_buffer.address(uu.undo_buffer_index))[0 .. uu.length];
}
unittest
{
UndoBuffer ub;
/* Each record_unit creates an operation when level == 0 */
ub = new UndoBuffer();
assert(ub.n_operations == 0u);
assert(ub.n_units == 0u);
ub.record_unit("hi", 2u, 0u, true);
assert(ub.n_operations == 1u);
assert(ub.n_units == 1u);
assert(ub.uu_string(ub.m_operations[1].units[0]) == "hi");
ub.record_unit("there", 5u, 2u, true);
assert(ub.n_operations == 2u);
assert(ub.n_units == 2u);
assert(ub.uu_string(ub.m_operations[2].units[0]) == "there");
/* Multiple record_unit calls are combined into one operation until
* opertaion level is popped. */
ub = new UndoBuffer();
assert(ub.n_operations == 0u);
assert(ub.n_units == 0u);
ub.push_operation();
ub.record_unit("hi", 2u, 0u, true);
assert(ub.n_operations == 1u);
assert(ub.n_units == 1u);
assert(ub.m_operations[1].units[0].target_index == 0u);
ub.record_unit("there", 5u, 2u, true);
assert(ub.n_operations == 1u);
/* Consecutive inserts are combined into one unit. */
assert(ub.n_units == 1u);
assert(ub.uu_string(ub.m_operations[1].units[0]) == "hithere");
assert(ub.m_operations[1].units[0].target_index == 0u);
/* Delete from end of last unit modifies last unit. */
ub.record_unit("e", 1u, 6u, false);
assert(ub.n_units == 1u);
assert(ub.uu_string(ub.m_operations[1].units[0]) == "hither");
assert(ub.m_operations[1].units[0].target_index == 0u);
/* Delete from beginning of last unit modifies last unit. */
ub.record_unit("h", 1u, 0u, false);
assert(ub.n_units == 1u);
assert(ub.uu_string(ub.m_operations[1].units[0]) == "ither");
assert(ub.m_operations[1].units[0].target_index == 0u);
/* Delete from middle of last unit modifies last unit. */
ub.record_unit("h", 1u, 2u, false);
assert(ub.n_units == 1u);
assert(ub.uu_string(ub.m_operations[1].units[0]) == "iter");
assert(ub.m_operations[1].units[0].target_index == 0u);
ub.pop_operation();
/* Congruent deletions are combined. */
ub.push_operation();
ub.record_unit("e", 1u, 2u, false);
assert(ub.n_units == 2u);
assert(ub.uu_string(ub.m_operations[2].units[0]) == "e");
assert(ub.m_operations[2].units[0].target_index == 2u);
ub.record_unit("r", 1u, 2u, false);
assert(ub.n_units == 2u);
assert(ub.uu_string(ub.m_operations[2].units[0]) == "er");
assert(ub.m_operations[2].units[0].target_index == 2u);
ub.record_unit("t", 1u, 1u, false);
assert(ub.n_units == 2u);
assert(ub.uu_string(ub.m_operations[2].units[0]) == "ter");
assert(ub.m_operations[2].units[0].target_index == 1u);
ub.pop_operation();
}
}

View File

@ -1,130 +0,0 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define round_up_26_6(val) (((val) + 63) >> 6u)
static FT_Library Library_Handle;
static bool Initialized;
typedef struct
{
int32_t advance;
int32_t line_height;
int32_t baseline_offset;
FT_Face face;
} Font;
typedef struct
{
uint8_t * bitmap;
int32_t width;
int32_t height;
int32_t left;
int32_t top;
int32_t advance;
} Glyph;
static bool Load_FreeType(void)
{
if (Initialized)
{
return true;
}
if (FT_Init_FreeType(&Library_Handle) != 0)
{
return false;
}
return Initialized = true;
}
Glyph * Font_LoadGlyph(Font * font, uint32_t char_code)
{
FT_Char ft_char_code = char_code;
if (FT_Load_Char(font->face, ft_char_code, FT_LOAD_RENDER) != 0)
return NULL;
Glyph * glyph = (Glyph *)malloc(sizeof(Glyph));
glyph->width = font->face->glyph->bitmap.width;
glyph->height = font->face->glyph->bitmap.rows;
glyph->left = font->face->glyph->bitmap_left;
glyph->top = font->face->glyph->bitmap_top;
glyph->advance = round_up_26_6(font->face->glyph->advance.x);
glyph->bitmap = malloc(glyph->width * glyph->height);
memcpy(glyph->bitmap, font->face->glyph->bitmap.buffer, glyph->width * glyph->height);
return glyph;
}
void Font_FreeGlyph(Glyph * glyph)
{
free(glyph->bitmap);
free(glyph);
}
static void PreloadGlyphs(Font * font)
{
static const char preload_glyph_list[] = "HMgjqxy_|^";
int max_top = -9999;
int min_bottom = 9999;
font->advance = 0;
for (size_t i = 0u; i < sizeof(preload_glyph_list) - 1u; i++)
{
Glyph * glyph = Font_LoadGlyph(font, (uint8_t)preload_glyph_list[i]);
if (glyph != NULL)
{
if (font->face->glyph->bitmap_top > max_top)
{
max_top = font->face->glyph->bitmap_top;
}
int bitmap_bottom = font->face->glyph->bitmap_top - font->face->glyph->bitmap.rows;
if (bitmap_bottom < min_bottom)
{
min_bottom = bitmap_bottom;
}
if (glyph->advance > font->advance)
{
font->advance = glyph->advance;
}
Font_FreeGlyph(glyph);
}
}
font->line_height = round_up_26_6(font->face->size->metrics.height);
font->baseline_offset = (font->line_height - (max_top - min_bottom)) / 2 - min_bottom;
}
Font * Font_Load(const char * fname, int32_t size)
{
FT_Face face;
if (!Load_FreeType())
{
return NULL;
}
if (FT_New_Face(Library_Handle, fname, 0, &face) != 0)
{
return NULL;
}
Font * font = (Font *)malloc(sizeof(Font));
font->face = face;
FT_Set_Pixel_Sizes(face, 0, size);
PreloadGlyphs(font);
return font;
}
void Font_Free(Font * font)
{
free(font);
}

View File

@ -1,143 +0,0 @@
module jes.gui.font;
import std.string;
import derelict.opengl;
import gltk;
import core.stdc.string;
struct CFont
{
int advance;
int line_height;
int baseline_offset;
}
struct CGlyph
{
ubyte * bitmap;
int width;
int height;
int left;
int top;
int advance;
}
private extern(C) CGlyph * Font_LoadGlyph(CFont * font, uint char_code);
private extern(C) void Font_FreeGlyph(CGlyph * glyph);
private extern(C) CFont * Font_Load(const char * fname, int size);
private extern(C) void Font_Free(CFont * font);
class Font
{
private static __gshared Glyph[uint] glyphs;
class Glyph
{
int advance;
gltk.Texture m_texture;
gltk.Buffer m_buffer;
gltk.Array m_array;
this(const(CGlyph) * cglyph)
{
advance = cglyph.advance;
m_texture = new gltk.Texture();
m_texture.bind(GL_TEXTURE_2D);
int rounded_width = gltk.Texture.next_power_of_2(cglyph.width);
int rounded_height = gltk.Texture.next_power_of_2(cglyph.height);
ubyte[] texture = new ubyte[rounded_width * rounded_height];
memset(texture.ptr, 0, rounded_width * rounded_height);
for (int i = 0; i < cglyph.height; i++)
{
memcpy(&texture[rounded_width * i],
&cglyph.bitmap[cglyph.width * (cglyph.height - i - 1)],
cglyph.width);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, rounded_width, rounded_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture.ptr);
m_array = new gltk.Array();
m_array.bind();
int left = cglyph.left;
int top = cglyph.top;
float s_max = cglyph.width / cast(float)rounded_width;
float t_max = cglyph.height / cast(float)rounded_height;
m_buffer = new gltk.Buffer(GL_ARRAY_BUFFER);
GLfloat[] data = [
cast(GLfloat)left, cast(GLfloat)(top - cglyph.height), 0.0, 0.0,
cast(GLfloat)(left + cglyph.width), cast(GLfloat)(top - cglyph.height), s_max, 0.0,
cast(GLfloat)left, cast(GLfloat)top, 0.0, t_max,
cast(GLfloat)(left + cglyph.width), cast(GLfloat)top, s_max, t_max,
];
m_buffer.set_buffer_data(GL_STATIC_DRAW, data);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, null);
}
void render()
{
m_array.bind();
m_texture.bind(GL_TEXTURE_2D);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
CFont * m_font;
this(const char * fname, int size)
{
m_font = Font_Load(fname, size);
if (m_font == null)
{
throw new Exception("Could not load font");
}
}
this(string fname, int size)
{
this(fname.toStringz(), size);
}
~this()
{
Font_Free(m_font);
}
@property int advance()
{
return m_font.advance;
}
@property int line_height()
{
return m_font.line_height;
}
@property int baseline_offset()
{
return m_font.baseline_offset;
}
Glyph get_glyph(uint char_code)
{
if (char_code in glyphs)
{
return glyphs[char_code];
}
Glyph glyph;
CGlyph * cglyph = Font_LoadGlyph(m_font, char_code);
if (cglyph != null)
{
glyph = new Glyph(cglyph);
Font_FreeGlyph(cglyph);
}
glyphs[char_code] = glyph;
return glyph;
}
}

View File

@ -1,100 +0,0 @@
module jes.gui.gl;
static import gltk;
import derelict.opengl;
import jes.gui.font;
class Gl
{
alias FlatProgram = gltk.Program!("viewport_size", "2i", "color", "4f", "position", "2i");
alias TextProgram = gltk.Program!("viewport_size", "2i", "texture", "1i", "color", "4f", "position", "2i");
alias RectProgram = gltk.Program!("viewport_size", "2i", "color", "4f", "position", "2i", "size", "2i");
private FlatProgram m_flat_program;
private TextProgram m_text_program;
private RectProgram m_rect_program;
private gltk.Array m_rect_array;
private gltk.Buffer m_rect_buffer;
private void build_flat_program()
{
m_flat_program = new FlatProgram(
build_shader(GL_VERTEX_SHADER, "share/jes/shaders/flat.v.glsl"),
build_shader(GL_FRAGMENT_SHADER, "share/jes/shaders/flat.f.glsl"),
"coords", 0);
}
private void build_text_program()
{
m_text_program = new TextProgram(
build_shader(GL_VERTEX_SHADER, "share/jes/shaders/text.v.glsl"),
build_shader(GL_FRAGMENT_SHADER, "share/jes/shaders/text.f.glsl"),
"coords", 0);
m_text_program.use();
m_text_program.set_texture(0);
}
private void build_rect_program()
{
m_rect_program = new RectProgram(
build_shader(GL_VERTEX_SHADER, "share/jes/shaders/rect.v.glsl"),
build_shader(GL_FRAGMENT_SHADER, "share/jes/shaders/rect.f.glsl"),
"coords", 0);
m_rect_array = new gltk.Array();
m_rect_array.bind();
m_rect_buffer = new gltk.Buffer(GL_ARRAY_BUFFER);
GLint[] rect_coords = [0, 0, 1, 0, 1, 1, 0, 1];
m_rect_buffer.set_buffer_data(GL_STATIC_DRAW, rect_coords);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, null);
}
this()
{
build_flat_program();
build_text_program();
build_rect_program();
glActiveTexture(GL_TEXTURE0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void resize(int width, int height)
{
glViewport(0, 0, width, height);
m_flat_program.use();
m_flat_program.set_viewport_size(width, height);
m_text_program.use();
m_text_program.set_viewport_size(width, height);
m_rect_program.use();
m_rect_program.set_viewport_size(width, height);
}
void draw_character(Font font, uint char_code, int x, int y, float r, float g, float b, float a)
{
m_text_program.use();
m_text_program.set_color(r, g, b, a);
m_text_program.set_position(x, y);
auto glyph = font.get_glyph(char_code);
glyph.render();
}
void draw_rect(int x, int y, int width, int height,
float r, float g, float b, float a)
{
m_rect_array.bind();
m_rect_program.use();
m_rect_program.set_color(r, g, b, a);
m_rect_program.set_position(x, y);
m_rect_program.set_size(width, height);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
private gltk.Shader build_shader(GLenum shader_type, string filename)
{
auto shader = new gltk.Shader(shader_type);
shader.set_source_from_file(filename);
return shader;
}
}

View File

@ -1,516 +0,0 @@
module jes.gui.icon;
const ubyte[] icon_32x32_bgra = [
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xc8u, 0xc8u, 0xc8u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x2au, 0x2au, 0x2au, 0xffu,
0xb1u, 0xb1u, 0xb1u, 0xffu, 0xf1u, 0xf1u, 0xf1u, 0xffu,
0xf5u, 0xf5u, 0xf5u, 0xffu, 0xb5u, 0xb5u, 0xb5u, 0xffu,
0x22u, 0x22u, 0x22u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x3bu, 0x3bu, 0x3bu, 0xffu,
0xc0u, 0xc0u, 0xc0u, 0xffu, 0xf0u, 0xf0u, 0xf0u, 0xffu,
0xe7u, 0xe7u, 0xe7u, 0xffu, 0xa0u, 0xa0u, 0xa0u, 0xffu,
0x1bu, 0x1bu, 0x1bu, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x26u, 0x26u, 0x26u, 0xffu, 0xf0u, 0xf0u, 0xf0u, 0xffu,
0xaau, 0xaau, 0xaau, 0xffu, 0x1du, 0x1du, 0x1du, 0xffu,
0x18u, 0x18u, 0x18u, 0xffu, 0xa7u, 0xa7u, 0xa7u, 0xffu,
0xdcu, 0xdcu, 0xdcu, 0xffu, 0x05u, 0x05u, 0x05u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x12u, 0x12u, 0x12u, 0xffu, 0xf0u, 0xf0u, 0xf0u, 0xffu,
0x91u, 0x91u, 0x91u, 0xffu, 0x12u, 0x12u, 0x12u, 0xffu,
0x15u, 0x15u, 0x15u, 0xffu, 0x5bu, 0x5bu, 0x5bu, 0xffu,
0x7fu, 0x7fu, 0x7fu, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0xaau, 0xaau, 0xaau, 0xffu, 0xe4u, 0xe4u, 0xe4u, 0xffu,
0x08u, 0x08u, 0x08u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x0fu, 0x0fu, 0x0fu, 0xffu,
0xf6u, 0xf6u, 0xf6u, 0xffu, 0x60u, 0x60u, 0x60u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x40u, 0x40u, 0x40u, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
0x34u, 0x34u, 0x34u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0xefu, 0xefu, 0xefu, 0xffu, 0x9eu, 0x9eu, 0x9eu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0xd0u, 0xd0u, 0xd0u, 0xffu, 0x92u, 0x92u, 0x92u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x1cu, 0x1cu, 0x1cu, 0xffu, 0xfau, 0xfau, 0xfau, 0xffu,
0xbfu, 0xbfu, 0xbfu, 0xffu, 0x4au, 0x4au, 0x4au, 0xffu,
0x0fu, 0x0fu, 0x0fu, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0xadu, 0xadu, 0xadu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x4cu, 0x4cu, 0x4cu, 0xffu,
0xc8u, 0xc8u, 0xc8u, 0xffu, 0xfdu, 0xfdu, 0xfdu, 0xffu,
0xfeu, 0xfeu, 0xfeu, 0xffu, 0xc7u, 0xc7u, 0xc7u, 0xffu,
0x31u, 0x31u, 0x31u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0xf0u, 0xf0u, 0xf0u, 0xffu, 0x89u, 0x89u, 0x89u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x0bu, 0x0bu, 0x0bu, 0xffu,
0x52u, 0x52u, 0x52u, 0xffu, 0xe2u, 0xe2u, 0xe2u, 0xffu,
0xdcu, 0xdcu, 0xdcu, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0xadu, 0xadu, 0xadu, 0xffu, 0xcau, 0xcau, 0xcau, 0xffu,
0x01u, 0x01u, 0x01u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x76u, 0x76u, 0x76u, 0xffu,
0xfau, 0xfau, 0xfau, 0xffu, 0x03u, 0x03u, 0x03u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x2au, 0x2au, 0x2au, 0xffu, 0xf3u, 0xf3u, 0xf3u, 0xffu,
0x9au, 0x9au, 0x9au, 0xffu, 0x22u, 0x22u, 0x22u, 0xffu,
0x0bu, 0x0bu, 0x0bu, 0xffu, 0x35u, 0x35u, 0x35u, 0xffu,
0x98u, 0x98u, 0x98u, 0xffu, 0x54u, 0x54u, 0x54u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x4du, 0x4du, 0x4du, 0xffu, 0x97u, 0x97u, 0x97u, 0xffu,
0x33u, 0x33u, 0x33u, 0xffu, 0x0au, 0x0au, 0x0au, 0xffu,
0x29u, 0x29u, 0x29u, 0xffu, 0xd0u, 0xd0u, 0xd0u, 0xffu,
0xb6u, 0xb6u, 0xb6u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x50u, 0x50u, 0x50u, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x20u, 0x20u, 0x20u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x2bu, 0x2bu, 0x2bu, 0xffu,
0xadu, 0xadu, 0xadu, 0xffu, 0xedu, 0xedu, 0xedu, 0xffu,
0xf5u, 0xf5u, 0xf5u, 0xffu, 0xcau, 0xcau, 0xcau, 0xffu,
0x69u, 0x69u, 0x69u, 0xffu, 0x07u, 0x07u, 0x07u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x06u, 0x06u, 0x06u, 0xffu, 0x68u, 0x68u, 0x68u, 0xffu,
0xccu, 0xccu, 0xccu, 0xffu, 0xf5u, 0xf5u, 0xf5u, 0xffu,
0xe3u, 0xe3u, 0xe3u, 0xffu, 0x98u, 0x98u, 0x98u, 0xffu,
0x13u, 0x13u, 0x13u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x5eu, 0x5eu, 0x5eu, 0xffu,
0xffu, 0xffu, 0xffu, 0xffu, 0x0eu, 0x0eu, 0x0eu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x0eu, 0x0eu, 0x0eu, 0xffu, 0xbcu, 0xbcu, 0xbcu, 0xffu,
0xceu, 0xceu, 0xceu, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x8cu, 0x8cu, 0x8cu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu,
0xf9u, 0xf9u, 0xf9u, 0xffu, 0xc6u, 0xc6u, 0xc6u, 0xffu,
0x2bu, 0x2bu, 0x2bu, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0xffu, 0x33u, 0xffu, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
0x00u, 0x00u, 0x00u, 0xffu, 0x00u, 0x00u, 0x00u, 0xffu,
];

View File

@ -1,54 +0,0 @@
module jes.gui;
static import jtk;
import std.stdio;
import jes.gui.window;
class Gui
{
this()
{
if (!jtk.initialize())
{
throw new Exception("JTK initialization failed.");
}
}
void run()
{
try
{
new Window();
event_loop();
}
finally
{
jtk.quit();
}
}
private void event_loop()
{
bool running = true;
while (running)
{
jtk.Event event = jtk.wait_event();
switch (event.type)
{
case jtk.Event.WINDOW_CLOSE:
Window window = Window[event.window_close.window];
window.close();
running = false;
break;
case jtk.Event.WINDOW_RESIZE:
Window window = Window[event.window_resize.window];
window.resize(event.window_resize.width, event.window_resize.height);
break;
default:
break;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More