/* -*- Objc -*- */ /* * $Id: UiText.m,v 1.1 2003/05/27 22:21:39 dam Exp $ * * Copyright (C) 2003 Free Software Foundation, Inc. * * This file is part of GNU Hégémonie. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include FT_FREETYPE_H #include FT_GLYPH_H #include #include "Interface/UiText.h" @interface UiGlyph : NSObject { @private FT_Glyph _glyph; FT_Vector _position; } + (id) glyphWithGlyph: (FT_Glyph)glyph position: (FT_Vector)position; - (id) initWithGlyph: (FT_Glyph)glyph position: (FT_Vector)position; - (FT_Glyph) glyph; - (FT_Vector) position; @end @implementation UiGlyph + (id) glyphWithGlyph: (FT_Glyph)glyph position: (FT_Vector)position { return AUTORELEASE ([[UiGlyph alloc] initWithGlyph: glyph position: position]); } - (id) initWithGlyph: (FT_Glyph)glyph position: (FT_Vector)position { self = [super init]; if (self != nil) { _glyph = glyph; _position = position; } return self; } - (FT_Glyph) glyph { return _glyph; } - (FT_Vector) position { return _position; } @end @implementation UiText static FT_Library _library; static FT_Face _face; + (void) initialize { if (FT_Init_FreeType (&_library)) { abort (); } if (FT_New_Face (_library, "vera.ttf", 0, &_face)) { abort (); } } - (void) _initGlyphesWithText: (NSString *)text { FT_GlyphSlot slot = _face->glyph; FT_Bool use_kerning = FT_HAS_KERNING(_face); FT_UInt previous = 0; FT_Vector pen = {0, 0}; NSParameterAssert (text); NSParameterAssert ([text length] != 0); int i; for (i = 0; i < [text length]; i++) { FT_UInt glyph_index; FT_Glyph glyph; glyph_index = FT_Get_Char_Index (_face, [text characterAtIndex: i]); if (use_kerning && previous && glyph_index) { FT_Vector delta; FT_Get_Kerning (_face, previous, glyph_index, ft_kerning_default, &delta); pen.x += delta.x >> 6; } if (FT_Load_Glyph (_face, glyph_index, FT_LOAD_DEFAULT)) continue; if (FT_Get_Glyph (_face->glyph, &glyph)) continue; [_glyphes addObject: [UiGlyph glyphWithGlyph: glyph position: pen]]; pen.x += slot->advance.x >> 6; previous = glyph_index; } } - (id) initWithText: (NSString *)text { NSParameterAssert (text); NSParameterAssert ([text length] != 0); self = [super init]; if (self != nil) { _glyphes = [NSMutableArray arrayWithCapacity: [text length]]; [self _initGlyphesWithText: text]; } return self; } static void _draw_bitmap (const FT_Bitmap *bitmap, FT_Int left, FT_Int top) { NSCParameterAssert (bitmap); NSCParameterAssert (bitmap->pixel_mode == FT_PIXEL_MODE_GRAY); glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, bitmap->width, bitmap->rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap->buffer); glEnable (GL_TEXTURE_2D); glBegin (GL_POLYGON); glTexCoord2f (0.0, 0.0); glVertex2f (0.0, 0.0); glTexCoord2f (1.0, 0.0); glVertex2f (1.0, 0.0); glTexCoord2f (1.0, 1.0); glVertex2f (1.0, 1.0); glTexCoord2f (0.0, 1.0); glVertex2f (0.0, 1.0); glEnd (); glDisable (GL_TEXTURE_2D); } - (void) display { NSEnumerator *enumerator = [_glyphes objectEnumerator]; UiGlyph *glyph; while ((glyph = [enumerator nextObject])) { FT_Glyph image = [glyph glyph]; FT_Vector pen = [glyph position]; if (FT_Glyph_To_Bitmap (&image, ft_render_mode_normal, &pen, 0)) continue; FT_BitmapGlyph bit = (FT_BitmapGlyph)image; _draw_bitmap (&bit->bitmap, bit->left, bit->top); FT_Done_Glyph (image); } } - (NSSize) size { FT_BBox bbox = {0, 0, 0, 0}; NSEnumerator *enumerator = [_glyphes objectEnumerator]; UiGlyph *glyph; while ((glyph = [enumerator nextObject])) { FT_BBox glyph_bbox; FT_Glyph_Get_CBox ([glyph glyph], ft_glyph_bbox_pixels, &glyph_bbox); glyph_bbox.xMin += [glyph position].x; glyph_bbox.xMax += [glyph position].x; glyph_bbox.yMin += [glyph position].y; glyph_bbox.yMax += [glyph position].y; bbox.xMin = MIN(bbox.xMin, glyph_bbox.xMin); bbox.yMin = MIN(bbox.yMin, glyph_bbox.yMin); bbox.xMax = MAX(bbox.xMax, glyph_bbox.xMax); bbox.yMax = MAX(bbox.yMax, glyph_bbox.yMax); } NSParameterAssert (bbox.xMin == 0); NSParameterAssert (bbox.yMin == 0); return NSMakeSize ((bbox.xMax - bbox.xMin), (bbox.yMax - bbox.yMin)); } @end