예제 #1
0
//----------------------------------------------------------------//
void MOAIFont::InitWithBMFont ( cc8* filename ) {

	USFileStream stream;
	if ( !stream.OpenRead ( filename )) return;

	u32 len = stream.GetLength ();
	char* buf = ( char* )malloc ( len + 1 );
	stream.ReadBytes ( buf, len );
	buf [ len ] = '\0';
	stream.Close ();

	char* p = buf;
	char* endp = p + len;

	MOAIGlyphSet* glyphSet = 0;
	MOAIStaticGlyphCache* glyphCache = new MOAIStaticGlyphCache ();

	this->mCache.Set ( *this, glyphCache );
	this->mReader.Set ( *this, 0 );

	p = buf;
	while ( p < endp ) {
	
		// Parse each line.
		bool endl;
		char* key;
		char* val;

		p = parseKeyVal ( p, &key, &val, &endl );

		if ( strcmp ( key, "info" ) == 0 ) {
		
			float size = 0.0f;
			
			//info face="Cambria" size=64 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2
			do {
				p = parseKeyVal ( p, &key, &val, &endl );
				if ( strcasecmp ( key, "size" ) == 0 ) { size = ( float )atof ( val ); }
			} while ( !endl );
			
			if ( size > 0.0f ) {
				glyphSet = &this->AffirmGlyphSet ( size );
				assert ( glyphSet );
			}
		}
		else if ( strcmp ( key, "common" ) == 0 ) {
			
			float lineSpacing = 0.0f;
			float base = 0.0f;
			u32 pages = 0;
			
			//common lineHeight=75 base=61 scaleW=512 scaleH=512 pages=1 packed=0
			do {
				p = parseKeyVal ( p, &key, &val, &endl );
				if ( strcasecmp ( key, "lineHeight" ) == 0 ) { lineSpacing = ( float )atof ( val ); }
				else if ( strcasecmp ( key, "pages" ) == 0 ) { pages = ( u32 )atoi ( val ); }
				else if ( strcasecmp ( key, "base" ) == 0 ) { base = ( float )atof ( val ); }
			} while ( !endl );
			
			glyphSet->SetHeight( lineSpacing );
			glyphSet->SetAscent( base );
			glyphCache->ReserveTextures ( pages );
		}
		else if ( strcmp ( key, "page" ) == 0 ) {
			
			STLString texturename;
			u32 id = 0;
		
			//page id=0 file="Blah.png"
			do {
				p = parseKeyVal ( p, &key, &val, &endl );
				if( strcmp(key, "id") == 0 ) { id = ( u32 )atoi ( val ); }
				else if ( strcmp ( key, "file" ) == 0 ) { texturename = val; }
			} while ( !endl );
			
			MOAITexture* texture = new MOAITexture ();
			glyphCache->SetTexture ( id, texture );
			texture->Init ( texturename, MOAITexture::DEFAULT_TRANSFORM );
		}
		else if ( strcmp ( key, "chars" ) == 0 ) {
			//chars count=95
			do {
				p = parseKeyVal ( p, &key, &val, &endl );
			} while ( !endl );
		}
		else if ( strcmp ( key, "char" ) == 0 ) {
			
			//char id=47 x=2 y=2 width=32 height=63 xoffset=1 yoffset=15 xadvance=31 page=0 chnl=0 letter="/"
			u32 c = 0;
			u32 x = 0;
			u32 y = 0;
			float width = 0.0f;
			float height = 0.0f;
			float xoff = 0.0f;
			float yoff = 0.0f;
			float xadv = 0.0f;
			u32 page = 0;
			
			do {
				p = parseKeyVal ( p, &key, &val, &endl );
				if ( strcasecmp ( key, "id" ) == 0 ) { c = ( u32 )atoi ( val ); }
				else if ( strcasecmp ( key, "x" ) == 0 ) { x = ( u32 )atoi ( val ); }
				else if ( strcasecmp ( key, "y" ) == 0 ) { y = ( u32 )atoi ( val ); }
				else if ( strcasecmp ( key, "width" ) == 0 ) { width = ( float )atof ( val ); }
				else if ( strcasecmp ( key, "height" ) == 0 ) { height = ( float )atof ( val ); }
				else if ( strcasecmp ( key, "xoffset" ) == 0 ) { xoff = ( float )atof ( val ); }
				else if ( strcasecmp ( key, "yoffset" ) == 0 ) { yoff = ( float )atof ( val ); }
				else if ( strcasecmp ( key, "xadvance" ) == 0 ) { xadv = ( float )atof ( val ); }
				else if ( strcasecmp ( key, "page" ) == 0 ) { page = ( u32 )atoi ( val ); }

			} while( !endl );
			
			assert ( glyphSet );
			MOAIGlyph& glyph = glyphSet->EditGlyph ( c );
			
			glyph.mSrcX = x;
			glyph.mSrcY = y;
			glyph.mPageID = page;
			glyph.mWidth = width;
			glyph.mHeight = height;
			glyph.mAdvanceX = xadv;
			glyph.mBearingX = xoff;
			glyph.mBearingY = glyphSet->GetAscent() - yoff;
			
		}
		else if ( strcmp ( key, "kernings" ) == 0 ) {
			//kernings count=560
			do {
				p = parseKeyVal ( p, &key, &val, &endl );
			} while ( !endl );
		}
		else if ( strcmp ( key, "kerning" ) == 0 ) {
			
			//kerning first=47 second=65 amount=-1
			u32 first = 0;
			u32 second = 0;
			float amount = 0.0f;

			do {
				p = parseKeyVal ( p, &key, &val, &endl );
				if( strcasecmp ( key, "first" ) == 0 ) { first = ( u32 )atoi ( val ); }
				else if ( strcasecmp ( key, "second" ) == 0 ) { second = ( u32 )atoi ( val ); }
				else if ( strcasecmp ( key, "amount" ) == 0 ) { amount =( float )atof ( val ); }
			} while( !endl );
			
			if ( first && second && ( amount != 0.0f )) {
			
				assert ( glyphSet );
				MOAIGlyph& glyph = glyphSet->EditGlyph ( first );
				
				u32 i = glyph.mKernTable.Size();
				glyph.mKernTable.Grow ( i + 1 );
				glyph.mKernTable [ i ].mName = second;
				glyph.mKernTable [ i ].mX = amount;
				glyph.mKernTable [ i ].mY = 0;
			}
		}
	}
}
예제 #2
0
//----------------------------------------------------------------//
void MOAIDraw::DrawString ( cc8* text, float x, float y, float width, float height ) {

	// Sanity check
	size_t textLength = strlen ( text );
	if ( textLength <= 0 ) return;
	
	// Get the context data
	assert ( g_CurrentTextDrawContext );

	// Transform the center into 'world' space
	MOAIGfxDevice& gfxDevice = MOAIGfxDevice::Get ();
	const ZLMatrix4x4& orgWorldTransform = gfxDevice.GetVertexTransform ( MOAIGfxDevice::VTX_WORLD_TRANSFORM );
	USVec2D pos ( x, y );
	orgWorldTransform.Transform ( pos );
	x = pos.mX;
	y = pos.mY;

	// Extract the 'state'
	MOAIFont& font = *g_CurrentTextDrawContext->mFont;
	float scale = g_CurrentTextDrawContext->mScale;
	float fontSize = g_CurrentTextDrawContext->mFontSize;
	
	MOAIGlyphSet* glyphSet = font.GetGlyphSet ( fontSize );
	assert ( glyphSet );

	// Let's draw the string!
	float cursorX = x;
	float cursorY = y + glyphSet->GetAscent() * scale;
	MOAIGlyph* prevGlyph = 0;
	
	// Update the glyph cache
	for ( size_t i = 0; i < textLength; i++ ) {

		cc8 c = text [ i ];
		if ( c != '\n' ) {

			font.AffirmGlyph ( fontSize, c );
		}
	}
	font.ProcessGlyphs ();

	glyphSet = font.GetGlyphSet ( fontSize );
	assert ( glyphSet );

	for ( size_t i = 0; i < textLength; i++ ) {

		cc8 c = text [ i ];
		if ( c == '\n' ) {

			// Move to the next line
			cursorX = x;
			cursorY += glyphSet->GetHeight () * scale;
			prevGlyph = 0;

			if ( height > 0 && (cursorY - y) > height ) {
				break;
			}
		}
		else {

			if ( width > 0 && (cursorX - x) > width ) {
				continue;
			}

			// Get the glyph for the current character
			MOAIGlyph* glyph = glyphSet->GetGlyph ( c );
			if ( glyph ) {

				// Draw the current glyph
				MOAITextureBase* glyphTexture = font.GetGlyphTexture ( *glyph );
				if ( glyphTexture ) {

					GlyphPlacement placement = { glyph, cursorX, cursorY };
					g_CurrentTextDrawContext->mGlyphs.push_back( placement );
				}

				// Apply kerning
				if ( prevGlyph ) {

					MOAIKernVec kern = prevGlyph->GetKerning ( glyph->GetCode () );
					cursorX += kern.mX * scale;
				}

				// Move the cursor
				cursorX += glyph->GetAdvanceX () * scale;
			}

			prevGlyph = glyph;
		}
	}
}