// 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 (.node.Kind == "munder" || .node.Kind == "munderover") && len(.children) > 1 {
		return .children[1]
	}
	return nil
}

func ( *wrapper) () *wrapper {
	if .node.Kind == "mover" && len(.children) > 1 {
		return .children[1]
	}
	if .node.Kind == "munderover" && len(.children) > 2 {
		return .children[2]
	}
	return nil
}

// movableLimitCore follows the node-specific coreMO contract used by
// CommonScriptbase.hasMovableLimits and math-accent classification. A
// non-operator may be the returned core.
// Keep the distinct layout-base and accent-operator traversals unchanged.
func movableLimitCore( *wrapper) *wrapper {
	for  != nil {
		 := 0
		switch .node.Kind {
		case "mrow":
			if !.node.Flags.Embellished {
				return 
			}
			 = .node.Flags.CoreIndex
		case "msub", "msup", "msubsup", "munder", "mover", "munderover", "mmultiscripts",
			"TeXAtom", "mstyle", "mpadded", "mphantom", "semantics", "mfrac", "math", "mtd":
			// AbstractMmlBaseNode and AbstractMmlLayoutNode always use child 0.
		case "maction":
			,  := .node.Attributes.Get("selection")
			 := mml.MactionSelectionNumber(, )
			if math.IsNaN() {
				return nil
			}
			 := math.Max(1, math.Min(float64(len(.children)), )) - 1
			if  != math.Trunc() {
				return nil
			}
			 = int()
		default:
			return 
		}
		if  < 0 ||  >= len(.children) {
			return nil
		}
		 = .children[]
	}
	return nil
}

func ( *wrapper) () bool {
	 := movableLimitCore(.scriptBase())
	return !.displayStyle &&  != nil && boolAttributeDefault(.node, "movablelimits", false)
}

func ( *wrapper) ( *wrapper) bool {
	// CommonScriptbase.isLineAccent examines the core token, not all text
	// descendants of a non-embellished script row.
	 := movableLimitCore()
	return  != nil && .node.Flags.Token && nodeText(.node) == "―"
}

// CommonScriptbase records the first under/over accent below transparent
// wrappers. Its existing gap is removed before a further label is stacked.
func ( *wrapper) ( string) bool {
	, ,  := .scriptBaseInfo()
	if  == "accent" {
		return 
	}
	return  == "accentunder" && 
}

func ( *wrapper) (,  *layout.BBox) (,  float64) {
	 := boolAttributeDefault(.node, "accent", false)
	 := .renderer.params
	 := .D * .RScale
	 := .Rule * .SeparationFactor
	 := 
	if .lineAccent(.overChild()) {
		 = 3 * .Rule
	}
	 = math.Max(.BigOp1, .BigOp3-math.Max(0, ))
	if  {
		 = 
	}
	if .baseHasAccent("accent") {
		 -= 
	}
	 = .H*.RScale +  + 
	return
}

func ( *wrapper) (,  *layout.BBox) (,  float64) {
	 := boolAttributeDefault(.node, "accentunder", false)
	 := .renderer.params
	 := .H * .RScale
	 := .Rule * .SeparationFactor
	 := 
	if .lineAccent(.underChild()) {
		 = 3 * .Rule
	}
	 = math.Max(.BigOp2, .BigOp4-)
	if  {
		 = 
	}
	if .baseHasAccent("accentunder") {
		 -= 
	}
	 = -(.D*.RScale +  + )
	return
}

func ( *wrapper) ( bool) float64 {
	 := .scriptBaseCore()
	if  == nil {
		return 0
	}
	 := .outerBBox()
	 := 0.0
	if boolAttributeDefault(.node, "accent", false) && ! {
		 = .Skew
	}
	// CommonScriptbase.getDelta rounds the italic-correction product before
	// adding the skew; a fused operation can change the serialized position.
	return ( + float64(.75*.IC)) * .baseScale()
}

func ( *wrapper) ( []*layout.BBox,  []float64) []float64 {
	 := make([]float64, len())
	for ,  := range  {
		[] = .W * .RScale
	}
	 := .scriptBaseCore()
	if len() != 0 && .removeBaseIC() &&  != nil && !boolAttributeDefault(.node, "largeop", false) {
		[0] -= .baseIC()
	}
	 := 0.0
	for ,  := range  {
		 = math.Max(, )
	}
	 := stringAttribute(.node, "align", "center")
	 := make([]float64, len())
	 := 0.0
	for  := range  {
		switch  {
		case "right":
			[] =  - []
		case "left":
			[] = 0
		default:
			[] = ( - []) / 2
		}
		if  < len() {
			[] += []
		}
		if [] <  {
			 = -[]
		}
	}
	if  != 0 {
		for  := range  {
			[] += 
		}
	}
	for  := 1;  < len(); ++ {
		[] += [].DX * [0].Scale
	}
	return 
}

// stretchUnderOverChildren ports CommonScriptbase.stretchChildren(). The outer
// child decides whether it stretches (a fraction can be embellished but refuse
// stretching); only the final resize is delivered to its core mo.
func ( *wrapper) () {
	 := make([]*wrapper, 0, len(.children))
	for ,  := range .children {
		if .canStretch(font.DirectionHorizontal) {
			 = append(, )
		}
	}
	if len() == 0 || len(.children) <= 1 {
		return
	}

	 := len() > 1 && len() == len(.children)
	 := 0.0
	for ,  := range .children {
		if ! && .hasStretch {
			continue
		}
		 := .styledOuterBBoxWithSave(!.hasStretch)
		 = math.Max(, .W*.RScale)
	}
	for ,  := range  {
		if  := tableCoreMO();  != nil {
			.getStretchedVariant([]float64{ / .bbox.RScale}, false)
		}
	}
}

func ( *wrapper) ( *layout.BBox) {
	 := .scriptBase()
	if  == nil {
		.computeChildrenBBox()
		return
	}
	.Empty()
	.Append(.outerBBox())
	 := .baseWidth()
	switch .node.Kind {
	case "munder":
		 := .underChild()
		.Combine(.outerBBox(), , -.subShift(, .renderer.params.Sub1))
	case "mover":
		 := .overChild()
		 := .adjustedIC() - .baseIC()
		.Combine(.outerBBox(), +, .supShift())
	case "munderover":
		,  := .underChild(), .overChild()
		,  := .scriptOffsetsFor(, )
		.Combine(.outerBBox(), , )
		.Combine(.outerBBox(), +.adjustedIC(), )
	}
	.W += .renderer.params.ScriptSpace
	.Clean()
}

func ( *wrapper) (,  *wrapper) (,  float64) {
	if  == nil ||  == nil {
		return 0, 0
	}
	,  := .outerBBox(), .outerBBox()
	 := .renderer.params
	// Movable munderover uses CommonMsubsup.getUVQ, whose inherited
	// scriptChild getter measures child 1 for the initial getU.
	 := .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 {
			 += 
			 -= 
		}
	}
	return -, 
}

func ( *wrapper) ( *layout.BBox) {
	if .hasMovableLimits() {
		.computeMovableLimitsBBox()
		return
	}
	 := .scriptBase()
	if  == nil {
		.computeChildrenBBox()
		return
	}
	.Empty()
	 := .outerBBox()
	if boolAttributeDefault(.node, "accent", false) {
		.H = math.Max(.H, .renderer.params.XHeight*.Scale)
	}
	switch .node.Kind {
	case "munder":
		 := .underChild()
		 := .outerBBox()
		,  := .underKV(, )
		 := .underOverDelta(true)
		if .lineAccent() {
			 = 0
		}
		 := .stackOffsets([]*layout.BBox{, }, []float64{0, -})
		.Combine(, [0], 0)
		.Combine(, [1], )
		.D += .renderer.params.BigOp5
	case "mover":
		 := .overChild()
		 := .outerBBox()
		,  := .overKU(, )
		 := .underOverDelta(false)
		if .lineAccent() {
			 = 0
		}
		 := .stackOffsets([]*layout.BBox{, }, []float64{0, })
		.Combine(, [0], 0)
		.Combine(, [1], )
		.H += .renderer.params.BigOp5
	case "munderover":
		,  := .underChild(), .overChild()
		,  := .outerBBox(), .outerBBox()
		,  := .overKU(, )
		,  := .underKV(, )
		 := .underOverDelta(false)
		,  := -, 
		if .lineAccent() {
			 = 0
		}
		if .lineAccent() {
			 = 0
		}
		 := .stackOffsets([]*layout.BBox{, , }, []float64{0, , })
		.Combine(, [0], 0)
		.Combine(, [2], )
		.Combine(, [1], )
		.H += .renderer.params.BigOp5
		.D += .renderer.params.BigOp5
	}
	.Clean()
}

func ( *wrapper) ( *Element) {
	if .hasMovableLimits() {
		.movableLimitsToSVG()
		return
	}
	 := .standardSVG()
	 := .scriptBase()
	if  == nil {
		return
	}
	 := .outerBBox()
	.toSVG()
	switch .node.Kind {
	case "munder":
		 := .underChild()
		 := .outerBBox()
		.toSVG()
		 := .underOverDelta(true)
		if .lineAccent() {
			 = 0
		}
		,  := .underKV(, )
		 := .stackOffsets([]*layout.BBox{, }, []float64{0, -})
		.place([0], 0)
		.place([1], )
	case "mover":
		 := .overChild()
		 := .outerBBox()
		.toSVG()
		 := .underOverDelta(false)
		if .lineAccent() {
			 = 0
		}
		,  := .overKU(, )
		 := .stackOffsets([]*layout.BBox{, }, []float64{0, })
		.place([0], 0)
		.place([1], )
	case "munderover":
		,  := .underChild(), .overChild()
		,  := .outerBBox(), .outerBBox()
		.toSVG()
		.toSVG()
		 := .underOverDelta(false)
		,  := -, 
		if .lineAccent() {
			 = 0
		}
		if .lineAccent() {
			 = 0
		}
		,  := .overKU(, )
		,  := .underKV(, )
		 := .stackOffsets([]*layout.BBox{, , }, []float64{0, , })
		.place([0], 0)
		.place([1], )
		.place([2], )
	}
}

func ( *wrapper) ( *Element) {
	 := .standardSVG()
	 := .scriptBase()
	.toSVG()
	 := .baseWidth()
	switch .node.Kind {
	case "munder":
		 := .underChild()
		.toSVG()
		.place(, -.subShift(, .renderer.params.Sub1))
	case "mover":
		 := .overChild()
		.toSVG()
		.place(+.adjustedIC()-.baseIC(), .supShift())
	case "munderover":
		,  := .underChild(), .overChild()
		,  := .scriptOffsetsFor(, )
		.toSVG()
		.toSVG()
		.place(, )
		.place(+.adjustedIC(), )
	}
}