Skip to content

Commit

Permalink
Construct arbitrarily tall glyphs.
Browse files Browse the repository at this point in the history
Fix the descent for glyphs in large operators. This fixes placement of limits
for the XITS font.

Fixes tophatmonocle#9.
  • Loading branch information
kostub committed Oct 17, 2016
1 parent d890065 commit 1dee822
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 59 deletions.
85 changes: 79 additions & 6 deletions iosMath/render/MTMathListDisplay.m
Original file line number Diff line number Diff line change
Expand Up @@ -440,14 +440,16 @@ @implementation MTGlyphDisplay {
MTFont* _font;
}

- (instancetype)initWithGlpyh:(CGGlyph) glyph position:(CGPoint) position range:(NSRange) range font:(MTFont*) font
@synthesize shiftDown;

- (instancetype)initWithGlpyh:(CGGlyph) glyph range:(NSRange) range font:(MTFont*) font
{
self = [super init];
if (self) {
_font = font;
_glyph = glyph;

self.position = position;
self.position = CGPointZero;
self.range = range;
}
return self;
Expand All @@ -460,16 +462,87 @@ - (void)draw:(CGContextRef)context
[self.textColor setFill];

// Make the current position the origin as all the positions of the sub atoms are relative to the origin.
CGContextTranslateCTM(context, self.position.x, self.position.y);
CGContextTranslateCTM(context, self.position.x, self.position.y - self.shiftDown);
CGContextSetTextPosition(context, 0, 0);

// Draw the glyph.
CGPoint glyphPosition = CGPointMake(0, -self.shiftDown);
CTFontDrawGlyphs(_font.ctFont, &_glyph, &glyphPosition, 1, context);
CTFontDrawGlyphs(_font.ctFont, &_glyph, &CGPointZero, 1, context);

CGContextRestoreGState(context);
}

- (CGFloat)ascent
{
return super.ascent - self.shiftDown;
}

- (CGFloat)descent
{
return super.descent + self.shiftDown;
}

@end

#pragma mark - MTGlyphConstructionDisplay

@implementation MTGlyphConstructionDisplay {
CGGlyph *_glyphs;
CGPoint *_positions;
MTFont* _font;
int _numGlyphs;
}

@synthesize shiftDown;

- (instancetype)initWithGlyphs:(NSArray<NSNumber *> *)glyphs offsets:(NSArray<NSNumber *> *)offsets font:(MTFont *)font
{
self = [super init];
if (self) {
NSAssert(glyphs.count == offsets.count, @"Glyphs and offsets need to match");
_numGlyphs = glyphs.count;
_glyphs = malloc(sizeof(CGGlyph) * _numGlyphs);
_positions = malloc(sizeof(CGPoint) * _numGlyphs);
for (int i = 0; i < _numGlyphs; i++) {
_glyphs[i] = glyphs[i].shortValue;
_positions[i] = CGPointMake(0, offsets[i].floatValue);
}
_font = font;
self.position = CGPointZero;
}
return self;
}

- (void)draw:(CGContextRef)context
{
CGContextSaveGState(context);

[self.textColor setFill];

// Make the current position the origin as all the positions of the sub atoms are relative to the origin.
CGContextTranslateCTM(context, self.position.x, self.position.y - self.shiftDown);
CGContextSetTextPosition(context, 0, 0);

// Draw the glyphs.
CTFontDrawGlyphs(_font.ctFont, _glyphs, _positions, _numGlyphs, context);

CGContextRestoreGState(context);
}

- (CGFloat)ascent
{
return super.ascent - self.shiftDown;
}

- (CGFloat)descent
{
return super.descent + self.shiftDown;
}

- (void)dealloc
{
free(_glyphs);
free(_positions);
}

@end

#pragma mark - MTLargeOpLimitsDisplay
Expand Down
30 changes: 30 additions & 0 deletions iosMath/render/internal/MTFontMathTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@

@class MTFont;

/** MTGlyphPart represents a part of a glyph used for assembling a large vertical or horizontal
glyph. */
@interface MTGlyphPart : NSObject

/// The glyph that represents this part
@property (nonatomic, readonly) CGGlyph glyph;

/// Full advance width/height for this part, in the direction of the extension in points.
@property (nonatomic, readonly) CGFloat fullAdvance;

/// Advance width/ height of the straight bar connector material at the beginning of the glyph in points.
@property (nonatomic, readonly) CGFloat startConnectorLength;

/// Advance width/ height of the straight bar connector material at the end of the glyph in points.
@property (nonatomic, readonly) CGFloat endConnectorLength;

/// If this part is an extender. If set, the part can be skipped or repeated.
@property (nonatomic, readonly) BOOL isExtender;

@end

/** This class represents the Math table of an open type font.
The math table is documented here: https://www.microsoft.com/typography/otspec/math.htm
Expand Down Expand Up @@ -135,4 +156,13 @@
If there isn't any this returns -1. */
- (CGFloat) getTopAccentAdjustment:(CGGlyph) glyph;

#pragma mark Glyph Construction

/** Minimum overlap of connecting glyphs during glyph construction */
@property (nonatomic, readonly) CGFloat minConnectorOverlap;

/** 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. */
- (nullable NSArray<MTGlyphPart*>*) getVerticalGlyphAssemblyForGlyph:(CGGlyph) glyph;

@end
58 changes: 58 additions & 0 deletions iosMath/render/internal/MTFontMathTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@
#import "MTFont.h"
#import "MTFont+Internal.h"


@interface MTGlyphPart ()

@property (nonatomic) CGGlyph glyph;
@property (nonatomic) CGFloat fullAdvance;
@property (nonatomic) CGFloat startConnectorLength;
@property (nonatomic) CGFloat endConnectorLength;
@property (nonatomic) BOOL isExtender;

@end

@implementation MTGlyphPart

@end

@interface MTFontMathTable ()

// The font for this math table.
Expand Down Expand Up @@ -476,4 +491,47 @@ - (CGFloat) getTopAccentAdjustment:(CGGlyph) glyph
}
}

#pragma mark - Glyph Assembly

- (CGFloat)minConnectorOverlap
{
return [self constantFromTable:@"MinConnectorOverlap"];
}

static NSString* const kVertAssembly = @"v_assembly";
static NSString* const kAssemblyParts = @"parts";

- (NSArray<MTGlyphPart *> *)getVerticalGlyphAssemblyForGlyph:(CGGlyph)glyph
{
NSDictionary* assemblyTable = (NSDictionary*) _mathTable[kVertAssembly];
NSString* glyphName = [self.font getGlyphName:glyph];
NSDictionary* assemblyInfo = (NSDictionary*) assemblyTable[glyphName];
if (!assemblyInfo) {
// No vertical assembly defined for glyph
return nil;
}
NSArray* parts = (NSArray*) assemblyInfo[kAssemblyParts];
if (!parts) {
// parts should always have been defined, but if it isn't return nil
return nil;
}
NSMutableArray<MTGlyphPart*>* rv = [NSMutableArray array];
for (NSDictionary* partInfo in parts) {
MTGlyphPart* part = [[MTGlyphPart alloc] init];
NSNumber* adv = (NSNumber*) partInfo[@"advance"];
part.fullAdvance = [self fontUnitsToPt:adv.intValue];
NSNumber* end = (NSNumber*) partInfo[@"endConnector"];
part.endConnectorLength = [self fontUnitsToPt:end.intValue];
NSNumber* start = (NSNumber*) partInfo[@"startConnector"];
part.startConnectorLength = [self fontUnitsToPt:start.intValue];
NSNumber* ext = (NSNumber*) partInfo[@"extender"];
part.isExtender = ext.boolValue;
NSString* glyphName = (NSString*) partInfo[@"glyph"];
part.glyph = [self.font getGlyphWithName:glyphName];

[rv addObject:part];
}
return rv;
}

@end
20 changes: 16 additions & 4 deletions iosMath/render/internal/MTMathListDisplayInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@

@end

// The Downshift protocol allows an MTDisplay to be shifted down by a given amount.
@protocol DownShift <NSObject>

@property (nonatomic) CGFloat shiftDown;

@end

@interface MTMathListDisplay ()

- (instancetype)init NS_UNAVAILABLE;
Expand Down Expand Up @@ -64,12 +71,17 @@
@end

// Rendering of an large glyph as an MTDisplay
@interface MTGlyphDisplay()
@interface MTGlyphDisplay() <DownShift>

- (instancetype)initWithGlpyh:(CGGlyph) glyph position:(CGPoint) position range:(NSRange) range font:(MTFont*) font NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithGlpyh:(CGGlyph) glyph range:(NSRange) range font:(MTFont*) font NS_DESIGNATED_INITIALIZER;

// Shift the glyph down by the given amount.
@property (nonatomic) CGFloat shiftDown;
@end

// Rendering of a constructed glyph as an MTDisplay
@interface MTGlyphConstructionDisplay : MTDisplay<DownShift>

- (instancetype) init NS_UNAVAILABLE;
- (instancetype) initWithGlyphs:(NSArray<NSNumber*>*) glyphs offsets:(NSArray<NSNumber*>*) offsets font:(MTFont*) font NS_DESIGNATED_INITIALIZER;

@end

Expand Down
Loading

0 comments on commit 1dee822

Please sign in to comment.