Skip to content
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
- FormFit과 쪽 수 추정이 텍스트 내보내기가 쓰지 않는 번호 형식(`KOREAN_DIGIT`, `HANGUL` 등)의 문단 번호를 만나도
멈추지 않는다. 한/글이 재는 번호(`useInstWidth`)이면 그 숫자를 한글 한 글자 폭으로 잰다. 전에는 번호가 자기 글자
모양을 가진 문단에서 `KeyError`가 났다.
- 쪽 수 추정이 `hp:colPr@sameSz`와 각주 `hp:placement@beneathText`의 `true`를 `1`과 같이 읽는다(xs:boolean). 전에는
`sameSz="true"`인 같은 폭 다단을 폭이 다른 다단으로 보고 추정하지 않았다.
- `.hwp`를 열 때 그림의 투명도와 반전을 한/글이 읽는 자리에서 읽는다. 한/글은 그림 레코드의 투명도를 그림 원래 크기
뒤 마지막 바이트에서 읽고, 바이너리 항목 번호 뒤 바이트는 읽지 않는다(저장할 때 0으로 쓴다). 전에는 그 바이트를
투명도로 옮겨, 거기에 255가 든 문서의 그림이 HWPX에서 보이지 않았다. 반전(`hp:pic@reverse`)은 그림 개체 속성의
Expand Down
10 changes: 8 additions & 2 deletions src/hwpx/layout/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -1427,13 +1427,19 @@ def _first_columns(section: Any) -> Any:
return next((cols for cols in section.iter(f"{HP}colPr") if not _in_sub_list(cols)), None)


def _true(value: Any) -> bool:
"""Whether an ``xs:boolean`` attribute *value* is true: ``1`` or ``true`` (Hancom writes ``1``)."""

return value in ("1", "true")


def _column_layout(settings: Any, text_width: int) -> tuple[int, int, tuple[int, ...], int]:
""":func:`_columns` of the column settings *settings* (``hp:colPr``; ``None``: one column)."""

count = int(settings.get("colCount", "1")) if settings is not None else 1
if count <= 1:
return 1, text_width, (), 0
if settings.get("sameSz") != "1": # each column takes its share of 32768 of the text width (hp:colSz),
if not _true(settings.get("sameSz")): # each column takes its share of 32768 of the text width (hp:colSz),
sizes = settings.findall(f"{HP}colSz") # rounded, whatever the shares add up to
total = sum(int(size.get("width", 0)) + int(size.get("gap", 0)) for size in sizes)
if len(sizes) != count or total <= 0:
Expand Down Expand Up @@ -1502,7 +1508,7 @@ def _note_shape(section: Any) -> _NoteShape:
if settings is None:
return _NoteShape()
placement = settings.find(f"{HP}placement")
if placement is not None and placement.get("beneathText") == "1":
if placement is not None and _true(placement.get("beneathText")):
raise _Unsupported("footnotes beneath the text")
spacing = settings.find(f"{HP}noteSpacing")
rule = settings.find(f"{HP}noteLine")
Expand Down
21 changes: 21 additions & 0 deletions tests/test_layout_page_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,27 @@ def test_the_multi_column_sample_breaks_its_lines_at_each_column_width_without_c
_assert_like_hancom(estimate_pages(_without_caches(data)), data, 2)


def test_columns_of_the_same_size_written_as_true_are_of_the_same_size() -> None:
# hp:colPr@sameSz is an xs:boolean: "true" is "1" (Hancom writes "1"; other writers "true").
document = HwpxDocument.new()
document.page.set_columns(2)
for number in range(80):
document.add_paragraph(f"{number} 단 나누기 문단입니다")
data = document.to_bytes()
out = io.BytesIO()
with zipfile.ZipFile(io.BytesIO(data)) as source, zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as target:
for info in source.infolist():
payload = source.read(info.filename)
if info.filename.startswith("Contents/section"):
payload = re.sub(rb'(colCount="2"[^>]*)sameSz="1"', rb'\1sameSz="true"', payload)
target.writestr(info, payload)
assert b'sameSz="true"' in zipfile.ZipFile(out).read("Contents/section0.xml")

ones, trues = estimate_pages(data), estimate_pages(out.getvalue())

assert (trues.unsupported, trues.pages, trues.lines) == ((), ones.pages, ones.lines)


def test_a_footnote_in_a_paragraph_without_a_cache_in_columns_of_unequal_width_is_not_followed() -> None:
document = HwpxDocument.new()
document.set_columns(2, same_size=False, column_widths=[(10632, 873), (21263, 0)])
Expand Down
Loading