RenderedGlyphContainer::RenderedGlyph RenderedGlyphContainer::renderGlyph(glyph_char glyph, void*fontptr, void*renderer, unsigned int size, int fontstyle, bool antialiasing)
	{
		TTF_Font* font = (TTF_Font*)fontptr;
		SDL_Color color = {255,255,255,255}; //white
		SDL_Surface* surface = nullptr;
		if(antialiasing)
		{
			surface = TTF_RenderGlyph_Blended(font, CharForceConvert<glyph_char, GameLibrary::Uint16>(glyph), color);
		}
		else
		{
			surface = TTF_RenderGlyph_Solid(font, CharForceConvert<glyph_char, GameLibrary::Uint16>(glyph), color);
		}
		if(surface == nullptr)
		{
			throw RenderGlyphException(TTF_GetError());
		}
		SDL_Texture*texture = SDL_CreateTextureFromSurface((SDL_Renderer*)renderer, surface);
		SDL_FreeSurface(surface);
		if(texture == nullptr)
		{
			throw RenderGlyphException(SDL_GetError());
		}

		RenderedGlyph renderedGlyph;
		renderedGlyph.texture = texture;
		renderedGlyph.size = size;
		renderedGlyph.fontstyle = fontstyle;
		renderedGlyph.antialias = antialiasing;

		return renderedGlyph;
	}
예제 #2
0
extern DECLSPEC SDL_Surface * SDLCALL
  TTF_RenderGlyph_Blended_p(
    TTF_Font *font,
    uint16_t glyph,
    SDL_Color *fg) {

  return TTF_RenderGlyph_Blended(font, glyph, *fg);
}
예제 #3
0
SDL_Surface* SimKit::TTFVFont::render_font(const Uint32 ch, const SDL_Color textcol, const SimKit::IVFont::TransparencyType bg) {
    switch (bg) {
        case SimKit::IVFont::COLORKEY:
            return TTF_RenderGlyph_Solid(this->rfont, ch, textcol);
        case SimKit::IVFont::ALPHA:
            return TTF_RenderGlyph_Blended(this->rfont, ch, textcol);
    }
};
예제 #4
0
void cache_glyphs()
{
    int i;
    char title[800];
    SDL_Color fg={0,0,0,255};
#if RENDER_MODE==1
    SDL_Color bg={255,255,255,255};
#endif

    free_glyphs();
    if(!font)
        return;
    if(style!=TTF_GetFontStyle(font))
        TTF_SetFontStyle(font,style);
    if(kerning != !!TTF_GetFontKerning(font))
        TTF_SetFontKerning(font,kerning);
    if(hinting != TTF_GetFontHinting(font))
        TTF_SetFontHinting(font,hinting);
    if(outline != TTF_GetFontOutline(font))
        TTF_SetFontOutline(font,outline);
    for(i=0; i<128; i++)
    {
        /* cache rendered surface */
#if RENDER_MODE==0
        text[i]=TTF_RenderGlyph_Solid(font,i+start_glyph,fg);
#elif RENDER_MODE==1
        text[i]=TTF_RenderGlyph_Shaded(font,i+start_glyph,fg,bg);
#elif RENDER_MODE==2
        text[i]=TTF_RenderGlyph_Blended(font,i+start_glyph,fg);
#endif
        if(!text[i])
        {
            printf("TTF_RenderGlyph_Shaded: %s\n", TTF_GetError());
            exit(4);
        }
        /* cache metrics */
        TTF_GlyphMetrics(font, i+start_glyph,
            &gm[i].minx, &gm[i].maxx,
            &gm[i].miny, &gm[i].maxy,
            &gm[i].advance);
    }

    sprintf(title,"%s-%s:%d+0x%04x",TTF_FontFaceFamilyName(font),
        TTF_FontFaceStyleName(font),font_size,start_glyph);
    SDL_WM_SetCaption(title,"latin1");
}
예제 #5
0
파일: font.cpp 프로젝트: kulibali/periapsis
        texture *font_impl::get_glyph(const wchar_t ch) const
        {
            shared_pointer<texture> tex = glyph_textures[ch];

            if (!tex.ptr())
            {
                int minx, maxx, miny, maxy, advance;
                if (TTF_GlyphMetrics(static_cast<TTF_Font *>(ttf_font_ptr), ch, &minx, &maxx, &miny, &maxy, &advance) == -1)
                    throw runtime_exception(L"Error getting glyph metrics: %hs", TTF_GetError());

                SDL_Color c;
                c.r = static_cast<Uint8>(fg[color::COMPONENT_RED] * 255.0f);
                c.g = static_cast<Uint8>(fg[color::COMPONENT_GREEN] * 255.0f);
                c.b = static_cast<Uint8>(fg[color::COMPONENT_BLUE] * 255.0f);

                SDL_Surface *surf1 = TTF_RenderGlyph_Blended(static_cast<TTF_Font *>(ttf_font_ptr), ch, c);

                SDL_Surface *surf2 = SDL_CreateRGBSurface(SDL_SWSURFACE, nearest_power_2(minx + surf1->w), texture_height, 32, surf1->format->Rmask, surf1->format->Gmask, surf1->format->Bmask, surf1->format->Amask);

                if (!surf2)
                    throw runtime_exception(L"Unable to create SDL surface: %hs", SDL_GetError());

                SDL_Rect dest;

                dest.x = minx > 0 ? minx : 0;
                dest.y = (surf2->h - font_height) + (font_ascent - maxy);
                dest.w = surf1->w;
                dest.h = surf1->h;

                clear_pixel_alpha(surf2);
                src_alpha_blit(surf1, surf2, dest.x, dest.y);

                string glyph_id = string::format(L"%ls %d: %lc", face.w_string(), size, ch);
                tex = new texture(FONT_TEXTURE_CATEGORY, surf2, texture::TEXTURE_ENV_REPLACE | texture::TEXTURE_WRAP_CLAMP | texture::TEXTURE_FILTER_LINEAR, texture::TEXTURE_COLORMAP, glyph_id.w_string());
                glyph_textures[ch] = tex;

                glyph_pct_x[ch] = static_cast<float>(advance) / static_cast<float>(surf2->w);
                glyph_pct_y[ch] = static_cast<float>(font_height) / static_cast<float>(surf2->h);
                glyph_widths[ch] = static_cast<float>(advance);

                SDL_FreeSurface(surf2);
                SDL_FreeSurface(surf1);
            }

            return tex.ptr();
        } // font_impl::get_glyph()
예제 #6
0
static mrb_value
mrb_sdl2_ttf_font_render_glyph_blended(mrb_state *mrb, mrb_value self)
{
  mrb_value text; 
  mrb_int r, g, b, a;
  SDL_Surface * c;
  SDL_Color color;
  mrb_get_args(mrb, "Siiii", &text, &r, &g, &b, &a);
  color.r = r;
  color.g = g;
  color.b = b;
  color.a = a;
  c = TTF_RenderGlyph_Blended(mrb_sdl2_font_get_ptr(mrb, self), RSTRING_PTR(text)[0], color);
  if (c == NULL) {
    mruby_sdl2_raise_error(mrb);
    return mrb_false_value();
  }
  return mrb_sdl2_video_surface(mrb, c, 0);
}
예제 #7
0
JNIEXPORT jlong JNICALL Java_sdljava_x_swig_SWIG_1SDLTTFJNI_TTF_1RenderGlyph_1Blended(JNIEnv *jenv, jclass jcls, jlong jarg1, jint jarg2, jlong jarg3) {
    jlong jresult = 0 ;
    TTF_Font *arg1 = (TTF_Font *) 0 ;
    Uint16 arg2 ;
    SDL_Color arg3 ;
    SDL_Surface *result;
    SDL_Color *argp3 ;
    
    (void)jenv;
    (void)jcls;
    arg1 = *(TTF_Font **)&jarg1; 
    arg2 = (Uint16)jarg2; 
    argp3 = *(SDL_Color **)&jarg3; 
    if (!argp3) {
        SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null SDL_Color");
        return 0;
    }
    arg3 = *argp3; 
    result = (SDL_Surface *)TTF_RenderGlyph_Blended(arg1,arg2,arg3);
    
    *(SDL_Surface **)&jresult = result; 
    return jresult;
}
예제 #8
0
/*
 * create_font
 */
int create_font(char *filename,
                FONT **font,
                int size,
                int style,
                SDL_Color color)
{
  TTF_Font* ttffont;
  SDL_Surface* character_surface;
  int ret_code = BUILD_FONT_OK;
  int rc;
  Uint16 ii;

  /*
   * Allocate the memory required for the font object.
   */
  (*font) = (FONT *) DT_MALLOC(sizeof(FONT));

  /*
   * Set the font attributes.
   */
  memcpy(&((*font)->color), &color, sizeof(SDL_Color));
  (*font)->pointsize = size;
  (*font)->style = style;

  /*
   * The font loading may fail if the file does not exist or permissions are
   * incorrect etc.
   */
  ttffont = TTF_OpenFont(filename, (*font)->pointsize);
  if (ttffont == NULL)
  {
    DT_DEBUG_LOG("Error opening font (%s): %s\n", filename, TTF_GetError());
    ret_code = BUILD_FONT_LOAD_FAIL;
    goto EXIT_LABEL;
  }

  /*
   * Set the style of the font to whatever we passed in.
   */
  TTF_SetFontStyle(ttffont, (*font)->style);

  /*
   * Retrieve the font information to store in our font structure.
   */
  (*font)->ascent = TTF_FontAscent(ttffont);
  (*font)->descent = TTF_FontDescent(ttffont);
  (*font)->height = TTF_FontHeight(ttffont);
  (*font)->lineskip = TTF_FontLineSkip(ttffont);

  /*
   * For each possible glyph, attempt to load the font character and create a
   * texture for it. If any of these fail we attempt to close down gracefully
   * and exit the function.
   */
  for (ii = ' '; ii <= '~'; ii++)
  {
    character_surface = TTF_RenderGlyph_Blended(ttffont, ii, (*font)->color);
    if (NULL == character_surface)
    {
      DT_DEBUG_LOG("Error rendering glyph %c whilst creating font (%s): %s\n",
                   (char) ii,
                   filename,
                   TTF_GetError());
      ret_code = BUILD_FONT_RENDER_FAIL;
      goto EXIT_LABEL;
    }

    /*
     * Retrieve the metric info from the font object and store it in our local
     * structure.
     */
    TTF_GlyphMetrics(ttffont,
                     ii,
                     &((*font)->glyphs[ii].minx),
                     &((*font)->glyphs[ii].maxx),
                     &((*font)->glyphs[ii].miny),
                     &((*font)->glyphs[ii].maxy),
                     &((*font)->glyphs[ii].advance));

    /*
     * This function can fail if opengl cannot allocate any more memory for
     * textures.
     */
    rc = SDL_GL_LoadTexture(character_surface, &((*font)->glyphs[ii].texid), false);
    if (LOAD_TEXTURE_OK != rc)
    {
      DT_DEBUG_LOG("Failed creating texture for glyph %c from font %s\n",
                   (char) ii,
                   TTF_GetError());
      SDL_FreeSurface(character_surface);
      ret_code = BUILD_FONT_CREATE_TEXTURE_FAIL;
      goto EXIT_LABEL;
    }

    /*
     * Set the texture coordinates for the glyph (note this is the same for all
     * glyphs).
     */
    (*font)->glyphs[ii].texcoord[0] = 0.0f;
    (*font)->glyphs[ii].texcoord[1] = 0.0f;
    (*font)->glyphs[ii].texcoord[2] = 1.0f;
    (*font)->glyphs[ii].texcoord[3] = 1.0f;

    /*
     * The surface used for that character is no longer required.
     */
    SDL_FreeSurface(character_surface);
  }

EXIT_LABEL:

  if (NULL != ttffont)
  {
    TTF_CloseFont(ttffont);
  }

  return ret_code;
}
예제 #9
0
SDL_Texture* generateVerticalText(const char* text, SDL_Color color)
{
	std::vector <SDL_Texture*> glyphs;
	
	int w=0,h=0;
	
	
	for(int i=0;text[i]!='\0';++i)
	{
		SDL_Surface* text_surface=TTF_RenderGlyph_Blended(monoFont, text[i], color);
		SDL_Texture *tex = SDL_CreateTextureFromSurface(render, text_surface);
		
		
		w=std::max(w, text_surface->w);
		
		int miny, maxy;
		if(text[i]=='_')
		{miny=1; maxy=11;}
		else
		TTF_GlyphMetrics(font, text[i], NULL, NULL, &miny, &maxy, NULL);
		
		h+=maxy-miny+3;
		
		SDL_FreeSurface(text_surface);
		
		glyphs.push_back(tex);
	}

	SDL_Texture *tex=SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
	
	SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND); 
	SDL_SetRenderTarget(render, tex);
	
	SDL_SetRenderDrawColor(render, 0, 0, 0, 0);
	SDL_RenderClear(render);
	
	int p=0;
	for(int i=0;i<glyphs.size();++i)
	{
		int texW, texH;
		SDL_QueryTexture(glyphs[i], NULL, NULL, &texW, &texH);
		
		int miny, maxy;
		if(text[i]=='_')
		{miny=1; maxy=11;}
		else
		TTF_GlyphMetrics(font, text[i], NULL, NULL, &miny, &maxy, NULL);
		
		SDL_Rect glyphRect;
		glyphRect.y=p;
		glyphRect.x=0;//(w-texW)/2;
		glyphRect.w=texW;
		glyphRect.h=texH;
		p+=maxy-miny+3;
		
		if(text[i]!='_')
		SDL_RenderCopy(render, glyphs[i], NULL, &glyphRect);
		
		SDL_DestroyTexture(glyphs[i]);
	}
	
	SDL_SetRenderTarget(render, NULL);
	return tex;

}
예제 #10
0
  void Font_FT::init(const String &filepath) {
    TTF_Font *font = TTF_OpenFont(filepath.c_str(), int(get_text_height() * m_vratio + 0.5f));
    if(!font)
      throw Font_Init_Failure();

    /*** Set Style ***/

    if(is_bold() && is_italic())
      TTF_SetFontStyle(font, TTF_STYLE_BOLD | TTF_STYLE_ITALIC);
    else if(is_bold())
      TTF_SetFontStyle(font, TTF_STYLE_BOLD);
    else if(is_italic())
      TTF_SetFontStyle(font, TTF_STYLE_ITALIC);

    /*** Determine Width & Height ***/

    float font_width = 0;
    float font_height = 0;
    SDL_Color color2 = {0xFF, 0xFF, 0xFF, 0xFF};
    SDL_Surface *source[256] = {0};
    for(unsigned char c = 1; c; ++c) {
      Core::assert_no_error();
      //char t[2] = {c, '\0'};
      //source[c] = TTF_RenderText_Blended(font, t, color2);
      source[c] = TTF_RenderGlyph_Blended(font, c, color2);
      Core::print_error();
      font_width = std::max(font_width, float(source[c] ? source[c]->w : 0));
      font_height = std::max(font_height, float(source[c] ? source[c]->h : 0));
    }

    /*** Initialize Intermediate SDL Surface ***/

    const int 
      next_w = int(pow(2.0f, ceil(log(float(16 * font_width))/log(2.0f)))), 
      next_h = int(pow(2.0f, ceil(log(float(16 * font_height))/log(2.0f))));
  
    SDL_Surface *font_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, next_w, next_h, 32, source[END_OF_TIME]->format->Rmask, source[END_OF_TIME]->format->Gmask, source[END_OF_TIME]->format->Bmask, source[END_OF_TIME]->format->Amask);
    if(!font_surface) {
      for(unsigned char c = 1; c; ++c)
        SDL_FreeSurface(source[c]);
      TTF_CloseFont(font);

      if(next_h > 1024) {
        m_vratio /= 2.0f;
        init(filepath);
        return;
      }
      else
        throw Font_Init_Failure();
    }

    SDL_LockSurface(font_surface);
    SDL_FillRect(font_surface, 0, SDL_MapRGBA(font_surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT));
    SDL_UnlockSurface(font_surface);

    /*** Initialize Glyphs ***/

    SDL_Rect dstrect = {0, 0, Uint16(font_width), Uint16(font_height)};
    m_glyph[0] = 0;
    for(unsigned char c = 1; c; ++c) {
      dstrect.x = Sint16((c % 16) * font_width);
      dstrect.y = Sint16((c / 16) * font_height);
      m_glyph[c] = new Glyph(font, c, source[c], font_surface, dstrect, next_w, next_h, m_vratio);
    }

    /*** Correct Transparency ***/

    const Uint32 transparent_white = font_surface->format->Rmask | font_surface->format->Gmask | font_surface->format->Bmask;
    for(int i = 0; i < font_surface->h; ++i)
      for(Uint32 * src = reinterpret_cast<Uint32 *>(font_surface->pixels) + i * font_surface->pitch / 4,
                 * src_end = src + font_surface->w;
          src != src_end;
          ++src)
        if(*src & font_surface->format->Rmask)
          *src = transparent_white | ((*src & font_surface->format->Rmask) >> font_surface->format->Rshift << font_surface->format->Ashift);

    /*** Initialize Final Texture ***/
    
    m_texture = get_Video().create_Texture(font_surface, false);

    TTF_CloseFont(font);
  }
예제 #11
0
void Font::ConvertToBitmapFont(Display* display, int numchar)
{
	int textureW = size * sqrt(numchar);
	int textureH = size * sqrt(numchar);

	bitmapFont = SDL_CreateTexture(display->GetRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, textureW, textureH);

	if (bitmapFont == nullptr)
	{
		LOG_ERROR("Couldn't create texture for bitmap font creating! Error: " << SDL_GetError());
	}

	if(SDL_SetTextureBlendMode(bitmapFont, SDL_BLENDMODE_BLEND) == -1)
		LOG_ERROR("Couldn't set blendmode for texture when creating bitmap font!");


	if(SDL_SetRenderTarget(display->GetRenderer(), bitmapFont) == -1)
		LOG_ERROR("Couldn't set render target to texture when creating bitmap font!");

	display->PushRenderColor();
	display->SetRenderColor(255, 255, 255, 0);

	if(SDL_RenderClear(display->GetRenderer()) == -1)
		LOG_ERROR("Couldn't clear texture when creating bitmap font!");

	display->PopRenderColor();

	int x = 0;
	int y = 0;	

	for (int i = 0; i < numchar; i++)
	{	
		
		//If break line charater skip
		if (i == 10)
		{ 
			glyphPositions.push_back(Rect(0, 0, 0, 0));
			continue;
		}

		SDL_Surface* surface = nullptr;
		surface = TTF_RenderGlyph_Blended(font, i, COLOR_WHITE.ToSDLColor());

		if (surface == nullptr)
		{
			//Don't show error on the NULL character
			if (i != 0)
			{
				LOG_ERROR("Couldn't create glyph surface! Using letter " << (char)i);
			}
			glyphPositions.push_back(Rect(0, 0, 0, 0));
			continue;
		}

		SDL_Texture* texture = nullptr;
		texture = SDL_CreateTextureFromSurface(display->GetRenderer(), surface);

		SDL_FreeSurface(surface);

		if (texture == nullptr)
		{
			LOG_ERROR("Couldn't create glyph texture! Using letter " << (char)i);
			glyphPositions.push_back(Rect(0, 0, 0, 0));
			continue;
		}

		Rect pos;
		if (SDL_QueryTexture(texture, NULL, NULL, &pos.w, &pos.h) == -1)
		{
			LOG_ERROR("Couldn't query texture when creating bitmap font!");
			break;
		}

		if (x + pos.GetW() > textureW)
		{
			x = 0;
			y++;
		}
		if (y * pos.h > textureH)
		{
			LOG_ERROR("Can't render anymore letters to the texture it's full! Font size: " << size);
			SDL_DestroyTexture(texture);
			break;
		}

		pos.x = x;
		pos.y = y * pos.h;

		height = pos.GetH();

		glyphPositions.push_back(pos);

		x += pos.GetW();

		//Don't render tab character
		if (i != 9)
		{
			if (SDL_RenderCopy(display->GetRenderer(), texture, NULL, pos.ToSDLRect()) == -1)
				LOG_ERROR("Couldn't draw on texture when creating bitmap font!");
		}

		SDL_DestroyTexture(texture);
	}

	if(SDL_SetRenderTarget(display->GetRenderer(), NULL) == -1)
		LOG_ERROR("Couldn't set render target back to renderer when creating bitmap font!");
	
	return;
}
예제 #12
0
파일: Font.cpp 프로젝트: Dwarfius/GP2
Font::Font(const string& fileName)
{
	guiCam = new Camera(true);
	vertices = new vector<Vertex>();
	indices = new vector<int>();

	TTF_Font *font = TTF_OpenFont(fileName.c_str(), 64);
	if (!font)
		printf("Unable to load font %s-%s\n", fileName.c_str(), TTF_GetError());

	//first of all, need to render out the text atlas to use for vertex rendering
	SDL_Surface *atlasSurf = SDL_CreateRGBSurface(0, width, height, 32, 
								0xFF000000, 0xFF0000, 0xFF00, 0xFF);
	//to track where to put next glyphs
	int x = 0, y = 0;
	//marks where the newline starts
	int newY = 0; 
	//32 being space, 126 being ~, all visible characters
	for (uint glyph = 32; glyph < 127; glyph++)
	{
		SDL_Surface *glyphSurf = TTF_RenderGlyph_Blended(font, glyph, {255, 255, 255});
		int w = glyphSurf->w, h = glyphSurf->h;

		if (x + w > width) //if we can't go right anymore
		{
			x = 0; //start from left
			y += newY; //on a new line
			newY = 0; //start looking for a new newline offset
		}
		
		SDL_Rect r = { x, y, w, h };
		SDL_BlitSurface(glyphSurf, NULL, atlasSurf, &r);
		RECTF rect = { x, y, w, h - 4 }; //adding a 4pixel boundary from the bottom
		rects[glyph - 32] = rect; //saving the unnormalized UVs
		x += w;
		newY = glm::max(newY, h);
		SDL_FreeSurface(glyphSurf);
	}

	//now normalizing the UVs
	int count = 127 - 32;
	for (int i = 0; i < count; i++)
	{
		RECTF r = rects[i];
		r.x /= (float)width;
		r.y /= (float)height;
		r.w /= (float)width;
		r.h /= (float)height;
		rects[i] = r;
	}

	//for debug
	SDL_SaveBMP(atlasSurf, "atlas.bmp");

	GLuint atlasText = ConvertSDLSurfaceToTexture(atlasSurf);
	SDL_FreeSurface(atlasSurf);
	TTF_CloseFont(font);

	//saving the previous state
	GLint currActive;
	glGetIntegerv(GL_ACTIVE_TEXTURE, &currActive);

	//pushing our texture and setting standard settings
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, atlasText);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

	//restoring it
	glActiveTexture(currActive);

	m = new Model();
	m->SetUpAttrib(0, 3, GL_FLOAT, 0);
	m->SetUpAttrib(1, 2, GL_FLOAT, sizeof(vec3) + sizeof(vec4));

	shader = new ShaderProgram(SHADER_PATH + "guiVS.glsl", SHADER_PATH + "guiFS.glsl");
	shader->BindAttribLoc(0, "vertexPosition");
	shader->BindAttribLoc(1, "uvs");
	shader->Link();
	t = new Texture(atlasText);
	renderer = new Renderer();
	renderer->SetModel(m, GL_TRIANGLES);
	renderer->SetShaderProgram(shader);
	renderer->AddTexture(t);
}
예제 #13
0
파일: text.cpp 프로젝트: AMDmi3/ValyriaTear
bool TextSupervisor::_RenderText(vt_utils::ustring &string, TextStyle &style, ImageMemory &buffer)
{
    FontProperties *fp = _font_map[style.font];
    TTF_Font *font = fp->ttf_font;

    if(font == NULL) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "font of TextStyle argument '" << style.font << "' was invalid" << std::endl;
        return false;
    }

    static const SDL_Color white_color = { 0xFF, 0xFF, 0xFF, 0xFF };

    SDL_Surface *intermediary = NULL;

    // Width and height of each line of text
    int32 line_w, line_h;
    // Minimum Y value of the line
    int32 min_y = 0;
    // Calculated line width
    int32 calc_line_width = 0;
    // Pixels left of '0' the first character extends, if any
    int32 line_start_x = 0;

    if(TTF_SizeUNICODE(font, string.c_str(), &line_w, &line_h) == -1) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_SizeUNICODE() failed" << std::endl;
        return false;
    }

    _CacheGlyphs(string.c_str(), fp);

    // Calculate the width of the width and minimum y value of the text
    const uint16 *char_ptr;
    for(char_ptr = string.c_str(); *char_ptr != '\0'; ++char_ptr) {
        FontGlyph *glyphinfo = (*fp->glyph_cache)[*char_ptr];
        if(glyphinfo->top_y < min_y)
            min_y = glyphinfo->top_y;
        calc_line_width += glyphinfo->advance;
    }

    // Subtract one pixel from the minimum y value (TODO: explain why)
    min_y -= 1;

    // Check if the first character starts left of pixel 0, and set
// 	char_ptr = string.c_str();
    if(*char_ptr) {
        FontGlyph *first_glyphinfo = (*fp->glyph_cache)[*char_ptr];
        if(first_glyphinfo->min_x < 0)
            line_start_x = first_glyphinfo->min_x;
    }

    // TTF_SizeUNICODE can underestimate line width as a result of its micro positioning.
    // Check if this condition is true and if so, set the line width appropriately.
    if(calc_line_width > line_w)
        line_w = calc_line_width;

    // Adjust line dimensions by negative starting offsets if present
    line_w -= line_start_x;
    line_h -= min_y;

    // Allocate enough memory for the entire text surface to reside on
    uint8 *intermed_buf = static_cast<uint8 *>(calloc(line_w * line_h, 4));
    intermediary = SDL_CreateRGBSurfaceFrom(intermed_buf, line_w, line_h, 32, line_w * 4, RMASK, GMASK, BMASK, AMASK);
    if(intermediary == NULL) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "call to SDL_CreateRGBSurfaceFrom() failed" << std::endl;
        return false;
    }

    // Go through the string and render each glyph one by one
    SDL_Rect surf_target;
    int32 xpos = -line_start_x;
    int32 ypos = -min_y;
    for(char_ptr = string.c_str(); *char_ptr != '\0'; ++char_ptr) {
        FontGlyph *glyphinfo = (*fp->glyph_cache)[*char_ptr];

        // Render the glyph
        SDL_Surface* initial = TTF_RenderGlyph_Blended(font, *char_ptr, white_color);
        if(initial == NULL) {
            IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_RenderGlyph_Blended() failed" << std::endl;
            return false;
        }

        surf_target.x = xpos + glyphinfo->min_x;
        surf_target.y = ypos + glyphinfo->top_y;

        // Add the glyph to the end of the rendered string
        if(SDL_BlitSurface(initial, NULL, intermediary, &surf_target) < 0) {
            SDL_FreeSurface(initial);
            SDL_FreeSurface(intermediary);
            free(intermed_buf);
            IF_PRINT_WARNING(VIDEO_DEBUG) << "call to SDL_BlitSurface() failed, SDL error: " << SDL_GetError() << std::endl;
            return false;
        }
        SDL_FreeSurface(initial);
        xpos += glyphinfo->advance;
    }

    SDL_LockSurface(intermediary);

    uint8 color_mult[] = {
        static_cast<uint8>(style.color[0] * 0xFF),
        static_cast<uint8>(style.color[1] * 0xFF),
        static_cast<uint8>(style.color[2] * 0xFF)
    };

    uint32 num_bytes = intermediary->w * intermediary->h * 4;
    for(uint32 j = 0; j < num_bytes; j += 4) {
        ((uint8 *)intermediary->pixels)[j + 3] = ((uint8 *)intermediary->pixels)[j + 2];
        ((uint8 *)intermediary->pixels)[j + 0] = color_mult[0];
        ((uint8 *)intermediary->pixels)[j + 1] = color_mult[1];
        ((uint8 *)intermediary->pixels)[j + 2] = color_mult[2];
    }

    buffer.width = line_w;
    buffer.height = line_h;
    buffer.pixels = intermed_buf;

    SDL_UnlockSurface(intermediary);
    SDL_FreeSurface(intermediary);

    return true;
} // bool TextSupervisor::_RenderText(vt_utils::ustring& string, TextStyle& style, ImageMemory& buffer)
예제 #14
0
파일: text.cpp 프로젝트: AMDmi3/ValyriaTear
void TextSupervisor::_CacheGlyphs(const uint16 *text, FontProperties *fp)
{
    if(fp == NULL) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "FontProperties argument was null" << std::endl;
        return;
    }

    // Empty string means there are no glyphs to cache
    if(*text == 0) {
        return;
    }

    static const SDL_Color glyph_color = { 0xFF, 0xFF, 0xFF, 0xFF }; // Opaque white color
    static const uint16 fall_back_glyph = '?'; // If we can't cache a particular glyph, we fall back to this one

    TTF_Font *font = fp->ttf_font;
    SDL_Surface *initial = NULL;
    SDL_Surface *intermediary = NULL;
    int32 w, h;
    GLuint texture;

    // Go through each character in the string and cache those glyphs that have not already been cached
    for(const uint16 *character_ptr = text; *character_ptr != 0; ++character_ptr) {
        // A reference for legibility
        const uint16 &character = *character_ptr;

        // Update the glyph cache when needed
        if(character >= fp->glyph_cache->size())
            fp->glyph_cache->resize(character + 1, 0);

        // Check if the glyph is already cached. If so, move on to the next character
        if(fp->glyph_cache->at(character) != 0)
            continue;

        // Attempt to create the initial SDL_Surface that contains the rendered glyph
        initial = TTF_RenderGlyph_Blended(font, character, glyph_color);
        if(initial == NULL) {
            IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_RenderGlyph_Blended() failed, resorting to fall back glyph: '?'" << std::endl;
            initial = TTF_RenderGlyph_Blended(font, fall_back_glyph, glyph_color);
            if(initial == NULL) {
                IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_RenderGlyph_Blended() failed for fall back glyph, aborting glyph caching" << std::endl;
                return;
            }
        }

        w = RoundUpPow2(initial->w + 1);
        h = RoundUpPow2(initial->h + 1);

        intermediary = SDL_CreateRGBSurface(0, w, h, 32, RMASK, GMASK, BMASK, AMASK);
        if(intermediary == NULL) {
            SDL_FreeSurface(initial);
            IF_PRINT_WARNING(VIDEO_DEBUG) << "call to SDL_CreateRGBSurface() failed" << std::endl;
            return;
        }


        if(SDL_BlitSurface(initial, 0, intermediary, 0) < 0) {
            SDL_FreeSurface(initial);
            SDL_FreeSurface(intermediary);
            IF_PRINT_WARNING(VIDEO_DEBUG) << "call to SDL_BlitSurface() failed" << std::endl;
            return;
        }

        glGenTextures(1, &texture);
        TextureManager->_BindTexture(texture);


        SDL_LockSurface(intermediary);

        uint32 num_bytes = w * h * 4;
        for(uint32 j = 0; j < num_bytes; j += 4) {
            (static_cast<uint8 *>(intermediary->pixels))[j + 3] = (static_cast<uint8 *>(intermediary->pixels))[j + 2];
            (static_cast<uint8 *>(intermediary->pixels))[j + 0] = 0xff;
            (static_cast<uint8 *>(intermediary->pixels))[j + 1] = 0xff;
            (static_cast<uint8 *>(intermediary->pixels))[j + 2] = 0xff;
        }

        glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, intermediary->pixels);
        SDL_UnlockSurface(intermediary);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        if(VideoManager->CheckGLError()) {
            SDL_FreeSurface(initial);
            SDL_FreeSurface(intermediary);
            IF_PRINT_WARNING(VIDEO_DEBUG) << "an OpenGL error was detected: " << VideoManager->CreateGLErrorString() << std::endl;
            return;
        }

        int minx, maxx;
        int miny, maxy;
        int advance;
        if(TTF_GlyphMetrics(font, character, &minx, &maxx, &miny, &maxy, &advance) != 0) {
            SDL_FreeSurface(initial);
            SDL_FreeSurface(intermediary);
            IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_GlyphMetrics() failed" << std::endl;
            return;
        }

        FontGlyph *glyph = new FontGlyph;
        glyph->texture = texture;
        glyph->min_x = minx;
        glyph->min_y = miny;
        glyph->top_y = fp->ascent - maxy;
        glyph->width = initial->w + 1;
        glyph->height = initial->h + 1;
        glyph->max_x = static_cast<float>(initial->w + 1) / static_cast<float>(w);
        glyph->max_y = static_cast<float>(initial->h + 1) / static_cast<float>(h);
        glyph->advance = advance;

        (*fp->glyph_cache)[character] = glyph;

        SDL_FreeSurface(initial);
        SDL_FreeSurface(intermediary);
    }
} // void TextSupervisor::_CacheGlyphs(const uint16* text, FontProperties* fp)
예제 #15
0
    SpriteFont::SpriteFont(const char* font, int size, char cs, char ce) {
        // Initialize SDL_ttf
        if (!TTF_WasInit()) {
            TTF_Init();
        }
        TTF_Font* f = TTF_OpenFont(font, size);
        if (f == nullptr) {
            fprintf(stderr, "Failed to open TTF font %s\n", font);
            fflush(stderr);
            throw 281;
        }
        _fontHeight = TTF_FontHeight(f);
        _regStart = cs;
        _regLength = ce - cs + 1;
        int padding = size / 8;

        // First neasure all the regions
        glm::ivec4* glyphRects = new glm::ivec4[_regLength];
        int i = 0, advance;
        for (char c = cs; c <= ce; c++) {
            TTF_GlyphMetrics(f, c, &glyphRects[i].x, &glyphRects[i].z, &glyphRects[i].y, &glyphRects[i].w, &advance);
            glyphRects[i].z -= glyphRects[i].x;
            glyphRects[i].x = 0;
            glyphRects[i].w -= glyphRects[i].y;
            glyphRects[i].y = 0;
            i++;
        }

        // Find best partitioning of glyphs
        int rows = 1, w, h, bestWidth = 0, bestHeight = 0, area = MAX_TEXTURE_RES * MAX_TEXTURE_RES, bestRows = 0;
        std::vector<int>* bestPartition = nullptr;
        while (rows <= _regLength) {
            h = rows * (padding + _fontHeight) + padding;
            auto gr = createRows(glyphRects, _regLength, rows, padding, w);

            // Desire a power of 2 texture
            w = closestPow2(w);
            h = closestPow2(h);

            // A texture must be feasible
            if (w > MAX_TEXTURE_RES || h > MAX_TEXTURE_RES) {
                rows++;
                delete[] gr;
                continue;
            }

            // Check for minimal area
            if (area >= w * h) {
                if (bestPartition) delete[] bestPartition;
                bestPartition = gr;
                bestWidth = w;
                bestHeight = h;
                bestRows = rows;
                area = bestWidth * bestHeight;
                rows++;
            } else {
                delete[] gr;
                break;
            }
        }

        // Can a bitmap font be made?
        if (!bestPartition) {
            fprintf(stderr, "Failed to Map TTF font %s to texture. Try lowering resolution.\n", font);
            fflush(stderr);
            throw 282;
        }
        // Create the texture
        glGenTextures(1, &_texID);
        glBindTexture(GL_TEXTURE_2D, _texID);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bestWidth, bestHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

        // Now draw all the glyphs
        SDL_Color fg = { 255, 255, 255, 255 };
        int ly = padding;
        for (int ri = 0; ri < bestRows; ri++) {
            int lx = padding;
            for (size_t ci = 0; ci < bestPartition[ri].size(); ci++) {
                int gi = bestPartition[ri][ci];

                SDL_Surface* glyphSurface = TTF_RenderGlyph_Blended(f, (char)(cs + gi), fg);

                // Pre-multiplication occurs here
                unsigned char* sp = (unsigned char*)glyphSurface->pixels;
                int cp = glyphSurface->w * glyphSurface->h * 4;
                for (int i = 0; i < cp; i += 4) {
                    float a = sp[i + 3] / 255.0f;
                    sp[i] = (unsigned char)((float)sp[i] * a);
                    sp[i + 1] = sp[i];
                    sp[i + 2] = sp[i];
                }

                // Save glyph image and update coordinates
                glTexSubImage2D(GL_TEXTURE_2D, 0, lx, bestHeight - ly - 1 - glyphSurface->h, glyphSurface->w, glyphSurface->h, GL_BGRA, GL_UNSIGNED_BYTE, glyphSurface->pixels);
                glyphRects[gi].x = lx;
                glyphRects[gi].y = ly;
                glyphRects[gi].z = glyphSurface->w;
                glyphRects[gi].w = glyphSurface->h;

                SDL_FreeSurface(glyphSurface);
                glyphSurface = nullptr;

                lx += glyphRects[gi].z + padding;
            }
            ly += _fontHeight + padding;
        }

        // Draw the unsupported glyph
        int rs = padding - 1;
        int* pureWhiteSquare = new int[rs * rs];
        memset(pureWhiteSquare, 0xffffffff, rs * rs * sizeof(int));
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rs, rs, GL_RGBA, GL_UNSIGNED_BYTE, pureWhiteSquare);
        delete[] pureWhiteSquare;
        pureWhiteSquare = nullptr;

        // Set some texture parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        // Create spriteBatch glyphs
        _glyphs = new CharGlyph[_regLength + 1];
        for (i = 0; i < _regLength; i++) {
            _glyphs[i].character = (char)(cs + i);
            _glyphs[i].size = glm::vec2(glyphRects[i].z, glyphRects[i].w);
            _glyphs[i].uvRect = glm::vec4(
                (float)glyphRects[i].x / (float)bestWidth,
                (float)glyphRects[i].y / (float)bestHeight,
                (float)glyphRects[i].z / (float)bestWidth,
                (float)glyphRects[i].w / (float)bestHeight
                );
        }
        _glyphs[_regLength].character = ' ';
        _glyphs[_regLength].size = _glyphs[0].size;
        _glyphs[_regLength].uvRect = glm::vec4(0, 0, (float)rs / (float)bestWidth, (float)rs / (float)bestHeight);

        glBindTexture(GL_TEXTURE_2D, 0);
        delete[] glyphRects;
        delete[] bestPartition;
        TTF_CloseFont(f);
    }
예제 #16
0
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;
}
예제 #17
0
Font::Font(const std::string& path, int size)
{
    TTF_Font* font = TTF_OpenFont(path.c_str(), size);
    if (!font)
    {
        fatalError("Failed to open font '" + path + "'.");
    }
    SDL_Color color {255, 255, 255, 255};
    SDL_Surface* surfaces [NUM_GLYPHS];
    for (int i = 0; i < NUM_GLYPHS; i++)
    {
        char c = FIRST_CHAR + i;
        TTF_GlyphMetrics(
                font, c, 
                &glyph_metrics_map_[i].min_x,
                &glyph_metrics_map_[i].max_x,
                &glyph_metrics_map_[i].min_y,
                &glyph_metrics_map_[i].max_y,
                &glyph_metrics_map_[i].advance);
        surfaces[i] = TTF_RenderGlyph_Blended(font, c, color);
    }
    int font_height = TTF_FontHeight(font);
    int font_offset = font_height - TTF_FontAscent(font);
    int num_glyphs_per_row = 16;
    int num_rows = (NUM_GLYPHS - 1) / num_glyphs_per_row + 1;
    int max_row_width = 0;
    for (int i = 0; i < num_rows; i++)
    {
        int row_width = 0;
        for (int j = 0; j < num_glyphs_per_row; j++)
        {
            int index = i * num_glyphs_per_row + j;
            if (index >= NUM_GLYPHS)
                break;
            row_width += surfaces[index]->w;
        }
        if (row_width > max_row_width)
            max_row_width = row_width;
    }
    int atlas_height = num_rows * font_height;
    int atlas_width =  max_row_width;
    int cursor_x = 0;
    int cursor_y = 0;
    int bytes_per_pixel = 4;
    std::vector<uint8_t> atlas_pixels (bytes_per_pixel * atlas_height * atlas_width);
    for (int i = 0; i < num_rows; i++)
    {
        for (int j = 0; j < num_glyphs_per_row; j++)
        {
            int index = i * num_glyphs_per_row + j;
            if (index >= NUM_GLYPHS)
                break;
            SDL_Surface* surface = surfaces[index];
            for (int k = 0; k < font_height; k++)
            {
                for (int l = 0; l < surface->w; l++)
                {
                    int atlas_index = bytes_per_pixel * ((cursor_y + k) * atlas_width + cursor_x + l);
                    int surface_index = bytes_per_pixel * ((surface->h - k - 1) * surface->w + l);
                    for (int m = 0; m < bytes_per_pixel; m++)
                    {
                        atlas_pixels[atlas_index + m] = reinterpret_cast<uint8_t*>(surface->pixels)[surface_index + m];
                    }
                }
            }
            GlyphMetrics& metrics = glyph_metrics_map_[index];
            GlyphBound& bound = glyph_bound_map_[index];
            bound.min_s = double(cursor_x + metrics.min_x) / atlas_width;
            bound.max_s = double(cursor_x + metrics.max_x) / atlas_width;
            bound.min_t = double(cursor_y + font_offset + metrics.min_y) / atlas_height;
            bound.max_t = double(cursor_y + font_offset + metrics.max_y) / atlas_height;
            cursor_x += surface->w;
        }
        cursor_x = 0;
        cursor_y += font_height;
    }
    for (int i = 0; i < NUM_GLYPHS; i++)
    {
        SDL_FreeSurface(surfaces[i]);
    }
    TTF_CloseFont(font);
    glGenTextures(1, &atlas_);
    glBindTexture(GL_TEXTURE_2D, atlas_);
    glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RGBA,
            atlas_width,
            atlas_height,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            atlas_pixels.data());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
예제 #18
0
bool Fonte::criarTexturaTrueType(TTF_Font* ttf_font, int tamanho, Uint16 primeiro_glifo, Uint16 ultimo_glifo, EnumQualidadeEscala qualidade_escala)
{
	ascent = TTF_FontAscent(ttf_font);

	int larg_glifo = tamanho;
	int alt_glifo = TTF_FontHeight(ttf_font);
	if (ultimo_glifo < primeiro_glifo)
		ultimo_glifo = primeiro_glifo;

	Uint16 num_glifos = ultimo_glifo - primeiro_glifo + 1;
	Uint16 glifos_por_linha = sqrt(num_glifos);
	if (glifos_por_linha*glifos_por_linha != num_glifos)
		glifos_por_linha++;
	Uint16 glifos_por_coluna = ceilf((float)num_glifos / (float)glifos_por_linha);
	int larg = glifos_por_linha*larg_glifo;
	int alt = glifos_por_coluna*alt_glifo;

	glifos.resize(num_glifos);

	Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	SDL_Surface* surface = SDL_CreateRGBSurface(0, larg, alt, 32, rmask, gmask, bmask, amask);
	if (!surface)
	{
		return false;
	}
	SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
	SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, 0));
	SDL_Color cor_glifo = { 255, 255, 255, 255 };
	SDL_Rect rect;

	Uint16 i_glifo = 0;
	Uint16 lin = 0, col = 0;
	Glifo* g;
	for (Uint16 i = primeiro_glifo; i <= ultimo_glifo; ++i)
	{
		g = &glifos[i_glifo];
		g->caractere = i;
		SDL_Surface* surface_glifo = TTF_RenderGlyph_Blended(ttf_font, g->caractere, cor_glifo);
		if (surface_glifo)
		{
			SDL_SetSurfaceBlendMode(surface_glifo, SDL_BLENDMODE_BLEND);
			rect.x = col*larg_glifo;
			rect.y = lin*alt_glifo;
			rect.w = surface_glifo->w;
			rect.h = surface_glifo->h;
			SDL_BlitSurface(surface_glifo, NULL, surface, &rect);
			SDL_FreeSurface(surface_glifo);

			int minx, miny, maxx, maxy, av;
			TTF_GlyphMetrics(ttf_font, g->caractere, &minx, &maxx, &miny, &maxy, &av);
			g->avanco = av;
			g->quad.x = (col*larg_glifo);
			g->quad.y = (lin*alt_glifo) + ascent - maxy;
			g->quad.larg = rect.w;
			g->quad.alt = maxy - miny;
			g->dx = minx;
			g->alturaAcimaDaBase = maxy;
		}
		else
		{
			g->avanco = tamanho;
			g->quad.x = 0;
			g->quad.y = 0;
			g->quad.larg = 0;
			g->quad.alt = 0;
			g->dx = 0;
			g->alturaAcimaDaBase = 0;
		}

		++i_glifo;
		++col;
		if (col == glifos_por_linha)
		{
			col = 0;
			++lin;
		}
	}

	bool r = tex.criarDaSDL_Surface(surface, qualidade_escala);
	SDL_FreeSurface(surface);

	if (r)
	{
		numGlifosX = glifos_por_linha;
		numGlifosY = glifos_por_coluna;
	}

	return r;
}