Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

couple of enhancements #24

Merged
merged 8 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/rmscene/scene_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Line(SceneItem):
points: list[Point]
thickness_scale: float
starting_length: float
move_id: tp.Optional[CrdtId] = None


## Text
Expand All @@ -144,6 +145,7 @@ class ParagraphStyle(enum.IntEnum):
BOLD = 3
BULLET = 4
BULLET2 = 5
CHECKBOX = 6


END_MARKER = CrdtId(0, 0)
Expand Down
62 changes: 58 additions & 4 deletions src/rmscene/scene_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,34 @@ def to_stream(self, writer: TaggedBlockWriter):
writer.data.write_bytes(self.data)


@dataclass
class SceneInfo(Block):
BLOCK_TYPE: tp.ClassVar = 0x0D

def version_info(self, _) -> tuple[int, int]:
"""Return (min_version, current_version) to use when writing."""
return (0, 1)

current_layer: LwwValue[CrdtId]
background_visible: LwwValue[bool]
root_document_visible: LwwValue[bool]

@classmethod
def from_stream(cls, stream: TaggedBlockReader) -> SceneInfo:
current_layer = stream.read_lww_id(1)
background_visible = stream.read_lww_bool(2)
root_document_visible = stream.read_lww_bool(3)

return SceneInfo(current_layer=current_layer,
background_visible=background_visible,
root_document_visible=root_document_visible)

def to_stream(self, writer: TaggedBlockWriter):
writer.write_lww_id(1, self.current_layer)
writer.write_lww_bool(2, self.background_visible)
writer.write_lww_bool(3, self.root_document_visible)


@dataclass
class AuthorIdsBlock(Block):
BLOCK_TYPE: tp.ClassVar = 0x09
Expand Down Expand Up @@ -164,6 +192,12 @@ def to_stream(self, writer: TaggedBlockWriter):
class TreeNodeBlock(Block):
BLOCK_TYPE: tp.ClassVar = 0x02

def version_info(self, writer: TaggedBlockWriter) -> tuple[int, int]:
"""Return (min_version, current_version) to use when writing."""
version = writer.options.get("version", Version("9999"))
# XXX this is a guess about which version this changed in
return (1, 2) if (version >= Version("3.4")) else (1, 1)

group: si.Group

@classmethod
Expand Down Expand Up @@ -217,7 +251,7 @@ def version_info(self, _) -> tuple[int, int]:
merges_count: int
text_chars_count: int
text_lines_count: int
_unknown: int = 0
type_folio_use_count: int = 0

@classmethod
def from_stream(cls, stream: TaggedBlockReader) -> PageInfoBlock:
Expand All @@ -230,7 +264,7 @@ def from_stream(cls, stream: TaggedBlockReader) -> PageInfoBlock:
text_lines_count=stream.read_int(4),
)
if stream.bytes_remaining_in_block():
info._unknown = stream.read_int(5)
info.type_folio_use_count = stream.read_int(5)
return info

def to_stream(self, writer: TaggedBlockWriter):
Expand All @@ -241,7 +275,7 @@ def to_stream(self, writer: TaggedBlockWriter):
writer.write_int(4, self.text_lines_count)
version = writer.options.get("version", Version("9999"))
if version >= Version("3.2.2"):
writer.write_int(5, self._unknown)
writer.write_int(5, self.type_folio_use_count)


@dataclass
Expand Down Expand Up @@ -355,7 +389,12 @@ def line_from_stream(stream: TaggedBlockReader, version: int = 2) -> si.Line:
# XXX unused
timestamp = stream.read_id(6)

return si.Line(color, tool, points, thickness_scale, starting_length)
if stream.bytes_remaining_in_block() >= 3:
move_id = stream.read_id(7)
else:
move_id = None

return si.Line(color, tool, points, thickness_scale, starting_length, move_id)


def line_to_stream(line: si.Line, writer: TaggedBlockWriter, version: int = 2):
Expand All @@ -371,6 +410,8 @@ def line_to_stream(line: si.Line, writer: TaggedBlockWriter, version: int = 2):
# XXX didn't save
timestamp = CrdtId(0, 1)
writer.write_id(6, timestamp)
if line.move_id is not None:
writer.write_id(7, line.move_id)


@dataclass
Expand All @@ -395,6 +436,8 @@ def from_stream(cls, stream: TaggedBlockReader) -> SceneItemBlock:
subclass = SceneLineItemBlock
elif block_type == SceneTextItemBlock.BLOCK_TYPE:
subclass = SceneTextItemBlock
elif block_type == SceneTombstoneItemBlock.BLOCK_TYPE:
subclass = SceneTombstoneItemBlock
else:
raise ValueError(
"unknown scene type %d in %s" % (block_type, stream.current_block)
Expand Down Expand Up @@ -500,6 +543,17 @@ def glyph_range_to_stream(stream: TaggedBlockWriter, item: si.GlyphRange):
stream.data.write_float64(rect.h)


class SceneTombstoneItemBlock(SceneItemBlock):
BLOCK_TYPE: tp.ClassVar = 0x08

@classmethod
def value_from_stream(cls, reader: TaggedBlockReader):
pass

def value_to_stream(self, writer: TaggedBlockWriter, value):
pass


class SceneGlyphItemBlock(SceneItemBlock):
BLOCK_TYPE: tp.ClassVar = 0x03
ITEM_TYPE: tp.ClassVar = 0x01
Expand Down
Binary file added tests/data/With_SceneInfo_Block.rm
Binary file not shown.
12 changes: 8 additions & 4 deletions tests/test_scene_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def _hex_lines(b, n=32):
("Lines_v2_updated.rm", "3.2"), # extra 7fXXXX part of Line data was added
("Wikipedia_highlighted_p1.rm", "3.1"),
("Wikipedia_highlighted_p2.rm", "3.1"),
("With_SceneInfo_Block.rm", "3.4"), # XXX version?
],
)
def test_full_roundtrip(test_file, version):
Expand Down Expand Up @@ -259,15 +260,17 @@ def test_write_blocks():


def test_blocks_keep_unknown_data():
# The "7f 010f" is new, unknown data
# The "8f 010f" is represents new, unknown data -- note that this might need
# to be changed in future if the next id starts to actually be used in a
# future update!
data_hex = """
56000000 00020205
59000000 00020205
1f 0219
2f 021e
3f 0000
4f 0000
54 0000 0000
6c 4000 0000
6c 4300 0000
03
14 0f000000
24 00000000
Expand All @@ -278,11 +281,12 @@ def test_blocks_keep_unknown_data():
83c2622d 30c30000 08000000
6f 0001
7f 010f
8f 0101
"""
buf = BytesIO(HEADER_V6 + bytes.fromhex(data_hex))
block = next(read_blocks(buf))
assert isinstance(block, SceneLineItemBlock)
assert block.extra_data == bytes.fromhex("7f 010f")
assert block.extra_data == bytes.fromhex("8f 0101")


def test_error_in_block_contained():
Expand Down
Loading