#include #include #include #include "input_file.hpp" #include "renderers/pgm_renderer.hpp" #include "renderers/svg_renderer.hpp" #include /** * @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 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 `x` * @return Tuple of width and height */ static std::tuple 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 x"); 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(shapes, outputFile, width, height); else Render(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 << " " << std::endl; return 1; } Run(argv[1], argv[2], argv[3]); return 0; }