From 8a581ed59ebf45b80c2b3372bc3db313d1cd9666 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Thu, 7 Mar 2019 18:22:34 +0100 Subject: [PATCH] huge abr refactoring --- src/abr.cpp | 213 +++++-------------------------- src/abr.h | 361 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 319 insertions(+), 255 deletions(-) diff --git a/src/abr.cpp b/src/abr.cpp index 02896ba..64755ec 100644 --- a/src/abr.cpp +++ b/src/abr.cpp @@ -2,6 +2,27 @@ #include "abr.h" #include "log.h" +SerializedStream::Type::Ref SerializedStream::instanciate(const std::string& key) +{ + if (m_ctor_table.find(key) != m_ctor_table.end()) + return m_ctor_table[key](); + return nullptr; +} + +std::map> SerializedStream::m_ctor_table = +{ + { "VlLs", []{ return std::make_shared(); } }, + { "TEXT", []{ return std::make_shared(); } }, + { "Objc", []{ return std::make_shared(); } }, + { "UntF", []{ return std::make_shared(); } }, + { "bool", []{ return std::make_shared(); } }, + { "long", []{ return std::make_shared(); } }, + { "doub", []{ return std::make_shared(); } }, + { "enum", []{ return std::make_shared(); } }, + { "tdta", []{ return std::make_shared(); } }, +}; + + bool ABR::section_desc() { auto sz = align4(ru32()); @@ -13,8 +34,9 @@ bool ABR::section_desc() // presets list auto name = rkey_or_string(); // "Brsh" auto list = rstring(4); // "VlLs" - if (auto presets = std::dynamic_pointer_cast(call(list))) + if (auto presets = std::dynamic_pointer_cast(instanciate(list))) { + presets->read(*this); for (auto const& pr : presets->items) { if (auto desc = std::dynamic_pointer_cast(pr)) @@ -42,8 +64,8 @@ bool ABR::section_samp() auto uid = rpascal(); //printf("sample brush %s\n", uid.c_str()); skip(4); // unknown bytes usually 00 01 00 00 - auto vm = parse_vmem(); - if (vm) + auto vm = std::make_shared(); + if (vm->read(*this)) { if (auto img = vm->image(true, true)) { @@ -74,7 +96,8 @@ bool ABR::section_patt() snap(); continue; } - auto point = rpoint(); + Point point; + point.read(*this); auto name = rwstring(); auto uid = rpascal(); @@ -83,8 +106,8 @@ bool ABR::section_patt() // read(...); // no worries indexed is skipped anyway - auto vm = parse_vmem(); - if (vm) + auto vm = std::make_shared(); + if (vm->read(*this)) { int nc = std::min((int)vm->channels.size(), 3); if (nc != image_mode) @@ -349,184 +372,6 @@ std::vector> ABR::compute_brushes(const std::string& path return ret; } -std::shared_ptr SerializedStreamReader::parse_vmem() -{ - // Virtual Memory Array List - auto vmem_version = ru32(); // = 3 - assert(vmem_version == 3); - auto vmem_length = ru32(); - // TODO: check if at the end there's good data - // check if the bounds are within the parent's size - auto vmem_rect = rrect(); - auto vmem_channels = ru32(); - // The following is a virtual memory array, - // repeated for the number of channels - // + one for a user mask + one for a sheet mask. - vmem_channels += 2; // user and sheet mask - auto ret = std::make_shared(vmem_version, vmem_rect); - for (int ch = 0; ch < vmem_channels; ch++) - { - auto array_written = ru32(); // skip if 0 - if (array_written == 0) - continue; - auto length = ru32(); // skip if 0, length is from the next field to the end - if (length == 0) - continue; - auto depth = ru32(); // Pixel depth: 1, 8, 16 or 32 - auto rect = rrect(); - auto depth2 = ru16(); // again? - auto compression = ru8(); // 1 = zip - if (depth != 8) - { - LOG("unsupported depth %d bits\n", depth); - skip(length - 23); - continue; - } - if (compression == 0) - { - int data_size = (depth >> 3) * rect.area(); - ret->channels.emplace_back(depth, rect, compression, rraw(data_size)); - } - else if (compression == 1) - { - auto start = pos(); - auto height = rect.height(); - // contain the compressed length of each scanline - std::vector scanlines; - scanlines.reserve(height); - for (int i = 0; i < height; i++) - scanlines.push_back(ru16()); - std::vector raw; - for (auto sl : scanlines) - { - auto decoded = rrle(sl); - raw.insert(raw.end(), decoded.begin(), decoded.end()); - } - ret->channels.emplace_back(depth, rect, compression, raw); - auto len = pos() - start; - } - else - { - LOG("unsupported compression mode %d\n", compression); - skip(length - 23); - continue; - } - } - snap(); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_vlls() -{ - auto ret = std::make_shared(); - auto count = ru32(); - //printf("list: %d\n", count); - for (int i = 0; i < count; i++) - { - auto type = rstring(4); - auto item = call(type); - if (!item) - return nullptr; - ret->items.push_back(item); - } - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_text() -{ - auto ret = std::make_shared(); - ret->value = rwstring(); - //wprintf(L"text: %s\n", ret->value.c_str()); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_objc() -{ - auto ret = std::make_shared(); - ret->name = rwstring(); - ret->class_id = rkey_or_string(); - auto count = ru32(); - //printf("objc type %s, %d props\n", ret->class_id.c_str(), count); - for (int i = 0; i < count; i++) - { - auto key = rkey_or_string(); - auto type = rstring(4); - //printf("prop %s\n", t.c_str()); - auto property = call(type); - if (!property) - return nullptr; - if (ret->props.find(key) != ret->props.end()) - LOG("DUPLICATE prop %s\n", key.c_str()); - ret->props[key] = property; - } - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_untf() -{ - auto ret = std::make_shared(); - ret->unit = rstring(4); - ret->value = rdbl(); - //printf("float %s: %f\n", ret->unit.c_str(), ret->value); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_bool() -{ - auto ret = std::make_shared(); - ret->value = ru8(); - //printf("bool: %s\n", ret->value ? "true" : "false"); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_long() -{ - auto ret = std::make_shared(); - ret->value = ru32(); - //printf("long: %d\n", ret->value); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_doub() -{ - auto ret = std::make_shared(); - ret->value = rdbl(); - //printf("double: %d\n", ret->value); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_enum() -{ - auto ret = std::make_shared(); - ret->type = rkey_or_string(); - ret->value = rkey_or_string(); - //printf("enum: %s %s\n", t.c_str(), e.c_str()); - return ret; -} - -std::shared_ptr SerializedStreamReader::parse_tdta() -{ - auto ret = std::make_shared(); - ret->data = rraw(); - return ret; -} - -SerializedStreamReader::SerializedStreamReader() -{ - m_parser_table = std::map> - { - { "VlLs", std::bind(&SerializedStreamReader::parse_vlls, this) }, - { "TEXT", std::bind(&SerializedStreamReader::parse_text, this) }, - { "Objc", std::bind(&SerializedStreamReader::parse_objc, this) }, - { "UntF", std::bind(&SerializedStreamReader::parse_untf, this) }, - { "bool", std::bind(&SerializedStreamReader::parse_bool, this) }, - { "long", std::bind(&SerializedStreamReader::parse_long, this) }, - { "doub", std::bind(&SerializedStreamReader::parse_doub, this) }, - { "enum", std::bind(&SerializedStreamReader::parse_enum, this) }, - { "tdta", std::bind(&SerializedStreamReader::parse_tdta, this) }, - }; -} - bool ABR::open(const std::string& path) { Asset asset; diff --git a/src/abr.h b/src/abr.h index 893e675..e69e95b 100644 --- a/src/abr.h +++ b/src/abr.h @@ -176,6 +176,13 @@ public: } return data; } + std::string rkey_or_string() + { + auto len = ru32(); + if (len == 0) + len = 4; + return rstring(len); + } protected: template inline T align4(T x) { return ((x - T{1}) & (~(T{3}))) + T{4}; } template T read() @@ -240,12 +247,21 @@ public: wu32(s.size()); write(s.data(), s.size()); } + void wstring_raw(std::string s) + { + write(s.data(), s.size()); + } void wwstring(std::wstring s) { wu32(s.size()); std::wstring_convert> converter; wstring(converter.to_bytes(s)); } + void wwstring_raw(std::wstring s) + { + std::wstring_convert> converter; + wstring(converter.to_bytes(s)); + } void wpascal(std::string s) { wu8(s.size()); @@ -293,6 +309,10 @@ public: idx = seq.first + seq.second; } } + void wkey_or_string(std::string s) + { + wstring(s); + } protected: template void write(T x) { @@ -318,13 +338,24 @@ public: { return "type"; } + virtual bool read(BinaryStreamReader& r) { return false; } + virtual void write(BinaryStreamWriter& w) const { } + virtual std::string type_key() const { return ""; } }; struct Class : public Type { }; struct Property : public Type { }; struct Reference : public Type { }; + struct EnumRef : public Type { }; + struct Offset : public Type { }; + struct Identifier : public Type { }; + struct Index : public Type { }; + struct Name : public Type { }; + struct LargeInteger : public Type { }; + struct Alias : public Type { }; struct List : public Type { Type::Vec items; + virtual std::string type_key() const override { return "VlLs"; } virtual std::string str(int indent, const std::string& prefix) const override { auto ret = std::string(indent, '-') + fmt::format("list: {} items:", items.size()); @@ -332,68 +363,169 @@ public: ret += "\n" + items[i]->str(indent + 1, fmt::format("{}) ", i)); return ret; } + virtual bool read(BinaryStreamReader& r) override + { + auto count = r.ru32(); + for (int i = 0; i < count; i++) + { + auto type = r.rstring(4); + auto item = instanciate(type); + if (!item || !item->read(r)) + return false; + items.push_back(item); + } + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wi32(items.size()); + for (auto& i : items) + i->write(w); + } }; struct Double : public Type { using native_type = double; double value; + virtual std::string type_key() const override { return "doub"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("double: {}", value); } + { + return std::string(indent, '-') + prefix + fmt::format("double: {}", value); + } + virtual bool read(BinaryStreamReader& r) override + { + value = r.rdbl(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wdbl(value); + } }; struct UnitFloat : public Type { using native_type = double; std::string unit; double value; + virtual std::string type_key() const override { return "UntF"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("float: {} ({})", value, unit); } + { + return std::string(indent, '-') + prefix + fmt::format("float: {} ({})", value, unit); + } + virtual bool read(BinaryStreamReader& r) override + { + unit = r.rstring(4); + value = r.rdbl(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wstring_raw(unit); + w.wdbl(value); + } }; struct String : public Type { using native_type = std::wstring; std::wstring value; + virtual std::string type_key() const override { return "TEXT"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("string: {}", wstr2str(value)); } + { + return std::string(indent, '-') + prefix + fmt::format("string: {}", wstr2str(value)); + } + virtual bool read(BinaryStreamReader& r) override + { + value = r.rwstring(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wwstring(value); + } }; struct Enum : public Type { std::string type; std::string value; + virtual std::string type_key() const override { return "enum"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("enum {}: {}", type, value); } + { + return std::string(indent, '-') + prefix + fmt::format("enum {}: {}", type, value); + } + virtual bool read(BinaryStreamReader& r) override + { + type = r.rkey_or_string(); + value = r.rkey_or_string(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wkey_or_string(type); + w.wkey_or_string(value); + } }; - struct EnumRef : public Type { }; - struct Offset : public Type { }; - struct Identifier : public Type { }; - struct Index : public Type { }; - struct Name : public Type { }; struct Integer : public Type { using native_type = int32_t; int32_t value; + virtual std::string type_key() const override { return "long"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("int: {}", value); } + { + return std::string(indent, '-') + prefix + fmt::format("int: {}", value); + } + virtual bool read(BinaryStreamReader& r) override + { + value = r.ri32(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wi32(value); + } }; - struct LargeInteger : public Type { }; struct Boolean : public Type { using native_type = bool; bool value; + virtual std::string type_key() const override { return "bool"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("bool: {}", value); } + { + return std::string(indent, '-') + prefix + fmt::format("bool: {}", value); + } + virtual bool read(BinaryStreamReader& r) override + { + value = r.ru8(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wu8(value); + } }; - struct Alias : public Type { }; struct RawData : public Type { std::vector data; + virtual std::string type_key() const override { return "tdta"; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("raw: {} bytes", data.size()); } + { + return std::string(indent, '-') + prefix + fmt::format("raw: {} bytes", data.size()); + } + virtual bool read(BinaryStreamReader& r) override + { + data = r.rraw(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wraw(data); + } }; struct Descriptor : public Type { std::wstring name; std::string class_id; Type::Map props; + virtual std::string type_key() const override { return "Objc"; } virtual std::string str(int indent, const std::string& prefix) const override { auto ret = std::string(indent, '-') + prefix + @@ -427,6 +559,37 @@ public: if (auto v = get(key)) dest = static_cast(v->value); } + virtual bool read(BinaryStreamReader& r) override + { + name = r.rwstring(); + class_id = r.rkey_or_string(); + auto count = r.ru32(); + for (int i = 0; i < count; i++) + { + auto key = r.rkey_or_string(); + auto type = r.rstring(4); + //printf("prop %s\n", t.c_str()); + auto p = instanciate(type); + if (!p || !p->read(r)) + return false; + if (props.find(key) != props.end()) + LOG("DUPLICATE prop %s\n", key.c_str()); + props[key] = p; + } + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wwstring(name); + w.wkey_or_string(class_id); + w.wu32(props.size()); + for (auto& p : props) + { + w.wkey_or_string(p.first); + w.wstring(p.second->type_key()); + p.second->write(w); + } + } }; struct Rectangle : public Type { @@ -438,14 +601,44 @@ public: uint32_t width() const { return right - left; } uint32_t height() const { return bottom - top; } virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("rect: [{}, {}, {}, {}]", top, left, bottom, right); } + { + return std::string(indent, '-') + prefix + fmt::format("rect: [{}, {}, {}, {}]", top, left, bottom, right); + } + virtual bool read(BinaryStreamReader& r) override + { + top = r.ru32(); + left = r.ru32(); + bottom = r.ru32(); + right = r.ru32(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wu32(top); + w.wu32(left); + w.wu32(bottom); + w.wu32(right); + } }; struct Point : public Type { uint32_t x; uint32_t y; virtual std::string str(int indent, const std::string& prefix) const override - { return std::string(indent, '-') + prefix + fmt::format("point: [{}, {}]", x, y); } + { + return std::string(indent, '-') + prefix + fmt::format("point: [{}, {}]", x, y); + } + virtual bool read(BinaryStreamReader& r) override + { + x = r.ru32(); + y = r.ru32(); + return true; + } + virtual void write(BinaryStreamWriter& w) const override + { + w.wu32(x); + w.wu32(y); + } }; struct Channel : public Type { @@ -454,8 +647,54 @@ public: uint8_t compression; std::vector data; Channel() = default; - Channel(uint32_t depth, Rectangle rect, uint8_t compression, std::vector data) : - depth(depth), rect(rect), compression(compression), data(std::move(data)) { } + //Channel(uint32_t depth, Rectangle rect, uint8_t compression, std::vector data) : + // depth(depth), rect(rect), compression(compression), data(std::move(data)) { } + virtual bool read(BinaryStreamReader& r) override + { + auto length = r.ru32(); // skip if 0, length is from the next field to the end + if (length == 0) + return true; + depth = r.ru32(); // Pixel depth: 1, 8, 16 or 32 + rect.read(r); + auto depth2 = r.ru16(); // again? + compression = r.ru8(); // 1 = zip + if (depth != 8) + { + LOG("unsupported depth %d bits\n", depth); + r.skip(length - 23); + return true; + } + if (compression == 0) + { + int data_size = (depth >> 3) * rect.area(); + data = r.rraw(data_size); + } + else if (compression == 1) + { + auto start = r.pos(); + auto height = rect.height(); + // contain the compressed length of each scanline + std::vector scanlines; + scanlines.reserve(height); + for (int i = 0; i < height; i++) + scanlines.push_back(r.ru16()); + for (auto sl : scanlines) + { + auto decoded = r.rrle(sl); + data.insert(data.end(), decoded.begin(), decoded.end()); + } + auto len = r.pos() - start; + } + else + { + LOG("unsupported compression mode %d\n", compression); + r.skip(length - 23); + return true; + } + } + virtual void write(BinaryStreamWriter& w) const override + { + } }; struct VMArray : public Type { @@ -463,7 +702,7 @@ public: Rectangle rect; std::vector channels; VMArray() = default; - VMArray(uint32_t version, const Rectangle& rect) : version(version), rect(rect) { } + //VMArray(uint32_t version, const Rectangle& rect) : version(version), rect(rect) { } std::shared_ptr image(bool grayscale, bool invert) const { int nc = channels.size(); @@ -518,62 +757,42 @@ public: } return nullptr; } - }; -}; - -class SerializedStreamReader : public SerializedStream, public BinaryStreamReader -{ -public: - std::shared_ptr parse_vmem(); // Parse Virtual Memory Array List - std::shared_ptr parse_vlls(); - std::shared_ptr parse_text(); - std::shared_ptr parse_objc(); - std::shared_ptr parse_untf(); - std::shared_ptr parse_bool(); - std::shared_ptr parse_long(); - std::shared_ptr parse_doub(); - std::shared_ptr parse_enum(); - std::shared_ptr parse_tdta(); - - std::map> m_parser_table; - SerializedStreamReader(); - - std::string rkey_or_string() - { - auto len = ru32(); - if (len == 0) - len = 4; - return rstring(len); - } - Rectangle rrect() - { - Rectangle ret; - ret.top = ru32(); - ret.left = ru32(); - ret.bottom = ru32(); - ret.right = ru32(); - return ret; - } - Point rpoint() - { - Point ret; - ret.x = ru16(); - ret.y = ru16(); - return ret; - } - - Type::Ref call(std::string t) - { - if (m_parser_table.find(t) != m_parser_table.end()) + virtual bool read(BinaryStreamReader& r) override { - auto& method = m_parser_table[t]; - return method(); + // Virtual Memory Array List + version = r.ru32(); // = 3 + assert(version == 3); + auto vmem_length = r.ru32(); + // TODO: check if at the end there's good data + // check if the bounds are within the parent's size + rect.read(r); + auto vmem_channels = r.ru32(); + // The following is a virtual memory array, + // repeated for the number of channels + // + one for a user mask + one for a sheet mask. + vmem_channels += 2; // user and sheet mask + for (int ch = 0; ch < vmem_channels; ch++) + { + auto array_written = r.ru32(); // skip if 0 + if (array_written == 0) + continue; + channels.emplace_back(); + if (!channels.back().read(r)) + return false; + } + r.snap(); + return true; } - return nullptr; - } + virtual void write(BinaryStreamWriter& w) const override + { + } + }; +protected: + static Type::Ref instanciate(const std::string& key); + static std::map> m_ctor_table; }; -class ABR : private SerializedStreamReader +class ABR : public SerializedStream, public BinaryStreamReader { bool section_desc(); bool section_samp();