Strengthen paste logic

This commit is contained in:
GenevensiS
2026-05-11 13:51:43 +02:00
committed by GitHub
parent 2135a14b17
commit f4fe9ab6b0
9 changed files with 497 additions and 375 deletions
+53 -49
View File
@@ -13,6 +13,7 @@
#include <boost/json.hpp>
#include <wx/filename.h>
#include <fstream>
#include <filesystem>
// ----------------------------------------------------------------------------- : Crop Rect Encoding
@@ -111,67 +112,70 @@ inline static String transformAllEncodedRects(const String& rectString, RectTran
// ----------------------------------------------------------------------------- : File to UTF8 Encoding
inline static const char Base64Alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
inline static const std::vector<int> Base64ReverseAlphabet = [] {
std::vector<int> table(256, -1);
for (int i = 0; i < 64; i++) table[(uint8_t)Base64Alphabet[i]] = i;
return table;
}();
/// Encode a file in a string
inline static std::string fileToUTF8(const std::string& filepath) {
// File to char
// Load file
std::ifstream file(filepath, std::ios::binary);
file.unsetf(std::ios::skipws);
std::vector<unsigned char> buffer = std::vector<unsigned char>(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
int size = buffer.size();
if (size < 2) {
queue_message(MESSAGE_WARNING, _("File too small to encode"));
if (!file) {
queue_message(MESSAGE_WARNING, _("Could not find file: ") + String(filepath));
return "";
}
// All bytes that have a highest bit of 0 are valid UTF8 characters, so:
// Reset the highest bit of each byte, store these bits in additional bytes at the end
const unsigned char highest_bit = 1 << 7;
unsigned char added_byte = 0;
for (int i = 0, b = 0 ; i < size ; ++i, ++b) {
if (b == 7) { // Never set the highest bit of the added byte
buffer.push_back(added_byte);
b = 0;
}
unsigned char bit = 1 << b;
if ((buffer[i] & highest_bit) != 0) { // The highest bit of the buffer is set
buffer[i] &= ~highest_bit; // Reset the highest bit of the buffer
added_byte |= bit; // Set the bit of the added byte
} else {
added_byte &= ~bit; // Reset the bit of the added byte
size_t size = std::filesystem::file_size(filepath);
std::vector<uint8_t> data(size);
file.read(reinterpret_cast<char*>(data.data()), size);
// Base64 encode
std::string out;
out.reserve(((size + 2) / 3) * 4);
int val = 0;
int valb = -6;
for (uint8_t c : data) {
val = (val << 8) | c;
valb += 8;
while (valb >= 0) {
out.push_back(Base64Alphabet[(val >> valb) & 0x3F]);
valb -= 6;
}
}
buffer.push_back(added_byte);
// Char to string
return std::string(buffer.begin(), buffer.end());
if (valb > -6) {
out.push_back(Base64Alphabet[((val << 8) >> (valb + 8)) & 0x3F]);
}
// Pad
while (out.size() % 4) {
out.push_back('=');
}
return out;
}
/// Retreive a file encoded in a string, return true if successful
inline static bool UTF8ToFile(const std::string& filepath, std::string& string) {
// String to char
std::vector<unsigned char> buffer(string.begin(), string.end());
int size = buffer.size();
if (size < 2) {
queue_message(MESSAGE_WARNING, _("File too small to decode"));
return false;
}
// Restore the highest bit of each byte
size = (size * 7) / 8;
const unsigned char highest_bit = 1 << 7;
unsigned char added_byte = buffer[size];
for (int i = 0, j = size, b = 0 ; i < size ; ++i, ++b) {
if (b == 7) {
++j;
added_byte = buffer[j];
b = 0;
}
unsigned char bit = 1 << b;
if ((added_byte & bit) != 0) { // The bit of the added byte is set
buffer[i] |= highest_bit; // Set the highest bit of the buffer
inline static bool UTF8ToFile(const std::string& filepath, std::string& data) {
// Base64 decode
std::string out;
out.reserve(data.size() * 3 / 4);
int val = 0;
int valb = -8;
for (uint8_t c : data) {
if (c == '=') break; // padding, we're done
val = (val << 6) | Base64ReverseAlphabet[c];
valb += 6;
if (valb >= 0) {
out.push_back(static_cast<char>((val >> valb) & 0xFF));
valb -= 8;
}
}
buffer.resize(size);
// Char to file
std::ofstream file(filepath, std::ios::out|std::ios::binary);
std::copy(buffer.cbegin(), buffer.cend(), std::ostream_iterator<unsigned char>(file));
// Save file
std::ofstream file(filepath, std::ios::binary);
file.write(out.data(), out.size());
return true;
}
+2 -5
View File
@@ -850,14 +850,11 @@ DownloadedImage::DownloadedImage(Set* set, const String& url)
}
// is the data an image?
const String& content_type = wnd.out.GetContentType();
if (!content_type.StartsWith(_("image"))) throw ScriptError(_ERROR_1_("download not image", loadpath));
Image img(*wnd.out.GetStream());
if (!img.IsOk()) throw ScriptError(_ERROR_("web request corrupted"));
if (!wnd.content_type.StartsWith(_("image/"))) throw ScriptError(_ERROR_1_("download not image", loadpath));
// add the file to the set (or overwrite it if pre-existing), save set
auto outStream = set->openOut(savename);
img.SaveFile(*outStream, wxBITMAP_TYPE_PNG);
wnd.image_out.SaveFile(*outStream, wxBITMAP_TYPE_PNG);
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", loadpath));
outStream->Close();
set->save(false);
+76 -23
View File
@@ -305,18 +305,11 @@ bool CardListBase::parseUrl(String& url, vector<CardP>& out) {
WebRequestWindow wnd(url);
if (wnd.ShowModal() == wxID_OK) {
const String& content_type = wnd.out.GetContentType();
if (content_type.StartsWith(_("image"))) {
Image img(*wnd.out.GetStream());
if (img.IsOk()) {
parseImage(img, out);
}
else {
queue_message(MESSAGE_ERROR, _ERROR_("web request corrupted"));
}
if (wnd.content_type.StartsWith(_("image/"))) {
parseImage(wnd.image_out, out);
}
else if (content_type.StartsWith(_("text"))) {
String text = wnd.out.AsString();
else if (wnd.content_type.StartsWith(_("text/"))) {
String text = String(wnd.text_out.data(), wnd.text_out.size());
parseText(text, out);
}
else {
@@ -369,6 +362,9 @@ bool CardListBase::parseImage(Image& image, vector<CardP>& out) {
}
bool CardListBase::parseText(String& text, vector<CardP>& out) {
if (text.size() == 0) {
return false;
}
size_t j = out.size();
size_t pos = text.find("<mse-card-data>");
if (pos != wxString::npos) {
@@ -407,13 +403,19 @@ bool CardListBase::parseData(bool ignore_cards_from_own_card_list) {
if (format == CardsDataObject::format) {
String id = ignore_cards_from_own_card_list ? drop_target->ignored_id : _("");
size_t size = composite->GetDataSize(format);
if (size > 0) {
std::vector<char> buffer(size);
if (composite->GetDataHere(format, buffer.data())) {
CardsDataObject card_data;
card_data.SetData(size, buffer.data());
card_data.getCards(set, id, new_cards);
}
if (size < 1) {
queue_message(MESSAGE_ERROR, _("DEBUG: CardsDataObject corrupted"));
return false;
}
if (size > 10000000) { // 10Mb
queue_message(MESSAGE_ERROR, _("Too much card data, paste less cards!"));
return false;
}
std::vector<char> buffer(size);
if (composite->GetDataHere(format, buffer.data())) {
CardsDataObject card_data;
card_data.SetData(size, buffer.data());
card_data.getCards(set, id, new_cards);
}
}
else {
@@ -432,17 +434,59 @@ bool CardListBase::parseData(bool ignore_cards_from_own_card_list) {
case wxDF_PNG:
{
wxImageDataObject* image_data = static_cast<wxImageDataObject*>(data);
Image image = image_data->GetImage();
parseImage(image, new_cards);
size_t size = image_data->GetDataSize();
if (size < 1) {
queue_message(MESSAGE_ERROR, _("DEBUG: ImageDataObject corrupted"));
return false;
}
if (size > 50000000) { // 50Mb
queue_message(MESSAGE_ERROR, _("Image data too large or corrupted"));
return false;
}
try {
Image image = image_data->GetImage();
if (!image.IsOk() || image.GetWidth() > 20000 || image.GetHeight() > 20000) {
queue_message(MESSAGE_ERROR, _("Image too large or corrupted"));
return false;
}
parseImage(image, new_cards);
} catch (const std::bad_alloc&) {
//queue_message(MESSAGE_ERROR, _("Image couldn't be allocated"));
return false;
} catch (...) {
queue_message(MESSAGE_ERROR, _("Image couldn't be processed"));
return false;
}
}
break;
case wxDF_BITMAP:
{
wxBitmapDataObject* bitmap_data = static_cast<wxBitmapDataObject*>(data);
wxBitmap bitmap = bitmap_data->GetBitmap();
Image image = bitmap.ConvertToImage();
parseImage(image, new_cards);
size_t size = bitmap_data->GetDataSize();
if (size < 1) {
queue_message(MESSAGE_ERROR, _("DEBUG: BitmapDataObject corrupted"));
return false;
}
if (size > 50000000) { // 50Mb
queue_message(MESSAGE_ERROR, _("Bitmap data too large or corrupted"));
return false;
}
try {
wxBitmap bitmap = bitmap_data->GetBitmap();
if (!bitmap.IsOk() || bitmap.GetWidth() > 20000 || bitmap.GetHeight() > 20000) {
queue_message(MESSAGE_ERROR, _("Bitmap too large or corrupted"));
return false;
}
Image image = bitmap.ConvertToImage();
parseImage(image, new_cards);
} catch (const std::bad_alloc&) {
//queue_message(MESSAGE_ERROR, _("Bitmap or Image couldn't be allocated"));
return false;
} catch (...) {
queue_message(MESSAGE_ERROR, _("Bitmap or Image couldn't be processed"));
return false;
}
}
break;
@@ -451,6 +495,15 @@ bool CardListBase::parseData(bool ignore_cards_from_own_card_list) {
case wxDF_HTML:
{
wxTextDataObject* text_data = static_cast<wxTextDataObject*>(data);
size_t size = text_data->GetDataSize();
if (size < 1) {
queue_message(MESSAGE_ERROR, _("DEBUG: TextDataObject corrupted"));
return false;
}
if (size > 30000000) { // 30Mb
queue_message(MESSAGE_ERROR, _("Text too large or corrupted"));
return false;
}
String text = text_data->GetText();
if (!parseUrl(text, new_cards)) parseText(text, new_cards);
}
+39 -4
View File
@@ -9,6 +9,7 @@
#include <util/prec.hpp>
#include <gui/web_request_window.hpp>
#include <util/window_id.hpp>
#include <wx/mstream.h>
// ----------------------------------------------------------------------------- : WebRequestWindow
@@ -76,16 +77,50 @@ void WebRequestWindow::onUpdate(wxWebRequestEvent& evt) {
}
void WebRequestWindow::onComplete(wxWebRequestEvent& evt) {
out = evt.GetResponse();
if (out.IsOk()) {
EndModal(wxID_OK);
wxWebResponse response = evt.GetResponse();
if (!response.IsOk()) {
onFail(_ERROR_("web request corrupted"));
return;
}
wxInputStream* stream = response.GetStream();
if (!stream || !stream->IsOk()) {
onFail(_ERROR_("web request corrupted"));
return;
}
content_type = response.GetContentType();
if (content_type.StartsWith("image/")) {
image_out = Image(*stream);
if (!image_out.IsOk()) {
onFail(_ERROR_("web request corrupted"));
return;
}
}
else if (content_type.StartsWith("text/") || content_type.Contains("json")) {
wxMemoryOutputStream mem;
char buffer[8192];
while (true) {
stream->Read(buffer, sizeof(buffer));
size_t read = stream->LastRead();
if (read > 0) mem.Write(buffer, read);
if (stream->Eof()) break;
if (stream->GetLastError() != wxSTREAM_NO_ERROR) {
onFail(_ERROR_("web request corrupted"));
return;
}
}
text_out.resize(mem.GetSize());
mem.CopyTo(text_out.data(), mem.GetSize());
}
else {
onFail(_ERROR_("web request corrupted"));
onFail(_ERROR_("web request unsupported format"));
return;
}
EndModal(wxID_OK);
}
void WebRequestWindow::onFail(const String& message) {
content_type.Clear();
info->SetLabel(_ERROR_("web request failed"));
address->SetLabel(message);
}
+3 -1
View File
@@ -19,7 +19,9 @@ class WebRequestWindow : public wxDialog {
public:
WebRequestWindow(const String& url, bool sizer=true);
wxWebResponse out;
String content_type;
std::string text_out;
Image image_out;
protected:
DECLARE_EVENT_TABLE();
+293 -264
View File
@@ -112,13 +112,25 @@ void pretty_print(std::ostream& os, const boost::json::value& jv, std::string* i
String json_pretty_print(const boost::json::value& jv, std::string* indent) {
std::ostringstream stream;
pretty_print(stream, jv, indent);
String string = wxString(stream.str().c_str());
return string;
std::string stdstring = stream.str();
const char* data = stdstring.data();
size_t size = stdstring.size();
String wxstring = String::FromUTF8(data, size);
if (wxstring.empty() && size > 0) {
wxstring = String(data, wxConvWhateverWorks, size);
}
return wxstring;
}
String json_ugly_print(const boost::json::value& jv) {
String string = wxString(boost::json::serialize(jv).c_str());
return string;
std::string stdstring = boost::json::serialize(jv);
const char* data = stdstring.data();
size_t size = stdstring.size();
String wxstring = String::FromUTF8(data, size);
if (wxstring.empty() && size > 0) {
wxstring = String(data, wxConvWhateverWorks, size);
}
return wxstring;
}
// ----------------------------------------------------------------------------- : JSON to MSE
@@ -128,23 +140,33 @@ ScriptValueP json_to_mse(const boost::json::value& jv, Set* set);
template <typename T>
void read(T& out, boost::json::object& jv, const char value_name[]) {
if (!jv.contains(value_name)) return;
else {
wxStringInputStream stream = {_("")};
Reader reader(stream, nullptr, _(""));
reader.setValue(wxString(jv[value_name].as_string().c_str()));
reader.handle(out);
boost::json::string jstring = jv[value_name].as_string();
const char* data = jstring.data();
size_t size = jstring.size();
String wxstring = String::FromUTF8(data, size);
if (wxstring.empty() && size > 0) {
wxstring = String(data, wxConvWhateverWorks, size);
}
wxStringInputStream stream(wxstring);
Reader reader(stream, nullptr, _(""), false, true);
reader.setValue(wxstring);
reader.handle(out);
}
// templates don't work with enums? are you kidding me with this language?
void read(PackSelectType& out, boost::json::object& jv, const char value_name[]) {
if (!jv.contains(value_name)) return;
else {
wxStringInputStream stream = {_("")};
Reader reader(stream, nullptr, _(""));
reader.setValue(wxString(jv[value_name].as_string().c_str()));
reader.handle(out);
boost::json::string jstring = jv[value_name].as_string();
const char* data = jstring.data();
size_t size = jstring.size();
String wxstring = String::FromUTF8(data, size);
if (wxstring.empty() && size > 0) {
wxstring = String(data, wxConvWhateverWorks, size);
}
wxStringInputStream stream(wxstring);
Reader reader(stream, nullptr, _(""), false, true);
reader.setValue(wxstring);
reader.handle(out);
}
PackItemP json_to_mse_pack_item(boost::json::object& jv) {
@@ -163,7 +185,7 @@ PackTypeP json_to_mse_pack_type(boost::json::object& jv) {
read(pack_type->summary, jv, "summary");
read(pack_type->select, jv, "select");
if (jv.contains("items") && jv["items"].is_array()) {
boost::json::array pack_itemsv = jv["items"].as_array();
boost::json::array pack_itemsv = jv["items"].get_array();
for (size_t i = 0; i < pack_itemsv.size(); i++) {
boost::json::object pack_itemv = pack_itemsv[i].as_object();
pack_type->items.emplace_back(json_to_mse_pack_item(pack_itemv));
@@ -184,38 +206,43 @@ KeywordP json_to_mse_keyword(boost::json::object& jv) {
CardP json_to_mse_card(boost::json::object& jv, Set* set) {
CardP card = make_intrusive<Card>(*set->game);
read(card->time_created, jv, "time_created");
read(card->time_modified, jv, "time_modified");
read(card->notes, jv, "notes");
read(card->uid, jv, "uid");
read(card->linked_card_1, jv, "linked_card_1");
read(card->linked_card_2, jv, "linked_card_2");
read(card->linked_card_3, jv, "linked_card_3");
read(card->linked_card_4, jv, "linked_card_4");
read(card->linked_relation_1, jv, "linked_relation_1");
read(card->linked_relation_2, jv, "linked_relation_2");
read(card->linked_relation_3, jv, "linked_relation_3");
read(card->linked_relation_4, jv, "linked_relation_4");
read(card->time_created, jv, "time_created");
read(card->time_modified, jv, "time_modified");
read(card->notes, jv, "notes");
read(card->uid, jv, "uid");
read(card->linked_card_1, jv, "linked_card_1");
read(card->linked_card_2, jv, "linked_card_2");
read(card->linked_card_3, jv, "linked_card_3");
read(card->linked_card_4, jv, "linked_card_4");
read(card->linked_relation_1, jv, "linked_relation_1");
read(card->linked_relation_2, jv, "linked_relation_2");
read(card->linked_relation_3, jv, "linked_relation_3");
read(card->linked_relation_4, jv, "linked_relation_4");
// card fields
if (jv.contains("data") && jv["data"].is_object()) {
boost::json::object datav = jv["data"].as_object();
boost::json::object datav = jv["data"].get_object();
for (auto it = datav.begin(); it != datav.end(); ++it) {
String key_name = wxString(it->key_c_str());
boost::json::string_view key_view = it->key();
String key_name = String::FromUTF8(key_view.data(), key_view.size());
Value* container = get_card_field_container(*set->game, card->data, key_name, false);
ScriptValueP value = json_to_mse(it->value(), set);
set_container(container, value, key_name);
}
}
// stylesheet
if (jv.contains("stylesheet")) card->stylesheet = StyleSheet::byGameAndName(*set->game, wxString(jv["stylesheet"].as_string().c_str()));
if (jv.contains("stylesheet")) {
boost::json::string stylesheet_name = jv["stylesheet"].as_string();
card->stylesheet = StyleSheet::byGameAndName(*set->game, String::FromUTF8(stylesheet_name.data(), stylesheet_name.size()));
}
if (card->stylesheet) {
// styling fields
card->styling_data.init(card->stylesheet->styling_fields);
if (jv.contains("styling_data") && jv["styling_data"].is_object()) {
boost::json::object datav = jv["styling_data"].as_object();
boost::json::object datav = jv["styling_data"].get_object();
for (auto it = datav.begin(); it != datav.end(); ++it) {
String key_name = wxString(it->key_c_str());
Value* container = get_container(card->styling_data, wxString("styling"), key_name, false);
boost::json::string_view key_view = it->key();
String key_name = String::FromUTF8(key_view.data(), key_view.size());
Value* container = get_container(card->styling_data, String("styling"), key_name, false);
ScriptValueP value = json_to_mse(it->value(), set);
set_container(container, value, key_name);
card->has_styling = true;
@@ -223,15 +250,17 @@ CardP json_to_mse_card(boost::json::object& jv, Set* set) {
}
// extra card fields
if (jv.contains("extra_data") && jv["extra_data"].is_object()) {
boost::json::object datav = jv["extra_data"].as_object();
boost::json::object datav = jv["extra_data"].get_object();
for (auto it = datav.begin(); it != datav.end(); ++it) {
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, it->key_c_str());
boost::json::string_view stylesheet_view = it->key();
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, String::FromUTF8(stylesheet_view.data(), stylesheet_view.size()));
if (!stylesheet) continue;
IndexMap<FieldP, ValueP>& stylesheet_data = card->extraDataFor(*stylesheet);
boost::json::object stylesheet_datav = it->value().as_object();
for (auto stylesheet_it = stylesheet_datav.begin(); stylesheet_it != stylesheet_datav.end(); ++stylesheet_it) {
String key_name = wxString(stylesheet_it->key_c_str());
Value* container = get_container(stylesheet_data, wxString("extra card"), key_name, false);
boost::json::string_view key_view = stylesheet_it->key();
String key_name = String::FromUTF8(key_view.data(), key_view.size());
Value* container = get_container(stylesheet_data, String("extra card"), key_name, false);
ScriptValueP value = json_to_mse(stylesheet_it->value(), set);
set_container(container, value, key_name);
}
@@ -248,30 +277,35 @@ SetP json_to_mse_set(boost::json::object& jv) {
if (!jv.contains("stylesheet")) {
throw ScriptError(_ERROR_("json set without stylesheet"));
}
GameP game = Game::byName(wxString(jv["game"].as_string().c_str()));
StyleSheetP stylesheet = StyleSheet::byGameAndName(*game, wxString(jv["stylesheet"].as_string().c_str()));
boost::json::string game_name = jv["game"].as_string();
GameP game = Game::byName(String::FromUTF8(game_name.data(), game_name.size()));
boost::json::string stylesheet_name = jv["stylesheet"].as_string();
StyleSheetP stylesheet = StyleSheet::byGameAndName(*game, String::FromUTF8(stylesheet_name.data(), stylesheet_name.size()));
SetP set = make_intrusive<Set>(stylesheet);
// set fields
if (jv.contains("set_info") && jv["set_info"].is_object()) {
boost::json::object datav = jv["set_info"].as_object();
boost::json::object datav = jv["set_info"].get_object();
for (auto it = datav.begin(); it != datav.end(); ++it) {
String key_name = wxString(it->key_c_str());
Value* container = get_container(set->data, wxString("set"), key_name, false);
boost::json::string_view key_view = it->key();
String key_name = String::FromUTF8(key_view.data(), key_view.size());
Value* container = get_container(set->data, String("set"), key_name, false);
ScriptValueP value = json_to_mse(it->value(), set.get());
set_container(container, value, key_name);
}
}
// styling
if (jv.contains("styling") && jv["styling"].is_object()) {
boost::json::object datav = jv["styling"].as_object();
boost::json::object datav = jv["styling"].get_object();
for (auto it = datav.begin(); it != datav.end(); ++it) {
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, it->key_c_str());
boost::json::string_view stylesheet_view = it->key();
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, String::FromUTF8(stylesheet_view.data(), stylesheet_view.size()));
if (!stylesheet) continue;
IndexMap<FieldP, ValueP>& stylesheet_data = set->stylingDataFor(*stylesheet);
boost::json::object stylesheet_datav = it->value().as_object();
for (auto stylesheet_it = stylesheet_datav.begin(); stylesheet_it != stylesheet_datav.end(); ++stylesheet_it) {
String key_name = wxString(stylesheet_it->key_c_str());
Value* container = get_container(stylesheet_data, wxString("styling"), key_name, false);
boost::json::string_view key_view = stylesheet_it->key();
String key_name = String::FromUTF8(key_view.data(), key_view.size());
Value* container = get_container(stylesheet_data, String("styling"), key_name, false);
ScriptValueP value = json_to_mse(stylesheet_it->value(), set.get());
set_container(container, value, key_name);
}
@@ -279,7 +313,7 @@ SetP json_to_mse_set(boost::json::object& jv) {
}
// cards
if (jv.contains("cards") && jv["cards"].is_array()) {
boost::json::array cardsv = jv["cards"].as_array();
boost::json::array cardsv = jv["cards"].get_array();
for (size_t i = 0; i < cardsv.size(); i++) {
boost::json::object cardv = cardsv[i].as_object();
set->cards.emplace_back(json_to_mse_card(cardv, set.get()));
@@ -287,7 +321,7 @@ SetP json_to_mse_set(boost::json::object& jv) {
}
// keywords
if (jv.contains("keywords") && jv["keywords"].is_array()) {
boost::json::array keywordsv = jv["keywords"].as_array();
boost::json::array keywordsv = jv["keywords"].get_array();
for (size_t i = 0; i < keywordsv.size(); i++) {
boost::json::object keywordv = keywordsv[i].as_object();
set->keywords.emplace_back(json_to_mse_keyword(keywordv));
@@ -295,7 +329,7 @@ SetP json_to_mse_set(boost::json::object& jv) {
}
// pack types
if (jv.contains("pack_types") && jv["pack_types"].is_array()) {
boost::json::array pack_typesv = jv["pack_types"].as_array();
boost::json::array pack_typesv = jv["pack_types"].get_array();
for (size_t i = 0; i < pack_typesv.size(); i++) {
boost::json::object pack_typev = pack_typesv[i].as_object();
set->pack_types.emplace_back(json_to_mse_pack_type(pack_typev));
@@ -318,17 +352,13 @@ ScriptValueP json_to_mse(const boost::json::value& jv, Set* set) {
return to_script(integer);
}
else if (jv.is_string()) {
if (jv.as_string().empty()) return to_script(String());
std::string string = boost::json::value_to<std::string>(jv);
const char* cstring = string.c_str();
size_t nulpos = strlen(cstring);
// if the string contains nul bytes, we have to use the std::string constructor, even though we can't specify the encoding
if (nulpos < string.size()) return to_script(String(string));
// if the string doesn't contain nul bytes, we can use the constructor that allows to specify the encoding
String wxstring(cstring, wxConvUTF8);
boost::json::string jstring = jv.get_string();
if (jstring.empty()) return to_script(String());
const char* data = jstring.data();
size_t size = jstring.size();
String wxstring = String::FromUTF8(data, size);
if (!wxstring.empty()) return to_script(wxstring);
// if all else fails, use "Whatever Works"
return to_script(String(cstring, wxConvWhateverWorks));
return to_script(String(data, wxConvWhateverWorks, size));
}
else if (jv.is_array()) {
boost::json::array array = jv.get_array();
@@ -349,18 +379,16 @@ ScriptValueP json_to_mse(const boost::json::value& jv, Set* set) {
if (mse_object_type == "keyword") return make_intrusive<ScriptObject<KeywordP>> (json_to_mse_keyword(object));
if (mse_object_type == "pack_type") return make_intrusive<ScriptObject<PackTypeP>>(json_to_mse_pack_type(object));
if (mse_object_type == "pack_item") return make_intrusive<ScriptObject<PackItemP>>(json_to_mse_pack_item(object));
queue_message(MESSAGE_ERROR, _ERROR_("json unknown type") + _("(") + wxString(mse_object_type.c_str()) + _(")"));
queue_message(MESSAGE_ERROR, _ERROR_("json unknown type") + _("(") + String(mse_object_type.c_str()) + _(")"));
return script_nil;
}
ScriptCustomCollectionP result = make_intrusive<ScriptCustomCollection>();
for (auto it = object.begin(); it != object.end(); ++it) {
boost::json::string_view jview = it->key();
std::string_view stdview = std::string_view(jview.data(), jview.size());
std::string stdstring = { stdview.begin(), stdview.end() };
String key(stdstring.c_str(), wxConvUTF8);
String key_name = String::FromUTF8(jview.data(), jview.size());
boost::json::value jvalue = it->value();
ScriptValueP value = json_to_mse(jvalue, set);
result->key_value[key] = value;
result->key_value[key_name] = value;
}
return result;
}
@@ -374,8 +402,9 @@ ScriptValueP json_to_mse(const String& string, Set* set) {
boost::system::error_code ec;
boost::json::parse_options options;
options.allow_invalid_utf8 = true;
boost::json::value jv = boost::json::parse(string.ToStdString(), ec, {}, options);
//if(ec) queue_message(MESSAGE_ERROR, _ERROR_("json cant parse") + _("\n\n") + ec.message());
wxScopedCharBuffer buffer = string.ToUTF8();
boost::json::value jv = boost::json::parse(boost::json::string_view(buffer.data(), buffer.length()), ec, {}, options);
if(ec && buffer.length() > 0) queue_message(MESSAGE_ERROR, _ERROR_("json cant parse") + _("\n\n") + ec.message());
if(ec) return script_nil;
return json_to_mse(jv, set);
}
@@ -512,92 +541,92 @@ boost::json::object mse_to_json(const StyleP& style) {
boost::json::object stylev;
stylev.emplace("mse_object_type", "style");
stylev.emplace("z_index", wxString::Format(wxT("%i"), style->z_index));
stylev.emplace("tab_index", wxString::Format(wxT("%i"), style->tab_index));
stylev.emplace("left", wxString::Format(wxT("%.2f"), style->left()));
stylev.emplace("top", wxString::Format(wxT("%.2f"), style->top()));
stylev.emplace("right", wxString::Format(wxT("%.2f"), style->right()));
stylev.emplace("bottom", wxString::Format(wxT("%.2f"), style->bottom()));
stylev.emplace("width", wxString::Format(wxT("%.2f"), style->width()));
stylev.emplace("height", wxString::Format(wxT("%.2f"), style->height()));
stylev.emplace("angle", wxString::Format(wxT("%.2f"), style->angle()));
stylev.emplace("visible", style->visible());
stylev.emplace("mask", style->mask.toScriptString());
stylev.emplace("z_index", String::Format(wxT("%i"), style->z_index));
stylev.emplace("tab_index", String::Format(wxT("%i"), style->tab_index));
stylev.emplace("left", String::Format(wxT("%.2f"), style->left()));
stylev.emplace("top", String::Format(wxT("%.2f"), style->top()));
stylev.emplace("right", String::Format(wxT("%.2f"), style->right()));
stylev.emplace("bottom", String::Format(wxT("%.2f"), style->bottom()));
stylev.emplace("width", String::Format(wxT("%.2f"), style->width()));
stylev.emplace("height", String::Format(wxT("%.2f"), style->height()));
stylev.emplace("angle", String::Format(wxT("%.2f"), style->angle()));
stylev.emplace("visible", style->visible());
stylev.emplace("mask", style->mask.toScriptString());
if (TextStyle* s = dynamic_cast<TextStyle*>(style.get())) {
stylev.emplace("field_type", "text");
boost::json::object fontv;
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
boost::json::object symbolfontv;
symbolfontv.emplace("name", s->symbol_font.name());
symbolfontv.emplace("size", wxString::Format(wxT("%.2f"), s->symbol_font.size()));
symbolfontv.emplace("underline", s->symbol_font.underline());
symbolfontv.emplace("strikethrough", s->symbol_font.strikethrough());
symbolfontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->symbol_font.scale_down_to));
symbolfontv.emplace("shadow_color", format_color( s->symbol_font.shadow_color()));
symbolfontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_x()));
symbolfontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_y()));
symbolfontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->symbol_font.shadow_blur()));
symbolfontv.emplace("stroke_color", format_color( s->symbol_font.stroke_color()));
symbolfontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->symbol_font.stroke_radius()));
symbolfontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->symbol_font.stroke_blur()));
stylev.emplace("symbol_font", symbolfontv);
symbolfontv.emplace("name", s->symbol_font.name());
symbolfontv.emplace("size", String::Format(wxT("%.2f"), s->symbol_font.size()));
symbolfontv.emplace("underline", s->symbol_font.underline());
symbolfontv.emplace("strikethrough", s->symbol_font.strikethrough());
symbolfontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->symbol_font.scale_down_to));
symbolfontv.emplace("shadow_color", format_color( s->symbol_font.shadow_color()));
symbolfontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_x()));
symbolfontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_y()));
symbolfontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->symbol_font.shadow_blur()));
symbolfontv.emplace("stroke_color", format_color( s->symbol_font.stroke_color()));
symbolfontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->symbol_font.stroke_radius()));
symbolfontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->symbol_font.stroke_blur()));
stylev.emplace("symbol_font", symbolfontv);
stylev.emplace("always_symbol", s->always_symbol);
stylev.emplace("allow_formating", s->allow_formating);
stylev.emplace("alignment", alignment_to_string( s->alignment()));
stylev.emplace("direction", direction_to_string( s->direction));
stylev.emplace("padding_left", wxString::Format(wxT("%.2f"), s->padding_left()));
stylev.emplace("padding_right", wxString::Format(wxT("%.2f"), s->padding_right()));
stylev.emplace("padding_top", wxString::Format(wxT("%.2f"), s->padding_top()));
stylev.emplace("padding_bottom", wxString::Format(wxT("%.2f"), s->padding_bottom()));
stylev.emplace("padding_left_min", wxString::Format(wxT("%.2f"), s->padding_left_min()));
stylev.emplace("padding_right_min", wxString::Format(wxT("%.2f"), s->padding_right_min()));
stylev.emplace("padding_top_min", wxString::Format(wxT("%.2f"), s->padding_top_min()));
stylev.emplace("padding_bottom_min", wxString::Format(wxT("%.2f"), s->padding_bottom_min()));
stylev.emplace("line_height_soft", wxString::Format(wxT("%.2f"), s->line_height_soft()));
stylev.emplace("line_height_hard", wxString::Format(wxT("%.2f"), s->line_height_hard()));
stylev.emplace("line_height_line", wxString::Format(wxT("%.2f"), s->line_height_line()));
stylev.emplace("line_height_soft_max", wxString::Format(wxT("%.2f"), s->line_height_soft_max()));
stylev.emplace("line_height_hard_max", wxString::Format(wxT("%.2f"), s->line_height_hard_max()));
stylev.emplace("line_height_line_max", wxString::Format(wxT("%.2f"), s->line_height_line_max()));
stylev.emplace("paragraph_height", wxString::Format(wxT("%.2f"), s->paragraph_height()));
stylev.emplace("always_symbol", s->always_symbol);
stylev.emplace("allow_formating", s->allow_formating);
stylev.emplace("alignment", alignment_to_string( s->alignment()));
stylev.emplace("direction", direction_to_string( s->direction));
stylev.emplace("padding_left", String::Format(wxT("%.2f"), s->padding_left()));
stylev.emplace("padding_right", String::Format(wxT("%.2f"), s->padding_right()));
stylev.emplace("padding_top", String::Format(wxT("%.2f"), s->padding_top()));
stylev.emplace("padding_bottom", String::Format(wxT("%.2f"), s->padding_bottom()));
stylev.emplace("padding_left_min", String::Format(wxT("%.2f"), s->padding_left_min()));
stylev.emplace("padding_right_min", String::Format(wxT("%.2f"), s->padding_right_min()));
stylev.emplace("padding_top_min", String::Format(wxT("%.2f"), s->padding_top_min()));
stylev.emplace("padding_bottom_min", String::Format(wxT("%.2f"), s->padding_bottom_min()));
stylev.emplace("line_height_soft", String::Format(wxT("%.2f"), s->line_height_soft()));
stylev.emplace("line_height_hard", String::Format(wxT("%.2f"), s->line_height_hard()));
stylev.emplace("line_height_line", String::Format(wxT("%.2f"), s->line_height_line()));
stylev.emplace("line_height_soft_max", String::Format(wxT("%.2f"), s->line_height_soft_max()));
stylev.emplace("line_height_hard_max", String::Format(wxT("%.2f"), s->line_height_hard_max()));
stylev.emplace("line_height_line_max", String::Format(wxT("%.2f"), s->line_height_line_max()));
stylev.emplace("paragraph_height", String::Format(wxT("%.2f"), s->paragraph_height()));
boost::json::object layoutv;
layoutv.emplace("content_top", wxString::Format(wxT("%.2f"), s->layout->top));
layoutv.emplace("content_middle", wxString::Format(wxT("%.2f"), s->layout->middle()));
layoutv.emplace("content_bottom", wxString::Format(wxT("%.2f"), s->layout->bottom()));
layoutv.emplace("content_width", wxString::Format(wxT("%.2f"), s->layout->width));
layoutv.emplace("content_height", wxString::Format(wxT("%.2f"), s->layout->height));
layoutv.emplace("content_lines", wxString::Format(wxT("%i"), s->layout->lines.size()));
layoutv.emplace("content_clauses", wxString::Format(wxT("%i"), s->layout->clauses.size()));
layoutv.emplace("content_paragraphs", wxString::Format(wxT("%i"), s->layout->paragraphs.size()));
layoutv.emplace("content_blocks", wxString::Format(wxT("%i"), s->layout->blocks.size()));
layoutv.emplace("content_top", String::Format(wxT("%.2f"), s->layout->top));
layoutv.emplace("content_middle", String::Format(wxT("%.2f"), s->layout->middle()));
layoutv.emplace("content_bottom", String::Format(wxT("%.2f"), s->layout->bottom()));
layoutv.emplace("content_width", String::Format(wxT("%.2f"), s->layout->width));
layoutv.emplace("content_height", String::Format(wxT("%.2f"), s->layout->height));
layoutv.emplace("content_lines", String::Format(wxT("%i"), s->layout->lines.size()));
layoutv.emplace("content_clauses", String::Format(wxT("%i"), s->layout->clauses.size()));
layoutv.emplace("content_paragraphs", String::Format(wxT("%i"), s->layout->paragraphs.size()));
layoutv.emplace("content_blocks", String::Format(wxT("%i"), s->layout->blocks.size()));
boost::json::array separatorsv;
int size = s->layout->separators.size();
for (int i = 0; i < size; i++) {
separatorsv.emplace_back(wxString::Format(wxT("%.2f"), s->layout->separators[i]));
separatorsv.emplace_back(String::Format(wxT("%.2f"), s->layout->separators[i]));
}
if (size > 0) layoutv.emplace("content_separators", separatorsv);
@@ -612,35 +641,35 @@ boost::json::object mse_to_json(const StyleP& style) {
else if (MultipleChoiceStyle* s = dynamic_cast<MultipleChoiceStyle*>(style.get())) {
stylev.emplace("field_type", "multiple_choice");
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
stylev.emplace("render_style", render_style_to_string( s->render_style));
stylev.emplace("image", s->image.toScriptString());
stylev.emplace("combine", combine_to_string( s->combine));
stylev.emplace("alignment", alignment_to_string( s->alignment));
stylev.emplace("direction", direction_to_string( s->direction()));
stylev.emplace("spacing", wxString::Format(wxT("%.2f"), s->spacing()));
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
stylev.emplace("render_style", render_style_to_string( s->render_style));
stylev.emplace("image", s->image.toScriptString());
stylev.emplace("combine", combine_to_string( s->combine));
stylev.emplace("alignment", alignment_to_string( s->alignment));
stylev.emplace("direction", direction_to_string( s->direction()));
stylev.emplace("spacing", String::Format(wxT("%.2f"), s->spacing()));
boost::json::object fontv;
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
boost::json::object choiceimagesv;
for (auto choice_image : s->choice_images) {
@@ -652,33 +681,33 @@ boost::json::object mse_to_json(const StyleP& style) {
else if (ChoiceStyle* s = dynamic_cast<ChoiceStyle*>(style.get())) {
stylev.emplace("field_type", dynamic_cast<BooleanStyle*>(style.get()) ? "boolean" : "choice");
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
stylev.emplace("render_style", render_style_to_string( s->render_style));
stylev.emplace("image", s->image.toScriptString());
stylev.emplace("combine", combine_to_string( s->combine));
stylev.emplace("alignment", alignment_to_string( s->alignment));
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
stylev.emplace("render_style", render_style_to_string( s->render_style));
stylev.emplace("image", s->image.toScriptString());
stylev.emplace("combine", combine_to_string( s->combine));
stylev.emplace("alignment", alignment_to_string( s->alignment));
boost::json::object fontv;
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
boost::json::object choiceimagesv;
for (auto choice_image : s->choice_images) {
@@ -692,71 +721,71 @@ boost::json::object mse_to_json(const StyleP& style) {
stylev.emplace("field_type", "package_choice");
boost::json::object fontv;
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
}
else if (ColorStyle* s = dynamic_cast<ColorStyle*>(style.get())) {
stylev.emplace("field_type", "color");
stylev.emplace("radius", wxString::Format(wxT("%.2f"), s->radius()));
stylev.emplace("left_width", wxString::Format(wxT("%.2f"), s->left_width()));
stylev.emplace("right_width", wxString::Format(wxT("%.2f"), s->right_width()));
stylev.emplace("top_width", wxString::Format(wxT("%.2f"), s->top_width()));
stylev.emplace("bottom_width", wxString::Format(wxT("%.2f"), s->bottom_width()));
stylev.emplace("combine", combine_to_string( s->combine));
stylev.emplace("radius", String::Format(wxT("%.2f"), s->radius()));
stylev.emplace("left_width", String::Format(wxT("%.2f"), s->left_width()));
stylev.emplace("right_width", String::Format(wxT("%.2f"), s->right_width()));
stylev.emplace("top_width", String::Format(wxT("%.2f"), s->top_width()));
stylev.emplace("bottom_width", String::Format(wxT("%.2f"), s->bottom_width()));
stylev.emplace("combine", combine_to_string( s->combine));
}
else if (SymbolStyle* s = dynamic_cast<SymbolStyle*>(style.get())) {
stylev.emplace("field_type", "symbol");
stylev.emplace("min_aspect_ratio", wxString::Format(wxT("%.2f"), s->min_aspect_ratio));
stylev.emplace("max_aspect_ratio", wxString::Format(wxT("%.2f"), s->max_aspect_ratio));
stylev.emplace("min_aspect_ratio", String::Format(wxT("%.2f"), s->min_aspect_ratio));
stylev.emplace("max_aspect_ratio", String::Format(wxT("%.2f"), s->max_aspect_ratio));
boost::json::array variationsv;
int size = s->variations.size();
for (int i = 0; i < size; i++) {
boost::json::object variationv;
variationv.emplace("name", s->variations[i]->name);
variationv.emplace("border_radius", wxString::Format(wxT("%.2f"), s->variations[i]->border_radius));
variationv.emplace("name", s->variations[i]->name);
variationv.emplace("border_radius", String::Format(wxT("%.2f"), s->variations[i]->border_radius));
SymbolFilterP filter = s->variations[i]->filter;
if (SolidFillSymbolFilter* f = dynamic_cast<SolidFillSymbolFilter*>(filter.get())) {
variationv.emplace("fill_type", f->fillType());
variationv.emplace("fill_color", format_color( f->fill_color));
variationv.emplace("border_color", format_color( f->border_color));
variationv.emplace("fill_type", f->fillType());
variationv.emplace("fill_color", format_color( f->fill_color));
variationv.emplace("border_color", format_color( f->border_color));
}
else if (RadialGradientSymbolFilter* f = dynamic_cast<RadialGradientSymbolFilter*>(filter.get())) {
variationv.emplace("fill_type", f->fillType());
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
variationv.emplace("border_color_1", format_color( f->border_color_1));
variationv.emplace("border_color_2", format_color( f->border_color_2));
variationv.emplace("fill_type", f->fillType());
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
variationv.emplace("border_color_1", format_color( f->border_color_1));
variationv.emplace("border_color_2", format_color( f->border_color_2));
}
else if (LinearGradientSymbolFilter* f = dynamic_cast<LinearGradientSymbolFilter*>(filter.get())) {
variationv.emplace("fill_type", f->fillType());
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
variationv.emplace("border_color_1", format_color( f->border_color_1));
variationv.emplace("border_color_2", format_color( f->border_color_2));
variationv.emplace("center_x", wxString::Format(wxT("%.2f"), f->center_x));
variationv.emplace("center_y", wxString::Format(wxT("%.2f"), f->center_y));
variationv.emplace("end_x", wxString::Format(wxT("%.2f"), f->end_x));
variationv.emplace("end_y", wxString::Format(wxT("%.2f"), f->end_y));
variationv.emplace("fill_type", f->fillType());
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
variationv.emplace("border_color_1", format_color( f->border_color_1));
variationv.emplace("border_color_2", format_color( f->border_color_2));
variationv.emplace("center_x", String::Format(wxT("%.2f"), f->center_x));
variationv.emplace("center_y", String::Format(wxT("%.2f"), f->center_y));
variationv.emplace("end_x", String::Format(wxT("%.2f"), f->end_x));
variationv.emplace("end_y", String::Format(wxT("%.2f"), f->end_y));
}
variationsv.emplace_back(variationv);
}
@@ -765,34 +794,34 @@ boost::json::object mse_to_json(const StyleP& style) {
else if (InfoStyle* s = dynamic_cast<InfoStyle*>(style.get())) {
stylev.emplace("field_type", "info");
stylev.emplace("alignment", alignment_to_string( s->alignment));
stylev.emplace("padding_left", wxString::Format(wxT("%.2f"), s->padding_left));
stylev.emplace("padding_right", wxString::Format(wxT("%.2f"), s->padding_right));
stylev.emplace("padding_top", wxString::Format(wxT("%.2f"), s->padding_top));
stylev.emplace("padding_bottom", wxString::Format(wxT("%.2f"), s->padding_bottom));
stylev.emplace("background_color", format_color( s->background_color));
stylev.emplace("alignment", alignment_to_string( s->alignment));
stylev.emplace("padding_left", String::Format(wxT("%.2f"), s->padding_left));
stylev.emplace("padding_right", String::Format(wxT("%.2f"), s->padding_right));
stylev.emplace("padding_top", String::Format(wxT("%.2f"), s->padding_top));
stylev.emplace("padding_bottom", String::Format(wxT("%.2f"), s->padding_bottom));
stylev.emplace("background_color", format_color( s->background_color));
boost::json::object fontv;
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
fontv.emplace("name", s->font.name());
fontv.emplace("italic_name", s->font.italic_name());
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
fontv.emplace("weight", s->font.weight());
fontv.emplace("style", s->font.style());
fontv.emplace("underline", s->font.underline());
fontv.emplace("strikethrough", s->font.strikethrough());
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
fontv.emplace("color", format_color( s->font.color()));
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
fontv.emplace("separator_color", format_color( s->font.separator_color));
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
stylev.emplace("font", fontv);
}
return stylev;
+3 -3
View File
@@ -18,9 +18,9 @@ using boost::tribool;
// ----------------------------------------------------------------------------- : Reader
Reader::Reader(wxInputStream& input, Packaged* package, const String& filename, bool ignore_invalid)
Reader::Reader(wxInputStream& input, Packaged* package, const String& filename, bool ignore_invalid, bool suppress_warnings)
: indent(0), expected_indent(0), state(OUTSIDE)
, ignore_invalid(ignore_invalid)
, ignore_invalid(ignore_invalid), suppress_warnings(suppress_warnings)
, filename(filename), package(package), line_number(0), previous_line_number(0)
, input(input)
{
@@ -53,7 +53,7 @@ void Reader::warning(const String& msg, int line_number_delta, bool warn_on_prev
}
void Reader::showWarnings() {
if (!warnings.empty()) {
if (!suppress_warnings && !warnings.empty()) {
queue_message(MESSAGE_WARNING, _("Warnings while reading file:\n") + filename + _("\n") + warnings);
warnings.clear();
}
+3 -1
View File
@@ -38,7 +38,7 @@ public:
/** filename is used only for error messages
* package is used for looking up included files.
*/
Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = _(""), bool ignore_invalid = false);
Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = _(""), bool ignore_invalid = false, bool suppress_warnings = false);
~Reader() { showWarnings(); }
@@ -148,6 +148,8 @@ private:
} state;
/// Should all invalid keys be ignored?
bool ignore_invalid;
/// Should warnings be emitted?
bool suppress_warnings;
/// Filename for error messages
String filename;