//----------------------------------------------------------------// 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; } } } }
//----------------------------------------------------------------// 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; } } }