From 7a3d59e03e980cfdd220f13f8b41a1c068b7231b Mon Sep 17 00:00:00 2001 From: cat Date: Wed, 23 Jul 2025 02:47:42 +0300 Subject: [PATCH] Added entireity of utility and generate-report(only works with PNG for now) --- CMakeLists.txt | 3 +- assets/report_bumper.png | Bin 0 -> 16731 bytes src/Commands/GenerativeCommands.cpp | 28 +++++----- src/Utility/CairoGenerate.cpp | 80 ++++++++++++++++++++++++++++ src/Utility/CairoTools.cpp | 39 ++++++++++++++ src/Utility/CairoTools.hpp | 31 +++++++++++ src/Utility/Utility.cpp | 3 ++ 7 files changed, 168 insertions(+), 16 deletions(-) create mode 100644 assets/report_bumper.png create mode 100644 src/Utility/CairoGenerate.cpp create mode 100644 src/Utility/CairoTools.cpp create mode 100644 src/Utility/CairoTools.hpp create mode 100644 src/Utility/Utility.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c5a1f39..6463723 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,8 @@ project(TheBartender VERSION 0.3) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) # Create an executable -add_executable(${PROJECT_NAME} src/Base/Entry.cpp src/Commands.cpp) +add_executable(${PROJECT_NAME} src/Base/Entry.cpp src/Commands.cpp + src/Utility/Utility.cpp) # Find our pre-installed DPP package (using FindDPP.cmake). find_package(DPP REQUIRED) diff --git a/assets/report_bumper.png b/assets/report_bumper.png new file mode 100644 index 0000000000000000000000000000000000000000..50fd43081106e7ea13cd0f66e6b860694f4d4ced GIT binary patch literal 16731 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 S%>n2Ez{p4_idTz%3H*Pw|3Hxd literal 0 HcmV?d00001 diff --git a/src/Commands/GenerativeCommands.cpp b/src/Commands/GenerativeCommands.cpp index 6229e9c..b59c703 100644 --- a/src/Commands/GenerativeCommands.cpp +++ b/src/Commands/GenerativeCommands.cpp @@ -1,4 +1,5 @@ #include "../Common.hpp" +#include "../Utility/CairoTools.hpp" #include #include @@ -9,24 +10,10 @@ #include #include -#include - #include #include #include -void pngToCairoSurface(std::string data) { - cairo_surface_t *image = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 200); -} -void jpegToCairoSurface(std::string data) {} -void webpToCairoSurface(std::string data) {} - -std::unordered_map> - supportedImageFileTypes{{"image/png", pngToCairoSurface}, - {"image/jpeg", jpegToCairoSurface}, - {"image/webp", webpToCairoSurface}}; - void commandGenerateReport(const dpp::slashcommand_t &event, dpp::cluster &bot) { event.thinking(); @@ -38,7 +25,14 @@ void commandGenerateReport(const dpp::slashcommand_t &event, bot.request( file.url, dpp::http_method::m_get, [event, &bot, fileType](const dpp::http_request_completion_t &result) { - fileType->second(result.body); + std::string responseData = GenerateReportImage( + fileType->second( + result.body), // Image itself processed for cario to handle + std::get(event.get_parameter("headline"))); + + dpp::message response(event.command.channel_id, ""); + response.add_file("report.png", responseData); + event.edit_response(response); }); } else { event.edit_response( @@ -46,3 +40,7 @@ void commandGenerateReport(const dpp::slashcommand_t &event, " is not allowed. Only PNG, JPEG, and WEBP are allowed!"); } } + +// +// ACTUAL GENERATION STARTS HERE +// diff --git a/src/Utility/CairoGenerate.cpp b/src/Utility/CairoGenerate.cpp new file mode 100644 index 0000000..87c34af --- /dev/null +++ b/src/Utility/CairoGenerate.cpp @@ -0,0 +1,80 @@ +#include "CairoTools.hpp" + +std::string GenerateReportImage(cairo_surface_t *background, + std::string headline) { + cairo_surface_t *surface = cairo_image_surface_create( + CAIRO_FORMAT_ARGB32, REPORT_WIDTH, REPORT_HEIGHT); + + cairo_t *ctx = cairo_create(surface); + cairo_set_source_rgb(ctx, 0, 0, 0); + cairo_paint(ctx); + int imgW = 0, imgH = 0; + + // Background Image + cairo_save(ctx); + imgW = cairo_image_surface_get_width(background); + imgH = cairo_image_surface_get_height(background); + + cairo_scale(ctx, (double)REPORT_WIDTH / imgW, + (double)(REPORT_HEIGHT - REPORT_HEIGHT_OFFSET) / imgH); + cairo_set_source_surface(ctx, background, 0, 0); + cairo_paint(ctx); + cairo_restore(ctx); + + // Gradient + cairo_pattern_t *gradient = + cairo_pattern_create_linear(0, 0, 0, REPORT_HEIGHT); + cairo_pattern_add_color_stop_rgba(gradient, 0.85, 0, 0, 0, 1); + cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 0, 0, 0); + cairo_rectangle(ctx, 0, 0, REPORT_WIDTH, REPORT_HEIGHT); + cairo_set_source(ctx, gradient); + cairo_fill(ctx); + + // Bumper + cairo_save(ctx); + cairo_surface_t *bumper = + cairo_image_surface_create_from_png(REPORT_RESOURCE_BUMPER_PATH); + + imgW = cairo_image_surface_get_width(bumper); + imgH = cairo_image_surface_get_height(bumper); + + cairo_scale(ctx, (double)REPORT_WIDTH / imgW, 1.5); + cairo_set_source_surface(ctx, bumper, 0, REPORT_HEIGHT - (imgH * 7.1)); + cairo_paint(ctx); + cairo_restore(ctx); + + // Text + cairo_select_font_face(ctx, "Steelfish", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(ctx, REPORT_TEXT_FONT_SIZE); + + // Iteration 3 + std::stringstream text(headline + " "); + + std::string output, part; + std::vector outputList; + while (text.tellp() == std::streampos(0)) { + std::getline(text, part, ' '); + if (output.length() + part.length() < REPORT_TEXT_LENGTH) { + output += part + ' '; + continue; + } + outputList.push_back(output); + output = part + ' '; + } + outputList.push_back(output); + + // Display Text + int lineCount = 0; + for (std::string line : outputList) { + cairo_move_to(ctx, REPORT_TEXT_START_X, + REPORT_HEIGHT - + (REPORT_TEXT_JUMP_Y * (outputList.size() - lineCount++))); + cairo_set_source_rgb(ctx, CAIRO_TEXT_WHITE); + cairo_show_text(ctx, line.c_str()); + } + + std::string data; + cairo_surface_write_to_png_stream(surface, cairoOutputAsPNGStream, &data); + return data; +} diff --git a/src/Utility/CairoTools.cpp b/src/Utility/CairoTools.cpp new file mode 100644 index 0000000..4091316 --- /dev/null +++ b/src/Utility/CairoTools.cpp @@ -0,0 +1,39 @@ +#include "CairoTools.hpp" + +std::unordered_map> + supportedImageFileTypes{{"image/png", pngToCairoSurface}, + {"image/jpeg", jpegToCairoSurface}, + {"image/webp", webpToCairoSurface}}; + +cairo_status_t cairoReadPNGdata(void *closure, unsigned char *data, + unsigned int length) { + std::string *imageData = static_cast(closure); + static size_t offset = 0; + + if (offset + length > imageData->size()) { + return CAIRO_STATUS_READ_ERROR; + } + + memcpy(data, imageData->data() + offset, length); + offset += length; + return CAIRO_STATUS_SUCCESS; +} + +cairo_status_t cairoOutputAsPNGStream(void *closure, const unsigned char *data, + unsigned int length) { + std::string *output = static_cast(closure); + output->append(reinterpret_cast(data), length); + return CAIRO_STATUS_SUCCESS; +} + +cairo_surface_t *pngToCairoSurface(const std::string &data) { + return cairo_image_surface_create_from_png_stream( + cairoReadPNGdata, const_cast(&data)); +} +cairo_surface_t *jpegToCairoSurface(std::string data) { + return cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 200); +} +cairo_surface_t *webpToCairoSurface(std::string data) { + return cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 200); +} diff --git a/src/Utility/CairoTools.hpp b/src/Utility/CairoTools.hpp new file mode 100644 index 0000000..1ac1dcf --- /dev/null +++ b/src/Utility/CairoTools.hpp @@ -0,0 +1,31 @@ +#include +#include +#include + +#define REPORT_WIDTH 1000 +#define REPORT_HEIGHT 1200 +#define REPORT_HEIGHT_OFFSET 200 +#define REPORT_TEXT_START_X 40 +#define REPORT_TEXT_JUMP_Y 120 +#define REPORT_TEXT_FONT_SIZE 120.0 +#define REPORT_TEXT_LENGTH 26 +#define REPORT_RESOURCE_BUMPER_PATH "./assets/report_bumper.png" +#define CAIRO_TEXT_WHITE 0.87, 0.87, 0.87 + +std::string GenerateReportImage(cairo_surface_t *background, + std::string headline); + +// File type management +cairo_status_t cairoReadPNGdata(void *closure, unsigned char *data, + unsigned int length); + +cairo_status_t cairoOutputAsPNGStream(void *closure, const unsigned char *data, + unsigned int length); + +cairo_surface_t *pngToCairoSurface(const std::string &data); +cairo_surface_t *jpegToCairoSurface(std::string data); +cairo_surface_t *webpToCairoSurface(std::string data); + +extern std::unordered_map> + supportedImageFileTypes; diff --git a/src/Utility/Utility.cpp b/src/Utility/Utility.cpp new file mode 100644 index 0000000..7a02739 --- /dev/null +++ b/src/Utility/Utility.cpp @@ -0,0 +1,3 @@ +// Unity Build +#include "CairoGenerate.cpp" +#include "CairoTools.cpp"