Rought font extractor that probably has a memory error causing it to behave mysteriously, and the designer now uses a json file of the characters that will work.
This commit is contained in:
parent
9ab064126f
commit
a9e25668fb
7 changed files with 293 additions and 44 deletions
|
@ -1,3 +1,5 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono> // for operator""s, chrono_literals
|
||||
#include <thread> // for sleep_for
|
||||
#include "dinkyecs.hpp"
|
||||
|
@ -13,9 +15,9 @@
|
|||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <vector>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace nlohmann;
|
||||
using namespace fmt;
|
||||
using namespace ftxui;
|
||||
using namespace std::chrono_literals;
|
||||
|
@ -26,58 +28,80 @@ using std::string, std::wstring, std::vector;
|
|||
const Point GRID_SIZE={15,8};
|
||||
const int DEFAULT_FONT_SIZE=200;
|
||||
|
||||
struct FontGridCell {
|
||||
size_t cm_index;
|
||||
string as_string;
|
||||
wstring as_wstring;
|
||||
};
|
||||
|
||||
struct FontGrid {
|
||||
size_t width;
|
||||
size_t height;
|
||||
vector<vector<string>> $chars;
|
||||
vector<vector<FontGridCell>> $grid;
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
|
||||
vector<wstring> $wcharmap;
|
||||
vector<string> $charmap;
|
||||
|
||||
FontGrid(size_t width, size_t height) :
|
||||
width(width), height(height),
|
||||
$chars(height, vector<string>(width, ""))
|
||||
$grid(height, vector<FontGridCell>(width, {0, "", L""}))
|
||||
{
|
||||
configure_font();
|
||||
}
|
||||
|
||||
void render(wchar_t start_char, bool fill) {
|
||||
wchar_t cur_char = start_char;
|
||||
void configure_font() {
|
||||
std::ifstream in_file("./fontlist.json");
|
||||
json input = json::parse(in_file);
|
||||
|
||||
for(auto inchar : input) {
|
||||
$charmap.push_back(inchar);
|
||||
$wcharmap.push_back($converter.from_bytes(inchar));
|
||||
}
|
||||
}
|
||||
|
||||
size_t max_chars() {
|
||||
return $wcharmap.size();
|
||||
}
|
||||
|
||||
void render(size_t start_char, bool fill) {
|
||||
size_t next_char = start_char;
|
||||
|
||||
for(size_t y = 0; y < height; ++y) {
|
||||
for(size_t x = 0; x < width; ++x) {
|
||||
if(!fill) {
|
||||
cur_char += (x+1) * (y+1);
|
||||
next_char++;
|
||||
}
|
||||
|
||||
wstring out_w{cur_char};
|
||||
$chars[y][x] = from_unicode(out_w);
|
||||
$grid[y][x] = {
|
||||
.cm_index = next_char,
|
||||
.as_string = $charmap[next_char],
|
||||
.as_wstring = $wcharmap[next_char]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string from_unicode(wstring input) {
|
||||
try {
|
||||
return $converter.to_bytes(input);
|
||||
} catch(...) {
|
||||
return $converter.to_bytes(L"?");
|
||||
}
|
||||
size_t charmap_index(size_t x, size_t y) {
|
||||
FontGridCell &cell = $grid[y][x];
|
||||
return cell.cm_index;
|
||||
}
|
||||
|
||||
wchar_t to_unicode_char(size_t x, size_t y) {
|
||||
try {
|
||||
string input = $chars[y][x]; // BUG: bounds check this instead
|
||||
return $converter.from_bytes(input)[0];
|
||||
} catch(...) {
|
||||
return L'?';
|
||||
}
|
||||
string& as_string(size_t x, size_t y) {
|
||||
return $grid[y][x].as_string;
|
||||
}
|
||||
|
||||
string at(size_t x, size_t y) {
|
||||
return $chars[y][x];
|
||||
wstring& as_wstring(size_t x, size_t y) {
|
||||
return $grid[y][x].as_wstring;
|
||||
}
|
||||
|
||||
wchar_t as_wchar(size_t cm_index) {
|
||||
return $wcharmap[cm_index][0];
|
||||
}
|
||||
|
||||
|
||||
unsigned int page_size() {
|
||||
return width * height;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct WhatTheColor {
|
||||
|
@ -97,8 +121,8 @@ class GUI {
|
|||
Canvas $canvas;
|
||||
SFMLRender $renderer;
|
||||
FontGrid $font_grid;
|
||||
wchar_t $start_char = L'\u28cc';
|
||||
wchar_t $fill_char = WCHAR_MIN;
|
||||
size_t $start_char = 0;
|
||||
size_t $fill_char = 0;
|
||||
WhatTheColor $fg_color;
|
||||
WhatTheColor $bg_color;
|
||||
Component $fg_settings;
|
||||
|
@ -113,7 +137,11 @@ class GUI {
|
|||
$bg_color{.h=100, .s=100, .v=100}
|
||||
{
|
||||
resize_fonts(DEFAULT_FONT_SIZE);
|
||||
$font_grid.render($start_char, false);
|
||||
render_grid($start_char, false);
|
||||
}
|
||||
|
||||
void render_grid(size_t start_char, bool fill) {
|
||||
$font_grid.render(start_char, fill);
|
||||
}
|
||||
|
||||
void resize_fonts(int new_size) {
|
||||
|
@ -124,11 +152,12 @@ class GUI {
|
|||
}
|
||||
|
||||
void draw_font_grid() {
|
||||
int flip_it = 0;
|
||||
for(size_t y = 0; y < $font_grid.height; y++) {
|
||||
for(size_t x = 0; x < $font_grid.width; x++) {
|
||||
$canvas.DrawText(x * 2, y * 4, $font_grid.at(x, y), [&](auto &pixel) {
|
||||
for(size_t x = 0; x < $font_grid.width; x++, flip_it++) {
|
||||
$canvas.DrawText(x * 2, y * 4, $font_grid.as_string(x, y), [&](auto &pixel) {
|
||||
pixel.foreground_color = Color::HSV($fg_color.h, $fg_color.s, $fg_color.v);
|
||||
pixel.background_color = Color::HSV($bg_color.h, $bg_color.s, $bg_color.v);
|
||||
pixel.background_color = Color::HSV($bg_color.h, $bg_color.s, $bg_color.v / (flip_it % 2 * 2 + 1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -150,10 +179,12 @@ class GUI {
|
|||
$bg_color.v_slider = Slider("BG V:", &$bg_color.v, 0, 255, 1);
|
||||
|
||||
$status_ui.set_renderer(Renderer([&]{
|
||||
wchar_t fill_char = $font_grid.as_wchar($fill_char);
|
||||
|
||||
return hbox({
|
||||
hflow(
|
||||
vbox(
|
||||
text(format("\\u{:x} {} MIN: {}, MAX: {}", int($fill_char), int($fill_char), WCHAR_MIN, WCHAR_MAX)) | border,
|
||||
text(format("\\u{:x} {} IDX: {}, MIN: {}, MAX: {}", int(fill_char), int(fill_char), $fill_char, WCHAR_MIN, WCHAR_MAX)) | border,
|
||||
separator(),
|
||||
text(format("FG H: {}, S: {}, V: {}",
|
||||
$fg_color.h, $fg_color.s, $fg_color.v)) | border,
|
||||
|
@ -190,12 +221,12 @@ class GUI {
|
|||
}
|
||||
|
||||
void select_cell(Point pos) {
|
||||
$fill_char = $font_grid.to_unicode_char(pos.x, pos.y);
|
||||
$font_grid.render($fill_char, true);
|
||||
$fill_char = $font_grid.charmap_index(pos.x, pos.y);
|
||||
render_grid($fill_char, true);
|
||||
}
|
||||
|
||||
void deselect_cell() {
|
||||
$font_grid.render($start_char, false);
|
||||
render_grid($start_char, false);
|
||||
}
|
||||
|
||||
bool handle_ui_events() {
|
||||
|
@ -210,13 +241,13 @@ class GUI {
|
|||
return true;
|
||||
} else if(event.type == sf::Event::KeyPressed) {
|
||||
if(KB::isKeyPressed(KB::Up)) {
|
||||
$start_char = std::max(WCHAR_MIN+1, $start_char - $font_grid.page_size());
|
||||
$font_grid.render($start_char, false);
|
||||
$start_char = std::max(size_t(1), $start_char - $font_grid.page_size());
|
||||
render_grid($start_char, false);
|
||||
event_happened = true;
|
||||
$renderer.clear_cache();
|
||||
} else if(KB::isKeyPressed(KB::Down)) {
|
||||
$start_char = std::min(WCHAR_MAX, $start_char + $font_grid.page_size());
|
||||
$font_grid.render($start_char, false);
|
||||
$start_char = std::min($font_grid.max_chars(), $start_char + $font_grid.page_size());
|
||||
render_grid($start_char, false);
|
||||
$renderer.clear_cache();
|
||||
} else if(KB::isKeyPressed(KB::Equal)) {
|
||||
resize_fonts(font_size + 10);
|
||||
|
@ -264,7 +295,6 @@ int main(int argc, char *argv[]) {
|
|||
gui.render_scene();
|
||||
|
||||
if(gui.handle_ui_events()) {
|
||||
println("THERE WERE EVENTS");
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue