/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program 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 3 of the License, or ** (at your option) any later version. ** ** This program 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 this program. If not, see . */ /************************************************************************************************ *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** ************************************************************************************************ * * * Project Name: Setup * * * * Archive: TTFont.cpp * * * * Author: Maria del Mar McCready Legg * * * * Modtime: 8/24/99 3:44pm * * * * Revision: 01 * * * *----------------------------------------------------------------------------------------------* * Functions: * * TTFontClass::TTFontClass -- Constructor for a font class object. * * TTFontClass::Char_Pixel_Width -- Fetch the pixel width of the character specified. * * TTFontClass::Find_Text_VLength -- Finds length of text in pixels * * TTFontClass::Get_Height -- Fetch the normalized height of the nominal font character. * * TTFontClass::Get_Width -- Get normalized width of the nominal font character. * * TTFontClass::Print -- Print text to the surface specified. * * TTFontClass::Raw_Height -- Fetch the height of the font. * * TTFontClass::Raw_Width -- Fetch the raw width of a character. * * TTFontClass::Set_XSpacing -- Set the X spacing override value. * * TTFontClass::Set_YSpacing -- Set the vertical (Y) spacing override value. * * TTFontClass::String_Pixel_Width -- Determines the width of the string in pixels. * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ #define STRICT #include #include #include #include #include #include "args.h" #include "autorun.h" #include "rect.h" #include "wnd_file.h" #include "ttfont.h" #include "jsupport.h" // [OYO] #include "locale_api.h" #define FONTINFOMAXHEIGHT 4 #define FONTINFOMAXWIDTH 5 #define FUDGEDIV 16 //------------------------------------------------------------------------- // Text Fonts. //------------------------------------------------------------------------- TTFontClass *TTButtonFontPtr = NULL; TTFontClass *TTButtonFontPtrSmall = NULL; TTFontClass *TTTextFontPtr = NULL; TTFontClass *TTTextFontPtr640 = NULL; TTFontClass *TTTextFontPtr800 = NULL; TTFontClass *TTLicenseFontPtr = NULL; FontManagerClass * FontManager = NULL; //unsigned long TEXT_COLOR = RGB( 247, 171, 11 ); //unsigned long SHADOW_COLOR = RGB( 40, 8, 8 ); unsigned long TEXT_COLOR = RGB( 255, 204, 51 ); unsigned long SHADOW_COLOR = RGB( 40, 8, 8 ); unsigned long TEXT_NORMAL_COLOR = RGB( 255, 204, 51 ); unsigned long TEXT_NORMAL_SHADOW_COLOR = RGB( 40, 8, 8 ); unsigned long TEXT_FOCUSED_COLOR = RGB( 255, 204, 51 ); unsigned long TEXT_FOCUSED_SHADOW_COLOR = RGB( 40, 8, 8 ); unsigned long TEXT_PRESSED_COLOR = RGB( 194, 79, 32 ); unsigned long TEXT_PRESSED_SHADOW_COLOR = RGB( 70, 55, 49 ); unsigned long BLACK_COLOR = RGB( 0, 0, 0 ); unsigned long WHITE_COLOR = RGB( 255, 255, 255 ); unsigned long RED_COLOR = RGB( 255, 0, 0 ); unsigned long ORANGE_COLOR = RGB( 199, 91, 0 ); unsigned long YELLOW_COLOR = RGB( 255, 247, 0 ); unsigned long GREEN_COLOR = RGB( 0, 255, 0 ); unsigned long BLUE_COLOR = RGB( 0, 0, 255 ); unsigned long INDIGO_COLOR = RGB( 90, 2, 253 ); unsigned long VIOLET_COLOR = RGB( 128, 0, 255 ); /************************************************************************************ * TTFontClass::TTFontClass -- Constructor for a font class object. * * * * This constructs a font object as it is based upon the true type windows fonts. * * * * INPUT: char *filename -- True Type Windows font file to open. * * char *facename -- It's face name. * * int height -- The height requested. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 08/24/1999 MML : Created. * *==================================================================================*/ TTFontClass::TTFontClass( HDC hdc, char *filename, char *facename, int height, int weight, BYTE charset, int width, int escapement, int orientation, BYTE italic, BYTE underline, BYTE strikeout, BYTE outputPrecision, BYTE clipPrecision, BYTE quality, BYTE pitchAndFamily ) { HGDIOBJ old_object; TEXTMETRIC tm; char real_facename[MAX_PATH]; //-------------------------------------------------------------------------- // Get or Set a Font filename. //-------------------------------------------------------------------------- if (( filename == NULL ) || ( filename[0] == '\0' )) { strcpy( szFilename, "Arial.ttf" ); } else { strcpy( szFilename, filename ); } //-------------------------------------------------------------------------- // Get or Set a Font facename. //-------------------------------------------------------------------------- if (( facename == NULL ) || ( facename[0] == '\0' )) { strcpy( szFacename, "Arial" ); } else { strcpy( szFacename, facename ); } real_facename[0] = '\0'; Msg( __LINE__, __FILE__, "TTFontClass -- filename=%s, facename=%s, height=%d.", filename, facename, height ); //-------------------------------------------------------------------------- // Make sure the font file is "Registered". Then create the font. //-------------------------------------------------------------------------- AddFontResource( szFilename ); Font = CreateFont( height, width, escapement, orientation, weight, italic, underline, strikeout, charset, outputPrecision, clipPrecision, quality, pitchAndFamily, szFacename ); if ( hdc && ( Font != NULL )) { //---------------------------------------------------------------------- // The GetTextFace function lets a program determine the face name of // THE font currently selected in the device context: //---------------------------------------------------------------------- old_object = SelectObject( hdc, Font ); GetTextFace( hdc, ( sizeof( real_facename ) / sizeof( TCHAR )), real_facename ); if( _stricmp( real_facename, szFacename ) != 0 ) { strcpy( szFilename, "Arial.ttf" ); strcpy( szFacename, "Arial" ); SelectObject( hdc, old_object ); DeleteObject( Font ); Font = NULL; Font = CreateFont( height, // height of font width, // average character width escapement, // angle of escapement orientation, // base-line orientation angle weight, // font weight italic, // italic attribute option underline, // underline attribute option strikeout, // strikeout attribute option charset, // character set identifier outputPrecision, // output precision clipPrecision, // clipping precision quality, // output quality pitchAndFamily, // pitch and family szFacename ); // typeface name real_facename[0] = '\0'; old_object = SelectObject( hdc, Font ); GetTextFace( hdc, ( sizeof( real_facename ) / sizeof( TCHAR )), real_facename ); } } //-------------------------------------------------------------------------- // Save off the height. //-------------------------------------------------------------------------- Height = height; if ( hdc ) { //----------------------------------------------------------------------- // Get info from the font in BackBuffer's DC. //----------------------------------------------------------------------- old_object = SelectObject( hdc, Font ); GetTextMetrics( hdc, &tm ); FontXSpacing = GetTextCharacterExtra( hdc ); Ascent = tm.tmAscent; Descent = tm.tmDescent; InternalLeading = tm.tmInternalLeading; ExternalLeading = tm.tmExternalLeading; AveCharWidth = tm.tmAveCharWidth; MaxCharWidth = tm.tmMaxCharWidth; Overhang = tm.tmOverhang; Italic = tm.tmItalic; Underlined = tm.tmUnderlined; StruckOut = tm.tmStruckOut; CharSet = tm.tmCharSet; // [OYO] It is important to support Double Byte Chars SelectObject( hdc, old_object ); } else { //----------------------------------------------------------------------- // Set default values. //----------------------------------------------------------------------- Ascent = 0; Descent = 0; InternalLeading = 0; ExternalLeading = 0; AveCharWidth = 0; MaxCharWidth = 0; Overhang = 0; Italic = 0; Underlined = 0; StruckOut = 0; CharSet = 0; // [OYO] FontXSpacing = 0; } } /*********************************************************************************************** * TTFontClass::Char_Pixel_Width -- Fetch the pixel width of the character specified. * * * * This will return with the pixel width of the character specified. * * * * INPUT: c -- The character to determine the pixel width for. * * * * OUTPUT: Returns with the pixel width of the character. * * * * WARNINGS: The return width is the screen real estate width which may differ from the * * actual pixels of the character. This difference is controlled by the font * * X spacing. * * * * HISTORY: * * 05/26/1997 JLB : Created. * *=============================================================================================*/ int TTFontClass::Char_Pixel_Width( HDC hdc, UINT c ) const { HGDIOBJ old_object; ABC abc; abc.abcA = 0; abc.abcB = 0; abc.abcC = 0; if ( hdc ) { old_object = SelectObject( hdc, Font ); GetCharABCWidths( hdc, c, c, &abc ); SelectObject( hdc, old_object ); } return( abc.abcA + abc.abcB + abc.abcC ); } /************************************************************************************************ * TTFontClass::Char_Pixel_Width -- Fetch the pixel width of the character specified. * * This will return with the pixel width of the character specified. * * INPUT: HDC hdc -- must be passed in from calling function. * char const * string -- the pointer to the character in the string. * int *num_bytes -- return number of bytes this character has: 1 or 2. * * OUTPUT: Returns with the pixel width of the character. * * WARNINGS: The return width is the screen real estate width which may differ from the * actual pixels of the character. This difference is controlled by the font * X spacing. * * NOTE: This is function determines if the character is a double-byte or single-byte * character, then calls the standard Char_Pixel_Width. * * HISTORY: * 05/26/1997 JLB : Created. *==============================================================================================*/ // // [OYO] Supports DBCS ( multi-byte characters ). // int TTFontClass::Char_Pixel_Width ( HDC hdc, char const * string, int *num_bytes ) const { char const *letter = string; int length = 0; UINT c; //-------------------------------------------------------------------------- // These values must be passed in. //-------------------------------------------------------------------------- if ( string == NULL || *string == '\0' || hdc == NULL ) { return( 0 ); } //-------------------------------------------------------------------------- // If this value is passed in, the set the default value (1=single). //-------------------------------------------------------------------------- if ( num_bytes!= NULL ) { *num_bytes = 1; } //-------------------------------------------------------------------------- // Get the pixel width of the character. If it is a double-byte character, // then num_bytes will come back as '2'. //-------------------------------------------------------------------------- if( IsFontDBCS() && IsDBCSLeadByte( *letter )){ c = Get_Double_Byte_Char( letter, num_bytes ); length += Char_Pixel_Width( hdc, c ); // pixel length of double-byte character. } else { length += Char_Pixel_Width( hdc, *letter ); // pixel length of single-byte character. } return( length ); } /************************************************************************************************ * TTFontClass::String_Pixel_Width -- Determines the width of the string in pixels. * * * * This routine is used to determine how many pixels wide the string will be if it were * * printed. * * * * INPUT: string -- The string to convert into its pixel width. * * * * OUTPUT: Returns with the number of pixels the string would span if it were printed. * * * * WARNINGS: This routine does not take into account clipping. * * * * HISTORY: * * 05/26/1997 JLB : Created. * *==============================================================================================*/ int TTFontClass::String_Pixel_Width( HDC hdc, char const * string ) const { if ( string == NULL ) { return(0); } int largest = 0; // Largest recorded width of the string. int width = 0; HGDIOBJ old_object; int length; SIZE size; bool make_dc = FALSE; HDC localDC = hdc; size.cx = 0; if ( localDC == NULL ) { return( size.cx ); } if ( localDC ) { length = strlen( string ); old_object = SelectObject( localDC, Font ); GetTextExtentPoint32( localDC, string, length, &size ); SelectObject( localDC, old_object ); } return( size.cx ); } /**************************************************************************** * * NAME * String_Pixel_Bounds(String, Bounds) * * DESCRIPTION * Calculate the bounding box for the specified string. * * INPUTS * String - String to calculate bounds for * Bounds - Rect to fill with bounds * * RESULT * NONE * ****************************************************************************/ // // [OYO] Supports DBCS ( multi-byte characters ). // void TTFontClass::String_Pixel_Bounds( HDC hdc, const char* string, Rect& bounds ) const { int width; int height; bounds.Width = 0; bounds.Height = 0; if ( string == NULL ) { return; } if ( hdc == NULL ) { return; } width = 0; height = Get_Height(); while ( *string != 0 ) { if (( *string == '\r' ) || ( *string == '\n' )) { string++; height += Get_Height(); bounds.Width = max( bounds.Width, width ); width = 0; } else if( IsFontDBCS()){ #if(0) //-------------------------------------------------------------------- // Using one of those _tc functions: // Get a character, get the width of that character, then // move the pointer to the next character. //-------------------------------------------------------------------- UINT c = Get_Double_Byte_Char( string ); width += Char_Pixel_Width( hdc, c ); string = _tcsinc( string ); #else //-------------------------------------------------------------------- // MBCS way: Get a byte. If byte is a "Lead" byte, get the second half, // combine them into one character, then get the width of that character. //-------------------------------------------------------------------- UINT c = *(BYTE*)string++; if( IsDBCSLeadByte( c )&& *string ) { c = ( c << 8 ) | *(BYTE *)string++; } width += Char_Pixel_Width( hdc, c ); #endif } else { width += Char_Pixel_Width( hdc, *string++ ); } } bounds.Width = max( bounds.Width, width ); bounds.Height = height; } /*********************************************************************************************** * TTFontClass::Get_Double_Byte_Char -- Get the first character even if DBSC. * * INPUT: char * -- string to look at. * * OUTPUT: Returns with the normalized width of the character in the font. * * WARNINGS: I added this function based on code provided by Ikeda-san. * * HISTORY: * 06/05/2000 MML : Created. *=============================================================================================*/ // // [OYO] Supports DBCS ( multi-byte characters ). // UINT TTFontClass::Get_Double_Byte_Char ( const char *string, int *num_bytes ) const { if ( string == NULL || *string == '\0' ) { return( 0 ); } const char *ptr = string; UINT c = *(BYTE *)ptr++; if ( num_bytes != NULL ) { *num_bytes = 1; } //-------------------------------------------------------------------------- // The IsDBCSLeadByte function determines whether a character is a // lead byte — that is, the first byte of a character in a double-byte // character set (DBCS). // // BOOL IsDBCSLeadByte( BYTE TestChar /* character to test */ ); // // TestChar -- Specifies the character to be tested. // // Return Values // If the character is a lead byte, the return value is nonzero. // If the character is not a lead byte, the return value is zero. // To get extended error information, call GetLastError. // Remarks // Lead bytes are unique to double-byte character sets. // A lead byte introduces a double-byte character. Lead bytes // occupy a specific range of byte values. The IsDBCSLeadByte // function uses the ANSI code page to check lead-byte ranges. // To specify a different code page, use the IsDBCSLeadByteEx function. // // Declared in winnls.h. //-------------------------------------------------------------------------- if( IsDBCSLeadByte( c )&& *ptr ) { // [OYO] c = ( c << 8 ) | *(BYTE *)ptr++; if ( num_bytes != NULL ) { *num_bytes = 2; } } return( c ); } /*********************************************************************************************** * TTFontClass::Get_Width -- Get normalized width of the nominal font character. * * * * This routine is used to fetch the width of the widest character in the font but the * * width has been biased according to any X spacing override present. * * * * INPUT: none * * * * OUTPUT: Returns with the normalized width of the widest character in the font. * * * * WARNINGS: none * * * * HISTORY: * * 05/26/1997 JLB : Created. * *=============================================================================================*/ int TTFontClass::Get_Width( void ) const { return( MaxCharWidth - Overhang ); } /*********************************************************************************************** * TTFontClass::Get_Height -- Fetch the normalized height of the nominal font character. * * * * This will return the height of the font but the returned height will be adjusted by any * * Y spacing override present. * * * * INPUT: none * * * * OUTPUT: Returns with the height of the font normalized by any spacing overrides. * * * * WARNINGS: none * * * * HISTORY: * * 05/26/1997 JLB : Created. * *=============================================================================================*/ int TTFontClass::Get_Height( void ) const { return( Height ); } /*********************************************************************************************** * TTFontClass::Set_XSpacing -- Set the X spacing override value. * * * * Use this routine to control the horizontal spacing override for this font. If the value * * is negative, the font becomes compressed. If the value is positive, then the font * * becomes expanded. * * * * INPUT: x -- The X spacing override to use for this font. * * * * OUTPUT: Returns with the old X spacing override value. * * * * WARNINGS: none * * * * HISTORY: * * 05/26/1997 JLB : Created. * *=============================================================================================*/ int TTFontClass::Set_XSpacing( HDC hdc, int x ) { // HGDIOBJ old_object; // int answer = 0; // if ( hdc ) { // old_object = SelectObject( hdc, Font ); // answer = SetTextCharacterExtra( hdc, x ); // SelectObject( hdc, old_object ); // } FontXSpacing = x; return( x ); } /*********************************************************************************************** * TTFontClass::Set_YSpacing -- Set the vertical (Y) spacing override value. * * * * Use this routine to control the "line spacing" of a font. If the Y spacing is negative * * then the font becomes closer to the line above it. If value is positive, then more * * space occurs between lines. * * * * INPUT: y -- The Y spacing override to use for this font. * * * * OUTPUT: Returns with the old Y spacing override value. * * * * WARNINGS: none * * * * HISTORY: * * 05/26/1997 JLB : Created. * *=============================================================================================*/ int TTFontClass::Set_YSpacing( int y ) { FontYSpacing = y; return(y); } /*********************************************************************************************** * TTFontClass::Print -- Print text to the surface specified. WCHAR Version. * * * * This displays text to the surface specified and with the attributes specified. * * * * INPUT: string -- The string to display to the surface. * * surface -- The surface to display the text upon. * * cliprect -- The clipping rectangle that both clips the text and biases the print * * location to. * * point -- The draw position for the upper left corner of the first character. * * convert -- The pixel convert object that is used to draw the correct colors to * * the destination surface. * * remap -- Auxiliary remap table for font colors. * * * * OUTPUT: Returns with the point where the next print should begin if it is to smoothly * * continue where this print operation left off. * * * * WARNINGS: There are two separate drawing routines; one for old fonts and one for new fonts. * * * * HISTORY: * * 05/26/1997 JLB : Created. * * 06/20/1887 BNA : Modified to handle new fonts. * *=============================================================================================*/ #if(NDEBUG) Point2D TTFontClass::Print( HDC hdc, wchar_t const * string, Rect const & cliprect, COLORREF forecolor, /* = TEXT_COLOR, */ COLORREF backcolor, /* = TEXT_SHADOW_COLOR, */ TextFormatType flag, /* = TPF_DEFAULT, */ TextShadowType shadow ) /* = TPF_FULLSHADOW */ { char buffer[ _MAX_PATH ]; int length = wcslen( string ); memset( buffer, '\0', _MAX_PATH ); WideCharToMultiByte( CodePage, 0, string, length, buffer, _MAX_PATH, NULL, NULL ); return( Print( hdc, buffer, cliprect, forecolor, backcolor, flag, shadow )); } #else Point2D TTFontClass::Print( HDC hdc, wchar_t const * string, Rect const & cliprect, COLORREF forecolor, /* = TEXT_COLOR, */ COLORREF backcolor, /* = TEXT_SHADOW_COLOR, */ TextFormatType flag, /* = TPF_DEFAULT, */ TextShadowType shadow ) /* = TPF_FULLSHADOW */ { Point2D point( cliprect.X, cliprect.Y ); RECT rect; HGDIOBJ old_object; SIZE size; int length = 0; int result = 0; //-------------------------------------------------------------------------- // If no string, why continue? //-------------------------------------------------------------------------- assert( string != NULL ); assert( hdc != NULL ); if (( string == NULL ) || ( string[0] == '\0' )) { return( point ); } //-------------------------------------------------------------------------- // Set up rectangle print regions for the "shadow" and the main color. //-------------------------------------------------------------------------- length = wcslen( string ); rect.left = cliprect.X; rect.top = cliprect.Y; rect.right = cliprect.X + cliprect.Width; rect.bottom = cliprect.Y + cliprect.Height; Msg( __LINE__, __FILE__, "TTFontClass::Print -- string = %s.", string ); Msg( __LINE__, __FILE__, "TTFontClass::Print -- strlen = %d.", length ); Msg( __LINE__, __FILE__, "TTFontClass::Print -- rect = [%d, %d, %d, %d].", rect.left, rect.top, rect.right, rect.bottom ); // Msg( __LINE__, __FILE__, "TTFontClass::Print -- rect2 = [%d, %d, %d, %d].", rect.left, rect.top, rect.right, rect.bottom ); //-------------------------------------------------------------------------- // Print the "Shadow" depending on style desired, then the text in the requested color. //-------------------------------------------------------------------------- if ( hdc ) { assert( Font != NULL ); old_object = SelectObject( hdc, Font ); SetTextCharacterExtra( hdc, FontXSpacing ); SetTextAlign( hdc, TA_LEFT | TA_TOP ); SetBkMode( hdc, TRANSPARENT ); SetTextColor( hdc, forecolor ); // result = ExtTextOutW( // hdc, // handle to DC // rect.left, // x-coordinate of reference point // rect.top, // y-coordinate of reference point // ETO_CLIPPED, // text-output options // &rect, // optional dimensions // string, // string // length, // number of characters in string // NULL // array of spacing values // ); // result = TextOutW( // hdc, // handle to DC // rect.left, // x-coordinate of starting position // rect.top, // y-coordinate of starting position // string, // character string // length // number of characters // ); result = DrawTextW( hdc, string, length, &rect, flag ); GetTextExtentPointW( hdc, string, length, &size ); SelectObject( hdc, old_object ); } point.X += size.cx; return( point ); } #endif /*********************************************************************************************** * TTFontClass::Print -- Print text to the surface specified. CHAR version. * * * * This displays text to the surface specified and with the attributes specified. * * * * INPUT: string -- The string to display to the surface. * * surface -- The surface to display the text upon. * * cliprect -- The clipping rectangle that both clips the text and biases the print * * location to. * * point -- The draw position for the upper left corner of the first character. * * convert -- The pixel convert object that is used to draw the correct colors to * * the destination surface. * * remap -- Auxiliary remap table for font colors. * * * * OUTPUT: Returns with the point where the next print should begin if it is to smoothly * * continue where this print operation left off. * * * * WARNINGS: There are two separate drawing routines; one for old fonts and one for new fonts. * * * * HISTORY: * * 05/26/1997 JLB : Created. * * 06/20/1887 BNA : Modified to handle new fonts. * *=============================================================================================*/ Point2D TTFontClass::Print( HDC hdc, char const * string, Rect const & cliprect, COLORREF forecolor, /* = TEXT_COLOR, */ COLORREF backcolor, /* = TEXT_SHADOW_COLOR, */ TextFormatType flag, /* = TPF_DEFAULT, */ TextShadowType shadow ) /* = TPF_FULLSHADOW */ { Point2D point( cliprect.X, cliprect.Y ); RECT rect, rect2; HGDIOBJ old_object; SIZE size; int length = 0; int result = 0; //-------------------------------------------------------------------------- // If no string, why continue? //-------------------------------------------------------------------------- assert( string != NULL ); assert( hdc != NULL ); if (( string == NULL ) || ( string[0] == '\0' )) { return( point ); } //-------------------------------------------------------------------------- // Set up rectangle print regions for the "shadow" and the main color. //-------------------------------------------------------------------------- length = strlen( string ); rect.left = cliprect.X; rect.top = cliprect.Y; rect.right = cliprect.X + cliprect.Width; rect.bottom = cliprect.Y + cliprect.Height; // Shadow rect2.left = rect.left - 1; rect2.top = rect.top - 1; rect2.right = rect.right - 1; rect2.bottom= rect.bottom - 1; // Msg( __LINE__, __FILE__, "TTFontClass::Print -- strlen = %d.", length ); // Msg( __LINE__, __FILE__, "TTFontClass::Print -- rect = [%d, %d, %d, %d].", rect.left, rect.top, rect.right, rect.bottom ); // Msg( __LINE__, __FILE__, "TTFontClass::Print -- rect2 = [%d, %d, %d, %d].", rect.left, rect.top, rect.right, rect.bottom ); //-------------------------------------------------------------------------- // Print the "Shadow" depending on style desired, then the text in the requested color. //-------------------------------------------------------------------------- if ( hdc ) { assert( Font != NULL ); old_object = SelectObject( hdc, Font ); SetTextCharacterExtra( hdc, FontXSpacing ); SetTextAlign( hdc, TA_LEFT | TA_TOP ); SetBkMode( hdc, TRANSPARENT ); SetTextColor( hdc, backcolor ); if ( shadow == TPF_SHADOW ) { // One left, One up. result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One left. rect2.left = rect.left - 1; rect2.top = rect.top; rect2.right = rect.right - 1; rect2.bottom = rect.bottom; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One up. rect2.left = rect.left; rect2.top = rect.top - 1; rect2.right = rect.right; rect2.bottom = rect.bottom - 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); } else if ( shadow == TPF_DOUBLESHADOW ) { // One left, One up. result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One left. rect2.left = rect.left - 1; rect2.top = rect.top; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One up. rect2.left = rect.left; rect2.top = rect.top - 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two left, Two up. rect2.left = rect.left - 2; rect2.top = rect.top - 2; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two left. rect2.left = rect.left - 2; rect2.top = rect.top; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two up. rect2.left = rect.left; rect2.top = rect.top - 2; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); } else if ( shadow == TPF_FULLSHADOW ) { // One left, One up. result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One right, One up. rect2.left = rect.left + 1; rect2.top = rect.top - 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One left, One down. rect2.left = rect.left - 1; rect2.top = rect.top + 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One right, One down. rect2.left = rect.left + 1; rect2.top = rect.top + 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One left. rect2.left = rect.left - 1; rect2.top = rect.top; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One right. rect2.left = rect.left + 1; rect2.top = rect.top; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One up. rect2.left = rect.left; rect2.top = rect.top - 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // One down. rect2.left = rect.left; rect2.top = rect.top + 1; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two right. rect2.left = rect.left + 2; rect2.top = rect.top; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two down. rect2.left = rect.left; rect2.top = rect.top + 2; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two right, One up. rect2.left = rect.left + 2; rect2.top = rect.top - 2; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Two right, One down. rect2.left = rect.left + 2; rect2.top = rect.top + 2; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Three right. rect2.left = rect.left + 3; rect2.top = rect.top; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Three down. rect2.left = rect.left; rect2.top = rect.top + 3; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Three right, One up. rect2.left = rect.left + 3; rect2.top = rect.top - 3; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); // Three right, One down. rect2.left = rect.left + 3; rect2.top = rect.top + 3; result = DrawText( hdc, string, length, &rect2, flag ); assert( result != 0 ); } SetTextColor( hdc, forecolor ); result = DrawText( hdc, string, length, &rect, flag ); assert( result != 0 ); GetTextExtentPoint( hdc, string, length, &size ); SelectObject( hdc, old_object ); } point.X += size.cx; return( point ); } /*************************************************************************** * TTFontClass::FIND_TEXT_VLENGTH -- Finds length of text in pixels * * * * INPUT: BYTE *string - the strength to find the vertical length of * * int width - the width of the region to fit it in * * * * OUTPUT: int -- the number of pixels it takes up veritcally. * * * * HISTORY: * * 09/27/1994 PWG : Created. * *=========================================================================*/ // // [OYO] Supports DBCS ( multi-byte characters ). // int TTFontClass::Find_Text_VLength( HDC hdc, char *str, int width ) { int curlen = 0; int lastlen = 0; int lines = Get_Height(); char *letter = str; bool make_dc = FALSE; HDC localDC = hdc; if ( *str == '\0' || str == NULL ) { return( 0 ); } //-------------------------------------------------------------------------- // If no DC was passed in, then we need to get one. //-------------------------------------------------------------------------- if ( localDC == NULL ) { return( 0 ); } //========================================================================== // Process languages EXCEPT Double-byte languages. //========================================================================== if( !(IS_LANGUAGE_DBCS( LanguageID ))) { //----------------------------------------------------------------------- // Get the pixel length of the string. //----------------------------------------------------------------------- curlen = String_Pixel_Width( localDC, str ); lines = 0; //----------------------------------------------------------------------- // If the string in longer than the width given, calculate the number of // lines needed in pixels (height of string in pixels ). //----------------------------------------------------------------------- if ( curlen > width ) { while( curlen > 0 ) { if ( curlen > width ) { curlen -= width; } else { curlen = 0; } lines += Get_Height(); } } else { lines = Get_Height(); } //----------------------------------------------------------------------- // Check for any newlines. Add one line per newline. //----------------------------------------------------------------------- letter = str; while ( *letter ) { if ( *letter == '\n') { lines += Get_Height(); } letter++; } } else { //======================================================================= // Process Double-Byte language text. //======================================================================= int i, n, wspc; UINT c; int fdbcs = IsFontDBCS(); lines = 0; //----------------------------------------------------------------------- // For each word... //----------------------------------------------------------------------- while ( n = nGetWord( letter, fdbcs )) { //-------------------------------------------------------------------- // For each character in the word... //-------------------------------------------------------------------- for ( c=0, wspc=0, curlen=0, i=0; i < n; i++ ) { if ( c ) { //-------------------------------------------------------------- // Double-byte character. //-------------------------------------------------------------- c = ( c<<8 )|(UINT)(BYTE)letter[i]; curlen += Char_Pixel_Width( localDC, c ) + wspc; c = 0; wspc = 0; } else if( fdbcs && IsDBCSLeadByte((BYTE)letter[i])) { //-------------------------------------------------------------- // First half of a Double-byte character. //-------------------------------------------------------------- c = (UINT)(BYTE)letter[i]; } else if((BYTE)letter[i] > ' ' ) { //-------------------------------------------------------------- // Single-byte character. //-------------------------------------------------------------- curlen += Char_Pixel_Width( localDC, (UINT)(BYTE)letter[i] ) + wspc; wspc = 0; } else if( letter[i] == ' ') { //-------------------------------------------------------------- // Space character. //-------------------------------------------------------------- wspc += Char_Pixel_Width( localDC, ' ' ); } } // end-of-for //-------------------------------------------------------------------- // //-------------------------------------------------------------------- if( lastlen + curlen > width ) { lines += Get_Height(); lastlen = 0; } //-------------------------------------------------------------------- // !!! If one block length bigger than available width, // next line will be overflow. but never endless loop. !!! //-------------------------------------------------------------------- lastlen += curlen + wspc; //-------------------------------------------------------------------- // //-------------------------------------------------------------------- if( letter[i] == '\n' ) { lines += Get_Height(); lastlen = 0; } letter += n; } // end-of-while //----------------------------------------------------------------------- // Left over, add a line. //----------------------------------------------------------------------- if( lastlen ) { lines += Get_Height(); } } //-------------------------------------------------------------------------- // Return the number of lines. //-------------------------------------------------------------------------- if ( !lines ) { lines = Get_Height(); } return( lines ); } /*********************************************************************************************** * FontManagerClass::FontManagerClass -- Constructor for FontManager class. * * * * INPUT: none. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 03/26/1998 MML : Created. * *=============================================================================================*/ FontManagerClass::FontManagerClass ( HDC hdc ) { //-------------------------------------------------------------------------- // Open a DC to the BackBuffer. //-------------------------------------------------------------------------- if ( hdc ) { char szPath[ MAX_PATH ]; char szFile[ MAX_PATH ]; char szFacename[ MAX_PATH ]; char drive[ _MAX_DRIVE ]; char dir[ _MAX_DIR ]; bool b640X480 = false; RECT rect; // Desktop Window ( used once ). strcpy( szFile, "Arial.ttf" ); strcpy( szFacename, "Arial" ); strcpy( szPath, Args->Get_argv(0)); _splitpath( szPath, drive, dir, NULL, NULL ); _makepath( szPath, drive, dir, "Setup\\Setup", ".ini" ); GetPrivateProfileString( "Fonts", "Font", "Arial.tff", szFile, MAX_PATH, szPath ); GetPrivateProfileString( "Fonts", "Fontname", "Arial", szFacename, MAX_PATH, szPath ); //--------------------------------------------------------------------- // Use codepage set by Locomoto class. //--------------------------------------------------------------------- UINT codepage = CodePage; // GetACP(); GetClientRect( GetDesktopWindow(), &rect ); if( rect.right <= 640 ) { b640X480 = TRUE; } Msg( __LINE__, __FILE__, "FontManagerClass -- szFile = %s, szFilename = %s.", szFile, szFacename ); //--------------------------------------------------------------------- // Create the True Type Fonts. // // Value Weight // ____________________________ // FW_DONTCARE 0 // FW_THIN 100 // FW_EXTRALIGHT 200 // FW_ULTRALIGHT 200 // FW_LIGHT 300 // FW_NORMAL 400 // FW_REGULAR 400 // FW_MEDIUM 500 // FW_SEMIBOLD 600 // FW_DEMIBOLD 600 // FW_BOLD 700 // FW_EXTRABOLD 800 // FW_ULTRABOLD 800 // FW_HEAVY 900 // FW_BLACK 900 //--------------------------------------------------------------------- switch( LanguageID ) { // [OYO] Add this line if you wish to support another languages //================================================================= // JAPANESE //================================================================= case LANG_JAP: // [OYO] Use MS PGothic for Japanese Win9x if( codepage == 932 ) { strcpy( szFile, "MSGothic.ttc" ); strcpy( szFacename, "MS PGothic" ); TTButtonFontPtr = new TTFontClass( hdc, szFile, szFacename, 20, FW_NORMAL, SHIFTJIS_CHARSET ); TTButtonFontPtrSmall= new TTFontClass( hdc, szFile, szFacename, 12, FW_NORMAL, SHIFTJIS_CHARSET ); TTTextFontPtr = new TTFontClass( hdc, szFile, szFacename, 16, FW_MEDIUM, SHIFTJIS_CHARSET ); TTTextFontPtr640 = new TTFontClass( hdc, szFile, szFacename, 14, FW_MEDIUM, SHIFTJIS_CHARSET ); TTTextFontPtr800 = new TTFontClass( hdc, szFile, szFacename, 14, FW_MEDIUM, SHIFTJIS_CHARSET ); TTLicenseFontPtr = new TTFontClass( hdc, szFile, szFacename, 12, FW_NORMAL, SHIFTJIS_CHARSET ); } break; //================================================================= // KOREAN //================================================================= case LANG_KOR: // [OYO] Use GulimChe for Korean Win9x if ( codepage == 949 ) { strcpy( szFile, "Gulim.tff" ); strcpy( szFacename, "Gulim" ); TTButtonFontPtr = new TTFontClass( hdc, szFile, szFacename, 20, FW_NORMAL, HANGEUL_CHARSET ); TTButtonFontPtrSmall= new TTFontClass( hdc, szFile, szFacename, 20, FW_NORMAL, HANGEUL_CHARSET ); TTTextFontPtr = new TTFontClass( hdc, szFile, szFacename, 16, FW_MEDIUM, HANGEUL_CHARSET ); TTTextFontPtr640 = new TTFontClass( hdc, szFile, szFacename, 14, FW_MEDIUM, HANGEUL_CHARSET ); TTTextFontPtr800 = new TTFontClass( hdc, szFile, szFacename, 14, FW_MEDIUM, HANGEUL_CHARSET ); TTLicenseFontPtr = new TTFontClass( hdc, szFile, szFacename, 12, FW_NORMAL, HANGEUL_CHARSET ); } break; //================================================================= // CHINESE //================================================================= case LANG_CHI: if ( codepage == 950 ) { strcpy( szFile, "mingliu.ttc" ); strcpy( szFacename, "mingliu" ); TTButtonFontPtr = new TTFontClass( hdc, szFile, szFacename, 20, FW_NORMAL, CHINESEBIG5_CHARSET ); TTButtonFontPtrSmall= new TTFontClass( hdc, szFile, szFacename, 14, FW_NORMAL, CHINESEBIG5_CHARSET ); TTTextFontPtr = new TTFontClass( hdc, szFile, szFacename, 16, FW_MEDIUM, CHINESEBIG5_CHARSET ); TTTextFontPtr640 = new TTFontClass( hdc, szFile, szFacename, 14, FW_MEDIUM, CHINESEBIG5_CHARSET ); TTTextFontPtr800 = new TTFontClass( hdc, szFile, szFacename, 14, FW_MEDIUM, CHINESEBIG5_CHARSET ); TTLicenseFontPtr = new TTFontClass( hdc, szFile, szFacename, 12, FW_NORMAL, CHINESEBIG5_CHARSET ); } break; //================================================================= // ENGLISH, FRENCH, GERMAN //================================================================= case LANG_GER: case LANG_FRE: case LANG_USA: default: TTButtonFontPtr = new TTFontClass( hdc, szFile, szFacename, 22, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); if( LANG_FRE == LanguageID ) { TTButtonFontPtrSmall= new TTFontClass( hdc, szFile, szFacename, 20, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } else { TTButtonFontPtrSmall= new TTFontClass( hdc, szFile, szFacename, 22, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } TTTextFontPtr = new TTFontClass( hdc, szFile, szFacename, 16, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); TTTextFontPtr640 = new TTFontClass( hdc, szFile, szFacename, 14, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); TTTextFontPtr800 = new TTFontClass( hdc, szFile, szFacename, 14, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); TTLicenseFontPtr = new TTFontClass( hdc, szFile, szFacename, 12, FW_MEDIUM, ANSI_CHARSET, 0, 0, 0, FALSE ); break; } //---------------------------------------------------------------------- // If we fell through... //---------------------------------------------------------------------- if( TTButtonFontPtr == NULL || TTTextFontPtr == NULL ) { strcpy( szFile, "Arial.tff" ); strcpy( szFacename, "Arial" ); if( TTButtonFontPtr == NULL ) { TTButtonFontPtr = new TTFontClass( hdc, szFile, szFacename, 22, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } if( TTButtonFontPtrSmall == NULL ) { TTButtonFontPtrSmall= new TTFontClass( hdc, szFile, szFacename, 22, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } if( TTTextFontPtr == NULL ) { TTTextFontPtr = new TTFontClass( hdc, szFile, szFacename, 16, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } if( TTTextFontPtr640 == NULL ) { TTTextFontPtr640 = new TTFontClass( hdc, szFile, szFacename, 14, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } if( TTTextFontPtr800 == NULL ) { TTTextFontPtr800 = new TTFontClass( hdc, szFile, szFacename, 14, FW_SEMIBOLD, ANSI_CHARSET, 0, 0, 0, FALSE ); } if( TTLicenseFontPtr == NULL ) { TTLicenseFontPtr = new TTFontClass( hdc, szFile, szFacename, 12, FW_MEDIUM, ANSI_CHARSET, 0, 0, 0, FALSE ); } } } assert( TTTextFontPtr != NULL ); assert( TTTextFontPtr640 != NULL ); assert( TTTextFontPtr800 != NULL ); assert( TTButtonFontPtr != NULL ); assert( TTButtonFontPtrSmall != NULL ); assert( TTLicenseFontPtr != NULL ); } /*********************************************************************************************** * FontManagerClass::~FontManagerClass -- Destructor for FontManager class. * * * * INPUT: none. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 03/26/1998 MML : Created. * *=============================================================================================*/ FontManagerClass::~FontManagerClass ( void ) { if ( TTButtonFontPtr != NULL ) { delete TTButtonFontPtr; TTButtonFontPtr = NULL; } if ( TTTextFontPtr != NULL ) { delete TTTextFontPtr; TTTextFontPtr = NULL; } } /*********************************************************************************************** * Font_From_TPF -- Convert flags into a font pointer. * * * * This routine will examine the specified flags and return with a pointer to the font * * that the flags represent. * * * * INPUT: flags -- The flags to convert into a font pointer. * * * * OUTPUT: Returns with a font pointer that matches the flags. * * * * WARNINGS: If no match could be found, a default font pointer is returned. * * * * HISTORY: * * 05/26/1997 JLB : Created. * *=============================================================================================*/ TTFontClass * Font_From_TPF ( TextPrintType flags ) { TTFontClass *fontptr= NULL; switch (flags & 0x000F) { case TPF_BUTTON_FONT: fontptr = TTButtonFontPtr; break; case TPF_TEXT_FONT: fontptr = TTTextFontPtr; break; default: fontptr = TTTextFontPtr; break; } return( fontptr ); } /************************************************************************************************ * Is_True_Type_Font -- Convert flags into a font pointer. * * * * This routine will examine the specified flags and return with a pointer to the font * * that the flags represent. * * * * INPUT: flags -- The flags to convert into a font pointer. * * * * OUTPUT: Returns with a font pointer that matches the flags. * * * * WARNINGS: If no match could be found, a default font pointer is returned. * * * * HISTORY: * * 05/26/1997 JLB : Created. * *==============================================================================================*/ bool Is_True_Type_Font( TextPrintType flags ) { if (( flags == TPF_BUTTON_FONT ) || ( flags == TPF_TEXT_FONT )) { return TRUE; } else { return FALSE; } }