diff --git a/Sources/SwiftMath/MathRender/MTMathList.swift b/Sources/SwiftMath/MathRender/MTMathList.swift index cadd5d6..8c99949 100644 --- a/Sources/SwiftMath/MathRender/MTMathList.swift +++ b/Sources/SwiftMath/MathRender/MTMathList.swift @@ -64,6 +64,7 @@ public enum MTMathAtomType: Int, CustomStringConvertible, Comparable { /// Denotes style changes during rendering. case style case color + case textcolor case colorBox // Atoms after this point are not part of TeX and do not have the usual structure. @@ -106,6 +107,7 @@ public enum MTMathAtomType: Int, CustomStringConvertible, Comparable { case .space: return "Space" case .style: return "Style" case .color: return "Color" + case .textcolor: return "TextColor" case .colorBox: return "Colorbox" case .table: return "Table" } @@ -235,6 +237,8 @@ public class MTMathAtom: NSObject { return MTMathSpace(self as? MTMathSpace) case .color: return MTMathColor(self as? MTMathColor) + case .textcolor: + return MTMathTextColor(self as? MTMathTextColor) case .colorBox: return MTMathColorbox(self as? MTMathColorbox) case .table: @@ -675,6 +679,38 @@ public class MTMathColor: MTMathAtom { } } +// MARK: - MTMathTextColor +/** An atom representing an textcolor element. + Note: None of the usual fields of the `MTMathAtom` apply even though this + class inherits from `MTMathAtom`. i.e. it is meaningless to have a value + in the nucleus, subscript or superscript fields. */ +public class MTMathTextColor: MTMathAtom { + public var colorString:String="" + public var innerList:MTMathList? + + init(_ color: MTMathTextColor?) { + super.init(color) + self.type = .textcolor + self.colorString = color?.colorString ?? "" + self.innerList = MTMathList(color?.innerList) + } + + override init() { + super.init() + self.type = .textcolor + } + + public override var string: String { + "\\textcolor{\(self.colorString)}{\(self.innerList!.string)}" + } + + override public var finalized: MTMathAtom { + let newColor = super.finalized as! MTMathTextColor + newColor.innerList = newColor.innerList?.finalized + return newColor + } +} + // MARK: - MTMathColorbox /** An atom representing an colorbox element. Note: None of the usual fields of the `MTMathAtom` apply even though this diff --git a/Sources/SwiftMath/MathRender/MTMathListBuilder.swift b/Sources/SwiftMath/MathRender/MTMathListBuilder.swift index 3857263..3b146c9 100644 --- a/Sources/SwiftMath/MathRender/MTMathListBuilder.swift +++ b/Sources/SwiftMath/MathRender/MTMathListBuilder.swift @@ -593,6 +593,12 @@ public struct MTMathListBuilder { mathColor.colorString = self.readColor()! mathColor.innerList = self.buildInternal(true) return mathColor + } else if command == "textcolor" { + // A textcolor command has 2 arguments + let mathColor = MTMathTextColor() + mathColor.colorString = self.readColor()! + mathColor.innerList = self.buildInternal(true) + return mathColor } else if command == "colorbox" { // A color command has 2 arguments let mathColorbox = MTMathColorbox() diff --git a/Sources/SwiftMath/MathRender/MTTypesetter.swift b/Sources/SwiftMath/MathRender/MTTypesetter.swift index 791c1a8..609767d 100644 --- a/Sources/SwiftMath/MathRender/MTTypesetter.swift +++ b/Sources/SwiftMath/MathRender/MTTypesetter.swift @@ -49,7 +49,7 @@ func getInterElementSpaces() -> [[InterElementSpaceType]] { // Get's the index for the given type. If row is true, the index is for the row (i.e. left element) otherwise it is for the column (right element) func getInterElementSpaceArrayIndexForType(_ type:MTMathAtomType, row:Bool) -> Int { switch type { - case .color, .colorBox, .ordinary, .placeholder: // A placeholder is treated as ordinary + case .color, .textcolor, .colorBox, .ordinary, .placeholder: // A placeholder is treated as ordinary return 0 case .largeOperator: return 1 @@ -511,7 +511,37 @@ class MTTypesetter { display!.position = currentPosition currentPosition.x += display!.width displayAtoms.append(display!) - + + case .textcolor: + // stash the existing layout + if currentLine.length > 0 { + self.addDisplayLine() + } + let colorAtom = atom as! MTMathTextColor + let display = MTTypesetter.createLineForMathList(colorAtom.innerList, font: font, style: style) + display!.localTextColor = MTColor(fromHexString: colorAtom.colorString) + + if prevNode != nil { + let subDisplay: MTDisplay = display!.subDisplays[0] + let subDisplayAtom = (subDisplay as? MTCTLineDisplay)!.atoms[0] + let interElementSpace = self.getInterElementSpace(prevNode!.type, right:subDisplayAtom.type) + if currentLine.length > 0 { + if interElementSpace > 0 { + // add a kerning of that space to the previous character + currentLine.addAttribute(kCTKernAttributeName as NSAttributedString.Key, + value:NSNumber(floatLiteral: interElementSpace), + range:currentLine.mutableString.rangeOfComposedCharacterSequence(at: currentLine.length-1)) + } + } else { + // increase the space + currentPosition.x += interElementSpace + } + } + + display!.position = currentPosition + currentPosition.x += display!.width + displayAtoms.append(display!) + case .colorBox: // stash the existing layout if currentLine.length > 0 {