// Copyright 2017-2022 The MathJax Consortium
// SPDX-License-Identifier: Apache-2.0
// This file is a Go translation and modification of MathJax 3.2.2.

package svg

import (
	
	

	
)

func ( *wrapper) () *wrapper {
	if len(.children) == 0 {
		return nil
	}
	return .children[0]
}

func ( *wrapper) () *wrapper {
	, ,  := .scriptBaseInfo()
	return 
}

// CommonScriptbase.getBaseCore keeps the first under/over accent flags while
// descending through transparent wrappers and constructor-classified math
// accents. A false outer flag must not be replaced by a true inner one.
func ( *wrapper) () ( *wrapper, ,  bool) {
	 := false
	 := func( *wrapper) {
		if  == nil ||  {
			return
		}
		switch .node.Kind {
		case "munder", "mover", "munderover":
			 = true
			,  := .node.Attributes.Get("accent")
			,  := .node.Attributes.Get("accentunder")
			,  = mathAccentTruthy(), mathAccentTruthy()
		}
	}
	 = .scriptBase()
	for  != nil {
		 := false
		switch .node.Kind {
		case "mrow", "mstyle", "mpadded", "mphantom", "semantics":
			 = len(.children) == 1
		case "TeXAtom":
			 = len(.children) == 1 && effectiveTeXClass(.node) != 8
		case "munder", "mover", "munderover":
			 = .isMathAccent && len(.children) != 0
		}
		()
		if ! {
			break
		}
		 = .children[0]
	}
	return
}

// Classification precedes this wrapper's stretching, as in the source
// CommonScriptbase constructor. Its scriptChild is child 1 even for the
// three-child munderover family. coreMO is not restricted to an mo result.
func ( *wrapper) () {
	if len(.children) < 2 {
		return
	}
	// The source computes baseScale/baseIc before isCharBase; preserve the
	// lazy base measurement that can select an operator's size.
	.baseIC()
	 := .scriptBaseCore()
	if  == nil || .bbox.RScale != 1 || utf8.RuneCountInString(nodeText(.node)) != 1 {
		return
	}
	switch .node.Kind {
	case "mi", "mn":
	case "mo":
		if .sizeSet {
			return
		}
	default:
		return
	}
	 := movableLimitCore(.children[1])
	if  != nil {
		,  := .node.Property("mathaccent")
		.isMathAccent = mathAccentTruthy()
	}
}

// Internal mathaccent and accent flags use JavaScript truthiness. In
// particular, the strings "false" and "0" are true; do not change the
// renderer's separate boolean-attribute conversion policy.
func mathAccentTruthy( any) bool {
	if ,  := .(string);  {
		return  != ""
	}
	return truthy()
}

func ( *wrapper) () float64 {
	 := .scriptBaseCore()
	 := 1.0
	for  := ;  != nil &&  != ;  = .parent {
		 *= .outerBBox().RScale
	}
	return 
}

func ( *wrapper) () float64 {
	 := .scriptBaseCore()
	if  == nil {
		return 0
	}
	return .outerBBox().IC * .baseScale()
}

func ( *wrapper) () bool {
	 := .scriptBaseCore()
	if  == nil || (.node.Kind != "mi" && .node.Kind != "mn" && .node.Kind != "mo") {
		return false
	}
	if .node.Kind == "mo" {
		// CommonScriptbase.isCharBase only treats an unstretched mo (size ===
		// null) as a character.  A fixed-size delimiter such as \bigr has a
		// selected size and must retain the TeX sup-drop term.
		if .sizeSet || boolAttributeDefault(.node, "largeop", false) {
			return false
		}
	}
	return .bbox.RScale == 1 && utf8.RuneCountInString(nodeText(.node)) == 1
}

func ( *wrapper) () bool {
	// CommonScriptbase retains italic correction for over/underlines, but
	// removes it for math accents even though mover normally keeps it.
	if .lineAccent(.overChild()) || .lineAccent(.underChild()) {
		return false
	}
	return .node.Kind == "msub" || .node.Kind == "msubsup" ||
		.node.Kind == "munder" || .node.Kind == "munderover" || .isMathAccent
}

func ( *wrapper) () float64 {
	 := .scriptBase()
	if  == nil {
		return 0
	}
	 := .outerBBox()
	 := .W * .RScale
	if .removeBaseIC() {
		 -= .baseIC()
	}
	return  + .renderer.params.ExtraIC
}

func ( *wrapper) () float64 {
	 := .scriptBaseCore()
	if  == nil {
		return 0
	}
	 := .outerBBox().IC
	if  == 0 {
		return 0
	}
	return (1.05* + .05) * .baseScale()
}

func ( *wrapper) ( float64) float64 {
	 := .scriptBaseCore()
	 :=  != nil && boolAttributeDefault(.node, "largeop", false)
	if .baseIsChar() && ! && .baseScale() == 1 {
		return 0
	}
	return 
}

func ( *wrapper) ( *wrapper,  float64) float64 {
	 := .scriptBaseCore()
	if  == nil ||  == nil {
		return 0
	}
	,  := .outerBBox(), .outerBBox()
	 := .renderer.params
	 := layout.Length2Em(attribute(.node, "subscriptshift", ""), , .bbox.Scale, .renderer.pxPerEm)
	return math.Max(
		.baseCharZero(.D*.baseScale()+.SubDrop*.RScale),
		math.Max(, .H*.RScale-.8*.XHeight),
	)
}

func ( *wrapper) ( *wrapper) float64 {
	 := .scriptBaseCore()
	if  == nil ||  == nil {
		return 0
	}
	,  := .outerBBox(), .outerBBox()
	 := .renderer.params
	 := .Sup2
	if ,  := .node.Property("texprimestyle");  && truthy() {
		 = .Sup3
	} else if .displayStyle {
		 = .Sup1
	}
	 := layout.Length2Em(attribute(.node, "superscriptshift", ""), , .bbox.Scale, .renderer.pxPerEm)
	return math.Max(
		.baseCharZero(.H*.baseScale()-.SupDrop*.RScale),
		math.Max(, .D*.RScale+.25*.XHeight),
	)
}

func ( *wrapper) () (,  float64) {
	if len(.children) < 3 {
		return 0, 0
	}
	,  := .children[1], .children[2]
	,  := .outerBBox(), .outerBBox()
	 := .renderer.params
	// CommonMsubsup keeps CommonScriptbase.scriptChild at child 1. Its
	// initial getU therefore measures the subscript before enforcing the
	// clearance between the separately measured sub/sup boxes.
	 := .supShift()
	 := .baseCharZero(.scriptBaseCore().outerBBox().D*.baseScale() + .SubDrop*.RScale)
	 := math.Max(, layout.Length2Em(attribute(.node, "subscriptshift", ""), .Sub2, .bbox.Scale, .renderer.pxPerEm))
	 := 3 * .Rule
	 := ( - .D*.RScale) - (.H*.RScale - )
	if  <  {
		 +=  - 
		 := .8*.XHeight - ( - .D*.RScale)
		if  > 0 {
			 += 
			 -= 
		}
	}
	 = math.Max(layout.Length2Em(attribute(.node, "superscriptshift", ""), , .bbox.Scale, .renderer.pxPerEm), )
	 = math.Max(layout.Length2Em(attribute(.node, "subscriptshift", ""), , .bbox.Scale, .renderer.pxPerEm), )
	return -, 
}

func ( *wrapper) ( *layout.BBox) {
	 := .scriptBase()
	if  == nil || len(.children) < 2 {
		.computeChildrenBBox()
		return
	}
	.Empty()
	.Append(.outerBBox())
	 := .baseWidth()
	switch .node.Kind {
	case "msub":
		 := .children[1]
		.Combine(.outerBBox(), , -.subShift(, .renderer.params.Sub1))
	case "msup":
		 := .children[1]
		 := .adjustedIC() - .baseIC()
		.Combine(.outerBBox(), +, .supShift())
	case "msubsup":
		,  := .children[1], .children[2]
		,  := .scriptOffsets()
		.Combine(.outerBBox(), , )
		.Combine(.outerBBox(), +.adjustedIC(), )
	}
	.W += .renderer.params.ScriptSpace
	.Clean()
}

func ( *wrapper) ( *Element) {
	 := .standardSVG()
	 := .scriptBase()
	if  == nil || len(.children) < 2 {
		return
	}
	 := .baseWidth()
	.toSVG()
	switch .node.Kind {
	case "msub":
		 := .children[1]
		.toSVG()
		.place(, -.subShift(, .renderer.params.Sub1))
	case "msup":
		 := .children[1]
		.toSVG()
		 := .adjustedIC() - .baseIC()
		.place(+, .supShift())
	case "msubsup":
		,  := .children[1], .children[2]
		,  := .scriptOffsets()
		// MathJax emits the superscript before the subscript.
		.toSVG()
		.toSVG()
		.place(, )
		.place(+.adjustedIC(), )
	}
}