2016-08-11 10:37:48 -07:00

140 lines
5.0 KiB
Plaintext

//
// ASDimension.mm
// AsyncDisplayKit
//
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "ASDimension.h"
#import "ASAssert.h"
ASRelativeDimension const ASRelativeDimensionUnconstrained = {};
#pragma mark - ASRelativeDimension
ASRelativeDimension ASRelativeDimensionMake(ASRelativeDimensionType type, CGFloat value)
{
if (type == ASRelativeDimensionTypePoints) {
ASDisplayNodeCAssertPositiveReal(@"Points", value);
} else if (type == ASRelativeDimensionTypeFraction) {
// TODO: Enable this assertion for 2.0. Check that there is no use case for using a larger value, e.g. to layout for a clipsToBounds = NO element.
// ASDisplayNodeCAssert( 0 <= value && value <= 1.0, @"ASRelativeDimension fraction value (%f) must be between 0 and 1.", value);
}
ASRelativeDimension dimension; dimension.type = type; dimension.value = value; return dimension;
}
ASRelativeDimension ASRelativeDimensionMakeWithPoints(CGFloat points)
{
ASDisplayNodeCAssertPositiveReal(@"Points", points);
return ASRelativeDimensionMake(ASRelativeDimensionTypePoints, points);
}
ASRelativeDimension ASRelativeDimensionMakeWithFraction(CGFloat fraction)
{
// ASDisplayNodeCAssert( 0 <= fraction && fraction <= 1.0, @"ASRelativeDimension fraction value (%f) must be between 0 and 1.", fraction);
return ASRelativeDimensionMake(ASRelativeDimensionTypeFraction, fraction);
}
ASRelativeDimension ASRelativeDimensionCopy(ASRelativeDimension aDimension)
{
return ASRelativeDimensionMake(aDimension.type, aDimension.value);
}
BOOL ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimension lhs, ASRelativeDimension rhs)
{
return lhs.type == rhs.type && lhs.value == rhs.value;
}
NSString *NSStringFromASRelativeDimension(ASRelativeDimension dimension)
{
switch (dimension.type) {
case ASRelativeDimensionTypePoints:
return [NSString stringWithFormat:@"%.0fpt", dimension.value];
case ASRelativeDimensionTypeFraction:
return [NSString stringWithFormat:@"%.0f%%", dimension.value * 100.0];
}
}
CGFloat ASRelativeDimensionResolve(ASRelativeDimension dimension, CGFloat parent)
{
switch (dimension.type) {
case ASRelativeDimensionTypePoints:
return dimension.value;
case ASRelativeDimensionTypeFraction:
return dimension.value * parent;
}
}
#pragma mark - ASSizeRange
ASSizeRange ASSizeRangeMake(CGSize min, CGSize max)
{
ASDisplayNodeCAssertPositiveReal(@"Range min width", min.width);
ASDisplayNodeCAssertPositiveReal(@"Range min height", min.height);
ASDisplayNodeCAssertInfOrPositiveReal(@"Range max width", max.width);
ASDisplayNodeCAssertInfOrPositiveReal(@"Range max height", max.height);
ASDisplayNodeCAssert(min.width <= max.width,
@"Range min width (%f) must not be larger than max width (%f).", min.width, max.width);
ASDisplayNodeCAssert(min.height <= max.height,
@"Range min height (%f) must not be larger than max height (%f).", min.height, max.height);
ASSizeRange sizeRange; sizeRange.min = min; sizeRange.max = max; return sizeRange;
}
ASSizeRange ASSizeRangeMakeExactSize(CGSize size)
{
return ASSizeRangeMake(size, size);
}
CGSize ASSizeRangeClamp(ASSizeRange sizeRange, CGSize size)
{
return CGSizeMake(MAX(sizeRange.min.width, MIN(sizeRange.max.width, size.width)),
MAX(sizeRange.min.height, MIN(sizeRange.max.height, size.height)));
}
struct _Range {
CGFloat min;
CGFloat max;
/**
Intersects another dimension range. If the other range does not overlap, this size range "wins" by returning a
single point within its own range that is closest to the non-overlapping range.
*/
_Range intersect(const _Range &other) const
{
CGFloat newMin = MAX(min, other.min);
CGFloat newMax = MIN(max, other.max);
if (newMin <= newMax) {
return {newMin, newMax};
} else {
// No intersection. If we're before the other range, return our max; otherwise our min.
if (min < other.min) {
return {max, max};
} else {
return {min, min};
}
}
}
};
ASSizeRange ASSizeRangeIntersect(ASSizeRange sizeRange, ASSizeRange otherSizeRange)
{
auto w = _Range({sizeRange.min.width, sizeRange.max.width}).intersect({otherSizeRange.min.width, otherSizeRange.max.width});
auto h = _Range({sizeRange.min.height, sizeRange.max.height}).intersect({otherSizeRange.min.height, otherSizeRange.max.height});
return {{w.min, h.min}, {w.max, h.max}};
}
BOOL ASSizeRangeEqualToSizeRange(ASSizeRange lhs, ASSizeRange rhs)
{
return CGSizeEqualToSize(lhs.min, rhs.min) && CGSizeEqualToSize(lhs.max, rhs.max);
}
NSString * NSStringFromASSizeRange(ASSizeRange sizeRange)
{
return [NSString stringWithFormat:@"<ASSizeRange: min=%@, max=%@>",
NSStringFromCGSize(sizeRange.min),
NSStringFromCGSize(sizeRange.max)];
}