RenderCore/Geometry/RCDimension.h (59 lines of code) (raw):
/*
* 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 <RenderCore/CKDefines.h>
#if CK_NOT_SWIFT
#import <UIKit/UIKit.h>
#import <RenderCore/RCAssert.h>
#import <RenderCore/CKSizeRange.h>
/**
A dimension relative to constraints to be provided in the future.
A RelativeDimension can be one of three types:
"Auto" - This indicated "I have no opinion" and may be resolved in whatever way makes most sense given
the circumstances. This is the default type.
"Points" - Just a number. It will always resolve to exactly this amount.
"Percent" - Multiplied to a provided parent amount to resolve a final amount.
If the parent amount is undefined (NaN) or infinite, it acts as if Auto size was specified instead.
A number of convenience constructors have been provided to make using RelativeDimension straight-forward.
RCRelativeDimension x; // Auto (default case)
RCRelativeDimension z = 10; // 10 Points
RCRelativeDimension y = RCRelativeDimension::Auto(); // Auto
RCRelativeDimension u = RCRelativeDimension::Percent(0.5); // 50%
*/
class RCRelativeDimension;
namespace std {
template <> struct hash<RCRelativeDimension> {
size_t operator ()(const RCRelativeDimension &) noexcept;
};
}
class RCRelativeDimension {
public:
// Make sizeof(Type) == sizeof(CGFloat) so that the default
// constructor takes fewer instructions (because of SLP
// vectorization).
enum class Type : NSInteger {
AUTO,
POINTS,
PERCENT,
};
/** Default constructor is equivalent to "Auto". */
constexpr RCRelativeDimension() noexcept : _type(Type::AUTO), _value(0) {}
RCRelativeDimension(CGFloat points) noexcept : RCRelativeDimension(Type::POINTS, points) {}
constexpr static RCRelativeDimension Auto() noexcept { return RCRelativeDimension(); }
static RCRelativeDimension Points(CGFloat p) noexcept { return RCRelativeDimension(p); }
static RCRelativeDimension Percent(CGFloat p) noexcept { return {RCRelativeDimension::Type::PERCENT, p}; }
RCRelativeDimension(const RCRelativeDimension &) = default;
RCRelativeDimension &operator=(const RCRelativeDimension &) = default;
bool operator==(const RCRelativeDimension &) const noexcept;
NSString *description() const noexcept;
CGFloat resolve(CGFloat autoSize, CGFloat parent) const noexcept;
Type type() const noexcept;
CGFloat value() const noexcept;
private:
RCRelativeDimension(Type type, CGFloat value)
: _type(type), _value(value) {}
Type _type;
CGFloat _value;
friend std::hash<RCRelativeDimension>;
};
/** Expresses a size with relative dimensions. */
struct RCRelativeSize {
RCRelativeDimension width;
RCRelativeDimension height;
RCRelativeSize(const RCRelativeDimension &width, const RCRelativeDimension &height) noexcept;
/** Convenience constructor to provide size in Points. */
RCRelativeSize(const CGSize &size) noexcept;
/** Convenience constructor for {Auto, Auto} */
constexpr RCRelativeSize() = default;
/** Resolve this size relative to a parent size and an auto size. */
CGSize resolveSize(const CGSize &parentSize, const CGSize &autoSize) const noexcept;
bool operator==(const RCRelativeSize &other) const noexcept;
NSString *description() const noexcept;
};
/**
Expresses an inclusive range of relative sizes. Used to provide additional constraint to component layout.
*/
struct RCRelativeSizeRange {
RCRelativeSize min;
RCRelativeSize max;
RCRelativeSizeRange(const RCRelativeSize &min, const RCRelativeSize &max);
/**
Convenience constructors to provide an exact size (min == max).
RCRelativeSizeRange r = {80, 60} // width: [80, 80], height: [60, 60].
*/
RCRelativeSizeRange(const RCRelativeSize &exact) noexcept;
RCRelativeSizeRange(const CGSize &exact) noexcept;
RCRelativeSizeRange(const RCRelativeDimension &exactWidth, const RCRelativeDimension &exactHeight) noexcept;
/** Convenience constructor for {{Auto, Auto}, {Auto, Auto}}. */
constexpr RCRelativeSizeRange() = default;
/**
Provided a parent size and values to use in place of Auto, compute final dimensions for this RelativeSizeRange
to arrive at a SizeRange. As an example:
CGSize parent = {200, 120};
RelativeSizeRange rel = {Percent(0.5), Percent(2/3)}
rel.resolveSizeRange(parent); // {{100, 60}, {100, 60}}
The default for Auto() is *everything*, meaning min = {0,0}; max = {INFINITY, INFINITY};
*/
CKSizeRange resolveSizeRange(const CGSize &parentSize,
const CKSizeRange &autoSizeRange = {{0,0}, {INFINITY, INFINITY}}) const noexcept;
};
#endif