112 lines
2.6 KiB
C++
112 lines
2.6 KiB
C++
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <tuple>
|
|
|
|
#include "input_file.hpp"
|
|
#include "renderers/pgm_renderer.hpp"
|
|
#include "renderers/svg_renderer.hpp"
|
|
#include <charconv>
|
|
|
|
/**
|
|
* @brief Render shapes using a specific renderer and save to a file
|
|
*
|
|
* @tparam T Renderer type
|
|
* @param shapes Shapes to render
|
|
* @param path Output file path
|
|
* @param width Width
|
|
* @param height Height
|
|
*/
|
|
template <class T>
|
|
void Render(const shapes::Group& shapes, const std::filesystem::path& path, size_t width, size_t height)
|
|
{
|
|
T renderer(width, height);
|
|
shapes.Draw(renderer);
|
|
renderer.Save(path);
|
|
}
|
|
|
|
/**
|
|
* @brief Parse a single dimension from a string
|
|
*
|
|
* @param start Pointer to the start of the dimension string
|
|
* @param end Pointer to the end of the dimension string
|
|
* @return Parsed dimension
|
|
*/
|
|
static size_t ParseDim(const char* start, const char* end)
|
|
{
|
|
size_t val;
|
|
auto [ptr, ec] = std::from_chars(start, end, val);
|
|
|
|
if (ec != std::errc())
|
|
{
|
|
throw std::runtime_error("Cannot parse size");
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* Parse a size string
|
|
*
|
|
* @param sizeStr Size string in the format of `<width>x<height>`
|
|
* @return Tuple of width and height
|
|
*/
|
|
static std::tuple<size_t, size_t> ParseSize(const std::string& sizeStr)
|
|
{
|
|
auto xPos = sizeStr.find('x');
|
|
|
|
if (xPos == std::string::npos)
|
|
throw std::runtime_error("Size must be in format of <width>x<height>");
|
|
|
|
size_t width = ParseDim(sizeStr.data(), sizeStr.data() + xPos);
|
|
size_t height = ParseDim(sizeStr.data() + xPos + 1, sizeStr.data() + sizeStr.size());
|
|
|
|
return std::make_tuple(width, height);
|
|
}
|
|
|
|
/**
|
|
* @brief Run the drawing process
|
|
*/
|
|
static void Run(const std::string& inputFile, const std::string& outputFile, const std::string& sizeStr)
|
|
{
|
|
try
|
|
{
|
|
auto [width, height] = ParseSize(sizeStr);
|
|
|
|
InputFile file(inputFile);
|
|
shapes::Group shapes = file.Parse();
|
|
|
|
if (outputFile.ends_with(".svg"))
|
|
Render<SvgRenderer>(shapes, outputFile, width, height);
|
|
else
|
|
Render<PgmRenderer>(shapes, outputFile, width, height);
|
|
|
|
std::cout << "OK" << std::endl;
|
|
std::cout << file.GetNumProcessedCmds() << std::endl;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cerr << "Error: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Main entry point
|
|
*/
|
|
int main(int argc, char** argv)
|
|
{
|
|
if (argc < 4)
|
|
{
|
|
const char* command = "drawing";
|
|
|
|
if (argc > 0)
|
|
command = argv[0];
|
|
|
|
std::cerr << "Usage: " << command << " <input_file> <output_file> <size>" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
Run(argv[1], argv[2], argv[3]);
|
|
return 0;
|
|
}
|