Skip to content

Commit

Permalink
added fitInto: method to SPRectangle
Browse files Browse the repository at this point in the history
  • Loading branch information
racarone committed Nov 27, 2015
1 parent 6be9372 commit 621a99e
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
27 changes: 27 additions & 0 deletions sparrow/src/Classes/SPRectangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ NS_ASSUME_NONNULL_BEGIN
@class SPPoint;
@class SPMatrix;

/// Provides constant values for the SPRectangle 'fitInto:' method.
typedef NS_ENUM(NSInteger, SPScaleMode)
{
/// Specifies that the rectangle is not scaled, but simply centered within the
/// specified area. */
SPScaleModeNone,

/// Specifies that the rectangle fills the specified area without distortion but possibly
/// with some cropping, while maintaining the original aspect ratio. */
SPScaleModeNoBorder,

/// Specifies that the entire rectangle will be scaled to fit into the specified area,
/// while maintaining the original aspect ratio. This might leave empty bars at either the
/// top and bottom, or left and right.
SPScaleModeShowAll
};

/// The SPRectangle class describes a rectangle by its top-left corner point (x, y) and by
/// its width and height.

Expand Down Expand Up @@ -76,6 +93,16 @@ NS_ASSUME_NONNULL_BEGIN
/// the top and the bottom by the dy value.
- (void)inflateXBy:(float)dx yBy:(float)dy;

/// Calculates a rectangle with the same aspect ratio as the current rectangle, centered
/// within 'into'.
///
/// This method is useful for calculating the optimal viewPort for a certain display size. You can
/// use different scale modes to specify how the result should be calculated; furthermore, you can
/// avoid pixel alignment errors by only allowing whole-number multipliers/divisors
/// (e.g. 3, 2, 1, 1/2, 1/3).
- (SPRectangle *)fitInto:(SPRectangle *)into scaleMode:(SPScaleMode)scaleMode
pixelPerfect:(BOOL)pixelPerfect;

/// Scales the rectangle by a scale factor (includes x and y coordinates).
- (void)scaleBy:(float)scale;

Expand Down
54 changes: 54 additions & 0 deletions sparrow/src/Classes/SPRectangle.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,33 @@
(GLKVector2){{ 1.0f, 1.0f }}
};

/// Calculates the next whole-number multiplier or divisor, moving either up or down.
static float nextSuitableScaleFactor(float factor, BOOL up)
{
float divisor = 1.0f;

if (up)
{
if (factor >= 0.5f) return ceilf(factor);
else
{
while (1.0f / (divisor + 1.0f) > factor)
++divisor;
}
}
else
{
if (factor >= 1.0) return floorf(factor);
else
{
while (1.0f / divisor > factor)
++divisor;
}
}

return 1.0f / divisor;
}

@implementation SPRectangle

#pragma mark Initialization
Expand Down Expand Up @@ -152,6 +179,33 @@ - (void)inflateXBy:(float)dx yBy:(float)dy
_height += 2 * dy;
}

- (SPRectangle *)fitInto:(SPRectangle *)into scaleMode:(SPScaleMode)scaleMode
pixelPerfect:(BOOL)pixelPerfect
{
float factorX = into->_width / _width;
float factorY = into->_height / _height;
float factor = 1.0f;

if (scaleMode == SPScaleModeShowAll)
{
factor = factorX < factorY ? factorX : factorY;
if (pixelPerfect) factor = nextSuitableScaleFactor(factor, false);
}
else if (scaleMode == SPScaleModeNoBorder)
{
factor = factorX > factorY ? factorX : factorY;
if (pixelPerfect) factor = nextSuitableScaleFactor(factor, true);
}

float width = _width * factor;
float height = _height * factor;

return [SPRectangle rectangleWithX:into->_x + (into->_width - width) / 2
y:into->_y + (into->_height - height) / 2
width:width
height:height];
}

- (void)scaleBy:(float)scale
{
_x *= scale;
Expand Down

0 comments on commit 621a99e

Please sign in to comment.