// // glFont.m // CGL // // Created by kat on Sat Jun 15 2002. // Copyright (c) 2001 Katherine Tattersall. All rights reserved. // #import "NSGLFont.h" #define PI 3.141592653589793238462643383280 @implementation NSGLFont -(id) initFont: (NSString *)fontname atSize:(int)size { CGContextRef cg_context; // we do not need to keep a cg_context: only the data needs to be kept size_t bytesPerRow; // at least (width * bitsPerComponent * number of components + 7)/8 CGColorSpaceRef colorspace; // create with CGColorSpaceCreateDevice... functions CGImageAlphaInfo alphaInfo; // see CGImage for valid enum constants size_t bitsPerComponent; // must be 1,2,4 or 8 size_t num; // number of components const char *c_fontname; int i; // the first character we will need to draw is a ' '. The c-string of this is a space with a null terminator char jstr[2] = { ' ', '\0' }; max_height = 8; max_width = 8; c_fontname = [fontname cString]; font = [NSFont fontWithName:fontname size:size]; if( font == nil ) return nil; NSLog(@"font is being initialized"); [font retain]; // get tthe minimum width and height for the data for the characters while( max_width < [font maximumAdvancement].width ) max_width += 8; while( max_height < [font defaultLineHeightForFont] ) max_height += 8; // CGContexts in grey space are all 8 bits bitsPerComponent = 8; // Gray color space is chosen here only because it is easy to convert to a bitmap colorspace = CGColorSpaceCreateDeviceGray(); // We do not need any alpha information alphaInfo = kCGImageAlphaNone; // we need to ensure that we have the correct number of componants in the colorspace ( exactly 1 ) num = CGColorSpaceGetNumberOfComponents(colorspace); // we now generate max_chars contiguous lists base = glGenLists( max_chars ); // if any of the operations above have failed, we should not continue if( colorspace != nil) // to use the font, we'll need an unpack alignment of 1 // otherwise we'll get lines or other wierd things (but not the font) glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); for( i = 0; i < max_chars ; i++ ) // each character { height[i] = max_height; // we need to have a multiple of 8 in order to use my convertBitmap method width[i] = max_width ; // width* number of componants: should be 1 componant for CGColorSpaceCreateDeviceGray() bytesPerRow = width[i]*num; // must use CALLOC <- if not, memory may not be empty, leading to strange results in the drawings // space must be at least (bytesPerRow * height) data[i] = (void *) calloc( bytesPerRow, height[i] ); if( data[i] != nil ) // calloc was successful { // create the context cg_context = CGBitmapContextCreate(data[i], width[i], height[i], bitsPerComponent, bytesPerRow, colorspace, alphaInfo); if( cg_context != nil ) { // x_offset is the width of the character (null terminated cString to NSString) + a bit of space // I don't know what this "bit of space" is called or I might be able to get it better x_offset[i] = (unsigned int)[font widthOfString: [NSString stringWithCString: jstr]] + 1; // draw the current letter [self drawLetter:jstr[0] context:cg_context atx:0 withFont:c_fontname atSize:size]; CGContextRelease(cg_context); } else NSLog(@"NSGLFont init ERROR: Didn't create CGContext[%d]",i); } // create a BITMAP (as opposed to the Apple BYTEMAP CGBitmapContextRef) [self convertBitmap:i]; jstr[0]++; glNewList( base+i,GL_COMPILE); // compile the following glBitmap(width[i],height[i],0,0,x_offset[i],0,data[i]); glEndList(); } return self; } -(void) drawLetter:(char) ch context: (CGContextRef)cg_context atx:(int)xpos withFont:(const char *)fontname atSize:(int)size { // OpenGL will draw these upside down if we don't do this CGContextTranslateCTM( cg_context, 0, max_height ); CGContextScaleCTM( cg_context, 1.0,-1.0); // set the gray fill color to 1,1 which will make the bitmap work properly CGContextSetGrayFillColor(cg_context, 1.0, 1.0); // if you're doing a glDrawPixel, then leave this on // using glBitmap means converting to a bit image, and antialiasing that doesn't really work CGContextSetShouldAntialias(cg_context, 0 ); // some fonts don't work very well, like "Courier" // they are drawn very strangely CGContextSelectFont(cg_context, fontname, size, kCGEncodingMacRoman ); CGContextSetTextDrawingMode(cg_context, kCGTextFill); // draw exactly one glyph into the context CGContextShowTextAtPoint(cg_context, xpos, -[font descender], &ch, 1); } // clean up the memory -(void) dealloc { int i; for( i=0; i