123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- #import "SVGLength.h"
- #import "CSSPrimitiveValue.h"
- #import "CSSPrimitiveValue_ConfigurablePixelsPerInch.h"
- #import "SVGUtils.h"
- #include <sys/types.h>
- #include <sys/sysctl.h>
- @interface SVGLength()
- @property(nonatomic,strong) CSSPrimitiveValue* internalCSSPrimitiveValue;
- @end
- @implementation SVGLength
- @synthesize unitType;
- @synthesize value;
- @synthesize valueInSpecifiedUnits;
- @synthesize valueAsString;
- @synthesize internalCSSPrimitiveValue;
- - (id)init
- {
- NSAssert(FALSE, @"This class must not be init'd. Use the static hepler methods to instantiate it instead");
- return nil;
- }
- - (id)initWithCSSPrimitiveValue:(CSSPrimitiveValue*) pv
- {
- self = [super init];
- if (self) {
- self.internalCSSPrimitiveValue = pv;
- }
- return self;
- }
- -(float)value
- {
- return [self.internalCSSPrimitiveValue getFloatValue:self.internalCSSPrimitiveValue.primitiveType];
- }
- -(SVG_LENGTH_TYPE)unitType
- {
- switch( self.internalCSSPrimitiveValue.primitiveType )
- {
- case CSS_CM:
- return SVG_LENGTHTYPE_CM;
- case CSS_EMS:
- return SVG_LENGTHTYPE_EMS;
- case CSS_EXS:
- return SVG_LENGTHTYPE_EXS;
- case CSS_IN:
- return SVG_LENGTHTYPE_IN;
- case CSS_MM:
- return SVG_LENGTHTYPE_MM;
- case CSS_PC:
- return SVG_LENGTHTYPE_PC;
- case CSS_PERCENTAGE:
- return SVG_LENGTHTYPE_PERCENTAGE;
- case CSS_PT:
- return SVG_LENGTHTYPE_PT;
- case CSS_PX:
- return SVG_LENGTHTYPE_PX;
- case CSS_NUMBER:
- case CSS_DIMENSION:
- return SVG_LENGTHTYPE_NUMBER;
- default:
- return SVG_LENGTHTYPE_UNKNOWN;
- }
- }
- -(void) newValueSpecifiedUnits:(SVG_LENGTH_TYPE) unitType valueInSpecifiedUnits:(float) valueInSpecifiedUnits
- {
- NSAssert(FALSE, @"Not supported yet");
- }
- -(void) convertToSpecifiedUnits:(SVG_LENGTH_TYPE) unitType
- {
- NSAssert(FALSE, @"Not supported yet");
- }
- /** Apple calls this method when the class is loaded; that's as good a time as any to calculate the device / screen's PPI */
- +(void)initialize
- {
- cachedDevicePixelsPerInch = [self pixelsPerInchForCurrentDevice];
- }
- +(SVGLength*) svgLengthZero
- {
- SVGLength* result = [[SVGLength alloc] initWithCSSPrimitiveValue:nil];
-
- return result;
- }
- static float cachedDevicePixelsPerInch;
- +(SVGLength*) svgLengthFromNSString:(NSString*) s
- {
- CSSPrimitiveValue* pv = [[CSSPrimitiveValue alloc] init];
-
- pv.pixelsPerInch = cachedDevicePixelsPerInch;
- pv.cssText = s;
-
- SVGLength* result = [[SVGLength alloc] initWithCSSPrimitiveValue:pv];
-
- return result;
- }
- -(float) pixelsValue
- {
- return [self.internalCSSPrimitiveValue getFloatValue:CSS_PX];
- }
- -(float) pixelsValueWithDimension:(float)dimension
- {
- if (self.internalCSSPrimitiveValue.primitiveType == CSS_PERCENTAGE)
- return dimension * self.value / 100.0;
-
- return [self pixelsValue];
- }
- -(float) pixelsValueWithGradientDimension:(float)dimension
- {
- if (self.internalCSSPrimitiveValue.primitiveType == CSS_PERCENTAGE) {
- return dimension * self.value / 100.0;
- } else if (self.internalCSSPrimitiveValue.primitiveType == CSS_NUMBER) {
- if (self.value >= 0 && self.value <= 1) {
- return dimension * self.value;
- }
- }
-
- return [self pixelsValue];
- }
- -(float) numberValue
- {
- return [self.internalCSSPrimitiveValue getFloatValue:CSS_NUMBER];
- }
- #pragma mark - secret methods needed to provide an implementation on ObjectiveC
- +(float) pixelsPerInchForCurrentDevice
- {
- /** Using this as reference: http://en.wikipedia.org/wiki/Retina_Display and https://www.theiphonewiki.com/wiki/Models
- */
-
- size_t size;
- sysctlbyname("hw.machine", NULL, &size, NULL, 0);
- char *machine = malloc(size);
- sysctlbyname("hw.machine", machine, &size, NULL, 0);
- NSString *platform = [NSString stringWithUTF8String:machine];
- free(machine);
-
- if( [platform hasPrefix:@"iPhone1"]
- || [platform hasPrefix:@"iPhone2"]
- || [platform hasPrefix:@"iPhone3"])
- return 163.0f;
-
- if( [platform hasPrefix:@"iPhone4"]
- || [platform hasPrefix:@"iPhone5"]
- || [platform hasPrefix:@"iPhone6"]
- || [platform hasPrefix:@"iPhone7,2"]
- || [platform hasPrefix:@"iPhone8,1"]
- || [platform hasPrefix:@"iPhone8,4"]
- || [platform hasPrefix:@"iPhone9,1"]
- || [platform hasPrefix:@"iPhone9,3"]) {
- return 326.0f;
- }
-
- if ( [platform hasPrefix:@"iPhone7,1"]
- || [platform hasPrefix:@"iPhone8,2"]
- || [platform hasPrefix:@"iPhone9,2"]
- || [platform hasPrefix:@"iPhone9,4"]) {
- return 401.0f;
- }
-
- if( [platform hasPrefix:@"iPhone"]) // catch-all for higher-end devices not yet existing
- {
- NSAssert(FALSE, @"Update your source code or disable assertions: you are using an iPhone that didn't exist when this code was written, we have no idea what the pixel count per inch is!");
- return 401.0f;
- }
-
- if( [platform hasPrefix:@"iPod1"]
- || [platform hasPrefix:@"iPod2"]
- || [platform hasPrefix:@"iPod3"])
- return 163.0f;
-
- if( [platform hasPrefix:@"iPod4"]
- || [platform hasPrefix:@"iPod5"]
- || [platform hasPrefix:@"iPod7"])
- return 326.0f;
-
- if( [platform hasPrefix:@"iPod"]) // catch-all for higher-end devices not yet existing
- {
- NSAssert(FALSE, @"Update your source code or disable assertions: you are using an iPod that didn't exist when this code was written, we have no idea what the pixel count per inch is!");
- return 326.0f;
- }
-
- if( [platform hasPrefix:@"iPad5,1"]
- || [platform hasPrefix:@"iPad5,2"])
- return 326.0f;
-
- if( [platform hasPrefix:@"iPad1"]
- || [platform hasPrefix:@"iPad2"])
- return 132.0f;
- if( [platform hasPrefix:@"iPad3"]
- || [platform hasPrefix:@"iPad4"]
- || [platform hasPrefix:@"iPad5,3"]
- || [platform hasPrefix:@"iPad5,4"]
- || [platform hasPrefix:@"iPad6"]
- || [platform hasPrefix:@"iPad7"]
- || [platform hasPrefix:@"iPad8"])
- return 264.0f;
-
- if( [platform hasPrefix:@"iPad"]) // catch-all for higher-end devices not yet existing
- {
- NSAssert(FALSE, @"Update your source code or disable assertions: you are using an iPad that didn't exist when this code was written, we have no idea what the pixel count per inch is!");
- return 264.0f;
- }
-
- if( [platform hasPrefix:@"iWatch1"])
- return 326.0f;
-
- if( [platform hasPrefix:@"iWatch"]) // catch-all for higher-end devices not yet existing
- {
- NSAssert(FALSE, @"Update your source code or disable assertions: you are using an iWatch that didn't exist when this code was written, we have no idea what the pixel count per inch is!");
- return 326.0f;
- }
-
- if( [platform hasPrefix:@"x86_64"])
- {
- SVGKitLogWarn(@"[%@] WARNING: you are running on the simulator; it's impossible for us to calculate centimeter/millimeter/inches units correctly", [self class]);
- return 132.0f; // Simulator, running on desktop machine
- }
-
- NSAssert(FALSE, @"Cannot determine the PPI values for current device; returning 0.0f - hopefully this will crash your code (you CANNOT run SVG's that use CM/IN/MM etc until you fix this)" );
- return 0.0f; // Bet you'll get a divide by zero here...
- }
- @end
|