Skip to content

Commit

Permalink
Add logging functionality for improved debugging and monitoring
Browse files Browse the repository at this point in the history
  • Loading branch information
sammycage committed Jun 6, 2024
1 parent 669abb9 commit 67e820d
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 37 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
libcurl4-openssl-dev \
libturbojpeg0-dev \
libwebp-dev \
libspdlog-dev \
ninja-build \
meson
Expand Down Expand Up @@ -62,6 +63,7 @@ jobs:
mingw-w64-x86_64-curl
mingw-w64-x86_64-libjpeg-turbo
mingw-w64-x86_64-libwebp
mingw-w64-x86_64-spdlog
mingw-w64-x86_64-ninja
mingw-w64-x86_64-meson
mingw-w64-x86_64-pkgconf
Expand Down
13 changes: 13 additions & 0 deletions include/plutobook.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,19 @@ typedef struct _plutobook_page_margins {
#define PLUTOBOOK_PAGE_MARGINS_MODERATE ((plutobook_page_margins_t){72, 54, 72, 54})
#define PLUTOBOOK_PAGE_MARGINS_WIDE ((plutobook_page_margins_t){72, 144, 72, 144})

typedef enum _plutobook_log_level {
PLUTOBOOK_LOG_LEVEL_TRACE = 0,
PLUTOBOOK_LOG_LEVEL_DEBUG = 1,
PLUTOBOOK_LOG_LEVEL_INFO = 2,
PLUTOBOOK_LOG_LEVEL_WARN = 3,
PLUTOBOOK_LOG_LEVEL_ERROR = 4,
PLUTOBOOK_LOG_LEVEL_CRITICAL = 5,
PLUTOBOOK_LOG_LEVEL_OFF = 6
} plutobook_log_level_t;

PLUTOBOOK_API plutobook_log_level_t plutobook_get_log_level(void);
PLUTOBOOK_API void plutobook_set_log_level(plutobook_log_level_t level);

typedef enum _plutobook_status {
PLUTOBOOK_STATUS_SUCCESS = 0,
PLUTOBOOK_STATUS_MEMORY_ERROR = 1,
Expand Down
6 changes: 6 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ project('plutobook', 'cpp',
default_options: ['cpp_std=c++20']
)

spdlog_dep = dependency('spdlog',
required: true,
fallback: ['spdlog', 'spdlog_dep']
)

expat_dep = dependency('expat',
required: true,
fallback: ['expat', 'expat_dep']
Expand Down Expand Up @@ -50,6 +55,7 @@ cairo_dep = dependency('cairo',
)

plutobook_deps = [
spdlog_dep,
expat_dep,
icu_dep,
freetype_dep,
Expand Down
54 changes: 50 additions & 4 deletions source/plutobook.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "plutobook.hpp"

#include <spdlog/spdlog.h>
#include <cairo-pdf.h>

#include <cstring>
#include <cstdlib>
#include <cairo-pdf.h>

int plutobook_version()
{
Expand All @@ -19,6 +21,16 @@ const char* plutobook_about()
return "PlutoBook " PLUTOBOOK_VERSION_STRING " (https://github.com/plutoprint)";
}

plutobook_log_level_t plutobook_get_log_level(void)
{
return static_cast<plutobook_log_level_t>(spdlog::get_level());
}

void plutobook_set_log_level(plutobook_log_level_t level)
{
spdlog::set_level(static_cast<spdlog::level::level_enum>(level));
}

struct _plutobook_canvas {
cairo_surface_t* surface;
cairo_t* context;
Expand All @@ -27,7 +39,8 @@ struct _plutobook_canvas {
static plutobook_canvas_t* plutobook_canvas_create(cairo_surface_t* surface)
{
auto context = cairo_create(surface);
if(cairo_status(context)) {
if(auto status = cairo_status(context)) {
spdlog::error("cairo error: {}", cairo_status_to_string(status));
cairo_surface_destroy(surface);
return nullptr;
}
Expand All @@ -49,39 +62,56 @@ void plutobook_canvas_destroy(plutobook_canvas_t* canvas)
std::free(canvas);
}

#define CHECK_CANVAS_SURFACE_ERROR(canvas) do { \
if(auto status = cairo_surface_status(canvas->surface)) { \
spdlog::error("cairo error: {}", cairo_status_to_string(status)); \
} \
} while(0)

#define CHECK_CANVAS_CONTEXT_ERROR(canvas) do { \
if(auto status = cairo_status(canvas->context)) { \
spdlog::error("cairo error: {}", cairo_status_to_string(status)); \
} \
} while(0)

void plutobook_canvas_flush(plutobook_canvas_t* canvas)
{
if(canvas == NULL)
return;
cairo_surface_flush(canvas->surface);
CHECK_CANVAS_SURFACE_ERROR(canvas);
}

void plutobook_canvas_finish(plutobook_canvas_t* canvas)
{
if(canvas == NULL)
return;
cairo_surface_finish(canvas->surface);
CHECK_CANVAS_SURFACE_ERROR(canvas);
}

void plutobook_canvas_translate(plutobook_canvas_t* canvas, float tx, float ty)
{
if(canvas == nullptr)
return;
cairo_translate(canvas->context, tx, ty);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_scale(plutobook_canvas_t* canvas, float sx, float sy)
{
if(canvas == nullptr)
return;
cairo_scale(canvas->context, sx, sy);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_rotate(plutobook_canvas_t* canvas, float angle)
{
if(canvas == nullptr)
return;
cairo_rotate(canvas->context, angle);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_transform(plutobook_canvas_t* canvas, float a, float b, float c, float d, float e, float f)
Expand All @@ -90,6 +120,7 @@ void plutobook_canvas_transform(plutobook_canvas_t* canvas, float a, float b, fl
return;
cairo_matrix_t matrix = {a, b, c, d, e, f};
cairo_transform(canvas->context, &matrix);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_set_matrix(plutobook_canvas_t* canvas, float a, float b, float c, float d, float e, float f)
Expand All @@ -98,13 +129,15 @@ void plutobook_canvas_set_matrix(plutobook_canvas_t* canvas, float a, float b, f
return;
cairo_matrix_t matrix = {a, b, c, d, e, f};
cairo_set_matrix(canvas->context, &matrix);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_reset_matrix(plutobook_canvas_t* canvas)
{
if(canvas == nullptr)
return;
cairo_identity_matrix(canvas->context);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_clip_rect(plutobook_canvas_t* canvas, float x, float y, float width, float height)
Expand All @@ -113,6 +146,7 @@ void plutobook_canvas_clip_rect(plutobook_canvas_t* canvas, float x, float y, fl
return;
cairo_rectangle(canvas->context, x, y, width, height);
cairo_clip(canvas->context);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_clear_surface(plutobook_canvas_t* canvas, float red, float green, float blue, float alpha)
Expand All @@ -124,20 +158,23 @@ void plutobook_canvas_clear_surface(plutobook_canvas_t* canvas, float red, float
cairo_set_operator(canvas->context, CAIRO_OPERATOR_SOURCE);
cairo_paint(canvas->context);
cairo_restore(canvas->context);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_save_state(plutobook_canvas_t* canvas)
{
if(canvas == nullptr)
return;
cairo_save(canvas->context);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

void plutobook_canvas_restore_state(plutobook_canvas_t* canvas)
{
if(canvas == nullptr)
return;
cairo_restore(canvas->context);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

cairo_surface_t* plutobook_canvas_get_surface(const plutobook_canvas_t* canvas)
Expand Down Expand Up @@ -210,17 +247,23 @@ plutobook_status_t plutobook_image_canvas_write_to_png(const plutobook_canvas_t*
{
if(canvas == nullptr)
return PLUTOBOOK_STATUS_WRITE_ERROR;
if(cairo_surface_write_to_png(canvas->surface, filename))
if(cairo_surface_write_to_png(canvas->surface, filename)) {
CHECK_CANVAS_SURFACE_ERROR(canvas);
return PLUTOBOOK_STATUS_WRITE_ERROR;
}

return PLUTOBOOK_STATUS_SUCCESS;
}

plutobook_status_t plutobook_image_canvas_write_to_png_stream(const plutobook_canvas_t* canvas, plutobook_stream_write_callback_t callback, void* closure)
{
if(canvas == nullptr)
return PLUTOBOOK_STATUS_WRITE_ERROR;
if(cairo_surface_write_to_png_stream(canvas->surface, (cairo_write_func_t)(callback), closure))
if(cairo_surface_write_to_png_stream(canvas->surface, (cairo_write_func_t)(callback), closure)) {
CHECK_CANVAS_SURFACE_ERROR(canvas);
return PLUTOBOOK_STATUS_WRITE_ERROR;
}

return PLUTOBOOK_STATUS_SUCCESS;
}

Expand All @@ -239,20 +282,23 @@ void plutobook_pdf_canvas_set_metadata(plutobook_canvas_t* canvas, plutobook_pdf
if(canvas == nullptr)
return;
cairo_pdf_surface_set_metadata(canvas->surface, (cairo_pdf_metadata_t)(name), value);
CHECK_CANVAS_SURFACE_ERROR(canvas);
}

void plutobook_pdf_canvas_set_size(plutobook_canvas_t* canvas, plutobook_page_size_t size)
{
if(canvas == nullptr)
return;
cairo_pdf_surface_set_size(canvas->surface, size.width, size.height);
CHECK_CANVAS_SURFACE_ERROR(canvas);
}

void plutobook_pdf_canvas_show_page(plutobook_canvas_t* canvas)
{
if(canvas == nullptr)
return;
cairo_show_page(canvas->context);
CHECK_CANVAS_CONTEXT_ERROR(canvas);
}

struct _plutobook_resource_data {
Expand Down
35 changes: 24 additions & 11 deletions source/plutobook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
#include "replacedbox.h"
#include "graphicscontext.h"

#include <spdlog/spdlog.h>
#include <fstream>
#include <cmath>

namespace plutobook {

class FileOutputStream final : public OutputStream {
public:
explicit FileOutputStream(const std::string& filename)
: m_stream(filename, std::ios::binary)
{}
explicit FileOutputStream(const std::string& filename);

bool isOpen() const { return m_stream.is_open(); }
bool write(const char* data, size_t length) final;
Expand All @@ -25,6 +24,14 @@ class FileOutputStream final : public OutputStream {
std::ofstream m_stream;
};

FileOutputStream::FileOutputStream(const std::string& filename)
: m_stream(filename, std::ios::binary)
{
if(!m_stream.is_open()) {
spdlog::error("unable to open file: {}", filename);
}
}

bool FileOutputStream::write(const char* data, size_t length)
{
m_stream.write(data, length);
Expand Down Expand Up @@ -283,8 +290,6 @@ PageSize Book::pageSizeAt(uint32_t pageIndex) const
bool Book::loadUrl(const std::string_view& url, const std::string_view& userStyle, const std::string_view& userScript)
{
auto completeUrl = ResourceLoader::completeUrl(url);
if(completeUrl.isEmpty())
return false;
std::string mimeType;
std::string textEncoding;
std::vector<char> content;
Expand All @@ -306,6 +311,7 @@ bool Book::loadImage(const char* data, size_t length, const std::string_view& mi
{
auto image = ImageResource::decode(data, length, mimeType, textEncoding, baseUrl);
if(image == nullptr) {
spdlog::error("unable to decode image data");
return false;
}

Expand All @@ -323,8 +329,11 @@ bool Book::loadImage(const char* data, size_t length, const std::string_view& mi
assert(imageElement && imageElement->tagName() == imgTag);

auto box = imageElement->box();
if(box == nullptr)
if(box == nullptr) {
spdlog::error("invalid img element");
return false;
}

auto& imageBox = to<ImageBox>(*box);
imageBox.setImage(std::move(image));
return true;
Expand Down Expand Up @@ -444,8 +453,11 @@ bool Book::writeToPdf(plutobook_stream_write_callback_t callback, void* closure,
{
fromPage = std::max(1u, std::min(fromPage, pageCount()));
toPage = std::max(1u, std::min(toPage, pageCount()));
if(pageStep == 0 || (pageStep > 0 && fromPage > toPage) || (pageStep < 0 && fromPage < toPage))
if(pageStep == 0 || (pageStep > 0 && fromPage > toPage) || (pageStep < 0 && fromPage < toPage)) {
spdlog::error("invalid page rage: from={} to={} step={}", fromPage, toPage, pageStep);
return false;
}

PDFCanvas canvas(callback, closure, pageSizeAt(fromPage - 1));
canvas.scale(PLUTOBOOK_UNITS_PX, PLUTOBOOK_UNITS_PX);
canvas.setTitle(m_title);
Expand All @@ -455,9 +467,7 @@ bool Book::writeToPdf(plutobook_stream_write_callback_t callback, void* closure,
canvas.setKeywords(m_keywords);
canvas.setCreationDate(m_creationDate);
canvas.setModificationDate(m_modificationDate);
for(auto pageIndex = fromPage; pageStep > 0 ? pageIndex <= toPage : pageIndex >= toPage; pageIndex += pageStep) {
if(!canvas.isGood())
break;
for(auto pageIndex = fromPage; canvas.isGood() && (pageStep > 0 ? pageIndex <= toPage : pageIndex >= toPage); pageIndex += pageStep) {
canvas.setPageSize(pageSizeAt(pageIndex - 1));
renderPage(canvas, pageIndex - 1);
canvas.showPage();
Expand All @@ -483,8 +493,11 @@ bool Book::writeToPng(plutobook_stream_write_callback_t callback, void* closure,
{
int width = std::ceil(documentWidth());
int height = std::ceil(documentHeight());
if(width <= 0 || height <= 0)
if(width <= 0 || height <= 0) {
spdlog::error("invalid document size");
return false;
}

ImageCanvas canvas(width, height, format);
renderDocument(canvas, 0, 0, width, height);
return canvas.writeToPng(callback, closure);
Expand Down
Loading

0 comments on commit 67e820d

Please sign in to comment.