diff --git a/Sources/SwiftMathRender/MathRender/MTFont.swift b/Sources/SwiftMathRender/MathRender/MTFont.swift index 63f20d0..718f685 100644 --- a/Sources/SwiftMathRender/MathRender/MTFont.swift +++ b/Sources/SwiftMathRender/MathRender/MTFont.swift @@ -9,11 +9,9 @@ import Foundation import CoreGraphics import CoreText -// -// Font.swift -// iosMath // // Created by Kostub Deshmukh on 5/18/16. +// Modified by Michael Griebling on 17 Jan 2023. // // This software may be modified and distributed under the terms of the // MIT license. See the LICENSE file for details. @@ -42,16 +40,15 @@ public class MTFont { self.ctFont = CTFontCreateWithGraphicsFont(self.defaultCGFont, size, nil, nil); + print("Loading associated .plist") let mathTablePlist = bundle.url(forResource:name, withExtension:"plist") - let dict = NSDictionary(contentsOf: mathTablePlist!) // dictionaryWithContentsOfFile:mathTablePlist]; - self.rawMathTable = dict + self.rawMathTable = NSDictionary(contentsOf: mathTablePlist!) self.mathTable = MTFontMathTable(withFont:self, mathTable:rawMathTable!) } static var fontBundle:Bundle { // Uses bundle for class so that this can be access by the unit tests. - let url = Bundle.module.url(forResource: "mathFonts", withExtension: "bundle")! - return Bundle(url: url)! + Bundle(url: Bundle.module.url(forResource: "mathFonts", withExtension: "bundle")!)! } func copy(withSize size: CGFloat) -> MTFont { @@ -65,15 +62,13 @@ public class MTFont { func get(nameForGlyph glyph:CGGlyph) -> String { let name = defaultCGFont.name(for: glyph) as? String - return name! + return name ?? "" } func get(glyphWithName name:String) -> CGGlyph { - return defaultCGFont.getGlyphWithGlyphName(name: name as CFString) + defaultCGFont.getGlyphWithGlyphName(name: name as CFString) } - var fontSize:CGFloat { - return CTFontGetSize(self.ctFont) - } + var fontSize:CGFloat { CTFontGetSize(self.ctFont) } } diff --git a/Sources/SwiftMathRender/MathRender/MTFontManager.swift b/Sources/SwiftMathRender/MathRender/MTFontManager.swift index 0206e08..06dd55f 100644 --- a/Sources/SwiftMathRender/MathRender/MTFontManager.swift +++ b/Sources/SwiftMathRender/MathRender/MTFontManager.swift @@ -10,6 +10,7 @@ import Foundation public class MTFontManager { static var manager:MTFontManager? = nil + let kDefaultFontSize = CGFloat(20) static var fontManager : MTFontManager { diff --git a/Sources/SwiftMathRender/MathRender/MTFontMathTable.swift b/Sources/SwiftMathRender/MathRender/MTFontMathTable.swift index 0cc0c6b..b867ef9 100644 --- a/Sources/SwiftMathRender/MathRender/MTFontMathTable.swift +++ b/Sources/SwiftMathRender/MathRender/MTFontMathTable.swift @@ -56,7 +56,7 @@ class MTFontMathTable { var muUnit:CGFloat { _fontSize/18 } func fontUnitsToPt(_ fontUnits:Int) -> CGFloat { - return CGFloat(fontUnits) * _fontSize / CGFloat(_unitsPerEm) + CGFloat(fontUnits) * _fontSize / CGFloat(_unitsPerEm) } init(withFont font: MTFont?, mathTable:NSDictionary) { @@ -286,7 +286,7 @@ class MTFontMathTable { let kAssemblyParts = "parts" /** Returns an array of the glyph parts to be used for constructing vertical variants - of this glyph. If there is no glyph assembly defined, returns nil. */ + of this glyph. If there is no glyph assembly defined, returns an empty array. */ func getVerticalGlyphAssembly(forGlyph glyph:CGGlyph) -> [GlyphPart] { let assemblyTable = _mathTable[kVertAssembly] as! NSDictionary? let glyphName = self.font?.get(nameForGlyph: glyph) // getGlyphName:glyph]; diff --git a/Sources/SwiftMathRender/MathRender/MTMathList.swift b/Sources/SwiftMathRender/MathRender/MTMathList.swift index 6845414..d5d3079 100644 --- a/Sources/SwiftMathRender/MathRender/MTMathList.swift +++ b/Sources/SwiftMathRender/MathRender/MTMathList.swift @@ -46,9 +46,7 @@ public enum MTMathAtomType: Int, CustomStringConvertible, Comparable { } } - func isScriptAllowed() -> Bool { - return self != .boundary && self != .space && self != .style && self != .table - } + func isScriptAllowed() -> Bool { self < .boundary } // we want string representations to be capitalized public var description: String { @@ -80,9 +78,7 @@ public enum MTMathAtomType: Int, CustomStringConvertible, Comparable { } // comparable support - public static func < (lhs: MTMathAtomType, rhs: MTMathAtomType) -> Bool { - lhs.rawValue < rhs.rawValue - } + public static func < (lhs: MTMathAtomType, rhs: MTMathAtomType) -> Bool { lhs.rawValue < rhs.rawValue } } @@ -109,6 +105,8 @@ public enum MTFontStyle:Int { boldItalic } +// MARK: - MTMathAtom + public class MTMathAtom: NSObject { public var type = MTMathAtomType.ordinary @@ -128,6 +126,7 @@ public class MTMathAtom: NSObject { } } } + public var nucleus: String = "" public var indexRange = NSRange(location: 0, length: 0) // indexRange in list that this atom tracks: @@ -183,22 +182,6 @@ public class MTMathAtom: NSObject { } } - public func setSuperScript(_ list: MTMathList?) { - if self.isScriptAllowed() { - self.superScript = list - } else { - NSException(name: NSExceptionName(rawValue: "Error"), reason: "Superscripts not allowed for atom \(self.type.rawValue)").raise() - } - } - - public func setSubScript(_ list: MTMathList?) { - if self.isScriptAllowed() { - self.subScript = list - } else { - NSException(name: NSExceptionName(rawValue: "Error"), reason: "Subscripts not allowed for atom \(self.type.rawValue)").raise() - } - } - public override var description: String { var string = "" string += self.nucleus @@ -267,25 +250,27 @@ public class MTMathAtom: NSObject { } func isNotBinaryOperator(_ prevNode:MTMathAtom?) -> Bool { - if prevNode == nil { return true } - return prevNode!.type.isNotBinaryOperator() + guard let prevNode = prevNode else { return true } + return prevNode.type.isNotBinaryOperator() } +// MARK: - MTFraction + public class MTFraction: MTMathAtom { public var hasRule: Bool = true public var leftDelimiter: String? public var rightDelimiter: String? - public var numerator: MTMathList? - public var denominator: MTMathList? + public var numerator: MTMathList? + public var denominator: MTMathList? init(_ frac: MTFraction?) { super.init(frac) self.type = .fraction - self.numerator = MTMathList(frac?.numerator) - self.denominator = MTMathList(frac?.denominator) - self.hasRule = frac?.hasRule ?? true - self.leftDelimiter = frac?.leftDelimiter - self.rightDelimiter = frac?.rightDelimiter + self.numerator = MTMathList(frac!.numerator) + self.denominator = MTMathList(frac!.denominator) + self.hasRule = frac!.hasRule + self.leftDelimiter = frac!.leftDelimiter + self.rightDelimiter = frac!.rightDelimiter } init(hasRule rule:Bool = true) { @@ -322,15 +307,15 @@ public class MTFraction: MTMathAtom { override public var finalized: MTMathAtom { let finalized: MTFraction = super.finalized as! MTFraction - finalized.numerator = finalized.numerator?.finalized finalized.denominator = finalized.denominator?.finalized - return finalized } } +// MARK: - MTRadical + public class MTRadical: MTMathAtom { // Under the roof public var radicand: MTMathList? @@ -383,19 +368,19 @@ public class MTRadical: MTMathAtom { } } +// MARK: - MTLargeOperator + public class MTLargeOperator: MTMathAtom { public var limits: Bool = false init(_ op:MTLargeOperator?) { super.init(op) self.type = .largeOperator - self.limits = op?.limits ?? false + self.limits = op!.limits } init(value: String, limits: Bool) { - super.init() - self.type = .largeOperator - self.nucleus = value + super.init(type: .largeOperator, value: value) self.limits = limits } } @@ -463,6 +448,8 @@ public class MTInner: MTMathAtom { } } +// MARK: - MTOverLIne + public class MTOverLine: MTMathAtom { public var innerList: MTMathList? @@ -484,6 +471,8 @@ public class MTOverLine: MTMathAtom { } } +// MARK: - MTUnderLine + public class MTUnderLine: MTMathAtom { public var innerList: MTMathList? @@ -505,6 +494,8 @@ public class MTUnderLine: MTMathAtom { } } +// MARK: - MTAccent + public class MTAccent: MTMathAtom { public var innerList: MTMathList? @@ -527,6 +518,8 @@ public class MTAccent: MTMathAtom { } } +// MARK: - MTMathSpace + public class MTMathSpace: MTMathAtom { public var space: CGFloat = 0 @@ -543,33 +536,32 @@ public class MTMathSpace: MTMathAtom { } } -public enum MTLineStyle { +public enum MTLineStyle:Int, Comparable { + case display case text case script case scriptOfScript public func inc() -> MTLineStyle { - switch self { - case .display: return .text - case .text: return .script - case .script: return .scriptOfScript - case .scriptOfScript: return .display - } + let raw = self.rawValue + 1 + if let style = MTLineStyle(rawValue: raw) { return style } + return .display } - public var isNotScript:Bool { - self == .display || self == .text - } + public var isNotScript:Bool { self < .script } + public static func < (lhs: MTLineStyle, rhs: MTLineStyle) -> Bool { lhs.rawValue < rhs.rawValue } } +// MARK: - MTMathStyle + public class MTMathStyle: MTMathAtom { public var style: MTLineStyle = .display init(_ style:MTMathStyle?) { super.init(style) self.type = .style - self.style = style?.style ?? .display + self.style = style!.style } init(style:MTLineStyle) { @@ -579,6 +571,8 @@ public class MTMathStyle: MTMathAtom { } } +// MARK: - MTMathColor + public class MTMathColor: MTMathAtom { public var colorString:String="" public var innerList:MTMathList? @@ -600,6 +594,8 @@ public class MTMathColor: MTMathAtom { } } +// MARK: - MTMathColorbox + public class MTMathColorbox: MTMathAtom { public var colorString:String="" public var innerList:MTMathList? @@ -627,6 +623,8 @@ public enum MTColumnAlignment { case right } +// MARK: - MTMathTable + public class MTMathTable: MTMathAtom { public var alignments = [MTColumnAlignment]() public var cells = [[MTMathList]]() @@ -711,19 +709,17 @@ public class MTMathTable: MTMathAtom { public var numColumns: Int { var numberOfCols = 0 - for row in self.cells { numberOfCols = max(numberOfCols, row.count) } - return numberOfCols } - public var numRows: Int { - return self.cells.count - } + public var numRows: Int { self.cells.count } } +// MARK: - MTMathList + // represent list of math objects extension MTMathList { public override var description: String { self.atoms.description } @@ -759,22 +755,15 @@ public class MTMathList : NSObject { if prevNode == nil || prevNode!.isNotBinaryOperator() { newNode.type = .unaryOperator } - break case .relation, .punctuation, .close: - if prevNode != nil && - prevNode!.type == .binaryOperator { + if prevNode != nil && prevNode!.type == .binaryOperator { prevNode!.type = .unaryOperator } - break case .number: - if prevNode != nil && - prevNode!.type == .number && - prevNode!.subScript == nil && - prevNode!.superScript == nil { + if prevNode != nil && prevNode!.type == .number && prevNode!.subScript == nil && prevNode!.superScript == nil { prevNode!.fuse(with: newNode) continue } - break default: break } @@ -840,7 +829,7 @@ public class MTMathList : NSObject { } func removeLastAtom() { - if self.atoms.count > 0 { + if !self.atoms.isEmpty { self.atoms.removeLast() } } @@ -856,7 +845,5 @@ public class MTMathList : NSObject { self.atoms.removeSubrange(range) } - func isAtomAllowed(_ atom: MTMathAtom?) -> Bool { - return atom?.type != .boundary - } + func isAtomAllowed(_ atom: MTMathAtom?) -> Bool { atom?.type != .boundary } } diff --git a/Sources/SwiftMathRender/MathRender/MTMathListDisplay.swift b/Sources/SwiftMathRender/MathRender/MTMathListDisplay.swift index 2104005..ff519a7 100644 --- a/Sources/SwiftMathRender/MathRender/MTMathListDisplay.swift +++ b/Sources/SwiftMathRender/MathRender/MTMathListDisplay.swift @@ -682,6 +682,7 @@ class MTLargeOpLimitsDisplay : MTDisplay { override var position: CGPoint { set { + super.position = newValue self.updateLowerLimitPosition() self.updateUpperLimitPosition() self.updateNucleusPosition() diff --git a/Sources/SwiftMathRender/MathRender/MTTypesetter.swift b/Sources/SwiftMathRender/MathRender/MTTypesetter.swift index e13117a..8a10720 100644 --- a/Sources/SwiftMathRender/MathRender/MTTypesetter.swift +++ b/Sources/SwiftMathRender/MathRender/MTTypesetter.swift @@ -346,9 +346,13 @@ class MTTypesetter { var currentLine:NSMutableAttributedString! var currentAtoms = [MTMathAtom]() // List of atoms that make the line var currentLineIndexRange = NSMakeRange(0, 0) - var style:MTLineStyle + var style:MTLineStyle { didSet { _styleFont = nil } } + private var _styleFont:MTFont? var styleFont:MTFont { - self.font.copy(withSize: Self.getStyleSize(self.style, font: self.font)) + if _styleFont == nil { + _styleFont = font.copy(withSize: Self.getStyleSize(style, font: font)) + } + return _styleFont! } var cramped = false var spaced = false @@ -752,18 +756,12 @@ class MTTypesetter { func getSpacingInMu(_ type: InterElementSpaceType) -> Int { // let valid = [MTLineStyle.display, .text] switch type { - case .invalid: - return -1; - case .none: - return 0; - case .thin: - return 3; - case .nsThin: - return style.isNotScript ? 3 : 0; - case .nsMedium: - return style.isNotScript ? 4 : 0; - case .nsThick: - return style.isNotScript ? 5 : 0; + case .invalid: return -1 + case .none: return 0 + case .thin: return 3 + case .nsThin: return style.isNotScript ? 3 : 0; + case .nsMedium: return style.isNotScript ? 4 : 0; + case .nsThick: return style.isNotScript ? 5 : 0; } } @@ -788,25 +786,19 @@ class MTTypesetter { func scriptStyle() -> MTLineStyle { switch style { - case .display, .text: - return .script - case .script, .scriptOfScript: - return .scriptOfScript + case .display, .text: return .script + case .script, .scriptOfScript: return .scriptOfScript } } // subscript is always cramped - func subscriptCramped() -> Bool { - return true; - } + func subscriptCramped() -> Bool { true } // superscript is cramped only if the current style is cramped - func superScriptCramped() -> Bool { - return cramped; - } + func superScriptCramped() -> Bool { cramped } func superScriptShiftUp() -> CGFloat { - if (cramped) { + if cramped { return styleFont.mathTable!.superscriptShiftUpCramped; } else { return styleFont.mathTable!.superscriptShiftUp; @@ -822,7 +814,6 @@ class MTTypesetter { var subscriptShiftDown = 0.0 display?.hasScript = true - // let classy = display is MTCTLineDisplay if !(display is MTCTLineDisplay) { // get the font in script style let scriptFontSize = Self.getStyleSize(self.scriptStyle(), font:font) @@ -893,21 +884,21 @@ class MTTypesetter { func numeratorShiftUp(_ hasRule:Bool) -> CGFloat { if hasRule { if style == .display { - return styleFont.mathTable!.fractionNumeratorDisplayStyleShiftUp; + return styleFont.mathTable!.fractionNumeratorDisplayStyleShiftUp } else { - return styleFont.mathTable!.fractionNumeratorShiftUp; + return styleFont.mathTable!.fractionNumeratorShiftUp } } else { - if (style == .display) { - return styleFont.mathTable!.stackTopDisplayStyleShiftUp; + if style == .display { + return styleFont.mathTable!.stackTopDisplayStyleShiftUp } else { - return styleFont.mathTable!.stackTopShiftUp; + return styleFont.mathTable!.stackTopShiftUp } } } func numeratorGapMin() -> CGFloat { - if (style == .display) { + if style == .display { return styleFont.mathTable!.fractionNumeratorDisplayStyleGapMin; } else { return styleFont.mathTable!.fractionNumeratorGapMin; @@ -916,13 +907,13 @@ class MTTypesetter { func denominatorShiftDown(_ hasRule:Bool) -> CGFloat { if hasRule { - if (style == .display) { + if style == .display { return styleFont.mathTable!.fractionDenominatorDisplayStyleShiftDown; } else { return styleFont.mathTable!.fractionDenominatorShiftDown; } } else { - if (style == .display) { + if style == .display { return styleFont.mathTable!.stackBottomDisplayStyleShiftDown; } else { return styleFont.mathTable!.stackBottomShiftDown; @@ -1295,7 +1286,7 @@ class MTTypesetter { currentPosition.x += display!.width return display; } - if (op.limits && style == .display) { + if op.limits && style == .display { // make limits var superScript:MTMathListDisplay? = nil, subScript:MTMathListDisplay? = nil if op.superScript != nil { @@ -1304,7 +1295,7 @@ class MTTypesetter { if op.subScript != nil { subScript = MTTypesetter.createLineForMathList(op.subScript, font:font, style:self.scriptStyle(), cramped:self.subscriptCramped()) } - assert((superScript != nil) || (subScript != nil), "Atleast one of superscript or subscript should have been present."); + assert((superScript != nil) || (subScript != nil), "At least one of superscript or subscript should have been present."); let opsDisplay = MTLargeOpLimitsDisplay(withNucleus:display, upperLimit:superScript, lowerLimit:subScript, limitShift:delta/2, extraPadding:0) if superScript != nil { let upperLimitGap = max(styleFont.mathTable!.upperLimitGapMin, styleFont.mathTable!.upperLimitBaselineRiseMin - superScript!.descent);