4
#import "VertexArray.h"
6
#import <OpenGLES/ES2/gl.h>
7
#import <CoreGraphics/CoreGraphics.h>
10
// The following is a NSBezierPath category to allow
11
// for rounded corners of the border
17
@implementation GLQuartzTexture
21
if (!(self = [super init]))
37
[GLResourceDisposal disposeOfResourcesWithTypes: texName, GL_TEXTURE, NULL];
42
- (void) deleteTexture
46
glDeleteTextures(1, &texName);
49
textureSize = CGSizeZero;
53
- (void) freeGLResources
58
- (void) updateTextureIfRequired
68
glBindTexture(GL_TEXTURE_2D, texName);
71
- (void) setAntialias:(BOOL)request
77
- (void) setSubpixelAA:(BOOL)request
83
- (void) setFilterTexture:(BOOL)request
85
filterTexture = request;
89
- (void) setMipmapTexture:(BOOL)request
91
mipmapTexture = request;
95
- (void) setTexturePadding:(double)rad
101
- (void) doQuartzDrawingInContext: (CGContextRef) context sized: (CGSize) imgSize
105
- (void) generateTextureSized: (CGSize) texSize; // generates the texture without drawing texture to current context
107
CGSize previousSize = textureSize;
109
int width = texSize.width;
110
int height = texSize.height;
112
void* spriteData = calloc(1, width * height * 4);
115
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
116
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast);
117
assert(spriteContext);
119
UIGraphicsPushContext(spriteContext);
121
CGContextSetShouldSmoothFonts(spriteContext, subpixelAA);
123
[self doQuartzDrawingInContext: spriteContext sized: texSize];
125
UIGraphicsPopContext();
126
CGContextRelease(spriteContext);
127
CGColorSpaceRelease(colorSpace);
130
glGenTextures(1, &texName);
131
glBindTexture(GL_TEXTURE_2D, texName);
133
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
137
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
138
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
141
glGenerateMipmap(GL_TEXTURE_2D);
142
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterTexture ? (mipmapTexture ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) : GL_NEAREST);
144
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterTexture ? GL_LINEAR : GL_NEAREST);
146
textureSize = texSize;
151
- (CGSize) updatedTextureSize
158
[self generateTextureSized: [self updatedTextureSize]];
161
- (CGSize) textureSize
164
return [self updatedTextureSize];
169
- (void) drawWithBounds:(CGRect)bounds
171
[self updateTextureIfRequired];
176
//glDisable (GL_DEPTH_TEST); // ensure text is not remove by depth buffer test.
177
//glEnable (GL_BLEND); // for text fading
178
//glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // ditto
179
glEnable (GL_TEXTURE_2D);
181
glBindTexture (GL_TEXTURE_2D, [self texName]);
183
[[VertexArray sharedQuad] draw];
188
- (void) drawAtPoint:(CGPoint)point scaled: (double) scale
190
[self drawWithBounds: CGRectMake(point.x-[self texturePadding]*scale, point.y-[self texturePadding]*scale, [self textureSize].width*scale, [self textureSize].height*scale)];
192
- (void) drawAtPoint:(CGPoint)point
194
[self drawAtPoint: point scaled: 1.0];
197
- (void) drawCenteredAtPoint:(CGPoint)point scaled: (double) scale
199
[self drawWithBounds: CGRectMake(point.x-0.5*[self textureSize].width*scale, point.y-0.5*[self textureSize].height*scale, [self textureSize].width*scale, [self textureSize].height*scale)];
201
- (void) drawCenteredAtPoint:(CGPoint)point
203
[self drawCenteredAtPoint: point scaled: 1.0];
207
@synthesize antialias, subpixelAA, texturePadding, filterTexture, mipmapTexture, textureSize, texName;
213
@implementation GLQuartzBox
217
if (!(self = [super init]))
222
// borderColor = [NSColor clearColor];
227
CGPathRef CGPathWithRoundedRect(CGRect rect, CGFloat r)
229
CGMutablePathRef path = CGPathCreateMutable();
230
CGPathMoveToPoint(path, NULL,
231
rect.origin.x + rect.size.width - r, rect.origin.y);
232
CGPathAddArcToPoint(path, NULL,
233
rect.origin.x + rect.size.width, rect.origin.y,
234
rect.origin.x + rect.size.width, rect.origin.y + r, r);
235
CGPathAddLineToPoint(path, NULL,
236
rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - r);
237
CGPathAddArcToPoint(path, NULL,
238
rect.origin.x + rect.size.width, rect.origin.y + rect.size.height,
239
rect.origin.x + rect.size.width - r, rect.origin.y + rect.size.height, r);
240
CGPathAddLineToPoint(path, NULL,
241
rect.origin.x + r, rect.origin.y + rect.size.height);
242
CGPathAddArcToPoint(path, NULL,
243
rect.origin.x, rect.origin.y + rect.size.height,
244
rect.origin.x, rect.origin.y + rect.size.height - r, r);
245
CGPathAddLineToPoint(path, NULL,
246
rect.origin.x, rect.origin.y + r);
247
CGPathAddArcToPoint(path, NULL,
248
rect.origin.x, rect.origin.y,
249
rect.origin.x + r, rect.origin.y, r);
250
CGPathAddLineToPoint(path, NULL,
251
rect.origin.x + r, rect.origin.y);
253
CGPathCloseSubpath(path);
257
- (void) doQuartzDrawingInContext: (CGContextRef) context sized: (CGSize) imgSize
259
float borderAlpha = 0.0;
260
float boxAlpha = 0.0;
263
borderAlpha = CGColorGetAlpha([borderColor CGColor]);
265
boxAlpha = CGColorGetAlpha([boxColor CGColor]);
267
double bw = (borderAlpha ? borderWidth : 0.0);
270
{ // this should be == 0.0f but need to make sure
272
CGPathRef path = CGPathWithRoundedRect(CGRectInset(CGRectMake(texturePadding, texturePadding, frameSize.width, frameSize.height), 0.5*borderWidth, 0.5*borderWidth), cornerRadius);
273
CGContextAddPath(context, path);
274
CGContextDrawPath(context, kCGPathFill);
280
CGPathRef path = CGPathWithRoundedRect(CGRectInset(CGRectMake(texturePadding, texturePadding, frameSize.width, frameSize.height), 0.5*borderWidth, 0.5*borderWidth), cornerRadius);
282
CGContextAddPath(context, path);
283
CGContextSetLineWidth(context, bw);
284
CGContextDrawPath(context, kCGPathStroke);
289
- (CGSize) updatedTextureSize
291
CGSize texSize = CGSizeMake(ceil(frameSize.width+2.0*texturePadding), ceil(frameSize.height+2.0*texturePadding));
295
- (void) setBoxColor:(UIColor *)color // set default text color
297
[boxColor autorelease];
298
boxColor = [color retain];
299
requiresUpdate = YES;
303
- (void) setBorderColor:(UIColor *)color // set default text color
305
[borderColor autorelease];
306
borderColor = [color retain];
307
requiresUpdate = YES;
310
- (void) setCornerRadius:(double)rad
313
requiresUpdate = YES;
316
- (void) setBorderWidth:(double)rad
319
requiresUpdate = YES;
322
@synthesize cornerRadius, borderWidth, boxColor, borderColor, frameSize;
328
@implementation GLQuartzArc
332
if (!(self = [super init]))
343
- (void) doQuartzDrawingInContext: (CGContextRef) context sized: (CGSize) imgSize // generates the texture without drawing texture to current context
345
double bw = (CGColorGetAlpha([borderColor CGColor]) ? borderWidth : 0.0);
347
// double meanRadius = 0.5*(innerRadius+outerRadius);
348
// double rdiff = (outerRadius-innerRadius);
349
double angleRange = endAngle - startAngle;
350
// double innerOffset = texturePadding + rdiff;
352
double cornerCenterRadius = outerRadius - cornerRadius;
353
double cornerAngle = cornerRadius/cornerCenterRadius;
355
BOOL fullCircle = (angleRange > 2.0*M_PI*(1.0-FLT_EPSILON));
360
cornerCenterRadius = outerRadius;
361
endAngle = 2.0*M_PI + startAngle;
364
double startArc = startAngle + cornerAngle;
365
double endArc = endAngle - cornerAngle;
367
CGPoint center = CGPointMake(imgSize.width*0.5, imgSize.height*0.5);
369
CGMutablePathRef path = CGPathCreateMutable();
370
// [path setLineJoinStyle: NSRoundLineJoinStyle];
371
// [path setLineJoinStyle: NSBevelLineJoinStyle];
373
CGPathMoveToPoint(path, NULL, center.x + cos(startAngle)*cornerCenterRadius, center.y + sin(startAngle)*cornerCenterRadius);
375
double startArcDegrees = 180.0/M_PI*startArc;
376
double endArcDegrees = 180.0/M_PI*endArc;
377
double startAngleDegrees = 180.0/M_PI*startAngle;
378
double endAngleDegrees = 180.0/M_PI*endAngle;
380
if (!fullCircle && (cornerRadius > 0.0))
382
CGPoint cc = CGPointMake(center.x + cos(startArc)*cornerCenterRadius, center.y + sin(startArc)*cornerCenterRadius);
383
CGPathAddArc(path, NULL, cc.x, cc.y, cornerRadius, startAngleDegrees - 90.0, startArcDegrees, NO);
386
CGPathAddArc(path, NULL, center.x, center.y, cornerRadius, startArcDegrees, endArcDegrees, NO);
388
if (!fullCircle && (cornerRadius > 0.0))
390
CGPoint cc = CGPointMake(center.x + cos(endArc)*cornerCenterRadius, center.y + sin(endArc)*cornerCenterRadius);
391
CGPathAddArc(path, NULL, cc.x, cc.y, cornerRadius, endAngleDegrees, endArcDegrees + 90, NO);
395
if (innerRadius > 0.0)
399
CGPathCloseSubpath(path);
400
CGPathMoveToPoint(path, NULL, center.x + cos(endArc)*innerRadius, center.y + sin(endArc)*innerRadius);
403
CGPathAddArc(path, NULL, center.x, center.y, innerRadius, endArcDegrees, startArcDegrees, YES);
407
else if (!fullCircle)
408
CGPathAddLineToPoint(path, NULL, center.x, center.y);
410
CGPathCloseSubpath(path);
412
if (CGColorGetAlpha([fillColor CGColor]))
413
{ // this should be == 0.0f but need to make sure
415
CGContextAddPath(context, path);
416
CGContextDrawPath(context, kCGPathFill);
419
if (CGColorGetAlpha([borderColor CGColor]))
422
CGContextSetLineWidth(context, bw);
423
CGContextAddPath(context, path);
424
CGContextDrawPath(context, kCGPathStroke);
429
- (CGSize) updatedTextureSize
431
CGSize texSize = CGSizeMake(ceil(2.0*outerRadius+2.0*texturePadding), ceil(2.0*outerRadius+2.0*texturePadding));
435
- (void) setFillColor:(UIColor *)color
437
[fillColor autorelease];
438
fillColor = [color retain];
439
requiresUpdate = YES;
443
- (void) setBorderColor:(UIColor *)color
445
[borderColor autorelease];
446
borderColor = [color retain];
447
requiresUpdate = YES;
450
- (void) setOuterRadius:(double)rad
453
requiresUpdate = YES;
456
- (void) setInnerRadius:(double)rad
459
requiresUpdate = YES;
462
- (void) setBorderWidth:(double)rad
465
requiresUpdate = YES;
468
- (void) setCornerRadius:(double)rad
471
requiresUpdate = YES;
474
- (void) setStartAngle:(double)rad
477
requiresUpdate = YES;
480
- (void) setEndAngle:(double)rad
483
requiresUpdate = YES;
486
@synthesize innerRadius, outerRadius, startAngle, endAngle, borderWidth, cornerRadius, fillColor, borderColor;
492
@implementation GLString
494
+ (UIFont*) defaultFont
496
UIFont* font = [UIFont systemFontOfSize: [UIFont systemFontSize]];
502
#pragma mark Initializers
504
// designated initializer
505
- (id) initWithString:(NSString *)aString withFont: (UIFont*) aFont withTextColor:(UIColor *)text withBoxColor:(UIColor *)box withBorderColor:(UIColor *)border
507
if (!(self = [super init]))
512
font = [aFont retain];
514
self.textColor = text;
516
self.borderColor = border;
518
marginSize.width = 4.0f; // standard margins
519
marginSize.height = 2.0f;
524
// basic methods that pick up defaults
525
- (id) initWithString:(NSString *)astring;
527
return [self initWithString: astring withFont: [GLString defaultFont] withTextColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f] withBoxColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:0.0f] withBorderColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:0.0f]];
530
- (id) initWithString:(NSString *)aString withFont:(UIFont *)aFont
532
return [self initWithString: aString withFont: aFont withTextColor: nil withBoxColor: nil withBorderColor: nil];
537
if (NO == staticFrame)
538
{ // find frame size if we have not already found it
539
frameSize = [string sizeWithFont: font]; // current string size
540
frameSize.width += marginSize.width * 2.0f; // add padding
541
frameSize.height += marginSize.height * 2.0f;
546
- (CGSize) updatedTextureSize
548
if (NO == staticFrame)
549
{ // find frame size if we have not already found it
550
frameSize = [string sizeWithFont: font]; // current string size
551
frameSize.width += marginSize.width * 2.0f; // add padding
552
frameSize.height += marginSize.height * 2.0f;
554
return [super updatedTextureSize];
557
- (void) doQuartzDrawingInContext: (CGContextRef) context sized: (CGSize) imgSize // generates the texture without drawing texture to current context
560
[super doQuartzDrawingInContext: context sized: imgSize];
563
[string drawAtPoint: CGPointMake(marginSize.width+texturePadding, marginSize.height+texturePadding) withFont: font]; // draw at offset position
567
- (void) setTextColor:(UIColor *)color // set default text color
569
[textColor autorelease];
570
textColor = [color retain];
571
requiresUpdate = YES;
575
#pragma mark Margin Size
577
// these will force the texture to be regenerated at the next draw
578
- (void) setMargins:(CGSize)size // set offset size and size to fit with offset
581
if (NO == staticFrame) { // ensure dynamic frame sizes will be recalculated
582
frameSize.width = 0.0f;
583
frameSize.height = 0.0f;
585
requiresUpdate = YES;
588
- (CGSize) marginSize
602
- (void) useStaticFrame:(CGSize)size // set static frame size and size to frame
604
requiresUpdate = requiresUpdate || !staticFrame || !CGSizeEqualToSize(frameSize,size);
609
- (void) useDynamicFrame
611
if (staticFrame) { // set to dynamic frame and set to regen texture
613
frameSize.width = 0.0f; // ensure frame sizes will be recalculated
614
frameSize.height = 0.0f;
615
requiresUpdate = YES;
621
- (void) setString:(NSString *)theString // set string after initial creation
623
[string autorelease];
624
string = [theString copy];
625
if (NO == staticFrame) { // ensure dynamic frame sizes will be recalculated
626
frameSize.width = 0.0f;
627
frameSize.height = 0.0f;
629
requiresUpdate = YES;
632
- (void) setFont: (UIFont*) aFont
635
font = [aFont retain];
636
if (NO == staticFrame) { // ensure dynamic frame sizes will be recalculated
637
frameSize.width = 0.0f;
638
frameSize.height = 0.0f;
640
requiresUpdate = YES;
643
@synthesize textColor;