Skip to content

Commit 2f4928a

Browse files
authored
♻️ refactor: use rust binding struct OptionComment (#318)
1 parent 4fcc115 commit 2f4928a

File tree

7 files changed

+86
-27
lines changed

7 files changed

+86
-27
lines changed

packages/biliass/rust/src/comment.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[derive(Debug, PartialEq)]
1+
#[derive(Debug, PartialEq, Clone)]
22
pub enum CommentPosition {
33
/// Regular moving comment
44
Scroll,
@@ -12,7 +12,7 @@ pub enum CommentPosition {
1212
Special,
1313
}
1414

15-
#[derive(Debug)]
15+
#[derive(Debug, PartialEq, Clone)]
1616
pub struct Comment {
1717
/// The position when the comment is replayed
1818
pub timeline: f64,

packages/biliass/rust/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fn biliass_pyo3(m: &Bound<'_, PyModule>) -> PyResult<()> {
2222
m.add_class::<python::PyDmSegMobileReply>()?;
2323
m.add_class::<python::PyDanmakuElem>()?;
2424
m.add_class::<python::PyComment>()?;
25+
m.add_class::<python::PyOptionComment>()?;
2526
m.add_class::<python::PyCommentPosition>()?;
2627
m.add_function(wrap_pyfunction!(python::py_read_comments_from_xml, m)?)?;
2728
m.add_function(wrap_pyfunction!(python::py_read_comments_from_protobuf, m)?)?;

packages/biliass/rust/src/python/comment.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,45 @@ impl PyComment {
9393
format!("Comment({:?})", self.inner)
9494
}
9595
}
96+
97+
#[pyclass(name = "OptionComment", frozen)]
98+
pub struct PyOptionComment {
99+
inner: Option<comment::Comment>,
100+
}
101+
102+
impl PyOptionComment {
103+
pub fn new(inner: Option<comment::Comment>) -> Self {
104+
PyOptionComment { inner }
105+
}
106+
}
107+
108+
#[pymethods]
109+
impl PyOptionComment {
110+
fn is_none(&self) -> bool {
111+
self.inner.is_none()
112+
}
113+
114+
fn is_some(&self) -> bool {
115+
self.inner.is_some()
116+
}
117+
118+
fn unwrap(&self) -> PyComment {
119+
PyComment::new(self.inner.clone().unwrap())
120+
}
121+
122+
#[staticmethod]
123+
fn from_comment(comment: &PyComment) -> Self {
124+
PyOptionComment {
125+
inner: Some(comment.inner.clone()),
126+
}
127+
}
128+
129+
#[staticmethod]
130+
fn none() -> Self {
131+
PyOptionComment { inner: None }
132+
}
133+
134+
fn __eq__(&self, other: &PyOptionComment) -> bool {
135+
self.inner == other.inner
136+
}
137+
}

packages/biliass/rust/src/python/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod proto;
33
mod reader;
44
mod writer;
55

6-
pub use comment::{PyComment, PyCommentPosition};
6+
pub use comment::{PyComment, PyCommentPosition, PyOptionComment};
77
pub use proto::{PyDanmakuElem, PyDmSegMobileReply};
88
pub use reader::{py_read_comments_from_protobuf, py_read_comments_from_xml};
99
pub use writer::{

packages/biliass/rust/src/python/writer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ pub fn py_convert_flash_rotation(
3939
rot_y, rot_z, x, y, width, height,
4040
))
4141
}
42+
43+
// #[pyfunction(name = "test_rows")]
44+
// pub fn py_test_rows(rows: Vec<Vec<PyRef<crate::python::PyOptionComment>>>) -> PyResult<()> {
45+
// Ok(())
46+
// }

packages/biliass/src/biliass/_core.pyi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ class Comment:
5555
height: float
5656
width: float
5757

58+
class OptionComment:
59+
def is_none(self) -> bool: ...
60+
def is_some(self) -> bool: ...
61+
def unwrap(self) -> Comment: ...
62+
@staticmethod
63+
def from_comment(comment: Comment) -> OptionComment: ...
64+
@staticmethod
65+
def none() -> OptionComment: ...
66+
5867
def read_comments_from_xml(text: str, fontsize: float) -> list[Comment]: ...
5968
def read_comments_from_protobuf(data: bytes, fontsize: float) -> list[Comment]: ...
6069
def convert_timestamp(timestamp: float) -> float: ...

packages/biliass/src/biliass/biliass.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
import math
88
import random
99
import re
10-
from typing import TYPE_CHECKING, TypeVar, Union
10+
from typing import TYPE_CHECKING, TypeVar
1111

1212
from biliass._core import (
1313
Comment,
1414
CommentPosition,
15+
OptionComment,
1516
ass_escape,
1617
convert_color,
1718
convert_flash_rotation,
@@ -26,7 +27,7 @@
2627

2728

2829
T = TypeVar("T")
29-
Rows = list[list[Union[Comment, None]]]
30+
Rows = list[list[OptionComment]]
3031

3132

3233
def read_comments_bilibili_xml(text: str | bytes, fontsize: float) -> list[Comment]:
@@ -228,23 +229,23 @@ def to_string(self):
228229

229230

230231
def process_comments(
231-
comments,
232-
width,
233-
height,
234-
bottom_reserved,
232+
comments: list[Comment],
233+
width: int,
234+
height: int,
235+
bottom_reserved: int,
235236
fontface,
236237
fontsize,
237238
alpha,
238-
duration_marquee,
239-
duration_still,
239+
duration_marquee: float,
240+
duration_still: float,
240241
filters_regex,
241242
reduced,
242243
progress_callback,
243244
):
244245
styleid = f"biliass_{random.randint(0, 0xFFFF):04x}"
245246
ass = AssText()
246247
ass.write_head(width, height, fontface, fontsize, alpha, styleid)
247-
rows = [[None] * (height - bottom_reserved + 1) for i in range(4)]
248+
rows = [[OptionComment.none()] * (height - bottom_reserved + 1) for i in range(4)]
248249
for idx, comment in enumerate(comments):
249250
if progress_callback and idx % 1000 == 0:
250251
progress_callback(idx, len(comments))
@@ -318,21 +319,21 @@ def test_free_rows(
318319
rows: Rows,
319320
comment: Comment,
320321
row: int,
321-
width,
322-
height,
323-
bottom_reserved,
324-
duration_marquee,
325-
duration_still,
326-
):
322+
width: int,
323+
height: int,
324+
bottom_reserved: int,
325+
duration_marquee: float,
326+
duration_still: float,
327+
) -> int:
327328
res = 0
328329
rowmax = height - bottom_reserved
329-
target_row = None
330+
target_row = OptionComment.none()
330331
comment_pos_id = comment.pos.id
331332
if comment.pos in (CommentPosition.Bottom, CommentPosition.Top):
332333
while row < rowmax and res < comment.height:
333334
if target_row != rows[comment_pos_id][row]:
334335
target_row = rows[comment_pos_id][row]
335-
if target_row and target_row.timeline + duration_still > comment.timeline:
336+
if target_row.is_some() and target_row.unwrap().timeline + duration_still > comment.timeline:
336337
break
337338
row += 1
338339
res += 1
@@ -345,9 +346,10 @@ def test_free_rows(
345346
if target_row != rows[comment_pos_id][row]:
346347
target_row = rows[comment_pos_id][row]
347348
try:
348-
if target_row and (
349-
target_row.timeline > threshold_time
350-
or target_row.timeline + target_row.width * duration_marquee / (target_row.width + width)
349+
if target_row.is_some() and (
350+
target_row.unwrap().timeline > threshold_time
351+
or target_row.unwrap().timeline
352+
+ target_row.unwrap().width * duration_marquee / (target_row.unwrap().width + width)
351353
> comment.timeline
352354
):
353355
break
@@ -362,9 +364,9 @@ def find_alternative_row(rows: Rows, comment: Comment, height, bottom_reserved):
362364
res = 0
363365
comment_pos_id = comment.pos.id
364366
for row in range(height - bottom_reserved - math.ceil(comment.height)):
365-
if not rows[comment_pos_id][row]:
367+
if rows[comment_pos_id][row].is_none():
366368
return row
367-
elif rows[comment_pos_id][row].timeline < rows[comment_pos_id][res].timeline:
369+
elif rows[comment_pos_id][row].unwrap().timeline < rows[comment_pos_id][res].unwrap().timeline:
368370
res = row
369371
return res
370372

@@ -373,7 +375,7 @@ def mark_comment_row(rows: Rows, comment: Comment, row: int):
373375
comment_pos_id = comment.pos.id
374376
try:
375377
for i in range(row, row + math.ceil(comment.height)):
376-
rows[comment_pos_id][i] = comment
378+
rows[comment_pos_id][i] = OptionComment.from_comment(comment)
377379
except IndexError:
378380
pass
379381

@@ -402,7 +404,7 @@ def Danmaku2ASS(
402404
stage_width: int,
403405
stage_height: int,
404406
input_format: str = "xml",
405-
reserve_blank: float = 0,
407+
reserve_blank: int = 0,
406408
font_face: str = "sans-serif",
407409
font_size: float = 25.0,
408410
text_opacity: float = 1.0,

0 commit comments

Comments
 (0)