Compare commits

..

2 Commits

Author SHA1 Message Date
Simon Hardt
0553927dad add: Basic Font Rendering 2022-03-05 02:37:08 +01:00
Simon Hardt
df1ce5583b remove Config 2022-03-04 21:53:27 +01:00
16 changed files with 386 additions and 11 deletions

1
.gitignore vendored
View File

@@ -34,3 +34,4 @@
build/*
.vscode/*
frame/src/Config.h

View File

@@ -15,6 +15,7 @@ option(BUILD_EPD
)
find_package(fmt CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
option(BUILD_VIRTUAL_DISPLAY
"Build virtual sfml based display"
@@ -28,6 +29,7 @@ endif (BUILD_EPD)
if (BUILD_VIRTUAL_DISPLAY)
find_package(SFML COMPONENTS system window graphics CONFIG REQUIRED)
add_subdirectory(fontConverter)
endif(BUILD_VIRTUAL_DISPLAY)
add_subdirectory(frame)

View File

@@ -0,0 +1,10 @@
add_executable(font src/main.cpp)
target_link_libraries(font PUBLIC
sfml-system
sfml-window
sfml-graphics
fmt::fmt
nlohmann_json::nlohmann_json
)

114
fontConverter/src/main.cpp Normal file
View File

@@ -0,0 +1,114 @@
#include <fmt/format.h>
#include <fstream>
#include <nlohmann/json.hpp>
#include <sfml/Graphics.hpp>
using json = nlohmann::json;
void PrintGlyph(sf::Font const& font, sf::Glyph const& g, unsigned int size);
int main()
{
sf::Font font;
auto ok =
font.loadFromFile(R"(C:\Users\s-har\Downloads\FiraCode-Regular.ttf)");
fmt::print("Loaded {}\n", ok);
std::vector<char> chars = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
fmt::print("{}\n", font.getInfo().family);
fmt::print("Line Spacing: {}\n", font.getLineSpacing(14));
std::map<char, sf::Glyph> glyphs;
for(auto el : chars)
{
auto a = font.getGlyph(el, 14, false);
fmt::print("{}: w {} h {}\n",
el,
a.textureRect.width,
a.textureRect.height);
fmt::print("- t: {} l: {} w: {} h: {}\n",
a.bounds.top,
a.bounds.left,
a.bounds.width,
a.bounds.height);
fmt::print("offset: {}\n\n", a.advance);
glyphs[el] = a;
}
auto font_image = font.getTexture(14).copyToImage();
auto size = font_image.getSize();
json export_font;
export_font["name"] = font.getInfo().family;
export_font["sizes"] = json::object();
auto& size_14 = export_font["sizes"]["14"];
size_14["LineSpacing"] = font.getLineSpacing(14);
auto& Glyphs = size_14["Glyphs"];
for(auto&& [c, g] : glyphs)
{
auto& current = Glyphs[std::string{c}];
current["advance"] = g.advance;
current["x_offset"] = g.bounds.left;
current["y_offset"] = g.bounds.top;
current["width"] = g.bounds.width;
current["height"] = g.bounds.height;
std::vector<uint8_t> data;
for(int y = 0; y < (int)g.bounds.height; ++y)
{
for(int x = 0; x < (int)g.bounds.width; ++x)
{
auto c = font_image.getPixel(g.textureRect.left + x,
g.textureRect.top + y);
data.push_back(c.a > 100 ? 1 : 0);
}
}
current["data"] = data;
}
std::fstream out(fmt::format("{}.json", font.getInfo().family),
std::ios::out);
out << export_font.dump();
fmt::print("Size x: {} y: {}\n", size.x, size.y);
font_image.saveToFile("Test.png");
}
void PrintGlyph(sf::Font const& font, sf::Glyph const& g, unsigned int size)
{
auto font_image = font.getTexture(size).copyToImage();
for(int y = 0; y < (int)g.bounds.height; ++y)
{
for(int x = 0; x < (int)g.bounds.width; ++x)
{
auto c = font_image.getPixel(g.textureRect.left + x,
g.textureRect.top + y);
if(c.a > 100)
{
fmt::print("X");
} else
{
fmt::print(" ");
}
}
fmt::print("\n");
}
}

View File

@@ -15,7 +15,10 @@ set(src
src/display/Display.cpp
src/render/RenderTarget.hpp
src/render/RenderTarget.cpp
src/font/Font.hpp
src/font/Font.cpp
src/font/Glyph.hpp
src/font/Glyph.cpp
)
if (BUILD_EPD)
@@ -33,12 +36,22 @@ if (BUILD_VIRTUAL_DISPLAY)
endif (BUILD_VIRTUAL_DISPLAY)
add_executable(${target} ${src})
target_link_libraries(${target} PRIVATE fmt::fmt)
target_link_libraries(${target} PRIVATE
fmt::fmt
)
if (BUILD_EPD)
target_link_libraries(${target} PRIVATE waveshare)
target_link_libraries(${target} PRIVATE
waveshare
)
endif (BUILD_EPD)
if (BUILD_VIRTUAL_DISPLAY)
target_link_libraries(${target} PRIVATE sfml-system sfml-window sfml-graphics)
target_link_libraries(${target} PRIVATE
sfml-system
sfml-window
sfml-graphics
fmt::fmt
nlohmann_json::nlohmann_json
)
endif(BUILD_VIRTUAL_DISPLAY)

View File

@@ -1,2 +0,0 @@
#define BUILD_VIRTUAL_DISPLAY
/* #undef BUILD_EPD */

View File

@@ -17,6 +17,15 @@ namespace frame
{
}
void Image::Create(uint32_t pWidth, uint32_t pHeight)
{
mWidth = pWidth;
mHeight = pHeight;
mBuffer.clear();
mBuffer.resize(mWidth * mHeight);
}
uint8_t& Image::at(uint32_t x, uint32_t y)
{
return mBuffer.at(toInternal(x, y));
@@ -27,6 +36,13 @@ namespace frame
return mBuffer.at(toInternal(x, y));
}
void Image::operator=(Image const& image)
{
mHeight = image.mHeight;
mWidth = image.mWidth;
mBuffer = image.mBuffer;
}
size_t Image::toInternal(uint32_t x, uint32_t y) const
{
return x + mWidth * y;

View File

@@ -14,8 +14,13 @@ namespace frame
std::vector<uint8_t> mBuffer;
public:
Image() = default;
Image(uint32_t pWidth, uint32_t pHeight);
Image(Size size);
Image(Image const&) = default;
Image(Image&&) = default;
void Create(uint32_t pWidth, uint32_t pHeight);
uint8_t& at(uint32_t x, uint32_t y);
uint8_t const& at(uint32_t x, uint32_t y) const;
@@ -29,6 +34,8 @@ namespace frame
return mHeight;
}
void operator=(Image const& image);
private:
size_t toInternal(uint32_t x, uint32_t y) const;
};

54
frame/src/font/Font.cpp Normal file
View File

@@ -0,0 +1,54 @@
#include "Font.hpp"
#include <fstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace frame::font
{
std::shared_ptr<Font> Font::LoadFromFile(std::string_view file)
{
try
{
std::fstream file_data(std::string{file}, std::ios::in);
auto out = std::make_shared<Font>();
out->LoadFromStream(file_data);
return out;
}
catch(std::exception const& e)
{
return nullptr;
}
}
void Font::LoadFromStream(std::istream& os)
{
json file_data = json::parse(os);
name = file_data["name"];
for(auto& [key, el] : file_data["sizes"].items())
{
auto size = std::atoi(key.c_str());
Glyphs curren_glyphs;
lineSpacing[size] = el["LineSpacing"];
for(auto& [glyph_c, glyph_d] : el["Glyphs"].items())
{
curren_glyphs[glyph_c[0]] = std::move(Glyph{glyph_d});
}
sizes[size] = std::move(curren_glyphs);
}
}
Glyph const& Font::getGlyph(uint32_t size, char c) const
{
return sizes.at(size).at(c);
}
} // namespace frame::font

29
frame/src/font/Font.hpp Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include "Glyph.hpp"
#include <map>
#include <memory>
#include <string_view>
namespace frame::font
{
using Glyphs = std::map<char, Glyph>;
using LineSpacing = std::map<uint8_t, uint32_t>;
class Font
{
std::string name;
std::map<uint8_t, Glyphs> sizes;
LineSpacing lineSpacing;
public:
Font() = default;
static std::shared_ptr<Font> LoadFromFile(std::string_view file);
Glyph const& getGlyph(uint32_t size, char c) const;
protected:
void LoadFromStream(std::istream& os);
};
} // namespace frame::font

39
frame/src/font/Glyph.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "Glyph.hpp"
namespace frame::font
{
Glyph::Glyph(json const& data)
{
height = data["height"];
width = data["width"];
x_offset = data["x_offset"];
y_offset = data["y_offset"];
advance = data["advance"];
image.Create(width, height);
auto& image_data = data["data"];
int index = 0;
for(auto y = 0; y < height; ++y)
{
for(auto x = 0; x < width; ++x)
{
uint8_t i = image_data[index];
image.at(x, y) = i * 0xFF;
++index;
}
}
}
void Glyph::operator=(Glyph const& glyph)
{
image = glyph.image;
height = glyph.height;
width = glyph.width;
x_offset = glyph.x_offset;
y_offset = glyph.y_offset;
advance = glyph.advance;
}
} // namespace frame::font

28
frame/src/font/Glyph.hpp Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "../Image.hpp"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace frame::font
{
struct Glyph
{
Image image;
uint8_t height;
uint8_t width;
int8_t x_offset;
int8_t y_offset;
int8_t advance;
public:
Glyph() = default;
Glyph(json const& data);
Glyph(Glyph const&) = default;
Glyph(Glyph&&) = default;
void operator=(Glyph const& glyph);
};
} // namespace frame::font

View File

@@ -7,12 +7,15 @@
using namespace std::chrono_literals;
#include "display/Display.hpp"
#include "font/Font.hpp"
#include "render/RenderTarget.hpp"
int main()
{
constexpr double pi = 3.14159;
auto font = frame::font::Font::LoadFromFile("Fira Code.json");
auto display = frame::display::Create();
if(!display)
@@ -62,6 +65,8 @@ int main()
{110, (int)display->getSize().height - 10},
5);
target.DrawText("abcdefghijklmnopqrstuvwxyz", {100, 50}, *font, 14);
display->Display(target.getImage());
std::this_thread::sleep_for(10s);

View File

@@ -142,6 +142,46 @@ namespace frame::render
{BottomRight.x, BottomRight.y - lw});
}
void RenderTarget::DrawImage(Vector topLeft, Image const& image)
{
auto pos = topLeft;
for(auto y = 0; y < image.getHeight(); ++y)
{
for(auto x = 0; x < image.getWidth(); ++x)
{
DrawPixel({pos.x + x, pos.y + y}, (Color)image.at(x, y));
}
}
}
Vector RenderTarget::DrawGlyph(Vector centerLine,
font::Glyph const& g,
Color color)
{
auto const& height = g.height;
Vector topleft = centerLine;
topleft.x += g.x_offset;
topleft.y += g.y_offset;
DrawImage(topleft, g.image);
centerLine.x += g.advance;
return centerLine;
}
void RenderTarget::DrawText(std::string_view pText,
Vector pCenterLineStart,
font::Font const& pFont,
uint8_t size)
{
auto pos = pCenterLineStart;
for(auto c : pText)
{
pos = DrawGlyph(pos, pFont.getGlyph(size, c));
}
}
void RenderTarget::DrawPointsMirrorCircle(Vector const& center,
Vector const& pos,
Color color)

View File

@@ -3,6 +3,7 @@
#include "../Color.hpp"
#include "../Image.hpp"
#include "../Vector.hpp"
#include "../font/Font.hpp"
namespace frame::render
{
@@ -24,17 +25,35 @@ namespace frame::render
int32_t radius,
Color color = BLACK);
void DrawRectFilled(Vector const& TopLeft, Vector const& BottomRight, Color color = BLACK);
void DrawRectFilled(Vector const& TopLeft,
Vector const& BottomRight,
Color color = BLACK);
void DrawRect(Vector const& TopLeft, Vector const& BottomRight, uint8_t LineWidth, Color color = BLACK);
void DrawRect(Vector const& TopLeft,
Vector const& BottomRight,
uint8_t LineWidth,
Color color = BLACK);
void DrawImage(Vector topLeft, Image const& image);
Vector DrawGlyph(Vector centerLine,
font::Glyph const& g,
Color color = BLACK);
void DrawText(std::string_view pText,
Vector pCenterLineStart,
font::Font const& pFont,
uint8_t size);
Image const& getImage()
{
return image;
}
private:
void DrawPointsMirrorCircle(Vector const& center, Vector const& pos, Color color);
private:
void DrawPointsMirrorCircle(Vector const& center,
Vector const& pos,
Color color);
};
} // namespace frame::render

View File

@@ -1,7 +1,7 @@
{
"name": "frame",
"version": "1.0",
"dependencies": ["fmt"],
"dependencies": ["fmt", "nlohmann-json"],
"features": {
"virtual": {
"description": "Build Virtual Display",