2001-12-17 14:31:42 +00:00
|
|
|
/** NSGeometry.m - geometry functions
|
1996-03-22 00:36:13 +00:00
|
|
|
* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
*
|
1996-03-22 00:36:13 +00:00
|
|
|
* Written by: Adam Fedor <fedor@boulder.colorado.edu>
|
|
|
|
* Date: Mar 1995
|
2005-02-22 11:22:44 +00:00
|
|
|
*
|
1996-05-12 00:56:10 +00:00
|
|
|
* This file is part of the GNUstep Base Library.
|
2005-02-22 11:22:44 +00:00
|
|
|
*
|
1996-03-22 00:36:13 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
1996-03-22 00:36:13 +00:00
|
|
|
* License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
* version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
*
|
1996-03-22 00:36:13 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
*
|
2007-09-14 11:36:11 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
1996-03-22 00:36:13 +00:00
|
|
|
* License along with this library; if not, write to the Free
|
2006-10-09 17:21:51 +00:00
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
<title>NSGeometry class reference</title>
|
|
|
|
$Date$ $Revision$
|
2005-02-22 11:22:44 +00:00
|
|
|
*/
|
1996-03-22 00:36:13 +00:00
|
|
|
|
1999-02-12 17:03:09 +00:00
|
|
|
/*
|
|
|
|
* Define IN_NSGEOMETRY_M so that the Foundation/NSGeometry.h header can
|
|
|
|
* provide non-inline versions of the function implementations for us.
|
|
|
|
*/
|
|
|
|
#define IN_NSGEOMETRY_M
|
|
|
|
|
2002-10-09 06:07:38 +00:00
|
|
|
|
|
|
|
/**** Included Headers *******************************************************/
|
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
#import "common.h"
|
1995-03-23 03:51:32 +00:00
|
|
|
#include <math.h>
|
2010-02-17 11:47:06 +00:00
|
|
|
#import "Foundation/NSGeometry.h"
|
|
|
|
#import "Foundation/NSScanner.h"
|
|
|
|
#import "Foundation/NSNotification.h"
|
|
|
|
#import "GSPrivate.h"
|
2000-09-13 12:32:19 +00:00
|
|
|
|
1999-09-27 19:56:21 +00:00
|
|
|
static Class NSStringClass = 0;
|
|
|
|
static Class NSScannerClass = 0;
|
2000-10-30 18:00:27 +00:00
|
|
|
static SEL scanFloatSel;
|
|
|
|
static SEL scanStringSel;
|
|
|
|
static SEL scannerSel;
|
2009-02-23 20:42:32 +00:00
|
|
|
static BOOL (*scanFloatImp)(NSScanner*, SEL, CGFloat*);
|
1999-09-27 19:56:21 +00:00
|
|
|
static BOOL (*scanStringImp)(NSScanner*, SEL, NSString*, NSString**);
|
|
|
|
static id (*scannerImp)(Class, SEL, NSString*);
|
|
|
|
|
|
|
|
static inline void
|
2002-11-09 16:40:00 +00:00
|
|
|
setupCache(void)
|
1999-09-27 19:56:21 +00:00
|
|
|
{
|
|
|
|
if (NSStringClass == 0)
|
|
|
|
{
|
|
|
|
NSStringClass = [NSString class];
|
|
|
|
NSScannerClass = [NSScanner class];
|
2009-02-23 20:42:32 +00:00
|
|
|
if (sizeof(CGFloat) == sizeof(double))
|
|
|
|
{
|
|
|
|
scanFloatSel = @selector(scanDouble:);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
scanFloatSel = @selector(scanFloat:);
|
|
|
|
}
|
2000-10-30 18:00:27 +00:00
|
|
|
scanStringSel = @selector(scanString:intoString:);
|
|
|
|
scannerSel = @selector(scannerWithString:);
|
2009-02-23 20:42:32 +00:00
|
|
|
scanFloatImp = (BOOL (*)(NSScanner*, SEL, CGFloat*))
|
1999-09-27 19:56:21 +00:00
|
|
|
[NSScannerClass instanceMethodForSelector: scanFloatSel];
|
|
|
|
scanStringImp = (BOOL (*)(NSScanner*, SEL, NSString*, NSString**))
|
|
|
|
[NSScannerClass instanceMethodForSelector: scanStringSel];
|
|
|
|
scannerImp = (id (*)(Class, SEL, NSString*))
|
|
|
|
[NSScannerClass methodForSelector: scannerSel];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-09 17:21:51 +00:00
|
|
|
static BOOL GSMacOSXCompatibleGeometry(void)
|
|
|
|
{
|
2006-10-20 10:56:27 +00:00
|
|
|
if (GSPrivateDefaultsFlag(GSOldStyleGeometry) == YES)
|
2006-10-09 17:21:51 +00:00
|
|
|
return NO;
|
2006-10-20 10:56:27 +00:00
|
|
|
return GSPrivateDefaultsFlag(GSMacOSXCompatible);
|
2006-10-09 17:21:51 +00:00
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/**** Function Implementations ***********************************************/
|
1999-02-12 17:03:09 +00:00
|
|
|
/* Most of these are implemented in the header file as inline functkions */
|
1995-03-23 03:51:32 +00:00
|
|
|
|
1999-02-12 17:04:53 +00:00
|
|
|
NSRect
|
|
|
|
NSIntegralRect(NSRect aRect)
|
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
NSRect rect;
|
1999-02-12 17:04:53 +00:00
|
|
|
|
|
|
|
if (NSIsEmptyRect(aRect))
|
|
|
|
return NSMakeRect(0, 0, 0, 0);
|
|
|
|
|
2003-12-23 17:11:14 +00:00
|
|
|
rect.origin.x = floor(NSMinX(aRect));
|
|
|
|
rect.origin.y = floor(NSMinY(aRect));
|
|
|
|
rect.size.width = ceil(NSMaxX(aRect)) - rect.origin.x;
|
|
|
|
rect.size.height = ceil(NSMaxY(aRect)) - rect.origin.y;
|
1999-02-12 17:04:53 +00:00
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
|
1995-03-23 03:51:32 +00:00
|
|
|
void
|
1996-03-22 00:36:13 +00:00
|
|
|
NSDivideRect(NSRect aRect,
|
|
|
|
NSRect *slice,
|
|
|
|
NSRect *remainder,
|
2009-02-23 20:42:32 +00:00
|
|
|
CGFloat amount,
|
1996-03-22 00:36:13 +00:00
|
|
|
NSRectEdge edge)
|
1995-03-23 03:51:32 +00:00
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
static NSRect sRect;
|
|
|
|
static NSRect rRect;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
if (!slice)
|
|
|
|
slice = &sRect;
|
|
|
|
if (!remainder)
|
|
|
|
remainder = &rRect;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
if (NSIsEmptyRect(aRect))
|
1999-09-27 19:56:21 +00:00
|
|
|
{
|
|
|
|
*slice = NSMakeRect(0,0,0,0);
|
|
|
|
*remainder = NSMakeRect(0,0,0,0);
|
|
|
|
return;
|
|
|
|
}
|
1996-03-22 00:36:13 +00:00
|
|
|
|
|
|
|
switch (edge)
|
1999-09-27 19:56:21 +00:00
|
|
|
{
|
|
|
|
case NSMinXEdge:
|
|
|
|
if (amount > aRect.size.width)
|
|
|
|
{
|
|
|
|
*slice = aRect;
|
|
|
|
*remainder = NSMakeRect(NSMaxX(aRect),
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
0,
|
|
|
|
aRect.size.height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
*slice = NSMakeRect(aRect.origin.x,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.origin.y,
|
2005-02-22 11:22:44 +00:00
|
|
|
amount,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.height);
|
|
|
|
*remainder = NSMakeRect(NSMaxX(*slice),
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
NSMaxX(aRect) - NSMaxX(*slice),
|
|
|
|
aRect.size.height);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NSMinYEdge:
|
|
|
|
if (amount > aRect.size.height)
|
|
|
|
{
|
1995-03-23 03:51:32 +00:00
|
|
|
*slice = aRect;
|
1996-03-22 00:36:13 +00:00
|
|
|
*remainder = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
NSMaxY(aRect),
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.width, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*slice = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.width,
|
|
|
|
amount);
|
|
|
|
*remainder = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
NSMaxY(*slice),
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.width,
|
|
|
|
NSMaxY(aRect) - NSMaxY(*slice));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case (NSMaxXEdge):
|
|
|
|
if (amount > aRect.size.width)
|
|
|
|
{
|
|
|
|
*slice = aRect;
|
|
|
|
*remainder = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
0,
|
|
|
|
aRect.size.height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1996-03-22 00:36:13 +00:00
|
|
|
*slice = NSMakeRect(NSMaxX(aRect) - amount,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.origin.y,
|
|
|
|
amount,
|
|
|
|
aRect.size.height);
|
|
|
|
*remainder = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
NSMinX(*slice) - aRect.origin.x,
|
|
|
|
aRect.size.height);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NSMaxYEdge:
|
|
|
|
if (amount > aRect.size.height)
|
|
|
|
{
|
|
|
|
*slice = aRect;
|
1996-03-22 00:36:13 +00:00
|
|
|
*remainder = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.width,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*slice = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
NSMaxY(aRect) - amount,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.width,
|
|
|
|
amount);
|
|
|
|
*remainder = NSMakeRect(aRect.origin.x,
|
2005-02-22 11:22:44 +00:00
|
|
|
aRect.origin.y,
|
1999-09-27 19:56:21 +00:00
|
|
|
aRect.size.width,
|
|
|
|
NSMinY(*slice) - aRect.origin.y);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1996-03-22 00:36:13 +00:00
|
|
|
|
|
|
|
return;
|
1995-03-23 03:51:32 +00:00
|
|
|
}
|
|
|
|
|
1996-03-22 00:36:13 +00:00
|
|
|
/** Get a String Representation... **/
|
2005-08-22 22:51:02 +00:00
|
|
|
/* NOTE: Spaces around '=' so that old OpenStep implementations can
|
|
|
|
read our strings (Both GNUstep and Mac OS X can read these as well). */
|
1996-03-22 00:36:13 +00:00
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
NSString*
|
1996-03-22 00:36:13 +00:00
|
|
|
NSStringFromPoint(NSPoint aPoint)
|
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
setupCache();
|
2000-09-13 12:32:19 +00:00
|
|
|
if (GSMacOSXCompatibleGeometry() == YES)
|
2000-09-07 16:42:45 +00:00
|
|
|
return [NSStringClass stringWithFormat:
|
|
|
|
@"{%g, %g}", aPoint.x, aPoint.y];
|
|
|
|
else
|
|
|
|
return [NSStringClass stringWithFormat:
|
2005-08-22 22:51:02 +00:00
|
|
|
@"{x = %g; y = %g}", aPoint.x, aPoint.y];
|
1996-03-22 00:36:13 +00:00
|
|
|
}
|
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
NSString*
|
1996-03-22 00:36:13 +00:00
|
|
|
NSStringFromRect(NSRect aRect)
|
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
setupCache();
|
2000-09-13 12:32:19 +00:00
|
|
|
if (GSMacOSXCompatibleGeometry() == YES)
|
2000-09-07 16:42:45 +00:00
|
|
|
return [NSStringClass stringWithFormat:
|
|
|
|
@"{{%g, %g}, {%g, %g}}",
|
|
|
|
aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height];
|
|
|
|
else
|
|
|
|
return [NSStringClass stringWithFormat:
|
2005-08-22 22:51:02 +00:00
|
|
|
@"{x = %g; y = %g; width = %g; height = %g}",
|
2000-09-07 16:42:45 +00:00
|
|
|
aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height];
|
1996-03-22 00:36:13 +00:00
|
|
|
}
|
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
NSString*
|
1996-03-22 00:36:13 +00:00
|
|
|
NSStringFromSize(NSSize aSize)
|
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
setupCache();
|
2000-09-13 12:32:19 +00:00
|
|
|
if (GSMacOSXCompatibleGeometry() == YES)
|
2000-09-07 16:42:45 +00:00
|
|
|
return [NSStringClass stringWithFormat:
|
|
|
|
@"{%g, %g}", aSize.width, aSize.height];
|
|
|
|
else
|
|
|
|
return [NSStringClass stringWithFormat:
|
2005-08-22 22:51:02 +00:00
|
|
|
@"{width = %g; height = %g}", aSize.width, aSize.height];
|
1995-03-23 03:51:32 +00:00
|
|
|
}
|
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
NSPoint
|
|
|
|
NSPointFromString(NSString* string)
|
1997-12-19 18:13:52 +00:00
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
NSScanner *scanner;
|
|
|
|
NSPoint point;
|
1997-12-19 18:13:52 +00:00
|
|
|
|
1999-09-27 19:56:21 +00:00
|
|
|
setupCache();
|
|
|
|
scanner = (*scannerImp)(NSScannerClass, scannerSel, string);
|
|
|
|
if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"x", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &point.x)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @";", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"y", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &point.y)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
|
2000-09-07 16:42:45 +00:00
|
|
|
{
|
|
|
|
return point;
|
|
|
|
}
|
1997-12-19 18:13:52 +00:00
|
|
|
else
|
2000-09-07 16:42:45 +00:00
|
|
|
{
|
|
|
|
[scanner setScanLocation: 0];
|
|
|
|
if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &point.x)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &point.y)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
|
|
|
|
{
|
|
|
|
return point;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NSMakePoint(0, 0);
|
|
|
|
}
|
|
|
|
}
|
1997-12-19 18:13:52 +00:00
|
|
|
}
|
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
NSSize
|
|
|
|
NSSizeFromString(NSString* string)
|
1997-12-19 18:13:52 +00:00
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
NSScanner *scanner;
|
|
|
|
NSSize size;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1999-09-27 19:56:21 +00:00
|
|
|
setupCache();
|
|
|
|
scanner = (*scannerImp)(NSScannerClass, scannerSel, string);
|
|
|
|
if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"width", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &size.width)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @";", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"height", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &size.height)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
|
2000-09-07 16:42:45 +00:00
|
|
|
{
|
|
|
|
return size;
|
|
|
|
}
|
1997-12-19 18:13:52 +00:00
|
|
|
else
|
2000-09-07 16:42:45 +00:00
|
|
|
{
|
|
|
|
[scanner setScanLocation: 0];
|
|
|
|
if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &size.width)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &size.height)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
|
|
|
|
{
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NSMakeSize(0, 0);
|
|
|
|
}
|
|
|
|
}
|
1997-12-19 18:13:52 +00:00
|
|
|
}
|
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
NSRect
|
|
|
|
NSRectFromString(NSString* string)
|
1997-12-19 18:13:52 +00:00
|
|
|
{
|
1999-09-27 19:56:21 +00:00
|
|
|
NSScanner *scanner;
|
|
|
|
NSRect rect;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1999-09-27 19:56:21 +00:00
|
|
|
setupCache();
|
|
|
|
scanner = (*scannerImp)(NSScannerClass, scannerSel, string);
|
|
|
|
if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"x", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.x)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @";", NULL)
|
|
|
|
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"y", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.y)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @";", NULL)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1999-09-27 19:56:21 +00:00
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"width", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.size.width)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @";", NULL)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1999-09-27 19:56:21 +00:00
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"height", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"=", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.size.height)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
|
2000-09-07 16:42:45 +00:00
|
|
|
{
|
|
|
|
return rect;
|
|
|
|
}
|
1997-12-19 18:13:52 +00:00
|
|
|
else
|
2000-09-07 16:42:45 +00:00
|
|
|
{
|
|
|
|
[scanner setScanLocation: 0];
|
|
|
|
if ((*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.x)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
|
|
|
|
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.origin.y)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"{", NULL)
|
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.size.width)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @",", NULL)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2000-09-07 16:42:45 +00:00
|
|
|
&& (*scanFloatImp)(scanner, scanFloatSel, &rect.size.height)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL)
|
|
|
|
&& (*scanStringImp)(scanner, scanStringSel, @"}", NULL))
|
|
|
|
{
|
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NSMakeRect(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
1997-12-19 18:13:52 +00:00
|
|
|
}
|
|
|
|
|
2009-02-23 08:57:49 +00:00
|
|
|
/* Tests for equality of floats/doubles.
|
|
|
|
* WARNING assumes the values are in the standard IEEE format ...
|
|
|
|
* this may not be true on all systems, though afaik it is the case
|
|
|
|
* on all systems we target.
|
|
|
|
*
|
|
|
|
* We use integer arithmetic for speed, assigning the float/double
|
|
|
|
* to an integer of the same size and then converting any negative
|
|
|
|
* values to twos-complement integer values so that a simple integer
|
|
|
|
* comparison can be done.
|
|
|
|
*
|
|
|
|
* MAX_ULP specified the number of Units in the Last Place by which
|
|
|
|
* the two values may differ and still be considered equal. A value
|
|
|
|
* of zero means that the two numbers must be identical.
|
|
|
|
*
|
|
|
|
* The way that infinity is represented means that it will be considered
|
|
|
|
* equal to MAX_FLT (or MAX_DBL) unless we are doing an exact comparison
|
|
|
|
* with MAX_ULP set to zero.
|
|
|
|
*
|
|
|
|
* The implementation will also treat two NaN values as being equal, which
|
|
|
|
* is technically wrong ... but is it worth adding a check for that?
|
|
|
|
*/
|
|
|
|
#define MAX_ULP 0
|
|
|
|
static inline BOOL
|
|
|
|
almostEqual(CGFloat A, CGFloat B)
|
|
|
|
{
|
|
|
|
#if MAX_ULP == 0
|
|
|
|
return (A == B) ? YES : NO;
|
|
|
|
#else /* MAX_UPL == 0 */
|
|
|
|
#if defined(CGFLOAT_IS_DBL)
|
|
|
|
union {int64_t i; double d;} valA, valB;
|
|
|
|
|
|
|
|
valA.d = A;
|
|
|
|
valB.d = B;
|
|
|
|
#if GS_SIZEOF_LONG == 8
|
|
|
|
if (valA.i < 0)
|
|
|
|
{
|
|
|
|
valA.i = 0x8000000000000000L - valA.i;
|
|
|
|
}
|
|
|
|
if (valB.i < 0)
|
|
|
|
{
|
|
|
|
valB.i = 0x8000000000000000L - valB.i;
|
|
|
|
}
|
|
|
|
if (labs(valA.i - valB.i) <= MAX_ULP)
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
#else /* GS_SIZEOF_LONG == 8 */
|
|
|
|
if (valA.i < 0)
|
|
|
|
{
|
|
|
|
valA.i = 0x8000000000000000LL - valA.i;
|
|
|
|
}
|
|
|
|
if (valB.i < 0)
|
|
|
|
{
|
|
|
|
valB.i = 0x8000000000000000LL - valB.i;
|
|
|
|
}
|
|
|
|
if (llabs(valA.i - valB.i) <= MAX_ULP)
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
#endif /* GS_SIZEOF_LONG == 8 */
|
|
|
|
return NO;
|
|
|
|
#else /* DEFINED(CGFLOAT_IS_DBL) */
|
|
|
|
union {int32_t i; float f;} valA, valB;
|
|
|
|
|
|
|
|
valA.f = A;
|
|
|
|
if (valA.i < 0)
|
|
|
|
{
|
|
|
|
valA.i = 0x80000000 - valA.i;
|
|
|
|
}
|
|
|
|
valB.f = B;
|
|
|
|
if (valB.i < 0)
|
|
|
|
{
|
|
|
|
valB.i = 0x80000000 - valB.i;
|
|
|
|
}
|
|
|
|
if (abs(valA.i - valB.i) <= MAX_ULP)
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
#endif /* DEFINED(CGFLOAT_IS_DBL) */
|
|
|
|
#endif /* MAX_UPL == 0 */
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
NSEqualRects(NSRect aRect, NSRect bRect)
|
|
|
|
{
|
|
|
|
return (almostEqual(NSMinX(aRect), NSMinX(bRect))
|
|
|
|
&& almostEqual(NSMinY(aRect), NSMinY(bRect))
|
|
|
|
&& almostEqual(NSWidth(aRect), NSWidth(bRect))
|
|
|
|
&& almostEqual(NSHeight(aRect), NSHeight(bRect))) ? YES : NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
NSEqualSizes(NSSize aSize, NSSize bSize)
|
|
|
|
{
|
|
|
|
return (almostEqual(aSize.width, bSize.width)
|
|
|
|
&& almostEqual(aSize.height, bSize.height)) ? YES : NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
NSEqualPoints(NSPoint aPoint, NSPoint bPoint)
|
|
|
|
{
|
|
|
|
return (almostEqual(aPoint.x, bPoint.x)
|
|
|
|
&& almostEqual(aPoint.y, bPoint.y)) ? YES : NO;
|
|
|
|
}
|
|
|
|
|
2017-06-20 23:40:26 +00:00
|
|
|
BOOL
|
|
|
|
NSEdgeInsetsEqual(NSEdgeInsets e1, NSEdgeInsets e2)
|
|
|
|
{
|
|
|
|
return (
|
|
|
|
almostEqual(e1.top, e2.top)
|
|
|
|
&& almostEqual(e1.left, e2.left)
|
|
|
|
&& almostEqual(e1.bottom, e2.bottom)
|
|
|
|
&& almostEqual(e1.right, e2.right)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|