diff --git a/iosMath/lib/MTMathList.h b/iosMath/lib/MTMathList.h index a385423..f6a65eb 100644 --- a/iosMath/lib/MTMathList.h +++ b/iosMath/lib/MTMathList.h @@ -9,7 +9,8 @@ // MIT license. See the LICENSE file for details. // -#import +@import Foundation; +@import CoreGraphics; NS_ASSUME_NONNULL_BEGIN @@ -62,6 +63,13 @@ typedef NS_ENUM(NSUInteger, MTMathAtomType) /// A left atom - Left & Right in TeX. We don't need two since we track boundaries separately. kMTMathAtomBoundary = 101, + + // Atoms after this are non-math TeX nodes that are still useful in math mode. They do not have + // the usual structure. + + /// Spacing between math atoms. This denotes both glue and kern for TeX. We do not + /// distinguish between glue and kern. + kMTMathAtomSpace = 201, }; /** A `MTMathAtom` is the basic unit of a math list. Each atom represents a single character @@ -222,6 +230,22 @@ typedef NS_ENUM(NSUInteger, MTMathAtomType) @end +/** An atom representing space. + @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. */ +@interface MTMathSpace : MTMathAtom + +/** Creates a new `MTMathSpace` with the given spacing. + @param space The amount of space in mu units. + */ +- (instancetype) initWithSpace:(CGFloat) space NS_DESIGNATED_INITIALIZER; + +/** The amount of space represented by this object in mu units. */ +@property (nonatomic, readonly) CGFloat space; + +@end + /** A representation of a list of math objects. This list can be constructed directly or built with diff --git a/iosMath/lib/MTMathList.m b/iosMath/lib/MTMathList.m index f8a9dce..9f1286b 100644 --- a/iosMath/lib/MTMathList.m +++ b/iosMath/lib/MTMathList.m @@ -62,6 +62,8 @@ static BOOL isNotBinaryOperator(MTMathAtom* prevNode) return @"Accent"; case kMTMathAtomBoundary: return @"Boundary"; + case kMTMathAtomSpace: + return @"Space"; } } @@ -105,6 +107,12 @@ + (instancetype)atomWithType:(MTMathAtomType)type value:(NSString *)value case kMTMathAtomUnderline: return [[MTUnderLine alloc] init]; + case kMTMathAtomAccent: + return [[MTAccent alloc] initWithValue:value]; + + case kMTMathAtomSpace: + return [[MTMathSpace alloc] initWithSpace:0]; + default: return [[MTMathAtom alloc] initWithType:type value:value]; } @@ -512,13 +520,45 @@ - (instancetype)initWithType:(MTMathAtomType)type value:(NSString *)value - (id)copyWithZone:(NSZone *)zone { - MTUnderLine* op = [super copyWithZone:zone]; + MTAccent* op = [super copyWithZone:zone]; op.innerList = [self.innerList copyWithZone:zone]; return op; } @end +#pragma mark - MTMathSpace + +@implementation MTMathSpace + +- (instancetype)initWithSpace:(CGFloat)space +{ + self = [super initWithType:kMTMathAtomSpace value:@""]; + if (self) { + _space = space; + } + return self; +} + +- (instancetype)initWithType:(MTMathAtomType)type value:(NSString *)value +{ + if (type == kMTMathAtomSpace) { + return [self initWithSpace:0]; + } + @throw [NSException exceptionWithName:@"InvalidMethod" + reason:@"[MTMathSpace initWithType:value:] cannot be called. Use [MTMathSpace initWithSpace:] instead." + userInfo:nil]; +} + +- (id)copyWithZone:(NSZone *)zone +{ + MTMathSpace* op = [super copyWithZone:zone]; + op->_space = self.space; + return op; +} + +@end + #pragma mark - MTMathList @implementation MTMathList { diff --git a/iosMath/render/internal/MTTypesetter.m b/iosMath/render/internal/MTTypesetter.m index f7664d2..0953e26 100644 --- a/iosMath/render/internal/MTTypesetter.m +++ b/iosMath/render/internal/MTTypesetter.m @@ -285,6 +285,7 @@ - (void) createDisplayAtoms:(NSArray*) preprocessed NSAssert(NO, @"These types should never show here as they are removed by preprocessing."); break; + case kMTMathAtomSpace: case kMTMathAtomAccent: NSAssert(NO, @"These math atom types are not yet implemented."); break; diff --git a/iosMathTests/MTMathListTest.m b/iosMathTests/MTMathListTest.m index b987b49..e9a2503 100644 --- a/iosMathTests/MTMathListTest.m +++ b/iosMathTests/MTMathListTest.m @@ -507,7 +507,7 @@ - (void) testCopyUnderline XCTAssertEqual(under.type, kMTMathAtomUnderline); under.innerList = list; - MTOverLine* copy = [under copy]; + MTUnderLine* copy = [under copy]; [MTMathListTest checkAtomCopy:copy original:under forTest:self]; [MTMathListTest checkListCopy:copy.innerList original:under.innerList forTest:self]; } @@ -526,8 +526,18 @@ - (void) testCopyAcccent XCTAssertEqual(accent.type, kMTMathAtomAccent); accent.innerList = list; - MTOverLine* copy = [accent copy]; + MTAccent* copy = [accent copy]; [MTMathListTest checkAtomCopy:copy original:accent forTest:self]; [MTMathListTest checkListCopy:copy.innerList original:accent.innerList forTest:self]; } + +- (void) testCopySpace +{ + MTMathSpace* space = [[MTMathSpace alloc] initWithSpace:3]; + XCTAssertEqual(space.type, kMTMathAtomSpace); + + MTMathSpace* copy = [space copy]; + [MTMathListTest checkAtomCopy:copy original:space forTest:self]; + XCTAssertEqual(space.space, copy.space); +} @end