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

Windows/css keywords #3214

Closed
Closed
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
17 changes: 15 additions & 2 deletions core/src/toga/style/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from travertino.colors import rgb, hsl

from travertino.constants import ( # noqa: F401
ABSOLUTE_FONT_SIZES,
BOLD,
BOTTOM,
CENTER,
Expand All @@ -23,6 +24,7 @@
NONE,
NORMAL,
OBLIQUE,
RELATIVE_FONT_SIZES,
RIGHT,
ROW,
RTL,
Expand Down Expand Up @@ -107,7 +109,12 @@ class IntrinsicSize(BaseIntrinsicSize):
font_style: str = validated_property(*FONT_STYLES, initial=NORMAL)
font_variant: str = validated_property(*FONT_VARIANTS, initial=NORMAL)
font_weight: str = validated_property(*FONT_WEIGHTS, initial=NORMAL)
font_size: int = validated_property(integer=True, initial=SYSTEM_DEFAULT_FONT_SIZE)
font_size: int | str = validated_property(
*ABSOLUTE_FONT_SIZES,
*RELATIVE_FONT_SIZES,
integer=True,
initial=SYSTEM_DEFAULT_FONT_SIZE,
)

@classmethod
def _debug(cls, *args: str) -> None: # pragma: no cover
Expand Down Expand Up @@ -930,7 +937,13 @@ def __css__(self) -> str:
else:
css.append(f"font-family: {self.font_family};")
if self.font_size != SYSTEM_DEFAULT_FONT_SIZE:
css.append(f"font-size: {self.font_size}pt;")
if isinstance(self.font_size, str) and (
self.font_size in ABSOLUTE_FONT_SIZES
or self.font_size in RELATIVE_FONT_SIZES
):
css.append(f"font-size: {self.font_size};")
else:
css.append(f"font-size: {self.font_size}pt;")
if self.font_weight != NORMAL:
css.append(f"font-weight: {self.font_weight};")
if self.font_style != NORMAL:
Expand Down
18 changes: 18 additions & 0 deletions travertino/src/travertino/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@

RELATIVE_FONT_SIZES = {LARGER, SMALLER}

FONT_SIZE_SCALE_FACTOR = 1.2

FONT_SIZE_SCALE = {
XX_SMALL: 0.512, # ~(1/FONT_SIZE_SCALE_FACTOR)^3 - 60% smaller
X_SMALL: 0.64, # ~(1/FONT_SIZE_SCALE_FACTOR)^2 - 40% smaller
SMALL: 0.8, # ~(1/FONT_SIZE_SCALE_FACTOR) - 20% smaller
MEDIUM: 1.0, # baseline
LARGE: 1.2, # ~FONT_SIZE_SCALE_FACTOR - 20% larger
X_LARGE: 1.44, # ~FONT_SIZE_SCALE_FACTOR^2 - 40% larger
XX_LARGE: 1.728, # ~FONT_SIZE_SCALE_FACTOR^3 - 60% larger
XXX_LARGE: 2.074, # ~FONT_SIZE_SCALE_FACTOR^4 - 80% larger
}

RELATIVE_FONT_SIZE_SCALE = {
LARGER: FONT_SIZE_SCALE_FACTOR, # 20% larger
SMALLER: 1 / FONT_SIZE_SCALE_FACTOR, # 20% smaller
}

######################################################################
# Colors
######################################################################
Expand Down
11 changes: 10 additions & 1 deletion travertino/src/travertino/fonts.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from .constants import (
ABSOLUTE_FONT_SIZES,
BOLD,
FONT_STYLES,
FONT_VARIANTS,
FONT_WEIGHTS,
ITALIC,
NORMAL,
OBLIQUE,
RELATIVE_FONT_SIZES,
SMALL_CAPS,
SYSTEM_DEFAULT_FONT_SIZE,
)
Expand All @@ -26,6 +28,11 @@ def __init__(self, family, size, style=NORMAL, variant=NORMAL, weight=NORMAL):
try:
if size.strip().endswith("pt"):
self.size = int(size[:-2])
elif (
size.strip() in ABSOLUTE_FONT_SIZES
or size.strip() in RELATIVE_FONT_SIZES
):
self.size = size.strip()
else:
raise ValueError(f"Invalid font size {size!r}")
except Exception:
Expand All @@ -47,7 +54,9 @@ def __repr__(self):
(
"system default size"
if self.size == SYSTEM_DEFAULT_FONT_SIZE
else f"{self.size}pt"
else (
f"{self.size}" if isinstance(self.size, str) else f"{self.size}pt"
)
),
self.family,
)
Expand Down
66 changes: 66 additions & 0 deletions travertino/tests/test_fonts.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import pytest

from travertino.constants import (
ABSOLUTE_FONT_SIZES,
BOLD,
ITALIC,
LARGE,
LARGER,
MEDIUM,
NORMAL,
OBLIQUE,
RELATIVE_FONT_SIZES,
SMALL,
SMALL_CAPS,
SMALLER,
SYSTEM_DEFAULT_FONT_SIZE,
X_LARGE,
X_SMALL,
XX_LARGE,
XX_SMALL,
XXX_LARGE,
)
from travertino.fonts import Font

Expand Down Expand Up @@ -79,10 +91,64 @@ def test_simple_construction(size):
assert_font(Font("Comic Sans", size), "Comic Sans", 12, NORMAL, NORMAL, NORMAL)


@pytest.mark.parametrize(
"size",
[
XX_SMALL,
X_SMALL,
SMALL,
MEDIUM,
LARGE,
X_LARGE,
XX_LARGE,
XXX_LARGE,
LARGER,
SMALLER,
],
)
def test_css_font_size_keywords(size):
font = Font("Comic Sans", size)
assert_font(font, "Comic Sans", size, NORMAL, NORMAL, NORMAL)
assert isinstance(font.size, str)
assert font.size in ABSOLUTE_FONT_SIZES or font.size in RELATIVE_FONT_SIZES


@pytest.mark.parametrize(
"size, expected_repr",
[
(XX_SMALL, "<Font: xx-small Comic Sans>"),
(X_SMALL, "<Font: x-small Comic Sans>"),
(SMALL, "<Font: small Comic Sans>"),
(MEDIUM, "<Font: medium Comic Sans>"),
(LARGE, "<Font: large Comic Sans>"),
(X_LARGE, "<Font: x-large Comic Sans>"),
(XX_LARGE, "<Font: xx-large Comic Sans>"),
(XXX_LARGE, "<Font: xxx-large Comic Sans>"),
(LARGER, "<Font: larger Comic Sans>"),
(SMALLER, "<Font: smaller Comic Sans>"),
],
)
def test_css_font_size_repr(size, expected_repr):
font = Font("Comic Sans", size)
assert repr(font) == expected_repr


def test_invalid_construction():
with pytest.raises(ValueError):
Font("Comic Sans", "12 quatloos")

with pytest.raises(ValueError):
Font("Comic Sans", "invalid-size")

with pytest.raises(ValueError):
Font("Comic Sans", "")

try:
Font("Comic Sans", None)
assert False, "Should have raised TypeError"
except TypeError:
pass


@pytest.mark.parametrize(
"family",
Expand Down
2 changes: 2 additions & 0 deletions winforms/src/toga_winforms/fonts.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ def __init__(self, interface):
font_style |= FontStyle.Italic

# Convert font size to Winforms format
# TODO: update font-size to include CSS keywords
# size such as small, medium, and large.
if self.interface.size == SYSTEM_DEFAULT_FONT_SIZE:
font_size = DEFAULT_FONT.Size
else:
Expand Down
Loading