void InputNode::renderText()
	{
		if ( _image != NULL )
			SDL_FreeSurface(_image);

		_image = TTF_RenderUNICODE_Blended(_font, _str, _foreground);

		// Account for input text scroll
		if ( _image != NULL && _image->clip_rect.w > _pos.w - 10 )
			_scroll.x = _image->clip_rect.w - _pos.w + 10;
		else
			_scroll.x = 0;

		// Get width of the text string by placing
		// a null byte character up to the point we
		// want to count, then putting the original
		// back. Nice.
		int w;
		Uint16 t = _str[_curr_index];
		_str[_curr_index] = '\0';
		TTF_SizeUNICODE(_font, _str, &w, NULL);
		_str[_curr_index] = t;

		_cursor_rect.x = w - _scroll.x;

		if ( _cursor_rect.x < 0 )
		{
			_scroll.x += _cursor_rect.x;
			_cursor_rect.x = 0;
		}
	}
示例#2
0
void Console::writeText(const Uint16 * text, int size, SDL_Color color){
	wprintf((const wchar_t*)text);
	printf("\n");
	/* font start*/
	SDL_Surface * tempsurface = 0;
	TTF_Font *font;
	font=TTF_OpenFont(this->m_font.c_str(), size);
	if(!font) {
		printf("TTF_OpenFont: %s\n", TTF_GetError());
		// handle error
	}
	/*do stuff with font*/
	int height, width;
	SDL_Rect r;
	r.x = 0;
	r.y = 0;
	int mul = this->m_lines.size();
	//if (mul<1) mul=1;
	if (font) {
		TTF_SizeUNICODE(font, text, &width, &height);					
		tempsurface = TTF_RenderUNICODE_Blended(font, text, color);
		r.w = width;
		r.h = height;
		r.y = height * mul;
		//printf("%d %d %d %d\n", r.w, r.h, r.x, m_lines.size());
		SDL_FillRect(this->m_psurface, &r, SDL_MapRGBA(this->m_psurface->format, 0,0,0,0));
		SDL_BlitSurface(tempsurface, NULL, this->m_psurface, &r);
		TTF_CloseFont(font);
		font=NULL; // to be safe...
		}
	delete (tempsurface);
	/* font end */
}
示例#3
0
void SDLFontGL::setupFontGL(int fnCount, TTF_Font** fnts, int colCount, SDL_Color *cols) {
	clearGL();

	assert(fnts && cols);
	assert((fnCount > 0) && (colCount > 0));

	nFonts = fnCount;
	nCols = colCount;

	this->fnts = (TTF_Font**)malloc(nFonts*sizeof(TTF_Font*));
	memcpy(this->fnts, fnts, nFonts*sizeof(TTF_Font*));

	this->cols = (SDL_Color*)malloc(nCols*sizeof(SDL_Color));
	memcpy(this->cols, cols, nCols*sizeof(SDL_Color));

	GlyphCache = 0;

	haveCacheLine = (bool*)malloc(nFonts*MAX_CHARSETS*sizeof(bool));
	memset(haveCacheLine, 0, nFonts*MAX_CHARSETS*sizeof(bool));

	const Uint16 OStr[] = {'O', 0};
	if (TTF_SizeUNICODE(fnts[0], OStr, &nWidth, &nHeight) != 0)
		assert(0 && "Failed to size font");
	assert((nWidth > 0) && (nHeight > 0));
}
示例#4
0
/*!
	\param string text string
	\param length length of string
	\return character width
*/
int Storm3D_Font::GetCharacterWidth(wchar_t *string, int length) const
{
	int w, h;
	if(font)
	{
		if (sizeof(wchar_t) == 2) {
			TTF_SizeUNICODE(font, (Uint16*)string, &w, &h);
			return w;
		} else {
			Uint16 *tmp = new Uint16[length+1];
			for (unsigned int i = 0; i < (unsigned int)(length + 1); ++i)
				tmp[i] = string[i] & 0xffff;
			TTF_SizeUNICODE(font, tmp, &w, &h);
			delete [] tmp;
			return w;
		}
	}

	return 0;
}
示例#5
0
JNIEXPORT jint JNICALL Java_sdljava_x_swig_SWIG_1SDLTTFJNI_TTF_1SizeUNICODE(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) {
    jint jresult = 0 ;
    TTF_Font *arg1 = (TTF_Font *) 0 ;
    Uint16 *arg2 = (Uint16 *) 0 ;
    int *arg3 = (int *) 0 ;
    int *arg4 = (int *) 0 ;
    int result;
    int temp3 ;
    int temp4 ;
    
    (void)jenv;
    (void)jcls;
    arg1 = *(TTF_Font **)&jarg1; 
    arg2 = *(Uint16 **)&jarg2; 
    {
        if (!jarg3) {
            SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
            return 0;
        }
        if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) {
            SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
            return 0;
        }
        arg3 = &temp3; 
    }
    {
        if (!jarg4) {
            SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
            return 0;
        }
        if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) {
            SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
            return 0;
        }
        arg4 = &temp4; 
    }
    result = (int)TTF_SizeUNICODE(arg1,(Uint16 const *)arg2,arg3,arg4);
    
    jresult = (jint)result; 
    {
        jint jvalue = (jint)temp3;
        (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue);
    }
    {
        jint jvalue = (jint)temp4;
        (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue);
    }
    return jresult;
}
示例#6
0
int32 TextSupervisor::CalculateTextWidth(const std::string &font_name, const vt_utils::ustring &text)
{
    if(IsFontValid(font_name) == false) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "font name argument was invalid: " << font_name << std::endl;
        return -1;
    }

    int32 width;
    if(TTF_SizeUNICODE(_font_map[font_name]->ttf_font, text.c_str(), &width, NULL) == -1) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_SizeUNICODE failed with TTF error: " << TTF_GetError() << std::endl;
        return -1;
    }

    return width;
}
示例#7
0
// Get real text dimensions -- the textshape will completely contain the 
// rendered text but won't match its size.  This function can be used to
// get the true position and dimensions of the rendered text.
//
// The fifth argument, b, is the baseline of the text
void TextShape::getTextDimensions(int *x, int *y, int *w, int *h, int *b,
        int *yOff)
{
    if (textShapeFont[fontSize] == NULL)
    {
        textShapeFont[fontSize] = FONT_LoadTTF("FreeSans.ttf", fontSize);
    }
    assert(textShapeFont[fontSize] != NULL);

    int realH = 0;
    Uint16 *ch = unicodeStr;
    int overallMaxY = 0;
    while (*ch != '\0')
    {
        int minx, maxx, miny, maxy, advance;

        int err = TTF_GlyphMetrics(textShapeFont[fontSize], *ch, &minx,
                &maxx, &miny, &maxy, &advance);
        if (!err)
        {
            realH = std::max(realH, maxy - miny + 1);
            overallMaxY = std::max(overallMaxY, maxy);
        }
        else
        {
            printf("warning: TTF_GlyphMetrics returned an error\n");
        }
        ch++;
    }
    int ascent = TTF_FontAscent(textShapeFont[fontSize]);
    int realYOffset = ascent - overallMaxY;

    // Can't get width from the individual glyphs due to kerning issues, 
    // just call TTF_SizeUNICODE
    int textw, dummy;
    // Get text size:
    TTF_SizeUNICODE(textShapeFont[fontSize], unicodeStr, &textw, &dummy);

    if (x)  *x = xpos + cxoff;
    if (y)  *y = ypos + cyoff;
    if (w)  *w = textw;
    if (h)  *h = realH;
    if (b)  *b = ypos + overallMaxY + cxoff;

    if (yOff) *yOff = realYOffset;
}
示例#8
0
		int LOBJECT_METHOD(getTextSizeUNICODE, TTF_Font * font){
			if (state.is_string(1)){
				int w = 0;
				int h = 0;

				int result = TTF_SizeUNICODE(font, reinterpret_cast<const Uint16*>(state.to_string(1).c_str()), &w, &h);
				if (result == 0){
					state.push_integer(w);
					state.push_integer(h);
					return 2;
				}else{
					state.push_boolean(false);
					return 1;
				}
			}
			return 0;
		}
示例#9
0
static mrb_value
mrb_sdl2_ttf_font_get_size_UNICODE(mrb_state *mrb, mrb_value self)
{
  mrb_value text;
  int w, h;
  mrb_value result;
  mrb_get_args(mrb, "S", &text);

  if (TTF_SizeUNICODE(mrb_sdl2_font_get_ptr(mrb, self), (Uint16 *) RSTRING_PTR(text), &w, &h) == -1) {
    mruby_sdl2_raise_error(mrb);
    return mrb_false_value();
  }
  result = mrb_ary_new_capa(mrb, 2);
  mrb_ary_push(mrb, result, mrb_fixnum_value(w));
  mrb_ary_push(mrb, result, mrb_fixnum_value(h));
  return result;
}
示例#10
0
int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h)
{
	Uint16 *unicode_text;
	int unicode_len;
	int status;

	/* Copy the UTF-8 text to a UNICODE text buffer */
	unicode_len = strlen(text);
	unicode_text = (Uint16 *)malloc((unicode_len+1)*(sizeof *unicode_text));
	if ( unicode_text == NULL ) {
		SDL_SetError("Out of memory");
		return -1;
	}
	UTF8_to_UNICODE(unicode_text, text, unicode_len);

	/* Render the new text */
	status = TTF_SizeUNICODE(font, unicode_text, w, h);

	/* Free the text buffer and return */
	free(unicode_text);
	return status;
}
示例#11
0
文件: gui.c 项目: chinaktv/gxgui
int get_text_width(FontDesc *font, const char *text)
{
	if (font == NULL) return 0;

#ifdef USE_TTF
	uint16_t cBuf[BUF_LEN];
	const char *i18n_text = i18n(text);
	memset(cBuf, '\0', BUF_LEN);

	UTF8_to_UNICODE(cBuf, i18n_text);
	if (font->fonthandle == NULL)
		font->fonthandle = TTF_OpenFont(font->filename, FONT_SIZE);

	if (font->fonthandle) {
		int w = 0, h = 0;
		TTF_SizeUNICODE((TTF_Font *)font->fonthandle, cBuf, &w, &h);
		return w;
	}
#else
	return 24;
#endif
	return 0;
}
示例#12
0
PREFIX void spFontChangeLetter( spFontPointer font, spLetterPointer letter, Uint32 character, Uint16 color )
{
	letter->color = color;
	Uint16 buffer[2];
	buffer[0] = character;
	buffer[1] = 0;
	SDL_Color sdlcolor = {( color >> 11 ) << 3, ( ( color << 5 ) >> 10 ) << 2, ( ( color & 31 ) << 3 )};
	SDL_Surface* surface;
	if (spFontBackgroundColor == SP_FONT_NO_BORDER)
		surface = TTF_RenderUNICODE_Solid( font->font, buffer, sdlcolor );
	else
	{
		SDL_Color background =	{( spFontBackgroundColor >> 11 ) << 3, ( ( spFontBackgroundColor << 5 ) >> 10 ) << 2, ( ( spFontBackgroundColor & 31 ) << 3 )};
		surface = TTF_RenderUNICODE_Shaded( font->font, buffer, sdlcolor ,background );
	}
	if (!surface)
		surface = spCreateSurface(0,font->maxheight);
	int width = surface->w + SP_FONT_EXTRASPACE * 2;
	if ( width & 1 )
		width++;
	letter->surface = spCreateSurface(width, surface->h + SP_FONT_EXTRASPACE * 2);
	SDL_FillRect( letter->surface, NULL, SP_ALPHA_COLOR );

	SDL_Rect DestR;
	DestR.x = SP_FONT_EXTRASPACE;
	DestR.y = SP_FONT_EXTRASPACE;
	DestR.w = surface->w;
	DestR.h = surface->h;
	SDL_BlitSurface( surface, NULL, letter->surface, &DestR );
	SDL_FreeSurface( surface );

	//Setting every spFontBackgroundColor to the alpha color
	SDL_LockSurface( letter->surface );
	Uint16* pixel = ( Uint16* )( letter->surface->pixels );
	int scanline = letter->surface->pitch/letter->surface->format->BytesPerPixel;
	int x, y;
	for ( x = 0; x < letter->surface->w; x++ )
		for ( y = 0; y < letter->surface->h; y++ )
			if ( pixel[x + y * scanline] == spFontBackgroundColor )
				pixel[x + y * scanline] = SP_ALPHA_COLOR;
	SDL_UnlockSurface( letter->surface );

	TTF_SizeUNICODE( font->font, buffer, &( letter->width ), &( letter->height ) );
	if ( font->maxheight < letter->height )
		font->maxheight = letter->height;
}

static void spFontInternalAddOneCharacter( spFontPointer font, Uint32 character, Uint16 color )
{
	if (spFontGetLetter(font,character))
		return;
	spLetterPointer letter = ( spLetterPointer )malloc( sizeof( spLetter ) );

	spFontChangeLetter( font, letter, character, color );
	letter->character = character;

	//tree insert
	font->root = spFontInsert( letter, font->root );
}

PREFIX void spFontAdd( spFontPointer font, char* characters, Uint16 color )
{
	//parsing the characters string.
	int pos = 0;
	while (1)
	{
		Uint32 character = spFontGetUnicodeFromUTF8(&(characters[pos]));
		if (character == 0)
			break;
		pos+=spFontLastUTF8Length;
		spFontInternalAddOneCharacter(font,character,color);
	}
}

PREFIX void spFontAddRange( spFontPointer font, char* from, char* to, Uint16 color )
{
	//getting the characters strings
	Uint32 c_from = spFontGetUnicodeFromUTF8(from);
	if (c_from == 0)
		return;
	Uint32 c_to = spFontGetUnicodeFromUTF8(to);
	if (c_to == 0)
		return;
	Uint32 character;
	if (c_from > c_to)
	{
		character = c_from;
		c_from = c_to;
		c_to = character;
	}
	for (character = c_from; character <= c_to; character++)
		spFontInternalAddOneCharacter(font,character,color);
}
示例#13
0
/**************************************************************************
  ...
**************************************************************************/
SDL_Rect str16size(SDL_String16 *pString16)
{
  SDL_Rect Ret = {0, 0, 0, 0};
  
  if (pString16 && pString16->text && pString16->text != '\0') {
    Uint16 *pStr16 = pString16->text;
    Uint16 c = *pStr16;
    bool new_line = FALSE;
    int w, h;
    
    /* find '\n' */
    while (c != '\0') {
      if (c == 10) {
	new_line = TRUE;
	break;
      }
      pStr16++;
      c = *pStr16;
    }
   
    if (!((pString16->style & 0x0F) & TTF_STYLE_NORMAL)) {
      TTF_SetFontStyle(pString16->font, (pString16->style & 0x0F));
    }
    
    if (new_line) {
      int ww, hh, count = 0;
      Uint16 **UniTexts = create_new_line_unistrings(pString16->text);
      
      w = 0;
      h = 0;
      while (UniTexts[count]) {
        if (TTF_SizeUNICODE(pString16->font, UniTexts[count], &ww, &hh) < 0) {
          do {
	    FC_FREE(UniTexts[count]);
            count++;
	  } while(UniTexts[count]);
          log_error("TTF_SizeUNICODE return ERROR !");
        }
        w = MAX(w, ww);
        h += hh;
        FC_FREE(UniTexts[count]);
        count++;
      }
    } else {  
      if (TTF_SizeUNICODE(pString16->font, pString16->text, &w, &h) < 0) {
        log_error("TTF_SizeUNICODE return ERROR !");
      }
    }
   
    if (!((pString16->style & 0x0F) & TTF_STYLE_NORMAL)) {
      TTF_SetFontStyle(pString16->font, TTF_STYLE_NORMAL);
    }
    
    Ret.w = w;
    Ret.h = h;
  } else {
    Ret.h = (pString16 ? TTF_FontHeight(pString16->font) : 0);
  }
  
  return Ret;
}
示例#14
0
SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font,
				const Uint16 *text, SDL_Color fg)
{
	int xstart, width;
	int w, h;
	SDL_Surface *textbuf;
	SDL_Palette *palette;
	const Uint16 *ch;
	Uint8 *src, *dst;
	int row, col;
	TT_Error error;

	/* Get the dimensions of the text surface */
	if ( (TTF_SizeUNICODE(font, text, &w, &h) < 0) || !w ) {
		TTF_SetError("Text has zero width");
		return(NULL);
	}

	/* Create the target surface */
	width = w;
	w = (w+7)&~7;
	textbuf = SDL_AllocSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
	if ( textbuf == NULL ) {
		return(NULL);
	}

	/* Fill the palette with the foreground color */
	palette = textbuf->format->palette;
	palette->colors[0].r = 255-fg.r;
	palette->colors[0].g = 255-fg.g;
	palette->colors[0].b = 255-fg.b;
	palette->colors[1].r = fg.r;
	palette->colors[1].g = fg.g;
	palette->colors[1].b = fg.b;
	SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, 0);

	/* Load and render each character */
	xstart = 0;
	for ( ch=text; *ch; ++ch ) {
		error = Find_Glyph(font, *ch);
		if ( ! error ) {
			w = font->current->bitmap.width;
			src = (Uint8 *)font->current->bitmap.bitmap;
			for ( row = 0; row < h; ++row ) {
				dst = (Uint8 *)textbuf->pixels +
				               row * textbuf->pitch +
				               xstart + font->current->minx;
				for ( col = 0; col < w; col += 8 ) {
					Uint8 c = *src++;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
					c <<= 1;
					*dst++ |= (c&0x80)>>7;
				}
			}
			xstart += font->current->advance;
			if ( font->style & TTF_STYLE_BOLD ) {
				xstart += font->glyph_overhang;
			}
		}
	}
示例#15
0
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)
示例#16
0
void TextSupervisor::_DrawTextHelper(const uint16 *const text, FontProperties *fp, Color text_color)
{
    if(*text == 0) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "invalid argument, empty string" << std::endl;
        return;
    }

    if(fp == NULL) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "invalid argument, NULL font properties" << std::endl;
        return;
    }

    glBlendFunc(GL_ONE, GL_ONE);
    VideoManager->EnableBlending();

    CoordSys &cs = VideoManager->_current_context.coordinate_system;

    _CacheGlyphs(text, fp);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    VideoManager->EnableTexture2D();

    VideoManager->PushMatrix();

    int font_width, font_height;
    if(TTF_SizeUNICODE(fp->ttf_font, text, &font_width, &font_height) != 0) {
        IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_SizeUNICODE() failed" << std::endl;
        return;
    }

    float xoff = ((VideoManager->_current_context.x_align + 1) * font_width) * 0.5f * -cs.GetHorizontalDirection();
    float yoff = ((VideoManager->_current_context.y_align + 1) * font_height) * 0.5f * -cs.GetVerticalDirection();

    VideoManager->MoveRelative(xoff, yoff);

    VideoManager->EnableVertexArray();
    VideoManager->EnableTextureCoordArray();

    GLint vertices[8];
    GLfloat tex_coords[8];
    glVertexPointer(2, GL_INT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT, 0, tex_coords);

    // Iterate through each character in the string and render the character glyphs one at a time
    int xpos = 0;
    for(const uint16 *glyph = text; *glyph != 0; ++glyph) {
        FontGlyph *glyph_info = (*fp->glyph_cache)[*glyph];

        int x_hi = glyph_info->width;
        int y_hi = glyph_info->height;
        if(cs.GetHorizontalDirection() < 0.0f)
            x_hi = -x_hi;
        if(cs.GetVerticalDirection() < 0.0f)
            y_hi = -y_hi;

        int min_x, min_y;
        min_x = glyph_info->min_x * static_cast<int>(cs.GetHorizontalDirection()) + xpos;
        min_y = glyph_info->min_y * static_cast<int>(cs.GetVerticalDirection());

        float tx, ty;
        tx = glyph_info->max_x;
        ty = glyph_info->max_y;

        TextureManager->_BindTexture(glyph_info->texture);
        if(VideoManager->CheckGLError()) {
            IF_PRINT_WARNING(VIDEO_DEBUG) << "OpenGL error detected: " << VideoManager->CreateGLErrorString() << std::endl;
            return;
        }

        vertices[0] = min_x;
        vertices[1] = min_y;
        vertices[2] = min_x + x_hi;
        vertices[3] = min_y;
        vertices[4] = min_x + x_hi;
        vertices[5] = min_y + y_hi;
        vertices[6] = min_x;
        vertices[7] = min_y + y_hi;
        tex_coords[0] = 0.0f;
        tex_coords[1] = ty;
        tex_coords[2] = tx;
        tex_coords[3] = ty;
        tex_coords[4] = tx;
        tex_coords[5] = 0.0f;
        tex_coords[6] = 0.0f;
        tex_coords[7] = 0.0f;

        glColor4fv((GLfloat *)&text_color);
        glDrawArrays(GL_QUADS, 0, 4);

        xpos += glyph_info->advance;
    } // for (const uint16* glyph = text; *glyph != 0; glyph++)

    VideoManager->PopMatrix();
} // void TextSupervisor::_DrawTextHelper(const uint16* const text, FontProperties* fp, Color color)