diff options
| author | Matthias Melcher <github@matthiasm.com> | 2025-12-28 21:37:23 +0100 |
|---|---|---|
| committer | Matthias Melcher <github@matthiasm.com> | 2025-12-28 21:37:30 +0100 |
| commit | f5e7d62f90f5eb88afad45d56017c42835149d0c (patch) | |
| tree | d1fae5330c7c107776626466e17aabc3844e6f84 /util/code_snapshot.cxx | |
| parent | 22c17302616acad9e4eb735d897948dee28942ae (diff) | |
Generate code block documentation using FLTK (#1353)
The Doxygen-to-pdf toolchain can not easily generate
pdf's with Japanese and Chinese characters. This patch
generates code blocks by rendering them in FLTK.
Diffstat (limited to 'util/code_snapshot.cxx')
| -rw-r--r-- | util/code_snapshot.cxx | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/util/code_snapshot.cxx b/util/code_snapshot.cxx new file mode 100644 index 000000000..a8a2f2cae --- /dev/null +++ b/util/code_snapshot.cxx @@ -0,0 +1,159 @@ +// +// PDF documentation tool to generate a png image from a Doxygen `@code` +// segment with international characters for the Fast Light Tool Kit (FLTK). +// +// Copyright 2025 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +// +// Our documentation for the FLTK unicode contains international characters +// to illustrate use of non ASCII characters in the GUI. To generate PDF +// output, Doxygen uses LaTeX which can not easily handle UTF-8 characters in +// beyond Western encoding. This tool generates PNG images from code segments +// containing international characters so that they can be included in the +// PDF documentation instead of the code segments with UTF-8 characters. +// + +#include <stdio.h> + +#include <FL/Fl_Window.H> +#include <FL/Fl_Group.H> +#include <FL/filename.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Image_Surface.H> +#include <FL/Fl_PNG_Image.H> + +#include "../fluid/widgets/Code_Editor.h" +#include "../fluid/widgets/Code_Viewer.h" +#include "../fluid/widgets/Style_Parser.h" + +Fl_Window* window = nullptr; +Fl_Group* group = nullptr; +fld::widget::Code_Viewer* code_viewer = nullptr; + +void create_window() { + window = new Fl_Window(1024, 100); + group = new Fl_Group(0, 0, 1024, 100); + group->color(0xf7f7ff00); + group->box(FL_FLAT_BOX); + + code_viewer = new fld::widget::Code_Viewer(5, 5, 1014, 94); + code_viewer->box(FL_FLAT_BOX); + code_viewer->color(0xf7f7ff00); + code_viewer->textsize(30); + + window->resizable(group); + group->resizable(code_viewer); +} + +void save_snapshot(const char* code, const char* filename) +{ +// fprintf(stderr, "\\code\n%s\n\\endcode\n", code); + + code_viewer->buffer()->text(code); + int n_lines = 1; + for (const char* s=code; *s; ++s) if (*s == '\n') n_lines++; + // 300 dpi for 7 inches = 2000 pixels + window->size(2100, 6 + 34*n_lines ); + + // Generate the Image Surface + Fl_Image_Surface *srfc = new Fl_Image_Surface(window->w(), window->h()); + + // Draw the window and its content + Fl_Image_Surface::push_current(srfc); + srfc->draw(group, 0, 0); + fl_rect(0, 0, window->w(), window->h(), 0xccccff00); + Fl_Image_Surface::pop_current(); + +// fprintf(stderr, " Saving to \"%s\".\n", filename); + + // Write the generated image + Fl_RGB_Image *img = srfc->image(); + fl_write_png(filename, img); + + // Clean up + delete img; + delete srfc; +} + +/** + Main entry point for the PDF documentation helper tool. + + The app scans the input file for the `\\code_international{"filename"}` + directive, reads the following code segment until + `\\endcode_international`, and generates a PNG image file with the given + filename containing the code segment rendered with FLTK's + code rendering capabilities. + + \param argc Argument count + \param argv a list of input files with documentation in Doxygen format + \return Exit code (0 for success, non-zero for failure) +*/ +int main(int argc, char *argv[]) +{ + int ret = 0; + char line[1024]; + char cwd[FL_PATH_MAX]; + +// fl_getcwd(cwd, FL_PATH_MAX-1); +// fprintf(stderr, "code_snapshot:\n"); +// fprintf(stderr, "Working directory is \"%s\".\n", cwd); + + create_window(); + + for (int i = 1; i < argc; i++) { + FILE* f = fl_fopen(argv[i], "rb"); + if (!f) { + fl_getcwd(cwd, FL_PATH_MAX-1); + fprintf(stderr, "code_snapshot:\nCan't open file \"%s\".\n", argv[i]); + fprintf(stderr, "Working directory is \"%s\".\n", cwd); + ret = -1; + break; + } + +// fprintf(stderr, "Reading \"%s\".\n", argv[i]); + + std::string code; + std::string filename; + bool in_code_block = false; + for (;;) { + fgets(line, 1023, f); + if (feof(f)) break; + if (in_code_block) { + if (strstr(line, "\\endcode_international")) { + if (!code.empty()) { + code.resize( code.size()-1 ); + save_snapshot(code.c_str(), filename.c_str()); + } + in_code_block = false; + } else { + code += line; + } + } else { + if (strstr(line, "\\code_international")) { + const char* fn_start = strstr(line, "{\""); + const char* fn_end = strstr(line, "\"}"); + if (fn_start && fn_end && (fn_end > fn_start)) { + filename = std::string(fn_start+2, fn_end-fn_start-2); + in_code_block = true; + } + } + } + } + fclose(f); + } + + delete window; + + return ret; +} |
