예제 #1
0
/*
========================
idSWF::DefineTextX
========================
*/
void idSWF::DefineTextX( idSWFBitStream & bitstream, bool rgba ) {
	uint16 characterID = bitstream.ReadU16();
	idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_TEXT );
	if ( entry == NULL ) {
		return;
	}
	idSWFText * text = entry->text;

	bitstream.ReadRect( text->bounds );
	bitstream.ReadMatrix( text->matrix );

	uint8 glyphBits = bitstream.ReadU8();
	uint8 advanceBits = bitstream.ReadU8();

	while ( true ) {
		uint8 flags = bitstream.ReadU8();
		if ( flags == 0 ) {
			break;
		}
		idSWFTextRecord & textRecord = text->textRecords.Alloc();

		if ( flags & BIT( 3 ) ) {
			textRecord.fontID = bitstream.ReadU16();
		}
		if ( flags & BIT( 2 ) ) {
			if ( rgba ) {
				bitstream.ReadColorRGBA( textRecord.color );
			} else {
				bitstream.ReadColorRGB( textRecord.color );
			}
		}
		if ( flags & BIT( 0 ) ) {
			textRecord.xOffset = bitstream.ReadS16();
		}
		if ( flags & BIT( 1 ) ) {
			textRecord.yOffset = bitstream.ReadS16();
		}
		if ( flags & BIT( 3 ) ) {
			textRecord.textHeight = bitstream.ReadU16();
		}
		textRecord.firstGlyph = text->glyphs.Num();
		textRecord.numGlyphs = bitstream.ReadU8();
		for ( int i = 0; i < textRecord.numGlyphs; i++ ) {
			swfGlyphEntry_t & glyph = text->glyphs.Alloc();
			glyph.index = bitstream.ReadU( glyphBits );
			glyph.advance = bitstream.ReadS( advanceBits );
		}
	};
}
예제 #2
0
/*
========================
idSWFSpriteInstance::PlaceObject2
========================
*/
void idSWFSpriteInstance::PlaceObject2( idSWFBitStream & bitstream ) {
	c_PlaceObject2++;

	uint64 flags = bitstream.ReadU8();
	int depth = bitstream.ReadU16();

	int characterID = -1;
	if ( ( flags & PlaceFlagHasCharacter ) != 0 ) {
		characterID = bitstream.ReadU16();
	}

	swfDisplayEntry_t * display = NULL;

	if ( ( flags & PlaceFlagMove ) != 0 ) {
		// modify an existing entry
		display = FindDisplayEntry( depth );
		if ( display == NULL ) {
			idLib::Warning( "PlaceObject2: trying to modify entry %d, which doesn't exist", depth );
			return;
		}
		if ( characterID >= 0 ) {
			// We are very picky about what kind of objects can change characters
			// Shapes can become other shapes, but sprites can never change
			if ( display->spriteInstance || display->textInstance ) {
				idLib::Warning( "PlaceObject2: Trying to change the character of a sprite after it's been created" );
				return;
			}
			idSWFDictionaryEntry * dictEntry = sprite->swf->FindDictionaryEntry( characterID );
			if ( dictEntry != NULL ) {
				if ( dictEntry->type == SWF_DICT_SPRITE || dictEntry->type == SWF_DICT_EDITTEXT ) {
					idLib::Warning( "PlaceObject2: Trying to change the character of a shape to a sprite" );
					return;
				}
			}
			display->characterID = characterID;
		}
	} else {
		if ( characterID < 0 ) {
			idLib::Warning( "PlaceObject2: Trying to create a new object without a character" );
			return;
		}
		// create a new entry
		display = AddDisplayEntry( depth, characterID );
		if ( display == NULL ) {
			idLib::Warning( "PlaceObject2: trying to create a new entry at %d, but an item already exists there", depth );
			return;
		}
	}
	if ( ( flags & PlaceFlagHasMatrix ) != 0 ) {
		bitstream.ReadMatrix( display->matrix );
	}
	if ( ( flags & PlaceFlagHasColorTransform ) != 0 ) {
		bitstream.ReadColorXFormRGBA( display->cxf );
	}
	if ( ( flags & PlaceFlagHasRatio ) != 0 ) {
		display->ratio = bitstream.ReadU16() * ( 1.0f / 65535.0f );
	}
	if ( ( flags & PlaceFlagHasName ) != 0 ) {
		idStr name = bitstream.ReadString();
		if ( display->spriteInstance ) {
			display->spriteInstance->name = name;
			scriptObject->Set( name, display->spriteInstance->GetScriptObject() );
		} else if ( display->textInstance ) {
			scriptObject->Set( name, display->textInstance->GetScriptObject() );
		}
	}
	if ( ( flags & PlaceFlagHasClipDepth ) != 0 ) {
		display->clipDepth = bitstream.ReadU16();
	}
	if ( ( flags & PlaceFlagHasClipActions ) != 0 ) {
		// FIXME: clip actions
	}
}
예제 #3
0
/*
========================
idSWFSpriteInstance::PlaceObject3
========================
*/
void idSWFSpriteInstance::PlaceObject3( idSWFBitStream & bitstream ) {
	c_PlaceObject3++;

	uint64 flags1 = bitstream.ReadU8();
	uint64 flags2 = bitstream.ReadU8();
	uint16 depth = bitstream.ReadU16();

	if ( ( flags2 & PlaceFlagHasClassName ) != 0 || ( ( ( flags2 & PlaceFlagHasImage ) != 0 ) && ( ( flags1 & PlaceFlagHasCharacter ) != 0 ) ) ) {
		bitstream.ReadString(); // ignored
	}

	int characterID = -1;
	if ( ( flags1 & PlaceFlagHasCharacter ) != 0 ) {
		characterID = bitstream.ReadU16();
	}

	swfDisplayEntry_t * display = NULL;

	if ( ( flags1 & PlaceFlagMove ) != 0 ) {
		// modify an existing entry
		display = FindDisplayEntry( depth );
		if ( display == NULL ) {
			idLib::Warning( "PlaceObject3: trying to modify entry %d, which doesn't exist", depth );
			return;
		}
		if ( characterID >= 0 ) {
			// We are very picky about what kind of objects can change characters
			// Shapes can become other shapes, but sprites can never change
			if ( display->spriteInstance || display->textInstance ) {
				idLib::Warning( "PlaceObject3: Trying to change the character of a sprite after it's been created" );
				return;
			}
			idSWFDictionaryEntry * dictEntry = sprite->swf->FindDictionaryEntry( characterID );
			if ( dictEntry != NULL ) {
				if ( dictEntry->type == SWF_DICT_SPRITE || dictEntry->type == SWF_DICT_EDITTEXT ) {
					idLib::Warning( "PlaceObject3: Trying to change the character of a shape to a sprite" );
					return;
				}
			}
			display->characterID = characterID;
		}
	} else {
		if ( characterID < 0 ) {
			idLib::Warning( "PlaceObject3: Trying to create a new object without a character" );
			return;
		}
		// create a new entry
		display = AddDisplayEntry( depth, characterID );
		if ( display == NULL ) {
			idLib::Warning( "PlaceObject3: trying to create a new entry at %d, but an item already exists there", depth );
			return;
		}
	}
	if ( ( flags1 & PlaceFlagHasMatrix ) != 0 ) {
		bitstream.ReadMatrix( display->matrix );
	}
	if ( ( flags1 & PlaceFlagHasColorTransform ) != 0 ) {
		bitstream.ReadColorXFormRGBA( display->cxf );
	}
	if ( ( flags1 & PlaceFlagHasRatio ) != 0 ) {
		display->ratio = bitstream.ReadU16() * ( 1.0f / 65535.0f );
	}
	if ( ( flags1 & PlaceFlagHasName ) != 0 ) {
		idStr name = bitstream.ReadString();
		if ( display->spriteInstance ) {
			display->spriteInstance->name = name;
			scriptObject->Set( name, display->spriteInstance->GetScriptObject() );
		} else if ( display->textInstance ) {
			scriptObject->Set( name, display->textInstance->GetScriptObject() );
		}
	}
	if ( ( flags1 & PlaceFlagHasClipDepth ) != 0 ) {
		display->clipDepth = bitstream.ReadU16();
	}
	if ( ( flags2 & PlaceFlagHasFilterList ) != 0 ) {
		// we don't support filters and because the filter list is variable length we
		// can't support anything after the filter list either (blend modes and clip actions)
		idLib::Warning( "PlaceObject3: has filters" );
		return;
	}
	if ( ( flags2 & PlaceFlagHasBlendMode ) != 0 ) {
		display->blendMode = bitstream.ReadU8();
	}
	if ( ( flags1 & PlaceFlagHasClipActions ) != 0 ) {
		// FIXME:
	}
}
예제 #4
0
/*
========================
idSWF::DefineFont2
========================
*/
void idSWF::DefineFont2( idSWFBitStream & bitstream ) {
	uint16 characterID = bitstream.ReadU16();
	idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_FONT );
	if ( entry == NULL ) {
		return;
	}
	uint8 flags = bitstream.ReadU8();
	uint8 language = bitstream.ReadU8();

	char fontName[257];
	uint8 fontNameLength = bitstream.ReadU8();
	memcpy( fontName, bitstream.ReadData( fontNameLength ), fontNameLength );
	fontName[ fontNameLength ] = 0;

	entry->font->fontID = renderSystem->RegisterFont( fontName );

	uint16 numGlyphs = bitstream.ReadU16();
	entry->font->glyphs.SetNum( numGlyphs );

	if ( flags & BIT( 3 ) ) {
		// 32 bit offsets
		uint32 offsetTableSize = ( numGlyphs + 1 ) * 4;
		idSWFBitStream offsetStream( bitstream.ReadData( offsetTableSize ), offsetTableSize, false );
		if ( offsetStream.ReadU32() != offsetTableSize ) {
			idLib::Warning( "idSWF::DefineFont2: first glyph offset != offsetTableSize" );
			return;
		}
		uint32 previousOffset = offsetTableSize;
		for ( int i = 0; i < numGlyphs; i++ ) {
			uint32 nextOffset = offsetStream.ReadU32();
			uint32 shapeSize = nextOffset - previousOffset;
			previousOffset = nextOffset;
			idSWFBitStream shapeStream( bitstream.ReadData( shapeSize ), shapeSize, false );
			idSWFShapeParser swfShapeParser;
			swfShapeParser.ParseFont( shapeStream, entry->font->glyphs[i] );
		}
	} else {
		// 16 bit offsets
		uint16 offsetTableSize = ( numGlyphs + 1 ) * 2;
		idSWFBitStream offsetStream( bitstream.ReadData( offsetTableSize ), offsetTableSize, false );
		if ( offsetStream.ReadU16() != offsetTableSize ) {
			idLib::Warning( "idSWF::DefineFont2: first glyph offset != offsetTableSize" );
			return;
		}
		uint16 previousOffset = offsetTableSize;
		for ( int i = 0; i < numGlyphs; i++ ) {
			uint16 nextOffset = offsetStream.ReadU16();
			uint16 shapeSize = nextOffset - previousOffset;
			previousOffset = nextOffset;
			idSWFBitStream shapeStream( bitstream.ReadData( shapeSize ), shapeSize, false );
			idSWFShapeParser swfShapeParser;
			swfShapeParser.ParseFont( shapeStream, entry->font->glyphs[i] );
		}
	}
	if ( flags & BIT( 2 ) ) {
		// 16 bit codes
		for ( int i = 0; i < numGlyphs; i++ ) {
			entry->font->glyphs[i].code = bitstream.ReadU16();
		}
	} else {
		// 8 bit codes
		for ( int i = 0; i < numGlyphs; i++ ) {
			entry->font->glyphs[i].code = bitstream.ReadU8();
		}
	}
	if ( flags & BIT( 7 ) ) {
		entry->font->ascent = bitstream.ReadS16();
		entry->font->descent = bitstream.ReadS16();
		entry->font->leading = bitstream.ReadS16();
		for ( int i = 0; i < numGlyphs; i++ ) {
			entry->font->glyphs[i].advance = bitstream.ReadS16();
		}
		for ( int i = 0; i < numGlyphs; i++ ) {
			swfRect_t ignored;
			bitstream.ReadRect( ignored );
		}
		uint16 kearningCount = bitstream.ReadU16();
		if ( flags & BIT( 2 ) ) {
			for ( int i = 0; i < kearningCount; i++ ) {
				uint16 code1 = bitstream.ReadU16();
				uint16 code2 = bitstream.ReadU16();
				int16 adjustment = bitstream.ReadS16();
			}
		} else {
			for ( int i = 0; i < kearningCount; i++ ) {
				uint16 code1 = bitstream.ReadU8();
				uint16 code2 = bitstream.ReadU8();
				int16 adjustment = bitstream.ReadS16();
			}
		}
	}
}
예제 #5
0
/*
========================
idSWF::DefineEditText
========================
*/
void idSWF::DefineEditText( idSWFBitStream & bitstream ) {
	uint16 characterID = bitstream.ReadU16();
	idSWFDictionaryEntry * entry = AddDictionaryEntry( characterID, SWF_DICT_EDITTEXT );
	if ( entry == NULL ) {
		return;
	}
	idSWFEditText * edittext = entry->edittext;
	bitstream.ReadRect( edittext->bounds );
	bitstream.ResetBits();
	bool hasText = bitstream.ReadBool();
	bool wordWrap = bitstream.ReadBool();
	bool multiline = bitstream.ReadBool();
	bool password = bitstream.ReadBool();
	bool readonly = bitstream.ReadBool();
	bool hasTextColor = bitstream.ReadBool();
	bool hasMaxLength = bitstream.ReadBool();
	bool hasFont = bitstream.ReadBool();
	bool hasFontClass = bitstream.ReadBool();
	bool autoSize = bitstream.ReadBool();
	bool hasLayout = bitstream.ReadBool();
	bool noSelect = bitstream.ReadBool();
	bool border = bitstream.ReadBool();
	bool wasStatic = bitstream.ReadBool();
	bool html = bitstream.ReadBool();
	bool useOutlines = bitstream.ReadBool();
	if ( hasFont ) {
		edittext->fontID = bitstream.ReadU16();
		edittext->fontHeight = bitstream.ReadU16();
	}
	if ( hasFontClass ) {
		idStr fontClass = bitstream.ReadString();
	}
	if ( hasTextColor ) {
		bitstream.ReadColorRGBA( edittext->color );
	}
	if ( hasMaxLength ) {
		edittext->maxLength = bitstream.ReadU16();
	}
	if ( hasLayout ) {
		edittext->align = (swfEditTextAlign_t)bitstream.ReadU8();
		edittext->leftMargin = bitstream.ReadU16();
		edittext->rightMargin = bitstream.ReadU16();
		edittext->indent = bitstream.ReadU16();
		edittext->leading = bitstream.ReadS16();
	}
	edittext->variable = bitstream.ReadString();
	if ( hasText ) {
		const char * text = bitstream.ReadString();
		idStr initialText;

		// convert html tags if necessary
		for ( int i = 0; text[i] != 0; i++ ) {
			if ( text[i] == '<' ) {
				if ( i != 0 && text[i+1] == 'p' ) {
					initialText.Append( '\n' );
				}
				for ( ; text[i] != 0 && text[i] != '>'; i++ ) {
				}
				continue;
			}
			byte tc = (byte)text[i];
			if ( tc == '&' ) {
				idStr special;
				for ( i++; text[i] != 0 && text[i] != ';'; i++ ) {
					special.Append( text[i] );
				}
				if ( special.Icmp( "amp" ) == 0 ) {
					tc = '&';
				} else if ( special.Icmp( "apos" ) == 0 ) {
					tc = '\'';
				} else if ( special.Icmp( "lt" ) == 0 ) {
					tc = '<';
				} else if ( special.Icmp( "gt" ) == 0 ) {
					tc = '>';
				} else if ( special.Icmp( "quot" ) == 0 ) {
					tc = '\"';
				}
			}
			initialText.Append( tc );
		}
		edittext->initialText = initialText;
	}
	edittext->flags |= wordWrap ? SWF_ET_WORDWRAP : 0;
	edittext->flags |= multiline ? SWF_ET_MULTILINE : 0;
	edittext->flags |= password ? SWF_ET_PASSWORD : 0;
	edittext->flags |= readonly ? SWF_ET_READONLY : 0;
	edittext->flags |= autoSize ? SWF_ET_AUTOSIZE : 0;
	edittext->flags |= border ? SWF_ET_BORDER : 0;
}
예제 #6
0
/*
========================
idSWFShapeParser::ParseShape
========================
*/
void idSWFShapeParser::Parse( idSWFBitStream& bitstream, idSWFShape& shape, int recordType )
{
	extendedCount = ( recordType > 1 );
	lineStyle2 = ( recordType == 4 );
	rgba = ( recordType >= 3 );
	morph = false;
	
	bitstream.ReadRect( shape.startBounds );
	shape.endBounds = shape.startBounds;
	
	if( recordType == 4 )
	{
		swfRect_t edgeBounds;
		bitstream.ReadRect( edgeBounds );
		bitstream.ReadU8();	// flags (that we ignore)
	}
	
	ReadFillStyle( bitstream );
	ParseShapes( bitstream, NULL, false );
	TriangulateSoup( shape );
	
	shape.lineDraws.SetNum( lineDraws.Num() );
	for( int i = 0; i < lineDraws.Num(); i++ )
	{
		idSWFShapeDrawLine& ld = shape.lineDraws[i];
		swfSPDrawLine_t& spld = lineDraws[i];
		ld.style = spld.style;
		ld.indices.SetNum( spld.edges.Num() * 3 );
		ld.indices.SetNum( 0 );
		for( int e = 0; e < spld.edges.Num(); e++ )
		{
			int v0 = ld.startVerts.AddUnique( verts[ spld.edges[e].start.v0 ] );
			ld.indices.Append( v0 );
			ld.indices.Append( v0 );
			
			// Rather then tesselating curves at run time, we do them once here by inserting a vert every 10 units
			// It may not wind up being 10 actual pixels when rendered because the shape may have scaling applied to it
			if( spld.edges[e].start.cp != 0xFFFF )
			{
				assert( spld.edges[e].end.cp != 0xFFFF );
				float length1 = ( verts[ spld.edges[e].start.v0 ] - verts[ spld.edges[e].start.v1 ] ).Length();
				float length2 = ( verts[ spld.edges[e].end.v0 ] - verts[ spld.edges[e].end.v1 ] ).Length();
				int numPoints = 1 + idMath::Ftoi( Max( length1, length2 ) / 10.0f );
				for( int ti = 0; ti < numPoints; ti++ )
				{
					float t0 = ( ti + 1 ) / ( ( float ) numPoints + 1.0f );
					float t1 = ( 1.0f - t0 );
					float c1 = t1 * t1;
					float c2 = t0 * t1 * 2.0f;
					float c3 = t0 * t0;
					
					idVec2	p1  = c1 * verts[ spld.edges[e].start.v0 ];
					p1 += c2 * verts[ spld.edges[e].start.cp ];
					p1 += c3 * verts[ spld.edges[e].start.v1 ];
					
					int v1 = ld.startVerts.AddUnique( p1 );
					ld.indices.Append( v1 );
					ld.indices.Append( v1 );
					ld.indices.Append( v1 );
				}
			}
			ld.indices.Append( ld.startVerts.AddUnique( verts[ spld.edges[e].start.v1 ] ) );
		}
	}
}
예제 #7
0
/*
========================
idSWFShapeParser::ParseShapes
========================
*/
void idSWFShapeParser::ParseShapes( idSWFBitStream& bitstream1, idSWFBitStream* bitstream2, bool swap )
{
	int32 pen1X = 0;
	int32 pen1Y = 0;
	int32 pen2X = 0;
	int32 pen2Y = 0;
	
	uint8 fillStyle0 = 0;
	uint8 fillStyle1 = 0;
	uint8 lineStyle = 0;
	
	uint16 baseFillStyle = 0;
	uint16 baseLineStyle = 0;
	
	uint8 numBits = bitstream1.ReadU8();
	uint8 numFillBits1 = numBits >> 4;
	uint8 numLineBits1 = numBits & 0xF;
	
	uint8 numFillBits2 = 0;
	uint8 numLineBits2 = 0;
	
	if( bitstream2 )
	{
		numBits = bitstream2->ReadU8();
		numFillBits2 = numBits >> 4;
		numLineBits2 = numBits & 0xF;
	}
	
	while( true )
	{
		if( !bitstream1.ReadBool() )
		{
			bool stateNewStyles = bitstream1.ReadBool();
			bool stateLineStyle = bitstream1.ReadBool();
			bool stateFillStyle1 = bitstream1.ReadBool();
			bool stateFillStyle0 = bitstream1.ReadBool();
			bool stateMoveTo = bitstream1.ReadBool();
			if( ( stateNewStyles || stateLineStyle || stateFillStyle1 || stateFillStyle0 || stateMoveTo ) == false )
			{
				// end record
				if( bitstream2 )
				{
					uint8 flags = bitstream2->ReadU( 6 );
					if( flags != 0 )
					{
						idLib::Warning( "idSWFShapeParser: morph stream 1 ends before 2" );
						break;
					}
				}
				break;
			}
			if( stateMoveTo )
			{
				uint8 moveBits = bitstream1.ReadU( 5 );
				pen1X = bitstream1.ReadS( moveBits );
				pen1Y = bitstream1.ReadS( moveBits );
			}
			if( stateFillStyle0 )
			{
				fillStyle0 = bitstream1.ReadU( numFillBits1 );
			}
			if( stateFillStyle1 )
			{
				fillStyle1 = bitstream1.ReadU( numFillBits1 );
			}
			if( stateLineStyle )
			{
				lineStyle = bitstream1.ReadU( numLineBits1 );
			}
			if( stateNewStyles )
			{
				baseFillStyle = fillDraws.Num();
				baseLineStyle = lineDraws.Num();
				ReadFillStyle( bitstream1 );
				numBits = bitstream1.ReadU8();
				numFillBits1 = numBits >> 4;
				numLineBits1 = numBits & 0xF;
			}
			if( bitstream2 )
			{
				bool isEdge = bitstream2->ReadBool();
				if( isEdge )
				{
					idLib::Warning( "idSWFShapeParser: morph stream 1 defines style change, but stream 2 does not" );
					break;
				}
				bool stateNewStyles = bitstream2->ReadBool();
				bool stateLineStyle = bitstream2->ReadBool();
				bool stateFillStyle1 = bitstream2->ReadBool();
				bool stateFillStyle0 = bitstream2->ReadBool();
				bool stateMoveTo = bitstream2->ReadBool();
				if( stateMoveTo )
				{
					uint8 moveBits = bitstream2->ReadU( 5 );
					pen2X = bitstream2->ReadS( moveBits );
					pen2Y = bitstream2->ReadS( moveBits );
				}
				if( stateFillStyle0 )
				{
					if( bitstream2->ReadU( numFillBits2 ) != fillStyle0 )
					{
						idLib::Warning( "idSWFShapeParser: morph stream 2 defined a different fillStyle0 from stream 1" );
						break;
					}
				}
				if( stateFillStyle1 )
				{
					if( bitstream2->ReadU( numFillBits2 ) != fillStyle1 )
					{
						idLib::Warning( "idSWFShapeParser: morph stream 2 defined a different fillStyle1 from stream 1" );
						break;
					}
				}
				if( stateLineStyle )
				{
					if( bitstream2->ReadU( numLineBits2 ) != lineStyle )
					{
						idLib::Warning( "idSWFShapeParser: morph stream 2 defined a different lineStyle from stream 1" );
						break;
					}
				}
				if( stateNewStyles )
				{
					idLib::Warning( "idSWFShapeParser: morph stream 2 defines new styles" );
					break;
				}
			}
		}
		else
		{