Add project files.

This commit is contained in:
falsycat 2021-08-21 17:29:58 +09:00
parent 3c7909c4d8
commit d1f943df8e
15 changed files with 6045 additions and 0 deletions

2
Font.cc Normal file
View File

@ -0,0 +1,2 @@
#define STB_TRUETYPE_IMPLEMENTATION
#include "Font.h"

73
Font.h Normal file
View File

@ -0,0 +1,73 @@
#pragma once
#include <cstdint>
#include <fstream>
#include <memory>
#include <string>
#include "stb_truetype.h"
#include "common.h"
#include "iAllocator.h"
#include "Rasterbuffer.h"
namespace gj {
class Font {
public:
Font() = delete;
Font(Font&&) = delete;
Font(const Font&) = delete;
Font& operator=(Font&&) = delete;
Font& operator=(const Font&) = delete;
Font(iAllocator* alloc, const std::string& path) : alloc_(alloc) {
std::ifstream ifs(path, std::ios::binary);
if (!ifs) {
Abort("failed to open: "+path);
}
ifs.seekg(0, std::ios::end);
const size_t size = ifs.tellg();
ifs.seekg(0);
buf_ = alloc_->MakeUniqueArray<uint8_t>(size);
ifs.read(reinterpret_cast<char*>(buf_.get()), size);
const int offset = stbtt_GetFontOffsetForIndex(buf_.get(), 0);
if (!stbtt_InitFont(&stb_, buf_.get(), offset)) {
Abort("invalid font: "+path);
}
}
Colorbuffer&& RenderGlyph(char16_t c, uint32_t fontsize = 32) {
int w, h;
const float s = stbtt_ScaleForPixelHeight(&stb_, fontsize*1.f);
const uint8_t* src = stbtt_GetCodepointBitmap(&stb_, 0, s, c, &w, &h, 0, 0);
Colorbuffer ret(alloc_, w, h);
float* dst = ret.ptr();
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
*dst = *src*1./UINT8_MAX;
++dst, ++src;
}
}
return std::move(ret);
}
private:
iAllocator* alloc_;
stbtt_fontinfo stb_;
iAllocator::UniquePtr<uint8_t> buf_;
};
}

31
GlyphsJuke.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31605.320
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GlyphsJuke", "GlyphsJuke.vcxproj", "{7AEB2CAE-89E0-4705-9020-26066ABDE274}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Debug|x64.ActiveCfg = Debug|x64
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Debug|x64.Build.0 = Debug|x64
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Debug|x86.ActiveCfg = Debug|Win32
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Debug|x86.Build.0 = Debug|Win32
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Release|x64.ActiveCfg = Release|x64
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Release|x64.Build.0 = Release|x64
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Release|x86.ActiveCfg = Release|Win32
{7AEB2CAE-89E0-4705-9020-26066ABDE274}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4FFC52B9-3723-4AEF-8A03-9DE3DC1BFB22}
EndGlobalSection
EndGlobal

161
GlyphsJuke.vcxproj Normal file
View File

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{7aeb2cae-89e0-4705-9020-26066abde274}</ProjectGuid>
<RootNamespace>GlyphsJuke</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Font.cc" />
<ClCompile Include="main.cc" />
<ClCompile Include="Win32Console.cc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="common.h" />
<ClInclude Include="Font.h" />
<ClInclude Include="Rasterbuffer.h" />
<ClInclude Include="iConsole.h" />
<ClInclude Include="iAllocator.h" />
<ClInclude Include="LinearAllocator.h" />
<ClInclude Include="StackAllocator.h" />
<ClInclude Include="stb_truetype.h" />
<ClInclude Include="Win32Console.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Win32Console.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Font.cc">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="iConsole.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iAllocator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LinearAllocator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StackAllocator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Rasterbuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Win32Console.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stb_truetype.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Font.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

97
LinearAllocator.h Normal file
View File

@ -0,0 +1,97 @@
#pragma once
#include <cassert>
#include <cstddef>
#include <cstdint>
#include "common.h"
#include "iAllocator.h"
namespace gj {
class LinearAllocator : public iAllocator {
public:
using iAllocator::Alloc;
using iAllocator::MakeUnique;
LinearAllocator() = delete;
LinearAllocator(LinearAllocator&&) = delete;
LinearAllocator(const LinearAllocator&) = delete;
LinearAllocator& operator=(LinearAllocator&&) = delete;
LinearAllocator& operator=(const LinearAllocator&) = delete;
LinearAllocator(void* ptr, const size_t size) :
ptr_(static_cast<uint8_t*>(ptr)) {
assert(size >= sizeof(Header)*2);
auto head = reinterpret_cast<Header*>(ptr_);
head->prev = 0;
head->next = size - sizeof(Header);
head->size = sizeof(Header);
auto tail = reinterpret_cast<Header*>(ptr_+head->next);
tail->prev = head->next;
tail->next = 0;
tail->size = sizeof(Header);
}
void* Alloc(const size_t size) override {
const size_t aligned_size = (((size >> 3) + !!(size & 0b111))) << 3;
const size_t whole_size = sizeof(Header) + aligned_size;
assert(aligned_size >= size);
auto h = reinterpret_cast<Header*>(ptr_);
while (h->next) {
const size_t remain = h->next - h->size;
if (remain >= whole_size) {
auto hprev = h;
auto hnext = reinterpret_cast<Header*>(reinterpret_cast<uint8_t*>(hprev) + hprev->next);
h = reinterpret_cast<Header*>(reinterpret_cast<uint8_t*>(hprev) + hprev->size);
h->prev = hprev->size;
h->next = remain;
h->size = whole_size;
hprev->next = h->prev;
hnext->prev = h->next;
return h + 1;
}
h = reinterpret_cast<Header*>(reinterpret_cast<uint8_t*>(h) + h->next);
}
Abort("LinearAllocator Allocation Failure");
}
void Free(void* ptr) override {
if (!ptr) return;
uint8_t* uptr = reinterpret_cast<uint8_t*>(ptr) - sizeof(Header);
auto h = reinterpret_cast<Header*>(uptr);
auto hprev = reinterpret_cast<Header*>(uptr - h->prev);
auto hnext = reinterpret_cast<Header*>(uptr + h->next);
hprev->next += h->next;
hnext->prev += h->prev;
}
private:
/* |------prev--------||--------next--------| */
/* |----size-----| */
/* memory: HHAAAAAAAAAAAAAAAAUUHHAAAAAAAAAAAAAUUUUUUUHHAAAAA */
/* H: header, A: allocated area, U: unused area */
struct Header {
size_t prev;
size_t next;
size_t size;
};
static_assert(sizeof(Header) == sizeof(size_t)*3, "padding detected in memory header");
uint8_t* const ptr_;
};
}

72
Rasterbuffer.h Normal file
View File

@ -0,0 +1,72 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include "iAllocator.h"
namespace gj {
template <typename T>
class Rasterbuffer {
public:
Rasterbuffer() = delete;
Rasterbuffer(const Rasterbuffer&) = delete;
Rasterbuffer& operator=(const Rasterbuffer&) = delete;
Rasterbuffer(iAllocator* alloc, uint32_t w, uint32_t h) :
alloc_(alloc), w_(w), h_(h),
buf_(alloc->Alloc<T>(static_cast<uint64_t>(w_)*h_)) {
_ASSERT(buf_ != nullptr);
}
~Rasterbuffer() {
alloc_->Free(buf_);
}
Rasterbuffer(Rasterbuffer&& src) noexcept :
alloc_(src.alloc_), w_(src.w_), h_(src.h_), buf_(src.buf_) {
src.buf_ = nullptr;
}
Rasterbuffer& operator=(Rasterbuffer&& src) noexcept {
if (this != &src) {
alloc_ = src.alloc_;
w_ = src.w_;
h_ = src.h_;
buf_ = src.buf_;
src.buf_ = nullptr;
}
return *this;
}
void Clear() {
memset(buf_, 0, static_cast<uint64_t>(w_) * h_ * sizeof(T));
}
uint32_t width() const {
return w_;
}
uint32_t height() const {
return h_;
}
T* ptr() {
return buf_;
}
const T* ptr() const {
return buf_;
}
private:
iAllocator* alloc_;
uint32_t w_, h_;
T* buf_;
};
using Colorbuffer = Rasterbuffer<float>;
using Textbuffer = Rasterbuffer<char16_t>;
}

63
StackAllocator.h Normal file
View File

@ -0,0 +1,63 @@
#pragma once
#include <cassert>
#include <cstddef>
#include <cstdint>
#include "iAllocator.h"
namespace gj {
class StackAllocator : public iAllocator {
public:
using iAllocator::Alloc;
using iAllocator::MakeUnique;
StackAllocator() = delete;
StackAllocator(StackAllocator&&) = delete;
StackAllocator(const StackAllocator&) = delete;
StackAllocator& operator=(StackAllocator&&) = delete;
StackAllocator& operator=(const StackAllocator&) = delete;
StackAllocator(void* ptr, const size_t size) :
begin_(static_cast<uint8_t*>(ptr)),
end_ (begin_+size),
next_ (begin_) {
}
~StackAllocator() {
assert(refcnt_ == 0);
}
void* Alloc(const size_t size) override {
const size_t aligned_size = ((size >> 3) + !!(size & 0b111)) << 3;
void* ret = next_;
next_ += aligned_size;
if (next_ >= end_) {
return nullptr;
}
++refcnt_;
return ret;
}
void Free(void* ptr) override {
if (!ptr) return;
assert(refcnt_);
if (--refcnt_ == 0) {
next_ = begin_;
}
}
private:
uint8_t* const begin_;
uint8_t* const end_;
uint8_t* next_;
size_t refcnt_ = 0;
};
}

87
Win32Console.cc Normal file
View File

@ -0,0 +1,87 @@
#include "Win32Console.h"
#include <cmath>
static void CalcChar(CHAR_INFO& c, float color, uint16_t text) {
constexpr wchar_t chars[] = L" .,:x!|X#%@$M";
constexpr uint8_t attrs[] = {
FOREGROUND_INTENSITY,
BACKGROUND_INTENSITY,
BACKGROUND_INTENSITY | FOREGROUND_RED,
BACKGROUND_RED | FOREGROUND_INTENSITY,
};
constexpr size_t char_expr_count = sizeof(chars)/sizeof(chars[0])-1;
constexpr size_t attr_expr_count = sizeof(attrs)/sizeof(attrs[0]);
constexpr size_t reso = char_expr_count*attr_expr_count;
/* post effect */
color = std::pow(color, 1.9);
int8_t a = static_cast<int8_t>(color*reso);
if (a >= reso) a = reso-1;
if (a < 0) a = 0;
size_t ci = a%char_expr_count;
size_t ai = a/char_expr_count;
if (ai%2 == 1) ci = char_expr_count-ci-1;
c.Char.UnicodeChar = chars[ci];
c.Attributes = attrs[ai];
if (text) c.Char.UnicodeChar = text;
}
void gj::Win32Console::main() {
bool shown = false;
while (alive_.load()) {
if (shown_.load()) {
if (!shown) {
shown = true;
ShowWindow(win_, TRUE);
}
constexpr CONSOLE_CURSOR_INFO cursor{ 1, FALSE };
SetConsoleCursorInfo(screen_, &cursor);
CHAR_INFO* c = chars_.get();
{ /* critical section */
std::lock_guard<std::mutex> _(mtx_);
const float* cb = cb_main_.ptr();
const char16_t* tb = tb_main_.ptr();
for (uint32_t y = 0; y < h_; ++y) {
bool mb = false;
for (uint32_t x = 0; x < w_; ++x) {
if (mb) {
*c = *(c - 1);
(c - 1)->Attributes |= COMMON_LVB_LEADING_BYTE;
c->Attributes |= COMMON_LVB_TRAILING_BYTE;
mb = false;
} else {
CalcChar(*c, *cb, *tb);
mb = (*tb & 0x80);
}
++cb, ++tb, ++c;
}
}
}
const COORD size = { static_cast<SHORT>(w_), static_cast<SHORT>(h_), };
const COORD pos = { 0, 0, };
SMALL_RECT rc = { 0, 0, static_cast<SHORT>(w_), static_cast<SHORT>(h_), };
WriteConsoleOutput(screen_, chars_.get(), size, pos, &rc);
} else {
if (shown) {
ShowWindow(win_, FALSE);
shown = false;
}
}
Sleep(30);
}
}

114
Win32Console.h Normal file
View File

@ -0,0 +1,114 @@
#pragma once
#include <atomic>
#include <cstdint>
#include <mutex>
#include <thread>
#include <vector>
#include <windows.h>
#include "iConsole.h"
namespace gj {
class Win32Console : iConsole {
public:
Win32Console() = delete;
Win32Console(Win32Console&&) = delete;
Win32Console(const Win32Console&) = delete;
Win32Console& operator=(Win32Console&&) = delete;
Win32Console& operator=(const Win32Console&) = delete;
Win32Console(iAllocator* alloc, uint32_t w, uint32_t h) :
w_(w), h_(h), shown_(false), alive_(true),
th_([this]() { main(); }),
cb_main_(alloc, w, h), cb_sub_(alloc, w, h),
tb_main_(alloc, w, h), tb_sub_(alloc, w, h),
chars_(std::make_unique<CHAR_INFO[]>(static_cast<uint64_t>(w)*h)),
win_(GetConsoleWindow()) {
_ASSERT(win_);
screen_ = GetStdHandle(STD_OUTPUT_HANDLE);
_ASSERT(screen_ != INVALID_HANDLE_VALUE);
CONSOLE_SCREEN_BUFFER_INFOEX size;
size.cbSize = sizeof(size);
GetConsoleScreenBufferInfoEx(screen_, &size);
COORD c;
c.X = w_;
c.Y = h_;
size.dwSize = c;
size.srWindow.Left = 0;
size.srWindow.Right = w_ + 1;
size.srWindow.Top = 0;
size.srWindow.Bottom = h_ + 1;
SetConsoleScreenBufferInfoEx(screen_, &size);
ShowWindow(win_, FALSE);
SetWindowLong(win_, GWL_STYLE, GetWindowLong(win_, GWL_STYLE) & ~WS_SIZEBOX);
}
~Win32Console() {
alive_.store(false);
th_.join();
}
void Show() override {
shown_.store(true);
}
void Hide() override {
shown_.store(false);
}
Colorbuffer& TakeColorbuffer() override {
return cb_sub_;
}
void SwapColorbuffer() override {
std::lock_guard<std::mutex> _(mtx_);
std::swap(cb_main_, cb_sub_);
}
Textbuffer& TakeTextbuffer() override {
return tb_sub_;
}
void SwapTextbuffer() override {
std::lock_guard<std::mutex> _(mtx_);
std::swap(tb_main_, tb_sub_);
}
uint32_t width() const override {
return w_;
}
uint32_t height() const override {
return h_;
}
private:
const uint32_t w_, h_;
std::atomic_bool alive_;
std::atomic_bool shown_;
std::mutex mtx_;
std::thread th_;
Colorbuffer cb_main_;
Colorbuffer cb_sub_;
Textbuffer tb_main_;
Textbuffer tb_sub_;
std::unique_ptr<CHAR_INFO[]> chars_;
HANDLE screen_ = INVALID_HANDLE_VALUE;
HWND win_ = nullptr;
void main();
};
}

23
common.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <codecvt>
#include <cstdlib>
#include <sstream>
#include <string>
#include <windows.h>
namespace gj {
[[noreturn]]
static inline void Abort(const std::string& msg) {
std::wostringstream conv;
conv << msg.c_str();
MessageBox(NULL, conv.str().c_str(), L"PROGRAM ABORTED", MB_OK);
std::exit(1);
}
}

68
iAllocator.h Normal file
View File

@ -0,0 +1,68 @@
#pragma once
#include <cassert>
#include <cstddef>
#include <memory>
namespace gj {
class iAllocator {
public:
template <typename T>
struct Deleter {
Deleter() = default;
Deleter(Deleter&&) = default;
Deleter(const Deleter&) = delete;
Deleter& operator=(Deleter&&) = default;
Deleter& operator=(const Deleter&) = delete;
Deleter(iAllocator* alloc) : alloc_(alloc) {
}
void operator()(T* ptr) {
assert(alloc_);
ptr->~T();
alloc_->Free(ptr);
}
iAllocator* alloc_;
};
template <typename T>
using UniquePtr = std::unique_ptr<T, Deleter<T>>;
iAllocator(iAllocator&&) = delete;
iAllocator(const iAllocator&) = delete;
iAllocator& operator=(iAllocator&&) = delete;
iAllocator& operator=(const iAllocator&) = delete;
iAllocator() = default;
virtual ~iAllocator() = default;
virtual void* Alloc(const size_t size) = 0;
virtual void Free(void* ptr) = 0;
template <typename T>
T* Alloc(size_t n = 1) {
return reinterpret_cast<T*>(Alloc(sizeof(T) * n));
}
template <typename T, typename... Args>
UniquePtr<T> MakeUnique(Args&&... args) {
T* ptr = Alloc<T>();
return std::unique_ptr<T, Deleter<T>>(new(ptr) T(args...), Deleter<T>(this));
}
template <typename T>
UniquePtr<T> MakeUniqueArray(size_t n) {
T* ptr = Alloc<T>(n);
return std::unique_ptr<T, Deleter<T>>(ptr, Deleter<T>(this));
}
};
}

34
iConsole.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "Rasterbuffer.h"
namespace gj {
class iConsole {
public:
iConsole(iConsole&&) = delete;
iConsole(const iConsole&) = delete;
iConsole& operator=(iConsole&&) = delete;
iConsole& operator=(const iConsole&) = delete;
iConsole() = default;
virtual ~iConsole() = default;
virtual void Show() = 0;
virtual void Hide() = 0;
virtual Colorbuffer& TakeColorbuffer() = 0;
virtual void SwapColorbuffer() = 0;
virtual Textbuffer& TakeTextbuffer() = 0;
virtual void SwapTextbuffer() = 0;
virtual uint32_t width() const = 0;
virtual uint32_t height() const = 0;
};
}

74
main.cc Normal file
View File

@ -0,0 +1,74 @@
#include <iostream>
#include <string>
#include <windows.h>
#include "common.h"
#include "Font.h"
#include "LinearAllocator.h"
#include "Win32Console.h"
constexpr size_t kHeapSize = 1024*1024*64;
constexpr uint32_t kWidth = 96;
constexpr uint32_t kHeight = 28;
int main() {
auto memory = std::make_unique<uint8_t[]>(kHeapSize);
gj::LinearAllocator alloc(memory.get(), kHeapSize);
gj::Win32Console console(&alloc, kWidth, kHeight);
console.Show();
gj::Font font(&alloc, "./font/shippori.ttf");
gj::Colorbuffer glyph = font.RenderGlyph(L'', 50);
size_t t = 0;
while (true) {
{
const std::u16string s = u"世界は猫によって支配されている";
gj::Textbuffer& tb = console.TakeTextbuffer();
tb.Clear();
char16_t* ptr = tb.ptr() + kWidth*(kHeight/2)+(t%(kWidth-s.length()*2));
for (size_t i = 0; i < s.length(); ++i) {
ptr[i*2] = s[i];
}
console.SwapTextbuffer();
}
{
gj::Colorbuffer& cb = console.TakeColorbuffer();
float* ptr = cb.ptr();
constexpr uintmax_t max = kHeight + kWidth;
for (uint32_t y = 0; y < kHeight; ++y) {
for (uint32_t x = 0; x < kWidth; ++x) {
*ptr = static_cast<float>((static_cast<uintmax_t>(y)+x+t)%(max*2)*1./max);
if (*ptr > 1) *ptr = 2-*ptr;
++ptr;
}
}
ptr = cb.ptr();
const uint32_t w = glyph.width();
const uint32_t h = glyph.height();
const float* src = glyph.ptr();
for (uint32_t y = 0; y < h; ++y) {
if (y >= kHeight) break;
for (uint32_t x = 0; x < w; ++x) {
if (x*2+1 >= kWidth) break;
ptr[y*kWidth+x*2] += src[y*w+x]*.3;
ptr[y*kWidth+x*2+1] += src[y*w+x]*.3;
}
}
console.SwapColorbuffer();
}
Sleep(60);
++t;
}
}

5089
stb_truetype.h Normal file

File diff suppressed because it is too large Load Diff