2007-01-15 12:09:25 -08:00
|
|
|
/*
|
|
|
|
This file is part of Warzone 2100.
|
|
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
|
|
Copyright (C) 2005-2007 Warzone Resurrection Project
|
|
|
|
|
|
|
|
Warzone 2100 is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Warzone 2100 is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Warzone 2100; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2007-06-14 14:56:36 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2006-06-02 12:34:58 -07:00
|
|
|
#include "lib/ivis_common/ivisdef.h"
|
|
|
|
#include "lib/ivis_common/piestate.h"
|
|
|
|
#include "lib/ivis_common/rendmode.h"
|
|
|
|
#include "lib/ivis_common/pieclip.h"
|
|
|
|
#include "lib/ivis_common/pieblitfunc.h"
|
|
|
|
#include "lib/ivis_common/piepalette.h"
|
|
|
|
#include "lib/ivis_common/ivispatch.h"
|
|
|
|
#include "lib/ivis_common/textdraw.h"
|
|
|
|
#include "lib/ivis_common/bitimage.h"
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-03 04:57:16 -07:00
|
|
|
#include <GL/gl.h>
|
2007-10-01 12:45:49 -07:00
|
|
|
#include <GL/glc.h>
|
|
|
|
|
2007-10-04 12:43:38 -07:00
|
|
|
static const char font_family[] = "DejaVu Sans Mono";
|
|
|
|
static const char font_face_regular[] = "Book";
|
|
|
|
static const char font_face_bold[] = "Bold";
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
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 GLC_Context = 0;
|
|
|
|
static GLint GLC_Font_Regular = 0;
|
|
|
|
static GLint GLC_Font_Bold = 0;
|
2007-08-03 04:57:16 -07:00
|
|
|
|
2007-10-04 14:29:16 -07:00
|
|
|
static bool anti_aliasing = true;
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/***************************************************************************/
|
|
|
|
/*
|
2007-10-01 12:45:49 -07:00
|
|
|
* Source
|
2007-06-28 10:47:08 -07:00
|
|
|
*/
|
|
|
|
/***************************************************************************/
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
static inline void iV_printFontList()
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
GLint font_count = glcGeti(GLC_CURRENT_FONT_COUNT);
|
2007-10-04 12:43:38 -07:00
|
|
|
debug(LOG_NEVER, "GLC_CURRENT_FONT_COUNT = %d", font_count);
|
|
|
|
|
|
|
|
if (font_count == 0)
|
|
|
|
debug(LOG_ERROR, "iV_printFontList: The required font (%s) isn't loaded", font_family);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
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 ", font, (const char*)glcGetFontc(font, GLC_FAMILY));
|
|
|
|
prBuffer[sizeof(prBuffer) - 1] = 0;
|
|
|
|
strncat(prBuffer, glcGetFontFace(font), sizeof(prBuffer));
|
|
|
|
prBuffer[sizeof(prBuffer) - 1] = 0;
|
2007-10-04 12:43:38 -07:00
|
|
|
debug(LOG_NEVER, prBuffer);
|
2007-10-01 12:45:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void iV_initializeGLC()
|
2007-08-01 11:26:56 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
if (GLC_Context)
|
|
|
|
return;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
GLC_Context = glcGenContext();
|
|
|
|
if (!GLC_Context)
|
|
|
|
debug(LOG_ERROR, "glcGenContext() failed");
|
|
|
|
else
|
|
|
|
debug(LOG_NEVER, "glcGenContext() succesful: GLC_Context = %d", GLC_Context);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
glcContext(GLC_Context);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
glcDisable(GLC_AUTO_FONT);
|
|
|
|
glcRenderStyle(GLC_TRIANGLE);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
GLC_Font_Regular = glcGenFontID();
|
|
|
|
GLC_Font_Bold = glcGenFontID();
|
|
|
|
|
|
|
|
if (!glcNewFontFromFamily(GLC_Font_Regular, font_family))
|
|
|
|
debug(LOG_ERROR, "glcNewFontFromFamily(GLC_Font_Regular (%d), \"%s\") failed", GLC_Font_Regular, font_family);
|
|
|
|
else
|
|
|
|
debug(LOG_NEVER, "glcNewFontFromFamily(GLC_Font_Regular (%d), \"%s\") succesful", GLC_Font_Regular, font_family);
|
|
|
|
|
|
|
|
if (!glcFontFace(GLC_Font_Regular, font_face_regular))
|
|
|
|
debug(LOG_ERROR, "glcFontFace(GLC_Font_Regular (%d), \"%s\") failed", GLC_Font_Regular, font_face_regular);
|
|
|
|
else
|
|
|
|
debug(LOG_NEVER, "glcFontFace(GLC_Font_Regular (%d), \"%s\") succesful", GLC_Font_Regular, font_face_regular);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
if (!glcNewFontFromFamily(GLC_Font_Bold, font_family))
|
|
|
|
debug(LOG_ERROR, "glcNewFontFromFamily(GLC_Font_Bold (%d), \"%s\") failed", GLC_Font_Bold, font_family);
|
|
|
|
else
|
|
|
|
debug(LOG_NEVER, "glcNewFontFromFamily(GLC_Font_Bold (%d), \"%s\") succesful", GLC_Font_Bold, font_family);
|
|
|
|
|
|
|
|
if (!glcFontFace(GLC_Font_Bold, font_face_bold))
|
|
|
|
debug(LOG_ERROR, "glcFontFace(GLC_Font_Bold (%d), \"%s\") failed", GLC_Font_Bold, font_face_bold);
|
|
|
|
else
|
|
|
|
debug(LOG_NEVER, "glcFontFace(GLC_Font_Bold (%d), \"%s\") succesful", GLC_Font_Bold, font_face_bold);
|
|
|
|
|
|
|
|
debug(LOG_NEVER, "finished initializing GLC");
|
|
|
|
|
|
|
|
// Set GLC's string type to UTF-8
|
|
|
|
glcStringType(GLC_UTF8_QSO);
|
|
|
|
}
|
|
|
|
|
|
|
|
void iV_TextInit()
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
iV_initializeGLC();
|
|
|
|
iV_SetFont(font_regular);
|
2007-10-04 12:43:38 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
iV_printFontList();
|
|
|
|
#endif
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
void iV_TextShutdown()
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
if (GLC_Font_Regular)
|
|
|
|
glcDeleteFont(GLC_Font_Regular);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
if (GLC_Font_Bold)
|
|
|
|
glcDeleteFont(GLC_Font_Bold);
|
2006-06-02 12:34:58 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
glcContext(0);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
if (GLC_Context)
|
|
|
|
glcDeleteContext(GLC_Context);
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-04 14:29:16 -07:00
|
|
|
void iV_SetTextAntialias(bool enable)
|
|
|
|
{
|
|
|
|
anti_aliasing = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool iV_TextAntialiased()
|
|
|
|
{
|
|
|
|
return anti_aliasing;
|
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
void iV_SetFont(enum iV_fonts FontID)
|
|
|
|
{
|
|
|
|
switch (FontID)
|
2007-08-01 11:26:56 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
case font_regular:
|
|
|
|
iV_SetTextSize(12.f);
|
|
|
|
glcFont(GLC_Font_Regular);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case font_large:
|
|
|
|
iV_SetTextSize(21.f);
|
|
|
|
glcFont(GLC_Font_Bold);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
static inline float getGLCResolution()
|
|
|
|
{
|
|
|
|
float resolution = glcGetf(GLC_RESOLUTION);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
// The default resolution as used by OpenGLC is 72 dpi
|
|
|
|
if (resolution == 0.f)
|
|
|
|
return 72.f;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
return resolution;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
static inline float getGLCPixelSize()
|
|
|
|
{
|
|
|
|
float pixel_size = font_size * getGLCResolution() / 72.f;
|
|
|
|
return pixel_size;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
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];
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
float point_width = rightTopX - leftTopX;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
return point_width;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
static inline float getGLCPointHeight(const float* boundingbox)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
// 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;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
static inline float getGLCPointToPixel(float point_width)
|
|
|
|
{
|
|
|
|
float pixel_width = point_width * getGLCPixelSize();
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
return pixel_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int iV_GetTextWidth(const char* string)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
float boundingbox[8];
|
|
|
|
float pixel_width, point_width;
|
|
|
|
|
|
|
|
glcMeasureString(GL_FALSE, string);
|
|
|
|
if (!glcGetStringMetric(GLC_BOUNDS, boundingbox))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetTextWidth: couldn't retrieve a bounding box for the string");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
point_width = getGLCPointWidth(boundingbox);
|
|
|
|
pixel_width = getGLCPointToPixel(point_width);
|
|
|
|
return (unsigned int)pixel_width;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
unsigned int iV_GetCountedTextWidth(const char* string, size_t string_length)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
float boundingbox[8];
|
|
|
|
float pixel_width, point_width;
|
|
|
|
|
|
|
|
glcMeasureCountedString(GL_FALSE, string_length, string);
|
|
|
|
if (!glcGetStringMetric(GLC_BOUNDS, boundingbox))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetTextWidth: couldn't retrieve a bounding box for the string");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
point_width = getGLCPointWidth(boundingbox);
|
|
|
|
pixel_width = getGLCPointToPixel(point_width);
|
|
|
|
return (unsigned int)pixel_width;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
unsigned int iV_GetTextHeight(const char* string)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
float boundingbox[8];
|
|
|
|
float pixel_height, point_height;
|
|
|
|
|
|
|
|
glcMeasureString(GL_FALSE, string);
|
|
|
|
if (!glcGetStringMetric(GLC_BOUNDS, boundingbox))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetTextHeight: couldn't retrieve a bounding box for the string");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
point_height = getGLCPointHeight(boundingbox);
|
|
|
|
pixel_height = getGLCPointToPixel(point_height);
|
|
|
|
return (unsigned int)pixel_height;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
unsigned int iV_GetCharWidth(uint32_t charCode)
|
|
|
|
{
|
|
|
|
float boundingbox[8];
|
|
|
|
float pixel_width, point_width;
|
|
|
|
|
|
|
|
if (!glcGetCharMetric(charCode, GLC_BOUNDS, boundingbox))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetCharWidth: couldn't retrieve a bounding box for the character");
|
|
|
|
return 0;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
point_width = getGLCPointWidth(boundingbox);
|
|
|
|
pixel_width = getGLCPointToPixel(point_width);
|
|
|
|
return (unsigned int)pixel_width;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
int iV_GetTextLineSize()
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
float boundingbox[8];
|
|
|
|
float pixel_height, point_height;
|
|
|
|
|
|
|
|
if (!glcGetMaxCharMetric(GLC_BOUNDS, boundingbox))
|
2007-07-30 09:42:37 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
debug(LOG_ERROR, "iV_GetCharWidth: couldn't retrieve a bounding box for the character");
|
|
|
|
return 0;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
point_height = getGLCPointHeight(boundingbox);
|
|
|
|
pixel_height = getGLCPointToPixel(point_height);
|
|
|
|
return (unsigned int)pixel_height;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
static float iV_GetMaxCharBaseY()
|
|
|
|
{
|
|
|
|
float base_line[4]; // [ xl yl xr yr ]
|
|
|
|
|
|
|
|
if (!glcGetMaxCharMetric(GLC_BASELINE, base_line))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetMaxCharBaseY: couldn't retrieve the baseline for the character");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return base_line[1];
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
int iV_GetTextAboveBase(void)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
float point_base_y = iV_GetMaxCharBaseY();
|
|
|
|
float point_top_y;
|
|
|
|
float boundingbox[8];
|
|
|
|
float pixel_height, point_height;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
if (!glcGetMaxCharMetric(GLC_BOUNDS, boundingbox))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetCharWidth: couldn't retrieve a bounding box for the character");
|
2007-07-30 09:42:37 -07:00
|
|
|
return 0;
|
2007-10-01 12:45:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
if (!glcGetMaxCharMetric(GLC_BOUNDS, boundingbox))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "iV_GetCharWidth: couldn't retrieve a bounding box for the character");
|
|
|
|
return 0;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
point_bottom_y = boundingbox[1];
|
|
|
|
point_height = point_bottom_y - point_base_y;
|
|
|
|
pixel_height = getGLCPointToPixel(point_height);
|
|
|
|
return (int)pixel_height;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void iV_SetTextColour(SWORD Index)
|
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
switch (Index)
|
|
|
|
{
|
|
|
|
case PIE_TEXT_WHITE:
|
|
|
|
font_colour[0] = 1.f;
|
|
|
|
font_colour[1] = 1.f;
|
|
|
|
font_colour[2] = 1.f;
|
|
|
|
font_colour[3] = 1.f;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIE_TEXT_LIGHTBLUE:
|
|
|
|
font_colour[0] = 0.627451f;
|
|
|
|
font_colour[1] = 0.627451f;
|
|
|
|
font_colour[2] = 1.f;
|
|
|
|
font_colour[3] = 1.f;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIE_TEXT_DARKBLUE:
|
|
|
|
font_colour[0] = 0.376471f;
|
|
|
|
font_colour[1] = 0.376471f;
|
|
|
|
font_colour[2] = 0.752941f;
|
|
|
|
font_colour[3] = 1.f;
|
|
|
|
break;
|
|
|
|
};
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
enum {
|
|
|
|
EXTENTS_NONE,
|
|
|
|
EXTENTS_START,
|
|
|
|
EXTENTS_END
|
|
|
|
};
|
|
|
|
|
2006-11-03 13:35:50 -08:00
|
|
|
static char FString[256]; // Must do something about these wastefull static arrays.
|
|
|
|
static char FWord[256];
|
2007-06-28 10:47:08 -07:00
|
|
|
static int LastX; // Cursor position after last draw.
|
|
|
|
static int LastY;
|
|
|
|
static int LastTWidth; // Pixel width of the last string draw.
|
|
|
|
static int RecordExtents = EXTENTS_NONE;
|
|
|
|
static int ExtentsStartX;
|
|
|
|
static int ExtentsStartY;
|
|
|
|
static int ExtentsEndX;
|
|
|
|
static int ExtentsEndY;
|
|
|
|
|
|
|
|
// Draws formatted text with word wrap, long word splitting, embedded
|
|
|
|
// newlines ( uses @ rather than \n ) and colour mode toggle ( # ) which enables
|
|
|
|
// or disables font colouring.
|
|
|
|
//
|
|
|
|
// UBYTE *String The string to display.
|
|
|
|
// UDWORD x x coord of top left of formatted text window.
|
|
|
|
// UDWORD y y coord of top left of formatted text window.
|
|
|
|
// UDWORD Width Width of formatted text window.
|
|
|
|
// UDWORD Justify Justify mode, one of the following:
|
|
|
|
// FTEXT_LEFTJUSTIFY
|
|
|
|
// FTEXT_CENTRE
|
|
|
|
// FTEXT_RIGHTJUSTIFY
|
|
|
|
// BOOL DrawBack If TRUE then draws transparent box behind text.
|
|
|
|
//
|
|
|
|
// Returns y coord of next text line.
|
|
|
|
//
|
2007-08-03 06:14:34 -07:00
|
|
|
UDWORD iV_DrawFormattedText(const char* String, UDWORD x, UDWORD y, UDWORD Width, UDWORD Justify)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-07-30 10:03:02 -07:00
|
|
|
int i;
|
2007-06-28 10:47:08 -07:00
|
|
|
int jx = x; // Default to left justify.
|
|
|
|
int jy = y;
|
2007-01-04 10:41:24 -08:00
|
|
|
UDWORD WWidth;
|
2007-06-28 10:47:08 -07:00
|
|
|
int TWidth;
|
|
|
|
|
2007-07-30 10:03:02 -07:00
|
|
|
const char* curChar = String;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
// DBPRINTF(("[%s] @(%d,%d) extentsmode=%d just=%d\n",String,x,y,ExtentsMode,Justify));
|
2006-06-02 12:34:58 -07:00
|
|
|
|
2007-07-30 10:03:02 -07:00
|
|
|
curChar = String;
|
|
|
|
while (*curChar != 0)
|
|
|
|
{
|
2007-08-06 04:22:31 -07:00
|
|
|
char* curSpaceChar;
|
|
|
|
|
2007-08-01 13:50:27 -07:00
|
|
|
bool GotSpace = false;
|
|
|
|
bool NewLine = false;
|
|
|
|
|
2007-08-01 13:17:23 -07:00
|
|
|
// Reset text draw buffer
|
2007-06-28 10:47:08 -07:00
|
|
|
FString[0] = 0;
|
|
|
|
|
2007-08-01 09:57:41 -07:00
|
|
|
WWidth = 0;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
// Parse through the string, adding words until width is achieved.
|
2007-08-01 13:50:27 -07:00
|
|
|
while (*curChar != 0 && WWidth < Width && !NewLine)
|
2007-07-30 10:03:02 -07:00
|
|
|
{
|
2007-08-01 13:50:27 -07:00
|
|
|
const char* startOfWord = curChar;
|
2007-10-01 12:45:49 -07:00
|
|
|
const unsigned int FStringWidth = iV_GetTextWidth(FString);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
// Get the next word.
|
2007-08-01 11:26:56 -07:00
|
|
|
i = 0;
|
2007-08-01 13:50:27 -07:00
|
|
|
for (; *curChar != 0
|
|
|
|
&& *curChar != ASCII_SPACE
|
|
|
|
&& *curChar != ASCII_NEWLINE;
|
|
|
|
++i, ++curChar)
|
2007-07-30 10:03:02 -07:00
|
|
|
{
|
2007-08-01 11:26:56 -07:00
|
|
|
if (*curChar == ASCII_COLOURMODE) // If it's a colour mode toggle char then just add it to the word.
|
2007-07-30 10:03:02 -07:00
|
|
|
{
|
|
|
|
FWord[i] = *curChar;
|
2007-08-01 13:17:23 -07:00
|
|
|
|
|
|
|
// this character won't be drawn so don't deal with its width
|
|
|
|
continue;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-08-01 13:17:23 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
// Update this line's pixel width.
|
|
|
|
WWidth = FStringWidth + iV_GetCountedTextWidth(FWord, i + 1);
|
2007-08-01 13:17:23 -07:00
|
|
|
|
|
|
|
// If this word doesn't fit on the current line then break out
|
|
|
|
if (WWidth > Width)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// If width ok then add this character to the current word.
|
|
|
|
FWord[i] = *curChar;
|
2007-08-01 11:26:56 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-01 11:26:56 -07:00
|
|
|
// Don't forget the space.
|
2007-08-01 13:50:27 -07:00
|
|
|
if (*curChar == ASCII_SPACE)
|
2007-07-30 10:03:02 -07:00
|
|
|
{
|
2007-08-01 11:26:56 -07:00
|
|
|
WWidth += iV_GetCharWidth(' ');
|
|
|
|
if (WWidth <= Width)
|
|
|
|
{
|
2007-06-28 10:47:08 -07:00
|
|
|
FWord[i] = ' ';
|
2007-07-30 10:03:02 -07:00
|
|
|
++i;
|
|
|
|
++curChar;
|
2007-08-01 13:50:27 -07:00
|
|
|
GotSpace = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-08-01 13:50:27 -07:00
|
|
|
// Check for new line character.
|
|
|
|
else if (*curChar == ASCII_NEWLINE)
|
|
|
|
{
|
|
|
|
NewLine = true;
|
|
|
|
++curChar;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-01 13:50:27 -07:00
|
|
|
// If we've passed a space on this line and the word goes past the
|
|
|
|
// maximum width and this isn't caused by the appended space then
|
|
|
|
// rewind to the start of this word and finish this line.
|
2007-08-01 13:17:23 -07:00
|
|
|
if (GotSpace
|
2007-08-01 13:50:27 -07:00
|
|
|
&& WWidth > Width
|
|
|
|
&& FWord[i - 1] != ' ')
|
2007-08-01 11:26:56 -07:00
|
|
|
{
|
2007-08-01 13:50:27 -07:00
|
|
|
// Skip back to the beginning of this
|
|
|
|
// word and draw it on the next line
|
|
|
|
curChar = startOfWord;
|
|
|
|
break;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Terminate the word.
|
|
|
|
FWord[i] = 0;
|
|
|
|
|
|
|
|
// And add it to the output string.
|
|
|
|
strcat(FString, FWord);
|
2007-08-01 11:26:56 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
|
2007-08-01 09:57:41 -07:00
|
|
|
// Remove trailing spaces, useful when doing center alignment.
|
2007-08-06 04:22:31 -07:00
|
|
|
curSpaceChar = &FString[strlen(FString) - 1];
|
|
|
|
while (curSpaceChar != &FString[-1] && *curSpaceChar == ASCII_SPACE)
|
2007-08-01 09:57:41 -07:00
|
|
|
{
|
2007-08-06 04:22:31 -07:00
|
|
|
*(curSpaceChar--) = 0;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TWidth = iV_GetTextWidth(FString);
|
|
|
|
|
|
|
|
|
|
|
|
// DBPRINTF(("string[%s] is %d of %d pixels wide (according to DrawFormattedText)\n",FString,TWidth,Width));
|
|
|
|
|
|
|
|
// Do justify.
|
2007-08-01 11:26:56 -07:00
|
|
|
switch (Justify)
|
2007-08-01 09:57:41 -07:00
|
|
|
{
|
|
|
|
case FTEXT_CENTRE:
|
2007-08-01 11:26:56 -07:00
|
|
|
jx = x + (Width - TWidth) / 2;
|
2007-06-28 10:47:08 -07:00
|
|
|
break;
|
|
|
|
|
2007-08-01 09:57:41 -07:00
|
|
|
case FTEXT_RIGHTJUSTIFY:
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-01 11:26:56 -07:00
|
|
|
jx = x + Width - TWidth;
|
2007-06-28 10:47:08 -07:00
|
|
|
break;
|
|
|
|
|
2007-08-01 09:57:41 -07:00
|
|
|
case FTEXT_LEFTJUSTIFY:
|
2007-06-28 10:47:08 -07:00
|
|
|
jx = x;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw the text.
|
2007-10-01 12:45:49 -07:00
|
|
|
//iV_SetTextSize(12.f);
|
2007-08-03 06:14:34 -07:00
|
|
|
iV_DrawText(FString, jx, jy);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
|
|
|
|
//DBPRINTF(("[%s] @ %d,%d\n",FString,jx,jy));
|
|
|
|
|
2007-08-01 11:26:56 -07:00
|
|
|
/* callback type for resload display callback*/
|
2007-06-28 10:47:08 -07:00
|
|
|
// remember where we were..
|
|
|
|
LastX = jx + TWidth;
|
|
|
|
LastY = jy;
|
|
|
|
LastTWidth = TWidth;
|
|
|
|
|
|
|
|
// and move down a line.
|
|
|
|
jy += iV_GetTextLineSize();
|
|
|
|
}
|
|
|
|
|
2007-08-01 11:26:56 -07:00
|
|
|
if (RecordExtents == EXTENTS_START)
|
|
|
|
{
|
2007-06-28 10:47:08 -07:00
|
|
|
RecordExtents = EXTENTS_END;
|
|
|
|
|
|
|
|
ExtentsStartY = y + iV_GetTextAboveBase();
|
2007-08-01 11:26:56 -07:00
|
|
|
ExtentsEndY = jy - iV_GetTextLineSize() + iV_GetTextBelowBase();
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-06 04:22:31 -07:00
|
|
|
ExtentsStartX = x; // Was jx, but this broke the console centre justified text background.
|
|
|
|
// ExtentsEndX = jx + TWidth;
|
|
|
|
ExtentsEndX = x + Width;
|
2007-08-01 11:26:56 -07:00
|
|
|
}
|
|
|
|
else if (RecordExtents == EXTENTS_END)
|
|
|
|
{
|
|
|
|
ExtentsEndY = jy - iV_GetTextLineSize() + iV_GetTextBelowBase();
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-06 04:22:31 -07:00
|
|
|
ExtentsEndX = x + Width;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return jy;
|
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
void iV_DrawTextRotated(const char* string, float XPos, float YPos, float rotation)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
pie_SetTexturePage(-2);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-04 14:29:16 -07:00
|
|
|
// Enable Anti Aliasing if it's enabled
|
|
|
|
if (anti_aliasing)
|
|
|
|
{
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
|
|
glEnable(GL_POLYGON_SMOOTH);
|
|
|
|
}
|
2007-09-25 13:40:56 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
if (rotation != 0.f)
|
|
|
|
rotation = 360.f - rotation;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
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);
|
2007-08-01 11:59:51 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
glColor4fv(font_colour);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
glFrontFace(GL_CW);
|
|
|
|
glcRenderString(string);
|
|
|
|
glFrontFace(GL_CCW);
|
2007-08-01 09:57:41 -07:00
|
|
|
|
2007-10-04 14:29:16 -07:00
|
|
|
// Turn off anti aliasing (if we enabled it above)
|
|
|
|
if (anti_aliasing)
|
|
|
|
{
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDisable(GL_POLYGON_SMOOTH);
|
|
|
|
}
|
2007-08-01 11:59:51 -07:00
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
// Reset the current model view matrix
|
2007-08-03 04:57:16 -07:00
|
|
|
glLoadIdentity();
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-10-01 12:45:49 -07:00
|
|
|
void iV_SetTextSize(float size)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-10-01 12:45:49 -07:00
|
|
|
font_size = size;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|