Example #1
0
void
SWFText_resolveCodes(SWFText text)
{
	SWFTextRecord textRecord, oldRecord;
	SWFOutput out = text->out;
	int nGlyphBits = 0;
	int len, i;
	int curX = 0, curY = 0, curH = 0;

	textRecord = text->initialRecord;

	while ( textRecord != NULL )
	{
		SWFTextRecord_computeAdvances(textRecord);

		text->nAdvanceBits = max(text->nAdvanceBits, textRecord->nAdvanceBits);

		if ( textRecord->flags & SWF_TEXT_HAS_FONT )
		{	
			int fontGlyphs = SWFFontCharacter_getNGlyphs(textRecord->font.fontchar);
			nGlyphBits = max(nGlyphBits, SWFOutput_numBits(fontGlyphs-1));
		}

		textRecord = textRecord->next;
	}

	textRecord = text->initialRecord;

	while ( textRecord != NULL )
	{
		SWFFontCharacter fontchar = NULL;
		SWFFont font = NULL;
		oldRecord = textRecord;

		if ( textRecord->string == NULL || textRecord->strlen == 0 )
		{
			textRecord = textRecord->next;
			destroySWFTextRecord(oldRecord);
			continue;
		}

		SWFOutput_byteAlign(out);

		/* Raff says the spec lies- there's always a change record, even if
			 it's empty, and the string record length is the full 8 bits. */

		SWFOutput_writeUInt8(out, textRecord->flags | SWF_TEXT_STATE_CHANGE);

		if ( textRecord->flags & SWF_TEXT_HAS_FONT )
			SWFOutput_writeUInt16(out, CHARACTERID(textRecord->font.fontchar));

		if ( textRecord->flags & SWF_TEXT_HAS_COLOR )
		{
			SWFOutput_writeUInt8(out, textRecord->r);
			SWFOutput_writeUInt8(out, textRecord->g);
			SWFOutput_writeUInt8(out, textRecord->b);

			if ( BLOCK(text)->type == SWF_DEFINETEXT2 )
				SWFOutput_writeUInt8(out, textRecord->a);
		}

		if ( textRecord->flags & SWF_TEXT_HAS_X )
		{
			SWFOutput_writeUInt16(out, textRecord->x);
			curX = textRecord->x;
		}

		if ( textRecord->flags & SWF_TEXT_HAS_Y )
		{
			SWFOutput_writeUInt16(out, textRecord->y);
			curY = textRecord->y;
		}

		if ( textRecord->flags & SWF_TEXT_HAS_FONT )
		{
			SWFOutput_writeUInt16(out, textRecord->height);
			curH = textRecord->height;
		}

		/* record type 0: string data */

		len = textRecord->strlen;

		if ( len >= 256 )
			SWF_error("Found text record >= 256 characters!");

		SWFOutput_writeUInt8(out, len);

		fontchar = textRecord->font.fontchar;
		font = SWFFontCharacter_getFont(fontchar);

		if ( font == NULL )
			SWF_error("Couldn't find font");

		for ( i=0; i<len; ++i )
		{
			SWFRect glyphBounds;
			int minX, maxX, minY, maxY;

			unsigned short font_glyphcode =
				SWFFont_findGlyphCode(font, textRecord->string[i]);
			glyphBounds = SWFFont_getGlyphBounds(font,font_glyphcode);
			SWFRect_getBounds(glyphBounds, &minX, &maxX, &minY, &maxY);

			int fontchar_glyphcode =
				SWFFontCharacter_findGlyphCode(fontchar, textRecord->string[i]);
			if (fontchar_glyphcode < 0) {
				SWF_error("SWFText_resolveCodes: no suitable glyph available (in dumped font)");
			}
			SWFOutput_writeBits(out, (unsigned short) fontchar_glyphcode,	nGlyphBits);
			SWFOutput_writeBits(out, textRecord->advance[i], text->nAdvanceBits);

			if ( CHARACTER(text)->bounds )
			{
				SWFRect_includePoint(CHARACTER(text)->bounds, curX + minX * curH / 1024, 
				                     curY + minY * curH / 1024, 0);
				SWFRect_includePoint(CHARACTER(text)->bounds, curX + maxX * curH / 1024, 
				                     curY + maxY * curH / 1024, 0);
			}
			else
			{
				CHARACTER(text)->bounds = newSWFRect(curX + minX * curH /1024, 
					curX + maxX * curH /1024, curY + minY * curH /1024, 
					curY + maxY * curH /1024);
			}

			if ( textRecord->advance != NULL )
				curX += textRecord->advance[i];
		}
		textRecord = textRecord->next;
		destroySWFTextRecord(oldRecord);
	}
	SWFOutput_writeUInt8(out, 0); /* end text records */

	text->nGlyphBits = nGlyphBits;
	text->initialRecord = NULL;
	text->currentRecord = NULL;
}
Example #2
0
void
SWFText_resolveCodes(SWFText text)
{
	SWFTextRecord textRecord, oldRecord;
	SWFOutput out = text->out;
	int nGlyphBits = 0;
	int len, i;
	int curX = 0, curY = 0, curH = 0;

	textRecord = text->initialRecord;

	while ( textRecord != NULL )
	{
		SWFTextRecord_computeAdvances(textRecord);

		text->nAdvanceBits = max(text->nAdvanceBits, textRecord->nAdvanceBits);

		if ( textRecord->flags & SWF_TEXT_HAS_FONT )
		{
			if ( textRecord->isBrowserFont )
			{
				/* XXX - assume browser fonts have 8bit glyph table? */
				nGlyphBits = max(nGlyphBits, 8);
			}
			else
			{
				int fontGlyphs = SWFFontCharacter_getNGlyphs(textRecord->font.fontchar);
				nGlyphBits = max(nGlyphBits, SWFOutput_numBits(fontGlyphs-1));
			}
		}

		textRecord = textRecord->next;
	}

	textRecord = text->initialRecord;

	while ( textRecord != NULL )
	{
		oldRecord = textRecord;

		if ( textRecord->string == NULL || textRecord->strlen == 0 )
		{
			textRecord = textRecord->next;
			destroySWFTextRecord(oldRecord);
			continue;
		}

		SWFOutput_byteAlign(out);

		/* Raff says the spec lies- there's always a change record, even if
			 it's empty, and the string record length is the full 8 bits. */

		SWFOutput_writeUInt8(out, textRecord->flags | SWF_TEXT_STATE_CHANGE);

		if ( textRecord->flags & SWF_TEXT_HAS_FONT )
		{
			if ( textRecord->isBrowserFont )
				SWFOutput_writeUInt16(out, CHARACTERID(textRecord->font.browserFont));
			else
				SWFOutput_writeUInt16(out, CHARACTERID(textRecord->font.fontchar));
		}

		if ( textRecord->flags & SWF_TEXT_HAS_COLOR )
		{
			SWFOutput_writeUInt8(out, textRecord->r);
			SWFOutput_writeUInt8(out, textRecord->g);
			SWFOutput_writeUInt8(out, textRecord->b);

			if ( BLOCK(text)->type == SWF_DEFINETEXT2 )
				SWFOutput_writeUInt8(out, textRecord->a);
		}

		if ( textRecord->flags & SWF_TEXT_HAS_X )
		{
			SWFOutput_writeUInt16(out, textRecord->x);
			curX = textRecord->x;
		}

		if ( textRecord->flags & SWF_TEXT_HAS_Y )
		{
			SWFOutput_writeUInt16(out, textRecord->y);
			curY = textRecord->y;
		}

		if ( textRecord->flags & SWF_TEXT_HAS_FONT )
		{
			SWFOutput_writeUInt16(out, textRecord->height);
			curH = textRecord->height;
		}

		/* record type 0: string data */

		len = textRecord->strlen;

		if ( len >= 256 )
			SWF_error("Found text record >= 256 characters!");

		SWFOutput_writeUInt8(out, len);

		/* XXX - er, browser fonts in text objects crash the player..
			 Maybe because there's no definefontinfo block? */

		if ( textRecord->isBrowserFont )
		{
			for ( i=0; i<len; ++i )
			{
				SWFOutput_writeBits(out, textRecord->string[i], nGlyphBits);
				SWFOutput_writeBits(out, textRecord->advance[i], text->nAdvanceBits);

				/* XXX - fudging the text character bounds since we don't
					 have font metrics */

				if ( CHARACTER(text)->bounds )
				{
					SWFRect_includePoint(CHARACTER(text)->bounds, curX, curY, 0);
					SWFRect_includePoint(CHARACTER(text)->bounds,
															 curX + curH, curY + curH, 0);
				}
				else
				{
					CHARACTER(text)->bounds =
						newSWFRect(curX, curX + curH, curY, curY + curH);
				}

				curX += curH;
			}
		}
		else
		{
			SWFFontCharacter fontchar = textRecord->font.fontchar;
			SWFFont font = SWFFontCharacter_getFont(fontchar);

			if ( font == NULL )
				SWF_error("Couldn't find font");

			for ( i=0; i<len; ++i )
			{
				SWFRect glyphBounds;
				int minX, maxX, minY, maxY;

				unsigned short code =
					SWFFontCharacter_getGlyphCode(fontchar, textRecord->string[i]);

				glyphBounds = SWFFont_getGlyphBounds(font, code);

				SWFRect_getBounds(glyphBounds, &minX, &maxX, &minY, &maxY);

				SWFOutput_writeBits(out, textRecord->string[i],	nGlyphBits);
				SWFOutput_writeBits(out, textRecord->advance[i], text->nAdvanceBits);

				if ( CHARACTER(text)->bounds )
				{
					SWFRect_includePoint(CHARACTER(text)->bounds,
															 curX + minX * curH / 1024,
															 curY + minY * curH / 1024, 0);

					SWFRect_includePoint(CHARACTER(text)->bounds,
															 curX + maxX * curH / 1024,
															 curY + maxY * curH / 1024, 0);
				}
				else
				{
					CHARACTER(text)->bounds =
						newSWFRect(curX + minX * curH /1024, curX + maxX * curH /1024,
											 curY + minY * curH /1024, curY + maxY * curH /1024);
				}

				if ( textRecord->advance != NULL )
					curX += textRecord->advance[i];
			}
		}

		textRecord = textRecord->next;
		destroySWFTextRecord(oldRecord);
	}

	SWFOutput_writeUInt8(out, 0); /* end text records */

	text->nGlyphBits = nGlyphBits;
	text->initialRecord = NULL;
	text->currentRecord = NULL;
}