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 @@ -128,6 +128,8 @@
- 쪽 수 추정(실험, `estimate_pages`)이 run의 `hp:switch` 안에 든 개체(차트와 그것을 대신하는 OLE 개체 등)가 있는 구역을
지원 밖으로 둔다(`an object in a switch (hp:switch)`). 한/글은 그런 개체도 자리를 차지해 곁의 줄을 좁히는데, 전에는
개체가 없는 것처럼 추정했다.
- FormFit과 쪽 수 추정이 묶음 빈칸(`hp:nbSpace`)에 장평만 적용하고 자간은 적용하지 않는다. 한/글이 그렇게 놓는다(9pt
장평 120 %·자간 −12 %에서 536, 전에는 472). 공백과 고정폭 빈칸은 전과 같다.
- FormFit과 쪽 수 추정에서 `!`의 반 em을 공백처럼 배치 단위(1/1800인치)로 내림한다. 9·11·13pt처럼 글자 크기의 4분의 1이
홀수인 크기에서 `!`가 4 넓게 잡혀, 그 뒤 탭 폭이 한/글보다 4 좁았다.
- FormFit과 쪽 수 추정이 공백 뒤의 닫는 문장부호(`!`·`?`·`)`·`%`·`」`·`·` 등 줄 머리에 오지 않는 문자 모두)로 줄을
Expand Down
6 changes: 4 additions & 2 deletions src/hwpx/form_fit/measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,8 @@ class TextStyle:
the Hangul script's; ``scripts`` holds ``(script, 장평, 자간)`` for the
Latin, symbol and Hanja scripts when the character shape gives them values
of their own, and each glyph takes its script's (see :func:`glyph_script`).
A space keeps the Hangul 장평 and takes the Latin 자간.
A space keeps the Hangul 장평 and takes the Latin 자간; a no-break space
takes the 장평 and no 자간.
``break_non_latin_word`` works the reverse of its name in Hancom:
``BREAK_WORD`` (the default) keeps Hangul words whole and ``KEEP_WORD``
breaks between any two syllables; ``break_latin_word`` works as named.
Expand Down Expand Up @@ -1499,7 +1500,8 @@ def char_advance(ch: str, font_pt: float, style: TextStyle | None = None) -> flo
return float(height // _LAYOUT_UNIT // 4 * _LAYOUT_UNIT)
ratio, spacing = _scaling(ch, style)
if ch in _HALF_EM_SPACES and not style.use_font_space:
return _laid_out_space(height, ratio, spacing)
# a no-break space takes its 장평 but no 자간
return _laid_out_space(height, ratio, 0.0 if ch == " " else spacing)
face = style.hangul_face if cls == "hangul" else style.glyph_face
if emoji:
design, base = _EMOJI_UNITS, _ADVANCE_EM[cls]
Expand Down
Binary file not shown.
19 changes: 19 additions & 0 deletions tests/test_form_fit_hancom_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import pytest

from hwpx.document import HwpxDocument
from hwpx.layout import pages as page_layout
from hwpx.form_fit import (
FitEngine,
FitPolicy,
Expand Down Expand Up @@ -58,6 +59,7 @@
PARAGRAPH_MARGINS = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_paragraph_margins.hwpx"
PARAGRAPH_SPACING = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_paragraph_spacing.hwpx"
BOLD_ADVANCES = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_bold_advances.hwpx"
SPACE_SCALING = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_space_scaling.hwpx"

CHARS = TextStyle(break_non_latin_word="KEEP_WORD") # Hancom 글자 단위
SPACE_RUNS = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_space_runs.hwpx"
Expand Down Expand Up @@ -417,6 +419,23 @@ def test_bold_glyphs_take_the_advances_hancom_lays_them_out_at() -> None:
assert bold_seen


def test_a_no_break_space_takes_its_ratio_and_no_spacing() -> None:
# Hancom laid "가", three no-break spaces (hp:nbSpace), fixed-width spaces or spaces and a tab out at 9, 10
# and 14 pt in 맑은 고딕 under several 장평 and 자간: the tab's width shows how wide the spaces are. A
# no-break space takes the 장평 but no 자간 (at 120 % and -12 % a 9 pt one is 536, not 472).
assert char_advance(" ", 9, TextStyle(ratio=120, spacing=-12)) == 536
assert char_advance(" ", 9, TextStyle(ratio=120, spacing=-12)) == 472
document = HwpxDocument.open(SPACE_SCALING)
for paragraph in document.oxml.sections[0].element.findall(f"{HP}p")[1:]:
runs = paragraph.findall(f"{HP}run")
ref = runs[0].get("charPrIDRef")
style = text_style_from_refs(document, paragraph.get("paraPrIDRef"), [ref])
size = int(document.oxml.char_property(ref).attributes["height"]) / 100
text = page_layout._run_text(runs)
x = sum(char_advance(ch, size, style) for ch in text[:text.index(" ")])
assert round((x // 4000 + 1) * 4000 - x) == int(paragraph.find(f".//{HP}tab").get("width"))


def test_a_hangul_syllable_takes_its_own_advance_where_the_font_gives_it_one() -> None:
# 한컴 말랑말랑 Regular's font draws the syllables with a horizontal vowel (ㅗ ㅛ ㅜ ㅠ ㅡ) 820 of 1000 units
# wide and the others 880; the faces whose syllables are all one width keep it.
Expand Down
Loading