Compare commits
87 Commits
Author | SHA1 | Date | |
---|---|---|---|
bec2e913c0 | |||
1252ed7879 | |||
c9650aada7 | |||
6f32d3f2fe | |||
51b1b34d03 | |||
997cf5efe0 | |||
b2bd75c2b1 | |||
394bbda32f | |||
f13f8bd524 | |||
9f75d6c763 | |||
5af185f917 | |||
e102c0c6f6 | |||
7678c00d25 | |||
9723c19514 | |||
42d1711bfb | |||
14b448d8fb | |||
a53b53e864 | |||
e51953445b | |||
64c3285fbc | |||
24b7ee9f16 | |||
4775435df4 | |||
23cfdb1273 | |||
e215485293 | |||
816aca30ac | |||
52d7eb5eab | |||
b16d6fa43f | |||
858ce9f7b1 | |||
4923eb1ab8 | |||
2ab09b47bf | |||
6ff4bdcc11 | |||
69f568cc7a | |||
97e4dde563 | |||
5385718e91 | |||
19a1ae222a | |||
9782ef2938 | |||
08f583e994 | |||
b3cb93612d | |||
45bbf230a5 | |||
401eb1d960 | |||
926ad3ec0d | |||
575589e5a3 | |||
b0adb417a0 | |||
1b5a2d92af | |||
97e01ab714 | |||
bc21e746fb | |||
047288ea3d | |||
179690f177 | |||
2db942f47d | |||
581b83fe54 | |||
3f4a8709b5 | |||
56c20c4a36 | |||
a30b4b7ff8 | |||
acb25132e4 | |||
d3203c7790 | |||
a0910191da | |||
303d387c20 | |||
0963b80234 | |||
3f326a46f0 | |||
ef036716b7 | |||
84b67e99b1 | |||
6cf36a852f | |||
d3d6fd0fbf | |||
7a381b87c5 | |||
5741266dfb | |||
0678bd79f4 | |||
5119332adb | |||
273d0faa44 | |||
eea524f106 | |||
a811a743b8 | |||
977b7cbf37 | |||
09875f5d49 | |||
a51d6e2b29 | |||
97ab41580a | |||
986800332c | |||
fef6a6f824 | |||
daf14dc4fc | |||
e4e280da4f | |||
4e6c392d44 | |||
18ed74615a | |||
6349423329 | |||
f650256986 | |||
3e5165361e | |||
846d81b60e | |||
5d6c6b0e0f | |||
e7acf05cc4 | |||
663ed8c465 | |||
50cd9efd86 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
|||||||
/test/tmp/
|
/test/tmp/
|
||||||
/coverage/
|
/coverage/
|
||||||
/jes
|
/jes
|
||||||
|
/jestest
|
||||||
|
13
.gitmodules
vendored
13
.gitmodules
vendored
@ -1,6 +1,15 @@
|
|||||||
[submodule "libs/googletest"]
|
[submodule "libs/googletest"]
|
||||||
path = libs/googletest
|
path = libs/googletest
|
||||||
url = git://github.com/google/googletest
|
url = https://github.com/google/googletest
|
||||||
[submodule "libs/glcxx"]
|
[submodule "libs/glcxx"]
|
||||||
path = 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
|
||||||
|
9
Makefile
9
Makefile
@ -5,3 +5,12 @@ all:
|
|||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
./rscons clean
|
./rscons clean
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
./rscons build
|
||||||
|
./jestest
|
||||||
|
|
||||||
|
.PHONY: icon
|
||||||
|
icon:
|
||||||
|
./scripts/icon.rb
|
||||||
|
47
Rsconscript
47
Rsconscript
@ -1,39 +1,20 @@
|
|||||||
project_name "jes"
|
|
||||||
|
|
||||||
configure do
|
configure do
|
||||||
check_c_compiler
|
|
||||||
check_cxx_compiler
|
|
||||||
check_d_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 "X11"
|
||||||
|
check_lib "GLX"
|
||||||
|
check_cfg package: "freetype2"
|
||||||
|
check_program "convert"
|
||||||
end
|
end
|
||||||
|
|
||||||
build do
|
main_env = env do |env|
|
||||||
Environment.new do |env|
|
env["sources"] = glob("src/**/*.{c,d}", "libs/Derelict*/**/*.d")
|
||||||
env["CPPDEFINES"] += %w[
|
env["CCFLAGS"] += %w[-Wall]
|
||||||
APPNAME="jes"
|
env["D_IMPORT_PATH"] += glob("src", "libs/Derelict*/source")
|
||||||
VERSION="0.0.1"
|
env["DFLAGS"] += %w[-Wall]
|
||||||
GLCXX_GL_INCLUDE="gl3w.h"
|
env["LIBS"] += %w[X11 GLX]
|
||||||
PLATFORM_LINUX
|
env.Program("jes", "${sources}")
|
||||||
JTK_X
|
end
|
||||||
]
|
main_env.clone do |env|
|
||||||
env["CPPPATH"] += glob("src/**", "libs/glcxx/include")
|
env["DFLAGS"] += %w[-g -funittest]
|
||||||
env["CCFLAGS"] += %w[
|
env.Program("jestest", "${sources}")
|
||||||
-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
|
|
||||||
end
|
end
|
||||||
|
1
libs/DerelictGL3
Submodule
1
libs/DerelictGL3
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit e1197a6c5f644a8c4a2f132de03d5c979490690c
|
1
libs/DerelictGLFW3
Submodule
1
libs/DerelictGLFW3
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 09b9680cc8b40e20a48b2c008907cc749254aced
|
1
libs/DerelictUtil
Submodule
1
libs/DerelictUtil
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 8dda33953e05e228a8a0459954023de2c0b375b5
|
20
scripts/icon.rb
Executable file
20
scripts/icon.rb
Executable 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
|
Before Width: | Height: | Size: 565 B After Width: | Height: | Size: 565 B |
@ -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
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
123
src/core/File.cc
123
src/core/File.cc
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
@ -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),
|
|
||||||
};
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
32
src/gltk/array.d
Normal 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
47
src/gltk/buffer.d
Normal 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
7
src/gltk/package.d
Normal 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
181
src/gltk/program.d
Normal 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
80
src/gltk/shader.d
Normal 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
44
src/gltk/texture.d
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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");
|
|
||||||
}
|
|
@ -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
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
|
|
@ -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");
|
|
||||||
}
|
|
@ -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
|
|
@ -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");
|
|
||||||
}
|
|
@ -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
|
|
1339
src/gui/gl3w/gl3w.c
1339
src/gui/gl3w/gl3w.c
File diff suppressed because it is too large
Load Diff
1235
src/gui/gl3w/gl3w.h
1235
src/gui/gl3w/gl3w.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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",
|
|
||||||
};
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef JTK_TIME_H
|
|
||||||
#define JTK_TIME_H
|
|
||||||
|
|
||||||
#include "Jtk_timer.h"
|
|
||||||
|
|
||||||
bool Jtk_Init();
|
|
||||||
uint64_t Jtk_UsTime();
|
|
||||||
|
|
||||||
#endif
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
178
src/jes/core/databuffer.d
Normal 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
346
src/jes/core/encoding.d
Normal 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);
|
||||||
|
}
|
||||||
|
};
|
76
src/jes/core/lineendings.d
Normal file
76
src/jes/core/lineendings.d
Normal 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
331
src/jes/core/undobuffer.d
Normal 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
130
src/jes/gui/font.c
Normal 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
143
src/jes/gui/font.d
Normal 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
100
src/jes/gui/gl.d
Normal 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
516
src/jes/gui/icon.d
Normal 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
54
src/jes/gui/package.d
Normal 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
Loading…
x
Reference in New Issue
Block a user