react-native/React/Base/RCTFPSGraph.m

139 lines
3.8 KiB
Objective-C

/**
* Copyright (c) 2015-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 "RCTFPSGraph.h"
#import "RCTAssert.h"
#import "RCTDefines.h"
#if RCT_DEV
@implementation RCTFPSGraph
{
CAShapeLayer *_graph;
NSString *_name;
NSTimeInterval _prevTime;
RCTFPSGraphPosition _position;
UILabel *_label;
float *_frames;
int _frameCount;
int _maxFPS;
int _minFPS;
int _length;
int _margin;
int _height;
}
- (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color
{
if ((self = [super initWithFrame:frame])) {
_margin = 2;
_prevTime = -1;
_maxFPS = 0;
_minFPS = 60;
_length = (frame.size.width - 2 * _margin) / 2;
_height = frame.size.height - 2 * _margin;
_frames = malloc(sizeof(float) * _length);
memset(_frames, 0, sizeof(float) * _length);
_name = name ?: @"FPS";
_position = position ?: RCTFPSGraphPositionLeft;
color = color ?: [UIColor greenColor];
_graph = [self createGraph:color];
_label = [self createLabel:color];
[self addSubview:_label];
[self.layer addSublayer:_graph];
}
return self;
}
RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame)
RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder)
- (void)dealloc
{
free(_frames);
}
- (void)layoutSubviews
{
[super layoutSubviews];
}
- (CAShapeLayer *)createGraph:(UIColor *)color
{
CGFloat left = _position & RCTFPSGraphPositionLeft ? 0 : _length;
CAShapeLayer *graph = [[CAShapeLayer alloc] init];
graph.frame = CGRectMake(left, 0, 2 * _margin + _length, self.frame.size.height);
graph.backgroundColor = [[color colorWithAlphaComponent:.2] CGColor];
graph.fillColor = [color CGColor];
return graph;
}
- (UILabel *)createLabel:(UIColor *)color
{
CGFloat left = _position & RCTFPSGraphPositionLeft ? 2 * _margin + _length : 0;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(left, 0, _length, self.frame.size.height)];
label.textColor = color;
label.font = [UIFont systemFontOfSize:9];
label.minimumScaleFactor = .5;
label.adjustsFontSizeToFitWidth = YES;
label.numberOfLines = 3;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.textAlignment = NSTextAlignmentCenter;
return label;
}
- (void)tick:(NSTimeInterval)timestamp
{
_frameCount++;
if (_prevTime == -1) {
_prevTime = timestamp;
} else if (timestamp - _prevTime > 1) {
float fps = round(_frameCount / (timestamp - _prevTime));
_minFPS = MIN(_minFPS, fps);
_maxFPS = MAX(_maxFPS, fps);
_label.text = [NSString stringWithFormat:@"%@\n%d FPS\n(%d - %d)", _name, (int)fps, _minFPS, _maxFPS];
float scale = 60.0 / _height;
for (int i = 0; i < _length - 1; i++) {
_frames[i] = _frames[i + 1];
}
_frames[_length - 1] = fps / scale;
CGMutablePathRef path = CGPathCreateMutable();
if (_position & RCTFPSGraphPositionLeft) {
CGPathMoveToPoint(path, NULL, _margin, _margin + _height);
for (int i = 0; i < _length; i++) {
CGPathAddLineToPoint(path, NULL, _margin + i, _margin + _height - _frames[i]);
}
CGPathAddLineToPoint(path, NULL, _margin + _length - 1, _margin + _height);
} else {
CGPathMoveToPoint(path, NULL, _margin + _length - 1, _margin + _height);
for (int i = 0; i < _length; i++) {
CGPathAddLineToPoint(path, NULL, _margin + _length - i - 1, _margin + _height - _frames[i]);
}
CGPathAddLineToPoint(path, NULL, _margin, _margin + _height);
}
_graph.path = path;
CGPathRelease(path);
_prevTime = timestamp;
_frameCount = 0;
}
}
@end
#endif