mirror of
https://github.com/danog/Telegram.git
synced 2024-12-04 10:27:46 +01:00
250 lines
7.8 KiB
Objective-C
250 lines
7.8 KiB
Objective-C
/*
|
|
* This is the source code of Telegram for iOS v. 1.1
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
*
|
|
* Copyright Peter Iakovlev, 2013.
|
|
*/
|
|
|
|
#import "TGGradientLabel.h"
|
|
|
|
#import "TGImageUtils.h"
|
|
|
|
@interface TGGradientLabel ()
|
|
{
|
|
CGSize _textSize;
|
|
|
|
void *_offscreenMemory;
|
|
int _offscreenContextWidth;
|
|
int _offscreenContextHeight;
|
|
int _offscreenContextStride;
|
|
CGContextRef _offscreenContext;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGGradientLabel
|
|
|
|
- (id)initWithFrame:(CGRect)frame
|
|
{
|
|
self = [super initWithFrame:frame];
|
|
if (self)
|
|
{
|
|
self.opaque = false;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)sizeToFit
|
|
{
|
|
if (_text == nil || _font == nil)
|
|
return;
|
|
|
|
_textSize = [self.text sizeWithFont:_font];
|
|
|
|
CGRect frame = self.frame;
|
|
frame.size = _textSize;
|
|
self.frame = frame;
|
|
}
|
|
|
|
- (void)setText:(NSString *)text
|
|
{
|
|
NSString *tmpText = text;
|
|
if (text.length == 1)
|
|
{
|
|
unichar c = [text characterAtIndex:0];
|
|
if (c >= 'a' && c <= 'z')
|
|
{
|
|
c += 'A' - 'a';
|
|
tmpText = [[NSString alloc] initWithCharacters:&c length:1];
|
|
}
|
|
}
|
|
else if (text.length == 3)
|
|
{
|
|
unichar c[3] = {[text characterAtIndex:0], [text characterAtIndex:1], [text characterAtIndex:2]};
|
|
if (c[0] >= 'a' && c[0] <= 'z')
|
|
c[0] += 'A' - 'a';
|
|
if (c[2] >= 'a' && c[2] <= 'z')
|
|
c[2] += 'A' - 'a';
|
|
|
|
tmpText = [[NSString alloc] initWithCharacters:c length:3];
|
|
}
|
|
_text = tmpText;
|
|
[self setNeedsDisplay];
|
|
}
|
|
|
|
- (void)drawRect:(CGRect)__unused rect
|
|
{
|
|
if (_text.length == 0 || _font == nil)
|
|
return;
|
|
|
|
bool nonEmpty = false;
|
|
for (int i = (int)_text.length - 1; i >= 0; i--)
|
|
{
|
|
if ([_text characterAtIndex:i] != ' ')
|
|
{
|
|
nonEmpty = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!nonEmpty)
|
|
return;
|
|
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
CGRect bounds = self.bounds;
|
|
|
|
if (bounds.size.width < FLT_EPSILON || bounds.size.height < FLT_EPSILON)
|
|
return;
|
|
|
|
int offscreenWidth = (int)bounds.size.width;
|
|
int offscreenHeight = (int)bounds.size.height;
|
|
|
|
if (offscreenWidth != _offscreenContextWidth || offscreenHeight != _offscreenContextHeight)
|
|
{
|
|
if (_offscreenMemory != NULL)
|
|
{
|
|
free(_offscreenMemory);
|
|
_offscreenMemory = NULL;
|
|
}
|
|
|
|
if (_offscreenContext != NULL)
|
|
{
|
|
CFRelease(_offscreenContext);
|
|
_offscreenContext = NULL;
|
|
}
|
|
|
|
_offscreenContextWidth = offscreenWidth;
|
|
_offscreenContextHeight = offscreenHeight;
|
|
_offscreenContextStride = ((4 * _offscreenContextWidth + 15) & (~15));
|
|
_offscreenMemory = malloc(_offscreenContextStride * _offscreenContextHeight);
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
|
_offscreenContext = CGBitmapContextCreate(_offscreenMemory, _offscreenContextWidth, _offscreenContextHeight, 8, _offscreenContextStride, colorSpace, bitmapInfo);
|
|
CGColorSpaceRelease(colorSpace);
|
|
}
|
|
|
|
if (_textColor != nil)
|
|
{
|
|
CGPoint drawingOffset = CGPointMake(CGFloor((bounds.size.width - _textSize.width) / 2.0f), CGFloor((bounds.size.height - _textSize.height) / 2.0f));
|
|
|
|
if (false)
|
|
{
|
|
memset(_offscreenMemory, 0x00, (int)(_offscreenContextStride * _offscreenContextHeight));
|
|
UIGraphicsPushContext(_offscreenContext);
|
|
[_text drawAtPoint:CGPointMake(2.0f, 2.0f) withFont:_font];
|
|
UIGraphicsPopContext();
|
|
|
|
int minX = _offscreenContextWidth;
|
|
int minY = _offscreenContextHeight;
|
|
int maxX = 0;
|
|
int maxY = 0;
|
|
|
|
const void *offscreenMemory = _offscreenMemory;
|
|
const int offscreenStride = _offscreenContextStride;
|
|
for (int y = 0; y < _offscreenContextHeight; y++)
|
|
{
|
|
for (int x = 0; x < _offscreenContextWidth; x++)
|
|
{
|
|
if ((*((uint32_t *)&offscreenMemory[y * offscreenStride + x * 4]) & 0xff000000) == 0xff000000)
|
|
{
|
|
if (x < minX)
|
|
minX = x;
|
|
if (y < minY)
|
|
minY = y;
|
|
if (x > maxX)
|
|
maxX = x;
|
|
if (y > maxY)
|
|
maxY = y;
|
|
}
|
|
}
|
|
}
|
|
|
|
const int halfY = (maxY + minY) / 2;
|
|
const int halfX = (maxX + minX) / 2;
|
|
|
|
int topHalf = 0;
|
|
int bottomHalf = 0;
|
|
int rightHalf = 0;
|
|
int leftHalf = 0;
|
|
for (int y = minY; y <= maxY; y++)
|
|
{
|
|
for (int x = minX; x <= maxX; x++)
|
|
{
|
|
if ((*((uint32_t *)&offscreenMemory[y * offscreenStride + x * 4]) & 0xff000000) == 0xff000000)
|
|
{
|
|
if (x < halfX)
|
|
leftHalf++;
|
|
else
|
|
rightHalf++;
|
|
|
|
if (y < halfY)
|
|
topHalf++;
|
|
else
|
|
bottomHalf++;
|
|
}
|
|
}
|
|
}
|
|
|
|
CGFloat topOffset = 0.0f;
|
|
CGFloat leftOffset = 0.0f;
|
|
|
|
if (topHalf != 0 && bottomHalf != 0 && leftHalf != 0 && rightHalf != 0)
|
|
{
|
|
topOffset = topHalf / (CGFloat)bottomHalf - 1.0f;
|
|
leftOffset = leftHalf / (CGFloat)rightHalf - 1.0f;
|
|
}
|
|
|
|
minY = _offscreenContextHeight - minY;
|
|
maxY = _offscreenContextHeight - maxY;
|
|
int tmp = maxY;
|
|
maxY = minY;
|
|
minY = tmp;
|
|
|
|
CGSize realSize = CGSizeMake(maxX - minX, maxY - minY);
|
|
CGPoint realOffset = CGPointMake(minX - 2.0f, minY - 2.0f);
|
|
|
|
if (realSize.width > FLT_EPSILON && realSize.height > FLT_EPSILON)
|
|
{
|
|
drawingOffset = CGPointMake(CGFloor((bounds.size.width - realSize.width) / 2.0f) - realOffset.x, CGFloor((bounds.size.height - realSize.height) / 2.0f) - realOffset.y);
|
|
//drawingOffset.x += leftOffset;
|
|
//drawingOffset.y += topOffset;
|
|
}
|
|
}
|
|
|
|
CGContextSetFillColorWithColor(context, _textColor.CGColor);
|
|
[_text drawAtPoint:drawingOffset withFont:_font];
|
|
}
|
|
else
|
|
{
|
|
CGContextSetTextDrawingMode(context, kCGTextClip);
|
|
|
|
[_text drawAtPoint:CGPointMake(CGFloor((bounds.size.width - _textSize.width) / 2.0f), CGFloor((bounds.size.height - _textSize.height) / 2.0f)) withFont:_font];
|
|
|
|
CGColorRef colors[2] = {
|
|
CGColorRetain(UIColorRGB(_topColor).CGColor),
|
|
CGColorRetain(UIColorRGB(_bottomColor).CGColor)
|
|
};
|
|
|
|
CFArrayRef colorsArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&colors, 2, NULL);
|
|
CGFloat locations[2] = {0.0f, 1.0f};
|
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorsArray, (CGFloat const *)&locations);
|
|
|
|
CFRelease(colorsArray);
|
|
CFRelease(colors[0]);
|
|
CFRelease(colors[1]);
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
|
|
CGContextDrawLinearGradient(context, gradient, CGPointMake(0.0f, 0.0f), CGPointMake(0.0f, bounds.size.height), 0);
|
|
|
|
CFRelease(gradient);
|
|
}
|
|
}
|
|
|
|
@end
|