Compare commits

...

2 commits

10 changed files with 218 additions and 19 deletions

13
CMake/gtl.cmake Normal file
View file

@ -0,0 +1,13 @@
if(NOT TARGET gtl)
include(FetchContent)
FetchContent_Declare(
gtl
GIT_REPOSITORY https://code.3011.io/Mirrors/gtl
GIT_TAG v1.2.0
)
FetchContent_MakeAvailable(
gtl
)
endif()

13
CMake/mio.cmake Normal file
View file

@ -0,0 +1,13 @@
if(NOT TARGET mio)
include(FetchContent)
FetchContent_Declare(
mio
GIT_REPOSITORY https://code.3011.io/Mirrors/mio
GIT_TAG 8b6b7d878c89e81614d05edca7936de41ccdd2da
)
FetchContent_MakeAvailable(
mio
)
endif()

13
CMake/simdjson.cmake Normal file
View file

@ -0,0 +1,13 @@
if(NOT TARGET simdjson)
include(FetchContent)
FetchContent_Declare(
simdjson
GIT_REPOSITORY https://code.3011.io/Mirrors/simdjson
GIT_TAG v3.13.0
)
FetchContent_MakeAvailable(
simdjson
)
endif()

View file

@ -1 +1,2 @@
add_subdirectory(Kanimaji)
add_subdirectory(Megane)

View file

@ -3,18 +3,19 @@
#include "Settings.hpp"
#include <filesystem>
#include <string>
namespace Kanimaji
{
using Path = std::filesystem::path;
void AnimateFile(const Path& source, const Path& destination,
void AnimateFile(const std::string& source, const std::string& destination,
const AnimationSettings& settings = AnimationSettings::Default());
std::string Animate(const std::string& source,
const AnimationSettings& settings = AnimationSettings::Default());
void RemoveStrokeNumbers(const std::string& source, const std::string& destination);
std::string RemoveStrokeNumbers(const std::string& source);
}
#endif // KANIMAJI_KANIMAJI_HPP

View file

@ -53,6 +53,13 @@ namespace Kanimaji
return std::max(0.0, duration.count());
}
void RemoveStrokeNumbers(pugi::xml_node& svg)
{
svg.remove_child(svg.find_child([](pugi::xml_node& node) {
return std::string_view(node.attribute("id").as_string()).contains("StrokeNumbers");
}));
}
pugi::xml_node AppendGroup(pugi::xml_node& svg, std::string_view name, StrokeStyle config)
{
pugi::xml_node newGroup = svg.append_child("g");
@ -92,17 +99,8 @@ namespace Kanimaji
}
}
void Animate(pugi::xml_document& doc, const AnimationSettings& settings)
void Animate(pugi::xml_node& svg, const AnimationSettings& settings)
{
pugi::xml_node svg = doc.child("svg");
if (!svg) {
throw Error("Unexpected document format: Expected to find a SVG element");
}
svg.remove_child(svg.find_child([](pugi::xml_node& node) {
return std::string_view(node.attribute("id").as_string()).contains("StrokeNumbers");
}));
pugi::xml_node pathsGroup = svg.find_child([](pugi::xml_node& node) {
return std::string_view(node.attribute("id").as_string()).contains("StrokePaths");
});
@ -225,20 +223,27 @@ namespace Kanimaji
}
}
void AnimateFile(const Path& source, const Path& destination, const AnimationSettings& settings)
void AnimateFile(const std::string& source, const std::string& destination,
const AnimationSettings& settings)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(source.c_str(), pugi::parse_full);
if (!result) {
constexpr std::string_view errorFormat = "Failed to load file from {}, due to: {}";
throw FileError(std::format(errorFormat, source.string(), result.description()));
throw FileError(std::format(errorFormat, source, result.description()));
}
pugi::xml_node svg = doc.child("svg");
if (!svg) {
throw Error("Unexpected document format: Expected to find a SVG element");
}
AmendComment(doc);
Animate(doc, settings);
RemoveStrokeNumbers(svg);
Animate(svg, settings);
if (!doc.save_file(destination.c_str())) {
throw FileError(std::format("Failed to save file to {}", destination.string()));
throw FileError(std::format("Failed to save file to {}", destination));
}
}
@ -251,8 +256,56 @@ namespace Kanimaji
throw ParseError(result.offset, std::format(errorFormat, result.description()));
}
pugi::xml_node svg = doc.child("svg");
if (!svg) {
throw Error("Unexpected document format: Expected to find a SVG element");
}
AmendComment(doc);
Animate(doc, settings);
RemoveStrokeNumbers(svg);
Animate(svg, settings);
std::stringstream str;
doc.save(str);
return str.str();
}
void RemoveStrokeNumbers(const std::string& source, const std::string& destination)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(source.c_str(), pugi::parse_full);
if (!result) {
constexpr std::string_view errorFormat = "Failed to load file from {}, due to: {}";
throw FileError(std::format(errorFormat, source, result.description()));
}
pugi::xml_node svg = doc.child("svg");
if (!svg) {
throw Error("Unexpected document format: Expected to find a SVG element");
}
RemoveStrokeNumbers(svg);
if (!doc.save_file(destination.c_str())) {
throw FileError(std::format("Failed to save file to {}", destination));
}
}
std::string RemoveStrokeNumbers(const std::string& source)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_string(source.c_str(), pugi::parse_full);
if (!result) {
constexpr std::string_view errorFormat = "Failed to parse SVG document: {}";
throw ParseError(result.offset, std::format(errorFormat, result.description()));
}
pugi::xml_node svg = doc.child("svg");
if (!svg) {
throw Error("Unexpected document format: Expected to find a SVG element");
}
RemoveStrokeNumbers(svg);
std::stringstream str;
doc.save(str);

View file

@ -0,0 +1,26 @@
include(${PROJECT_SOURCE_DIR}/CMake/gtl.cmake)
include(${PROJECT_SOURCE_DIR}/CMake/simdjson.cmake)
add_library(Megane STATIC)
target_compile_features(Megane
PUBLIC
cxx_std_23
)
target_link_libraries(Megane
PRIVATE
simdjson
PUBLIC
gtl
)
target_include_directories(Megane
PUBLIC
"Include"
)
target_sources(Megane
PRIVATE
"Source/Megane.cpp"
)

View file

@ -0,0 +1,29 @@
#ifndef MEGANE_MEGANE_HPP
#define MEGANE_MEGANE_HPP
#include <gtl/phmap.hpp>
#include <stdexcept>
#include <string>
namespace Megane
{
class Error : public std::runtime_error
{
using std::runtime_error::runtime_error;
};
class Megane
{
public:
Megane(const std::string& indexPath);
~Megane();
std::string GetCode(const std::string& character) const;
private:
gtl::flat_hash_map<std::string, std::string> mStorage;
};
}
#endif // MEGANE_MEGANE_HPP

View file

@ -0,0 +1,49 @@
#include "Megane/Megane.hpp"
#include <simdjson.h>
#include <print>
#include <string>
#include <string_view>
namespace Megane
{
Megane::Megane(const std::string& indexPath)
{
auto res = simdjson::padded_string::load(indexPath);
if (res.error()) {
throw Error("Could not load the file");
}
simdjson::padded_string rawJson = std::move(res.value());
simdjson::ondemand::parser parser;
simdjson::ondemand::document document = parser.iterate(rawJson);
for (auto field : document.get_object()) {
std::string_view key = field.unescaped_key();
std::string_view value;
for (auto candidate : field.value()) {
if (value.length() == 0) {
value = candidate.value_unsafe().get_string();
}
else {
std::string_view candidateValue(candidate);
if (candidateValue.length() < value.length()) {
value = candidateValue;
}
}
}
mStorage[std::string(key)] = value;
}
}
Megane::~Megane() = default;
std::string Megane::GetCode(const std::string& character) const
{
auto it = mStorage.find(character);
if (it == mStorage.end()) {
throw Error("Failed to find the provided character");
}
return it->second;
}
}

View file

@ -8,6 +8,7 @@ target_compile_features(KanimajiTool
target_link_libraries(KanimajiTool
PRIVATE
Kanimaji
Megane
)
target_sources(KanimajiTool