mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:37:35 +00:00
LibGfx/TIFF: Teach the generator how to handle tags of type Undefined
This tag type is a bit different as even if it fits in the general definition given in the TIFF specification. That is the value will be of one specified type multiplied by a known count. Having a `Vector<Variant<u8, ...>>` will be very painful to use. So let's deviate a bit from the normal way and use a `ByteBuffer` directly instead this complicated type.
This commit is contained in:
parent
24b9d05ea8
commit
62f28d9968
2 changed files with 30 additions and 5 deletions
|
@ -346,8 +346,13 @@ private:
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Byte:
|
case Type::Byte:
|
||||||
case Type::Undefined:
|
case Type::Undefined: {
|
||||||
return read_every_values.template operator()<u8>();
|
Vector<Value, 1> result;
|
||||||
|
auto buffer = TRY(ByteBuffer::create_uninitialized(count));
|
||||||
|
TRY(m_stream->read_until_filled(buffer));
|
||||||
|
result.append(move(buffer));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
case Type::ASCII:
|
case Type::ASCII:
|
||||||
case Type::UTF8: {
|
case Type::UTF8: {
|
||||||
Vector<Value, 1> result;
|
Vector<Value, 1> result;
|
||||||
|
@ -397,6 +402,9 @@ private:
|
||||||
if constexpr (TIFF_DEBUG) {
|
if constexpr (TIFF_DEBUG) {
|
||||||
if (tiff_value.size() == 1) {
|
if (tiff_value.size() == 1) {
|
||||||
tiff_value[0].visit(
|
tiff_value[0].visit(
|
||||||
|
[&](ByteBuffer& value) {
|
||||||
|
dbgln("Read tag({}), type({}): size {}", tag, to_underlying(type), value.size());
|
||||||
|
},
|
||||||
[&](auto const& value) {
|
[&](auto const& value) {
|
||||||
dbgln("Read tag({}), type({}): {}", tag, to_underlying(type), value);
|
dbgln("Read tag({}), type({}): {}", tag, to_underlying(type), value);
|
||||||
});
|
});
|
||||||
|
@ -404,6 +412,9 @@ private:
|
||||||
dbg("Read tag({}), type({}): [", tag, to_underlying(type));
|
dbg("Read tag({}), type({}): [", tag, to_underlying(type));
|
||||||
for (u32 i = 0; i < tiff_value.size(); ++i) {
|
for (u32 i = 0; i < tiff_value.size(); ++i) {
|
||||||
tiff_value[i].visit(
|
tiff_value[i].visit(
|
||||||
|
[&](ByteBuffer&) {
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
},
|
||||||
[&](auto const& value) {
|
[&](auto const& value) {
|
||||||
dbg("{}", value);
|
dbg("{}", value);
|
||||||
});
|
});
|
||||||
|
|
|
@ -103,6 +103,8 @@ def tiff_type_to_cpp(t: TIFFType, without_promotion: bool = False) -> str:
|
||||||
# Note that the Value<> type doesn't include u16 for this reason
|
# Note that the Value<> type doesn't include u16 for this reason
|
||||||
if not without_promotion:
|
if not without_promotion:
|
||||||
t = promote_type(t)
|
t = promote_type(t)
|
||||||
|
if t == TIFFType.Undefined:
|
||||||
|
return 'ByteBuffer'
|
||||||
if t == TIFFType.UnsignedShort:
|
if t == TIFFType.UnsignedShort:
|
||||||
return 'u16'
|
return 'u16'
|
||||||
if t == TIFFType.UnsignedLong:
|
if t == TIFFType.UnsignedLong:
|
||||||
|
@ -110,6 +112,15 @@ def tiff_type_to_cpp(t: TIFFType, without_promotion: bool = False) -> str:
|
||||||
raise RuntimeError(f'Type "{t}" not recognized, please update tiff_type_to_read_only_cpp()')
|
raise RuntimeError(f'Type "{t}" not recognized, please update tiff_type_to_read_only_cpp()')
|
||||||
|
|
||||||
|
|
||||||
|
def is_container(t: TIFFType) -> bool:
|
||||||
|
"""
|
||||||
|
Some TIFF types are defined on the unit scale but are intended to be used within a collection.
|
||||||
|
An example of that are ASCII strings defined as N * byte. Let's intercept that and generate
|
||||||
|
a nice API instead of Vector<u8>.
|
||||||
|
"""
|
||||||
|
return t in [TIFFType.Byte, TIFFType.Undefined]
|
||||||
|
|
||||||
|
|
||||||
def export_promoter() -> str:
|
def export_promoter() -> str:
|
||||||
output = R"""template<typename T>
|
output = R"""template<typename T>
|
||||||
struct TypePromoter {
|
struct TypePromoter {
|
||||||
|
@ -137,7 +148,8 @@ def pascal_case_to_snake_case(name: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def generate_getter(tag: Tag) -> str:
|
def generate_getter(tag: Tag) -> str:
|
||||||
variant_inner_type = tiff_type_to_cpp(retrieve_biggest_type(tag.types))
|
biggest_type = retrieve_biggest_type(tag.types)
|
||||||
|
variant_inner_type = tiff_type_to_cpp(biggest_type)
|
||||||
|
|
||||||
extracted_value_template = f"(*possible_value)[{{}}].get<{variant_inner_type}>()"
|
extracted_value_template = f"(*possible_value)[{{}}].get<{variant_inner_type}>()"
|
||||||
|
|
||||||
|
@ -146,8 +158,10 @@ def generate_getter(tag: Tag) -> str:
|
||||||
tag_final_type = f"TIFF::{tag.associated_enum.__name__}"
|
tag_final_type = f"TIFF::{tag.associated_enum.__name__}"
|
||||||
extracted_value_template = f"static_cast<{tag_final_type}>({extracted_value_template})"
|
extracted_value_template = f"static_cast<{tag_final_type}>({extracted_value_template})"
|
||||||
|
|
||||||
if len(tag.counts) == 1 and tag.counts[0] == 1:
|
if len(tag.counts) == 1 and tag.counts[0] == 1 or is_container(biggest_type):
|
||||||
return_type = tag_final_type
|
return_type = tag_final_type
|
||||||
|
if is_container(biggest_type):
|
||||||
|
return_type += ' const&'
|
||||||
unpacked_if_needed = f"return {extracted_value_template.format(0)};"
|
unpacked_if_needed = f"return {extracted_value_template.format(0)};"
|
||||||
else:
|
else:
|
||||||
if len(tag.counts) == 1:
|
if len(tag.counts) == 1:
|
||||||
|
@ -231,7 +245,7 @@ struct Rational {{
|
||||||
{export_promoter()}
|
{export_promoter()}
|
||||||
|
|
||||||
// Note that u16 is not include on purpose
|
// Note that u16 is not include on purpose
|
||||||
using Value = Variant<u8, String, u32, Rational<u32>, i32, Rational<i32>>;
|
using Value = Variant<ByteBuffer, String, u32, Rational<u32>, i32, Rational<i32>>;
|
||||||
|
|
||||||
{export_tag_related_enums(known_tags)}
|
{export_tag_related_enums(known_tags)}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue