void Quad::refresh(const Viewport &v, float sw, float sh) { if (!GLEE_ARB_texture_non_power_of_two) { sw = next_p2(sw); sh = next_p2(sh); } viewport = v; vertices[0].x = 0; vertices[0].y = 0; vertices[1].x = 0; vertices[1].y = v.h; vertices[2].x = v.w; vertices[2].y = v.h; vertices[3].x = v.w; vertices[3].y = 0; vertices[0].s = v.x/sw; vertices[0].t = v.y/sh; vertices[1].s = v.x/sw; vertices[1].t = (v.y+v.h)/sh; vertices[2].s = (v.x+v.w)/sw; vertices[2].t = (v.y+v.h)/sh; vertices[3].s = (v.x+v.w)/sw; vertices[3].t = v.y/sh; }
bool CFont2D::LoadFont(const char * FontName,int FontSizeW,int FontSizeH,int FontW,int FontH,int CHARSET) { glEnable( GL_TEXTURE_2D ); FontTexW=next_p2(FontW); FontTexH=next_p2(FontH); OnefontW=FontTexW/MAXNUMX; OnefontH=FontTexH/MAXNUMX; FontCharSet=CHARSET; if (FT_Init_FreeType( &library )) return false; if (FT_New_Face( library, FontName, 0, &face )) return false; if(FontSizeW<32) FT_Set_Char_Size( face, FontSizeW << 6, FontSizeH << 6, 66, 64); else FT_Set_Pixel_Sizes(face, min(FontSizeW,FontTexW/MAXNUMX), min(FontSizeH,FontTexH/MAXNUMX)); unsigned char* data; data =new unsigned char[FontTexW*FontTexH*2]; ZeroMemory(data,FontTexW*FontTexH*2); glGenTextures( 1, &TexID ); glBindTexture(GL_TEXTURE_2D, TexID); // glTexImage2D(GL_TEXTURE_2D,0, GL_ALPHA, FontTexW, FontTexH, 0,GL_ALPHA, GL_UNSIGNED_BYTE, data); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); delete [] data; OnefontData = new unsigned char[OnefontW*OnefontH]; return true; }
void Image::checkMipmapsCreated() const { if (filter.mipmap != FILTER_NEAREST && filter.mipmap != FILTER_LINEAR) return; if (!hasMipmapSupport()) throw love::Exception("Mipmap filtering is not supported on this system!"); // some old GPUs/systems claim support for NPOT textures, but fail when generating mipmaps // we can't detect which systems will do this, so we fail gracefully for all NPOT images int w = int(width), h = int(height); if (w != next_p2(w) || h != next_p2(h)) throw love::Exception("Could not generate mipmaps: image does not have power of two dimensions!"); bind(); GLint mipmapscreated; glGetTexParameteriv(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, &mipmapscreated); // generate mipmaps for this image if we haven't already if (!mipmapscreated) { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object) glGenerateMipmap(GL_TEXTURE_2D); else if (GLEE_EXT_framebuffer_object) glGenerateMipmapEXT(GL_TEXTURE_2D); else // modify single texel to trigger mipmap chain generation glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data->getData()); } }
Uint32 *texturaPotencia2(Uint32 *pixels, int w, int h, int *width, int *height) { int j, i; *width = next_p2(w); *height = next_p2(h); Uint32 *expanded_data = (Uint32 *) malloc(*width * *height * sizeof(Uint32)); for(j=0; j < *height;j++) { for(i=0; i < *width; i++){ expanded_data[i + j * *width] = (i>=w || j>=h) ? 0 : pixels[i + j*w]; } } return expanded_data; }
bool Image::loadVolatilePOT() { glGenTextures(1,(GLuint *)&texture); bindTexture(texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); float p2width = next_p2(width); float p2height = next_p2(height); float s = width/p2width; float t = height/p2height; vertices[1].t = t; vertices[2].t = t; vertices[2].s = s; vertices[3].s = s; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)p2width, (GLsizei)p2height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)width, (GLsizei)height, GL_RGBA, GL_UNSIGNED_BYTE, data->getData()); setMipmapSharpness(mipmapsharpness); setFilter(filter); setWrap(wrap); return true; }
void fontclean(font_data *ft_font) { if (ft_font == NULL) return; glDeleteLists(ft_font->list_base,next_p2(NUMCHARS)); if (ft_font->textures != NULL) { glDeleteTextures(NUMCHARS,ft_font->textures); } }
int64_t ceil_p2(int64_t x) { assert(x > 0); if (is_p2(x)) return x; return next_p2(x); }
_RIBS_INLINE_ int file_writer_init(struct file_writer *fw, const char *filename) { file_writer_close(fw); unlink(filename); fw->mem = NULL; fw->base_loc = fw->write_loc = 0; fw->fd = open(filename, O_RDWR | O_CREAT, 0644); fw->buffer_size = next_p2(fw->buffer_size); if (0 > fw->fd) return perror("open, file_writer_init"), -1; if (0 > ftruncate(fw->fd, fw->buffer_size)) return perror("ftruncate, file_writer_init"), -1; fw->mem = mmap(NULL, fw->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fw->fd, 0); if (MAP_FAILED == fw->mem) return perror("mmap, file_writer_init"), -1; fw->capacity = fw->buffer_size; fw->next_loc = fw->base_loc + fw->buffer_size; return 0; }
void make_dlist (FT_Face face, char ch, GLuint list_base, GLuint * tex_base) { // Load The Glyph For Our Character. if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT )) throw std::runtime_error("FT_Load_Glyph failed"); // Move The Face's Glyph Into A Glyph Object. FT_Glyph glyph; if(FT_Get_Glyph( face->glyph, &glyph )) throw std::runtime_error("FT_Get_Glyph failed"); // Convert The Glyph To A Bitmap. FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; // This Reference Will Make Accessing The Bitmap Easier. FT_Bitmap& bitmap=bitmap_glyph->bitmap; // Use Our Helper Function To Get The Widths Of // The Bitmap Data That We Will Need In Order To Create // Our Texture. int width = next_p2( bitmap.width ); int height = next_p2( bitmap.rows ); // Allocate Memory For The Texture Data. GLubyte* expanded_data = new GLubyte[ 2 * width * height]; for(int j=0; j <height;j++) { for(int i=0; i < width; i++){ expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j]; } } // Now We Just Setup Some Texture Parameters. glBindTexture( GL_TEXTURE_2D, tex_base[ch]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Here We Actually Create The Texture Itself, Notice // That We Are Using GL_LUMINANCE_ALPHA To Indicate That // We Are Using 2 Channel Data. glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data ); // With The Texture Created, We Don't Need The Expanded Data Anymore. delete [] expanded_data; // Now We Create The Display List glNewList(list_base+ch,GL_COMPILE); glBindTexture(GL_TEXTURE_2D,tex_base[ch]); glPushMatrix(); // First We Need To Move Over A Little So That // The Character Has The Right Amount Of Space // Between It And The One Before It. glTranslatef(bitmap_glyph->left,0,0); // Now We Move Down A Little In The Case That The // Bitmap Extends Past The Bottom Of The Line // This Is Only True For Characters Like 'g' Or 'y'. glTranslatef(0,bitmap_glyph->top-bitmap.rows,0); // Now We Need To Account For The Fact That Many Of // Our Textures Are Filled With Empty Padding Space. // We Figure What Portion Of The Texture Is Used By // The Actual Character And Store That Information In // The x And y Variables, Then When We Draw The // Quad, We Will Only Reference The Parts Of The Texture // That Contains The Character Itself. float x=(float)bitmap.width / (float)width, y=(float)bitmap.rows / (float)height; // Here We Draw The Texturemapped Quads. // The Bitmap That We Got From FreeType Was Not // Oriented Quite Like We Would Like It To Be, // But We Link The Texture To The Quad // In Such A Way That The Result Will Be Properly Aligned. glBegin(GL_QUADS); glTexCoord2d(0,0); glVertex2f(0,bitmap.rows); glTexCoord2d(0,y); glVertex2f(0,0); glTexCoord2d(x,y); glVertex2f(bitmap.width,0); glTexCoord2d(x,0); glVertex2f(bitmap.width,bitmap.rows); glEnd(); glPopMatrix(); glTranslatef(face->glyph->advance.x >> 6 ,0,0); // Increment The Raster Position As If We Were A Bitmap Font. // (Only Needed If You Want To Calculate Text Length) // glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL); // Finish The Display List glEndList(); }
bool Font::GenerateOpenglGlyphs( std::string configFileName) { unsigned int area = 0; Bitmap *bitmap; for (auto i = glyphsBitmapList.begin(); i != glyphsBitmapList.end(); i++) { bitmap = (*i).bitmap; area += bitmap->GetHeight() * bitmap->GetWidth(); } unsigned int sideAtlas = (unsigned int)(sqrt( float(area) )); sideAtlas = next_p2( sideAtlas ); float diff = float(sideAtlas * sideAtlas) / float(area); if( diff < 1.8f ) sideAtlas <<= 1; if(!glyphAtlas.Create(Bitmap::FORMAT_RGBA, sideAtlas, sideAtlas)) { //LOG_ERROR( return false; } glyphsBitmapList.sort(); iRect rect; Bitmap *atlasBitmap = glyphAtlas.GetAtlas(); for (auto i = glyphsBitmapList.begin(); i != glyphsBitmapList.end(); i++) { if( !glyphAtlas.InsertImage( (*i).bitmap, rect ) ) { //LOG(WARNING) << "font atlass ERROR"; delete (*i).bitmap; (*i).bitmap = nullptr; continue; } FontTexture fontTexture; fontTexture.width = (*i).bitmap->GetWidth(); fontTexture.height = (*i).bitmap->GetHeight(); fontTexture.offsetDown = (*i).offsetDown; GenerateTextCoord(atlasBitmap, &rect, fontTexture.texture); glyphsTextureMap[(*i).key] = fontTexture; delete (*i).bitmap; (*i).bitmap = nullptr; } // CreateAtlasOpenglTexture unsigned int ogltexture = GenerateOpenglBitmap(*atlasBitmap, false, false); tex = new Texture(); tex->textureId = ogltexture; tex->name = configFileName; tex->height = atlasBitmap->GetHeight(); tex->width = atlasBitmap->GetWidth(); for (auto i = glyphsTextureMap.begin(); i != glyphsTextureMap.end(); i++) { (*i).second.texture.textureId = ogltexture; } glyphsBitmapList.clear(); glyphAtlas.GetAtlas()->Save(configFileName+".png"); glyphAtlas.Remove(); return true; }
///Create a display list corresponding to the given character. ///glyph_id = actual font glyph id (32 bits), ch = id for printing to screen (16 bits) void font_data::make_dlist(uint glyph_id, ushort ch) { // get the texture reference m.alloc(ch); GLuint tex = m.get_t(ch); // Translate Win-1252 with additions to Unicode if (remapflag) { if (glyph_id >= 16 && glyph_id < 32) glyph_id = unichar_low[glyph_id-16]; else if (glyph_id >= 128 && glyph_id < 160) glyph_id = unichar_high[glyph_id-128]; } // Load the Glyph for our character. if (FT_Load_Glyph(face, FT_Get_Char_Index(face, glyph_id), FT_LOAD_DEFAULT)) throw std::runtime_error("FT_Load_Glyph failed"); // Move the face's glyph into a Glyph object. FT_Glyph glyph; if (FT_Get_Glyph(face->glyph, &glyph)) throw std::runtime_error("FT_Get_Glyph failed"); // Convert the glyph to a bitmap. FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph) glyph; // This reference will make accessing the bitmap easier FT_Bitmap& bitmap=bitmap_glyph->bitmap; // Use our helper function to get the widths of // the bitmap data that we will need in order to create // our texture. // The max(2, ...) is used to correct for OpenGL, which // apparently does not like to have rows less than 4 bytes // long. Probably a packing thing. int width = max(2, next_p2(bitmap.width)); int height = next_p2(bitmap.rows); // Allocate memory (temporarily) for the texture data. GLubyte* expanded_data = new GLubyte[2 * width * height]; // Here we fill in the data for the expanded bitmap. // Notice that we are using two channel bitmap (one for // luminocity and one for alpha). // Luma always 255. Alpha stays alpha. // (unless of course, it is premultiplied, which in OpenGL it is not.) // We use the ?: operator so that value which we use // will be 0 if we are in the padding zone, and whatever // is the Freetype bitmap otherwise. for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { expanded_data[ 2*(i+j*width) ] = 255; expanded_data[ 2*(i+j*width)+1 ] = (i >= bitmap.width || j >= bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j]; } } // Now we just setup some texture paramaters. glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Here we actually create the texture itself, notice // that we are using GL_LUMINANCE_ALPHA to indicate that // we are using 2 channel data. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); // With the texture created, we don't need the expanded data anymore delete [] expanded_data; // So now we can create the display list glNewList(list_base + ch, GL_COMPILE); glBindTexture(GL_TEXTURE_2D, tex); //glPushMatrix(); // First we need to move over a little so that // the character has the right amount of space // between it and the one before it. //glTranslatef((float) bitmap_glyph->left,0,0); // Now we move down a little in the case that the // bitmap extends past the bottom of the line // (this is only true for characters like 'g' or 'y'. //glTranslatef(0,(float)bitmap_glyph->top-bitmap.rows,0); float left_pad = (float) bitmap_glyph->left; float bot_pad = (float) bitmap.rows-bitmap_glyph->top; glTranslatef(left_pad, -bot_pad, 0); // Now we need to account for the fact that many of // our textures are filled with empty padding space. // We figure what portion of the texture is used by // the actual character and store that information in // the x and y variables, then when we draw the // quad, we will only reference the parts of the texture // that we contain the character itself. float x = (float) bitmap.width / (float) width, y = (float) bitmap.rows / (float) height; // Here we draw the texturemapped quads. // The bitmap that we got from FreeType was not // oriented quite like we would like it to be, // so we need to link the texture to the quad // so that the result will be properly aligned. glBegin(GL_QUADS); glTexCoord2d(0, 0); glVertex2f(0, (float) bitmap.rows); glTexCoord2d(0, y); glVertex2f(0, 0); glTexCoord2d(x, y); glVertex2f((float) bitmap.width, 0); glTexCoord2d(x, 0); glVertex2f((float) bitmap.width, (float) bitmap.rows); glEnd(); //glPopMatrix(); // Get width, round, and translate short ch_width = (short)(face->glyph->linearHoriAdvance >> 16); if (face->glyph->linearHoriAdvance & 0x8000) ++ch_width; //glTranslatef(ch_width, 0, 0); glTranslatef(ch_width-left_pad, bot_pad, 0); // The two ways to do width: // face->glyph->linearHoriAdvance >> 16 // face->glyph->advance.x >> 6 // Finish the display list glEndList(); // Store the width of this character m.set_w(ch, ch_width); }
static void set_shader_num (ClutterActor *actor, gint new_no) { int tex_width; int tex_height; if (new_no >= 0 && shaders[new_no].name) { ClutterShader *shader; GError *error; shader_no = new_no; g_print ("setting shaders[%i] named '%s'\n", shader_no, shaders[shader_no].name); shader = clutter_shader_new (); error = NULL; g_object_set (G_OBJECT (shader), "fragment-source", shaders[shader_no].source, NULL); /* try to bind the shader, provoking an error we catch if there is issues * with the shader sources we've provided. At a later stage it should be * possible to iterate through a set of alternate shader sources (glsl -> * asm -> cg?) and the one that succesfully compiles is used. */ clutter_shader_compile (shader, &error); if (error) { g_print ("unable to set shaders[%i] named '%s': %s", shader_no, shaders[shader_no].name, error->message); g_error_free (error); clutter_actor_set_shader (actor, NULL); } else { clutter_actor_set_shader (actor, NULL); clutter_actor_set_shader (actor, shader); clutter_actor_set_shader_param_int (actor, "tex", 0); clutter_actor_set_shader_param_float (actor, "radius", 3.0); clutter_actor_set_shader_param_float (actor, "brightness", 0.4); clutter_actor_set_shader_param_float (actor, "contrast", -1.9); if (CLUTTER_IS_TEXTURE (actor)) { /* XXX - this assumes *a lot* about how things are done * internally on *some* hardware and driver */ tex_width = clutter_actor_get_width (actor); tex_width = next_p2 (tex_width); tex_height = clutter_actor_get_height (actor); tex_height = next_p2 (tex_height); clutter_actor_set_shader_param_float (actor, "x_step", 1.0f / tex_width); clutter_actor_set_shader_param_float (actor, "y_step", 1.0f / tex_height); } } g_object_unref (shader); } }
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, texcoord_t *texcoord) { GLuint texture; int w, h; SDL_Surface *image; SDL_Rect area; Uint32 saved_flags; Uint8 saved_alpha; /* Use the surface width and height expanded to powers of 2 */ w = next_p2(surface->w); h = next_p2(surface->h); texcoord->MinX = 0.0f; /* Min X */ texcoord->MinY = 0.0f; /* Min Y */ texcoord->MaxX = (GLfloat)surface->w / w; /* Max X */ texcoord->MaxY = (GLfloat)surface->h / h; /* Max Y */ image = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 32, RMASK, GMASK, BMASK, AMASK ); if ( image == NULL ) { return 0; } /* Save the alpha blending attributes */ saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); saved_alpha = surface->format->alpha; if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { SDL_SetAlpha(surface, 0, 0); } /* Copy the surface into the GL texture image */ area.x = 0; area.y = 0; area.w = surface->w; area.h = surface->h; SDL_BlitSurface(surface, &area, image, &area); /* Restore the alpha blending attributes */ if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { SDL_SetAlpha(surface, saved_flags, saved_alpha); } /* Create an OpenGL texture for the image */ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); SDL_FreeSurface(image); /* No longer needed */ return texture; }
///Create a display list coresponding to the give character. void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) { //The first thing we do is get FreeType to render our character //into a bitmap. This actually requires a couple of FreeType commands: //Load the Glyph for our character. if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT )) throw std::runtime_error("FT_Load_Glyph failed"); //Move the face's glyph into a Glyph object. FT_Glyph glyph; if(FT_Get_Glyph( face->glyph, &glyph )) throw std::runtime_error("FT_Get_Glyph failed"); //Convert the glyph to a bitmap. FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; //This reference will make accessing the bitmap easier FT_Bitmap& bitmap=bitmap_glyph->bitmap; //Use our helper function to get the widths of //the bitmap data that we will need in order to create //our texture. int width = next_p2( bitmap.width ); int height = next_p2( bitmap.rows ); //Allocate memory for the texture data. GLubyte* expanded_data = new GLubyte[ 2 * width * height]; //Here we fill in the data for the expanded bitmap. //Notice that we are using two channel bitmap (one for //luminocity and one for alpha), but we assign //both luminocity and alpha to the value that we //find in the FreeType bitmap. //We use the ?: operator so that value which we use //will be 0 if we are in the padding zone, and whatever //is the the Freetype bitmap otherwise. for(int j=0; j <height; j++) { for(int i=0; i < width; i++) { expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j]; } } //Now we just setup some texture paramaters. glBindTexture( GL_TEXTURE_2D, tex_base[ch]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //Here we actually create the texture itself, notice //that we are using GL_LUMINANCE_ALPHA to indicate that //we are using 2 channel data. glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data ); //With the texture created, we don't need to expanded data anymore delete [] expanded_data; //So now we can create the display list glNewList(list_base+ch,GL_COMPILE); glBindTexture(GL_TEXTURE_2D,tex_base[ch]); //first we need to move over a little so that //the character has the right amount of space //between it and the one before it. glTranslatef(bitmap_glyph->left,0,0); //Now we move down a little in the case that the //bitmap extends past the bottom of the line //(this is only true for characters like 'g' or 'y'. glPushMatrix(); glTranslatef(0,bitmap_glyph->top-bitmap.rows,0); //Now we need to account for the fact that many of //our textures are filled with empty padding space. //We figure what portion of the texture is used by //the actual character and store that information in //the x and y variables, then when we draw the //quad, we will only reference the parts of the texture //that we contain the character itself. float x=(float)bitmap.width / (float)width, y=(float)bitmap.rows / (float)height; //Here we draw the texturemaped quads. //The bitmap that we got from FreeType was not //oriented quite like we would like it to be, //so we need to link the texture to the quad //so that the result will be properly aligned. glBegin(GL_QUADS); glTexCoord2d(0,0); glVertex2f(0,bitmap.rows); glTexCoord2d(0,y); glVertex2f(0,0); glTexCoord2d(x,y); glVertex2f(bitmap.width,0); glTexCoord2d(x,0); glVertex2f(bitmap.width,bitmap.rows); glEnd(); glPopMatrix(); glTranslatef(face->glyph->advance.x >> 6 ,0,0); //increment the raster position as if we were a bitmap font. //(only needed if you want to calculate text length) //glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL); //Finnish the display list glEndList(); }
bool CGLFTFont::MakeSymbol(FT_Face face, uint index, bool blend) { GLuint list = m_lists + index; CGLTexture& texture = m_textures[index]; char Symbol = index + startsymbol; if ( Symbol == ' ' ) return MakeSpace( index ); uint CharIndex = FT_Get_Char_Index( face, Symbol ); int error = FT_Load_Glyph( face, CharIndex, FT_LOAD_DEFAULT ); if( error != 0 ) return false; FT_Glyph glyph; error = FT_Get_Glyph( face->glyph, &glyph ); if( error != 0 ) return false; //!!****************************** FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; FT_Bitmap& bitmap = bitmap_glyph->bitmap; //!!*********************** int& bit_width = bitmap.width; int& bit_height = bitmap.rows; m_widths[index] = bit_width; int tex_width = next_p2( bit_width ); int tex_height = next_p2( bit_height ); // Выделим память для данных текстуры. size_t size = 2 * tex_width * tex_height; GLubyte* texture_data = new GLubyte[ size ]; memset( texture_data, 0, size ); for(int y = 0; y < bit_height; ++y) for(int x=0; x < bit_width; ++x) { if (blend == false) { texture_data[2 * ( x + y*tex_width )] = 0xFF; if ( bitmap.buffer[x + bit_width*y] < 0x80) texture_data[2 * (x + y*tex_width) + 1] = 0; else texture_data[2 *( x + y*tex_width) + 1] = 0xFF; } else { texture_data[ 2 * (x + y*tex_width) ] = 0xFF; texture_data[2 * (x + y*tex_width) + 1] = bitmap.buffer[x + bit_width*y]; } } texture.Load( tex_width, tex_height, GL_UNSIGNED_BYTE, texture_data, GL_RGBA, 0 ,0, GL_LUMINANCE_ALPHA ); texture.SetParametr( GL_TEXTURE_MAG_FILTER, GL_LINEAR ); texture.SetParametr( GL_TEXTURE_MIN_FILTER, GL_LINEAR ); delete []texture_data; glNewList( list, GL_COMPILE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); texture.Bind(); double xscale = (double)bit_width / (double)tex_width; double yscale = (double)bit_height / (double)tex_height; glMatrixMode(GL_MODELVIEW); int downshift = 0 - (bitmap_glyph->top - bit_height); if ( downshift > 0 ) { if ( m_downshift < downshift ) m_downshift = downshift; glPushMatrix(); glTranslatef(0,-downshift,0); } glBegin(GL_QUADS); glTexCoord2d(0,0); glVertex2f(0,bitmap.rows); glTexCoord2d(0,yscale); glVertex2f(0,0); glTexCoord2d(xscale,yscale); glVertex2f(bitmap.width,0); glTexCoord2d(xscale,0); glVertex2f(bitmap.width,bitmap.rows); glEnd(); if ( downshift > 0 ) glPopMatrix(); glTranslatef( bit_width + m_symbolspacer, 0, 0 ); glEndList(); }
void font_data::createGlyph(CharacterCode charCode) const { if (FT_Load_Glyph(_face, FT_Get_Char_Index(_face, charCode), FT_LOAD_DEFAULT)) { LogError << "FT_Load_Glyph failed" << std::endl; throw std::runtime_error("FT_Load_Glyph failed"); } FT_Glyph glyph; if (FT_Get_Glyph(_face->glyph, &glyph)) { LogError << "FT_Get_Glyph failed" << std::endl; throw std::runtime_error("FT_Get_Glyph failed"); } FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); FT_BitmapGlyph bitmap_glyph(reinterpret_cast<FT_BitmapGlyph>(glyph)); const FT_Bitmap& bitmap = bitmap_glyph->bitmap; const int width(next_p2(bitmap.width + 1)); const int height(next_p2(bitmap.rows + 1)); const size_t expanded_size(width * height * 2); GLubyte* expanded_data = new GLubyte[expanded_size]; memset(expanded_data, 0, expanded_size); for (int j(0); j < height; ++j) { for (int i(0); i < width; ++i) { expanded_data[2 * (i + j * width)] = expanded_data[2 * (i + j * width) + 1] = (i >= bitmap.width || j >= bitmap.rows) ? 0 : static_cast<GLubyte>(std::min(static_cast<float>(bitmap.buffer[i + bitmap.width * j]) * 1.5f, 255.0f)); } } GlyphData glyphData; glyphData._width = _face->glyph->advance.x >> 6; glyphData._texture = new OpenGL::Texture(); glyphData._texture->bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); delete[] expanded_data; expanded_data = NULL; glyphData._callList = new OpenGL::CallList(); glyphData._callList->startRecording(); glyphData._texture->bind(); const float xl((const float)bitmap_glyph->left); const float xh(xl + width); const float yl((const float)h - bitmap_glyph->top); const float yh(yl + height); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.0f, 0.0f); glVertex2f(xl, yl); glTexCoord2f(0.0f, 1.0f); glVertex2f(xl, yh); glTexCoord2f(1.0f, 0.0f); glVertex2f(xh, yl); glTexCoord2f(1.0f, 1.0f); glVertex2f(xh, yh); glEnd(); glTranslatef(static_cast<float>(glyphData._width), 0.0f, 0.0f); glyphData._callList->endRecording(); _cachedGlyphs[charCode] = glyphData; }
void Label::makeFont(string f) { if(fonts.find(f) != fonts.end()) { font = fonts[f]; return; } string floc = Location + f + ".ttf"; font = fonts[f] = new Font(); font->point = 200; // Create And Initilize A FreeType Font Library. FT_Init_FreeType( &ft ); // This Is Where We Load In The Font Information From The File. // Of All The Places Where The Code Might Die, This Is The Most Likely, // As FT_New_Face Will Fail If The Font File Does Not Exist Or Is Somehow Broken. if (FT_New_Face( ft, floc.c_str(), 0, &font->face )) return; // For Some Twisted Reason, FreeType Measures Font Size // In Terms Of 1/64ths Of Pixels. Thus, To Make A Font // h Pixels High, We Need To Request A Size Of h*64. // (h << 6 Is Just A Prettier Way Of Writing h*64) FT_Set_Char_Size( font->face, font->point * 64, font->point * 64, 96, 96); bool use_kerning = FT_HAS_KERNING( font->face ); for(unsigned char c=0; c<128; c++) { // The First Thing We Do Is Get FreeType To Render Our Character // Into A Bitmap. This Actually Requires A Couple Of FreeType Commands: // Load The Glyph For Our Character. if(FT_Load_Glyph( font->face, FT_Get_Char_Index( font->face, c ), FT_LOAD_DEFAULT )) return; // Move The Face's Glyph Into A Glyph Object. FT_Glyph glyph; if(FT_Get_Glyph( font->face->glyph, &glyph )) return; // Convert The Glyph To A Bitmap. FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; // This Reference Will Make Accessing The Bitmap Easier. FT_Bitmap& bitmap=bitmap_glyph->bitmap; // Use Our Helper Function To Get The Widths Of // The Bitmap Data That We Will Need In Order To Create // Our Texture. int downsample = 8; int width = next_p2( bitmap.width + 4 * downsample ); int height = next_p2( bitmap.rows + 4 * downsample ); float xs = (float)bitmap.width / width; float ys = (float)bitmap.rows / height; width /= downsample; height /= downsample; // Allocate Memory For The Texture Data. GLubyte* tex = (GLubyte*)malloc(width * height); memset(tex, 0, width*height); for(int i=0; i < width; i++) for(int j=0; j < height; j++) { tex[i + j*width]= edgeDistance(bitmap.buffer, bitmap.width, bitmap.rows, (i)/xs/width, (j)/ys/height, 1.0); } glGenTextures(1, &font->chars[c]); glBindTexture(GL_TEXTURE_2D, font->chars[c]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex); for(int k=0; k<128; k++) { if(use_kerning) { FT_Vector kern; FT_Get_Kerning( font->face, FT_Get_Char_Index( font->face, c ), FT_Get_Char_Index( font->face, k ), FT_KERNING_DEFAULT, &kern ); font->kerning[c][k] = (font->face->glyph->advance.x + kern.x) / (font->point * 64.0f); } else { font->kerning[c][k] = font->face->glyph->advance.x / (font->point * 64.0f); } } font->wid[c] = bitmap.width / (float)font->point; font->hgt[c] = bitmap.rows / (float)font->point; font->top[c] = (bitmap_glyph->top-bitmap.rows) / (float)font->point; font->xpad[c] = xs; font->ypad[c] = ys; free(tex); } FT_Done_Face(font->face); FT_Done_FreeType(ft); }
bool CText::MakeFTChar(FT_Face face, char ch, int list_base, int textures[NUM_CHARS], float charsizes[NUM_CHARS][2], bool mipmaps) { const int ich = ch; if(pFT_Load_Glyph(face,pFT_Get_Char_Index(face,ich),FT_LOAD_DEFAULT)) return false; FT_Glyph glyph; if(pFT_Get_Glyph(face->glyph,&glyph)) return false; bool empty=(pFT_Glyph_To_Bitmap(&glyph,FT_RENDER_MODE_NORMAL,0,1)!=0); FT_BitmapGlyph bitmap_glyph=(FT_BitmapGlyph)glyph; FT_Bitmap& bitmap=bitmap_glyph->bitmap; int width=1, height=1; if (!empty) { width=next_p2(bitmap.width); height=next_p2(bitmap.rows); unsigned char *expanded_data=(unsigned char *)malloc(2*width*height); if (!expanded_data) { pFT_Done_Glyph(glyph); return false; } for(int j=0; j<height; j++) { for(int i=0; i<width; i++) { expanded_data[2*(i+j*width)]=255; expanded_data[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j]; } } glBindTexture(GL_TEXTURE_2D, textures[ich]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); if (mipmaps) { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST); if (gluBuild2DMipmaps(GL_TEXTURE_2D,2,width,height,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,expanded_data)!=0) { free(expanded_data); pFT_Done_Glyph(glyph); return false; } } else { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); } free(expanded_data); } glNewList(list_base+ich,GL_COMPILE); { if (!empty) { glBindTexture(GL_TEXTURE_2D,textures[ich]); glPushMatrix(); glTranslatef((float)bitmap_glyph->left, (float)(bitmap_glyph->top-bitmap.rows),0); float x= (float)bitmap.width / (float)width, y= (float)bitmap.rows / (float)height; glBegin(GL_QUADS); { glNormal3f(0,0,1); glTexCoord2f(0,0); glVertex2f(0,(float)bitmap.rows); glTexCoord2f(x,0); glVertex2f((float)bitmap.width, (float)bitmap.rows); glTexCoord2f(x,y); glVertex2f((float)bitmap.width, 0); glTexCoord2f(0,y); glVertex2f(0,0); } glEnd(); glPopMatrix(); } glTranslatef((float)(face->glyph->advance.x>>6), 0, 0); } glEndList(); charsizes[ich][0]=((float)face->glyph->advance.x/64.0f); charsizes[ich][1]=((float)face->size->metrics.height/64.0f); pFT_Done_Glyph(glyph); return true; }
int FTinit(font_data *font, const char * fontname, int ptsize) { int i; SDL_Color white = { 0xFF, 0xFF, 0xFF, 0x00 }; SDL_Color black = { 0x00, 0x00, 0x00, 0 }; SDL_Color *forecol; SDL_Color *backcol; GLenum gl_error; texcoord_t texcoords; int minx = 0,miny = 0,maxx = 0,maxy = 0; /* We might support changing theese later */ /* Look for special rendering types */ renderstyle = TTF_STYLE_NORMAL; rendertype = RENDER_LATIN1; /* Default is black and white */ forecol = &white; backcol = &black; /* Initialize the TTF library */ /*if ( TTF_Init() < 0 ) { fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError()); return(2); }*/ font->ttffont = TTF_OpenFont(fontname, ptsize); if ( font->ttffont == NULL ) { fprintf(stderr, "Couldn't load %d pt font from %s: %s\n", ptsize, fontname, SDL_GetError()); return(2); } TTF_SetFontStyle(font->ttffont, renderstyle); font->list_base=glGenLists(next_p2(NUMCHARS)); /* Get the recommended spacing between lines of text for this font */ font->linespacing = TTF_FontLineSkip(font->ttffont); font->h = ptsize; for( i = 0; i < NUMCHARS; i++ ) { SDL_Surface *glyph = NULL; GLuint height = 0; /* kps - added default value */ forecol = &white; glyph = TTF_RenderGlyph_Blended( font->ttffont, i, *forecol ); if(glyph) { glGetError(); font->textures[i] = SDL_GL_LoadTexture(glyph, &texcoords); if ( (gl_error = glGetError()) != GL_NO_ERROR ) printf("Warning: Couldn't create texture: 0x%x\n", gl_error); font->W[i] = glyph->w; height = glyph->h; TTF_GlyphMetrics( font->ttffont, i, &minx,&maxx,&miny,&maxy,NULL); } SDL_FreeSurface(glyph); glNewList(font->list_base+i,GL_COMPILE); glBindTexture(GL_TEXTURE_2D, font->textures[i]); glTranslatef(1,0,0); glPushMatrix(); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(texcoords.MinX, texcoords.MaxY); glVertex2i(0 , miny); glTexCoord2f(texcoords.MaxX, texcoords.MaxY); glVertex2i(font->W[i] , miny); glTexCoord2f(texcoords.MinX, texcoords.MinY); glVertex2i(0 ,miny+height ); glTexCoord2f(texcoords.MaxX, texcoords.MinY); glVertex2i(font->W[i] , miny+height); glEnd(); glPopMatrix(); glTranslatef((font->W[i]>3)?font->W[i]:(font->W[i] = 3) + 1,0,0); /*one would think this should be += 2... I guess they overlap or the edge * isn't painted */ font->W[i] += 1; glEndList(); } /*TTF_CloseFont(font->ttffont);*/ /*TTF_Quit();*/ return 0; }