diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/AnsiEscapeTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/AnsiEscapeTest.java
new file mode 100644
index 00000000000..6f1d355dd35
--- /dev/null
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/AnsiEscapeTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.logging.log4j.core.pattern;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+/**
+ * Regression tests for ANSI SGR attribute codes (GitHub issue #4105).
+ *
+ * Expected values are hard-coded SGR sequences so a wrong mapping cannot
+ * compare equal to itself.
+ *
+ */
+class AnsiEscapeTest {
+
+ @ParameterizedTest
+ @CsvSource({
+ // Log4j style names
+ "normal, 0",
+ "bold, 1",
+ "dim, 2",
+ "italic, 3",
+ "underline, 4",
+ "blink, 5",
+ "reverse, 7",
+ "hidden, 8",
+ // Jansi AnsiRenderer.Code names / aliases (post-#3070 parity)
+ "reset, 0",
+ "intensity_bold, 1",
+ "faint, 2",
+ "intensity_faint, 2",
+ "blink_slow, 5",
+ "blink_fast, 6",
+ "blink_off, 25",
+ "negative_on, 7",
+ "negative_off, 27",
+ "conceal_on, 8",
+ "conceal_off, 28",
+ "underline_double, 21",
+ "underline_off, 24",
+ "bg_default, 49",
+ })
+ void styleMapsToSgr(final String name, final String sgrCode) {
+ assertEquals("\u001B[" + sgrCode + "m", AnsiEscape.createSequence(name));
+ }
+}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
index 0595f68533d..129829b1e0a 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
@@ -39,6 +39,14 @@ public static Stream testRendering() {
"",
"@|white key|@ = @|cyan,bold some value|@",
"\u001b[37mkey\u001b[m = \u001b[36;1msome value\u001b[m"),
+ Arguments.of(
+ "",
+ "@|italic italic text|@ and @|underline underlined text|@",
+ "\u001b[3mitalic text\u001b[m and \u001b[4munderlined text\u001b[m"),
+ Arguments.of(
+ "",
+ "@|faint faint text|@ and @|blink_slow blinking text|@",
+ "\u001b[2mfaint text\u001b[m and \u001b[5mblinking text\u001b[m"),
// Return broken escapes as is
Arguments.of("", "Hello @|crazy|@ world!", "Hello @|crazy|@ world!"),
Arguments.of("", "Hello @|world!", "Hello @|world!"));
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
index 34213373dfb..7b647f854df 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
@@ -58,6 +58,11 @@ public enum AnsiEscape {
*/
NORMAL("0"),
+ /**
+ * Reset general attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ RESET("0"),
+
/**
* Bright general attribute.
*
@@ -72,31 +77,96 @@ public enum AnsiEscape {
*/
BOLD("1"),
+ /**
+ * Bold intensity attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ INTENSITY_BOLD("1"),
+
/**
* Dim general attribute.
*/
DIM("2"),
+ /**
+ * Faint / dim general attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ FAINT("2"),
+
+ /**
+ * Faint intensity attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ INTENSITY_FAINT("2"),
+
+ /**
+ * Italic general attribute.
+ */
+ ITALIC("3"),
+
/**
* Underline general attribute.
*/
- UNDERLINE("3"),
+ UNDERLINE("4"),
/**
* Blink general attribute.
*/
BLINK("5"),
+ /**
+ * Slow blink general attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ BLINK_SLOW("5"),
+
+ /**
+ * Fast blink general attribute.
+ */
+ BLINK_FAST("6"),
+
/**
* Reverse general attribute.
*/
REVERSE("7"),
/**
- * Normal general attribute.
+ * Reverse / negative general attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ NEGATIVE_ON("7"),
+
+ /**
+ * Conceal / hidden general attribute.
*/
HIDDEN("8"),
+ /**
+ * Conceal general attribute (Jansi {@code AnsiRenderer.Code} name).
+ */
+ CONCEAL_ON("8"),
+
+ /**
+ * Double underline general attribute.
+ */
+ UNDERLINE_DOUBLE("21"),
+
+ /**
+ * Turns underline off.
+ */
+ UNDERLINE_OFF("24"),
+
+ /**
+ * Turns blink off.
+ */
+ BLINK_OFF("25"),
+
+ /**
+ * Turns reverse / negative video off.
+ */
+ NEGATIVE_OFF("27"),
+
+ /**
+ * Turns conceal off.
+ */
+ CONCEAL_OFF("28"),
+
/**
* Black foreground color.
*/
@@ -227,6 +297,11 @@ public enum AnsiEscape {
*/
BG_WHITE("47"),
+ /**
+ * Default background color.
+ */
+ BG_DEFAULT("49"),
+
/**
* Bright black foreground color.
*/
diff --git a/src/changelog/.2.x.x/4105_fix_AnsiEscape_italic_underline.xml b/src/changelog/.2.x.x/4105_fix_AnsiEscape_italic_underline.xml
new file mode 100644
index 00000000000..1452cb793e4
--- /dev/null
+++ b/src/changelog/.2.x.x/4105_fix_AnsiEscape_italic_underline.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ Fix `AnsiEscape` italic/underline SGR codes and restore missing Jansi `AnsiRenderer.Code` style names (for example `faint`, `blink_slow`)
+
+
diff --git a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index 4e3943066a7..84781f1d552 100644
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@ -1465,8 +1465,8 @@ In EBNF form the syntax of a style expression is:
|
::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7"
| "8" | "9" | "a" | "b" | "c" | "d" | "e" | "f"
- ::= "normal" | "bold" | "dim" | "underline"
- | "blink" | "reverse" | "hidden"
+ ::= "normal" | "reset" | "bold" | "dim" | "faint" | "italic" | "underline"
+ | "underline_double" | "blink" | "blink_slow" | "blink_fast" | "reverse" | "hidden"
| "black" | "bg_black" | "bright_black" | "bg_bright_black"
| "red" | "bg_red" | "bright_red" | "bg_bright_red"
| "green" | "bg_green" | "bright_green" | "bg_bright_green"
@@ -1481,11 +1481,14 @@ For example, you can use `underline blue bg_bright_yellow` to specify a blue und
The style specifiers have the following effects (see https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters[Select Graphic Rendition] for details):
-`normal`:: Reverts all parameters to their default value
+`normal` / `reset`:: Reverts all parameters to their default value
`bold`:: Increases the font weight or the color intensity
-`dim`:: Decreases the fond weight or the color intensity
+`dim` / `faint`:: Decreases the font weight or the color intensity
+`italic`:: Renders the text in italic on terminals that support it
`underline`:: Underlines the text on some terminals
-`blink`:: Causes the text to blink
+`underline_double`:: Double-underlines the text on terminals that support it
+`blink` / `blink_slow`:: Causes the text to blink
+`blink_fast`:: Causes the text to blink rapidly on terminals that support it
`reverse`:: Swaps foreground and background colors
`hidden`:: Hides the text