SWF_Load.cpp (16595B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 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. 23 24 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. 25 26 =========================================================================== 27 */ 28 #pragma hdrstop 29 #include "../idlib/precompiled.h" 30 #include "../renderer/Font.h" 31 32 #pragma warning(disable: 4355) // 'this' : used in base member initializer list 33 34 #define BSWF_VERSION 16 // bumped to 16 for storing atlas image dimensions for unbuffered loads 35 #define BSWF_MAGIC ( ( 'B' << 24 ) | ( 'S' << 16 ) | ( 'W' << 8 ) | BSWF_VERSION ) 36 37 /* 38 =================== 39 idSWF::LoadSWF 40 =================== 41 */ 42 bool idSWF::LoadSWF( const char * fullpath ) { 43 44 idFile * rawfile = fileSystem->OpenFileRead( fullpath ); 45 if ( rawfile == NULL ) { 46 idLib::Printf( "SWF File not found %s\n", fullpath ); 47 return false; 48 } 49 50 swfHeader_t header; 51 rawfile->Read( &header, sizeof( header ) ); 52 53 if ( header.W != 'W' || header.S != 'S' ) { 54 idLib::Warning( "Wrong signature bytes" ); 55 delete rawfile; 56 return false; 57 } 58 59 if ( header.version > 9 ) { 60 idLib::Warning( "Unsupported version %d", header.version ); 61 delete rawfile; 62 return false; 63 } 64 65 bool compressed; 66 if ( header.compression == 'F' ) { 67 compressed = false; 68 } else if ( header.compression == 'C' ) { 69 compressed = true; 70 } else { 71 idLib::Warning( "Unsupported compression type %c", header.compression ); 72 delete rawfile; 73 return false; 74 } 75 idSwap::Little( header.fileLength ); 76 77 // header.fileLength somewhat annoyingly includes the size of the header 78 uint32 fileLength2 = header.fileLength - (uint32)sizeof( swfHeader_t ); 79 80 // slurp the raw file into a giant array, which is somewhat atrocious when loading from the preload since it's already an idFile_Memory 81 byte * fileData = (byte *)Mem_Alloc( fileLength2, TAG_SWF ); 82 size_t fileSize = rawfile->Read( fileData, fileLength2 ); 83 delete rawfile; 84 85 if ( compressed ) { 86 byte * uncompressed = (byte *)Mem_Alloc( fileLength2, TAG_SWF ); 87 if ( !Inflate( fileData, (int)fileSize, uncompressed, fileLength2 ) ) { 88 idLib::Warning( "Inflate error" ); 89 Mem_Free( uncompressed ); 90 return false; 91 } 92 Mem_Free( fileData ); 93 fileData = uncompressed; 94 } 95 idSWFBitStream bitstream( fileData, fileLength2, false ); 96 97 swfRect_t frameSize; 98 bitstream.ReadRect( frameSize ); 99 100 if ( !frameSize.tl.Compare( vec2_zero ) ) { 101 idLib::Warning( "Invalid frameSize top left" ); 102 Mem_Free( fileData ); 103 return false; 104 } 105 106 frameWidth = frameSize.br.x; 107 frameHeight = frameSize.br.y; 108 frameRate = bitstream.ReadU16(); 109 110 // parse everything 111 mainsprite->Load( bitstream, true ); 112 113 // now that all images have been loaded, write out the combined image 114 idStr atlasFileName = "generated/"; 115 atlasFileName += fullpath; 116 atlasFileName.SetFileExtension( ".tga" ); 117 118 WriteSwfImageAtlas( atlasFileName ); 119 120 Mem_Free( fileData ); 121 122 return true; 123 } 124 125 /* 126 =================== 127 idSWF::LoadBinary 128 =================== 129 */ 130 bool idSWF::LoadBinary( const char * bfilename, ID_TIME_T sourceTime ) { 131 idFile * f = fileSystem->OpenFileReadMemory( bfilename ); 132 if ( f == NULL || f->Length() <= 0 ) { 133 return false; 134 } 135 136 uint32 magic = 0; 137 ID_TIME_T btimestamp = 0; 138 f->ReadBig( magic ); 139 f->ReadBig( btimestamp ); 140 141 if ( magic != BSWF_MAGIC || ( !fileSystem->InProductionMode() && sourceTime != btimestamp ) ) { 142 delete f; 143 return false; 144 } 145 146 f->ReadBig( frameWidth ); 147 f->ReadBig( frameHeight ); 148 f->ReadBig( frameRate ); 149 150 if ( mouseX == -1 ) { 151 mouseX = ( frameWidth / 2 ); 152 } 153 154 if ( mouseY == -1 ) { 155 mouseY = ( frameHeight / 2 ); 156 } 157 158 mainsprite->Read( f ); 159 160 int num = 0; 161 f->ReadBig( num ); 162 dictionary.SetNum( num ); 163 for ( int i = 0; i < dictionary.Num(); i++ ) { 164 f->ReadBig( dictionary[i].type ); 165 switch ( dictionary[i].type ) { 166 case SWF_DICT_IMAGE: { 167 idStr imageName; 168 f->ReadString( imageName ); 169 if ( imageName[0] == '.' ) { 170 // internal image in the atlas 171 dictionary[i].material = NULL; 172 } else { 173 dictionary[i].material = declManager->FindMaterial( imageName ); 174 } 175 for ( int j = 0 ; j < 2 ; j++ ) { 176 f->ReadBig( dictionary[i].imageSize[j] ); 177 f->ReadBig( dictionary[i].imageAtlasOffset[j] ); 178 } 179 for ( int j = 0 ; j < 4 ; j++ ) { 180 f->ReadBig( dictionary[i].channelScale[j] ); 181 } 182 break; 183 } 184 case SWF_DICT_MORPH: 185 case SWF_DICT_SHAPE: { 186 dictionary[i].shape = new (TAG_SWF) idSWFShape; 187 idSWFShape * shape = dictionary[i].shape; 188 f->ReadBig( shape->startBounds.tl ); 189 f->ReadBig( shape->startBounds.br ); 190 f->ReadBig( shape->endBounds.tl ); 191 f->ReadBig( shape->endBounds.br ); 192 f->ReadBig( num ); shape->fillDraws.SetNum( num ); 193 for ( int d = 0; d < shape->fillDraws.Num(); d++ ) { 194 idSWFShapeDrawFill & fillDraw = shape->fillDraws[d]; 195 f->ReadBig( fillDraw.style.type ); 196 f->ReadBig( fillDraw.style.subType ); 197 f->Read( &fillDraw.style.startColor, 4 ); 198 f->Read( &fillDraw.style.endColor, 4 ); 199 f->ReadBigArray( (float *)&fillDraw.style.startMatrix, 6 ); 200 f->ReadBigArray( (float *)&fillDraw.style.endMatrix, 6 ); 201 f->ReadBig( fillDraw.style.gradient.numGradients ); 202 for ( int g = 0; g < fillDraw.style.gradient.numGradients; g++ ) { 203 f->ReadBig( fillDraw.style.gradient.gradientRecords[g].startRatio ); 204 f->ReadBig( fillDraw.style.gradient.gradientRecords[g].endRatio ); 205 f->Read( &fillDraw.style.gradient.gradientRecords[g].startColor, 4 ); 206 f->Read( &fillDraw.style.gradient.gradientRecords[g].endColor, 4 ); 207 } 208 f->ReadBig( fillDraw.style.focalPoint ); 209 f->ReadBig( fillDraw.style.bitmapID ); 210 f->ReadBig( num ); fillDraw.startVerts.SetNum( num ); 211 f->ReadBigArray( fillDraw.startVerts.Ptr(), fillDraw.startVerts.Num() ); 212 f->ReadBig( num ); fillDraw.endVerts.SetNum( num ); 213 f->ReadBigArray( fillDraw.endVerts.Ptr(), fillDraw.endVerts.Num() ); 214 f->ReadBig( num ); fillDraw.indices.SetNum( num ); 215 f->ReadBigArray( fillDraw.indices.Ptr(), fillDraw.indices.Num() ); 216 } 217 f->ReadBig( num ); shape->lineDraws.SetNum( num ); 218 for ( int d = 0; d < shape->lineDraws.Num(); d++ ) { 219 idSWFShapeDrawLine & lineDraw = shape->lineDraws[d]; 220 f->ReadBig( lineDraw.style.startWidth ); 221 f->ReadBig( lineDraw.style.endWidth ); 222 f->Read( &lineDraw.style.startColor, 4 ); 223 f->Read( &lineDraw.style.endColor, 4 ); 224 f->ReadBig( num ); lineDraw.startVerts.SetNum( num ); 225 f->ReadBigArray( lineDraw.startVerts.Ptr(), lineDraw.startVerts.Num() ); 226 f->ReadBig( num ); lineDraw.endVerts.SetNum( num ); 227 f->ReadBigArray( lineDraw.endVerts.Ptr(), lineDraw.endVerts.Num() ); 228 f->ReadBig( num ); lineDraw.indices.SetNum( num ); 229 f->ReadBigArray( lineDraw.indices.Ptr(), lineDraw.indices.Num() ); 230 } 231 break; 232 } 233 case SWF_DICT_SPRITE: { 234 dictionary[i].sprite = new (TAG_SWF) idSWFSprite( this ); 235 dictionary[i].sprite->Read( f ); 236 break; 237 } 238 case SWF_DICT_FONT: { 239 dictionary[i].font = new (TAG_SWF) idSWFFont; 240 idSWFFont * font = dictionary[i].font; 241 idStr fontName; 242 f->ReadString( fontName ); 243 font->fontID = renderSystem->RegisterFont( fontName ); 244 f->ReadBig( font->ascent ); 245 f->ReadBig( font->descent ); 246 f->ReadBig( font->leading ); 247 f->ReadBig( num ); font->glyphs.SetNum( num ); 248 for ( int g = 0; g < font->glyphs.Num(); g++ ) { 249 f->ReadBig( font->glyphs[g].code ); 250 f->ReadBig( font->glyphs[g].advance ); 251 f->ReadBig( num ); font->glyphs[g].verts.SetNum( num ); 252 f->ReadBigArray( font->glyphs[g].verts.Ptr(), font->glyphs[g].verts.Num() ); 253 f->ReadBig( num ); font->glyphs[g].indices.SetNum( num ); 254 f->ReadBigArray( font->glyphs[g].indices.Ptr(), font->glyphs[g].indices.Num() ); 255 } 256 break; 257 } 258 case SWF_DICT_TEXT: { 259 dictionary[i].text = new (TAG_SWF) idSWFText; 260 idSWFText * text = dictionary[i].text; 261 f->ReadBig( text->bounds.tl ); 262 f->ReadBig( text->bounds.br ); 263 f->ReadBigArray( (float *)&text->matrix, 6 ); 264 f->ReadBig( num ); text->textRecords.SetNum( num ); 265 for ( int t = 0; t < text->textRecords.Num(); t++ ) { 266 idSWFTextRecord & textRecord = text->textRecords[t]; 267 f->ReadBig( textRecord.fontID ); 268 f->Read( &textRecord.color, 4 ); 269 f->ReadBig( textRecord.xOffset ); 270 f->ReadBig( textRecord.yOffset ); 271 f->ReadBig( textRecord.textHeight ); 272 f->ReadBig( textRecord.firstGlyph ); 273 f->ReadBig( textRecord.numGlyphs ); 274 } 275 f->ReadBig( num ); text->glyphs.SetNum( num ); 276 for ( int g = 0; g < text->glyphs.Num(); g++ ) { 277 f->ReadBig( text->glyphs[g].index ); 278 f->ReadBig( text->glyphs[g].advance ); 279 } 280 break; 281 } 282 case SWF_DICT_EDITTEXT: { 283 dictionary[i].edittext = new (TAG_SWF) idSWFEditText; 284 idSWFEditText * edittext = dictionary[i].edittext; 285 f->ReadBig( edittext->bounds.tl ); 286 f->ReadBig( edittext->bounds.br ); 287 f->ReadBig( edittext->flags ); 288 f->ReadBig( edittext->fontID ); 289 f->ReadBig( edittext->fontHeight ); 290 f->Read( &edittext->color, 4 ); 291 f->ReadBig( edittext->maxLength ); 292 f->ReadBig( edittext->align ); 293 f->ReadBig( edittext->leftMargin ); 294 f->ReadBig( edittext->rightMargin ); 295 f->ReadBig( edittext->indent ); 296 f->ReadBig( edittext->leading ); 297 f->ReadString( edittext->variable ); 298 f->ReadString( edittext->initialText ); 299 break; 300 } 301 } 302 } 303 delete f; 304 305 return true; 306 } 307 308 /* 309 =================== 310 idSWF::WriteBinary 311 =================== 312 */ 313 void idSWF::WriteBinary( const char * bfilename ) { 314 idFileLocal file( fileSystem->OpenFileWrite( bfilename, "fs_basepath" ) ); 315 if ( file == NULL ) { 316 return; 317 } 318 file->WriteBig( BSWF_MAGIC ); 319 file->WriteBig( timestamp ); 320 321 file->WriteBig( frameWidth ); 322 file->WriteBig( frameHeight ); 323 file->WriteBig( frameRate ); 324 325 mainsprite->Write( file ); 326 327 file->WriteBig( dictionary.Num() ); 328 for ( int i = 0; i < dictionary.Num(); i++ ) { 329 file->WriteBig( dictionary[i].type ); 330 switch ( dictionary[i].type ) { 331 case SWF_DICT_IMAGE: { 332 if ( dictionary[i].material ) { 333 file->WriteString( dictionary[i].material->GetName() ); 334 } else { 335 file->WriteString( "." ); 336 } 337 for ( int j = 0 ; j < 2 ; j++ ) { 338 file->WriteBig( dictionary[i].imageSize[j] ); 339 file->WriteBig( dictionary[i].imageAtlasOffset[j] ); 340 } 341 for ( int j = 0 ; j < 4 ; j++ ) { 342 file->WriteBig( dictionary[i].channelScale[j] ); 343 } 344 break; 345 } 346 case SWF_DICT_MORPH: 347 case SWF_DICT_SHAPE: { 348 idSWFShape * shape = dictionary[i].shape; 349 file->WriteBig( shape->startBounds.tl ); 350 file->WriteBig( shape->startBounds.br ); 351 file->WriteBig( shape->endBounds.tl ); 352 file->WriteBig( shape->endBounds.br ); 353 file->WriteBig( shape->fillDraws.Num() ); 354 for ( int d = 0; d < shape->fillDraws.Num(); d++ ) { 355 idSWFShapeDrawFill & fillDraw = shape->fillDraws[d]; 356 file->WriteBig( fillDraw.style.type ); 357 file->WriteBig( fillDraw.style.subType ); 358 file->Write( &fillDraw.style.startColor, 4 ); 359 file->Write( &fillDraw.style.endColor, 4 ); 360 file->WriteBigArray( (float *)&fillDraw.style.startMatrix, 6 ); 361 file->WriteBigArray( (float *)&fillDraw.style.endMatrix, 6 ); 362 file->WriteBig( fillDraw.style.gradient.numGradients ); 363 for ( int g = 0; g < fillDraw.style.gradient.numGradients; g++ ) { 364 file->WriteBig( fillDraw.style.gradient.gradientRecords[g].startRatio ); 365 file->WriteBig( fillDraw.style.gradient.gradientRecords[g].endRatio ); 366 file->Write( &fillDraw.style.gradient.gradientRecords[g].startColor, 4 ); 367 file->Write( &fillDraw.style.gradient.gradientRecords[g].endColor, 4 ); 368 } 369 file->WriteBig( fillDraw.style.focalPoint ); 370 file->WriteBig( fillDraw.style.bitmapID ); 371 file->WriteBig( fillDraw.startVerts.Num() ); 372 file->WriteBigArray( fillDraw.startVerts.Ptr(), fillDraw.startVerts.Num() ); 373 file->WriteBig( fillDraw.endVerts.Num() ); 374 file->WriteBigArray( fillDraw.endVerts.Ptr(), fillDraw.endVerts.Num() ); 375 file->WriteBig( fillDraw.indices.Num() ); 376 file->WriteBigArray( fillDraw.indices.Ptr(), fillDraw.indices.Num() ); 377 } 378 file->WriteBig( shape->lineDraws.Num() ); 379 for ( int d = 0; d < shape->lineDraws.Num(); d++ ) { 380 idSWFShapeDrawLine & lineDraw = shape->lineDraws[d]; 381 file->WriteBig( lineDraw.style.startWidth ); 382 file->WriteBig( lineDraw.style.endWidth ); 383 file->Write( &lineDraw.style.startColor, 4 ); 384 file->Write( &lineDraw.style.endColor, 4 ); 385 file->WriteBig( lineDraw.startVerts.Num() ); 386 file->WriteBigArray( lineDraw.startVerts.Ptr(), lineDraw.startVerts.Num() ); 387 file->WriteBig( lineDraw.endVerts.Num() ); 388 file->WriteBigArray( lineDraw.endVerts.Ptr(), lineDraw.endVerts.Num() ); 389 file->WriteBig( lineDraw.indices.Num() ); 390 file->WriteBigArray( lineDraw.indices.Ptr(), lineDraw.indices.Num() ); 391 } 392 break; 393 } 394 case SWF_DICT_SPRITE: { 395 dictionary[i].sprite->Write( file ); 396 break; 397 } 398 case SWF_DICT_FONT: { 399 idSWFFont * font = dictionary[i].font; 400 file->WriteString( font->fontID->GetName() ); 401 file->WriteBig( font->ascent ); 402 file->WriteBig( font->descent ); 403 file->WriteBig( font->leading ); 404 file->WriteBig( font->glyphs.Num() ); 405 for ( int g = 0; g < font->glyphs.Num(); g++ ) { 406 file->WriteBig( font->glyphs[g].code ); 407 file->WriteBig( font->glyphs[g].advance ); 408 file->WriteBig( font->glyphs[g].verts.Num() ); 409 file->WriteBigArray( font->glyphs[g].verts.Ptr(), font->glyphs[g].verts.Num() ); 410 file->WriteBig( font->glyphs[g].indices.Num() ); 411 file->WriteBigArray( font->glyphs[g].indices.Ptr(), font->glyphs[g].indices.Num() ); 412 } 413 break; 414 } 415 case SWF_DICT_TEXT: { 416 idSWFText * text = dictionary[i].text; 417 file->WriteBig( text->bounds.tl ); 418 file->WriteBig( text->bounds.br ); 419 file->WriteBigArray( (float *)&text->matrix, 6 ); 420 file->WriteBig( text->textRecords.Num() ); 421 for ( int t = 0; t < text->textRecords.Num(); t++ ) { 422 idSWFTextRecord & textRecord = text->textRecords[t]; 423 file->WriteBig( textRecord.fontID ); 424 file->Write( &textRecord.color, 4 ); 425 file->WriteBig( textRecord.xOffset ); 426 file->WriteBig( textRecord.yOffset ); 427 file->WriteBig( textRecord.textHeight ); 428 file->WriteBig( textRecord.firstGlyph ); 429 file->WriteBig( textRecord.numGlyphs ); 430 } 431 file->WriteBig( text->glyphs.Num() ); 432 for ( int g = 0; g < text->glyphs.Num(); g++ ) { 433 file->WriteBig( text->glyphs[g].index ); 434 file->WriteBig( text->glyphs[g].advance ); 435 } 436 break; 437 } 438 case SWF_DICT_EDITTEXT: { 439 idSWFEditText * edittext = dictionary[i].edittext; 440 file->WriteBig( edittext->bounds.tl ); 441 file->WriteBig( edittext->bounds.br ); 442 file->WriteBig( edittext->flags ); 443 file->WriteBig( edittext->fontID ); 444 file->WriteBig( edittext->fontHeight ); 445 file->Write( &edittext->color, 4 ); 446 file->WriteBig( edittext->maxLength ); 447 file->WriteBig( edittext->align ); 448 file->WriteBig( edittext->leftMargin ); 449 file->WriteBig( edittext->rightMargin ); 450 file->WriteBig( edittext->indent ); 451 file->WriteBig( edittext->leading ); 452 file->WriteString( edittext->variable ); 453 file->WriteString( edittext->initialText ); 454 break; 455 } 456 } 457 } 458 }