From 489f9c31519dfd9c361009f2727fe25c65c25b3b Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 8 Sep 2023 16:01:57 +0100 Subject: [PATCH] LibWeb: Implement `text-transform: math-auto` This is a simple mapping of some code-points to others. I was going to use a ref test for this, but without knowing that the font contains the code-points (which SerenitySans does not) we'd be comparing a series of replacement characters to a series of replacement characters, which doesn't tell you if they're the right code-points underneath. --- .../expected/css-text-transform-math-auto.txt | 17 ++ .../input/css-text-transform-math-auto.html | 1 + Userland/Libraries/LibWeb/CSS/Enums.json | 1 + .../Libraries/LibWeb/CSS/Identifiers.json | 1 + Userland/Libraries/LibWeb/Layout/TextNode.cpp | 248 ++++++++++++++++++ 5 files changed, 268 insertions(+) create mode 100644 Tests/LibWeb/Layout/expected/css-text-transform-math-auto.txt create mode 100644 Tests/LibWeb/Layout/input/css-text-transform-math-auto.html diff --git a/Tests/LibWeb/Layout/expected/css-text-transform-math-auto.txt b/Tests/LibWeb/Layout/expected/css-text-transform-math-auto.txt new file mode 100644 index 0000000000..ce6d937d65 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/css-text-transform-math-auto.txt @@ -0,0 +1,17 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,16) content-size 784x17.46875 children: not-inline + BlockContainer

at (8,16) content-size 784x17.46875 children: inline + line 0 width: 118.40625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 67, rect: [8,16 118.40625x17.46875] + "𝑊𝑒𝑙𝑙, ℎ𝑒𝑙𝑙𝑜 𝑓𝑟𝑖𝑒𝑛𝑑𝑠!" + TextNode <#text> + BlockContainer <(anonymous)> at (8,49.46875) content-size 784x0 children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x600] + PaintableWithLines (BlockContainer) [8,16 784x17.46875] overflow: [8,16 784x33.46875] + PaintableWithLines (BlockContainer

) [8,16 784x17.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [8,49.46875 784x0] diff --git a/Tests/LibWeb/Layout/input/css-text-transform-math-auto.html b/Tests/LibWeb/Layout/input/css-text-transform-math-auto.html new file mode 100644 index 0000000000..9934fa18bf --- /dev/null +++ b/Tests/LibWeb/Layout/input/css-text-transform-math-auto.html @@ -0,0 +1 @@ +

Well, hello friends!

diff --git a/Userland/Libraries/LibWeb/CSS/Enums.json b/Userland/Libraries/LibWeb/CSS/Enums.json index 7cf8fa939d..5e890d3701 100644 --- a/Userland/Libraries/LibWeb/CSS/Enums.json +++ b/Userland/Libraries/LibWeb/CSS/Enums.json @@ -384,6 +384,7 @@ "full-size-kana", "full-width", "lowercase", + "math-auto", "none", "uppercase" ], diff --git a/Userland/Libraries/LibWeb/CSS/Identifiers.json b/Userland/Libraries/LibWeb/CSS/Identifiers.json index 786831d24e..7ba577e50e 100644 --- a/Userland/Libraries/LibWeb/CSS/Identifiers.json +++ b/Userland/Libraries/LibWeb/CSS/Identifiers.json @@ -222,6 +222,7 @@ "mark", "marktext", "math", + "math-auto", "max-content", "medium", "menu", diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.cpp b/Userland/Libraries/LibWeb/Layout/TextNode.cpp index ecf73a6d1f..5cbd9ec3c6 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Userland/Libraries/LibWeb/Layout/TextNode.cpp @@ -32,6 +32,250 @@ static bool is_all_whitespace(StringView string) return true; } +// https://w3c.github.io/mathml-core/#new-text-transform-values +static DeprecatedString apply_math_auto_text_transform(DeprecatedString const& string) +{ + + // https://w3c.github.io/mathml-core/#italic-mappings + auto map_code_point_to_italic = [](u32 code_point) -> u32 { + switch (code_point) { + case 0x0041: + return 0x1D434; + case 0x0042: + return 0x1D435; + case 0x0043: + return 0x1D436; + case 0x0044: + return 0x1D437; + case 0x0045: + return 0x1D438; + case 0x0046: + return 0x1D439; + case 0x0047: + return 0x1D43A; + case 0x0048: + return 0x1D43B; + case 0x0049: + return 0x1D43C; + case 0x004A: + return 0x1D43D; + case 0x004B: + return 0x1D43E; + case 0x004C: + return 0x1D43F; + case 0x004D: + return 0x1D440; + case 0x004E: + return 0x1D441; + case 0x004F: + return 0x1D442; + case 0x0050: + return 0x1D443; + case 0x0051: + return 0x1D444; + case 0x0052: + return 0x1D445; + case 0x0053: + return 0x1D446; + case 0x0054: + return 0x1D447; + case 0x0055: + return 0x1D448; + case 0x0056: + return 0x1D449; + case 0x0057: + return 0x1D44A; + case 0x0058: + return 0x1D44B; + case 0x0059: + return 0x1D44C; + case 0x005A: + return 0x1D44D; + case 0x0061: + return 0x1D44E; + case 0x0062: + return 0x1D44F; + case 0x0063: + return 0x1D450; + case 0x0064: + return 0x1D451; + case 0x0065: + return 0x1D452; + case 0x0066: + return 0x1D453; + case 0x0067: + return 0x1D454; + case 0x0068: + return 0x0210E; + case 0x0069: + return 0x1D456; + case 0x006A: + return 0x1D457; + case 0x006B: + return 0x1D458; + case 0x006C: + return 0x1D459; + case 0x006D: + return 0x1D45A; + case 0x006E: + return 0x1D45B; + case 0x006F: + return 0x1D45C; + case 0x0070: + return 0x1D45D; + case 0x0071: + return 0x1D45E; + case 0x0072: + return 0x1D45F; + case 0x0073: + return 0x1D460; + case 0x0074: + return 0x1D461; + case 0x0075: + return 0x1D462; + case 0x0076: + return 0x1D463; + case 0x0077: + return 0x1D464; + case 0x0078: + return 0x1D465; + case 0x0079: + return 0x1D466; + case 0x007A: + return 0x1D467; + case 0x0131: + return 0x1D6A4; + case 0x0237: + return 0x1D6A5; + case 0x0391: + return 0x1D6E2; + case 0x0392: + return 0x1D6E3; + case 0x0393: + return 0x1D6E4; + case 0x0394: + return 0x1D6E5; + case 0x0395: + return 0x1D6E6; + case 0x0396: + return 0x1D6E7; + case 0x0397: + return 0x1D6E8; + case 0x0398: + return 0x1D6E9; + case 0x0399: + return 0x1D6EA; + case 0x039A: + return 0x1D6EB; + case 0x039B: + return 0x1D6EC; + case 0x039C: + return 0x1D6ED; + case 0x039D: + return 0x1D6EE; + case 0x039E: + return 0x1D6EF; + case 0x039F: + return 0x1D6F0; + case 0x03A0: + return 0x1D6F1; + case 0x03A1: + return 0x1D6F2; + case 0x03F4: + return 0x1D6F3; + case 0x03A3: + return 0x1D6F4; + case 0x03A4: + return 0x1D6F5; + case 0x03A5: + return 0x1D6F6; + case 0x03A6: + return 0x1D6F7; + case 0x03A7: + return 0x1D6F8; + case 0x03A8: + return 0x1D6F9; + case 0x03A9: + return 0x1D6FA; + case 0x2207: + return 0x1D6FB; + case 0x03B1: + return 0x1D6FC; + case 0x03B2: + return 0x1D6FD; + case 0x03B3: + return 0x1D6FE; + case 0x03B4: + return 0x1D6FF; + case 0x03B5: + return 0x1D700; + case 0x03B6: + return 0x1D701; + case 0x03B7: + return 0x1D702; + case 0x03B8: + return 0x1D703; + case 0x03B9: + return 0x1D704; + case 0x03BA: + return 0x1D705; + case 0x03BB: + return 0x1D706; + case 0x03BC: + return 0x1D707; + case 0x03BD: + return 0x1D708; + case 0x03BE: + return 0x1D709; + case 0x03BF: + return 0x1D70A; + case 0x03C0: + return 0x1D70B; + case 0x03C1: + return 0x1D70C; + case 0x03C2: + return 0x1D70D; + case 0x03C3: + return 0x1D70E; + case 0x03C4: + return 0x1D70F; + case 0x03C5: + return 0x1D710; + case 0x03C6: + return 0x1D711; + case 0x03C7: + return 0x1D712; + case 0x03C8: + return 0x1D713; + case 0x03C9: + return 0x1D714; + case 0x2202: + return 0x1D715; + case 0x03F5: + return 0x1D716; + case 0x03D1: + return 0x1D717; + case 0x03F0: + return 0x1D718; + case 0x03D5: + return 0x1D719; + case 0x03F1: + return 0x1D71A; + case 0x03D6: + return 0x1D71B; + default: + return code_point; + } + }; + + StringBuilder builder(string.length()); + + for (auto code_point : Utf8View(string)) + builder.append_code_point(map_code_point_to_italic(code_point)); + + return builder.to_deprecated_string(); +} + static ErrorOr apply_text_transform(DeprecatedString const& string, CSS::TextTransform text_transform) { switch (text_transform) { @@ -41,12 +285,16 @@ static ErrorOr apply_text_transform(DeprecatedString const& st return Unicode::to_unicode_lowercase_full(string); case CSS::TextTransform::None: return string; + case CSS::TextTransform::MathAuto: + return apply_math_auto_text_transform(string); case CSS::TextTransform::Capitalize: case CSS::TextTransform::FullSizeKana: case CSS::TextTransform::FullWidth: // FIXME: Implement these! return string; } + + VERIFY_NOT_REACHED(); } void TextNode::invalidate_text_for_rendering()