| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /*
- ** Command & Conquer Generals(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 <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando / G 3D Library *
- * *
- * $Archive:: /Commando/Code/ww3d2/font3d.cpp $*
- * *
- * $Author:: Jani_p $*
- * *
- * $Modtime:: 4/11/01 10:17p $*
- * *
- * $Revision:: 16 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "font3d.h"
- #include "assetmgr.h"
- #include "texture.h"
- #include <assert.h>
- #include <wwdebug.h>
- #include "surfaceclass.h"
- #include "texture.h"
- #include "vector2i.h"
- static SurfaceClass *_surface;
- /***********************************************************************************************
- * *
- * Font3DDataClass::Font3DDataClass -- constructor *
- * *
- * Constructs and load a Targa font image to create a texture matetial *
- * *
- ***********************************************************************************************/
- Font3DDataClass::Font3DDataClass( const char *filename )
- {
- Texture = NULL;
- Load_Font_Image( filename);
- Name = strdup( filename);
- Name = strupr( Name);
- }
- /***********************************************************************************************
- * *
- * Font3DDataClass::~Font3DDataClass -- destructor *
- * *
- ***********************************************************************************************/
- Font3DDataClass::~Font3DDataClass(void)
- {
- if (Name != NULL) {
- free(Name);
- Name = NULL;
- }
- REF_PTR_RELEASE(Texture);
- }
- /***********************************************************************************************
- * *
- * FontClass::Minimize_Font_Image *
- * *
- * Rebuilds the give image to better pack characters and to insure a square power of two size *
- * Must be called AFTER Make_Proportional() so each chars minimal bounding box is known *
- * Will only create a new texture of size 128x128 or 256x256, dependent on original width *
- * *
- ***********************************************************************************************/
- SurfaceClass *Font3DDataClass::Minimize_Font_Image( SurfaceClass *surface )
- {
- SurfaceClass::SurfaceDescription sd;
- surface->Get_Description(sd);
- float current_width = sd.Width;
- float current_height = sd.Height;
- // determine new width make the size of the new image either 128x128 or 256x256,
- // dependent on the width of the original image
- int new_width;
- if (current_width < 256) {
- new_width = 128;
- } else {
- new_width = 256;
- }
- int new_height = new_width;
- // create a new 4 bit alpha image to build into
- // We dont support non-homogeneous copies just yet
- SurfaceClass *new_surface = NEW_REF(SurfaceClass,(new_width, new_height,WW3D_FORMAT_A4R4G4B4));
- //SurfaceClass *new_surface0 = NEW_REF(SurfaceClass,(new_width, new_height,sd.Format));
- // fill with transparent black
- new_surface->Clear();
- // indices for the location of each added char
- int new_x = 0;
- int new_y = 0;
- // for each character, copy minimum bounding area to (new_x, new_y) in the new image
- for (int char_index = 0; char_index < 256; char_index++) {
- // find the lop left coordinate and the height and width of the char's bounding box
- // (must convert the normalized uv tables to pixels and round off)
- int src_x = (int)(UOffsetTable[ char_index ] * current_width + 0.5);
- int src_y = (int)(VOffsetTable[ char_index ] * current_height + 0.5);
- int width = (int)(UWidthTable[ char_index ] * current_width + 0.5);
- int height = (int)(VHeight * current_height + 0.5);
- // if the character has any visible pixels at all...
- if (width != 0) {
- // if this charactger will not fit on the current line, goto the next line
- if (new_x + width > new_width) {
- new_x = 0;
- new_y += height;
- // if we have run out of lines, we have a problem
- // we assert because we have already modified tables for some of the chars
- if (new_y + height > new_height) {
- new_y -= height;
- WWDEBUG_SAY(( "Font doesn't fit texture 2 on char %c\n", char_index ));
- }
- }
- // blit from original image to new image
- new_surface->Copy(new_x, new_y,src_x,src_y,width,height,surface);
- }
- // update the U and V tables to show new character location
- UOffsetTable[ char_index ] = (float)(new_x) / (float)new_width;
- VOffsetTable[ char_index ] = (float)(new_y) / (float)new_width;
- // update width in terms of new normal image width
- UWidthTable[ char_index ] *= (float)current_width / (float)new_width;
- new_x += width;
- }
- // update height in terms of new normal image height
- VHeight *= (float)current_height / (float)new_height;
- // be sure the new image is SMALLER than the old image
- // assert ( (new_width * new_height) <= (current_width * current_height));
- // release the old surface and return the new one
- REF_PTR_RELEASE(surface);
- _surface = new_surface;
- return _surface;
- }
- /***********************************************************************************************
- * *
- * FontClass::Make_Proportional *
- * *
- * Modifys U and Width tables to convert a monospace font into a proportional font. Hieght *
- * remains the same. Performed by getting the current mono-space bounding box and bringing *
- * in the left and right edges to the first non-transparent ( != 0 ) pixel. Then the U and *
- * width tables are updated with the new values. The image itself is not modified unless... *
- * *
- * we complete by calling Minimize_Font_Image to shink the image & insure a power of 2 square *
- * *
- ***********************************************************************************************/
- SurfaceClass *Font3DDataClass::Make_Proportional( SurfaceClass *surface )
- {
- SurfaceClass::SurfaceDescription sd;
- surface->Get_Description(sd);
- float width = sd.Width;
- float height = sd.Height;
- // for each character in the font...
- for (int char_index = 0; char_index < 256; char_index++) {
- // find the current bounding box
- // (must convert the normalized uv tables to pixels and round off)
- int x0 = (int)(UOffsetTable[ char_index ] * width + 0.5);
- int y0 = (int)(VOffsetTable[ char_index ] * height + 0.5);
- int x1 = x0 + (int)(UWidthTable[ char_index ] * width + 0.5);
- int y1 = y0 + (int)(VHeight * height + 0.5);
- // find minimum bounding box by finding the minimum and maximum non-0 x pixel location
- Vector2i minb(x0,y0);
- Vector2i maxb(x1,y1);
- surface->FindBB(&minb,&maxb);
-
- // set the new edges
- x0 = minb.I;
- x1 = maxb.I+1;
- // if we didn't find ANY non-transparent pixels, the char has no width.
- if (x1 < x0) {
- x1 = x0;
- }
- // turn off all character after del
- if (char_index > 0x80) {
- x1 = x0;
- }
- // update the U and width tables
- UOffsetTable[ char_index ] = (float)x0 / width;
- UWidthTable[ char_index ] = (float)( x1 - x0 ) / width;
- CharWidthTable[ char_index ] = x1 - x0;
- }
- // now shink the image given the minimum char sizes
- // surface = Minimize_Font_Image( surface );
- Minimize_Font_Image( _surface );
- return NULL;
- }
- /***********************************************************************************************
- * *
- * Font3DDataClass::Load_Font_Image( SR_SCENE *scene, char *filename ) *
- * *
- * Loads a targa font image file, arranged as 16x16 characters, and builds u v tables to *
- * find each character. Converts the mono-space font into a proportional font, then uploads *
- * the image to the scene as a textur material. *
- * *
- ***********************************************************************************************/
- bool Font3DDataClass::Load_Font_Image( const char *filename )
- {
- // get the font surface
- SurfaceClass *surface = NEW_REF(SurfaceClass,(filename));
- WWASSERT(surface);
- SurfaceClass::SurfaceDescription sd;
- surface->Get_Description(sd);
- // If input is a font strike (strip) process it as such
- if ( sd.Width > 8 * sd.Height ) {
- // the height of the strike is the height of the characters
- VHeight = 1;
- CharHeight = sd.Height;
- int column = 0;
- int width = sd.Width;
-
- // for each char, find the uv start location and set the
- // mono-spaced width and height in normalized screen units
- for (int char_index = 0; char_index < 256; char_index++) {
- if ( char_index >= 0x7F ) {
- UOffsetTable[ char_index ] = 0;
- VOffsetTable[ char_index ] = 0;
- UWidthTable[ char_index ] = 0;
- CharWidthTable[ char_index ] = 0;
- } else {
- // find the first non-transparent column...
- while (( column < width ) && ( surface->Is_Transparent_Column(column) )) column++;
- int start = column;
- // find the first transparent column...
- while (( column < width ) && ( !surface->Is_Transparent_Column(column) )) column++;
- int end = column;
-
- if ( end <= start ) {
- WWDEBUG_SAY(( "Error Char %d start %d end %d width %d\n", char_index, start, end, width ));
- }
- // WWASSERT( end > start );
- UOffsetTable[ char_index ] = (float)start / width;
- VOffsetTable[ char_index ] = 0;
- UWidthTable[ char_index ] = (float)(end - start) / width;
- CharWidthTable[ char_index ] = end - start;
- }
- }
- // convert the just created mon-spaced font to proportional (optional)
- // surface = Make_Proportional( surface );
- _surface = surface;
- surface = NULL;
- Minimize_Font_Image( _surface );
- } else {
- // Determine the width and height of each mono spaced character in pixels
- // (assumes 16x16 array of chars)
- float font_width = sd.Width;
- float font_height = sd.Height;
- float mono_pixel_width = (font_width / 16);
- float mono_pixel_height = (font_height / 16);
- // for each char, find the uv start location and set the
- // mono-spaced width and height in normalized screen units
- for (int char_index = 0; char_index < 256; char_index++) {
- UOffsetTable[ char_index ] = (float)((char_index % 16) * mono_pixel_width) / font_width;
- VOffsetTable[ char_index ] = (float)((char_index / 16) * mono_pixel_height) / font_height;
- UWidthTable[ char_index ] = mono_pixel_width / font_width;
- CharWidthTable[ char_index ] = mono_pixel_width;
- }
- VHeight = mono_pixel_height / font_height;
- CharHeight = mono_pixel_height;
- // convert the just created mon-spaced font to proportional (optional)
- _surface = surface;
- surface = NULL;
- Make_Proportional( _surface );
- }
- // create the texture
- if ( _surface ) {
- Texture = NEW_REF(TextureClass,(_surface,TextureClass::MIP_LEVELS_1));
- REF_PTR_RELEASE(_surface);
- }
- // return SUCCESS!
- return true;
- }
- /***********************************************************************************************
- * *
- * Font3DInstanceClass::Font3DInstanceClass -- constructor *
- * *
- * Constructs and load a Targa font image to create a texture matetial *
- * *
- ***********************************************************************************************/
- Font3DInstanceClass::Font3DInstanceClass( const char *filename )
- {
- FontData = WW3DAssetManager::Get_Instance()->Get_Font3DData( filename);
- MonoSpacing = 0.0f;
- Scale = 1.0f;
- SpaceSpacing = (int)(FontData->Char_Width('H') / 2.0f);
- InterCharSpacing = 1;
- Build_Cached_Tables();
- }
- /***********************************************************************************************
- * *
- * Font3DInstanceClass::~Font3DInstanceClass -- destructor *
- * *
- ***********************************************************************************************/
- Font3DInstanceClass::~Font3DInstanceClass(void)
- {
- REF_PTR_RELEASE(FontData);
- }
- /*
- **
- */
- void Font3DInstanceClass::Set_Mono_Spaced( void )
- {
- MonoSpacing = FontData->Char_Width('W') + 1;
- Build_Cached_Tables();
- }
- void Font3DInstanceClass::Build_Cached_Tables()
- {
- // Rebuild the cached tables
- for (int a=0;a<256;++a) {
- float width = (float)FontData->Char_Width(a);
- if ( a == ' ' ) {
- width = SpaceSpacing;
- }
- ScaledWidthTable[a] = Scale * width;
- if (MonoSpacing != 0.0f) {
- ScaledSpacingTable[a] = Scale * MonoSpacing;
- } else {
- ScaledSpacingTable[a] = Scale * (width + InterCharSpacing);
- }
- }
- ScaledHeight = floorf(Scale * (float)FontData->Char_Height('A'));
- }
- /***********************************************************************************************
- * *
- * Font3DInstanceClass::String_Screen_Width( char *test_str ) *
- * *
- * Finds the normalized screenspace width of a character string - useful for checking before *
- * printing to avoid overflowing the screen. * *
- ***********************************************************************************************/
- float Font3DInstanceClass::String_Width( const WCHAR *test_str )
- {
- float width = 0.0;
- for (; *test_str; test_str++) {
- width += Char_Spacing(*test_str);
- }
- return width;
- }
- float Font3DInstanceClass::String_Width( const char *test_str )
- {
- float width = 0.0;
- for (; *test_str; test_str++) {
- width += Char_Spacing(*test_str);
- }
- return width;
- }
|