From f36db0db3af6456f7bf0036d76f4386201895d36 Mon Sep 17 00:00:00 2001 From: Peter Tang Date: Fri, 15 Sep 2023 10:53:38 +0800 Subject: [PATCH] complete rest of MTFontMathTableV2 logic --- .../MathBundle/MTFontMathTableV2.swift | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/Sources/SwiftMath/MathBundle/MTFontMathTableV2.swift b/Sources/SwiftMath/MathBundle/MTFontMathTableV2.swift index db76a7e..cde8843 100644 --- a/Sources/SwiftMath/MathBundle/MTFontMathTableV2.swift +++ b/Sources/SwiftMath/MathBundle/MTFontMathTableV2.swift @@ -6,6 +6,8 @@ // import Foundation +import CoreGraphics +import CoreText // extension MathTable { // public func fontMathTableV2() -> MTFontMathTableV2 { @@ -47,5 +49,117 @@ internal class MTFontMathTableV2: MTFontMathTable { } return CGFloat(val.floatValue) / 100 } + /** Returns an Array of all the vertical variants of the glyph if any. If + there are no variants for the glyph, the array contains the given glyph. */ + override func getVerticalVariantsForGlyph(_ glyph: CGGlyph) -> [NSNumber?] { + guard let variants = mTable[kVertVariants] as? NSDictionary else { return [] } + return self.getVariantsForGlyph(glyph, inDictionary: variants) + } + /** Returns an Array of all the horizontal variants of the glyph if any. If + there are no variants for the glyph, the array contains the given glyph. */ + override func getHorizontalVariantsForGlyph(_ glyph: CGGlyph) -> [NSNumber?] { + guard let variants = mTable[kHorizVariants] as? NSDictionary else { return [] } + return self.getVariantsForGlyph(glyph, inDictionary:variants) + } + override func getVariantsForGlyph(_ glyph: CGGlyph, inDictionary variants: NSDictionary) -> [NSNumber?] { + let font = mathFont.mtfont(size: fontSize) + let glyphName = font.get(nameForGlyph: glyph) + + var glyphArray = [NSNumber]() + let variantGlyphs = variants[glyphName] as? NSArray + guard let variantGlyphs = variantGlyphs, variantGlyphs.count != .zero else { + // There are no extra variants, so just add the current glyph to it. + let glyph = font.get(glyphWithName: glyphName) + glyphArray.append(NSNumber(value:glyph)) + return glyphArray + } + for gvn in variantGlyphs { + if let glyphVariantName = gvn as? String { + let variantGlyph = font.get(glyphWithName: glyphVariantName) + glyphArray.append(NSNumber(value:variantGlyph)) + } + } + return glyphArray + } + /** Returns a larger vertical variant of the given glyph if any. + If there is no larger version, this returns the current glyph. + */ + override func getLargerGlyph(_ glyph: CGGlyph) -> CGGlyph { + let font = mathFont.mtfont(size: fontSize) + let glyphName = font.get(nameForGlyph: glyph) + + guard let variants = mTable[kVertVariants] as? NSDictionary, + let variantGlyphs = variants[glyphName] as? NSArray, variantGlyphs.count != .zero else { + // There are no extra variants, so just returnt the current glyph. + return glyph + } + // Find the first variant with a different name. + for gvn in variantGlyphs { + if let glyphVariantName = gvn as? String, glyphVariantName != glyphName { + let variantGlyph = font.get(glyphWithName: glyphVariantName) + return variantGlyph + } + } + // We did not find any variants of this glyph so return it. + return glyph + } + /** Returns the italic correction for the given glyph if any. If there + isn't any this returns 0. */ + override func getItalicCorrection(_ glyph: CGGlyph) -> CGFloat { + let font = mathFont.mtfont(size: fontSize) + let glyphName = font.get(nameForGlyph: glyph) + + guard let italics = mTable[kItalic] as? NSDictionary, let val = italics[glyphName] as? NSNumber else { + return .zero + } + // if val is nil, this returns 0. + return fontUnitsToPt(val.intValue) + } + override func getTopAccentAdjustment(_ glyph: CGGlyph) -> CGFloat { + let font = mathFont.mtfont(size: fontSize) + let glyphName = font.get(nameForGlyph: glyph) + + guard let accents = mTable[kAccents] as? NSDictionary, let val = accents[glyphName] as? NSNumber else { + // If no top accent is defined then it is the center of the advance width. + var glyph = glyph + var advances = CGSize.zero + CTFontGetAdvancesForGlyphs(font.ctFont, .horizontal, &glyph, &advances, 1) + return advances.width/2 + } + return fontUnitsToPt(val.intValue) + } + override func getVerticalGlyphAssembly(forGlyph glyph: CGGlyph) -> [GlyphPart] { + let font = mathFont.mtfont(size: fontSize) + let glyphName = font.get(nameForGlyph: glyph) + + guard let assemblyTable = mTable[kVertAssembly] as? NSDictionary, + let assemblyInfo = assemblyTable[glyphName] as? NSDictionary, + let parts = assemblyInfo[kAssemblyParts] as? NSArray else { + // No vertical assembly defined for glyph + // parts should always have been defined, but if it isn't return nil + return [] + } + + var rv = [GlyphPart]() + for part in parts { + guard let partInfo = part as? NSDictionary, + let adv = partInfo["advance"] as? NSNumber, + let end = partInfo["endConnector"] as? NSNumber, + let start = partInfo["startConnector"] as? NSNumber, + let ext = partInfo["extender"] as? NSNumber, + let glyphName = partInfo["glyph"] as? String else { continue } + let fullAdvance = fontUnitsToPt(adv.intValue) + let endConnectorLength = fontUnitsToPt(end.intValue) + let startConnectorLength = fontUnitsToPt(start.intValue) + let isExtender = ext.boolValue + let glyph = font.get(glyphWithName: glyphName) + let part = GlyphPart(glyph: glyph, fullAdvance: fullAdvance, + startConnectorLength: startConnectorLength, + endConnectorLength: endConnectorLength, + isExtender: isExtender) + rv.append(part) + } + return rv + } }