diff --git a/CMake/pugixml.cmake b/CMake/pugixml.cmake index fd5f750..b848487 100644 --- a/CMake/pugixml.cmake +++ b/CMake/pugixml.cmake @@ -1,4 +1,4 @@ -if(NOT TARGET pugixml) +if(NOT TARGET pugixml::static) include(FetchContent) FetchContent_Declare( diff --git a/Libraries/Kanimaji/CMakeLists.txt b/Libraries/Kanimaji/CMakeLists.txt index 7c72c1b..512379f 100644 --- a/Libraries/Kanimaji/CMakeLists.txt +++ b/Libraries/Kanimaji/CMakeLists.txt @@ -12,7 +12,7 @@ target_link_libraries(Kanimaji KVGToolsCommon PRIVATE - pugixml + pugixml::static ) target_include_directories(Kanimaji diff --git a/Libraries/Kanimaji/Include/Kanimaji/Kanimaji.hpp b/Libraries/Kanimaji/Include/Kanimaji/Kanimaji.hpp index 79d3d9b..024e9f2 100644 --- a/Libraries/Kanimaji/Include/Kanimaji/Kanimaji.hpp +++ b/Libraries/Kanimaji/Include/Kanimaji/Kanimaji.hpp @@ -13,9 +13,11 @@ namespace Kanimaji std::string Animate(const std::string& source, const AnimationSettings& settings = AnimationSettings::Default()); - void RemoveStrokeNumbers(const std::string& source, const std::string& destination); + void RemoveStrokeNumbers(const std::string& source, const std::string& destination, + const RemovalSetttings& settings = RemovalSetttings::Default()); - std::string RemoveStrokeNumbers(const std::string& source); + std::string RemoveStrokeNumbers(const std::string& source, + const RemovalSetttings& settings = RemovalSetttings::Default()); } #endif // KANIMAJI_KANIMAJI_HPP diff --git a/Libraries/Kanimaji/Include/Kanimaji/Settings.hpp b/Libraries/Kanimaji/Include/Kanimaji/Settings.hpp index 47496fa..53f8597 100644 --- a/Libraries/Kanimaji/Include/Kanimaji/Settings.hpp +++ b/Libraries/Kanimaji/Include/Kanimaji/Settings.hpp @@ -49,6 +49,13 @@ namespace Kanimaji static AnimationSettings Default(); }; + + struct RemovalSetttings + { + StrokeStyle Style; + + static RemovalSetttings Default(); + }; } #endif // KANIMAJI_CONFIG_HPP diff --git a/Libraries/Kanimaji/Source/Kanimaji.cpp b/Libraries/Kanimaji/Source/Kanimaji.cpp index 3bf8034..d10eadb 100644 --- a/Libraries/Kanimaji/Source/Kanimaji.cpp +++ b/Libraries/Kanimaji/Source/Kanimaji.cpp @@ -12,42 +12,55 @@ namespace Kanimaji { namespace { - using namespace std::string_view_literals; - constexpr auto StrokeProgressionFormat = + constexpr std::string_view StaticStrokeStyleFormat( + "fill:none;stroke:{};stroke-width:{};stroke-linecap:round;stroke-linejoin:round;" + ); + + constexpr std::string_view StrokeProgressionFormat( " " "@keyframes stroke-{} {{ " "0.000% {{ stroke-dashoffset: {:.3f}; }} " "{:.3f}% {{ stroke-dashoffset: {:.3f}; }} " "{:.3f}% {{ stroke-dashoffset: 0; }} " - "100.000% {{ stroke-dashoffset: 0; }} }}\n"sv; - constexpr auto AnimationVisibilityFormat = + "100.000% {{ stroke-dashoffset: 0; }} }}\n" + ); + + constexpr std::string_view AnimationVisibilityFormat( " " "@keyframes display-{} {{ " "{:.3f}% {{ visibility: hidden; }} " - "{:.3f}% {{ stroke: {}; }} }}\n"sv; - constexpr auto AnimationProgressionFormat = + "{:.3f}% {{ stroke: {}; }} }}\n" + ); + + constexpr std::string_view AnimationProgressionFormat( " " "#{} {{ " "stroke-dasharray: {:.3f} {:.3f}; " "stroke-dashoffset: 0; " "animation: stroke-{} {:.3f}s {} infinite, " - "display-{} {:.3f}s step-start infinite; }}\n"sv; - constexpr auto BrushVisibilityFormat = + "display-{} {:.3f}s step-start infinite; }}\n" + ); + + constexpr std::string_view BrushVisibilityFormat( " " "@keyframes display-brush-{} {{ " "{:.3f}% {{ visibility: hidden; }} " "{:.3f}% {{ visibility: visible; }} " - "100.000% {{ visibility: hidden; }} }}\n"sv; - constexpr auto BrushProgressionFormat = + "100.000% {{ visibility: hidden; }} }}\n" + ); + + constexpr std::string_view BrushProgressionFormat( " " "#{}, #{} {{ " "stroke-dasharray: 0 {:.3f}; " "animation: stroke-{} {:.3f}s {} infinite, " - "display-brush-{} {:.3f}s step-start infinite; }}\n"sv; + "display-brush-{} {:.3f}s step-start infinite; }}\n" + ); - constexpr auto StylesHeader = + constexpr std::string_view StylesHeader( "\n " - "/* Styles generated automatically by Kanimaji, please avoid editing manually. */\n"sv; + "/* Styles generated automatically by Kanimaji, please avoid editing manually. */\n" + ); double AsSeconds(auto duration) { return std::max(0.0, duration.count()); @@ -65,8 +78,7 @@ namespace Kanimaji pugi::xml_node newGroup = svg.append_child("g"); newGroup.append_attribute("id") = name; newGroup.append_attribute("style") = std::format( - "fill:none;stroke:{};stroke-width:{};stroke-linecap:round;stroke-linejoin:round;", - config.Colour.ToHex(), config.Width + StaticStrokeStyleFormat, config.Colour.ToHex(), config.Width ); return newGroup; } @@ -270,7 +282,8 @@ namespace Kanimaji return str.str(); } - void RemoveStrokeNumbers(const std::string& source, const std::string& destination) + void RemoveStrokeNumbers(const std::string& source, const std::string& destination, + const RemovalSetttings& settings) { pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(source.c_str(), pugi::parse_full); @@ -284,6 +297,13 @@ namespace Kanimaji throw Error("Unexpected document format: Expected to find a SVG element"); } + pugi::xml_node pathsGroup = svg.find_child([](pugi::xml_node& node) { + return std::string_view(node.attribute("id").as_string()).contains("StrokePaths"); + }); + pathsGroup.attribute("style") = std::format( + StaticStrokeStyleFormat, settings.Style.Colour.ToHex(), settings.Style.Width + ); + RemoveStrokeNumbers(svg); if (!doc.save_file(destination.c_str())) { @@ -291,7 +311,7 @@ namespace Kanimaji } } - std::string RemoveStrokeNumbers(const std::string& source) + std::string RemoveStrokeNumbers(const std::string& source, const RemovalSetttings& settings) { pugi::xml_document doc; pugi::xml_parse_result result = doc.load_string(source.c_str(), pugi::parse_full); @@ -305,6 +325,13 @@ namespace Kanimaji throw Error("Unexpected document format: Expected to find a SVG element"); } + pugi::xml_node pathsGroup = svg.find_child([](pugi::xml_node& node) { + return std::string_view(node.attribute("id").as_string()).contains("StrokePaths"); + }); + pathsGroup.attribute("style") = std::format( + StaticStrokeStyleFormat, settings.Style.Colour.ToHex(), settings.Style.Width + ); + RemoveStrokeNumbers(svg); std::stringstream str; diff --git a/Libraries/Kanimaji/Source/Settings.cpp b/Libraries/Kanimaji/Source/Settings.cpp index b2d676f..4574cc6 100644 --- a/Libraries/Kanimaji/Source/Settings.cpp +++ b/Libraries/Kanimaji/Source/Settings.cpp @@ -48,4 +48,14 @@ namespace Kanimaji .DelayBetweenStrokes = 50ms, }; } + + RemovalSetttings RemovalSetttings::Default() + { + return RemovalSetttings { + .Style = StrokeStyle { + .Width = 3.0, + .Colour = RGB::FromHex("#000000"), + }, + }; + } } diff --git a/Libraries/Tablegen/CMakeLists.txt b/Libraries/Tablegen/CMakeLists.txt index 7b17c78..7d14ce3 100644 --- a/Libraries/Tablegen/CMakeLists.txt +++ b/Libraries/Tablegen/CMakeLists.txt @@ -17,7 +17,7 @@ target_link_libraries(Tablegen KVGToolsCommon PRIVATE - pugixml + pugixml::static ) target_sources(Tablegen diff --git a/Libraries/Tablegen/Include/Tablegen/Settings.hpp b/Libraries/Tablegen/Include/Tablegen/Settings.hpp index 3e387fc..853d4e3 100644 --- a/Libraries/Tablegen/Include/Tablegen/Settings.hpp +++ b/Libraries/Tablegen/Include/Tablegen/Settings.hpp @@ -4,7 +4,6 @@ #include #include -#include namespace Tablegen { @@ -49,7 +48,6 @@ namespace Tablegen std::size_t CharactersPerRow; std::string ImageFormat; std::string AnimationFormat; - std::vector Characters; static Settings Default(); }; diff --git a/Libraries/Tablegen/Include/Tablegen/Tablegen.hpp b/Libraries/Tablegen/Include/Tablegen/Tablegen.hpp index 57a21eb..84a78ef 100644 --- a/Libraries/Tablegen/Include/Tablegen/Tablegen.hpp +++ b/Libraries/Tablegen/Include/Tablegen/Tablegen.hpp @@ -8,17 +8,22 @@ #endif #include +#include namespace Tablegen { - std::string GeneratePage(const Settings& settings = Settings::Default()); + std::string GeneratePage(const std::vector& characters, + const Settings& settings = Settings::Default()); - void GeneratePage(const std::string& path, const Settings& settings = Settings::Default()); + void GeneratePage(const std::string& path, const std::vector& characters, + const Settings& settings = Settings::Default()); # ifdef TABLEGEN_EXPOSE_XML - void GenerateAsChild(pugi::xml_node& node, const Settings& settings = Settings::Default()); + void GenerateAsChild(pugi::xml_node& node, const std::vector& characters, + const Settings& settings = Settings::Default()); - pugi::xml_document GenerateDocument(const Settings& settings = Settings::Default()); + pugi::xml_document GenerateDocument(const std::vector& characters, + const Settings& settings = Settings::Default()); # endif } diff --git a/Libraries/Tablegen/Source/Settings.cpp b/Libraries/Tablegen/Source/Settings.cpp index 2602eab..d6cbe15 100644 --- a/Libraries/Tablegen/Source/Settings.cpp +++ b/Libraries/Tablegen/Source/Settings.cpp @@ -32,7 +32,6 @@ namespace Tablegen .CharactersPerRow = 3, .ImageFormat = "https://3011.io/Assets/Images/Kanji/Static/{}.png", .AnimationFormat = "https://3011.io/Assets/Temp/{}.svg", - .Characters = {}, }; } } diff --git a/Libraries/Tablegen/Source/Tablegen.cpp b/Libraries/Tablegen/Source/Tablegen.cpp index bff9b28..6b3084d 100644 --- a/Libraries/Tablegen/Source/Tablegen.cpp +++ b/Libraries/Tablegen/Source/Tablegen.cpp @@ -64,11 +64,9 @@ namespace Tablegen constexpr std::string ImageStyle(std::string_view indent, std::size_t index, - std::string_view imageName, - std::string_view imageFormat, + std::string_view imagePath, std::string_view extraSpecifier = "") { - std::string imagePath = std::vformat(imageFormat, std::make_format_args(imageName)); return std::format(imageStyleFormat, indent, index, extraSpecifier, imagePath); } @@ -95,9 +93,9 @@ namespace Tablegen } } - std::string GeneratePage(const Settings& settings) + std::string GeneratePage(const std::vector& characters, const Settings& settings) { - pugi::xml_document doc = GenerateDocument(settings); + pugi::xml_document doc = GenerateDocument(characters, settings); std::uint32_t formatOptions; formatOptions = pugi::format_indent | pugi::format_no_escapes | pugi::format_no_declaration; @@ -106,16 +104,18 @@ namespace Tablegen return str.str(); } - void GeneratePage(const std::string& path, const Settings& settings) + void GeneratePage(const std::string& path, const std::vector& characters, + const Settings& settings) { - pugi::xml_document doc = GenerateDocument(settings); + pugi::xml_document doc = GenerateDocument(characters, settings); std::uint32_t formatOptions; formatOptions = pugi::format_indent | pugi::format_no_escapes | pugi::format_no_declaration; doc.save_file("test.html", " ", formatOptions); } - void GenerateAsChild(pugi::xml_node& node, const Settings& settings) + void GenerateAsChild(pugi::xml_node& node, const std::vector& characters, + const Settings& settings) { pugi::xml_node tableRoot = node; @@ -136,6 +136,9 @@ namespace Tablegen pugi::xml_node comment = table.append_child(pugi::node_comment); comment.set_value(" Autogenerated by Tablegen, please avoid editing manually. "); + pugi::xml_node preload = table.append_child("div"); + preload.append_attribute("hidden") = "hidden"; + pugi::xml_node script = table.append_child("script"); pugi::xml_node styles = table.append_child("style"); @@ -151,11 +154,28 @@ namespace Tablegen std::string tagIndent((indentLevel > 0 ? indentLevel - 1 : 0) * 4, ' '); pugi::xml_node tableBody = table.append_child("tbody"); - for (pugi::xml_node row; const auto& [i, character] : vw::enumerate(settings.Characters)) { + for (pugi::xml_node row; const auto& [i, character] : vw::enumerate(characters)) { + std::string imagePath = std::vformat( + settings.ImageFormat, std::make_format_args(character.ImagePath) + ); + std::string animationPath = std::vformat( + settings.AnimationFormat, std::make_format_args(character.AnimationPath) + ); + //////////////////////////////////////////////////////////////////// // HTML //////////////////////////////////////////////////////////////////// - if (i % 3 == 0) { + pugi::xml_node preloadImage = preload.append_child("link"); + preloadImage.append_attribute("rel") = "preload"; + preloadImage.append_attribute("href") = imagePath; + preloadImage.append_attribute("as") = "image"; + + pugi::xml_node preloadAnimation = preload.append_child("link"); + preloadAnimation.append_attribute("rel") = "preload"; + preloadAnimation.append_attribute("href") = animationPath; + preloadAnimation.append_attribute("as") = "image"; + + if (i % settings.CharactersPerRow == 0) { row = tableBody.append_child("tr"); row.append_attribute("class") = "kanji-table-row"; } @@ -186,9 +206,8 @@ namespace Tablegen //////////////////////////////////////////////////////////////////// // CSS //////////////////////////////////////////////////////////////////// - staticImg.append(ImageStyle(indent, i, character.ImagePath, settings.ImageFormat)); - animatedImg.append(ImageStyle(indent, i, character.AnimationPath, - settings.AnimationFormat, ":checked")); + staticImg.append(ImageStyle(indent, i, imagePath)); + animatedImg.append(ImageStyle(indent, i, animationPath, ":checked")); //////////////////////////////////////////////////////////////////// // JavaScript @@ -201,10 +220,11 @@ namespace Tablegen script.append_child(pugi::node_pcdata).set_value(Script(indent, tagIndent, buttons)); } - pugi::xml_document GenerateDocument(const Settings& settings) + pugi::xml_document GenerateDocument(const std::vector& characters, + const Settings& settings) { pugi::xml_document doc; - GenerateAsChild(doc); + GenerateAsChild(doc, characters, settings); return doc; } } diff --git a/README.md b/README.md index 7c73ff6..df391ea 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,12 @@ void AnimateFile(const Path& source, const Path& destination, std::string Animate(const std::string& source, const AnimationSettings& settings = AnimationSettings::Default()); + +void RemoveStrokeNumbers(const std::string& source, const std::string& destination, + const RemovalSetttings& settings = RemovalSetttings::Default()); + +std::string RemoveStrokeNumbers(const std::string& source, + const RemovalSetttings& settings = RemovalSetttings::Default()); ``` The former function takes in two paths, where the first one specifies the file to be read, and @@ -78,14 +84,18 @@ This library generates a table of kanji images from a specified list with variou values. It's made up of the following interface: ```cpp -std::string GeneratePage(const Settings& settings = Settings::Default()); +std::string GeneratePage(const std::vector& characters, + const Settings& settings = Settings::Default()); -void GeneratePage(const std::string& path, const Settings& settings = Settings::Default()); +void GeneratePage(const std::string& path, const std::vector& characters, + const Settings& settings = Settings::Default()); #ifdef TABLEGEN_EXPOSE_XML -void GenerateAsChild(pugi::xml_node& node, const Settings& settings = Settings::Default()); +void GenerateAsChild(pugi::xml_node& node, const std::vector& characters, + const Settings& settings = Settings::Default()); -pugi::xml_document GenerateDocument(const Settings& settings = Settings::Default()); +pugi::xml_document GenerateDocument(const std::vector& characters, + const Settings& settings = Settings::Default()); #endif ``` @@ -109,7 +119,7 @@ Some caveats: The default settings generate a table with no characters (and horrible styling), you will need to specify custom settings like this for actual use: ```cpp -auto doc = GeneratePage({ +auto doc = GeneratePage(std::vector(), { .FullDocument = Flag::Enable, .OverrideIndentLevel = Flag::Disable, .IndentLevel = 0, @@ -126,9 +136,5 @@ auto doc = GeneratePage({ .CharactersPerRow = 3, .ImageFormat = "http://the.url/where/you/have/images/{}.svg", .AnimationFormat = "http://the.url/where/you/have/animations/{}.svg", - .Characters = { - /* The actual characters you want in the table, example: */ - { .Label = "Day", .ImagePath = "%E6%97%A5", .AnimationPath = "%E6%97%A5", }, - }, }); ```