mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 17:52:08 -10:00
1020 lines
24 KiB
C++
1020 lines
24 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/Graphics/Font.cpp $
|
|
* $Revision: 2.20 $
|
|
* $Date: 2007-01-07 13:13:38 $
|
|
* $Author: taylor $
|
|
*
|
|
* source file for font stuff
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 2.19 2006/12/28 00:59:26 wmcoolmon
|
|
* WMC codebase commit. See pre-commit build thread for details on changes.
|
|
*
|
|
* Revision 2.18 2006/09/11 06:45:39 taylor
|
|
* various small compiler warning and strict compiling fixes
|
|
*
|
|
* Revision 2.17 2006/09/11 06:36:38 taylor
|
|
* clean up the grstub mess (for work on standalone server, and just for sanity sake)
|
|
* move color and shader functions to 2d.cpp since they are exactly the same everywhere
|
|
* don't bother with the function pointer for gr_set_font(), it's the same everywhere anyway
|
|
*
|
|
* Revision 2.16 2006/06/27 05:07:48 taylor
|
|
* fix various compiler warnings and things that Valgrind complained about
|
|
*
|
|
* Revision 2.15 2005/10/30 06:44:57 wmcoolmon
|
|
* Codebase commit - nebula.tbl, scripting, new dinky explosion/shockwave stuff, moving muzzle flashes
|
|
*
|
|
* Revision 2.14 2005/07/02 19:42:15 taylor
|
|
* ton of non-standard resolution fixes
|
|
*
|
|
* Revision 2.13 2005/05/12 17:49:12 taylor
|
|
* use vm_malloc(), vm_free(), vm_realloc(), vm_strdup() rather than system named macros
|
|
* fixes various problems and is past time to make the switch
|
|
*
|
|
* Revision 2.12 2005/01/31 23:27:53 taylor
|
|
* merge with Linux/OSX tree - p0131-2
|
|
*
|
|
* Revision 2.11 2004/07/26 20:47:31 Kazan
|
|
* remove MCD complete
|
|
*
|
|
* Revision 2.10 2004/07/17 18:46:07 taylor
|
|
* various OGL and memory leak fixes
|
|
*
|
|
* Revision 2.9 2004/07/12 16:32:48 Kazan
|
|
* MCD - define _MCD_CHECK to use memory tracking
|
|
*
|
|
* Revision 2.8 2004/02/20 04:29:54 bobboau
|
|
* pluged memory leaks,
|
|
* 3D HTL lasers (they work perfictly)
|
|
* and posably fixed Turnsky's shinemap bug
|
|
*
|
|
* Revision 2.7 2004/02/14 00:18:31 randomtiger
|
|
* Please note that from now on OGL will only run with a registry set by Launcher v4. See forum for details.
|
|
* OK, these changes effect a lot of file, I suggest everyone updates ASAP:
|
|
* Removal of many files from project.
|
|
* Removal of meanless Gr_bitmap_poly variable.
|
|
* Removal of glide, directdraw, software modules all links to them, and all code specific to those paths.
|
|
* Removal of redundant Fred paths that arent needed for Fred OGL.
|
|
* Have seriously tidied the graphics initialisation code and added generic non standard mode functionality.
|
|
* Fixed many D3D non standard mode bugs and brought OGL up to the same level.
|
|
* Removed texture section support for D3D8, voodoo 2 and 3 cards will no longer run under fs2_open in D3D, same goes for any card with a maximum texture size less than 1024.
|
|
*
|
|
* Revision 2.6 2004/01/24 12:47:48 randomtiger
|
|
* Font and other small changes for Fred
|
|
*
|
|
* Revision 2.5 2004/01/19 00:56:09 randomtiger
|
|
* Some more small changes for Fred OGL
|
|
*
|
|
* Revision 2.4 2003/03/02 05:41:52 penguin
|
|
* Added some #ifndef NO_SOFTWARE_RENDERING
|
|
* - penguin
|
|
*
|
|
* Revision 2.3 2002/08/01 01:41:05 penguin
|
|
* The big include file move
|
|
*
|
|
* Revision 2.2 2002/07/29 20:12:31 penguin
|
|
* added #ifdef _WIN32 around windows-specific system headers
|
|
*
|
|
* Revision 2.1 2002/07/07 19:55:59 penguin
|
|
* Back-port to MSVC
|
|
*
|
|
* Revision 2.0 2002/06/03 04:02:22 penguin
|
|
* Warpcore CVS sync
|
|
*
|
|
* Revision 1.2 2002/05/16 13:43:25 mharris
|
|
* ifdef WIN32 around (unused?) win-specific code
|
|
*
|
|
* Revision 1.1 2002/05/02 18:03:07 mharris
|
|
* Initial checkin - converted filenames and includes to lower case
|
|
*
|
|
*
|
|
* 9 7/09/99 10:32p Dave
|
|
* Command brief and red alert screens.
|
|
*
|
|
* 8 12/14/98 9:21a Dan
|
|
* Put gr8_string() back in
|
|
*
|
|
* 7 12/02/98 5:47p Dave
|
|
* Put in interface xstr code. Converted barracks screen to new format.
|
|
*
|
|
* 6 11/30/98 1:07p Dave
|
|
* 16 bit conversion, first run.
|
|
*
|
|
* 5 11/05/98 4:18p Dave
|
|
* First run nebula support. Beefed up localization a bit. Removed all
|
|
* conditional compiles for foreign versions. Modified mission file
|
|
* format.
|
|
*
|
|
* 4 10/13/98 9:28a Dave
|
|
* Started neatening up freespace.h. Many variables renamed and
|
|
* reorganized. Added AlphaColors.[h,cpp]
|
|
*
|
|
* 3 10/13/98 9:19a Andsager
|
|
* Add localization support to cfile. Optional parameter with cfopen that
|
|
* looks for localized files.
|
|
*
|
|
* 2 10/07/98 10:52a Dave
|
|
* Initial checkin.
|
|
*
|
|
* 1 10/07/98 10:49a Dave
|
|
*
|
|
* 49 7/02/98 3:41p Allender
|
|
* fix nasty assembler bug where pushf wasn't accompanied by corresponding
|
|
* pop in certain clipping conditions -- manifested only in software and
|
|
* usually on the PXO chat screen.
|
|
*
|
|
* 48 6/18/98 10:10a Allender
|
|
* fixed compiler warnings
|
|
*
|
|
* 47 6/13/98 10:48p Lawrance
|
|
* Changed code to utilize proper fixed-space 1 character.
|
|
*
|
|
* 46 6/13/98 3:18p Hoffoss
|
|
* NOX()ed out a bunch of strings that shouldn't be translated.
|
|
*
|
|
* 45 5/25/98 10:32a John
|
|
* Took out redundant code for font bitmap offsets that converted to a
|
|
* float, then later on converted back to an integer. Quite unnecessary.
|
|
*
|
|
* 44 5/12/98 11:45a John
|
|
* Fixed a bug with the length of string being passed to
|
|
* gr_get_string_size. The bug occurred if you had two or more'\n'''s in
|
|
* a row.
|
|
*
|
|
* 43 3/10/98 4:18p John
|
|
* Cleaned up graphics lib. Took out most unused gr functions. Made D3D
|
|
* & Glide have popups and print screen. Took out all >8bpp software
|
|
* support. Made Fred zbuffer. Made zbuffer allocate dynamically to
|
|
* support Fred. Made zbuffering key off of functions rather than one
|
|
* global variable.
|
|
*
|
|
* 42 3/09/98 6:06p John
|
|
* Restructured font stuff to avoid duplicate code in Direct3D and Glide.
|
|
* Restructured Glide to avoid redundent state setting.
|
|
*
|
|
* 41 3/02/98 10:33a John
|
|
* Fixed bug where Y clip was using X value.
|
|
*
|
|
* 40 2/19/98 9:04a John
|
|
* Fixed fonts with glide
|
|
*
|
|
* 39 2/17/98 7:27p John
|
|
* Got fonts and texturing working in Direct3D
|
|
*
|
|
* 38 2/05/98 9:21p John
|
|
* Some new Direct3D code. Added code to monitor a ton of stuff in the
|
|
* game.
|
|
*
|
|
* 37 1/20/98 2:25p Hoffoss
|
|
* Fixed bug where timestamp printing incorrectly increments an hour at 6
|
|
* minutes.
|
|
*
|
|
* 36 1/19/98 6:15p John
|
|
* Fixed all my Optimized Build compiler warnings
|
|
*
|
|
* 35 11/30/97 12:18p John
|
|
* added more 24 & 32-bpp primitives
|
|
*
|
|
* 34 11/29/97 2:24p John
|
|
* fixed warnings
|
|
*
|
|
* 33 11/29/97 2:06p John
|
|
* added mode 16-bpp support
|
|
*
|
|
* 32 11/10/97 2:35p Hoffoss
|
|
* Changed timestamp printing code to utilize new fixed-space '1'
|
|
* character.
|
|
*
|
|
* 31 11/06/97 5:42p Hoffoss
|
|
* Added support for fixed size timstamp rendering.
|
|
*
|
|
* 30 11/03/97 10:08p Hoffoss
|
|
* Changed gr_get_string_size to utilize an optional length specifier, if
|
|
* you want to use non-null terminated strings.
|
|
*
|
|
* 29 11/03/97 10:59a John
|
|
* added support for more than one font.
|
|
*
|
|
* 28 10/24/97 12:13p Hoffoss
|
|
* Added gr_force_fit_string().
|
|
*
|
|
* 27 10/19/97 12:55p John
|
|
* new code to lock / unlock surfaces for smooth directx integration.
|
|
*
|
|
* 26 10/14/97 4:50p John
|
|
* more 16 bpp stuff.
|
|
*
|
|
* 25 10/14/97 8:08a John
|
|
* added a bunch more 16 bit support
|
|
*
|
|
* 24 10/09/97 5:23p John
|
|
* Added support for more 16-bpp functions
|
|
*
|
|
* 23 9/23/97 10:53a Hoffoss
|
|
* Fixed bug in assumptions made half the time, and not the other half.
|
|
*
|
|
* 22 9/09/97 3:39p Sandeep
|
|
* warning level 4 bugs
|
|
*
|
|
* 21 8/19/97 5:46p Hoffoss
|
|
* Changed font used in Fred, and added display to show current eye
|
|
* position.
|
|
*
|
|
* 20 6/25/97 2:35p John
|
|
* added some functions to use the windows font for Fred.
|
|
*
|
|
* 19 6/17/97 12:03p John
|
|
* Moved color/alphacolor functions into their own module. Made all color
|
|
* functions be part of the low-level graphics drivers, not just the
|
|
* grsoft.
|
|
*
|
|
* 18 6/13/97 2:37p John
|
|
* fixed a string bug that printed weird characters sometimes.
|
|
*
|
|
* 17 6/11/97 6:00p John
|
|
* sped up alpha matching a bit.
|
|
*
|
|
* 16 6/11/97 5:49p John
|
|
* Changed palette code to only recalculate alphacolors when needed, not
|
|
* when palette changes.
|
|
*
|
|
* 15 6/11/97 5:01p John
|
|
* Fixed mission log text. Added fast clipped font drawer.
|
|
*
|
|
* 14 6/11/97 4:11p John
|
|
* addec function to get font height
|
|
*
|
|
* 13 6/11/97 1:12p John
|
|
* Started fixing all the text colors in the game.
|
|
*
|
|
* 12 6/09/97 9:24a John
|
|
* Changed the way fonts are set.
|
|
*
|
|
* 11 6/06/97 4:41p John
|
|
* Fixed alpha colors to be smoothly integrated into gr_set_color_fast
|
|
* code.
|
|
*
|
|
* 10 6/06/97 2:40p John
|
|
* Made all the radar dim in/out
|
|
*
|
|
* 9 6/05/97 4:53p John
|
|
* First rev of new antialiased font stuff.
|
|
*
|
|
* 8 5/12/97 12:27p John
|
|
* Restructured Graphics Library to add support for multiple renderers.
|
|
*
|
|
* 7 4/24/97 11:28a Hoffoss
|
|
* added code to handle gr_String being called before gr_init_font ever
|
|
* was called
|
|
*
|
|
* 6 4/23/97 5:26p John
|
|
* First rev of new debug console stuff.
|
|
*
|
|
* 5 4/22/97 12:20p John
|
|
* fixed more resource leaks
|
|
*
|
|
* 4 4/22/97 10:33a John
|
|
* fixed the 2d resource leaks that Alan found.
|
|
*
|
|
* 3 4/04/97 11:21a Hoffoss
|
|
* JOHN: Fixed invalid param that caused a trap in BoundsChecker.
|
|
*
|
|
* 2 4/01/97 9:26a Allender
|
|
* added support for descent style fonts although they are not used in the
|
|
* game yet
|
|
*
|
|
* 1 3/31/97 9:42a Allender
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "graphics/2d.h"
|
|
#include "cfile/cfile.h"
|
|
#include "graphics/font.h"
|
|
#include "palman/palman.h"
|
|
#include "io/key.h"
|
|
#include "bmpman/bmpman.h"
|
|
#include "localization/localize.h"
|
|
#include "globalincs/systemvars.h"
|
|
#include "parse/parselo.h" //For strextcmp
|
|
|
|
|
|
|
|
int Num_fonts = 0;
|
|
font Fonts[MAX_FONTS];
|
|
font *Current_font = NULL;
|
|
|
|
|
|
// crops a string if required to force it to not exceed max_width pixels when printed.
|
|
// Does this by dropping characters at the end of the string and adding '...' to the end.
|
|
// str = string to crop. Modifies this string directly
|
|
// max_str = max characters allowed in str
|
|
// max_width = number of pixels to limit string to (less than or equal to).
|
|
// Returns: returns same pointer passed in for str.
|
|
char *gr_force_fit_string(char *str, int max_str, int max_width)
|
|
{
|
|
int w;
|
|
|
|
gr_get_string_size(&w, NULL, str);
|
|
if (w > max_width) {
|
|
if ((int) strlen(str) > max_str - 3) {
|
|
Assert(max_str >= 3);
|
|
str[max_str - 3] = 0;
|
|
}
|
|
|
|
strcpy(str + strlen(str) - 1, "...");
|
|
gr_get_string_size(&w, NULL, str);
|
|
while (w > max_width) {
|
|
Assert(strlen(str) >= 4); // if this is hit, a bad max_width was passed in and the calling function needs fixing.
|
|
strcpy(str + strlen(str) - 4, "...");
|
|
gr_get_string_size(&w, NULL, str);
|
|
}
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
//takes the character BEFORE being offset into current font
|
|
// Returns the letter code
|
|
int get_char_width(ubyte c1,ubyte c2,int *width,int *spacing)
|
|
{
|
|
int i, letter;
|
|
|
|
Assert ( Current_font != NULL );
|
|
letter = c1-Current_font->first_ascii;
|
|
|
|
if (letter<0 || letter>=Current_font->num_chars) { //not in font, draw as space
|
|
*width=0;
|
|
*spacing = Current_font->w;
|
|
return -1;
|
|
}
|
|
|
|
*width = Current_font->char_data[letter].byte_width;
|
|
*spacing = Current_font->char_data[letter].spacing;
|
|
|
|
i = Current_font->char_data[letter].kerning_entry;
|
|
if ( i > -1) {
|
|
if (!(c2==0 || c2=='\n')) {
|
|
int letter2;
|
|
|
|
letter2 = c2-Current_font->first_ascii;
|
|
|
|
if ((letter2>=0) && (letter2<Current_font->num_chars) ) { //not in font, draw as space
|
|
font_kernpair *k = &Current_font->kern_data[i];
|
|
while( (k->c1 == (char)letter) && (k->c2<(char)letter2) && (i<Current_font->num_kern_pairs) ) {
|
|
i++;
|
|
k++;
|
|
}
|
|
if ( k->c2 == (char)letter2 ) {
|
|
*spacing += k->offset;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return letter;
|
|
}
|
|
|
|
// NOTE: this returns an unscaled size for non-standard resolutions
|
|
int get_centered_x(char *s)
|
|
{
|
|
int w,w2,s2;
|
|
|
|
for (w=0;*s!=0 && *s!='\n';s++) {
|
|
get_char_width(s[0],s[1],&w2,&s2);
|
|
w += s2;
|
|
}
|
|
|
|
return ((gr_screen.clip_width_unscaled - w) / 2);
|
|
}
|
|
|
|
// draws a character centered on x
|
|
void gr_char_centered(int x, int y, char chr)
|
|
{
|
|
char str[2];
|
|
int w, sc;
|
|
|
|
sc = Lcl_special_chars;
|
|
if (chr == '1')
|
|
chr = (char)(sc + 1);
|
|
|
|
str[0] = chr;
|
|
str[1] = 0;
|
|
gr_get_string_size(&w, NULL, str);
|
|
gr_string(x - w / 2, y, str);
|
|
}
|
|
|
|
void gr_print_timestamp(int x, int y, int timestamp)
|
|
{
|
|
char h[2], m[3], s[3];
|
|
int w, c;
|
|
|
|
// format the time information into strings
|
|
sprintf(h, "%.1d", (timestamp / 3600000) % 10);
|
|
sprintf(m, "%.2d", (timestamp / 60000) % 60);
|
|
sprintf(s, "%.2d", (timestamp / 1000) % 60);
|
|
|
|
gr_get_string_size(&w, NULL, "0");
|
|
gr_get_string_size(&c, NULL, ":");
|
|
|
|
gr_string(x + w, y, ":");
|
|
gr_string(x + w * 3 + c, y, ":");
|
|
|
|
x += w / 2;
|
|
gr_char_centered(x, y, h[0]);
|
|
x += w + c;
|
|
gr_char_centered(x, y, m[0]);
|
|
x += w;
|
|
gr_char_centered(x, y, m[1]);
|
|
x += w + c;
|
|
gr_char_centered(x, y, s[0]);
|
|
x += w;
|
|
gr_char_centered(x, y, s[1]);
|
|
}
|
|
|
|
int gr_get_font_height()
|
|
{
|
|
if (Current_font) {
|
|
return Current_font->h;
|
|
} else {
|
|
return 16;
|
|
}
|
|
}
|
|
|
|
void gr_get_string_size(int *w1, int *h1, char *text, int len)
|
|
{
|
|
int longest_width;
|
|
int width,spacing;
|
|
int w, h;
|
|
|
|
if (!Current_font) {
|
|
if ( w1)
|
|
*w1 = 16;
|
|
|
|
if ( h1 )
|
|
*h1 = 16;
|
|
|
|
return;
|
|
}
|
|
|
|
w = 0;
|
|
h = 0;
|
|
longest_width = 0;
|
|
|
|
if (text != NULL ) {
|
|
h += Current_font->h;
|
|
while (*text && (len>0) ) {
|
|
|
|
// Process one or more
|
|
while ((*text == '\n') && (len>0) ) {
|
|
text++;
|
|
len--;
|
|
if ( *text ) {
|
|
h += Current_font->h;
|
|
}
|
|
w = 0;
|
|
}
|
|
|
|
if (*text == 0) {
|
|
break;
|
|
}
|
|
|
|
get_char_width(text[0], text[1], &width, &spacing);
|
|
w += spacing;
|
|
if (w > longest_width)
|
|
longest_width = w;
|
|
|
|
text++;
|
|
len--;
|
|
}
|
|
}
|
|
|
|
if ( h1 )
|
|
*h1 = h;
|
|
|
|
if ( w1 )
|
|
*w1 = longest_width;
|
|
}
|
|
|
|
|
|
MONITOR( FontChars )
|
|
|
|
|
|
/*
|
|
|
|
void gr8_char(int x,int y,int letter)
|
|
{
|
|
font_char *ch;
|
|
|
|
ch = &Current_font->char_data[letter];
|
|
|
|
gr_aabitmap_ex( x, y, ch->byte_width, Current_font->h, Current_font->u[letter], Current_font->v[letter] );
|
|
|
|
// mprintf(( "String = %s\n", text ));
|
|
}
|
|
|
|
|
|
void gr8_string( int sx, int sy, char *s )
|
|
{
|
|
int width, spacing, letter;
|
|
int x, y;
|
|
|
|
if ( !Current_font ) return;
|
|
if ( !s ) return;
|
|
|
|
gr_set_bitmap(Current_font->bitmap);
|
|
|
|
x = sx;
|
|
y = sy;
|
|
|
|
if (sx==0x8000) { //centered
|
|
x = get_centered_x(s);
|
|
} else {
|
|
x = sx;
|
|
}
|
|
|
|
while (*s) {
|
|
while (*s== '\n' ) {
|
|
s++;
|
|
y += Current_font->h;
|
|
if (sx==0x8000) { //centered
|
|
x = get_centered_x(s);
|
|
} else {
|
|
x = sx;
|
|
}
|
|
}
|
|
if (*s == 0 ) break;
|
|
|
|
letter = get_char_width(s[0],s[1],&width,&spacing);
|
|
|
|
if (letter<0) { //not in font, draw as space
|
|
x += spacing;
|
|
s++;
|
|
continue;
|
|
}
|
|
gr8_char( x, y, letter );
|
|
|
|
x += spacing;
|
|
s++;
|
|
}
|
|
}
|
|
*/
|
|
/*
|
|
void gr8_string(int sx, int sy, char *s )
|
|
{
|
|
int row,width, spacing, letter;
|
|
int x, y;
|
|
|
|
if ( !Current_font ) return;
|
|
if ( !s ) return;
|
|
|
|
x = sx;
|
|
y = sy;
|
|
|
|
if (sx==0x8000) { //centered
|
|
x = get_centered_x(s);
|
|
} else {
|
|
x = sx;
|
|
}
|
|
|
|
spacing = 0;
|
|
|
|
gr_lock();
|
|
|
|
|
|
while (*s) {
|
|
MONITOR_INC( FontChars, 1 );
|
|
|
|
x += spacing;
|
|
while (*s== '\n' ) {
|
|
s++;
|
|
y += Current_font->h;
|
|
if (sx==0x8000) { //centered
|
|
x = get_centered_x(s);
|
|
} else {
|
|
x = sx;
|
|
}
|
|
}
|
|
if (*s == 0 ) break;
|
|
|
|
letter = get_char_width(s[0],s[1],&width,&spacing);
|
|
s++;
|
|
|
|
//If not in font, draw as space
|
|
if (letter<0) continue;
|
|
|
|
int xd, yd, xc, yc;
|
|
int wc, hc;
|
|
|
|
// Check if this character is totally clipped
|
|
if ( x + width < gr_screen.clip_left ) continue;
|
|
if ( y + Current_font->h < gr_screen.clip_top ) continue;
|
|
if ( x > gr_screen.clip_right ) continue;
|
|
if ( y > gr_screen.clip_bottom ) continue;
|
|
|
|
xd = yd = 0;
|
|
if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
|
|
if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
|
|
xc = x+xd;
|
|
yc = y+yd;
|
|
|
|
wc = width - xd; hc = Current_font->h - yd;
|
|
if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
|
|
if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
|
|
|
|
if ( wc < 1 ) continue;
|
|
if ( hc < 1 ) continue;
|
|
|
|
ubyte *fp = Current_font->pixel_data + Current_font->char_data[letter].offset + xd + yd*width;
|
|
ubyte *dptr = GR_SCREEN_PTR(ubyte, xc, yc);
|
|
|
|
#ifndef HARDWARE_ONLY
|
|
if ( Current_alphacolor ) {
|
|
for (row=0; row<hc; row++) {
|
|
#ifdef USE_INLINE_ASM
|
|
ubyte *lookup = &Current_alphacolor->table.lookup[0][0];
|
|
_asm mov edx, lookup
|
|
_asm xor eax, eax
|
|
_asm mov ecx, wc
|
|
_asm xor ebx, ebx
|
|
_asm mov edi, dptr
|
|
_asm mov esi, fp
|
|
_asm shr ecx, 1
|
|
_asm jz OnlyOne
|
|
_asm pushf
|
|
InnerFontLoop:
|
|
_asm mov al, [edi]
|
|
_asm mov bl, [edi+1]
|
|
_asm add edi,2
|
|
|
|
_asm mov ah, [esi]
|
|
_asm mov bh, [esi+1]
|
|
_asm add esi,2
|
|
|
|
_asm mov al, [edx+eax]
|
|
_asm mov ah, [edx+ebx]
|
|
|
|
_asm mov [edi-2], ax
|
|
|
|
_asm dec ecx
|
|
_asm jnz InnerFontLoop
|
|
|
|
_asm popf
|
|
_asm jnc NotOdd
|
|
|
|
OnlyOne:
|
|
_asm mov al, [edi]
|
|
_asm mov ah, [esi]
|
|
_asm mov al, [edx+eax]
|
|
_asm mov [edi], al
|
|
|
|
NotOdd:
|
|
dptr += gr_screen.rowsize;
|
|
fp += width;
|
|
#else
|
|
int i;
|
|
for (i=0; i< wc; i++ ) {
|
|
*dptr++ = Current_alphacolor->table.lookup[*fp++][*dptr];
|
|
}
|
|
fp += width - wc;
|
|
dptr += gr_screen.rowsize - wc;
|
|
#endif
|
|
}
|
|
} else { // No alpha color
|
|
#endif
|
|
for (row=0; row<hc; row++) {
|
|
int i;
|
|
for (i=0; i< wc; i++ ) {
|
|
if (*fp > 5 )
|
|
*dptr = gr_screen.current_color.raw8;
|
|
dptr++;
|
|
fp++;
|
|
}
|
|
fp += width - wc;
|
|
dptr += gr_screen.rowsize - wc;
|
|
}
|
|
// }
|
|
}
|
|
gr_unlock();
|
|
}
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
HFONT MyhFont = NULL;
|
|
HDC hDibDC = NULL;
|
|
|
|
void gr_string_win(int x, int y, char *s)
|
|
{
|
|
int old_bitmap = gr_screen.current_bitmap;
|
|
gr_set_font(FONT1);
|
|
gr_string(x,y,s);
|
|
gr_screen.current_bitmap = old_bitmap;
|
|
}
|
|
|
|
void gr_get_string_size_win(int *w, int *h, char *text)
|
|
{
|
|
char *ptr;
|
|
SIZE size;
|
|
|
|
ptr = strchr(text, '\n');
|
|
|
|
if (MyhFont==NULL) {
|
|
if (w) *w = 0;
|
|
if (h) *h = 0;
|
|
return;
|
|
}
|
|
|
|
SelectObject( hDibDC, MyhFont );
|
|
|
|
if (!ptr) {
|
|
GetTextExtentPoint32( hDibDC, text, strlen(text), &size);
|
|
if (w) *w = size.cx;
|
|
if (h) *h = size.cy;
|
|
return;
|
|
}
|
|
|
|
GetTextExtentPoint32(hDibDC, text, ptr - text, &size);
|
|
gr_get_string_size_win(w, h, ptr+1);
|
|
if (w && (size.cx > *w) )
|
|
*w = size.cx;
|
|
|
|
if (h)
|
|
*h += size.cy;
|
|
}
|
|
#endif // ifdef _WIN32
|
|
|
|
char grx_printf_text[2048];
|
|
|
|
void _cdecl gr_printf( int x, int y, char * format, ... )
|
|
{
|
|
va_list args;
|
|
|
|
if ( !Current_font ) return;
|
|
|
|
va_start(args, format);
|
|
vsprintf(grx_printf_text,format,args);
|
|
va_end(args);
|
|
|
|
gr_string(x,y,grx_printf_text);
|
|
}
|
|
|
|
void _cdecl gr_printf_no_resize( int x, int y, char * format, ... )
|
|
{
|
|
va_list args;
|
|
|
|
if ( !Current_font ) return;
|
|
|
|
va_start(args, format);
|
|
vsprintf(grx_printf_text,format,args);
|
|
va_end(args);
|
|
|
|
gr_string(x,y,grx_printf_text,false);
|
|
}
|
|
|
|
void gr_font_close()
|
|
{
|
|
font *fnt;
|
|
int i;
|
|
|
|
fnt = Fonts;
|
|
|
|
for (i=0; i<Num_fonts; i++) {
|
|
if (fnt->kern_data) {
|
|
vm_free(fnt->kern_data);
|
|
fnt->kern_data = NULL;
|
|
}
|
|
|
|
if (fnt->char_data) {
|
|
vm_free(fnt->char_data);
|
|
fnt->char_data = NULL;
|
|
}
|
|
|
|
if (fnt->pixel_data) {
|
|
vm_free(fnt->pixel_data);
|
|
fnt->pixel_data = NULL;
|
|
}
|
|
|
|
if (fnt->bm_data) {
|
|
vm_free(fnt->bm_data);
|
|
fnt->bm_data = NULL;
|
|
}
|
|
|
|
if (fnt->bm_u) {
|
|
vm_free(fnt->bm_u);
|
|
fnt->bm_u = NULL;
|
|
}
|
|
|
|
if (fnt->bm_v) {
|
|
vm_free(fnt->bm_v);
|
|
fnt->bm_v = NULL;
|
|
}
|
|
|
|
fnt++;
|
|
}
|
|
}
|
|
|
|
// Returns -1 if couldn't init font, otherwise returns the
|
|
// font id number.
|
|
int gr_create_font(char * typeface)
|
|
{
|
|
CFILE *fp;
|
|
font *fnt;
|
|
int n, fontnum;
|
|
|
|
fnt = Fonts;
|
|
n = -1;
|
|
for (fontnum=0; fontnum<Num_fonts; fontnum++ ) {
|
|
if (fnt->id != 0 ) {
|
|
if ( !_strnicmp( fnt->filename, typeface, MAX_FILENAME_LEN ) ) {
|
|
return fontnum;
|
|
}
|
|
} else {
|
|
if ( n < 0 ) {
|
|
n = fontnum;
|
|
}
|
|
}
|
|
fnt++;
|
|
}
|
|
|
|
if ( fontnum==MAX_FONTS ) {
|
|
Error( LOCATION, "Too many fonts!\nSee John, or change MAX_FONTS in Graphics\\Font.h\n" );
|
|
}
|
|
|
|
bool localize = true;
|
|
|
|
fp = cfopen( typeface, "rb", CFILE_NORMAL, CF_TYPE_ANY, localize );
|
|
if ( fp == NULL ) return -1;
|
|
|
|
if ( fontnum == Num_fonts ) {
|
|
Num_fonts++;
|
|
}
|
|
|
|
strncpy( fnt->filename, typeface, MAX_FILENAME_LEN );
|
|
cfread( &fnt->id, 4, 1, fp );
|
|
cfread( &fnt->version, sizeof(int), 1, fp );
|
|
cfread( &fnt->num_chars, sizeof(int), 1, fp );
|
|
cfread( &fnt->first_ascii, sizeof(int), 1, fp );
|
|
cfread( &fnt->w, sizeof(int), 1, fp );
|
|
cfread( &fnt->h, sizeof(int), 1, fp );
|
|
cfread( &fnt->num_kern_pairs, sizeof(int), 1, fp );
|
|
cfread( &fnt->kern_data_size, sizeof(int), 1, fp );
|
|
cfread( &fnt->char_data_size, sizeof(int), 1, fp );
|
|
cfread( &fnt->pixel_data_size, sizeof(int), 1, fp );
|
|
|
|
fnt->id = INTEL_SHORT( fnt->id );
|
|
fnt->version = INTEL_INT( fnt->version );
|
|
fnt->num_chars = INTEL_INT( fnt->num_chars );
|
|
fnt->first_ascii = INTEL_INT( fnt->first_ascii );
|
|
fnt->w = INTEL_INT( fnt->w );
|
|
fnt->h = INTEL_INT( fnt->h );
|
|
fnt->num_kern_pairs = INTEL_INT( fnt->num_kern_pairs );
|
|
fnt->kern_data_size = INTEL_INT( fnt->kern_data_size );
|
|
fnt->char_data_size = INTEL_INT( fnt->char_data_size );
|
|
fnt->pixel_data_size = INTEL_INT( fnt->pixel_data_size );
|
|
|
|
if ( fnt->kern_data_size ) {
|
|
fnt->kern_data = (font_kernpair *)vm_malloc( fnt->kern_data_size );
|
|
Assert(fnt->kern_data!=NULL);
|
|
cfread( fnt->kern_data, fnt->kern_data_size, 1, fp );
|
|
} else {
|
|
fnt->kern_data = NULL;
|
|
}
|
|
if ( fnt->char_data_size ) {
|
|
fnt->char_data = (font_char *)vm_malloc( fnt->char_data_size );
|
|
Assert( fnt->char_data != NULL );
|
|
cfread( fnt->char_data, fnt->char_data_size, 1, fp );
|
|
|
|
for (int i=0; i<fnt->num_chars; i++) {
|
|
fnt->char_data[i].spacing = INTEL_INT( fnt->char_data[i].spacing );
|
|
fnt->char_data[i].byte_width = INTEL_INT( fnt->char_data[i].byte_width );
|
|
fnt->char_data[i].offset = INTEL_INT( fnt->char_data[i].offset );
|
|
fnt->char_data[i].kerning_entry = INTEL_INT( fnt->char_data[i].kerning_entry );
|
|
fnt->char_data[i].user_data = INTEL_SHORT( fnt->char_data[i].user_data );
|
|
}
|
|
} else {
|
|
fnt->char_data = NULL;
|
|
}
|
|
if ( fnt->pixel_data_size ) {
|
|
fnt->pixel_data = (ubyte *)vm_malloc( fnt->pixel_data_size );
|
|
Assert(fnt->pixel_data!=NULL);
|
|
cfread( fnt->pixel_data, fnt->pixel_data_size, 1, fp );
|
|
} else {
|
|
fnt->pixel_data = NULL;
|
|
}
|
|
cfclose(fp);
|
|
|
|
// Create a bitmap for hardware cards.
|
|
// JAS: Try to squeeze this into the smallest square power of two texture.
|
|
// This should probably be done at font generation time, not here.
|
|
int w, h;
|
|
if ( fnt->pixel_data_size < 64*64 ) {
|
|
w = h = 64;
|
|
} else if ( fnt->pixel_data_size < 128*128 ) {
|
|
w = h = 128;
|
|
} else {
|
|
w = h = 256;
|
|
}
|
|
|
|
fnt->bm_w = w;
|
|
fnt->bm_h = h;
|
|
fnt->bm_data = (ubyte *)vm_malloc(fnt->bm_w*fnt->bm_h);
|
|
fnt->bm_u = (int *)vm_malloc(sizeof(int)*fnt->num_chars);
|
|
fnt->bm_v = (int *)vm_malloc(sizeof(int)*fnt->num_chars);
|
|
|
|
memset( fnt->bm_data, 0, fnt->bm_w * fnt->bm_h );
|
|
|
|
int i,x,y;
|
|
x = y = 0;
|
|
for (i=0; i<fnt->num_chars; i++ ) {
|
|
ubyte * fp;
|
|
int x1, y1;
|
|
fp = &fnt->pixel_data[fnt->char_data[i].offset];
|
|
if ( x + fnt->char_data[i].byte_width >= fnt->bm_w ) {
|
|
x = 0;
|
|
y += fnt->h;
|
|
if ( y+fnt->h > fnt->bm_h ) {
|
|
Error( LOCATION, "Font too big!\n" );
|
|
}
|
|
}
|
|
fnt->bm_u[i] = x;
|
|
fnt->bm_v[i] = y;
|
|
|
|
for( y1=0; y1<fnt->h; y1++ ) {
|
|
for (x1=0; x1<fnt->char_data[i].byte_width; x1++ ) {
|
|
uint c = *fp++;
|
|
if ( c > 14 ) c = 14;
|
|
fnt->bm_data[(x+x1)+(y+y1)*fnt->bm_w] = (unsigned char)(c);
|
|
}
|
|
}
|
|
x += fnt->char_data[i].byte_width;
|
|
}
|
|
|
|
fnt->bitmap_id = bm_create( 8, fnt->bm_w, fnt->bm_h, fnt->bm_data, BMP_AABITMAP );
|
|
|
|
return fontnum;
|
|
}
|
|
|
|
int gr_get_fontnum(char *filename)
|
|
{
|
|
int i;
|
|
for(i = 0; i < Num_fonts; i++)
|
|
{
|
|
if(!strextcmp(Fonts[i].filename, filename))
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void gr_set_font(int fontnum)
|
|
{
|
|
if ( fontnum < 0 ) {
|
|
Current_font = NULL;
|
|
return;
|
|
}
|
|
|
|
if ( fontnum >= 0 && fontnum < Num_fonts) {
|
|
Current_font = &Fonts[fontnum];
|
|
}
|
|
}
|
|
|
|
void gr_font_init()
|
|
{
|
|
gr_init_font( NOX("font01.vf") );
|
|
gr_init_font( NOX("font02.vf") );
|
|
gr_init_font( NOX("font03.vf") );
|
|
}
|
|
|
|
// Returns -1 if couldn't init font, otherwise returns the
|
|
// font id number.
|
|
int gr_init_font(char * typeface)
|
|
{
|
|
int Loaded_fontnum;
|
|
|
|
Loaded_fontnum = gr_create_font(typeface);
|
|
|
|
//WMC - Handle failure
|
|
if(Loaded_fontnum < 0)
|
|
return -1;
|
|
|
|
gr_set_font( Loaded_fontnum );
|
|
|
|
return Loaded_fontnum;
|
|
}
|