From cfdaa5735330cda74df01a0a95a64f5428270771 Mon Sep 17 00:00:00 2001
From: Calixte Denizet <calixte.denizet@gmail.com>
Date: Sat, 27 Nov 2021 15:49:57 +0100
Subject: [PATCH] Handle sub/super-scripts in rich text  - it aims to fix
 #14317;  - change the fontSize and the verticalAlign properties according to
 the position of the text.

---
 src/core/xfa/xhtml.js | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/src/core/xfa/xhtml.js b/src/core/xfa/xhtml.js
index 510747db4..273cc93bc 100644
--- a/src/core/xfa/xhtml.js
+++ b/src/core/xfa/xhtml.js
@@ -107,13 +107,14 @@ const StyleMapping = new Map([
   ["margin-top", value => measureToString(getMeasurement(value))],
   ["text-indent", value => measureToString(getMeasurement(value))],
   ["font-family", value => value],
+  ["vertical-align", value => measureToString(getMeasurement(value))],
 ]);
 
 const spacesRegExp = /\s+/g;
 const crlfRegExp = /[\r\n]+/g;
 const crlfForRichTextRegExp = /\r\n?/g;
 
-function mapStyle(styleStr, node) {
+function mapStyle(styleStr, node, richText) {
   const style = Object.create(null);
   if (!styleStr) {
     return style;
@@ -158,6 +159,29 @@ function mapStyle(styleStr, node) {
     );
   }
 
+  if (
+    richText &&
+    style.verticalAlign &&
+    style.verticalAlign !== "0px" &&
+    style.fontSize
+  ) {
+    // A non-zero verticalAlign means that we've a sub/super-script and
+    // consequently the font size must be decreased.
+    // https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf#G11.2097514
+    // And the two following factors to position the scripts have been
+    // found here:
+    // https://en.wikipedia.org/wiki/Subscript_and_superscript#Desktop_publishing
+    const SUB_SUPER_SCRIPT_FACTOR = 0.583;
+    const VERTICAL_FACTOR = 0.333;
+    const fontSize = getMeasurement(style.fontSize);
+    style.fontSize = measureToString(fontSize * SUB_SUPER_SCRIPT_FACTOR);
+    style.verticalAlign = measureToString(
+      Math.sign(getMeasurement(style.verticalAlign)) *
+        fontSize *
+        VERTICAL_FACTOR
+    );
+  }
+
   fixTextIndent(style);
   return style;
 }
@@ -333,7 +357,7 @@ class XhtmlObject extends XmlObject {
       name: this[$nodeName],
       attributes: {
         href: this.href,
-        style: mapStyle(this.style, this),
+        style: mapStyle(this.style, this, this[$richText]),
       },
       children,
       value,