Bring back quesoGLC to Warzone.

This renders the text much faster than what Qt offers, and also fixes issues with Vsync being ON, on windows.

patch fixes by Safety0ff

closes ticket:2824

This patch basically reverts:
828c0f72ae
Revert 9e29aa5210 which reverted the removal of QuesoGLC, to start
    working on fixing the font rendering with Qt.

NOTE: On some systems, there is a assertion failure with FcFini().
We could fix the issue by doing a embed of quesoGLC in our repo, or hope the fontconfig
guys fix the issue upstream.
See ticket:2824 for more discussion on this issue.
master
vexed 2011-07-17 13:15:15 -04:00
parent f8e1c75a48
commit ebc8976dc1
5 changed files with 501 additions and 1 deletions

View File

@ -410,6 +410,9 @@ AC_CHECK_LIB(GLU, main,
[${OPENGL_LIBS} -lm]), [${OPENGL_LIBS} -lm])
AC_SUBST([OPENGL_LIBS], [${OPENGL_LIBS}])
# Look for OpenGLC
PKG_CHECK_MODULES([OPENGLC], [quesoglc >= 0.7.2])
# When (cross-)compiling for Windows (MinGW) we need to link in BFD for the Dr.
# MinGW derived exception handler.
if test "x$host_os_mingw32" = "xyes" ; then

View File

@ -1079,6 +1079,9 @@ int wzSemaphoreAvailable(WZ_SEMAPHORE *semaphore)
/*** Font support ***/
/**************************/
// Font and text drawing support based on Qt postponed until we can get it working properly on
// all platforms, and with decent speed, and without clobbering existing OpenGL states.
#if 0
void iV_SetFont(enum iV_fonts FontID)
{
WzMainWindow::instance()->setFontType(FontID);
@ -1159,6 +1162,13 @@ void iV_DrawTextRotated(const char* string, float XPos, float YPos, float rotati
pie_SetRendMode(REND_OPAQUE); // beat state machinery into submission
}
void iV_SetTextSize(float size)
{
WzMainWindow::instance()->setFontSize(size);
}
#endif
void wzFatalDialog(const char *text)
{
crashing = true;

View File

@ -1,4 +1,4 @@
AM_CPPFLAGS = $(PNG_CFLAGS) $(OPENGL_CFLAGS) $(WZ_CPPFLAGS) $(GLEW_CFLAGS) $(QT4_CFLAGS)
AM_CPPFLAGS = $(PNG_CFLAGS) $(OPENGL_CFLAGS) $(OPENGLC_CFLAGS) $(WZ_CPPFLAGS) $(GLEW_CFLAGS) $(QT4_CFLAGS)
AM_CFLAGS = $(WZ_CFLAGS) -Wno-missing-declarations
AM_CXXFLAGS = $(WZ_CXXFLAGS) $(QT4_CFLAGS)

View File

@ -36,6 +36,412 @@
#define ASCII_NEWLINE ('@')
#define ASCII_COLOURMODE ('#')
#ifdef WZ_OS_MAC
# include <QuesoGLC/glc.h>
#else
# include <GL/glc.h>
#endif
static char font_family[128];
static char font_face_regular[128];
static char font_face_bold[128];
static float font_size = 12.f;
// Contains the font color in the following order: red, green, blue, alpha
static float font_colour[4] = {1.f, 1.f, 1.f, 1.f};
static GLint _glcContext = 0;
static GLint _glcFont_Regular = 0;
static GLint _glcFont_Bold = 0;
/***************************************************************************/
/*
* Source
*/
/***************************************************************************/
void iV_font(const char *fontName, const char *fontFace, const char *fontFaceBold)
{
if (_glcContext)
{
debug(LOG_ERROR, "Cannot change font in running game, yet.");
return;
}
if (fontName)
{
sstrcpy(font_family, fontName);
}
if (fontFace)
{
sstrcpy(font_face_regular, fontFace);
}
if (fontFaceBold)
{
sstrcpy(font_face_bold, fontFaceBold);
}
}
static inline void iV_printFontList(void)
{
unsigned int i;
unsigned int font_count = glcGeti(GLC_CURRENT_FONT_COUNT);
debug(LOG_NEVER, "GLC_CURRENT_FONT_COUNT = %d", font_count);
if (font_count == 0)
{
debug(LOG_ERROR, "The required font (%s) isn't loaded", font_family);
// Fall back to unselected fonts since the requested font apparently
// isn't available.
glcEnable(GLC_AUTO_FONT);
}
for (i = 0; i < font_count; ++i)
{
GLint font = glcGetListi(GLC_CURRENT_FONT_LIST, i);
/* The output of the family name and the face is printed using 2 steps
* because glcGetFontc and glcGetFontFace return their result in the
* same buffer (according to GLC specs).
*/
char prBuffer[1024];
snprintf(prBuffer, sizeof(prBuffer), "Font #%d : %s ", (int)font, (const char*)glcGetFontc(font, GLC_FAMILY));
prBuffer[sizeof(prBuffer) - 1] = 0;
sstrcat(prBuffer, (char const *)glcGetFontFace(font));
debug(LOG_NEVER, "%s", prBuffer);
}
}
static void iV_initializeGLC(void)
{
if (_glcContext)
{
return;
}
_glcContext = glcGenContext();
if (!_glcContext)
{
debug(LOG_ERROR, "Failed to initialize");
}
else
{
debug(LOG_NEVER, "Successfully initialized. _glcContext = %d", (int)_glcContext);
}
glcContext(_glcContext);
glcEnable(GLC_AUTO_FONT); // We *do* want font fall-backs
glcRenderStyle(GLC_TEXTURE);
glcStringType(GLC_UTF8_QSO); // Set GLC's string type to UTF-8 FIXME should be UCS4 to avoid conversions
#ifdef WZ_OS_MAC
{
char resourcePath[PATH_MAX];
CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
if (CFURLGetFileSystemRepresentation(resourceURL, true, (UInt8 *) resourcePath, PATH_MAX))
{
sstrcat(resourcePath, "/Fonts");
glcAppendCatalog(resourcePath);
}
else
{
debug(LOG_ERROR, "Could not change to resources directory.");
}
if (resourceURL != NULL)
{
CFRelease(resourceURL);
}
}
#endif
_glcFont_Regular = glcGenFontID();
_glcFont_Bold = glcGenFontID();
if (!glcNewFontFromFamily(_glcFont_Regular, font_family))
{
debug(LOG_ERROR, "Failed to select font family %s as regular font", font_family);
}
else
{
debug(LOG_NEVER, "Successfully selected font family %s as regular font", font_family);
}
if (!glcFontFace(_glcFont_Regular, font_face_regular))
{
debug(LOG_WARNING, "Failed to select the \"%s\" font face of font family %s", font_face_regular, font_family);
}
else
{
debug(LOG_NEVER, "Successfully selected the \"%s\" font face of font family %s", font_face_regular, font_family);
}
if (!glcNewFontFromFamily(_glcFont_Bold, font_family))
{
debug(LOG_ERROR, "iV_initializeGLC: Failed to select font family %s for the bold font", font_family);
}
else
{
debug(LOG_NEVER, "Successfully selected font family %s for the bold font", font_family);
}
if (!glcFontFace(_glcFont_Bold, font_face_bold))
{
debug(LOG_WARNING, "Failed to select the \"%s\" font face of font family %s", font_face_bold, font_family);
}
else
{
debug(LOG_NEVER, "Successfully selected the \"%s\" font face of font family %s", font_face_bold, font_family);
}
debug(LOG_NEVER, "Finished initializing GLC");
}
void iV_TextInit()
{
iV_initializeGLC();
iV_SetFont(font_regular);
#ifdef DEBUG
iV_printFontList();
#endif
}
void iV_TextShutdown()
{
if (_glcFont_Regular)
{
glcDeleteFont(_glcFont_Regular);
}
if (_glcFont_Bold)
{
glcDeleteFont(_glcFont_Bold);
}
glcContext(0);
if (_glcContext)
{
glcDeleteContext(_glcContext);
}
}
void iV_SetFont(enum iV_fonts FontID)
{
switch (FontID)
{
default:
case font_scaled:
case font_regular:
iV_SetTextSize(12.f);
glcFont(_glcFont_Regular);
break;
case font_large:
iV_SetTextSize(21.f);
glcFont(_glcFont_Bold);
break;
case font_small:
iV_SetTextSize(9.f);
glcFont(_glcFont_Regular);
break;
}
}
static inline float getGLCResolution(void)
{
float resolution = glcGetf(GLC_RESOLUTION);
// The default resolution as used by OpenGLC is 72 dpi
if (resolution == 0.f)
{
return 72.f;
}
return resolution;
}
static inline float getGLCPixelSize(void)
{
float pixel_size = font_size * getGLCResolution() / 72.f;
return pixel_size;
}
static inline float getGLCPointWidth(const float* boundingbox)
{
// boundingbox contains: [ xlb ylb xrb yrb xrt yrt xlt ylt ]
// l = left; r = right; b = bottom; t = top;
float rightTopX = boundingbox[4];
float leftTopX = boundingbox[6];
float point_width = rightTopX - leftTopX;
return point_width;
}
static inline float getGLCPointHeight(const float* boundingbox)
{
// boundingbox contains: [ xlb ylb xrb yrb xrt yrt xlt ylt ]
// l = left; r = right; b = bottom; t = top;
float leftBottomY = boundingbox[1];
float leftTopY = boundingbox[7];
float point_height = fabsf(leftTopY - leftBottomY);
return point_height;
}
static inline float getGLCPointToPixel(float point_width)
{
float pixel_width = point_width * getGLCPixelSize();
return pixel_width;
}
unsigned int iV_GetTextWidth(const char* string)
{
float boundingbox[8];
float pixel_width, point_width;
glcMeasureString(GL_FALSE, string);
if (!glcGetStringMetric(GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the string \"%s\"", string);
return 0;
}
point_width = getGLCPointWidth(boundingbox);
pixel_width = getGLCPointToPixel(point_width);
return (unsigned int)pixel_width;
}
unsigned int iV_GetCountedTextWidth(const char* string, size_t string_length)
{
float boundingbox[8];
float pixel_width, point_width;
glcMeasureCountedString(GL_FALSE, string_length, string);
if (!glcGetStringMetric(GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the string \"%s\" of length %u", string, (unsigned int)string_length);
return 0;
}
point_width = getGLCPointWidth(boundingbox);
pixel_width = getGLCPointToPixel(point_width);
return (unsigned int)pixel_width;
}
unsigned int iV_GetTextHeight(const char* string)
{
float boundingbox[8];
float pixel_height, point_height;
glcMeasureString(GL_FALSE, string);
if (!glcGetStringMetric(GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the string \"%s\"", string);
return 0;
}
point_height = getGLCPointHeight(boundingbox);
pixel_height = getGLCPointToPixel(point_height);
return (unsigned int)pixel_height;
}
unsigned int iV_GetCharWidth(uint32_t charCode)
{
float boundingbox[8];
float pixel_width, point_width;
if (!glcGetCharMetric(charCode, GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the character code %u", charCode);
return 0;
}
point_width = getGLCPointWidth(boundingbox);
pixel_width = getGLCPointToPixel(point_width);
return (unsigned int)pixel_width;
}
int iV_GetTextLineSize()
{
float boundingbox[8];
float pixel_height, point_height;
if (!glcGetMaxCharMetric(GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the character");
return 0;
}
point_height = getGLCPointHeight(boundingbox);
pixel_height = getGLCPointToPixel(point_height);
return (unsigned int)pixel_height;
}
static float iV_GetMaxCharBaseY(void)
{
float base_line[4]; // [ xl yl xr yr ]
if (!glcGetMaxCharMetric(GLC_BASELINE, base_line))
{
debug(LOG_ERROR, "Couldn't retrieve the baseline for the character");
return 0;
}
return base_line[1];
}
int iV_GetTextAboveBase(void)
{
float point_base_y = iV_GetMaxCharBaseY();
float point_top_y;
float boundingbox[8];
float pixel_height, point_height;
if (!glcGetMaxCharMetric(GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the character");
return 0;
}
point_top_y = boundingbox[7];
point_height = point_base_y - point_top_y;
pixel_height = getGLCPointToPixel(point_height);
return (int)pixel_height;
}
int iV_GetTextBelowBase(void)
{
float point_base_y = iV_GetMaxCharBaseY();
float point_bottom_y;
float boundingbox[8];
float pixel_height, point_height;
if (!glcGetMaxCharMetric(GLC_BOUNDS, boundingbox))
{
debug(LOG_ERROR, "Couldn't retrieve a bounding box for the character");
return 0;
}
point_bottom_y = boundingbox[1];
point_height = point_bottom_y - point_base_y;
pixel_height = getGLCPointToPixel(point_height);
return (int)pixel_height;
}
void iV_SetTextColour(PIELIGHT colour)
{
font_colour[0] = colour.byte.r / 255.0f;
font_colour[1] = colour.byte.g / 255.0f;
font_colour[2] = colour.byte.b / 255.0f;
font_colour[3] = colour.byte.a / 255.0f;
}
/** Draws formatted text with word wrap, long word splitting, embedded newlines
* (uses '@' rather than '\n') and colour toggle mode ('#') which enables or
* disables font colouring.
@ -195,3 +601,79 @@ int iV_DrawFormattedText(const char* String, UDWORD x, UDWORD y, UDWORD Width, U
return jy;
}
void iV_DrawTextRotated(const char* string, float XPos, float YPos, float rotation)
{
GLint matrix_mode = 0;
ASSERT_OR_RETURN( , string, "Couldn't render string!");
pie_SetTexturePage(TEXPAGE_EXTERN);
glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if (rotation != 0.f)
{
rotation = 360.f - rotation;
}
glTranslatef(XPos, YPos, 0.f);
glRotatef(180.f, 1.f, 0.f, 0.f);
glRotatef(rotation, 0.f, 0.f, 1.f);
glScalef(font_size, font_size, 0.f);
glColor4fv(font_colour);
glFrontFace(GL_CW);
glcRenderString(string);
glFrontFace(GL_CCW);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(matrix_mode);
// Reset the current model view matrix
glLoadIdentity();
}
static void iV_DrawTextRotatedFv(float x, float y, float rotation, const char* format, va_list ap)
{
va_list aq;
size_t size;
char* str;
/* Required because we're using the va_list ap twice otherwise, which
* results in undefined behaviour. See stdarg(3) for details.
*/
va_copy(aq, ap);
// Allocate a buffer large enough to hold our string on the stack
size = vsnprintf(NULL, 0, format, ap);
str = (char *)alloca(size + 1);
// Print into our newly created string buffer
vsprintf(str, format, aq);
va_end(aq);
// Draw the produced string to the screen at the given position and rotation
iV_DrawTextRotated(str, x, y, rotation);
}
void iV_DrawTextF(float x, float y, const char* format, ...)
{
va_list ap;
va_start(ap, format);
iV_DrawTextRotatedFv(x, y, 0.f, format, ap);
va_end(ap);
}
void iV_SetTextSize(float size)
{
font_size = size;
}

View File

@ -55,6 +55,9 @@ enum {
};
extern int iV_DrawFormattedText(const char* String, UDWORD x, UDWORD y, UDWORD Width, UDWORD Justify);
extern void iV_SetTextSize(float size);
extern void iV_DrawTextRotated(const char* string, float x, float y, float rotation);
/** Draws text with a printf syntax to the screen.
@ -64,4 +67,6 @@ static inline void iV_DrawText(const char* string, float x, float y)
iV_DrawTextRotated(string, x, y, 0.f);
}
extern void iV_DrawTextF(float x, float y, const char* format, ...) WZ_DECL_FORMAT(printf, 3, 4);
#endif // _INCLUDED_TEXTDRAW_