123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code 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.
- Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "../renderer/Font.h"
- #pragma warning(disable: 4355) // 'this' : used in base member initializer list
- #define BSWF_VERSION 16 // bumped to 16 for storing atlas image dimensions for unbuffered loads
- #define BSWF_MAGIC ( ( 'B' << 24 ) | ( 'S' << 16 ) | ( 'W' << 8 ) | BSWF_VERSION )
- /*
- ===================
- idSWF::LoadSWF
- ===================
- */
- bool idSWF::LoadSWF( const char * fullpath ) {
- idFile * rawfile = fileSystem->OpenFileRead( fullpath );
- if ( rawfile == NULL ) {
- idLib::Printf( "SWF File not found %s\n", fullpath );
- return false;
- }
- swfHeader_t header;
- rawfile->Read( &header, sizeof( header ) );
- if ( header.W != 'W' || header.S != 'S' ) {
- idLib::Warning( "Wrong signature bytes" );
- delete rawfile;
- return false;
- }
- if ( header.version > 9 ) {
- idLib::Warning( "Unsupported version %d", header.version );
- delete rawfile;
- return false;
- }
- bool compressed;
- if ( header.compression == 'F' ) {
- compressed = false;
- } else if ( header.compression == 'C' ) {
- compressed = true;
- } else {
- idLib::Warning( "Unsupported compression type %c", header.compression );
- delete rawfile;
- return false;
- }
- idSwap::Little( header.fileLength );
- // header.fileLength somewhat annoyingly includes the size of the header
- uint32 fileLength2 = header.fileLength - (uint32)sizeof( swfHeader_t );
- // slurp the raw file into a giant array, which is somewhat atrocious when loading from the preload since it's already an idFile_Memory
- byte * fileData = (byte *)Mem_Alloc( fileLength2, TAG_SWF );
- size_t fileSize = rawfile->Read( fileData, fileLength2 );
- delete rawfile;
- if ( compressed ) {
- byte * uncompressed = (byte *)Mem_Alloc( fileLength2, TAG_SWF );
- if ( !Inflate( fileData, (int)fileSize, uncompressed, fileLength2 ) ) {
- idLib::Warning( "Inflate error" );
- Mem_Free( uncompressed );
- return false;
- }
- Mem_Free( fileData );
- fileData = uncompressed;
- }
- idSWFBitStream bitstream( fileData, fileLength2, false );
- swfRect_t frameSize;
- bitstream.ReadRect( frameSize );
- if ( !frameSize.tl.Compare( vec2_zero ) ) {
- idLib::Warning( "Invalid frameSize top left" );
- Mem_Free( fileData );
- return false;
- }
- frameWidth = frameSize.br.x;
- frameHeight = frameSize.br.y;
- frameRate = bitstream.ReadU16();
- // parse everything
- mainsprite->Load( bitstream, true );
- // now that all images have been loaded, write out the combined image
- idStr atlasFileName = "generated/";
- atlasFileName += fullpath;
- atlasFileName.SetFileExtension( ".tga" );
- WriteSwfImageAtlas( atlasFileName );
- Mem_Free( fileData );
- return true;
- }
- /*
- ===================
- idSWF::LoadBinary
- ===================
- */
- bool idSWF::LoadBinary( const char * bfilename, ID_TIME_T sourceTime ) {
- idFile * f = fileSystem->OpenFileReadMemory( bfilename );
- if ( f == NULL || f->Length() <= 0 ) {
- return false;
- }
- uint32 magic = 0;
- ID_TIME_T btimestamp = 0;
- f->ReadBig( magic );
- f->ReadBig( btimestamp );
- if ( magic != BSWF_MAGIC || ( !fileSystem->InProductionMode() && sourceTime != btimestamp ) ) {
- delete f;
- return false;
- }
- f->ReadBig( frameWidth );
- f->ReadBig( frameHeight );
- f->ReadBig( frameRate );
- if ( mouseX == -1 ) {
- mouseX = ( frameWidth / 2 );
- }
- if ( mouseY == -1 ) {
- mouseY = ( frameHeight / 2 );
- }
- mainsprite->Read( f );
- int num = 0;
- f->ReadBig( num );
- dictionary.SetNum( num );
- for ( int i = 0; i < dictionary.Num(); i++ ) {
- f->ReadBig( dictionary[i].type );
- switch ( dictionary[i].type ) {
- case SWF_DICT_IMAGE: {
- idStr imageName;
- f->ReadString( imageName );
- if ( imageName[0] == '.' ) {
- // internal image in the atlas
- dictionary[i].material = NULL;
- } else {
- dictionary[i].material = declManager->FindMaterial( imageName );
- }
- for ( int j = 0 ; j < 2 ; j++ ) {
- f->ReadBig( dictionary[i].imageSize[j] );
- f->ReadBig( dictionary[i].imageAtlasOffset[j] );
- }
- for ( int j = 0 ; j < 4 ; j++ ) {
- f->ReadBig( dictionary[i].channelScale[j] );
- }
- break;
- }
- case SWF_DICT_MORPH:
- case SWF_DICT_SHAPE: {
- dictionary[i].shape = new (TAG_SWF) idSWFShape;
- idSWFShape * shape = dictionary[i].shape;
- f->ReadBig( shape->startBounds.tl );
- f->ReadBig( shape->startBounds.br );
- f->ReadBig( shape->endBounds.tl );
- f->ReadBig( shape->endBounds.br );
- f->ReadBig( num ); shape->fillDraws.SetNum( num );
- for ( int d = 0; d < shape->fillDraws.Num(); d++ ) {
- idSWFShapeDrawFill & fillDraw = shape->fillDraws[d];
- f->ReadBig( fillDraw.style.type );
- f->ReadBig( fillDraw.style.subType );
- f->Read( &fillDraw.style.startColor, 4 );
- f->Read( &fillDraw.style.endColor, 4 );
- f->ReadBigArray( (float *)&fillDraw.style.startMatrix, 6 );
- f->ReadBigArray( (float *)&fillDraw.style.endMatrix, 6 );
- f->ReadBig( fillDraw.style.gradient.numGradients );
- for ( int g = 0; g < fillDraw.style.gradient.numGradients; g++ ) {
- f->ReadBig( fillDraw.style.gradient.gradientRecords[g].startRatio );
- f->ReadBig( fillDraw.style.gradient.gradientRecords[g].endRatio );
- f->Read( &fillDraw.style.gradient.gradientRecords[g].startColor, 4 );
- f->Read( &fillDraw.style.gradient.gradientRecords[g].endColor, 4 );
- }
- f->ReadBig( fillDraw.style.focalPoint );
- f->ReadBig( fillDraw.style.bitmapID );
- f->ReadBig( num ); fillDraw.startVerts.SetNum( num );
- f->ReadBigArray( fillDraw.startVerts.Ptr(), fillDraw.startVerts.Num() );
- f->ReadBig( num ); fillDraw.endVerts.SetNum( num );
- f->ReadBigArray( fillDraw.endVerts.Ptr(), fillDraw.endVerts.Num() );
- f->ReadBig( num ); fillDraw.indices.SetNum( num );
- f->ReadBigArray( fillDraw.indices.Ptr(), fillDraw.indices.Num() );
- }
- f->ReadBig( num ); shape->lineDraws.SetNum( num );
- for ( int d = 0; d < shape->lineDraws.Num(); d++ ) {
- idSWFShapeDrawLine & lineDraw = shape->lineDraws[d];
- f->ReadBig( lineDraw.style.startWidth );
- f->ReadBig( lineDraw.style.endWidth );
- f->Read( &lineDraw.style.startColor, 4 );
- f->Read( &lineDraw.style.endColor, 4 );
- f->ReadBig( num ); lineDraw.startVerts.SetNum( num );
- f->ReadBigArray( lineDraw.startVerts.Ptr(), lineDraw.startVerts.Num() );
- f->ReadBig( num ); lineDraw.endVerts.SetNum( num );
- f->ReadBigArray( lineDraw.endVerts.Ptr(), lineDraw.endVerts.Num() );
- f->ReadBig( num ); lineDraw.indices.SetNum( num );
- f->ReadBigArray( lineDraw.indices.Ptr(), lineDraw.indices.Num() );
- }
- break;
- }
- case SWF_DICT_SPRITE: {
- dictionary[i].sprite = new (TAG_SWF) idSWFSprite( this );
- dictionary[i].sprite->Read( f );
- break;
- }
- case SWF_DICT_FONT: {
- dictionary[i].font = new (TAG_SWF) idSWFFont;
- idSWFFont * font = dictionary[i].font;
- idStr fontName;
- f->ReadString( fontName );
- font->fontID = renderSystem->RegisterFont( fontName );
- f->ReadBig( font->ascent );
- f->ReadBig( font->descent );
- f->ReadBig( font->leading );
- f->ReadBig( num ); font->glyphs.SetNum( num );
- for ( int g = 0; g < font->glyphs.Num(); g++ ) {
- f->ReadBig( font->glyphs[g].code );
- f->ReadBig( font->glyphs[g].advance );
- f->ReadBig( num ); font->glyphs[g].verts.SetNum( num );
- f->ReadBigArray( font->glyphs[g].verts.Ptr(), font->glyphs[g].verts.Num() );
- f->ReadBig( num ); font->glyphs[g].indices.SetNum( num );
- f->ReadBigArray( font->glyphs[g].indices.Ptr(), font->glyphs[g].indices.Num() );
- }
- break;
- }
- case SWF_DICT_TEXT: {
- dictionary[i].text = new (TAG_SWF) idSWFText;
- idSWFText * text = dictionary[i].text;
- f->ReadBig( text->bounds.tl );
- f->ReadBig( text->bounds.br );
- f->ReadBigArray( (float *)&text->matrix, 6 );
- f->ReadBig( num ); text->textRecords.SetNum( num );
- for ( int t = 0; t < text->textRecords.Num(); t++ ) {
- idSWFTextRecord & textRecord = text->textRecords[t];
- f->ReadBig( textRecord.fontID );
- f->Read( &textRecord.color, 4 );
- f->ReadBig( textRecord.xOffset );
- f->ReadBig( textRecord.yOffset );
- f->ReadBig( textRecord.textHeight );
- f->ReadBig( textRecord.firstGlyph );
- f->ReadBig( textRecord.numGlyphs );
- }
- f->ReadBig( num ); text->glyphs.SetNum( num );
- for ( int g = 0; g < text->glyphs.Num(); g++ ) {
- f->ReadBig( text->glyphs[g].index );
- f->ReadBig( text->glyphs[g].advance );
- }
- break;
- }
- case SWF_DICT_EDITTEXT: {
- dictionary[i].edittext = new (TAG_SWF) idSWFEditText;
- idSWFEditText * edittext = dictionary[i].edittext;
- f->ReadBig( edittext->bounds.tl );
- f->ReadBig( edittext->bounds.br );
- f->ReadBig( edittext->flags );
- f->ReadBig( edittext->fontID );
- f->ReadBig( edittext->fontHeight );
- f->Read( &edittext->color, 4 );
- f->ReadBig( edittext->maxLength );
- f->ReadBig( edittext->align );
- f->ReadBig( edittext->leftMargin );
- f->ReadBig( edittext->rightMargin );
- f->ReadBig( edittext->indent );
- f->ReadBig( edittext->leading );
- f->ReadString( edittext->variable );
- f->ReadString( edittext->initialText );
- break;
- }
- }
- }
- delete f;
- return true;
- }
- /*
- ===================
- idSWF::WriteBinary
- ===================
- */
- void idSWF::WriteBinary( const char * bfilename ) {
- idFileLocal file( fileSystem->OpenFileWrite( bfilename, "fs_basepath" ) );
- if ( file == NULL ) {
- return;
- }
- file->WriteBig( BSWF_MAGIC );
- file->WriteBig( timestamp );
- file->WriteBig( frameWidth );
- file->WriteBig( frameHeight );
- file->WriteBig( frameRate );
- mainsprite->Write( file );
- file->WriteBig( dictionary.Num() );
- for ( int i = 0; i < dictionary.Num(); i++ ) {
- file->WriteBig( dictionary[i].type );
- switch ( dictionary[i].type ) {
- case SWF_DICT_IMAGE: {
- if ( dictionary[i].material ) {
- file->WriteString( dictionary[i].material->GetName() );
- } else {
- file->WriteString( "." );
- }
- for ( int j = 0 ; j < 2 ; j++ ) {
- file->WriteBig( dictionary[i].imageSize[j] );
- file->WriteBig( dictionary[i].imageAtlasOffset[j] );
- }
- for ( int j = 0 ; j < 4 ; j++ ) {
- file->WriteBig( dictionary[i].channelScale[j] );
- }
- break;
- }
- case SWF_DICT_MORPH:
- case SWF_DICT_SHAPE: {
- idSWFShape * shape = dictionary[i].shape;
- file->WriteBig( shape->startBounds.tl );
- file->WriteBig( shape->startBounds.br );
- file->WriteBig( shape->endBounds.tl );
- file->WriteBig( shape->endBounds.br );
- file->WriteBig( shape->fillDraws.Num() );
- for ( int d = 0; d < shape->fillDraws.Num(); d++ ) {
- idSWFShapeDrawFill & fillDraw = shape->fillDraws[d];
- file->WriteBig( fillDraw.style.type );
- file->WriteBig( fillDraw.style.subType );
- file->Write( &fillDraw.style.startColor, 4 );
- file->Write( &fillDraw.style.endColor, 4 );
- file->WriteBigArray( (float *)&fillDraw.style.startMatrix, 6 );
- file->WriteBigArray( (float *)&fillDraw.style.endMatrix, 6 );
- file->WriteBig( fillDraw.style.gradient.numGradients );
- for ( int g = 0; g < fillDraw.style.gradient.numGradients; g++ ) {
- file->WriteBig( fillDraw.style.gradient.gradientRecords[g].startRatio );
- file->WriteBig( fillDraw.style.gradient.gradientRecords[g].endRatio );
- file->Write( &fillDraw.style.gradient.gradientRecords[g].startColor, 4 );
- file->Write( &fillDraw.style.gradient.gradientRecords[g].endColor, 4 );
- }
- file->WriteBig( fillDraw.style.focalPoint );
- file->WriteBig( fillDraw.style.bitmapID );
- file->WriteBig( fillDraw.startVerts.Num() );
- file->WriteBigArray( fillDraw.startVerts.Ptr(), fillDraw.startVerts.Num() );
- file->WriteBig( fillDraw.endVerts.Num() );
- file->WriteBigArray( fillDraw.endVerts.Ptr(), fillDraw.endVerts.Num() );
- file->WriteBig( fillDraw.indices.Num() );
- file->WriteBigArray( fillDraw.indices.Ptr(), fillDraw.indices.Num() );
- }
- file->WriteBig( shape->lineDraws.Num() );
- for ( int d = 0; d < shape->lineDraws.Num(); d++ ) {
- idSWFShapeDrawLine & lineDraw = shape->lineDraws[d];
- file->WriteBig( lineDraw.style.startWidth );
- file->WriteBig( lineDraw.style.endWidth );
- file->Write( &lineDraw.style.startColor, 4 );
- file->Write( &lineDraw.style.endColor, 4 );
- file->WriteBig( lineDraw.startVerts.Num() );
- file->WriteBigArray( lineDraw.startVerts.Ptr(), lineDraw.startVerts.Num() );
- file->WriteBig( lineDraw.endVerts.Num() );
- file->WriteBigArray( lineDraw.endVerts.Ptr(), lineDraw.endVerts.Num() );
- file->WriteBig( lineDraw.indices.Num() );
- file->WriteBigArray( lineDraw.indices.Ptr(), lineDraw.indices.Num() );
- }
- break;
- }
- case SWF_DICT_SPRITE: {
- dictionary[i].sprite->Write( file );
- break;
- }
- case SWF_DICT_FONT: {
- idSWFFont * font = dictionary[i].font;
- file->WriteString( font->fontID->GetName() );
- file->WriteBig( font->ascent );
- file->WriteBig( font->descent );
- file->WriteBig( font->leading );
- file->WriteBig( font->glyphs.Num() );
- for ( int g = 0; g < font->glyphs.Num(); g++ ) {
- file->WriteBig( font->glyphs[g].code );
- file->WriteBig( font->glyphs[g].advance );
- file->WriteBig( font->glyphs[g].verts.Num() );
- file->WriteBigArray( font->glyphs[g].verts.Ptr(), font->glyphs[g].verts.Num() );
- file->WriteBig( font->glyphs[g].indices.Num() );
- file->WriteBigArray( font->glyphs[g].indices.Ptr(), font->glyphs[g].indices.Num() );
- }
- break;
- }
- case SWF_DICT_TEXT: {
- idSWFText * text = dictionary[i].text;
- file->WriteBig( text->bounds.tl );
- file->WriteBig( text->bounds.br );
- file->WriteBigArray( (float *)&text->matrix, 6 );
- file->WriteBig( text->textRecords.Num() );
- for ( int t = 0; t < text->textRecords.Num(); t++ ) {
- idSWFTextRecord & textRecord = text->textRecords[t];
- file->WriteBig( textRecord.fontID );
- file->Write( &textRecord.color, 4 );
- file->WriteBig( textRecord.xOffset );
- file->WriteBig( textRecord.yOffset );
- file->WriteBig( textRecord.textHeight );
- file->WriteBig( textRecord.firstGlyph );
- file->WriteBig( textRecord.numGlyphs );
- }
- file->WriteBig( text->glyphs.Num() );
- for ( int g = 0; g < text->glyphs.Num(); g++ ) {
- file->WriteBig( text->glyphs[g].index );
- file->WriteBig( text->glyphs[g].advance );
- }
- break;
- }
- case SWF_DICT_EDITTEXT: {
- idSWFEditText * edittext = dictionary[i].edittext;
- file->WriteBig( edittext->bounds.tl );
- file->WriteBig( edittext->bounds.br );
- file->WriteBig( edittext->flags );
- file->WriteBig( edittext->fontID );
- file->WriteBig( edittext->fontHeight );
- file->Write( &edittext->color, 4 );
- file->WriteBig( edittext->maxLength );
- file->WriteBig( edittext->align );
- file->WriteBig( edittext->leftMargin );
- file->WriteBig( edittext->rightMargin );
- file->WriteBig( edittext->indent );
- file->WriteBig( edittext->leading );
- file->WriteString( edittext->variable );
- file->WriteString( edittext->initialText );
- break;
- }
- }
- }
- }
|