#include "font_d3d9.h" static unsigned int _pow2(unsigned int i) { register unsigned int p2; for (p2=1; p2pt; wids=(float *)malloc(sizeof(float)*255); bears=(float *)malloc(sizeof(float)*255); hoss=(float *)malloc(sizeof(float)*255); qvws=(int *)malloc(sizeof(int)*255); qvhs=(int *)malloc(sizeof(int)*255); qtws=(float *)malloc(sizeof(float)*255); qths=(float *)malloc(sizeof(float)*255); memset(textures,0,sizeof(LPDIRECT3DTEXTURE9)*255); LPDIRECT3DSURFACE9 surface; D3DLOCKED_RECT lockrect; // surface locked image rect (to copy stuff to) D3DSURFACE_DESC surfdesc; // surface descriptor (for information) for (register unsigned char ch=0; ch<255; ch++) { register int i,j; FT_Face face=ttf->face; FT_BitmapGlyph bitmap_glyph; FT_Glyph glyph; FT_Bitmap bitmap; unsigned int width,height; UINT8 *expanded_data; FT_Load_Glyph(face,FT_Get_Char_Index(face,ch),FT_LOAD_DEFAULT); FT_Get_Glyph(face->glyph,&glyph); FT_Glyph_To_Bitmap(&glyph,ft_render_mode_normal,0,1); bitmap_glyph=(FT_BitmapGlyph)glyph; bitmap=bitmap_glyph->bitmap; width=_pow2(bitmap.width); height=_pow2(bitmap.rows); expanded_data=new UINT8[width*height]; for (j=0; j<(int)height;j++) { for (i=0; i<(int)width; i++) { expanded_data[i+j*width]= (i>=bitmap.width||j>=bitmap.rows)? 0:bitmap.buffer[i+bitmap.width*j]; } } LPDIRECT3DTEXTURE9 tex; if (dev->CreateTexture(width,height,0,0,D3DFMT_A8,D3DPOOL_MANAGED,&tex,NULL)!=D3D_OK) is_valid=false; textures[ch]=tex; textures[ch]->GetLevelDesc(0,&surfdesc); textures[ch]->GetSurfaceLevel(0,&surface); if (surface->LockRect(&lockrect,NULL,0)==D3D_OK) { memcpy(lockrect.pBits,expanded_data,width*height); if (surface->UnlockRect()!=D3D_OK) is_valid=false; } else is_valid=false; delete[] expanded_data; this->wids[ch]=(float)(face->glyph->advance.x>>6); this->hoss[ch]=(float)(face->glyph->metrics.horiBearingY>>6); this->bears[ch]=(float)(face->glyph->metrics.horiBearingX>>6); this->qvws[ch]=bitmap.width; this->qvhs[ch]=bitmap.rows; this->qtws[ch]=(float)bitmap.width/(float)width; this->qths[ch]=(float)bitmap.rows/(float)height; } color=Vector4(1.0f); } FontD3D9::~FontD3D9() { for (register unsigned int i=0; i<255; i++) { if (textures[i]) textures[i]->Release(); } free((void *)wids); free((void *)bears); free((void *)hoss); free((void *)qvws); free((void *)qvhs); free((void *)qtws); free((void *)qths); } struct __fontquadvertex { float x,y,z,rhw; // x, y, and z pre-transformed DWORD color; // 32 bit ARGB color float s,t; // tex coords }; void FontD3D9::Render(int x,int y,const char *text) { if (!is_valid) return; // create a new state block. a lot like glPushAttrib IDirect3DStateBlock9 *stateblock=NULL; dev->CreateStateBlock(D3DSBT_ALL,&stateblock); if (!stateblock) return; // set up font render state dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); dev->SetRenderState(D3DRS_ALPHATESTENABLE,FALSE); dev->SetRenderState(D3DRS_ZENABLE,FALSE); dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_NONE); dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP); dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP); dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1); dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_DIFFUSE); dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_TEXTURE); dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE); dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE); dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); unsigned int len=strlen(text); __fontquadvertex verts[4]; memset(verts,0,sizeof(__fontquadvertex)*4); float widaccum=0.0f; for (char *ch=(char *)text; *ch; ch++) { verts[0].rhw=1.0f; verts[1].rhw=1.0f; verts[2].rhw=1.0f; verts[3].rhw=1.0f; float ex=(widaccum+x+bears[*ch])-0.5f; float wy=y+(pt-hoss[*ch])-0.5f; verts[0].x=ex; verts[0].y=wy; verts[1].x=ex; verts[1].y=wy+(float)qvhs[*ch]; verts[2].x=ex+(float)qvws[*ch]; verts[2].y=wy; verts[3].x=ex+(float)qvws[*ch]; verts[3].y=wy+(float)qvhs[*ch]; verts[1].t=qths[*ch]; verts[2].s=qtws[*ch]; verts[3].s=qtws[*ch]; verts[3].t=qths[*ch]; verts[0].color=verts[1].color= verts[2].color=verts[3].color= D3DCOLOR_COLORVALUE(color.x,color.y,color.z,color.w); dev->SetTexture(0,textures[*ch]); dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1); dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,verts,sizeof(__fontquadvertex)); widaccum+=wids[*ch]; } // restore the old state. a lot like glPopAttrib stateblock->Apply(); stateblock->Release(); }