commitffb55b0f31Author: Curtis Hard <curtishard@me.com> Date: Fri Mar 2 13:28:40 2018 +0000 Fixes viewBox origin translate commita4c032afa2Author: Curtis Hard <curtishard@me.com> Date: Wed Feb 28 21:29:11 2018 +0000 Added clip to viewport commitabe8f4cba5Author: Curtis Hard <curtishard@me.com> Date: Wed Feb 28 21:00:20 2018 +0000 Fixes drawInRect not obeying origin commita16842271bAuthor: Curtis Hard <curtishard@me.com> Date: Mon Feb 26 13:46:41 2018 +0000 Resolves namespaces correctly + added common HTML list to be parsed as groups commit58126e06e4Author: Curtis Hard <curtishard@me.com> Date: Sun Feb 25 21:58:49 2018 +0000 Fixes! commit5af5e054abAuthor: Curtis Hard <curtishard@me.com> Date: Fri Feb 23 22:37:53 2018 +0000 Fixed defNode being removed commitedd3aa1f33Author: Curtis Hard <curtishard@me.com> Date: Fri Feb 23 16:29:54 2018 +0000 excluded various elements from diff commit3366bc4fa5Author: Curtis Hard <curtishard@me.com> Date: Fri Feb 23 14:05:03 2018 +0000 Better optimaztion commit104002183bAuthor: Curtis Hard <curtishard@me.com> Date: Thu Feb 22 22:17:50 2018 +0000 Added rudimenatry inline styles -> stylesheet commit7010b7ea50Author: Curtis Hard <curtishard@me.com> Date: Thu Feb 22 13:33:32 2018 +0000 Correct order of cleanup commit5266a8c07aAuthor: Curtis Hard <curtishard@me.com> Date: Thu Feb 22 08:22:17 2018 +0000 corrent length of string commitcaf55e8bdfAuthor: Curtis Hard <curtishard@me.com> Date: Wed Feb 21 20:45:17 2018 +0000 removes useless def if required commit8160d05ebaAuthor: Curtis Hard <curtishard@me.com> Date: Tue Feb 20 14:12:02 2018 +0000 Refactor of a few methods commita6d6a06521Author: Curtis Hard <curtishard@me.com> Date: Tue Feb 20 09:40:21 2018 +0000 Added collpasing of gradients commit103a4d71f6Author: Curtis Hard <curtishard@me.com> Date: Mon Feb 19 19:07:30 2018 +0000 Reduced floats even more commit98874b1d2cAuthor: Curtis Hard <curtishard@me.com> Date: Mon Feb 19 18:53:02 2018 +0000 More compression goodness commite742db31e0Author: Curtis Hard <curtishard@me.com> Date: Mon Feb 19 14:02:15 2018 +0000 Added intermediateParent commit198fd09f07Author: Curtis Hard <curtishard@me.com> Date: Mon Feb 19 11:51:37 2018 +0000 Fixes! and performance increases commit3493194b1bAuthor: Curtis Hard <curtishard@me.com> Date: Mon Feb 19 08:20:02 2018 +0000 Scale computation commit0016775eafAuthor: Curtis Hard <curtishard@me.com> Date: Sun Feb 18 22:33:26 2018 +0000 More goodness commit304a04cc22Author: Curtis Hard <curtishard@me.com> Date: Sun Feb 18 22:32:04 2018 +0000 Vastly improved the exporter commite4fd0af582Author: Curtis Hard <curtishard@me.com> Date: Sun Feb 18 15:20:28 2018 +0000 This is insanely important! commit69a2a0c97eAuthor: Curtis Hard <curtishard@me.com> Date: Sun Feb 4 22:02:19 2018 +0000 Refactor commit5299bb0479Author: Curtis Hard <curtishard@me.com> Date: Sun Feb 4 21:58:21 2018 +0000 will continue to use CoreAnimation for the time being commit4f1943cad1Author: Curtis Hard <curtishard@me.com> Date: Sun Feb 4 21:57:46 2018 +0000 Fixes gradient strokes commitf02d186293Author: Curtis Hard <curtishard@me.com> Date: Sun Feb 4 11:15:04 2018 +0000 trying to get masks to work commit3291718cfbAuthor: Curtis Hard <curtishard@me.com> Date: Fri Feb 2 22:35:22 2018 +0000 Beginning of quartz renderer commit6fbaaf5884Author: Curtis Hard <curtishard@me.com> Date: Mon Jan 29 22:32:08 2018 +0000 Removed useless log commitabc65797eaAuthor: Curtis Hard <curtishard@me.com> Date: Mon Jan 29 21:37:45 2018 +0000 I think gradients work :D commitaf5a1c2718Author: Curtis Hard <curtishard@me.com> Date: Sun Jan 28 22:18:02 2018 +0000 Possible fx and fy things… commitfb9a5282b9Author: Curtis Hard <curtishard@me.com> Date: Sun Jan 28 19:22:40 2018 +0000 Even more gradient fixes commitd83933a103Author: Curtis Hard <curtishard@me.com> Date: Sun Jan 28 14:21:50 2018 +0000 Various improvements commitbd7a0d5021Author: Curtis Hard <curtishard@me.com> Date: Sat Jan 27 22:26:33 2018 +0000 Start to linear commita9a038568cAuthor: Curtis Hard <curtishard@me.com> Date: Sat Jan 27 21:14:25 2018 +0000 This kind of actually works... commit77fbb38b6fAuthor: Curtis Hard <curtishard@me.com> Date: Sat Jan 27 20:31:36 2018 +0000 I guess this could be a good start? Posssible start of fixes? commit12c3191569Author: Curtis Hard <curtishard@me.com> Date: Sat Jan 27 15:32:15 2018 +0000 Added method for findind absolute position commite3e9626ef7Author: Curtis Hard <curtishard@me.com> Date: Sat Jan 27 14:25:03 2018 +0000 Fixes crash due to parentNode on temp groups being released commit1160d89f16Author: Curtis Hard <curtishard@me.com> Date: Fri Jan 26 22:29:22 2018 +0000 Fixes use statements with transforms commit1575cbfde8Author: Curtis Hard <curtishard@me.com> Date: Fri Jan 26 18:16:03 2018 +0000 Moved color tree over to modern syntax commit5c4c2eee91Author: Curtis Hard <curtishard@me.com> Date: Thu Jan 25 18:23:53 2018 +0000 Added HSL/HSLA support commit087b13e58fAuthor: Curtis Hard <curtishard@me.com> Date: Wed Jan 24 22:24:43 2018 +0000 Various image loading issues resolved from base64 images commit1183e167aaAuthor: Curtis Hard <curtishard@me.com> Date: Wed Jan 24 21:21:41 2018 +0000 Rect issue fix commit4dbfc59437Author: Curtis Hard <curtishard@me.com> Date: Wed Jan 24 21:19:24 2018 +0000 Moved transforms over from being concatinated to seperate calls commit409bd509faAuthor: Curtis Hard <curtishard@me.com> Date: Wed Jan 24 20:30:38 2018 +0000 Fixes color issue commit8ae1d1b4e0Author: Curtis Hard <curtishard@me.com> Date: Wed Jan 24 18:41:08 2018 +0000 Removed check as its not needed here commit7243fbe5ffAuthor: Curtis Hard <curtishard@me.com> Date: Wed Jan 24 18:35:43 2018 +0000 Added excludeAttributes list to parseCommonAttributes added x and y to that list for rect commit51b9a5e85fAuthor: Curtis Hard <curtishard@me.com> Date: Tue Jan 23 19:53:04 2018 +0000 Added isSubcommand to IJSVGCommand - Fixes move command going awol when preceding move commands are not subcommands (woah) commit40098589deAuthor: Curtis Hard <curtishard@me.com> Date: Mon Jan 22 22:04:48 2018 +0000 removed reverseObjectEnumerator IJSVGTransform already deals with this at parse stage (was a test from earlier), spec states transforms are applied in reverse order (which parser already dealth with :-)) commit7cb96b21f2Author: Curtis Hard <curtishard@me.com> Date: Mon Jan 22 22:01:56 2018 +0000 Removed use of origin here as its computed in apply defaults commit1bff7c6970Author: Curtis Hard <curtishard@me.com> Date: Mon Jan 22 21:48:07 2018 +0000 Various fixes… still going…
610 lines
18 KiB
Objective-C
610 lines
18 KiB
Objective-C
//
|
|
// IJSVGUtils.m
|
|
// IconJar
|
|
//
|
|
// Created by Curtis Hard on 30/08/2014.
|
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
|
//
|
|
|
|
#import "IJSVGUtils.h"
|
|
#import "IJSVGLayer.h"
|
|
#import "IJSVGShapeLayer.h"
|
|
|
|
@implementation IJSVGUtils
|
|
|
|
BOOL IJSVGIsCommonHTMLElementName(NSString * str)
|
|
{
|
|
str = str.lowercaseString;
|
|
return [IJSVGCommonHTMLElementNames() containsObject:str];
|
|
};
|
|
|
|
NSArray * IJSVGCommonHTMLElementNames()
|
|
{
|
|
static NSArray * names = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
names = [@[@"a",
|
|
@"abbr",
|
|
@"acronym",
|
|
@"abbr",
|
|
@"address",
|
|
@"applet",
|
|
@"embed",
|
|
@"object",
|
|
@"area",
|
|
@"article",
|
|
@"aside",
|
|
@"audio",
|
|
@"b",
|
|
@"base",
|
|
@"basefont",
|
|
@"bdi",
|
|
@"bdo",
|
|
@"big",
|
|
@"blockquote",
|
|
@"body",
|
|
@"br",
|
|
@"button",
|
|
@"canvas",
|
|
@"caption",
|
|
@"center",
|
|
@"cite",
|
|
@"code",
|
|
@"col",
|
|
@"colgroup",
|
|
@"colgroup",
|
|
@"datalist",
|
|
@"dd",
|
|
@"del",
|
|
@"details",
|
|
@"dfn",
|
|
@"dialog",
|
|
@"dir",
|
|
@"ul",
|
|
@"div",
|
|
@"dl",
|
|
@"dt",
|
|
@"em",
|
|
@"embed",
|
|
@"fieldset",
|
|
@"figcaption",
|
|
@"figure",
|
|
@"figure",
|
|
@"font",
|
|
@"footer",
|
|
@"form",
|
|
@"frame",
|
|
@"frameset",
|
|
@"h1",
|
|
@"h6",
|
|
@"head",
|
|
@"header",
|
|
@"hr",
|
|
@"html",
|
|
@"i",
|
|
@"iframe",
|
|
@"img",
|
|
@"input",
|
|
@"ins",
|
|
@"kbd",
|
|
@"label",
|
|
@"input",
|
|
@"legend",
|
|
@"fieldset",
|
|
@"li",
|
|
@"link",
|
|
@"main",
|
|
@"map",
|
|
@"mark",
|
|
@"menu",
|
|
@"menuitem",
|
|
@"meta",
|
|
@"meter",
|
|
@"nav",
|
|
@"noframes",
|
|
@"noscript",
|
|
@"object",
|
|
@"ol",
|
|
@"optgroup",
|
|
@"option",
|
|
@"output",
|
|
@"p",
|
|
@"param",
|
|
@"picture",
|
|
@"pre",
|
|
@"progress",
|
|
@"q",
|
|
@"rp",
|
|
@"rt",
|
|
@"ruby",
|
|
@"s",
|
|
@"samp",
|
|
@"script",
|
|
@"section",
|
|
@"select",
|
|
@"small",
|
|
@"source",
|
|
@"video",
|
|
@"audio",
|
|
@"span",
|
|
@"strike",
|
|
@"del",
|
|
@"s",
|
|
@"strong",
|
|
@"style",
|
|
@"sub",
|
|
@"summary",
|
|
@"details",
|
|
@"sup",
|
|
@"table",
|
|
@"tbody",
|
|
@"td",
|
|
@"template",
|
|
@"textarea",
|
|
@"tfoot",
|
|
@"th",
|
|
@"thead",
|
|
@"time",
|
|
@"title",
|
|
@"tr",
|
|
@"track",
|
|
@"video",
|
|
@"audio",
|
|
@"tt",
|
|
@"u",
|
|
@"ul",
|
|
@"var",
|
|
@"video",
|
|
@"wbr"] retain];
|
|
});
|
|
return names;
|
|
};
|
|
|
|
NSString * IJSVGShortFloatString(CGFloat f)
|
|
{
|
|
return [NSString stringWithFormat:@"%g",f];
|
|
};
|
|
|
|
NSString * IJSVGShortFloatStringWithPrecision(CGFloat f, NSInteger precision)
|
|
{
|
|
NSString * format = [NSString stringWithFormat:@"%@.%ld%@",@"%",precision,@"f"];
|
|
NSString * ret = [NSString stringWithFormat:format,f];
|
|
// can it be reduced even more?
|
|
if(ret.floatValue == (float)ret.integerValue) {
|
|
ret = [NSString stringWithFormat:@"%ld",ret.integerValue];
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
BOOL IJSVGIsLegalCommandCharacter(unichar aChar)
|
|
{
|
|
char * validChars = "MmZzLlHhVvCcSsQqTtAa";
|
|
NSUInteger length = strlen(validChars);
|
|
for(NSUInteger i = 0; i < length; i++) {
|
|
if(aChar == validChars[i]) {
|
|
return YES;
|
|
}
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
BOOL IJSVGIsSVGLayer(CALayer * layer)
|
|
{
|
|
return [layer isKindOfClass:IJSVGLayer.class] ||
|
|
[layer isKindOfClass:IJSVGShapeLayer.class];
|
|
}
|
|
|
|
CGFloat angle( CGPoint a, CGPoint b ) {
|
|
return [IJSVGUtils angleBetweenPointA:a
|
|
pointb:b];
|
|
}
|
|
|
|
CGFloat ratio( CGPoint a, CGPoint b ) {
|
|
return (a.x * b.x + a.y * b.y) / (magnitude(a) * magnitude(b));
|
|
}
|
|
|
|
CGFloat magnitude(CGPoint point)
|
|
{
|
|
return sqrtf(powf(point.x, 2) + powf(point.y, 2));
|
|
}
|
|
|
|
CGFloat radians_to_degrees(CGFloat radians)
|
|
{
|
|
return ((radians) * (180.0 / M_PI));
|
|
}
|
|
|
|
CGFloat degrees_to_radians( CGFloat degrees )
|
|
{
|
|
return ( ( degrees ) / 180.0 * M_PI );
|
|
}
|
|
|
|
+ (IJSVGCommandType)typeForCommandString:(NSString *)string
|
|
{
|
|
return [string isEqualToString:[string uppercaseString]] ? IJSVGCommandTypeAbsolute : IJSVGCommandTypeRelative;
|
|
}
|
|
|
|
+ (NSString *)defURL:(NSString *)string
|
|
{
|
|
static NSRegularExpression * _reg = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
_reg = [[NSRegularExpression alloc] initWithPattern:@"url\\s?\\(\\s?#(.*?)\\)\\;?"
|
|
options:0
|
|
error:nil];
|
|
});
|
|
__block NSString * foundID = nil;
|
|
[_reg enumerateMatchesInString:string
|
|
options:0
|
|
range:NSMakeRange( 0, string.length )
|
|
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
|
|
{
|
|
if( ( foundID = [string substringWithRange:[result rangeAtIndex:1]] ) != nil )
|
|
*stop = YES;
|
|
}];
|
|
return foundID;
|
|
}
|
|
|
|
+ (IJSVGFontTraits)fontWeightTraitForString:(NSString *)string
|
|
weight:(CGFloat *)weight
|
|
{
|
|
*weight = string.floatValue;
|
|
if([string isEqualToString:@"bold"])
|
|
return IJSVGFontTraitBold;
|
|
return IJSVGFontTraitNone;
|
|
}
|
|
|
|
+ (IJSVGFontTraits)fontStyleStringForString:(NSString *)string
|
|
{
|
|
if([string isEqualToString:@"italic"])
|
|
return IJSVGFontTraitItalic;
|
|
return IJSVGFontTraitNone;
|
|
}
|
|
|
|
+ (IJSVGWindingRule)windingRuleForString:(NSString *)string
|
|
{
|
|
if( [string isEqualToString:@"evenodd"] )
|
|
return IJSVGWindingRuleEvenOdd;
|
|
if( [string isEqualToString:@"inherit"] )
|
|
return IJSVGWindingRuleInherit;
|
|
return IJSVGWindingRuleNonZero;
|
|
}
|
|
|
|
+ (IJSVGLineJoinStyle)lineJoinStyleForString:(NSString *)string
|
|
{
|
|
if( [string isEqualToString:@"mitre"] )
|
|
return IJSVGLineJoinStyleMiter;
|
|
if( [string isEqualToString:@"round"] )
|
|
return IJSVGLineJoinStyleRound;
|
|
if( [string isEqualToString:@"bevel"] )
|
|
return IJSVGLineJoinStyleBevel;
|
|
if( [string isEqualToString:@"inherit"] )
|
|
return IJSVGLineJoinStyleInherit;
|
|
return IJSVGLineJoinStyleMiter;
|
|
}
|
|
|
|
+ (IJSVGLineCapStyle)lineCapStyleForString:(NSString *)string
|
|
{
|
|
if( [string isEqualToString:@"butt"] )
|
|
return IJSVGLineCapStyleButt;
|
|
if( [string isEqualToString:@"square"] )
|
|
return IJSVGLineCapStyleSquare;
|
|
if( [string isEqualToString:@"round"] )
|
|
return IJSVGLineCapStyleRound;
|
|
if( [string isEqualToString:@"inherit"] )
|
|
return IJSVGLineCapStyleInherit;
|
|
return IJSVGLineCapStyleButt;
|
|
}
|
|
|
|
+ (IJSVGUnitType)unitTypeForString:(NSString *)string
|
|
{
|
|
if([string isEqualToString:@"userSpaceOnUse"]) {
|
|
return IJSVGUnitUserSpaceOnUse;
|
|
}
|
|
return IJSVGUnitObjectBoundingBox;
|
|
}
|
|
|
|
+ (IJSVGBlendMode)blendModeForString:(NSString *)string
|
|
{
|
|
string = string.lowercaseString;
|
|
if([string isEqualToString:@"normal"])
|
|
return IJSVGBlendModeNormal;
|
|
if([string isEqualToString:@"multiply"])
|
|
return IJSVGBlendModeMultiply;
|
|
if([string isEqualToString:@"screen"])
|
|
return IJSVGBlendModeScreen;
|
|
if([string isEqualToString:@"overlay"])
|
|
return IJSVGBlendModeOverlay;
|
|
if([string isEqualToString:@"darken"])
|
|
return IJSVGBlendModeDarken;
|
|
if([string isEqualToString:@"lighten"])
|
|
return IJSVGBlendModeLighten;
|
|
if([string isEqualToString:@"color-dodge"])
|
|
return IJSVGBlendModeColorDodge;
|
|
if([string isEqualToString:@"color-burn"])
|
|
return IJSVGBlendModeColorBurn;
|
|
if([string isEqualToString:@"hard-light"])
|
|
return IJSVGBlendModeHardLight;
|
|
if([string isEqualToString:@"soft-light"])
|
|
return IJSVGBlendModeSoftLight;
|
|
if([string isEqualToString:@"difference"])
|
|
return IJSVGBlendModeDifference;
|
|
if([string isEqualToString:@"exclusion"])
|
|
return IJSVGBlendModeExclusion;
|
|
if([string isEqualToString:@"hue"])
|
|
return IJSVGBlendModeHue;
|
|
if([string isEqualToString:@"saturation"])
|
|
return IJSVGBlendModeSaturation;
|
|
if([string isEqualToString:@"color"])
|
|
return IJSVGBlendModeColor;
|
|
if([string isEqualToString:@"luminosity"])
|
|
return IJSVGBlendModeLuminosity;
|
|
return IJSVGBlendModeNormal;
|
|
}
|
|
|
|
+ (NSString *)mixBlendingModeForBlendMode:(IJSVGBlendMode)blendMode
|
|
{
|
|
switch (blendMode) {
|
|
case IJSVGBlendModeMultiply: {
|
|
return @"multiple";
|
|
}
|
|
case IJSVGBlendModeScreen: {
|
|
return @"screen";
|
|
}
|
|
case IJSVGBlendModeOverlay: {
|
|
return @"overlay";
|
|
}
|
|
case IJSVGBlendModeDarken: {
|
|
return @"darken";
|
|
}
|
|
case IJSVGBlendModeLighten: {
|
|
return @"lighten";
|
|
}
|
|
case IJSVGBlendModeColorDodge: {
|
|
return @"color-dodge";
|
|
}
|
|
case IJSVGBlendModeColorBurn: {
|
|
return @"color-burn";
|
|
}
|
|
case IJSVGBlendModeHardLight: {
|
|
return @"hard-light";
|
|
}
|
|
case IJSVGBlendModeSoftLight: {
|
|
return @"soft-light";
|
|
}
|
|
case IJSVGBlendModeDifference: {
|
|
return @"difference";
|
|
}
|
|
case IJSVGBlendModeExclusion: {
|
|
return @"exclusion";
|
|
}
|
|
case IJSVGBlendModeHue: {
|
|
return @"hue";
|
|
}
|
|
case IJSVGBlendModeSaturation: {
|
|
return @"saturation";
|
|
}
|
|
case IJSVGBlendModeColor: {
|
|
return @"color";
|
|
}
|
|
case IJSVGBlendModeLuminosity: {
|
|
return @"luminosity";
|
|
}
|
|
case IJSVGBlendModeNormal:
|
|
default: {
|
|
return nil;
|
|
}
|
|
}
|
|
}
|
|
|
|
+ (CGFloat *)commandParameters:(NSString *)command
|
|
count:(NSInteger *)count
|
|
{
|
|
if( [command isKindOfClass:[NSNumber class]] )
|
|
{
|
|
CGFloat * ret = (CGFloat *)malloc(1*sizeof(CGFloat));
|
|
ret[0] = [(NSNumber *)command floatValue];
|
|
*count = 1;
|
|
return ret;
|
|
}
|
|
return [[self class] scanFloatsFromString:command
|
|
size:count];
|
|
}
|
|
|
|
+ (CGFloat *)scanFloatsFromString:(NSString *)string
|
|
size:(NSInteger *)length
|
|
{
|
|
// default sizes and memory
|
|
// sizes for the string buffer
|
|
NSInteger defSize = 50;
|
|
NSInteger size = defSize;
|
|
|
|
// default memory size for the floats
|
|
NSInteger defFloatSize = 100;
|
|
NSInteger floatSize = defFloatSize;
|
|
|
|
NSInteger i = 0;
|
|
NSInteger counter = 0;
|
|
|
|
const char * cString = [string cStringUsingEncoding:NSUTF8StringEncoding];
|
|
const char * validChars = "0123456789eE+-.";
|
|
|
|
NSInteger sLength = strlen(cString);
|
|
|
|
// buffer for the returned floats
|
|
CGFloat * floats = (CGFloat *)malloc(sizeof(CGFloat)*defFloatSize);
|
|
|
|
char * buffer = NULL;
|
|
bool isDecimal = false;
|
|
int bufferCount = 0;
|
|
|
|
while(i < sLength) {
|
|
char currentChar = cString[i];
|
|
|
|
// work out next char
|
|
char nextChar = (char)0;
|
|
if(i < (sLength-1)) {
|
|
nextChar = cString[i+1];
|
|
}
|
|
|
|
bool isValid = strchr(validChars, currentChar);
|
|
|
|
// in order to work out the split, its either because the next char is
|
|
// a hyphen or a plus, or next char is a decimal and the current number is a decimal
|
|
bool isE = currentChar == 'e' || currentChar == 'E';
|
|
bool wantsEnd = nextChar == '-' || nextChar == '+' ||
|
|
(nextChar == '.' && isDecimal);
|
|
|
|
// could be a float like 5.334e-5 so dont break on the hypen
|
|
if(wantsEnd && isE && (nextChar == '-' || nextChar == '+')) {
|
|
wantsEnd = false;
|
|
}
|
|
|
|
// make sure its a valid string
|
|
if(isValid) {
|
|
// alloc the buffer if needed
|
|
if(buffer == NULL) {
|
|
buffer = (char *)calloc(sizeof(char),size);
|
|
} else if((bufferCount+1) == size) {
|
|
// realloc the buffer, incase the string is overflowing the
|
|
// allocated memory
|
|
size += defSize;
|
|
buffer = (char *)realloc(buffer, sizeof(char)*size);
|
|
}
|
|
// set the actual char against it
|
|
if(currentChar == '.') {
|
|
isDecimal = true;
|
|
}
|
|
buffer[bufferCount++] = currentChar;
|
|
} else {
|
|
// if its an invalid char, just stop it
|
|
wantsEnd = true;
|
|
}
|
|
|
|
// is at end of string, or wants to be stopped
|
|
// buffer has to actually exist or its completly
|
|
// useless and will cause a crash
|
|
if(buffer != NULL && (wantsEnd || i == sLength-1)) {
|
|
// make sure there is enough room in the float pool
|
|
if((counter+1) == floatSize) {
|
|
floatSize += defFloatSize;
|
|
floats = (CGFloat *)realloc(floats, sizeof(CGFloat)*floatSize);
|
|
}
|
|
|
|
// add the float
|
|
floats[counter++] = atof(buffer);
|
|
|
|
// memory clean and counter resets
|
|
free(buffer);
|
|
size = defSize;
|
|
isDecimal = false;
|
|
bufferCount = 0;
|
|
buffer = NULL;
|
|
}
|
|
i++;
|
|
}
|
|
*length = counter;
|
|
return floats;
|
|
}
|
|
|
|
+ (CGFloat *)parseViewBox:(NSString *)string
|
|
{
|
|
NSInteger size = 0;
|
|
return [[self class] scanFloatsFromString:string
|
|
size:&size];
|
|
}
|
|
|
|
+ (CGFloat)floatValue:(NSString *)string
|
|
fallBackForPercent:(CGFloat)fallBack
|
|
{
|
|
CGFloat val = [string floatValue];
|
|
if( [string rangeOfString:@"%"].location != NSNotFound )
|
|
val = (fallBack * val)/100;
|
|
return val;
|
|
}
|
|
|
|
+ (void)logParameters:(CGFloat *)param
|
|
count:(NSInteger)count
|
|
{
|
|
NSMutableString * str = [[[NSMutableString alloc] init] autorelease];
|
|
for( NSInteger i = 0; i < count; i++ )
|
|
{
|
|
[str appendFormat:@"%f ",param[i]];
|
|
}
|
|
NSLog(@"%@",str);
|
|
}
|
|
|
|
+ (CGFloat)floatValue:(NSString *)string
|
|
{
|
|
if( [string isEqualToString:@"inherit"] )
|
|
return IJSVGInheritedFloatValue;
|
|
return [string floatValue];
|
|
}
|
|
|
|
+ (CGFloat)angleBetweenPointA:(NSPoint)point1
|
|
pointb:(NSPoint)point2
|
|
{
|
|
return (point1.x * point2.y < point1.y * point2.x ? -1 : 1) * acosf(ratio(point1, point2));
|
|
}
|
|
|
|
+ (CGPathRef)newFlippedCGPath:(CGPathRef)path
|
|
{
|
|
CGRect boundingBox = CGPathGetPathBoundingBox(path);
|
|
CGAffineTransform scale = CGAffineTransformMakeScale(1.f, -1.f);
|
|
CGAffineTransform translate = CGAffineTransformTranslate(scale, 0.f, boundingBox.size.height);
|
|
CGPathRef transformPath = CGPathCreateCopyByTransformingPath(path, &translate);
|
|
return transformPath;
|
|
}
|
|
|
|
+ (CGPathRef)newCGPathFromBezierPath:(NSBezierPath *)bezPath
|
|
{
|
|
CGPathRef immutablePath = NULL;
|
|
// Then draw the path elements.
|
|
NSInteger numElements = bezPath.elementCount;
|
|
if (numElements > 0) {
|
|
CGMutablePathRef path = CGPathCreateMutable();
|
|
NSPoint points[3];
|
|
BOOL didClosePath = YES;
|
|
|
|
for (NSInteger i = 0; i < numElements; i++) {
|
|
switch ([bezPath elementAtIndex:i associatedPoints:points]) {
|
|
case NSMoveToBezierPathElement: {
|
|
CGPathMoveToPoint(path, NULL, points[0].x, points[0].y);
|
|
break;
|
|
}
|
|
|
|
case NSLineToBezierPathElement: {
|
|
CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y);
|
|
didClosePath = NO;
|
|
break;
|
|
}
|
|
|
|
case NSCurveToBezierPathElement: {
|
|
CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y,
|
|
points[1].x, points[1].y,
|
|
points[2].x, points[2].y);
|
|
didClosePath = NO;
|
|
break;
|
|
}
|
|
|
|
case NSClosePathBezierPathElement: {
|
|
CGPathCloseSubpath(path);
|
|
didClosePath = YES;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Be sure the path is closed or Quartz may not do valid hit detection.
|
|
if (didClosePath == NO) {
|
|
CGPathCloseSubpath(path);
|
|
}
|
|
|
|
// memory clean
|
|
immutablePath = CGPathCreateCopy(path);
|
|
CGPathRelease(path);
|
|
}
|
|
return immutablePath;
|
|
}
|
|
|
|
@end
|