[LyX/master] Math: add a structure to hold font information.

Thibaut Cuvelier tcuvelier at lyx.org
Tue Oct 29 03:31:52 UTC 2024


commit 9a81bb36f4a51891730f052b84ca535f20583c52
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Tue Oct 29 04:06:07 2024 +0100

    Math: add a structure to hold font information.
    
    It will allow to merge a lot of code for MathML and HTML: same parsing, slightly different outputs. The refactoring also shows clearly what parts are missing in HTML (while being easily fixable). The change is a prerequisite for implementing font nesting (although it is not done yet).
    
    The new class is not yet used within InsetMathFont; it will come in the next commit.
    
    Open question: should we use InsetMath::mode_type somewhere? I believe so, to determine whether the current default is italics or not in MathML.
---
 src/mathed/InsetMathFont.cpp | 145 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/src/mathed/InsetMathFont.cpp b/src/mathed/InsetMathFont.cpp
index 25ee4ae53b..584de5c1ad 100644
--- a/src/mathed/InsetMathFont.cpp
+++ b/src/mathed/InsetMathFont.cpp
@@ -28,6 +28,151 @@ using namespace lyx::support;
 
 namespace lyx {
 
+namespace {
+// Similar to FontInfo and its related enums, but specifically for the math
+// mode.
+//
+// All types have enumerations, like FontEnums.h, even though there are
+// sometimes only two cases: this design ensures some future-proofness and
+// ensures that you cannot inadvertently swap two values.
+class MathFontInfo {
+public:
+	enum MathFontFamily {
+		MATH_NORMAL_FAMILY = 0, // Default value in MathML.
+		MATH_FRAKTUR_FAMILY,
+		MATH_SANS_FAMILY,
+		MATH_MONOSPACE_FAMILY,
+		MATH_DOUBLE_STRUCK_FAMILY,
+		MATH_SCRIPT_FAMILY,
+		MATH_SMALL_CAPS // Not natively supported in any version of MathML.
+	};
+
+	enum MathFontSeries {
+		MATH_MEDIUM_SERIES = 0, // Default value in MathML. // Default value in MathML.
+		MATH_BOLD_SERIES
+	};
+
+	enum MathFontShape {
+		MATH_UP_SHAPE = 0,
+		MATH_ITALIC_SHAPE // Default value in MathML mi, not outside.
+	};
+
+	MathFontInfo() :
+		family_(MATH_NORMAL_FAMILY), series_(MATH_MEDIUM_SERIES), shape_(MATH_UP_SHAPE) {}
+	MathFontInfo(const MathFontFamily family, const MathFontSeries series, const MathFontShape shape) :
+		family_(family), series_(series), shape_(shape) {}
+
+	static MathFontInfo fromMacro(const docstring& tag)
+	{
+		MathFontInfo font;
+		if (tag == "mathnormal" || tag == "mathrm"
+				|| tag == "text" || tag == "textnormal"
+				|| tag == "textrm" || tag == "textup"
+				|| tag == "textmd")
+			font.shape_ = MATH_UP_SHAPE;
+		else if (tag == "frak" || tag == "mathfrak")
+			font.family_ = MATH_FRAKTUR_FAMILY;
+		else if (tag == "mathbf" || tag == "textbf")
+			font.series_ = MATH_BOLD_SERIES;
+		else if (tag == "mathbb" || tag == "mathbbm"
+				 || tag == "mathds")
+			font.family_ = MATH_DOUBLE_STRUCK_FAMILY;
+		else if (tag == "mathcal")
+			font.family_ = MATH_SCRIPT_FAMILY;
+		else if (tag == "mathit" || tag == "textsl"
+				 || tag == "emph" || tag == "textit")
+			font.shape_ = MATH_ITALIC_SHAPE;
+		else if (tag == "mathsf" || tag == "textsf")
+			font.family_ = MATH_SANS_FAMILY;
+		else if (tag == "mathtt" || tag == "texttt")
+			font.family_ = MATH_MONOSPACE_FAMILY;
+		else if (tag == "textipa" || tag == "textsc" || tag == "noun")
+			font.family_ = MATH_SMALL_CAPS;
+
+		return font;
+	}
+
+	MathFontFamily family() const { return family_; }
+	MathFontSeries series() const { return series_; }
+	MathFontShape shape() const { return shape_; }
+
+	std::string toMathMLMathVariant(MathMLStream::MathMLVersion mathml_version) const
+	{
+		return mathml_version == MathMLStream::MathMLVersion::mathml3 ?
+			toMathVariantForMathML3() : toMathVariantForMathMLCore();
+	}
+
+	std::string toHTMLSpanClass() const
+	{
+		// See the existing classes in InsetMathFont::validate. In particular,
+		// there is no double-struck style!
+		switch (family_) {
+		case MATH_MONOSPACE_FAMILY:
+			return "monospace";
+		case MATH_FRAKTUR_FAMILY:
+			return "fraktur";
+		case MATH_SCRIPT_FAMILY:
+			return "script";
+		case MATH_SMALL_CAPS:
+			return "noun";
+		case MATH_SANS_FAMILY:
+			return "sans";
+		case MATH_NORMAL_FAMILY:
+			if (series_ == MATH_MEDIUM_SERIES) {
+				return shape_ == MATH_UP_SHAPE ? "normal" : "italic";
+			}
+			return "bold";
+		case MATH_DOUBLE_STRUCK_FAMILY:
+			// No support for double-struck font in CSS.
+			return "";
+		}
+	}
+
+private:
+	MathFontFamily family_;
+	MathFontSeries series_;
+	MathFontShape shape_;
+
+	std::string toMathVariantForMathML3() const
+	{
+		// mathvariant is the way MathML 3 encodes fonts.
+		// Not all combinations are supported. Official list:
+		// https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
+		// "initial", "tailed", "looped", and "stretched" are not implemented,
+		// as they are only useful for Arabic characters (for which LyX has no
+		// support right now).
+		switch (family_) {
+		case MATH_MONOSPACE_FAMILY:
+			return "monospace";
+		case MATH_DOUBLE_STRUCK_FAMILY:
+			return "double-struck";
+		case MATH_FRAKTUR_FAMILY:
+			return series_ == MATH_BOLD_SERIES ? "bold-fraktur" : "fraktur";
+		case MATH_SCRIPT_FAMILY:
+			return series_ == MATH_BOLD_SERIES ? "bold-script" : "script";
+		case MATH_SANS_FAMILY:
+			if (series_ == MATH_MEDIUM_SERIES) {
+				return shape_ == MATH_UP_SHAPE ? "sans-serif" : "sans-serif-italic";
+			}
+			return shape_ == MATH_UP_SHAPE ? "bold-sans-serif" : "sans-serif-bold-italic";
+		case MATH_NORMAL_FAMILY:
+			if (series_ == MATH_MEDIUM_SERIES) {
+				return shape_ == MATH_UP_SHAPE ? "normal" : "italic";
+			}
+			return shape_ == MATH_UP_SHAPE ? "bold" : "bold-italic";
+		case MATH_SMALL_CAPS:
+			// No valid value...
+				return "";
+		}
+	}
+
+	std::string toMathVariantForMathMLCore() const
+	{
+		return shape_ == MATH_UP_SHAPE ? "normal" : "";
+	}
+};
+}
+
 InsetMathFont::InsetMathFont(Buffer * buf, latexkeys const * key)
 	: InsetMathNest(buf, 1), key_(key)
 {}


More information about the lyx-cvs mailing list