Skip to content

Commit

Permalink
Merge pull request #10 from petersktang/main
Browse files Browse the repository at this point in the history
Sunset MathTable, added MTFontV2, MTFontMathTableV2 and MathImage

Thanks for your work on this.
  • Loading branch information
mgriebling authored Sep 15, 2023
2 parents 2762cbe + 40a6896 commit be802ae
Show file tree
Hide file tree
Showing 10 changed files with 464 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ internal struct MathTable {
let kConstants = "constants"

let font: MathFont
private let unitsPerEm: UInt
private let fontSize: CGFloat
let unitsPerEm: UInt
let fontSize: CGFloat
weak var fontMathTable: NSDictionary?

init(withFont font: MathFont, fontSize: CGFloat, unitsPerEm: UInt) {
Expand Down Expand Up @@ -176,13 +176,15 @@ internal struct MathTable {
let glyphName = font.get(nameForGlyph: glyph)
let variantGlyphs = variants[glyphName] as? NSArray
var glyphArray = [NSNumber]()
if variantGlyphs == nil || variantGlyphs?.count == 0, let glyph = font.get(glyphWithName: glyphName) {
if variantGlyphs == nil || variantGlyphs?.count == 0 {
// 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
} else if let variantGlyphs = variantGlyphs {
for gvn in variantGlyphs {
if let glyphVariantName = gvn as? String, let variantGlyph = font.get(glyphWithName: glyphVariantName) {
if let glyphVariantName = gvn as? String {
let variantGlyph = font.get(glyphWithName: glyphVariantName)
glyphArray.append(NSNumber(value:variantGlyph))
}
}
Expand All @@ -204,9 +206,8 @@ internal struct MathTable {
// 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
glyphVariantName != glyphName {
return font.get(glyphWithName: glyphVariantName)
}
}
// We did not find any variants of this glyph so return it.
Expand Down Expand Up @@ -243,9 +244,7 @@ internal struct MathTable {
} else {
// If no top accent is defined then it is the center of the advance width.
var advances = CGSize.zero
guard let ctFont = font.ctFont(withSize: fontSize) else {
fatalError("\(#function) unable to obtain ctFont resource name: \(font.rawValue) with size \(fontSize)")
}
let ctFont = font.ctFont(withSize: fontSize)
CTFontGetAdvancesForGlyphs(ctFont, .horizontal, &glyph, &advances, 1)
return advances.width/2
}
Expand All @@ -272,7 +271,8 @@ internal struct MathTable {
}
var rv = [GlyphPart]()
for part in parts {
guard let partInfo = part as? NSDictionary, let glyph = font.get(glyphWithName: glyphName) else { continue }
guard let partInfo = part as? NSDictionary else { continue }
let glyph = font.get(glyphWithName: glyphName)
var part = GlyphPart(glyph: glyph)
if let adv = partInfo["advance"] as? NSNumber,
let end = partInfo["endConnector"] as? NSNumber,
Expand Down
160 changes: 160 additions & 0 deletions Sources/SwiftMath/MathBundle/MTFontMathTableV2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//
// MTFontMathTableV2.swift
//
//
// Created by Peter Tang on 15/9/2023.
//

import Foundation
import CoreGraphics
import CoreText

internal class MTFontMathTableV2: MTFontMathTable {
private let mathFont: MathFont
private let fontSize: CGFloat
private let unitsPerEm: UInt
private let mTable: NSDictionary
init(mathFont: MathFont, size: CGFloat) {
self.mathFont = mathFont
self.fontSize = size
mTable = mathFont.mathTable()
unitsPerEm = mathFont.ctFont(withSize: fontSize).unitsPerEm
super.init(withFont: mathFont.mtfont(size: fontSize), mathTable: mTable)
super._mathTable = nil
// disable all possible access to _mathTable in superclass!
}
override var _mathTable: NSDictionary? {
set { fatalError("\(#function) change to _mathTable \(mathFont.rawValue) not allowed.") }
get { mTable }
}
override var muUnit: CGFloat { fontSize/18 }

override func fontUnitsToPt(_ fontUnits:Int) -> CGFloat {
CGFloat(fontUnits) * fontSize / CGFloat(unitsPerEm)
}
override func constantFromTable(_ constName: String) -> CGFloat {
guard let consts = mTable[kConstants] as? NSDictionary, let val = consts[constName] as? NSNumber else {
return .zero
}
return fontUnitsToPt(val.intValue)
}
override func percentFromTable(_ percentName: String) -> CGFloat {
guard let consts = mTable[kConstants] as? NSDictionary, let val = consts[percentName] as? NSNumber else {
return .zero
}
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
}
}
57 changes: 57 additions & 0 deletions Sources/SwiftMath/MathBundle/MTFontV2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// MTFontV2.swift
//
//
// Created by Peter Tang on 15/9/2023.
//

import Foundation
import CoreGraphics
import CoreText

extension MathFont {
public func mtfont(size: CGFloat) -> MTFontV2 {
MTFontV2(font: self, size: size)
}
}
public final class MTFontV2: MTFont {
let font: MathFont
let size: CGFloat
private lazy var _cgFont: CGFont = {
font.cgFont()
}()
private lazy var _ctFont: CTFont = {
font.ctFont(withSize: size)
}()
private lazy var _mathTab = MTFontMathTableV2(mathFont: font, size: size)
init(font: MathFont = .latinModernFont, size: CGFloat) {
self.font = font
self.size = size

super.init()

super.defaultCGFont = nil
super.ctFont = nil
super.mathTable = nil
super.rawMathTable = nil
}
override var defaultCGFont: CGFont! {
set { fatalError("\(#function): change to \(font.fontName) not allowed.") }
get { _cgFont }
}
override var ctFont: CTFont! {
set { fatalError("\(#function): change to \(font.fontName) not allowed.") }
get { _ctFont }
}
override var mathTable: MTFontMathTable? {
set { fatalError("\(#function): change to \(font.rawValue) not allowed.") }
get { _mathTab }
}
override var rawMathTable: NSDictionary? {
set { fatalError("\(#function): change to \(font.rawValue) not allowed.") }
get { fatalError("\(#function): access to \(font.rawValue) not allowed.") }
}
public override func copy(withSize size: CGFloat) -> MTFont {
MTFontV2(font: font, size: size)
}
}
Loading

0 comments on commit be802ae

Please sign in to comment.