Finalize
This commit is contained in:
parent
f84394fc0e
commit
9e103519d0
@ -14,16 +14,8 @@
|
||||
|
||||
InputFile::InputFile(const std::filesystem::path& path) : m_file(path), m_cmdsProcessed(0)
|
||||
{
|
||||
if (m_file.bad())
|
||||
{
|
||||
throw std::runtime_error("Cannot open " + path.string() + " for reading");
|
||||
}
|
||||
}
|
||||
|
||||
// istream >> operator for math::Vector
|
||||
static std::istream& operator>>(std::istream& is, math::Vector& vec)
|
||||
{
|
||||
return is >> vec.x >> vec.y;
|
||||
if (!m_file)
|
||||
throw std::runtime_error(std::format("Cannot open {} for reading", path.string()));
|
||||
}
|
||||
|
||||
// command name -> command handler map
|
||||
@ -53,12 +45,6 @@ const char* GetTypeName<float>()
|
||||
return "float";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* GetTypeName<math::Vector>()
|
||||
{
|
||||
return "vector";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* GetTypeName<std::string>()
|
||||
{
|
||||
@ -78,7 +64,7 @@ static T ReadVal(std::istream& is)
|
||||
T v;
|
||||
is >> v;
|
||||
|
||||
if (is.bad())
|
||||
if (!is)
|
||||
throw std::runtime_error(std::format("Could not parse {} from stream", GetTypeName<T>()));
|
||||
|
||||
return v;
|
||||
@ -166,7 +152,7 @@ shapes::Group InputFile::Parse()
|
||||
auto cmd = cmds.find(cmdName);
|
||||
|
||||
if (cmd == cmds.end())
|
||||
throw std::runtime_error("Unknown command: " + cmdName);
|
||||
throw std::runtime_error(std::format("Unknown command: {}", cmdName));
|
||||
|
||||
cmd->second(iss);
|
||||
++m_cmdsProcessed;
|
||||
|
||||
@ -2,64 +2,37 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
class Color
|
||||
using Color = uint8_t;
|
||||
|
||||
namespace colors
|
||||
{
|
||||
public:
|
||||
Color() : l{0} {}
|
||||
|
||||
Color(uint8_t l) : l{l} {}
|
||||
|
||||
uint8_t l{}; // luminence
|
||||
|
||||
void Blend(const Color& src, uint8_t alpha)
|
||||
{
|
||||
l = BlendChannel(l, src.l, alpha);
|
||||
// l = alpha;
|
||||
}
|
||||
|
||||
private:
|
||||
static uint8_t BlendChannel(uint8_t a, uint8_t b, uint8_t alpha)
|
||||
{
|
||||
return static_cast<uint8_t>(
|
||||
(static_cast<int>(a) * (255 - static_cast<int>(alpha)) + static_cast<int>(b) * static_cast<int>(alpha)) /
|
||||
255);
|
||||
}
|
||||
};
|
||||
constexpr Color BLACK{0};
|
||||
constexpr Color WHITE{1};
|
||||
} // namespace colors
|
||||
|
||||
class Bitmap
|
||||
{
|
||||
public:
|
||||
Bitmap(size_t width, size_t height, const Color& clearColor)
|
||||
Bitmap(size_t width, size_t height, Color clearColor)
|
||||
: m_width(width), m_height(height), m_data(width * height, clearColor)
|
||||
{
|
||||
}
|
||||
|
||||
// std::span<Color> operator[](size_t row)
|
||||
// {
|
||||
// return {&m_data[row * m_width], m_width};
|
||||
// };
|
||||
|
||||
// std::span<const Color> operator[](size_t row) const
|
||||
// {
|
||||
// return {&m_data[row * m_width], m_width};
|
||||
// };
|
||||
|
||||
Color* operator[](size_t row) { return &m_data[row * m_width]; };
|
||||
|
||||
const Color* operator[](size_t row) const { return &m_data[row * m_width]; };
|
||||
std::span<Color> operator[](size_t row) { return {&m_data[row * m_width], m_width}; };
|
||||
std::span<const Color> operator[](size_t row) const { return {&m_data[row * m_width], m_width}; };
|
||||
|
||||
size_t GetWidth() const { return m_width; }
|
||||
|
||||
size_t GetHeight() const { return m_height; }
|
||||
|
||||
void Put(int x, int y, const Color& color, uint8_t alpha)
|
||||
void SetPixel(int x, int y, Color color)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= m_width || y >= m_height)
|
||||
return; // out of bounds
|
||||
return; // out of bounds, ignore
|
||||
|
||||
(*this)[y][x].Blend(color, alpha);
|
||||
(*this)[y][x] = color;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
PgmRenderer::PgmRenderer(size_t width, size_t height) : m_bitmap(width, height, Color{0xFF}) {}
|
||||
PgmRenderer::PgmRenderer(size_t width, size_t height) : m_bitmap(width, height, colors::WHITE) {}
|
||||
|
||||
void PgmRenderer::DrawLine(const math::Vector& p0, const math::Vector& p1)
|
||||
{
|
||||
@ -47,13 +47,13 @@ void PgmRenderer::Save(const std::filesystem::path& path)
|
||||
file << "P2" << std::endl;
|
||||
file << "# KIV/CPP" << std::endl;
|
||||
file << m_bitmap.GetWidth() << ' ' << m_bitmap.GetHeight() << std::endl;
|
||||
file << 255 << std::endl;
|
||||
file << 1 << std::endl;
|
||||
|
||||
for (size_t y = 0; y < m_bitmap.GetHeight(); ++y)
|
||||
{
|
||||
for (size_t x = 0; x < m_bitmap.GetWidth(); ++x)
|
||||
{
|
||||
file << static_cast<int>(m_bitmap[y][x].l) << ' ';
|
||||
file << static_cast<int>(m_bitmap[y][x]) << ' ';
|
||||
}
|
||||
|
||||
file << std::endl;
|
||||
@ -62,9 +62,7 @@ void PgmRenderer::Save(const std::filesystem::path& path)
|
||||
|
||||
void PgmRenderer::RasterizeLine(int x0, int y0, int x1, int y1)
|
||||
{
|
||||
// TODO: fix
|
||||
const Color lineColor{0x00};
|
||||
float w = 2.0f;
|
||||
int w = 2; // thickness
|
||||
|
||||
int dx = abs(x1 - x0);
|
||||
int dy = abs(y1 - y0);
|
||||
@ -90,7 +88,7 @@ void PgmRenderer::RasterizeLine(int x0, int y0, int x1, int y1)
|
||||
{
|
||||
for (int j = -w / 2; j <= w / 2; j++)
|
||||
{
|
||||
m_bitmap.Put(x0 + i * ox, y0 + j * oy, lineColor, 0xFF);
|
||||
m_bitmap.SetPixel(x0 + i * ox, y0 + j * oy, colors::BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,10 +110,7 @@ void PgmRenderer::RasterizeLine(int x0, int y0, int x1, int y1)
|
||||
|
||||
void PgmRenderer::RasterizeCircle(int cx, int cy, int r)
|
||||
{
|
||||
// TODO: fix
|
||||
|
||||
const Color circleColor{0x00};
|
||||
float w = 2.0f;
|
||||
int w = 2; // thickness
|
||||
|
||||
int r_outer = r + w / 2;
|
||||
int r_inner = r - w / 2;
|
||||
@ -129,7 +124,7 @@ void PgmRenderer::RasterizeCircle(int cx, int cy, int r)
|
||||
int dist2 = x * x + y * y;
|
||||
if (dist2 <= r_outer * r_outer && dist2 >= r_inner * r_inner)
|
||||
{
|
||||
m_bitmap.Put(cx + x, cy + y, circleColor, 0xFF);
|
||||
m_bitmap.SetPixel(cx + x, cy + y, colors::BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,33 +1,40 @@
|
||||
#include "svg_renderer.hpp"
|
||||
|
||||
#include "math/constants.hpp"
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
|
||||
SvgRenderer::SvgRenderer(size_t width, size_t height) : m_width{width}, m_height{height}
|
||||
{
|
||||
// white bg
|
||||
m_out << " <rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\" />" << std::endl;
|
||||
m_out << R"SVG( <rect width="100%" height="100%" fill="#FFFFFF" />)SVG" << std::endl;
|
||||
}
|
||||
|
||||
void SvgRenderer::DrawLine(const math::Vector& p0, const math::Vector& p1)
|
||||
{
|
||||
m_out << " <line x1=\"" << p0.x << "\" y1=\"" << p0.y << "\" x2=\"" << p1.x << "\" y2=\"" << p1.y << "\" "
|
||||
<< "stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" />" << std::endl;
|
||||
m_out
|
||||
<< std::format(
|
||||
R"SVG( <line x1="{}" y1="{}" x2="{}" y2="{}" stroke="#000000" stroke-width="2" stroke-linecap="round" />)SVG",
|
||||
p0.x, p0.y, p1.x, p1.y)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void SvgRenderer::DrawRectangle(const math::Vector& pos, const math::Vector& size, float angle)
|
||||
{
|
||||
float angleDeg = angle * math::RAD_TO_DEG;
|
||||
|
||||
m_out << " <rect x=\"" << pos.x << "\" y=\"" << pos.y << "\" width=\"" << size.x << "\" height=\"" << size.y
|
||||
<< "\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" stroke-linejoin=\"round\" transform=\"rotate("
|
||||
<< angleDeg << ", " << pos.x << ", " << pos.y << ")\" />" << std::endl;
|
||||
m_out
|
||||
<< std::format(
|
||||
R"SVG( <rect x="{0}" y="{1}" width="{2}" height="{3}" fill="none" stroke="#000000" stroke-width="2" stroke-linejoin="round" transform="rotate({4}, {0}, {1})" />)SVG",
|
||||
pos.x, pos.y, size.x, size.y, angleDeg)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void SvgRenderer::DrawCircle(const math::Vector& center, float radius)
|
||||
{
|
||||
m_out << " <circle cx=\"" << center.x << "\" cy=\"" << center.y << "\" r=\"" << radius
|
||||
<< "\" fill=\"none\" stroke=\"#000000\" stroke-width=\"2\" />" << std::endl;
|
||||
m_out << std::format(R"SVG( <circle cx="{}" cy="{}" r="{}" fill="none" stroke="#000000" stroke-width="2" />)SVG",
|
||||
center.x, center.y, radius)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void SvgRenderer::Save(const std::filesystem::path& path)
|
||||
@ -38,9 +45,12 @@ void SvgRenderer::Save(const std::filesystem::path& path)
|
||||
{
|
||||
throw std::runtime_error{"Cannot open file for writing: " + path.string()};
|
||||
}
|
||||
|
||||
file << "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"" << m_width << "\" height=\"" << m_height
|
||||
<< "\" viewBox=\"0 0 " << m_width << " " << m_height << "\" role=\"img\" aria-label=\"KIV/CPP\">" << std::endl;
|
||||
|
||||
file
|
||||
<< std::format(
|
||||
R"SVG(<svg xmlns="http://www.w3.org/2000/svg" width="{0}" height="{1}" viewBox="0 0 {0} {1}" role="img" aria-label="KIV/CPP">)SVG",
|
||||
m_width, m_height)
|
||||
<< std::endl;
|
||||
|
||||
file << m_out.str();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user