Skip to content
Draft
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
5 changes: 4 additions & 1 deletion docs/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Positioning

Some caption formats support positioning information and PyCaption tries to preserve it when possible. In the process, some adjustments are made. Some of these adjustments can be customized by properly initializing the Writer class.

.. py:class:: BaseWriter(relativize=True, video_width=None, video_height=None, fit_to_screen=True)
.. py:class:: BaseWriter(relativize=True, video_width=None, video_height=None, fit_to_screen=True, include_positioning=True)

:param relativize: If True (default), converts absolute positioning
values (e.g. px) to percentage. ATTENTION: WebVTT does not support
Expand All @@ -163,6 +163,9 @@ Some caption formats support positioning information and PyCaption tries to pres
(re)calculate it based on origin. It is a pycaption fix for caption
files that are technically valid but contains inconsistent settings
that may cause long captions to be cut out of the screen.
:param include_positioning: If True (default), positioning information
is processed and included in the output. If False, all positioning
information is ignored and default positioning is used.

Examples
~~~~~~~~
Expand Down
9 changes: 8 additions & 1 deletion pycaption/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ def read(self, content):

class BaseWriter:
def __init__(
self, relativize=True, video_width=None, video_height=None, fit_to_screen=True
self, relativize=True, video_width=None, video_height=None, fit_to_screen=True,
include_positioning=True
):
"""
Initialize writer with the given parameters.
Expand All @@ -72,13 +73,19 @@ def __init__(
It is a pycaption fix for caption files that are technically valid
but contains inconsistent settings that may cause long captions to
be cut out of the screen.
:param include_positioning: If True (default), positioning information
is processed and included in the output. If False, all positioning
information is ignored and default positioning is used.
"""
self.relativize = relativize
self.video_width = video_width
self.video_height = video_height
self.fit_to_screen = fit_to_screen
self.include_positioning = include_positioning

def _relativize_and_fit_to_screen(self, layout_info):
if not self.include_positioning:
return None
if layout_info:
if self.relativize:
# Transform absolute values (e.g. px) into percentages
Expand Down
9 changes: 9 additions & 0 deletions pycaption/dfxp/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,16 @@ def write(self, caption_set, force=''):

# Loop through all captions/nodes and apply transformations to layout
# in function of the provided or default settings
caption_set.layout_info = self._relativize_and_fit_to_screen(
caption_set.layout_info)

for lang in langs:
# Also process the language-specific layout info
lang_layout_info = caption_set.get_layout_info(lang)
if hasattr(caption_set._captions[lang], 'layout_info'):
caption_set._captions[lang].layout_info = self._relativize_and_fit_to_screen(
lang_layout_info)

for caption in caption_set.get_captions(lang):
caption.layout_info = self._relativize_and_fit_to_screen(
caption.layout_info)
Expand Down
2 changes: 1 addition & 1 deletion pycaption/webvtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def _convert_positioning(self, layout):
:type layout: Layout
:rtype: str
"""
if not layout:
if not self.include_positioning or not layout:
return ""

# If it's converting from WebVTT to WebVTT, keep positioning info
Expand Down
56 changes: 55 additions & 1 deletion tests/test_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest

from pycaption.base import CaptionList, Caption
from pycaption.base import CaptionList, Caption, BaseWriter
from pycaption.geometry import Layout, Point, Size, UnitEnum


class TestCaption:
Expand Down Expand Up @@ -56,3 +57,56 @@ def test_add_two_caption_lists(self):

with pytest.raises(ValueError):
newcaps = self.caps + CaptionList([4], layout_info="Other Layout")


class TestBaseWriter:
def setup_method(self):
# Create a mock layout_info for testing
self.layout_info = Layout(
origin=Point(Size(10, UnitEnum.PERCENT), Size(20, UnitEnum.PERCENT))
)

def test_include_positioning_default_true(self):
"""Test that include_positioning defaults to True"""
writer = BaseWriter()
assert writer.include_positioning is True

def test_include_positioning_false(self):
"""Test that include_positioning can be set to False"""
writer = BaseWriter(include_positioning=False)
assert writer.include_positioning is False

def test_relativize_and_fit_to_screen_with_include_positioning_true(self):
"""Test that layout_info is processed when include_positioning=True"""
writer = BaseWriter(include_positioning=True, video_width=640, video_height=360)
result = writer._relativize_and_fit_to_screen(self.layout_info)
# Should return processed layout_info, not None
assert result is not None

def test_relativize_and_fit_to_screen_with_include_positioning_false(self):
"""Test that layout_info is ignored when include_positioning=False"""
writer = BaseWriter(include_positioning=False, video_width=640, video_height=360)
result = writer._relativize_and_fit_to_screen(self.layout_info)
# Should return None when positioning is disabled
assert result is None

def test_relativize_and_fit_to_screen_with_none_layout_info(self):
"""Test that None layout_info is handled correctly"""
writer = BaseWriter(include_positioning=True)
result = writer._relativize_and_fit_to_screen(None)
assert result is None

def test_relativize_and_fit_to_screen_with_none_layout_info_and_positioning_false(self):
"""Test that None layout_info returns None even when include_positioning=False"""
writer = BaseWriter(include_positioning=False)
result = writer._relativize_and_fit_to_screen(None)
assert result is None

def test_backward_compatibility_default_parameters(self):
"""Test that all BaseWriter parameters have appropriate defaults for backward compatibility"""
writer = BaseWriter()
assert writer.relativize is True
assert writer.video_width is None
assert writer.video_height is None
assert writer.fit_to_screen is True
assert writer.include_positioning is True