1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-04 10:27:46 +01:00
Telegram/legacy/TelegraphKit/TGGradientLabel.m
2015-10-01 19:19:52 +03:00

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