/* ** Haaf's Game Engine 1.7 ** Copyright (C) 2003-2007, Relish Games ** hge.relishgames.com ** ** hgeFont helper class implementation */ #include "hgefont.h" #include #include const char FNTHEADERTAG[] = "[HGEFONT]"; const char FNTBITMAPTAG[] = "Bitmap"; const char FNTCHARTAG[] = "Char"; HGE *hgeFont::hge=0; char hgeFont::buffer[1024]; hgeFont::hgeFont(const char *szFont, bool bMipmap) { void *data; DWORD size; char *desc, *pdesc; char linebuf[256]; char buf[MAX_PATH], *pbuf; char chr; int i, x, y, w, h, a, c; // Setup variables hge=hgeCreate(HGE_VERSION); fHeight=0.0f; fScale=1.0f; fProportion=1.0f; fRot=0.0f; fTracking=0.0f; fSpacing=1.0f; hTexture=0; fZ=0.5f; nBlend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE; dwCol=0xFFFFFFFF; ZeroMemory( &letters, sizeof(letters) ); ZeroMemory( &pre, sizeof(pre) ); ZeroMemory( &post, sizeof(post) ); // Load font description data=hge->Resource_Load(szFont, &size); if(!data) return; desc = new char[size+1]; memcpy(desc,data,size); desc[size]=0; hge->Resource_Free(data); pdesc=_get_line(desc,linebuf); if(strcmp(linebuf, FNTHEADERTAG)) { hge->System_Log("Font %s has incorrect format.", szFont); delete[] desc; return; } // Parse font description while((pdesc = _get_line(pdesc,linebuf))) { if(!strncmp(linebuf, FNTBITMAPTAG, sizeof(FNTBITMAPTAG)-1 )) { strcpy(buf,szFont); pbuf=strrchr(buf,'\\'); if(!pbuf) pbuf=strrchr(buf,'/'); if(!pbuf) pbuf=buf; else pbuf++; if(!sscanf(linebuf, "Bitmap = %s", pbuf)) continue; hTexture=hge->Texture_Load(buf, 0, bMipmap); if(!hTexture) { delete[] desc; return; } } else if(!strncmp(linebuf, FNTCHARTAG, sizeof(FNTCHARTAG)-1 )) { pbuf=strchr(linebuf,'='); if(!pbuf) continue; pbuf++; while(*pbuf==' ') pbuf++; if(*pbuf=='\"') { pbuf++; i=(unsigned char)*pbuf++; pbuf++; // skip " } else { i=0; while((*pbuf>='0' && *pbuf<='9') || (*pbuf>='A' && *pbuf<='F') || (*pbuf>='a' && *pbuf<='f')) { chr=*pbuf; if(chr >= 'a') chr-='a'-':'; if(chr >= 'A') chr-='A'-':'; chr-='0'; if(chr>0xF) chr=0xF; i=(i << 4) | chr; pbuf++; } if(i<0 || i>255) continue; } sscanf(pbuf, " , %d , %d , %d , %d , %d , %d", &x, &y, &w, &h, &a, &c); letters[i] = new hgeSprite(hTexture, (float)x, (float)y, (float)w, (float)h); pre[i]=(float)a; post[i]=(float)c; if(h>fHeight) fHeight=(float)h; } } delete[] desc; } hgeFont::~hgeFont() { for(int i=0; i<256; i++) if(letters[i]) delete letters[i]; if(hTexture) hge->Texture_Free(hTexture); hge->Release(); } void hgeFont::Render(float x, float y, int align, const char *string) { int i; float fx=x; align &= HGETEXT_HORZMASK; if(align==HGETEXT_RIGHT) fx-=GetStringWidth(string, false); if(align==HGETEXT_CENTER) fx-=int(GetStringWidth(string, false)/2.0f); while(*string) { if(*string=='\n') { y += int(fHeight*fScale*fSpacing); fx = x; if(align == HGETEXT_RIGHT) fx -= GetStringWidth(string+1, false); if(align == HGETEXT_CENTER) fx -= int(GetStringWidth(string+1, false)/2.0f); } else { i=(unsigned char)*string; if(!letters[i]) i='?'; if(letters[i]) { fx += pre[i]*fScale*fProportion; letters[i]->RenderEx(fx, y, fRot, fScale*fProportion, fScale); fx += (letters[i]->GetWidth()+post[i]+fTracking)*fScale*fProportion; } } string++; } } void hgeFont::printf(float x, float y, int align, const char *format, ...) { va_list vl; va_start(vl, format); vsnprintf(buffer, sizeof(buffer)-1, format, vl); va_end(vl); buffer[sizeof(buffer)-1] = '\0'; Render(x,y,align,buffer); } void hgeFont::printfb(float x, float y, float w, float h, int align, const char *format, ...) { char chr, *pbuf, *prevword, *linestart; int i,lines=0; float tx, ty, hh, ww; va_list vl; va_start(vl, format); vsnprintf(buffer, sizeof(buffer)-1, format, vl); va_end(vl); buffer[sizeof(buffer)-1] = '\0'; linestart=buffer; pbuf=buffer; prevword=0; for(;;) { i=0; while(pbuf[i] && pbuf[i]!=' ' && pbuf[i]!='\n') i++; chr=pbuf[i]; pbuf[i]=0; ww=GetStringWidth(linestart); pbuf[i]=chr; if(ww > w) { if(pbuf==linestart) { pbuf[i]='\n'; linestart=&pbuf[i+1]; } else { *prevword='\n'; linestart=prevword+1; } lines++; } if(pbuf[i]=='\n') { prevword=&pbuf[i]; linestart=&pbuf[i+1]; pbuf=&pbuf[i+1]; lines++; continue; } if(!pbuf[i]) {lines++;break;} prevword=&pbuf[i]; pbuf=&pbuf[i+1]; } tx=x; ty=y; hh=fHeight*fSpacing*fScale*lines; switch(align & HGETEXT_HORZMASK) { case HGETEXT_LEFT: break; case HGETEXT_RIGHT: tx+=w; break; case HGETEXT_CENTER: tx+=int(w/2); break; } switch(align & HGETEXT_VERTMASK) { case HGETEXT_TOP: break; case HGETEXT_BOTTOM: ty+=h-hh; break; case HGETEXT_MIDDLE: ty+=int((h-hh)/2); break; } Render(tx,ty,align,buffer); } float hgeFont::GetStringWidth(const char *string, bool bMultiline) const { int i; float linew, w = 0; while(*string) { linew = 0; while(*string && *string != '\n') { i=(unsigned char)*string; if(!letters[i]) i='?'; if(letters[i]) linew += letters[i]->GetWidth() + pre[i] + post[i] + fTracking; string++; } if(!bMultiline) return linew*fScale*fProportion; if(linew > w) w = linew; while (*string == '\n' || *string == '\r') string++; } return w*fScale*fProportion; } void hgeFont::SetColor(DWORD col) { dwCol = col; for(int i=0; i<256; i++) if(letters[i]) letters[i]->SetColor(col); } void hgeFont::SetZ(float z) { fZ = z; for(int i=0; i<256; i++) if(letters[i]) letters[i]->SetZ(z); } void hgeFont::SetBlendMode(int blend) { nBlend = blend; for(int i=0; i<256; i++) if(letters[i]) letters[i]->SetBlendMode(blend); } char *hgeFont::_get_line(char *file, char *line) { int i=0; if(!file[i]) return 0; while(file[i] && file[i]!='\n' && file[i]!='\r') { line[i]=file[i]; i++; } line[i]=0; while(file[i] && (file[i]=='\n' || file[i]=='\r')) i++; return file + i; }