Skip to content

Commit

Permalink
Feature: Color (#54)
Browse files Browse the repository at this point in the history
* add color-command

* add color-feature to the readme; add example

* bugfix redraw

* restructure for the color-command

* bugfix failed travis build: UIColor->MTColor
  • Loading branch information
Markus Sähn authored and kostub committed Apr 13, 2017
1 parent fd76ff2 commit 563551f
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 5 deletions.
6 changes: 3 additions & 3 deletions Podfile.lock
@@ -1,5 +1,5 @@
PODS:
- iosMath (0.9.2)
- iosMath (0.9.3)

DEPENDENCIES:
- iosMath (from `./`)
Expand All @@ -9,8 +9,8 @@ EXTERNAL SOURCES:
:path: ./

SPEC CHECKSUMS:
iosMath: 0f978bf5528620d3fc585c33ff969839cfe611c1
iosMath: 619e53c34dfa19ac3062869f9974747b44507083

PODFILE CHECKSUM: bade56080a0531a08830155fc215a0a5b44dd183

COCOAPODS: 1.1.1
COCOAPODS: 1.2.0
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -109,6 +109,7 @@ This is a list of formula types that the library currently supports:
* Equation alignment
* Change bold, roman, caligraphic and other font styles (\\bf, \\text, etc.)
* Most commonly used math symbols
* Colors

### Example

Expand Down
18 changes: 18 additions & 0 deletions iosMath/lib/MTMathList.h
Expand Up @@ -72,6 +72,7 @@ typedef NS_ENUM(NSUInteger, MTMathAtomType)
kMTMathAtomSpace = 201,
/// Denotes style changes during rendering.
kMTMathAtomStyle,
kMTMathAtomColor,

// Atoms after this point are not part of TeX and do not have the usual structure.

Expand Down Expand Up @@ -322,6 +323,23 @@ typedef NS_ENUM(unsigned int, MTLineStyle) {

@end

/** An atom representing an color element.
@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 MTMathColor : MTMathAtom

/// Creates an empty color with a nil environment
- (instancetype) init NS_DESIGNATED_INITIALIZER;

/** The style represented by this object. */
@property (nonatomic, nullable) NSString* colorString;

/// The inner math list
@property (nonatomic, nullable) MTMathList* innerList;

@end

/** An atom representing an table element. This atom is not like other
atoms and is not present in TeX. We use it to represent the `\halign` command
in TeX with some simplifications. This is used for matrices, equation
Expand Down
50 changes: 50 additions & 0 deletions iosMath/lib/MTMathList.m
Expand Up @@ -66,6 +66,8 @@ static BOOL isNotBinaryOperator(MTMathAtom* prevNode)
return @"Space";
case kMTMathAtomStyle:
return @"Style";
case kMTMathAtomColor:
return @"Color";
case kMTMathAtomTable:
return @"Table";
}
Expand Down Expand Up @@ -116,6 +118,9 @@ + (instancetype)atomWithType:(MTMathAtomType)type value:(NSString *)value

case kMTMathAtomSpace:
return [[MTMathSpace alloc] initWithSpace:0];

case kMTMathAtomColor:
return [[MTMathColor alloc] init];

default:
return [[MTMathAtom alloc] initWithType:type value:value];
Expand Down Expand Up @@ -652,6 +657,51 @@ - (id)copyWithZone:(NSZone *)zone

@end

#pragma mark - MTMathColor

@implementation MTMathColor


- (instancetype)init
{
self = [super initWithType:kMTMathAtomColor value:@""];
return self;
}

- (instancetype)initWithType:(MTMathAtomType)type value:(NSString *)value
{
if (type == kMTMathAtomColor) {
return [self init];
}
@throw [NSException exceptionWithName:@"InvalidMethod"
reason:@"[MTMathColor initWithType:value:] cannot be called. Use [MTMathColor init] instead."
userInfo:nil];
}

- (NSString *)stringValue
{
NSMutableString* str = [NSMutableString stringWithString:@"\\color"];
[str appendFormat:@"{%@}{%@}", self.colorString, self.innerList.stringValue];
return str;
}

- (id)copyWithZone:(NSZone *)zone
{
MTMathColor* op = [super copyWithZone:zone];
op.innerList = [self.innerList copyWithZone:zone];
op->_colorString = self.colorString;
return op;
}

- (instancetype)finalized
{
MTMathColor *newInner = [super finalized];
newInner.innerList = newInner.innerList.finalized;
return newInner;
}

@end

#pragma mark - MTMathTable

@interface MTMathTable ()
Expand Down
38 changes: 38 additions & 0 deletions iosMath/lib/MTMathListBuilder.m
Expand Up @@ -271,6 +271,38 @@ - (NSString*) readString
return mutable;
}

- (NSString*) readColor
{
if (![self expectCharacter:'{']) {
// We didn't find an opening brace, so no env found.
[self setError:MTParseErrorCharacterNotFound message:@"Missing {"];
return nil;
}

// Ignore spaces and nonascii.
[self skipSpaces];

// a string of all upper and lower case characters.
NSMutableString* mutable = [NSMutableString string];
while([self hasCharacters]) {
unichar ch = [self getNextCharacter];
if (ch == '#' || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || (ch >= '0' && ch <= '9')) {
[mutable appendString:[NSString stringWithCharacters:&ch length:1]];
} else {
// we went too far
[self unlookCharacter];
break;
}
}

if (![self expectCharacter:'}']) {
// We didn't find an closing brace, so invalid format.
[self setError:MTParseErrorCharacterNotFound message:@"Missing }"];
return nil;
}
return mutable;
}

- (void) skipSpaces
{
while ([self hasCharacters]) {
Expand Down Expand Up @@ -462,6 +494,12 @@ - (MTMathAtom*) atomForCommand:(NSString*) command
}
MTMathAtom* table = [self buildTable:env firstList:nil row:NO];
return table;
} else if ([command isEqualToString:@"color"]) {
// A color command has 2 arguments
MTMathColor* mathColor = [[MTMathColor alloc] init];
mathColor.colorString = [self readColor];
mathColor.innerList = [self buildInternal:true];
return mathColor;
} else {
NSString* errorMessage = [NSString stringWithFormat:@"Invalid command \\%@", command];
[self setError:MTParseErrorInvalidCommand message:errorMessage];
Expand Down
2 changes: 2 additions & 0 deletions iosMath/render/MTConfig.h
Expand Up @@ -16,6 +16,7 @@
// TARGET_OS_MAC is defined as 1 for both Mac OS and iOS,
// so TARGET_OS_IPHONE is reliable.
@import UIKit;
#import "UIColor+HexString.h"

typedef UIView MTView;
typedef UIColor MTColor;
Expand All @@ -31,6 +32,7 @@ typedef CGRect MTRect;
@import AppKit;
#import "NSBezierPath+addLineToPoint.h"
#import "NSView+backgroundColor.h"
#import "NSColor+HexString.h"
#import "MTLabel.h"

typedef NSView MTView;
Expand Down
3 changes: 3 additions & 0 deletions iosMath/render/MTMathListDisplay.h
Expand Up @@ -49,6 +49,9 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) BOOL hasScript;
/// The text color for this display
@property (nonatomic, nullable) MTColor *textColor;
// The local color, if the color was mutated local with the color
// command
@property (nonatomic, nullable) MTColor *localTextColor;

@end

Expand Down
8 changes: 7 additions & 1 deletion iosMath/render/MTMathListDisplay.m
Expand Up @@ -200,7 +200,13 @@ - (void)setTextColor:(MTColor *)textColor
// Set the color on all subdisplays
[super setTextColor:textColor];
for (MTDisplay* displayAtom in self.subDisplays) {
displayAtom.textColor = textColor;
// set the global color, if there is no local color
if(displayAtom.localTextColor == nil) {
displayAtom.textColor = textColor;
} else {
displayAtom.textColor = displayAtom.localTextColor;
}

}
}

Expand Down
19 changes: 19 additions & 0 deletions iosMath/render/NSColor+HexString.h
@@ -0,0 +1,19 @@
//
// NSColor+HexString.h
// iosMath
//
// Created by Markus Sähn on 21/03/2017.
//
//

#include <TargetConditionals.h>

#if !TARGET_OS_IPHONE
#import <Cocoa/Cocoa.h>

@interface NSColor (HexString)

+ (NSColor *)colorFromHexString:(NSString *)hexString;

@end
#endif
35 changes: 35 additions & 0 deletions iosMath/render/NSColor+HexString.m
@@ -0,0 +1,35 @@
//
// NSColor+HexString.m
// iosMath
//
// Created by Markus Sähn on 21/03/2017.
//
//

#import "NSColor+HexString.h"

#if !TARGET_OS_IPHONE
@implementation NSColor (HexString)

+ (NSColor *)colorFromHexString:(NSString *)hexString {
if ([hexString isEqualToString:@""]) {
return nil;
}

if ([hexString characterAtIndex:0] != '#') {
return nil;
}

unsigned rgbValue = 0;

NSScanner *scanner = [NSScanner scannerWithString:hexString];
if ([hexString characterAtIndex:0] == '#') {
[scanner setScanLocation:1];
}

[scanner scanHexInt:&rgbValue];
return [NSColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
}

@end
#endif
16 changes: 16 additions & 0 deletions iosMath/render/UIColor+HexString.h
@@ -0,0 +1,16 @@
//
// UIColor+HexString.h
// iosMath
//
// Created by Markus Sähn on 21/03/2017.
//
//

#if TARGET_OS_IPHONE

@interface UIColor (HexString)

+ (UIColor *)colorFromHexString:(NSString *)hexString;

@end
#endif
36 changes: 36 additions & 0 deletions iosMath/render/UIColor+HexString.m
@@ -0,0 +1,36 @@
//
// UIColor+HexString.m
// iosMath
//
// Created by Markus Sähn on 21/03/2017.
//
//

#import "UIColor+HexString.h"

#if TARGET_OS_IPHONE

@implementation UIColor (HexString)

+ (UIColor *)colorFromHexString:(NSString *)hexString {
if ([hexString isEqualToString:@""]) {
return nil;
}

if ([hexString characterAtIndex:0] != '#') {
return nil;
}

unsigned rgbValue = 0;

NSScanner *scanner = [NSScanner scannerWithString:hexString];
if ([hexString characterAtIndex:0] == '#') {
[scanner setScanLocation:1];
}

[scanner scanHexInt:&rgbValue];
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
}

@end
#endif
15 changes: 15 additions & 0 deletions iosMath/render/internal/MTTypesetter.m
Expand Up @@ -47,6 +47,7 @@ typedef NS_ENUM(int, MTInterElementSpaceType) {
// Get's the index for the given type. If row is true, the index is for the row (i.e. left element) otherwise it is for the column (right element)
NSUInteger getInterElementSpaceArrayIndexForType(MTMathAtomType type, BOOL row) {
switch (type) {
case kMTMathAtomColor:
case kMTMathAtomOrdinary:
case kMTMathAtomPlaceholder: // A placeholder is treated as ordinary
return 0;
Expand Down Expand Up @@ -614,6 +615,20 @@ - (void) createDisplayAtoms:(NSArray*) preprocessed
continue;
}

case kMTMathAtomColor: {
// stash the existing layout
if (_currentLine.length > 0) {
[self addDisplayLine];
}
MTMathColor* colorAtom = (MTMathColor*) atom;
MTDisplay* display = [MTTypesetter createLineForMathList:colorAtom.innerList font:_font style:_style];
display.localTextColor = [MTColor colorFromHexString:colorAtom.colorString];
display.position = _currentPosition;
_currentPosition.x += display.width;
[_displayAtoms addObject:display];
break;
}

case kMTMathAtomRadical: {
// stash the existing layout
if (_currentLine.length > 0) {
Expand Down
4 changes: 3 additions & 1 deletion iosMathExample/example/ViewController.m
Expand Up @@ -99,7 +99,7 @@ - (void)viewDidLoad
views:views]];


self.demoLabels[1] = [self createMathLabel:@"(a_1+a_2)^2=a_1^2+2a_1a_2+a_2^2" withHeight:40];
self.demoLabels[1] = [self createMathLabel:@"\\color{#ff3399}{(a_1+a_2)^2}=a_1^2+2a_1a_2+a_2^2" withHeight:40];

self.demoLabels[2] = [self createMathLabel:@"\\cos(\\theta + \\varphi) = \
\\cos(\\theta)\\cos(\\varphi) - \\sin(\\theta)\\sin(\\varphi)"
Expand Down Expand Up @@ -175,6 +175,8 @@ - (void)viewDidLoad
"\\frac{e^x}{2} & x \\geq 0 \\\\"
"1 & x < 0"
"\\end{cases}" withHeight:60];

self.demoLabels[21] = [self createMathLabel:@"\\color{#ff3333}{c}\\color{#9933ff}{o}\\color{#ff0080}{l}+\\color{#99ff33}{\\frac{\\color{#ff99ff}{o}}{\\color{#990099}{r}}}-\\color{#33ffff}{\\sqrt[\\color{#3399ff}{e}]{\\color{#3333ff}{d}}}" withHeight:60];


for (NSUInteger i = 1; i < self.demoLabels.count; i++) {
Expand Down

0 comments on commit 563551f

Please sign in to comment.