Changeset 80
- Timestamp:
- 07/20/08 15:45:47 (4 months ago)
- Files:
-
- trunk/yage/gui/surface.d (modified) (1 diff)
- trunk/yage/resource/font.d (modified) (7 diffs)
- trunk/yage/resource/resource.d (modified) (1 diff)
- trunk/yage/resource/texture.d (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/yage/gui/surface.d
r79 r80 333 333 // Todo: check style font properties for changes also. 334 334 if (style.fontFamily && text != old_text) 335 { Timer a = new Timer();336 textImage = style.fontFamily.render(text, cast(int)style.fontSize, cast(int)style.fontSize, -1, -1, true);337 writefln(a, textImage.getWidth(), textImage.getHeight());338 a.reset();339 if (textTexture.texture)340 delete textTexture.texture;335 { textImage = style.fontFamily.render(text, cast(int)style.fontSize, cast(int)style.fontSize, -1, -1, true); 336 if (!textTexture.texture) 337 textTexture = Texture(new GPUTexture(textImage, false, false), true, TEXTURE_FILTER_BILINEAR); 338 else 339 textTexture.texture.upload(textImage, false, false); 340 old_text = text; 341 341 342 writefln(a);343 a.reset();344 textTexture = Texture(new GPUTexture(textImage, false, false), true, TEXTURE_FILTER_BILINEAR);345 346 writefln(a);347 348 old_text = text;349 342 } 350 343 trunk/yage/resource/font.d
r79 r80 9 9 import std.string; 10 10 import std.stdio; 11 import std.utf; 11 12 import derelict.freetype.ft; 12 13 import yage.core.math; 14 import yage.core.timer; 15 import yage.core.types; 16 import yage.core.parse; 13 17 import yage.resource.exception; 14 18 import yage.resource.resource; 15 19 import yage.resource.image; 20 import yage.resource.texture; 16 21 22 //Stores a single rendered letter. 23 private struct Letter 24 { Image image; 25 int top; 26 int left; 27 int advancex; 28 int advancey; 29 } 30 31 // Used as a key to lookup cached letters. 32 private struct Key 33 { dchar letter; 34 short width; 35 short height; 36 37 // Hash recognizes that most letters are two bytes or less, most sizes are one byte or less 38 hash_t toHash() 39 { return (cast(uint)letter<<16) + ((cast(uint)width)<<8) + (cast(uint)height); 40 } 41 int opEquals(Key s) 42 { return letter==s.letter && width==s.width && height==s.height; 43 } 44 int opCmp(Key s) 45 { return toHash() - s.toHash(); 46 } 47 } 48 49 /** 50 * An instance of a loaded Font. 51 * Fonts are typically used to render strings of text to an image. */ 17 52 class Font 18 53 { 19 static FT_Library library;20 static bool freetype_initialized = false;54 protected static FT_Library library; 55 protected static bool freetype_initialized = false; 21 56 22 char[] source; 23 FT_Face face; 57 protected FT_Face face; 58 protected char[] source; 59 protected Letter[Key] cache; // Using this cache of rendered character images increases performance by about 5x. 24 60 25 /// 61 /** 62 * Construct and load the font file specified by filename. 63 * Params: 64 * filename = Any font file supported by Freetype that exists in Resource.paths. */ 26 65 this(char[] filename) 27 66 { … … 29 68 // TODO: Move this into Device? 30 69 if (!freetype_initialized) 31 { if (FT_Init_FreeType(&library)) 32 throw new Exception("Freetype2 Failed"); 33 } 70 if (FT_Init_FreeType(&library)) 71 throw new Exception("Freetype2 Failed to load."); 34 72 35 73 // Load … … 44 82 /// 45 83 ~this() 46 { // / TODO: cleanup.84 { // Do freetype libraries not require any type of cleanup? 47 85 } 48 86 … … 50 88 /** 51 89 * Render an image from text. 90 * TODO: Fix text from Right-to-Left languages from being rendered backwards. 52 91 * Params: 53 * text = 54 * width = 55 * height = 56 * line_width = Letters will wrap to the next line after this amount (breaking on spaces) 57 * line_height = This much space will occur between each line, defaults to 1.5x height. 58 * image_pow2 = If true, the image returned will always have its dimensions as powers of two. 59 * Returns: 60 */ 61 Image render(char[] text, int width, int height=0, int line_width=-1, int line_height=-1, bool image_pow2=false) 62 { 92 * text = A string of text to render, can be utf-8 or unencoded unicode (dchar[]). 93 * width = The horizontal pixel size of the font to render. 94 * height = The vertical pixel size of the font to render, if 0 it will be the same as the width. 95 * line_width = Letters will wrap to the next line after this amount (breaking on spaces), unsupported 96 * line_height = This much space will occur between each line, defaults to 1.5x height, unsupported 97 * image_pow2 = If true, the image returned will always have its dimensions as powers of two. */ 98 Image render(char[] utf8, int width, int height=0, int line_width=-1, int line_height=-1, bool image_pow2=false) 99 { dchar[] unicode = toUTF32(utf8); 100 Image result = render(unicode, width, height, line_width, line_height, image_pow2); 101 delete unicode; 102 return result; 103 } 104 105 /// ditto 106 Image render(dchar[] text, int width, int height=0, int line_width=-1, int line_height=-1, bool image_pow2=false) 107 { 63 108 // Calculate parameters 64 109 if (line_height==-1) … … 70 115 auto error = FT_Set_Pixel_Sizes(face, width, height); // face, pixel width, pixel height 71 116 if (error) 72 throw new Exception( "Invalid font size.");117 throw new Exception(formatString("Font '%s' does not support pixel sizes of %dx%d.", source, width, height)); 73 118 74 // Stores a single rendered letter. 75 struct Letter 76 { Image image; 77 int advancex; 78 int advancey; // unnecessary? 79 int top; 80 int left; 81 } 82 83 Letter[] letters; // array of all rendered letters. 119 /* 120 * First, we render (or retrieve from cache) all letters into an array of Letter. 121 * This allows us to calculate dimensinal information like total width/height, number of lines etc. 122 * We then allocate an image of appropriate size, composite the letters onto it, and then return it. */ 123 Letter[] letters; 84 124 int total_width = 0; 85 125 int total_height = 0; … … 89 129 // Create a glyph for each letter and store its parameters 90 130 foreach (c; text) 91 { 92 error = FT_Load_Char(face, c, FT_LOAD_RENDER); // Load into slot 93 if (error) 94 throw new Exception("Font Error."); 131 { 132 Key key = Key(c, width, height); 133 Letter letter; 134 if (key in cache) 135 letter = cache[key]; 136 else 137 { // Render the character into the glyph slot. 138 error = FT_Load_Char(face, c, FT_LOAD_RENDER); 139 if (error) 140 throw new Exception("Font '"~source~"' cannot render the character '"~toUTF8([c])~"'."); 141 142 auto bitmap = face.glyph.bitmap; 143 ubyte[] data = (cast(ubyte*)bitmap.buffer)[0..(bitmap.width*bitmap.rows)]; 144 145 // Set the values of the letter. 146 letter.image = new Image(data.dup, 1, bitmap.width, bitmap.rows); 147 letter.top = face.glyph.bitmap_top; 148 letter.left = face.glyph.bitmap_left; 149 letter.advancex = face.glyph.advance.x>>6; 150 letter.advancey = face.glyph.advance.y>>6; 151 152 cache[key] = letter; 153 } 95 154 96 auto bitmap = face.glyph.bitmap;97 ubyte[] data = (cast(ubyte*)bitmap.buffer)[0..(bitmap.width*bitmap.rows)];98 99 // Set the values of the100 Letter letter;101 letter.image = new Image(data.dup, 1, bitmap.width, bitmap.rows);102 letter.top = face.glyph.bitmap_top;103 letter.left = face.glyph.bitmap_left;104 letter.advancex = total_width;105 letter.advancey = total_height;106 155 letters ~= letter; 107 108 total_width+= face.glyph.advance.x>>6; 109 total_height+= face.glyph.advance.y>>6; 156 total_width+= letter.advancex; 157 total_height+= letter.advancey; 110 158 } 111 159 … … 116 164 int img_height = image_pow2 ? nextPow2(line_height*lines) : line_height*lines; 117 165 Image result = new Image(1, img_width, img_height); 166 167 int advancex=0, advancey=0; 118 168 for (int i=0; i<letters.length; i++) 119 { result.overlay(letters[i].image, letters[i].advancex+letters[i].left, (letters[i].advancey-letters[i].top+height)); 120 delete letters[i].image; 169 { result.overlay(letters[i].image, advancex+letters[i].left, (advancey-letters[i].top+height)); 170 advancex+= letters[i].advancex; 171 advancey+= letters[i].advancey; 121 172 } 173 delete letters; 122 174 123 175 return result; trunk/yage/resource/resource.d
r79 r80 41 41 42 42 /// Get the array of path strings 43 static char[][] getPath ()43 static char[][] getPaths() 44 44 { return paths; 45 45 } trunk/yage/resource/texture.d
r79 r80 305 305 // glu has resizing issues with non power of two source textures. 306 306 if (mipmap) 307 { //writefln(GL_TEXTURE_2D, " ", glinternalformat, " ", image.getWidth(), " ", image.getHeight(), " ", glformat, " ", GL_UNSIGNED_BYTE, " ", image.getData().length); 308 gluBuild2DMipmaps(GL_TEXTURE_2D, glinternalformat, image.getWidth(), image.getHeight(), glformat, GL_UNSIGNED_BYTE, image.getData().ptr); 309 } 310 else 307 gluBuild2DMipmaps(GL_TEXTURE_2D, glinternalformat, image.getWidth(), image.getHeight(), glformat, GL_UNSIGNED_BYTE, image.getData().ptr); 308 else 311 309 { 312 310 uint max = Device.getLimit(DEVICE_MAX_TEXTURE_SIZE); … … 325 323 // Resize if necessary 326 324 if (newwidth != width || newheight != height) 327 image = image.resize(min(newwidth, max), min(newheight, max)); 325 image = image.resize(min(newwidth, max), min(newheight, max)); 328 326 glTexImage2D(GL_TEXTURE_2D, 0, glinternalformat, image.getWidth(), image.getHeight(), 0, glformat, GL_UNSIGNED_BYTE, image.getData().ptr); 329 330 } 327 } 331 328 if(this.requested_width == 0) this.requested_width = this.getWidth(); 332 329 if(this.requested_height == 0) this.requested_height = this.getHeight();
