Compare commits

..

87 Commits
master ... d

Author SHA1 Message Date
bec2e913c0 Update rscons 2025-04-14 20:12:38 -04:00
1252ed7879 Fix a few new D compilation errors 2022-04-12 09:20:03 -04:00
c9650aada7 Update rscons 2022-04-12 09:19:18 -04:00
6f32d3f2fe Fix github URLs for security changes 2022-04-11 17:31:04 -04:00
51b1b34d03 Remove C+ Change modules 2021-04-03 10:22:51 -04:00
997cf5efe0 Add UndoBuffer class 2021-03-31 23:20:16 -04:00
b2bd75c2b1 Rename TextBuffer to DataBuffer 2021-03-19 19:14:34 -04:00
394bbda32f Remove Timer C++ module 2021-03-18 14:12:43 -04:00
f13f8bd524 Add LineEndings.text() 2021-03-11 15:02:34 -05:00
9f75d6c763 Verify UTF8 is detected encoding of empty buffer 2021-03-11 14:46:52 -05:00
5af185f917 rm PagedBuffer 2020-12-20 10:41:48 -05:00
e102c0c6f6 Store icon in BGRA format so runtime conversion is not necessary. 2020-12-19 12:31:07 -05:00
7678c00d25 Move icon. 2020-12-19 11:26:58 -05:00
9723c19514 Set window title. 2020-12-19 11:20:32 -05:00
42d1711bfb Set window icon. 2020-12-19 10:39:19 -05:00
14b448d8fb Remove src-c files that have been ported. 2020-12-13 20:26:58 -05:00
a53b53e864 Add Gl.draw_rect(). 2020-12-10 20:40:03 -05:00
e51953445b gltk.Buffer constructor takes target parameter. 2020-12-10 20:28:49 -05:00
64c3285fbc gltk.Buffer.set_buffer_data() can take an arbitrary array. 2020-12-10 20:26:58 -05:00
24b7ee9f16 Add Gl class to manage OpenGL drawing operations for a Window. 2020-12-10 20:21:17 -05:00
4775435df4 Add jes.gui.Window to own jes-related window functionality. 2020-12-09 21:51:44 -05:00
23cfdb1273 Add FlatProgram and RectProgram. 2020-12-08 20:34:41 -05:00
e215485293 Convert gltk.Program to a class template to generate specialized program classes. 2020-12-07 23:43:42 -05:00
816aca30ac Add gltk.Program.get_uniform_locations(). 2020-12-07 15:55:03 -05:00
52d7eb5eab Allow passing shaders and attribute locations to Program constructor. 2020-12-07 15:40:11 -05:00
b16d6fa43f add gltk.Program.bind_attrib_location() 2020-12-07 14:17:37 -05:00
858ce9f7b1 Glyph rendering working (test code; needs refactoring). 2020-12-06 15:32:47 -05:00
4923eb1ab8 Fix OpenGL buffer data for Glyph rendering. 2020-12-06 15:30:15 -05:00
2ab09b47bf Some work on rendering glyphs. 2020-12-04 17:58:34 -05:00
6ff4bdcc11 Free the preloaded font glyphs. 2020-12-03 10:50:46 -05:00
69f568cc7a remove Font.next_power_of_2() 2020-12-03 10:46:24 -05:00
97e4dde563 jtk: Store event list as untranslated events from C to avoid threading issues. 2020-12-03 10:41:41 -05:00
5385718e91 Add Gui class and move GUI logic from main module to it. 2020-12-03 10:00:34 -05:00
19a1ae222a gltk: import other gltk modules in package 2020-12-03 09:47:52 -05:00
9782ef2938 Create window on startup and run event loop. 2020-12-01 21:48:45 -05:00
08f583e994 add initial gltk files 2020-11-29 22:03:47 -05:00
b3cb93612d Start on Font module. 2020-11-29 11:05:11 -05:00
45bbf230a5 Add C Font module for FreeType interface. 2020-11-29 10:37:19 -05:00
401eb1d960 Completed migrating Encoding to D. 2020-11-27 21:37:53 -05:00
926ad3ec0d Add Encoding.encode() and Encoding.decode(). 2020-11-27 20:51:40 -05:00
575589e5a3 mark some functions private 2020-11-27 19:54:52 -05:00
b0adb417a0 remove a few C++ modules that have been converted to D 2020-11-24 17:15:33 -05:00
1b5a2d92af Add LineEndings module. 2020-11-24 16:57:51 -05:00
97e01ab714 Fix Encoding detection of UTF-16. 2020-11-15 22:06:17 -05:00
bc21e746fb Start on some Encoding unit tests. 2020-11-15 22:01:55 -05:00
047288ea3d Add some encoding test files. 2020-11-15 21:35:51 -05:00
179690f177 Start on Encoding module. 2020-11-11 22:26:16 -05:00
2db942f47d Replace GapBuffer with TextBuffer. 2020-11-10 19:56:58 -05:00
581b83fe54 call jtk.quit() 2020-08-03 16:55:55 -04:00
3f4a8709b5 pull in DerelictGL3 and load it 2020-08-03 16:53:22 -04:00
56c20c4a36 jtk: indicate which Window had event; convert Event to class 2020-07-16 11:35:29 -04:00
a30b4b7ff8 fix Event structure alignment between C and D 2020-07-09 15:06:48 -04:00
acb25132e4 add jtk.quit() 2020-07-09 12:05:13 -04:00
d3203c7790 fix XInitThreads() error check 2020-07-09 11:04:07 -04:00
a0910191da add jtk.event.wait_event() 2020-07-08 14:14:29 -04:00
303d387c20 add event thread and jtk.event.check_event() 2020-07-08 12:52:32 -04:00
0963b80234 jtk.timer: make thread safe 2020-07-08 11:17:12 -04:00
3f326a46f0 compile C sources with -Wall 2020-07-08 11:06:22 -04:00
ef036716b7 use a ulong instead of void * for window handle 2020-07-08 11:05:53 -04:00
84b67e99b1 add jtk_wake() 2020-07-08 10:16:38 -04:00
6cf36a852f jtk.c: support multiple threads 2020-07-07 16:25:12 -04:00
d3d6fd0fbf add jtk event functionality C backend 2020-06-30 17:16:34 -04:00
7a381b87c5 compile with -Wall 2020-06-23 17:03:07 -04:00
5741266dfb jes.core.gapbuffer: use D-style dynamic array syntax 2020-06-23 17:03:00 -04:00
0678bd79f4 jtk: couple unsigned literals 2020-06-23 17:01:11 -04:00
5119332adb jtk.timer: mark fields private 2020-06-23 16:57:51 -04:00
273d0faa44 jtk.timer: specify functions with package-only access 2020-06-23 16:55:50 -04:00
eea524f106 jtk.timer: store times in microseconds, not milliseconds 2020-06-23 16:55:02 -04:00
a811a743b8 add jtk.timer module 2020-06-23 13:50:44 -04:00
977b7cbf37 add jtk.time module 2020-06-23 12:34:16 -04:00
09875f5d49 add jtk.Window.swap_buffers() 2020-06-23 12:25:13 -04:00
a51d6e2b29 add jtk/package.d 2020-06-23 12:24:28 -04:00
97ab41580a add configure checks for needed libraries 2020-06-15 12:49:01 -04:00
986800332c update rscons to 2.1.0 2020-06-15 12:46:28 -04:00
fef6a6f824 allow constructing/closing a jtk.window.Window 2019-12-30 22:35:41 -05:00
daf14dc4fc reorganize jtk into src/jtk 2019-12-30 22:21:10 -05:00
e4e280da4f add some jtk window functions 2019-12-29 20:41:48 -05:00
4e6c392d44 add jtk.c 2019-12-16 22:23:02 -05:00
18ed74615a update rscons to v2.0.2 2019-12-16 21:51:32 -05:00
6349423329 add gapbuffer 2019-12-06 22:17:37 -05:00
f650256986 mv src/jes.d -> src/main.d 2019-12-03 12:38:06 -05:00
3e5165361e fix Rsconscript 2019-12-03 12:32:05 -05:00
846d81b60e Merge branch 'master' into d
switch from waf to rscons
2019-12-02 21:06:44 -05:00
5d6c6b0e0f start on jtk module 2018-07-25 22:05:11 -04:00
e7acf05cc4 add src/jes.d 2018-07-25 21:33:41 -04:00
663ed8c465 add Rsconsfile 2018-07-25 21:30:14 -04:00
50cd9efd86 mv src src-c 2018-07-25 20:47:02 -04:00
117 changed files with 3556 additions and 9601 deletions

1
.gitignore vendored
View File

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

13
.gitmodules vendored
View File

@ -1,6 +1,15 @@
[submodule "libs/googletest"]
path = libs/googletest
url = git://github.com/google/googletest
url = https://github.com/google/googletest
[submodule "libs/glcxx"]
path = libs/glcxx
url = git://github.com/holtrop/glcxx.git
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

View File

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

View File

@ -1,39 +1,20 @@
project_name "jes"
configure do
check_c_compiler
check_cxx_compiler
check_d_compiler
check_c_header "getopt.h"
check_c_header "X11/Xlib.h"
check_cfg package: "freetype2"
check_lib "GL"
check_lib "dl"
check_lib "X11"
check_lib "GLX"
check_cfg package: "freetype2"
check_program "convert"
end
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 = 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}")
end
main_env.clone do |env|
env["DFLAGS"] += %w[-g -funittest]
env.Program("jestest", "${sources}")
end

1
libs/DerelictGL3 Submodule

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

1
libs/DerelictGLFW3 Submodule

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

1
libs/DerelictUtil Submodule

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

33
rscons

File diff suppressed because one or more lines are too long

20
scripts/icon.rb Executable file
View File

@ -0,0 +1,20 @@
#!/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

@ -1,16 +0,0 @@
#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

View File

@ -1,15 +0,0 @@
#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

View File

@ -1,244 +0,0 @@
#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;
}

View File

@ -1,29 +0,0 @@
#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

View File

@ -1,123 +0,0 @@
#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;
}

View File

@ -1,27 +0,0 @@
#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

View File

@ -1,129 +0,0 @@
#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);
}
}
}

View File

@ -1,169 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
#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),
};

View File

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

View File

@ -1,72 +0,0 @@
#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

View File

@ -1,32 +0,0 @@
#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);
}

View File

@ -1,19 +0,0 @@
#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

32
src/gltk/array.d Normal file
View File

@ -0,0 +1,32 @@
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;
}
}

47
src/gltk/buffer.d Normal file
View File

@ -0,0 +1,47 @@
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);
}
}

7
src/gltk/package.d Normal file
View File

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

181
src/gltk/program.d Normal file
View File

@ -0,0 +1,181 @@
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();
}
}

80
src/gltk/shader.d Normal file
View File

@ -0,0 +1,80 @@
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;
}
}

44
src/gltk/texture.d Normal file
View File

@ -0,0 +1,44 @@
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;
}
};

View File

@ -1,91 +0,0 @@
#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;
}

View File

@ -1,27 +0,0 @@
#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

View File

@ -1,52 +0,0 @@
#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;
}

View File

@ -1,27 +0,0 @@
#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

View File

@ -1,44 +0,0 @@
#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

View File

@ -1,17 +0,0 @@
#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");
}

View File

@ -1,40 +0,0 @@
#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

View File

@ -1,51 +0,0 @@
#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);
}

View File

@ -1,34 +0,0 @@
#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

View File

@ -1,18 +0,0 @@
#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");
}

View File

@ -1,46 +0,0 @@
#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

View File

@ -1,18 +0,0 @@
#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");
}

View File

@ -1,46 +0,0 @@
#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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
#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",
};

View File

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

View File

@ -1,59 +0,0 @@
#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

View File

@ -1,12 +0,0 @@
#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

View File

@ -1,482 +0,0 @@
#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

View File

@ -1,62 +0,0 @@
#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

@ -1,9 +0,0 @@
#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

View File

@ -1,9 +0,0 @@
#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;
}

View File

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

View File

@ -1,157 +0,0 @@
#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;
}

View File

@ -1,14 +0,0 @@
#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

View File

@ -1,95 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
#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

178
src/jes/core/databuffer.d Normal file
View File

@ -0,0 +1,178 @@
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));
}
}

346
src/jes/core/encoding.d Normal file
View File

@ -0,0 +1,346 @@
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

@ -0,0 +1,76 @@
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");
}
}

331
src/jes/core/undobuffer.d Normal file
View File

@ -0,0 +1,331 @@
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();
}
}

130
src/jes/gui/font.c Normal file
View File

@ -0,0 +1,130 @@
#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);
}

143
src/jes/gui/font.d Normal file
View File

@ -0,0 +1,143 @@
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;
}
}

100
src/jes/gui/gl.d Normal file
View File

@ -0,0 +1,100 @@
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;
}
}

516
src/jes/gui/icon.d Normal file
View File

@ -0,0 +1,516 @@
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,
];

54
src/jes/gui/package.d Normal file
View File

@ -0,0 +1,54 @@
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