aboutsummaryrefslogtreecommitdiff
path: root/extensions/smbmfont.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/smbmfont.cpp')
-rw-r--r--extensions/smbmfont.cpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/extensions/smbmfont.cpp b/extensions/smbmfont.cpp
new file mode 100644
index 0000000..22f9280
--- /dev/null
+++ b/extensions/smbmfont.cpp
@@ -0,0 +1,219 @@
+// -*- C++ -*-
+/*
+ * Simple MultimEdia LiTerator(SMELT)
+ * by Chris Xiong 2015
+ * Bitmap font support implementation
+ *
+ * WARNING: This library is in development and interfaces would be very
+ * unstable.
+ * This library is developed for the BLR series games.
+ */
+#include "smbmfont.hpp"
+#include <cstdio>
+#include <cstring>
+#include <cstdarg>
+
+SMELT *smBMFont::sm=NULL;
+SMELT *smBMFontw::sm=NULL;
+
+void smBMFont::parseMeta(const char* meta,DWORD size)
+{
+ const char* cp=meta;
+ char line[65];
+ int cc,cod,pa,pb;smTexRect rct;
+ while(cp-meta<=size)
+ {
+ cc=0;
+ for(;*(cp+cc)!='\n'&&cp+cc-meta<=size;++cc);
+ strncpy(line,cp,cc);if(line[cc]=='\n')line[cc]='\0';
+ cp+=cc+1;
+ char* tp=strchr(line,',');
+ if(tp)*tp='\0';else continue;
+ sscanf(tp+1,"%d,%f,%f,%f,%f,%d,%d",&cod,&rct.x,&rct.y,&rct.w,&rct.h,&pb,&pa);
+ if(cod>=0&&cod<256)
+ {
+ if(xm.find(std::string(line))==xm.end())
+ {
+ char* texct=anm.getFilePtr(line);
+ DWORD texsz=anm.getFileSize(line);
+ xm[std::string(line)]=sm->smTextureLoadFromMemory(texct,texsz);
+ anm.releaseFilePtr(line);
+ }
+ chars[cod]=new smEntity2D(xm[std::string(line)],rct);
+ pdb[cod]=pb;pda[cod]=pa;if(hadv<rct.h)hadv=(float)rct.h;
+ }
+ }
+}
+bool smBMFont::loadAnmFromMemory(const char* ptr,DWORD size)
+{
+ sm=smGetInterface(SMELT_APILEVEL);
+ anm.openDtpFromMemory(ptr,size);hadv=0;
+ xm.clear();memset(chars,0,sizeof(chars));
+ char* mptr=anm.getFilePtr("content.meta");
+ DWORD msez=anm.getFileSize("content.meta");
+ parseMeta(mptr,msez);
+ anm.releaseFilePtr("content.meta");
+ setBlend(BLEND_ALPHABLEND);
+ setColor(0xFFFFFFFF);
+}
+void smBMFont::close()
+{
+ anm.closeDtp();
+ for(int i=0;i<256;++i)if(chars[i]){delete chars[i];chars[i]=NULL;}
+ for(std::map<std::string,SMTEX>::iterator i=xm.begin();i!=xm.end();++i)
+ sm->smTextureFree(i->second);
+ xm.clear();
+ sm->smRelease();
+}
+void smBMFont::render(float x,float y,float z,int align,float *rw,const char* text)
+{
+ float width=0,cw=0,ofs=x;
+ const char* t=text;
+ while(*t)
+ {
+ cw=0;
+ for(;*t&&*t!='\n';++t)
+ {
+ if(chars[(int)*t])
+ cw+=chars[(int)*t]->_w()+pdb[(int)*t]+pda[(int)*t];
+ }
+ if(cw>width)width=cw;
+ while(*t=='\n')++t;
+ }
+ width*=sc;
+ if(rw)*rw=width;
+ if(align==ALIGN_CENTER)ofs-=width/2.;
+ if(align==ALIGN_RIGHT)ofs-=width;
+ while(*text)
+ {
+ if(*text=='\n')
+ {
+ y+=hadv*sc;ofs=x;
+ if(align==ALIGN_CENTER)ofs-=width/2.;
+ if(align==ALIGN_RIGHT)ofs-=width;
+ }
+ else
+ {
+ if(chars[(int)*text])
+ {
+ ofs+=pdb[(int)*text]*sc;
+ chars[(int)*text]->setZ(z);
+ chars[(int)*text]->setColor(color);
+ chars[(int)*text]->setBlend(b);
+ chars[(int)*text]->render(ofs,y,0,sc);
+ ofs+=(chars[(int)*text]->_w()+pda[(int)*text])*sc;
+ }
+ }
+ ++text;
+ }
+}
+void smBMFont::printf(float x,float y,float z,int align,float *rw,const char* format,...)
+{
+ char buf[1024];
+ va_list vl;
+ va_start(vl,format);
+ vsnprintf(buf,sizeof(buf)-1,format,vl);
+ va_end(vl);
+ buf[sizeof(buf)-1]='\0';
+ render(x,y,z,align,rw,buf);
+}
+
+void smBMFontw::parseMeta(char* meta,DWORD size)
+{
+ char* cp=meta;
+ char line[65];
+ int cc,cod,pa,pb;smTexRect rct;
+ while(cp-meta<=size)
+ {
+ cc=0;
+ for(;*(cp+cc)!='\n'&&cp+cc-meta<=size;++cc);
+ strncpy(line,cp,cc);if(line[cc]=='\n')line[cc]='\0';
+ cp+=cc+1;
+ char* tp=strchr(line,',');
+ if(tp)*tp='\0';else continue;
+ sscanf(tp+1,"%d,%f,%f,%f,%f,%d,%d",&cod,&rct.x,&rct.y,&rct.w,&rct.h,&pb,&pa);
+ if(cod>=WCHAR_MIN&&cod<=WCHAR_MAX)
+ {
+ if(xm.find(std::string(line))==xm.end())
+ {
+ char* texct=anm.getFilePtr(line);
+ DWORD texsz=anm.getFileSize(line);
+ xm[std::string(line)]=sm->smTextureLoadFromMemory(texct,texsz);
+ anm.releaseFilePtr(line);
+ }
+ chars[cod]=new smEntity2D(xm.find(std::string(line))->second,rct);
+ pdb[cod]=pb;pda[cod]=pa;if(hadv<rct.h)hadv=(float)rct.h;
+ }
+ }
+}
+bool smBMFontw::loadAnmFromMemory(char* ptr,DWORD size)
+{
+ sm=smGetInterface(SMELT_APILEVEL);
+ anm.openDtpFromMemory(ptr,size);hadv=0;
+ xm.clear();chars.clear();pdb.clear();pda.clear();
+ char* mptr=anm.getFilePtr("content.meta");
+ DWORD msez=anm.getFileSize("content.meta");
+ parseMeta(mptr,msez);
+ anm.releaseFilePtr("content.meta");
+}
+void smBMFontw::close()
+{
+ anm.closeDtp();
+ for(std::map<wchar_t,smEntity2D*>::iterator i=chars.begin();i!=chars.end();++i)if(i->second){delete i->second;i->second=NULL;}
+ for(std::map<std::string,SMTEX>::iterator i=xm.begin();i!=xm.end();++i)
+ sm->smTextureFree(i->second);
+ xm.clear();chars.clear();pdb.clear();pda.clear();
+ sm->smRelease();
+}
+void smBMFontw::render(float x,float y,float z,int align,float *rw,const wchar_t* text)
+{
+ float width=0,cw=0,ofs=x;
+ const wchar_t* t=text;
+ while(*t)
+ {
+ cw=0;
+ for(;*t&&*t!='\n';++t)
+ {
+ if(chars[*t])
+ cw+=chars[*t]->_w()+pdb[*t]+pda[*t];
+ }
+ if(cw>width)width=cw;
+ while(*t=='\n')++t;
+ }
+ width*=sc;
+ if(rw)*rw=width;
+ if(align==ALIGN_CENTER)ofs-=width/2.;
+ if(align==ALIGN_RIGHT)ofs-=width;
+ while(*text)
+ {
+ if(*text=='\n')
+ {
+ y+=hadv*sc;ofs=x;
+ if(align==ALIGN_CENTER)ofs-=width/2.;
+ if(align==ALIGN_RIGHT)ofs-=width;
+ }
+ else
+ {
+ if(chars[*text])
+ {
+ ofs+=pdb[*text]*sc;
+ chars[*text]->setZ(z);
+ chars[*text]->setColor(color);
+ chars[*text]->setBlend(b);
+ chars[*text]->render(ofs,y,0,sc);
+ ofs+=(chars[*text]->_w()+pda[*text])*sc;
+ }
+ }
+ ++text;
+ }
+}
+void smBMFontw::printf(float x,float y,float z,int align,float *rw,const wchar_t* format,...)
+{
+ wchar_t buf[1024];
+ va_list vl;
+ va_start(vl,format);
+ vswprintf(buf,sizeof(buf)-1,format,vl);
+ va_end(vl);
+ buf[sizeof(buf)-1]='\0';
+ render(x,y,z,align,rw,buf);
+}