GithubHelp home page GithubHelp logo

mgriebling / swiftmath Goto Github PK

View Code? Open in Web Editor NEW
141.0 7.0 22.0 2.45 MB

SwiftMath provides a full Swift implementation of iosMath for displaying beautifully rendered math equations in iOS and MacOS applications. It typesets formulae written using LaTeX in a UILabel equivalent class.

License: MIT License

Swift 100.00%
ios latex mac math swift typeset iosmath

swiftmath's Introduction

SwiftMath

SwiftMath provides a full Swift implementation of iosMath for displaying beautifully rendered math equations in iOS and MacOS applications. It typesets formulae written using LaTeX in a UILabel equivalent class. It uses the same typesetting rules as LaTeX and so the equations are rendered exactly as LaTeX would render them.

SwiftMath is similar to MathJax or KaTeX for the web but for native iOS or MacOS applications without having to use a UIWebView and Javascript. More importantly, it is significantly faster than using a UIWebView.

SwiftMath is a Swift translation of the latest iosMath v0.9.5 release but includes bug fixes and enhancements like a new \lbar (lambda bar) character and cyrillic alphabet support. The original iosMath test suites have also been translated to Swift and run without errors. Note: Error test conditions are ignored to avoid tagging everything with silly throws. Please let me know of any bugs or bug fixes that you find.

SwiftMath prepackages everything needed for direct access via the Swift Package Manager.

Examples

Here are screenshots of some formulae that were rendered with this library:

x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}

Quadratic Formula

f(x) = \int\limits_{-\infty}^\infty\!\hat f(\xi)\,e^{2 \pi i \xi x}\,\mathrm{d}\xi

Calculus

\frac{1}{n}\sum_{i=1}^{n}x_i \geq \sqrt[n]{\prod_{i=1}^{n}x_i}

AM-GM

\frac{1}{\left(\sqrt{\phi \sqrt{5}}-\phi\\right) e^{\frac25 \pi}}
= 1+\frac{e^{-2\pi}} {1 +\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}} {1+\frac{e^{-8\pi}} {1+\cdots} } } }

Ramanujan Identity

More examples are included in EXAMPLES

Requirements

SwiftMath works on iOS 11+ or MacOS 11+. It depends on the following Apple frameworks:

  • Foundation.framework
  • CoreGraphics.framework
  • QuartzCore.framework
  • CoreText.framework

Additionally for iOS it requires:

  • UIKit.framework

Additionally for MacOS it requires:

  • AppKit.framework

Installation

Swift Package

SwiftMath is available from SwiftMath. To use it in your code, just add the https://github.com/mgriebling/SwiftMath.git path to XCode's package manager.

Usage

The library provides a class MTMathUILabel which is a UIView that supports rendering math equations. To display an equation simply create an MTMathUILabel as follows:

import SwiftMath

let label = MTMathUILabel()
label.latex = "x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}"

Adding MTMathUILabel as a sub-view of your UIView will render the quadratic formula example shown above.

The following code creates a SwiftUI component called MathView encapsulating the MTMathUILabel:

import SwiftUI
import SwiftMath

struct MathView: UIViewRepresentable {

    var equation: String
    var fontSize: CGFloat
    
    func makeUIView(context: Context) -> MTMathUILabel {
        let view = MTMathUILabel()
        return view
    }
    
    func updateUIView(_ uiView: MTMathUILabel, context: Context) {
        uiView.latex = equation
        uiView.fontSize = fontSize
        uiView.font = MTFontManager().termesFont(withSize: fontSize)
        uiView.textAlignment = .right
        uiView.labelMode = .text
    }
}

For code that works with SwiftUI running natively under MacOS use the following:

import SwiftUI
import SwiftMath

struct MathView: NSViewRepresentable {
    
    var equation: String
    var fontSize: CGFloat
    
    func makeNSView(context: Context) -> MTMathUILabel {
        let view = MTMathUILabel()
        return view
    }
    
    func updateNSView(_ view: MTMathUILabel, context: Context) {
        view.latex = equation
        view.fontSize = fontSize
        view.font = MTFontManager().termesFont(withSize: fontSize)
        view.textColor = .textColor
        view.textAlignment = .center
        view.labelMode = .display
    }
}

Included Features

This is a list of formula types that the library currently supports:

  • Simple algebraic equations
  • Fractions and continued fractions
  • Exponents and subscripts
  • Trigonometric formulae
  • Square roots and n-th roots
  • Calculus symbos - limits, derivatives, integrals
  • Big operators (e.g. product, sum)
  • Big delimiters (using \left and \right)
  • Greek alphabet
  • Combinatorics (\binom, \choose etc.)
  • Geometry symbols (e.g. angle, congruence etc.)
  • Ratios, proportions, percents
  • Math spacing
  • Overline and underline
  • Math accents
  • Matrices
  • Equation alignment
  • Change bold, roman, caligraphic and other font styles (\bf, \text, etc.)
  • Most commonly used math symbols
  • Colors

Example

The SwiftMathDemo is a SwiftUI version of the Objective-C demo included in iosMath that uses SwiftMath as a Swift package dependency.

Advanced configuration

MTMathUILabel supports some advanced configuration options:

Math mode

You can change the mode of the MTMathUILabel between Display Mode (equivalent to $$ or \[ in LaTeX) and Text Mode (equivalent to $ or \( in LaTeX). The default style is Display. To switch to Text simply:

label.labelMode = .text
Text Alignment

The default alignment of the equations is left. This can be changed to center or right as follows:

label.textAlignment = .center
Font size

The default font-size is 25pt. You can change it as follows:

label.fontSize = 30
Font

The default font is Latin Modern Math. This can be changed as:

label.font = MTFontManager.fontmanager.termesFont(withSize:20)

This project has 3 fonts bundled with it, but you can use any OTF math font. Note: I couldn't get the iosMath Python script to work. If you do manage to get it working, please let me know.

Color

The default color of the rendered equation is black. You can change it to any other color as follows:

label.textColor = .red

It is also possible to set different colors for different parts of the equation. Just access the displayList field and set the textColor on the underlying displays that you want to change the color of.

Custom Commands

You can define your own commands that are not already predefined. This is similar to macros is LaTeX. To define your own command use:

MTMathAtomFactory.addLatexSymbol("lcm", value: MTMathAtomFactory.operator(withName: "lcm", limits: false))

This creates an \lcm command that can be used in the LaTeX.

Content Insets

The MTMathUILabel has contentInsets for finer control of placement of the equation in relation to the view.

If you need to set it you can do as follows:

label.contentInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 20)
Error handling

If the LaTeX text given to MTMathUILabel is invalid or if it contains commands that aren't currently supported then an error message will be displayed instead of the label.

This error can be programmatically retrieved as label.error. If you prefer not to display anything then set:

label.displayErrorInline = true

Future Enhancements

Note this is not a complete implementation of LaTeX math mode. There are some important pieces that are missing and will be included in future updates. This includes:

  • Support for explicit big delimiters (bigl, bigr etc.)
  • Addition of missing plain TeX commands

License

SwiftMath is available under the MIT license. See the LICENSE file for more info.

Fonts

This distribution contains the following fonts. These fonts are licensed as follows:

swiftmath's People

Contributors

andredouzette avatar mgriebling avatar oskarpersson avatar petersktang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftmath's Issues

No difference between 'display' and 'text'

You might want to remove the "math mode" section of the Read Me's Advanced Config section. As far as I can tell, there isn't any difference between MTMathUILabelMode.display and MTMathUILabelMode.text. There wasn't in the iOSMath version of this, either, so it's the original authors' code that doesn't work as intended, not yours.

Users who see it will expect the code to properly format inline (text) mode, which the code can't, for some reason.

Line breaks not supported

Greetings

I'm working on a math app and SwiftMath has been very useful in my project and I Love it..

However, whenever I stumble upon an edge case where I'm dealing with long equations that simply can't fit into one line,
I can't seem to find a solution to create either manual line breaks or automatic line breaks within Latex in case of the text being longer than the screens width.

Will there ever be support for this feature in future?

Support for MathJax Font

I’d like to express my appreciation for the SwiftMath package, which has been incredibly useful in my recent Swift projects. I am seeking to add support for the MathJax font within the package. The MathJax font is preferred for its aesthetic and would help ensure consistency between the app and web versions of my project.

I've explored the fonts provided by the SwiftMath package and attempted to integrate the MathJax font by adding SwiftMath as a local package and modifying it. Despite these efforts, I consistently encounter crashes originating from the MTFontMathTable file due to the absence of a math table.

This issue leads me to believe that the MathJax font may lack a necessary math table, which could render direct support for the MathJax font unfeasible.

Could you please investigate the possibility of integrating MathJax font support within SwiftMath? Any guidance or suggestions on how to overcome the current limitations would be greatly appreciated.

Thank you for your attention to this matter.

\\newline Command not working on swiftUI IOS

Hi, I've adopted the dependency on a side project I'm working on in SwiftUI for IOS, however I cant seem to create a new line or wrap the equation to be confined in frame or container with a specific width..

can you please help

MTFontManager manager is nil

manager is accessible to external apps, fontManager is inaccessible, the below fixes manager nil issue.

public class MTFontManager {
static public private(set) var manager: MTFontManager = {
    MTFontManager()
}()

let kDefaultFontSize = CGFloat(20)

static var fontManager : MTFontManager {
    return manager
}

Colored text gets misaligned

The following string results in c being misaligned

\color{#ff0000}a + b + \color{#ff0000}c

In Latex and MathJax it seems like \textcolor is the way to go to avoid alignment issues but that doesn't seem to exist in SwiftMath yet?

\textcolor{#ff0000}{a}+b+\textcolor{#ff0000}{c}

Thread-safe exception

Description of the Exception

When running the below concurrently in a multi-thread situation, the below functions sometimes hit thread-safe exception.

  • getInterElementSpaces()
  • MTMathAtomFactory.delimValueToName
  • MTMathAtomFactory.accentValueToName
  • MTMathAtomFactory.textToLatexSymbolName

Thread 2: EXC_BAD_ACCESS (code=1, address=0xfffffffffffffff0)

Test code run repeatedly

    private let executionQueue = DispatchQueue(label: "com.swiftmath.concurrencytests", attributes: .concurrent)
    private let executionGroup = DispatchGroup()
    
    let totalCases = 20
    var testCount = 0
    
    func testSwiftMathConcurrentScript() throws {
        for caseNumber in 0 ..< totalCases {
            helperConcurrency(caseNumber, in: executionGroup, on: executionQueue) {
                let result1 = getInterElementSpaces()
                let result2 = MTMathAtomFactory.delimValueToName
                let result3 = MTMathAtomFactory.accentValueToName
                let result4 = MTMathAtomFactory.textToLatexSymbolName
                XCTAssertNotNil(result1)
                XCTAssertNotNil(result2)
                XCTAssertNotNil(result3)
                XCTAssertNotNil(result4)
            }
        }
        executionGroup.notify(queue: .main) { [weak self] in
            // print("All test cases completed: \(self?.testCount ?? 0)")
        }
        executionGroup.wait()
    }
    func helperConcurrency(_ count: Int, in group: DispatchGroup, on queue: DispatchQueue, _ testClosure: @escaping () -> (Void)) {
        let workitem = DispatchWorkItem {
            testClosure()
        }
        workitem.notify(queue: .main) { [weak self] in
            self?.testCount += 1
        }
        queue.async(group: group, execute: workitem)
    }

Further investigations

At the moment the below static function is not invoked by any code, however, if in-use, will also cause thread-safety exception.

    public static func add(latexSymbol name: String, value: MTMathAtom) {
        supportedLatexSymbols[name] = value
        Self.textToLatexSymbolName[value.nucleus] = name
    }

How can i use other fonts ?

SwiftMath is wonderfull. I'm trying to integrate it in my project EureKalc. But I don't understand how to manage using other fonts thant those provided. You writ : "you can use any OTF math font." But the mathFonts bundle contains, for each font, a .ort file and a .plist. I found some .otf files for math fonts on the web. But no .plist file. I suppose I did not understand something important. Can you help ???
Thanks !
Nico

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.